impersonation

package
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 24, 2025 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Index

Constants

View Source
const (
	CodePermissionDenied      = "IMPERSONATION_PERMISSION_DENIED"
	CodeUserNotFound          = "IMPERSONATION_USER_NOT_FOUND"
	CodeSessionNotFound       = "IMPERSONATION_SESSION_NOT_FOUND"
	CodeImpersonationNotFound = "IMPERSONATION_NOT_FOUND"
	CodeAlreadyImpersonating  = "ALREADY_IMPERSONATING"
	CodeCannotImpersonateSelf = "CANNOT_IMPERSONATE_SELF"
	CodeSessionExpired        = "IMPERSONATION_SESSION_EXPIRED"
	CodeInvalidReason         = "INVALID_IMPERSONATION_REASON"
	CodeInvalidDuration       = "INVALID_IMPERSONATION_DURATION"
	CodeRequireTicket         = "REQUIRE_TICKET_NUMBER"
	CodeInvalidPermission     = "INVALID_IMPERSONATION_PERMISSION"
	CodeSessionAlreadyEnded   = "IMPERSONATION_SESSION_ALREADY_ENDED"
	CodeFailedToCreateSession = "FAILED_TO_CREATE_SESSION"
	CodeFailedToRevokeSession = "FAILED_TO_REVOKE_SESSION"
	CodeTargetUserNotFound    = "TARGET_USER_NOT_FOUND"
	CodeImpersonatorNotFound  = "IMPERSONATOR_NOT_FOUND"
	CodeAuditEventNotFound    = "AUDIT_EVENT_NOT_FOUND"
)

Variables

View Source
var (
	ErrPermissionDenied      = &errs.AuthsomeError{Code: CodePermissionDenied}
	ErrUserNotFound          = &errs.AuthsomeError{Code: CodeUserNotFound}
	ErrSessionNotFound       = &errs.AuthsomeError{Code: CodeSessionNotFound}
	ErrImpersonationNotFound = &errs.AuthsomeError{Code: CodeImpersonationNotFound}
	ErrAlreadyImpersonating  = &errs.AuthsomeError{Code: CodeAlreadyImpersonating}
	ErrCannotImpersonateSelf = &errs.AuthsomeError{Code: CodeCannotImpersonateSelf}
	ErrSessionExpired        = &errs.AuthsomeError{Code: CodeSessionExpired}
	ErrInvalidReason         = &errs.AuthsomeError{Code: CodeInvalidReason}
	ErrInvalidDuration       = &errs.AuthsomeError{Code: CodeInvalidDuration}
	ErrRequireTicket         = &errs.AuthsomeError{Code: CodeRequireTicket}
	ErrInvalidPermission     = &errs.AuthsomeError{Code: CodeInvalidPermission}
	ErrSessionAlreadyEnded   = &errs.AuthsomeError{Code: CodeSessionAlreadyEnded}
	ErrFailedToCreateSession = &errs.AuthsomeError{Code: CodeFailedToCreateSession}
	ErrFailedToRevokeSession = &errs.AuthsomeError{Code: CodeFailedToRevokeSession}
	ErrTargetUserNotFound    = &errs.AuthsomeError{Code: CodeTargetUserNotFound}
	ErrImpersonatorNotFound  = &errs.AuthsomeError{Code: CodeImpersonatorNotFound}
	ErrAuditEventNotFound    = &errs.AuthsomeError{Code: CodeAuditEventNotFound}
)

Functions

func AlreadyImpersonating

func AlreadyImpersonating(impersonatorID string) *errs.AuthsomeError

func AuditEventNotFound

func AuditEventNotFound(eventID string) *errs.AuthsomeError

Audit errors

func CannotImpersonateSelf

func CannotImpersonateSelf() *errs.AuthsomeError

func FailedToCreateSession

func FailedToCreateSession(err error) *errs.AuthsomeError

Operation errors

func FailedToRevokeSession

