Documentation
¶
Index ¶
- Constants
- Variables
- func AlreadyImpersonating(impersonatorID string) *errs.AuthsomeError
- func AuditEventNotFound(eventID string) *errs.AuthsomeError
- func CannotImpersonateSelf() *errs.AuthsomeError
- func FailedToCreateSession(err error) *errs.AuthsomeError
- func FailedToRevokeSession(err error) *errs.AuthsomeError
- func ImpersonationNotFound(impersonationID string) *errs.AuthsomeError
- func ImpersonatorNotFound(userID string) *errs.AuthsomeError
- func InvalidDuration(min, max int) *errs.AuthsomeError
- func InvalidPermission(permission string) *errs.AuthsomeError
- func InvalidReason(minLength int) *errs.AuthsomeError
- func PermissionDenied(reason string) *errs.AuthsomeError
- func RequireTicket() *errs.AuthsomeError
- func SessionAlreadyEnded(impersonationID string) *errs.AuthsomeError
- func SessionExpired(sessionID string) *errs.AuthsomeError
- func SessionNotFound(sessionID string) *errs.AuthsomeError
- func TargetUserNotFound(userID string) *errs.AuthsomeError
- func UserNotFound(userID string) *errs.AuthsomeError
- type AuditEvent
- type Config
- type EndRequest
- type EndResponse
- type GetRequest
- type ImpersonationSession
- type ListAuditEventsFilter
- type ListAuditEventsResponse
- type ListSessionsFilter
- type ListSessionsResponse
- type Repository
- type Service
- func (s *Service) End(ctx context.Context, req *EndRequest) (*EndResponse, error)
- func (s *Service) ExpireSessions(ctx context.Context) (int, error)
- func (s *Service) Get(ctx context.Context, req *GetRequest) (*SessionInfo, error)
- func (s *Service) List(ctx context.Context, filter *ListSessionsFilter) (*ListSessionsResponse, error)
- func (s *Service) ListAuditEvents(ctx context.Context, filter *ListAuditEventsFilter) (*ListAuditEventsResponse, error)
- func (s *Service) Start(ctx context.Context, req *StartRequest) (*StartResponse, error)
- func (s *Service) Verify(ctx context.Context, req *VerifyRequest) (*VerifyResponse, error)
- type SessionInfo
- type StartRequest
- type StartResponse
- type VerifyRequest
- type VerifyResponse
Constants ¶
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 ¶
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 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 RequireTicket ¶
func RequireTicket() *errs.AuthsomeError
func SessionAlreadyEnded ¶
func SessionAlreadyEnded(impersonationID string) *errs.AuthsomeError
func SessionExpired ¶
func SessionExpired(sessionID string) *errs.AuthsomeError
func TargetUserNotFound ¶
func TargetUserNotFound(userID string) *errs.AuthsomeError
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
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 ¶
func (s *ImpersonationSession) ToSchema() *schema.ImpersonationSession
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 ¶
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 ¶
func (s *Service) List(ctx context.Context, filter *ListSessionsFilter) (*ListSessionsResponse, error)
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 ¶
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