func FailedToRevokeSession(err error) *errs.AuthsomeError

func ImpersonationNotFound

func ImpersonationNotFound(impersonationID string) *errs.AuthsomeError

func ImpersonatorNotFound

func ImpersonatorNotFound(userID string) *errs.AuthsomeError

func InvalidDuration

func InvalidDuration(min, max int) *errs.AuthsomeError

func InvalidPermission

func InvalidPermission(permission string) *errs.AuthsomeError

func InvalidReason

func InvalidReason(minLength int) *errs.AuthsomeError

Validation errors

func PermissionDenied

func PermissionDenied(reason string) *errs.AuthsomeError

Permission errors

func RequireTicket

func RequireTicket() *errs.AuthsomeError

func SessionAlreadyEnded

func SessionAlreadyEnded(impersonationID string) *errs.AuthsomeError

func SessionExpired

func SessionExpired(sessionID string) *errs.AuthsomeError

func SessionNotFound

func SessionNotFound(sessionID string) *errs.AuthsomeError

Session errors

func TargetUserNotFound

func TargetUserNotFound(userID string) *errs.AuthsomeError

func UserNotFound

func UserNotFound(userID string) *errs.AuthsomeError

User errors

Types

type AuditEvent

type AuditEvent struct {
	ID              xid.ID            `json:"id"`
	ImpersonationID xid.ID            `json:"impersonationId"`
	AppID           xid.ID            `json:"appId"`
	EnvironmentID   *xid.ID           `json:"environmentId,omitempty"`
	OrganizationID  *xid.ID           `json:"organizationId,omitempty"`
	EventType       string            `json:"eventType"`
	Action          string            `json:"action,omitempty"`
	Resource        string            `json:"resource,omitempty"`
	IPAddress       string            `json:"ipAddress"`
	UserAgent       string            `json:"userAgent"`
	Details         map[string]string `json:"details,omitempty"`
	CreatedAt       time.Time         `json:"createdAt"`
}

AuditEvent represents an impersonation audit event DTO

func FromSchemaAuditEvent

func FromSchemaAuditEvent(se *schema.ImpersonationAuditEvent) *AuditEvent

FromSchemaAuditEvent converts a schema.ImpersonationAuditEvent model to AuditEvent DTO

func FromSchemaAuditEvents

func FromSchemaAuditEvents(events []*schema.ImpersonationAuditEvent) []*AuditEvent

FromSchemaAuditEvents converts a slice of schema.ImpersonationAuditEvent to AuditEvent DTOs

func (*AuditEvent) ToSchema

func (e *AuditEvent) ToSchema() *schema.ImpersonationAuditEvent

ToSchema converts the AuditEvent DTO to a schema.ImpersonationAuditEvent model

type Config

type Config struct {
	// Time limits
	DefaultDurationMinutes int `json:"default_duration_minutes" yaml:"default_duration_minutes"`
	MaxDurationMinutes     int `json:"max_duration_minutes" yaml:"max_duration_minutes"`
	MinDurationMinutes     int `json:"min_duration_minutes" yaml:"min_duration_minutes"`

	// Security
	RequireReason   bool `json:"require_reason" yaml:"require_reason"`
	RequireTicket   bool `json:"require_ticket" yaml:"require_ticket"`
	MinReasonLength int  `json:"min_reason_length" yaml:"min_reason_length"`

	// RBAC
	RequirePermission     bool   `json:"require_permission" yaml:"require_permission"`
	ImpersonatePermission string `json:"impersonate_permission" yaml:"impersonate_permission"`

	// Audit
	AuditAllActions bool `json:"audit_all_actions" yaml:"audit_all_actions"` // Log every action during impersonation

	// Auto-cleanup
	AutoCleanupEnabled     bool `json:"auto_cleanup_enabled" yaml:"auto_cleanup_enabled"`
	CleanupIntervalMinutes int  `json:"cleanup_interval_minutes" yaml:"cleanup_interval_minutes"`
}

Config holds impersonation service configuration

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns default configuration

type EndRequest

type EndRequest struct {
	ImpersonationID xid.ID  `json:"impersonationId" validate:"required"`
	AppID           xid.ID  `json:"appId" validate:"required"`
	EnvironmentID   *xid.ID `json:"environmentId,omitempty"`
	OrganizationID  *xid.ID `json:"organizationId,omitempty"`
	ImpersonatorID  xid.ID  `json:"impersonatorId" validate:"required"`
	Reason          string  `json:"reason,omitempty"`
}

EndRequest represents a request to end impersonation

type EndResponse

type EndResponse struct {
	Success         bool      `json:"success"`
	ImpersonationID xid.ID    `json:"impersonationId"`
	EndedAt         time.Time `json:"endedAt"`
	Message         string    `json:"message"`
}

EndResponse represents the response after ending impersonation

type GetRequest

type GetRequest struct {
	ImpersonationID xid.ID  `json:"impersonationId" validate:"required"`
	AppID           xid.ID  `json:"appId" validate:"required"`
	EnvironmentID   *xid.ID `json:"environmentId,omitempty"`
	OrganizationID  *xid.ID `json:"organizationId,omitempty"`
}

GetRequest represents a request to get an impersonation session

type ImpersonationSession

type ImpersonationSession struct {
	ID             xid.ID     `json:"id"`
	AppID          xid.ID     `json:"appId"`
	EnvironmentID  *xid.ID    `json:"environmentId,omitempty"`
	OrganizationID *xid.ID    `json:"organizationId,omitempty"`
	ImpersonatorID xid.ID     `json:"impersonatorId"`
	TargetUserID   xid.ID     `json:"targetUserId"`
	NewSessionID   *xid.ID    `json:"newSessionId,omitempty"`
	SessionToken   string     `json:"-"` // Never expose in JSON
	Reason         string     `json:"reason"`
	TicketNumber   string     `json:"ticketNumber,omitempty"`
	IPAddress      string     `json:"ipAddress,omitempty"`
	UserAgent      string     `json:"userAgent,omitempty"`
	Active         bool       `json:"active"`
	ExpiresAt      time.Time  `json:"expiresAt"`
	EndedAt        *time.Time `json:"endedAt,omitempty"`
	EndReason      string     `json:"endReason,omitempty"`
	// Audit fields
	CreatedAt time.Time  `json:"createdAt"`
	UpdatedAt time.Time  `json:"updatedAt"`
	DeletedAt *time.Time `json:"deletedAt,omitempty"`
}

ImpersonationSession represents an impersonation session DTO This is separate from schema.ImpersonationSession to maintain proper separation of concerns

func FromSchemaImpersonationSession

func FromSchemaImpersonationSession(ss *schema.ImpersonationSession) *ImpersonationSession

FromSchemaImpersonationSession converts a schema.ImpersonationSession model to ImpersonationSession DTO

func FromSchemaImpersonationSessions

func FromSchemaImpersonationSessions(sessions []*schema.ImpersonationSession) []*ImpersonationSession

FromSchemaImpersonationSessions converts a slice of schema.ImpersonationSession to ImpersonationSession DTOs

func (*ImpersonationSession) IsActive

func (s *ImpersonationSession) IsActive() bool

IsActive checks if the impersonation session is active

func (*ImpersonationSession) IsEnded

func (s *ImpersonationSession) IsEnded() bool

IsEnded checks if the session has been manually ended

func (*ImpersonationSession) IsExpired

func (s *ImpersonationSession) IsExpired() bool

IsExpired checks if the session has expired

func (*ImpersonationSession) ToSchema

ToSchema converts the ImpersonationSession DTO to a schema.ImpersonationSession model

type ListAuditEventsFilter

type ListAuditEventsFilter struct {
	pagination.PaginationParams
	AppID           xid.ID     `json:"appId" query:"app_id"`
	EnvironmentID   *xid.ID    `json:"environmentId,omitempty" query:"environment_id"`
	OrganizationID  *xid.ID    `json:"organizationId,omitempty" query:"organization_id"`
	ImpersonationID *xid.ID    `json:"impersonationId,omitempty" query:"impersonation_id"`
	ImpersonatorID  *xid.ID    `json:"impersonatorId,omitempty" query:"impersonator_id"`
	TargetUserID    *xid.ID    `json:"targetUserId,omitempty" query:"target_user_id"`
	EventType       *string    `json:"eventType,omitempty" query:"event_type"`
	Since           *time.Time `json:"since,omitempty" query:"since"`
	Until           *time.Time `json:"until,omitempty" query:"until"`
}

ListAuditEventsFilter represents filter parameters for listing audit events

type ListAuditEventsResponse

type ListAuditEventsResponse = pagination.PageResponse[*AuditEvent]

ListAuditEventsResponse represents paginated audit events response

type ListSessionsFilter

type ListSessionsFilter struct {
	pagination.PaginationParams
	AppID          xid.ID  `json:"appId" query:"app_id"`
	EnvironmentID  *xid.ID `json:"environmentId,omitempty" query:"environment_id"`
	OrganizationID *xid.ID `json:"organizationId,omitempty" query:"organization_id"`
	ImpersonatorID *xid.ID `json:"impersonatorId,omitempty" query:"impersonator_id"`
	TargetUserID   *xid.ID `json:"targetUserId,omitempty" query:"target_user_id"`
	ActiveOnly     *bool   `json:"activeOnly,omitempty" query:"active_only"`
}

ListSessionsFilter represents filter parameters for listing impersonation sessions

type ListSessionsResponse

type ListSessionsResponse = pagination.PageResponse[*ImpersonationSession]

ListSessionsResponse represents paginated session response

type Repository

type Repository interface {
	// Session operations
	Create(ctx context.Context, session *schema.ImpersonationSession) error
	Get(ctx context.Context, id xid.ID, appID xid.ID) (*schema.ImpersonationSession, error)
	GetBySessionID(ctx context.Context, sessionID xid.ID) (*schema.ImpersonationSession, error)
	Update(ctx context.Context, session *schema.ImpersonationSession) error

	// ListSessions lists impersonation sessions with pagination and filtering
	ListSessions(ctx context.Context, filter *ListSessionsFilter) (*pagination.PageResponse[*schema.ImpersonationSession], error)

	GetActive(ctx context.Context, impersonatorID xid.ID, appID xid.ID) (*schema.ImpersonationSession, error)
	ExpireOldSessions(ctx context.Context) (int, error) // Returns number of expired sessions

	// Audit operations
	CreateAuditEvent(ctx context.Context, event *schema.ImpersonationAuditEvent) error

	// ListAuditEvents lists audit events with pagination and filtering
	ListAuditEvents(ctx context.Context, filter *ListAuditEventsFilter) (*pagination.PageResponse[*schema.ImpersonationAuditEvent], error)
}

Repository defines persistence operations for impersonation sessions This follows the Interface Segregation Principle from core/app and core/jwt architecture

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service handles impersonation business logic

func NewService

func NewService(
	repo Repository,
	userSvc user.ServiceInterface,
	sessionSvc session.ServiceInterface,
	auditSvc *audit.Service,
	rbacSvc *rbac.Service,
	config Config,
) *Service

NewService creates a new impersonation service

func (*Service) End

func (s *Service) End(ctx context.Context, req *EndRequest) (*EndResponse, error)

End terminates an impersonation session

func (*Service) ExpireSessions

func (s *Service) ExpireSessions(ctx context.Context) (int, error)

ExpireSessions expires old impersonation sessions (run as cron job)

func (*Service) Get

func (s *Service) Get(ctx context.Context, req *GetRequest) (*SessionInfo, error)

Get retrieves an impersonation session

func (*Service) List

List retrieves impersonation sessions with pagination and filtering

func (*Service) ListAuditEvents

func (s *Service) ListAuditEvents(ctx context.Context, filter *ListAuditEventsFilter) (*ListAuditEventsResponse, error)

ListAuditEvents retrieves audit events with pagination and filtering

func (*Service) Start

func (s *Service) Start(ctx context.Context, req *StartRequest) (*StartResponse, error)

Start begins an impersonation session

func (*Service) Verify

func (s *Service) Verify(ctx context.Context, req *VerifyRequest) (*VerifyResponse, error)

Verify checks if a session is an impersonation session

type SessionInfo

type SessionInfo struct {
	ID             xid.ID     `json:"id"`
	AppID          xid.ID     `json:"appId"`
	EnvironmentID  *xid.ID    `json:"environmentId,omitempty"`
	OrganizationID *xid.ID    `json:"organizationId,omitempty"`
	ImpersonatorID xid.ID     `json:"impersonatorId"`
	TargetUserID   xid.ID     `json:"targetUserId"`
	Reason         string     `json:"reason"`
	TicketNumber   string     `json:"ticketNumber,omitempty"`
	Active         bool       `json:"active"`
	ExpiresAt      time.Time  `json:"expiresAt"`
	EndedAt        *time.Time `json:"endedAt,omitempty"`
	EndReason      string     `json:"endReason,omitempty"`
	CreatedAt      time.Time  `json:"createdAt"`
	UpdatedAt      time.Time  `json:"updatedAt"`

	// Enriched data
	ImpersonatorEmail string `json:"impersonatorEmail,omitempty"`
	ImpersonatorName  string `json:"impersonatorName,omitempty"`
	TargetEmail       string `json:"targetEmail,omitempty"`
	TargetName        string `json:"targetName,omitempty"`
}

SessionInfo represents enriched impersonation session information

type StartRequest

type StartRequest struct {
	AppID           xid.ID  `json:"appId" validate:"required"`
	EnvironmentID   *xid.ID `json:"environmentId,omitempty"`
	OrganizationID  *xid.ID `json:"organizationId,omitempty"`
	ImpersonatorID  xid.ID  `json:"impersonatorId" validate:"required"`
	TargetUserID    xid.ID  `json:"targetUserId" validate:"required"`
	Reason          string  `json:"reason" validate:"required,min=10,max=500"`
	TicketNumber    string  `json:"ticketNumber,omitempty" validate:"max=100"`
	IPAddress       string  `json:"ipAddress,omitempty"`
	UserAgent       string  `json:"userAgent,omitempty"`
	DurationMinutes int     `json:"durationMinutes,omitempty"`
}

StartRequest represents a request to start impersonation

type StartResponse

type StartResponse struct {
	ImpersonationID xid.ID    `json:"impersonationId"`
	SessionID       xid.ID    `json:"sessionId"`
	SessionToken    string    `json:"sessionToken"`
	ExpiresAt       time.Time `json:"expiresAt"`
	Message         string    `json:"message"`
}

StartResponse represents the response after starting impersonation

type VerifyRequest

type VerifyRequest struct {
	SessionID xid.ID `json:"sessionId" validate:"required"`
}

VerifyRequest represents a request to verify if a session is impersonating

type VerifyResponse

type VerifyResponse struct {
	IsImpersonating bool       `json:"isImpersonating"`
	ImpersonationID *xid.ID    `json:"impersonationId,omitempty"`
	AppID           *xid.ID    `json:"appId,omitempty"`
	EnvironmentID   *xid.ID    `json:"environmentId,omitempty"`
	OrganizationID  *xid.ID    `json:"organizationId,omitempty"`
	ImpersonatorID  *xid.ID    `json:"impersonatorId,omitempty"`
	TargetUserID    *xid.ID    `json:"targetUserId,omitempty"`
	ExpiresAt       *time.Time `json:"expiresAt,omitempty"`
}

VerifyResponse represents the response for verification

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL