organization

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: 11 Imported by: 0

Documentation

Index

Constants

Re-export organization member roles from schema

View Source
const (
	StatusActive    = schema.OrgMemberStatusActive
	StatusSuspended = schema.OrgMemberStatusSuspended
	StatusPending   = schema.OrgMemberStatusPending
)

Re-export organization member statuses from schema

View Source
const (
	InvitationStatusPending   = schema.OrgInvitationStatusPending
	InvitationStatusAccepted  = schema.OrgInvitationStatusAccepted
	InvitationStatusExpired   = schema.OrgInvitationStatusExpired
	InvitationStatusCancelled = schema.OrgInvitationStatusCancelled
	InvitationStatusDeclined  = schema.OrgInvitationStatusDeclined
)

Re-export organization invitation statuses from schema

View Source
const (
	CodeOrganizationNotFound         = "ORGANIZATION_NOT_FOUND"
	CodeOrganizationSlugExists       = "ORGANIZATION_SLUG_EXISTS"
	CodeOrganizationAlreadyExists    = "ORGANIZATION_ALREADY_EXISTS"
	CodeMemberNotFound               = "ORGANIZATION_MEMBER_NOT_FOUND"
	CodeMemberAlreadyExists          = "ORGANIZATION_MEMBER_ALREADY_EXISTS"
	CodeMaxMembersReached            = "MAX_ORGANIZATION_MEMBERS_REACHED"
	CodeMaxOrganizationsReached      = "MAX_ORGANIZATIONS_REACHED"
	CodeTeamNotFound                 = "ORGANIZATION_TEAM_NOT_FOUND"
	CodeTeamAlreadyExists            = "ORGANIZATION_TEAM_ALREADY_EXISTS"
	CodeMaxTeamsReached              = "MAX_ORGANIZATION_TEAMS_REACHED"
	CodeTeamMemberNotFound           = "ORGANIZATION_TEAM_MEMBER_NOT_FOUND"
	CodeInvitationNotFound           = "ORGANIZATION_INVITATION_NOT_FOUND"
	CodeInvitationExpired            = "ORGANIZATION_INVITATION_EXPIRED"
	CodeInvitationInvalid            = "ORGANIZATION_INVITATION_INVALID_STATUS"
	CodeInvitationNotPending         = "ORGANIZATION_INVITATION_NOT_PENDING"
	CodeInvalidRole                  = "INVALID_ORGANIZATION_ROLE"
	CodeInvalidStatus                = "INVALID_ORGANIZATION_STATUS"
	CodeCannotRemoveOwner            = "CANNOT_REMOVE_ORGANIZATION_OWNER"
	CodeNotOwner                     = "NOT_ORGANIZATION_OWNER"
	CodeNotAdmin                     = "NOT_ORGANIZATION_ADMIN"
	CodeOrganizationCreationDisabled = "ORGANIZATION_CREATION_DISABLED"
)

Variables

View Source
var (
	ErrOrganizationNotFound         = &errs.AuthsomeError{Code: CodeOrganizationNotFound}
	ErrOrganizationSlugExists       = &errs.AuthsomeError{Code: CodeOrganizationSlugExists}
	ErrOrganizationAlreadyExists    = &errs.AuthsomeError{Code: CodeOrganizationAlreadyExists}
	ErrOrganizationCreationDisabled = &errs.AuthsomeError{Code: CodeOrganizationCreationDisabled}
	ErrMemberNotFound               = &errs.AuthsomeError{Code: CodeMemberNotFound}
	ErrMemberAlreadyExists          = &errs.AuthsomeError{Code: CodeMemberAlreadyExists}
	ErrMaxMembersReached            = &errs.AuthsomeError{Code: CodeMaxMembersReached}
	ErrMaxOrganizationsReached      = &errs.AuthsomeError{Code: CodeMaxOrganizationsReached}
	ErrCannotRemoveOwner            = &errs.AuthsomeError{Code: CodeCannotRemoveOwner}
	ErrTeamNotFound                 = &errs.AuthsomeError{Code: CodeTeamNotFound}
	ErrTeamAlreadyExists            = &errs.AuthsomeError{Code: CodeTeamAlreadyExists}
	ErrMaxTeamsReached              = &errs.AuthsomeError{Code: CodeMaxTeamsReached}
	ErrTeamMemberNotFound           = &errs.AuthsomeError{Code: CodeTeamMemberNotFound}
	ErrInvitationNotFound           = &errs.AuthsomeError{Code: CodeInvitationNotFound}
	ErrInvitationExpired            = &errs.AuthsomeError{Code: CodeInvitationExpired}
	ErrInvitationInvalid            = &errs.AuthsomeError{Code: CodeInvitationInvalid}
	ErrInvitationNotPending         = &errs.AuthsomeError{Code: CodeInvitationNotPending}
	ErrUnauthorized                 = &errs.AuthsomeError{Code: errs.CodeUnauthorized}
	ErrNotOwner                     = &errs.AuthsomeError{Code: CodeNotOwner}
	ErrNotAdmin                     = &errs.AuthsomeError{Code: CodeNotAdmin}
	ErrInvalidRole                  = &errs.AuthsomeError{Code: CodeInvalidRole}
	ErrInvalidStatus                = &errs.AuthsomeError{Code: CodeInvalidStatus}
)

Functions

func CannotRemoveOwner

func CannotRemoveOwner() *errs.AuthsomeError

func InvalidRole

func InvalidRole(role string) *errs.AuthsomeError

Validation errors

func InvalidStatus

func InvalidStatus(status string) *errs.AuthsomeError

func InvitationExpired

func InvitationExpired() *errs.AuthsomeError

func InvitationInvalidStatus

func InvitationInvalidStatus(expected, actual string) *errs.AuthsomeError

func InvitationNotFound

func InvitationNotFound() *errs.AuthsomeError

Invitation errors

func InvitationNotPending

func InvitationNotPending() *errs.AuthsomeError

func IsValidInvitationStatus

func IsValidInvitationStatus(status string) bool

IsValidInvitationStatus checks if an invitation status is valid

func IsValidRole

func IsValidRole(role string) bool

IsValidRole checks if a role is valid

func IsValidStatus

func IsValidStatus(status string) bool

IsValidStatus checks if a status is valid

func MaxMembersReached

func MaxMembersReached(limit int) *errs.AuthsomeError

func MaxOrganizationsReached

func MaxOrganizationsReached(limit int) *errs.AuthsomeError

func MaxTeamsReached

func MaxTeamsReached(limit int) *errs.AuthsomeError

func MemberAlreadyExists

func MemberAlreadyExists(userID string) *errs.AuthsomeError

func MemberNotFound

func MemberNotFound() *errs.AuthsomeError

Member errors

func NotAdmin

func NotAdmin() *errs.AuthsomeError

func NotOwner

func NotOwner() *errs.AuthsomeError

func OrganizationAlreadyExists

func OrganizationAlreadyExists(identifier string) *errs.AuthsomeError

func OrganizationCreationDisabled

func OrganizationCreationDisabled() *errs.AuthsomeError

func OrganizationNotFound

func OrganizationNotFound() *errs.AuthsomeError

Organization errors

func OrganizationSlugExists

func OrganizationSlugExists(slug string) *errs.AuthsomeError

func TeamAlreadyExists

func TeamAlreadyExists(name string) *errs.AuthsomeError

func TeamMemberNotFound

func TeamMemberNotFound() *errs.AuthsomeError

func TeamNotFound

func TeamNotFound() *errs.AuthsomeError

Team errors

func Unauthorized

func Unauthorized() *errs.AuthsomeError

Authorization errors

func UnauthorizedAction

func UnauthorizedAction(action string) *errs.AuthsomeError

func ValidInvitationStatuses

func ValidInvitationStatuses() []string

ValidInvitationStatuses returns the list of valid invitation statuses

func ValidRoles

func ValidRoles() []string

ValidRoles returns the list of valid member roles

func ValidStatuses

func ValidStatuses() []string

ValidStatuses returns the list of valid member statuses

Types

type CompositeOrganizationService

type CompositeOrganizationService interface {
	OrganizationOperations
	MemberOperations
	TeamOperations
	InvitationOperations
}

CompositeOrganizationService defines the complete contract for all organization-related service operations This interface combines all focused operations and is useful for backward compatibility or when a component needs access to all operations. New code should prefer using the focused interfaces (OrganizationOperations, MemberOperations, etc.)

type Config

type Config struct {
	MaxOrganizationsPerUser   int  `json:"maxOrganizationsPerUser"`
	MaxMembersPerOrganization int  `json:"maxMembersPerOrganization"`
	MaxTeamsPerOrganization   int  `json:"maxTeamsPerOrganization"`
	EnableUserCreation        bool `json:"enableUserCreation"`
	RequireInvitation         bool `json:"requireInvitation"`
	InvitationExpiryHours     int  `json:"invitationExpiryHours"`
}

Config holds the organization service configuration

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns sensible default configuration values

type CreateOrganizationRequest

type CreateOrganizationRequest struct {
	Name               string                             `json:"name" validate:"required,min=1,max=100"`
	Slug               string                             `json:"slug" validate:"required,min=1,max=100,slug"`
	Metadata           map[string]interface{}             `json:"metadata,omitempty"`
	RoleTemplateIDs    []xid.ID                           `json:"roleTemplateIDs,omitempty"`    // Role templates to bootstrap (empty = all)
	RoleCustomizations map[xid.ID]*rbac.RoleCustomization `json:"roleCustomizations,omitempty"` // Customizations for role templates
}

CreateOrganizationRequest represents a create organization request

type CreateTeamRequest

type CreateTeamRequest struct {
	Name        string                 `json:"name" validate:"required,min=1,max=100"`
	Description *string                `json:"description,omitempty"`
	Metadata    map[string]interface{} `json:"metadata,omitempty"`
}

CreateTeamRequest represents a request to create a team

type Invitation

type Invitation struct {
	ID             xid.ID     `json:"id"`
	OrganizationID xid.ID     `json:"organizationID"`
	Email          string     `json:"email"`
	Role           string     `json:"role"` // owner, admin, member
	InviterID      xid.ID     `json:"inviterID"`
	Token          string     `json:"token"`
	ExpiresAt      time.Time  `json:"expiresAt"`
	AcceptedAt     *time.Time `json:"acceptedAt,omitempty"`
	Status         string     `json:"status"` // pending, accepted, expired, cancelled, declined
	// Audit fields
	CreatedAt time.Time  `json:"createdAt"`
	UpdatedAt time.Time  `json:"updatedAt"`
	DeletedAt *time.Time `json:"deletedAt,omitempty"`
}

Invitation represents an organization invitation entity DTO (Data Transfer Object) This is separate from schema.OrganizationInvitation to maintain proper separation of concerns

func FromSchemaInvitation

func FromSchemaInvitation(si *schema.OrganizationInvitation) *Invitation

FromSchemaInvitation converts a schema.OrganizationInvitation model to Invitation DTO

func FromSchemaInvitations

func FromSchemaInvitations(invitations []*schema.OrganizationInvitation) []*Invitation

FromSchemaInvitations converts a slice of schema.OrganizationInvitation to Invitation DTOs

func (*Invitation) ToSchema

func (i *Invitation) ToSchema() *schema.OrganizationInvitation

ToSchema converts the Invitation DTO to a schema.OrganizationInvitation model

type InvitationOperations

type InvitationOperations interface {
	// InviteMember creates an invitation for a user to join an organization
	InviteMember(ctx context.Context, orgID xid.ID, req *InviteMemberRequest, inviterUserID xid.ID) (*Invitation, error)

	// FindInvitationByID retrieves an invitation by its ID
	FindInvitationByID(ctx context.Context, id xid.ID) (*Invitation, error)

	// FindInvitationByToken retrieves an invitation by its token
	FindInvitationByToken(ctx context.Context, token string) (*Invitation, error)

	// ListInvitations retrieves a paginated list of invitations for an organization
	ListInvitations(ctx context.Context, filter *ListInvitationsFilter) (*pagination.PageResponse[*Invitation], error)

	// AcceptInvitation accepts an invitation and adds the user to the organization
	AcceptInvitation(ctx context.Context, token string, userID xid.ID) (*Member, error)

	// DeclineInvitation declines an invitation
	DeclineInvitation(ctx context.Context, token string) error

	// CancelInvitation cancels a pending invitation (admin/owner only)
	CancelInvitation(ctx context.Context, id, cancellerUserID xid.ID) error

	// ResendInvitation resends an invitation with a new token and updated expiry
	ResendInvitation(ctx context.Context, id, resenderUserID xid.ID) (*Invitation, error)

	// CleanupExpiredInvitations removes all expired invitations
	CleanupExpiredInvitations(ctx context.Context) (int, error)
}

InvitationOperations defines invitation management operations

type InvitationRepository

type InvitationRepository interface {
	// Create creates a new invitation
	Create(ctx context.Context, inv *Invitation) error

	// FindByID retrieves an invitation by its ID
	FindByID(ctx context.Context, id xid.ID) (*Invitation, error)

	// FindByToken retrieves an invitation by its token
	FindByToken(ctx context.Context, token string) (*Invitation, error)

	// ListByOrganization retrieves a paginated list of invitations for an organization
	ListByOrganization(ctx context.Context, filter *ListInvitationsFilter) (*pagination.PageResponse[*Invitation], error)

	// Update updates an existing invitation
	Update(ctx context.Context, inv *Invitation) error

	// Delete deletes an invitation by ID
	Delete(ctx context.Context, id xid.ID) error

	// DeleteExpired deletes all expired invitations and returns the count
	DeleteExpired(ctx context.Context) (int, error)
}

InvitationRepository defines the interface for organization invitation data access

type InvitationService

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

InvitationService handles invitation lifecycle operations

func NewInvitationService

func NewInvitationService(repo InvitationRepository, memberRepo MemberRepository, orgRepo OrganizationRepository, cfg Config, rbacSvc *rbac.Service) *InvitationService

NewInvitationService creates a new invitation service

func (*InvitationService) AcceptInvitation

func (s *InvitationService) AcceptInvitation(ctx context.Context, token string, userID xid.ID) (*Member, error)

AcceptInvitation accepts an invitation and adds the user to the organization This is a cross-aggregate operation: it updates the invitation and creates a member

func (*InvitationService) CancelInvitation

func (s *InvitationService) CancelInvitation(ctx context.Context, id, cancellerUserID xid.ID) error

CancelInvitation cancels a pending invitation (admin/owner only)

func (*InvitationService) CleanupExpiredInvitations

func (s *InvitationService) CleanupExpiredInvitations(ctx context.Context) (int, error)

CleanupExpiredInvitations removes all expired invitations

func (*InvitationService) DeclineInvitation

func (s *InvitationService) DeclineInvitation(ctx context.Context, token string) error

DeclineInvitation declines an invitation

func (*InvitationService) FindInvitationByID

func (s *InvitationService) FindInvitationByID(ctx context.Context, id xid.ID) (*Invitation, error)

FindInvitationByID retrieves an invitation by its ID

func (*InvitationService) FindInvitationByToken

func (s *InvitationService) FindInvitationByToken(ctx context.Context, token string) (*Invitation, error)

FindInvitationByToken retrieves an invitation by its token

func (*InvitationService) InviteMember

func (s *InvitationService) InviteMember(ctx context.Context, orgID xid.ID, req *InviteMemberRequest, inviterUserID xid.ID) (*Invitation, error)

InviteMember creates an invitation for a user to join an organization

func (*InvitationService) ListInvitations

ListInvitations retrieves a paginated list of invitations for an organization

func (*InvitationService) ResendInvitation

func (s *InvitationService) ResendInvitation(ctx context.Context, id, resenderUserID xid.ID) (*Invitation, error)

ResendInvitation resends an invitation with a new token and updated expiry

type InviteMemberRequest

type InviteMemberRequest struct {
	Email string `json:"email" validate:"required,email"`
	Role  string `json:"role" validate:"required,oneof=owner admin member"`
}

InviteMemberRequest represents a request to invite a member to an organization

type ListInvitationsFilter

type ListInvitationsFilter struct {
	pagination.PaginationParams
	OrganizationID xid.ID
	Status         *string // Filter by status (pending, accepted, expired, etc.)
}

ListInvitationsFilter defines filters for listing invitations

func (*ListInvitationsFilter) Validate

func (f *ListInvitationsFilter) Validate() error

Validate validates the filter parameters

type ListMembersFilter

type ListMembersFilter struct {
	pagination.PaginationParams
	OrganizationID xid.ID
	Role           *string // Filter by role (owner, admin, member)
	Status         *string // Filter by status (active, suspended, pending)
}

ListMembersFilter defines filters for listing organization members

func (*ListMembersFilter) Validate

func (f *ListMembersFilter) Validate() error

Validate validates the filter parameters

type ListOrganizationsFilter

type ListOrganizationsFilter struct {
	pagination.PaginationParams
	AppID         xid.ID
	EnvironmentID xid.ID
}

ListOrganizationsFilter defines filters for listing organizations

func (*ListOrganizationsFilter) GetLimit

func (f *ListOrganizationsFilter) GetLimit() int

GetLimit returns the limit for pagination

func (*ListOrganizationsFilter) GetOffset

func (f *ListOrganizationsFilter) GetOffset() int

GetOffset returns the offset for pagination

func (*ListOrganizationsFilter) Validate

func (f *ListOrganizationsFilter) Validate() error

Validate validates the filter parameters

type ListTeamMembersFilter

type ListTeamMembersFilter struct {
	pagination.PaginationParams
	TeamID xid.ID
}

ListTeamMembersFilter defines filters for listing team members

func (*ListTeamMembersFilter) Validate

func (f *ListTeamMembersFilter) Validate() error

Validate validates the filter parameters

type ListTeamsFilter

type ListTeamsFilter struct {
	pagination.PaginationParams
	OrganizationID xid.ID
}

ListTeamsFilter defines filters for listing teams

func (*ListTeamsFilter) Validate

func (f *ListTeamsFilter) Validate() error

Validate validates the filter parameters

type Member

type Member struct {
	ID             xid.ID    `json:"id"`
	OrganizationID xid.ID    `json:"organizationID"`
	UserID         xid.ID    `json:"userID"`
	Role           string    `json:"role"`   // owner, admin, member
	Status         string    `json:"status"` // active, suspended, pending
	JoinedAt       time.Time `json:"joinedAt"`
	// Audit fields
	CreatedAt time.Time  `json:"createdAt"`
	UpdatedAt time.Time  `json:"updatedAt"`
	DeletedAt *time.Time `json:"deletedAt,omitempty"`
}

Member represents an organization member entity DTO (Data Transfer Object) This is separate from schema.OrganizationMember to maintain proper separation of concerns

func FromSchemaMember

func FromSchemaMember(sm *schema.OrganizationMember) *Member

FromSchemaMember converts a schema.OrganizationMember model to Member DTO

func FromSchemaMembers

func FromSchemaMembers(members []*schema.OrganizationMember) []*Member

FromSchemaMembers converts a slice of schema.OrganizationMember to Member DTOs

func (*Member) ToSchema

func (m *Member) ToSchema() *schema.OrganizationMember

ToSchema converts the Member DTO to a schema.OrganizationMember model

type MemberOperations

type MemberOperations interface {
	// AddMember adds a user as a member of an organization with a specified role
	AddMember(ctx context.Context, orgID, userID xid.ID, role string) (*Member, error)

	// FindMemberByID retrieves a member by their ID
	FindMemberByID(ctx context.Context, id xid.ID) (*Member, error)

	// FindMember retrieves a member by organization ID and user ID
	FindMember(ctx context.Context, orgID, userID xid.ID) (*Member, error)

	// ListMembers retrieves a paginated list of members in an organization
	ListMembers(ctx context.Context, filter *ListMembersFilter) (*pagination.PageResponse[*Member], error)

	// UpdateMember updates a member's role or status
	UpdateMember(ctx context.Context, id xid.ID, req *UpdateMemberRequest, updaterUserID xid.ID) (*Member, error)

	// RemoveMember removes a member from an organization
	RemoveMember(ctx context.Context, id, removerUserID xid.ID) error

	// GetUserMemberships retrieves all organization memberships for a user
	GetUserMemberships(ctx context.Context, userID xid.ID, filter *pagination.PaginationParams) (*pagination.PageResponse[*Member], error)

	// RemoveUserFromAllOrganizations removes a user from all organizations they belong to
	RemoveUserFromAllOrganizations(ctx context.Context, userID xid.ID) error

	// IsMember checks if a user is a member of an organization
	IsMember(ctx context.Context, orgID, userID xid.ID) (bool, error)

	// IsOwner checks if a user is the owner of an organization
	IsOwner(ctx context.Context, orgID, userID xid.ID) (bool, error)

	// IsAdmin checks if a user is an admin or owner of an organization
	IsAdmin(ctx context.Context, orgID, userID xid.ID) (bool, error)

	// RequireOwner checks if a user is the owner and returns an error if not
	RequireOwner(ctx context.Context, orgID, userID xid.ID) error

	// RequireAdmin checks if a user is an admin or owner and returns an error if not
	RequireAdmin(ctx context.Context, orgID, userID xid.ID) error
}

MemberOperations defines member management operations

type MemberRepository

type MemberRepository interface {
	// Create creates a new organization member
	Create(ctx context.Context, member *Member) error

	// FindByID retrieves a member by their ID
	FindByID(ctx context.Context, id xid.ID) (*Member, error)

	// FindByUserAndOrg retrieves a member by user ID and organization ID
	FindByUserAndOrg(ctx context.Context, userID, orgID xid.ID) (*Member, error)

	// ListByOrganization retrieves a paginated list of members in an organization
	ListByOrganization(ctx context.Context, filter *ListMembersFilter) (*pagination.PageResponse[*Member], error)

	// ListByUser retrieves a paginated list of organization memberships for a user
	ListByUser(ctx context.Context, userID xid.ID, filter *pagination.PaginationParams) (*pagination.PageResponse[*Member], error)

	// Update updates an existing member
	Update(ctx context.Context, member *Member) error

	// Delete deletes a member by ID
	Delete(ctx context.Context, id xid.ID) error

	// DeleteByUserAndOrg deletes a member by user ID and organization ID
	DeleteByUserAndOrg(ctx context.Context, userID, orgID xid.ID) error

	// CountByOrganization counts the number of members in an organization
	CountByOrganization(ctx context.Context, orgID xid.ID) (int, error)
}

MemberRepository defines the interface for organization member data access

type MemberService

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

MemberService handles member aggregate operations

func NewMemberService

func NewMemberService(repo MemberRepository, orgRepo OrganizationRepository, cfg Config, rbacSvc *rbac.Service) *MemberService

NewMemberService creates a new member service

func (*MemberService) AddMember

func (s *MemberService) AddMember(ctx context.Context, orgID, userID xid.ID, role string) (*Member, error)

AddMember adds a user as a member of an organization

func (*MemberService) FindMember

func (s *MemberService) FindMember(ctx context.Context, orgID, userID xid.ID) (*Member, error)

FindMember retrieves a member by organization ID and user ID

func (*MemberService) FindMemberByID

func (s *MemberService) FindMemberByID(ctx context.Context, id xid.ID) (*Member, error)

FindMemberByID retrieves a member by ID

func (*MemberService) GetUserMemberships

func (s *MemberService) GetUserMemberships(ctx context.Context, userID xid.ID, filter *pagination.PaginationParams) (*pagination.PageResponse[*Member], error)

GetUserMemberships returns all organizations a user is a member of

func (*MemberService) IsAdmin

func (s *MemberService) IsAdmin(ctx context.Context, orgID, userID xid.ID) (bool, error)

IsAdmin checks if a user is an admin or owner of an organization

func (*MemberService) IsMember

func (s *MemberService) IsMember(ctx context.Context, orgID, userID xid.ID) (bool, error)

IsMember checks if a user is a member of an organization

func (*MemberService) IsOwner

func (s *MemberService) IsOwner(ctx context.Context, orgID, userID xid.ID) (bool, error)

IsOwner checks if a user is the owner of an organization

func (*MemberService) ListMembers

ListMembers lists members in an organization with pagination and filtering

func (*MemberService) RemoveMember

func (s *MemberService) RemoveMember(ctx context.Context, id, removerUserID xid.ID) error

RemoveMember removes a member from an organization

func (*MemberService) RemoveUserFromAllOrganizations

func (s *MemberService) RemoveUserFromAllOrganizations(ctx context.Context, userID xid.ID) error

RemoveUserFromAllOrganizations removes a user from all organizations they belong to

func (*MemberService) RequireAdmin

func (s *MemberService) RequireAdmin(ctx context.Context, orgID, userID xid.ID) error

RequireAdmin checks if a user is an admin or owner of an organization and returns an error if not

func (*MemberService) RequireOwner

func (s *MemberService) RequireOwner(ctx context.Context, orgID, userID xid.ID) error

RequireOwner checks if a user is the owner of an organization and returns an error if not

func (*MemberService) UpdateMember

func (s *MemberService) UpdateMember(ctx context.Context, id xid.ID, req *UpdateMemberRequest, updaterUserID xid.ID) (*Member, error)

UpdateMember updates a member

type Organization

type Organization struct {
	ID            xid.ID                 `json:"id"`
	AppID         xid.ID                 `json:"appID"`
	EnvironmentID xid.ID                 `json:"environmentID"`
	Name          string                 `json:"name"`
	Slug          string                 `json:"slug"`
	Metadata      map[string]interface{} `json:"metadata,omitempty"`
	CreatedBy     xid.ID                 `json:"createdBy"`
	// Audit fields
	CreatedAt time.Time  `json:"createdAt"`
	UpdatedAt time.Time  `json:"updatedAt"`
	DeletedAt *time.Time `json:"deletedAt,omitempty"`
}

Organization represents an organization entity DTO (Data Transfer Object) This is separate from schema.Organization to maintain proper separation of concerns

func FromSchemaOrganization

func FromSchemaOrganization(so *schema.Organization) *Organization

FromSchemaOrganization converts a schema.Organization model to Organization DTO

func FromSchemaOrganizations

func FromSchemaOrganizations(orgs []*schema.Organization) []*Organization

FromSchemaOrganizations converts a slice of schema.Organization to Organization DTOs

func (*Organization) ToSchema

func (o *Organization) ToSchema() *schema.Organization

ToSchema converts the Organization DTO to a schema.Organization model

type OrganizationOperations

type OrganizationOperations interface {
	// CreateOrganization creates a new user-created organization
	CreateOrganization(ctx context.Context, req *CreateOrganizationRequest, creatorUserID, appID, environmentID xid.ID) (*Organization, error)

	// FindOrganizationByID retrieves an organization by its ID
	FindOrganizationByID(ctx context.Context, id xid.ID) (*Organization, error)

	// FindOrganizationBySlug retrieves an organization by its slug within an app and environment
	FindOrganizationBySlug(ctx context.Context, appID, environmentID xid.ID, slug string) (*Organization, error)

	// ListOrganizations retrieves a paginated list of organizations within an app and environment
	ListOrganizations(ctx context.Context, filter *ListOrganizationsFilter) (*pagination.PageResponse[*Organization], error)

	// ListUserOrganizations retrieves a paginated list of organizations a user is a member of
	ListUserOrganizations(ctx context.Context, userID xid.ID, filter *pagination.PaginationParams) (*pagination.PageResponse[*Organization], error)

	// UpdateOrganization updates an existing organization
	UpdateOrganization(ctx context.Context, id xid.ID, req *UpdateOrganizationRequest) (*Organization, error)

	// DeleteOrganization deletes an organization (owner only)
	DeleteOrganization(ctx context.Context, id, userID xid.ID) error
}

OrganizationOperations defines organization management operations

type OrganizationRepository

type OrganizationRepository interface {
	// Create creates a new organization
	Create(ctx context.Context, org *Organization) error

	// FindByID retrieves an organization by its ID
	FindByID(ctx context.Context, id xid.ID) (*Organization, error)

	// FindBySlug retrieves an organization by its slug within an app and environment
	FindBySlug(ctx context.Context, appID, envID xid.ID, slug string) (*Organization, error)

	// ListByApp retrieves a paginated list of organizations within an app and environment
	ListByApp(ctx context.Context, filter *ListOrganizationsFilter) (*pagination.PageResponse[*Organization], error)

	// ListByUser retrieves a paginated list of organizations a user is a member of
	ListByUser(ctx context.Context, userID xid.ID, filter *pagination.PaginationParams) (*pagination.PageResponse[*Organization], error)

	// Update updates an existing organization
	Update(ctx context.Context, org *Organization) error

	// Delete deletes an organization by ID
	Delete(ctx context.Context, id xid.ID) error

	// CountByUser counts the number of organizations a user has created or is a member of
	CountByUser(ctx context.Context, userID xid.ID) (int, error)
}

OrganizationRepository defines the interface for organization data access

type OrganizationService

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

OrganizationService handles organization aggregate operations

func NewOrganizationService

func NewOrganizationService(repo OrganizationRepository, cfg Config, rbacSvc *rbac.Service) *OrganizationService

NewOrganizationService creates a new organization service

func (*OrganizationService) CreateOrganization

func (s *OrganizationService) CreateOrganization(ctx context.Context, req *CreateOrganizationRequest, creatorUserID, appID, environmentID xid.ID) (*Organization, error)

CreateOrganization creates a new user-created organization

func (*OrganizationService) DeleteOrganization

func (s *OrganizationService) DeleteOrganization(ctx context.Context, id, userID xid.ID) error

DeleteOrganization deletes an organization (owner only - authorization check should be done before calling)

func (*OrganizationService) FindOrganizationByID

func (s *OrganizationService) FindOrganizationByID(ctx context.Context, id xid.ID) (*Organization, error)

FindOrganizationByID retrieves an organization by ID

func (*OrganizationService) FindOrganizationBySlug

func (s *OrganizationService) FindOrganizationBySlug(ctx context.Context, appID, environmentID xid.ID, slug string) (*Organization, error)

FindOrganizationBySlug retrieves an organization by slug

func (*OrganizationService) ListOrganizations

ListOrganizations lists organizations with pagination and filtering

func (*OrganizationService) ListUserOrganizations

func (s *OrganizationService) ListUserOrganizations(ctx context.Context, userID xid.ID, filter *pagination.PaginationParams) (*pagination.PageResponse[*Organization], error)

ListUserOrganizations lists organizations a user is a member of

func (*OrganizationService) UpdateOrganization

func (s *OrganizationService) UpdateOrganization(ctx context.Context, id xid.ID, req *UpdateOrganizationRequest) (*Organization, error)

UpdateOrganization updates an organization

type Service

type Service struct {
	Organization *OrganizationService
	Member       *MemberService
	Team         *TeamService
	Invitation   *InvitationService
}

Service provides access to all organization-related services Internally delegates to focused services for better separation of concerns

func NewService

func NewService(
	orgRepo OrganizationRepository,
	memberRepo MemberRepository,
	teamRepo TeamRepository,
	invitationRepo InvitationRepository,
	cfg Config,
	rbacSvc *rbac.Service,
) *Service

NewService creates a new service with all focused services

func (*Service) AcceptInvitation

func (s *Service) AcceptInvitation(ctx context.Context, token string, userID xid.ID) (*Member, error)

func (*Service) AddMember

func (s *Service) AddMember(ctx context.Context, orgID, userID xid.ID, role string) (*Member, error)

func (*Service) AddTeamMember

func (s *Service) AddTeamMember(ctx context.Context, teamID, memberID, adderUserID xid.ID) error

func (*Service) CancelInvitation

func (s *Service) CancelInvitation(ctx context.Context, id, cancellerUserID xid.ID) error

func (*Service) CleanupExpiredInvitations

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

func (*Service) CreateOrganization

func (s *Service) CreateOrganization(ctx context.Context, req *CreateOrganizationRequest, creatorUserID, appID, environmentID xid.ID) (*Organization, error)

func (*Service) CreateTeam

func (s *Service) CreateTeam(ctx context.Context, orgID xid.ID, req *CreateTeamRequest, creatorUserID xid.ID) (*Team, error)

func (*Service) DeclineInvitation

func (s *Service) DeclineInvitation(ctx context.Context, token string) error

func (*Service) DeleteOrganization

func (s *Service) DeleteOrganization(ctx context.Context, id, userID xid.ID) error

func (*Service) DeleteTeam

func (s *Service) DeleteTeam(ctx context.Context, id, deleterUserID xid.ID) error

func (*Service) FindInvitationByID

func (s *Service) FindInvitationByID(ctx context.Context, id xid.ID) (*Invitation, error)

func (*Service) FindInvitationByToken

func (s *Service) FindInvitationByToken(ctx context.Context, token string) (*Invitation, error)

func (*Service) FindMember

func (s *Service) FindMember(ctx context.Context, orgID, userID xid.ID) (*Member, error)

func (*Service) FindMemberByID

func (s *Service) FindMemberByID(ctx context.Context, id xid.ID) (*Member, error)

func (*Service) FindOrganizationByID

func (s *Service) FindOrganizationByID(ctx context.Context, id xid.ID) (*Organization, error)

func (*Service) FindOrganizationBySlug

func (s *Service) FindOrganizationBySlug(ctx context.Context, appID, environmentID xid.ID, slug string) (*Organization, error)

func (*Service) FindTeamByID

func (s *Service) FindTeamByID(ctx context.Context, id xid.ID) (*Team, error)

func (*Service) FindTeamByName

func (s *Service) FindTeamByName(ctx context.Context, orgID xid.ID, name string) (*Team, error)

func (*Service) GetUserMemberships

func (s *Service) GetUserMemberships(ctx context.Context, userID xid.ID, filter *pagination.PaginationParams) (*pagination.PageResponse[*Member], error)

func (*Service) InviteMember

func (s *Service) InviteMember(ctx context.Context, orgID xid.ID, req *InviteMemberRequest, inviterUserID xid.ID) (*Invitation, error)

func (*Service) IsAdmin

func (s *Service) IsAdmin(ctx context.Context, orgID, userID xid.ID) (bool, error)

func (*Service) IsMember

func (s *Service) IsMember(ctx context.Context, orgID, userID xid.ID) (bool, error)

func (*Service) IsOwner

func (s *Service) IsOwner(ctx context.Context, orgID, userID xid.ID) (bool, error)

func (*Service) IsTeamMember

func (s *Service) IsTeamMember(ctx context.Context, teamID, memberID xid.ID) (bool, error)

func (*Service) ListInvitations

func (s *Service) ListInvitations(ctx context.Context, filter *ListInvitationsFilter) (*pagination.PageResponse[*Invitation], error)

func (*Service) ListMembers

func (s *Service) ListMembers(ctx context.Context, filter *ListMembersFilter) (*pagination.PageResponse[*Member], error)

func (*Service) ListOrganizations

func (s *Service) ListOrganizations(ctx context.Context, filter *ListOrganizationsFilter) (*pagination.PageResponse[*Organization], error)

func (*Service) ListTeamMembers

func (s *Service) ListTeamMembers(ctx context.Context, filter *ListTeamMembersFilter) (*pagination.PageResponse[*TeamMember], error)

func (*Service) ListTeams

func (s *Service) ListTeams(ctx context.Context, filter *ListTeamsFilter) (*pagination.PageResponse[*Team], error)

func (*Service) ListUserOrganizations

func (s *Service) ListUserOrganizations(ctx context.Context, userID xid.ID, filter *pagination.PaginationParams) (*pagination.PageResponse[*Organization], error)

func (*Service) RemoveMember

func (s *Service) RemoveMember(ctx context.Context, id, removerUserID xid.ID) error

func (*Service) RemoveTeamMember

func (s *Service) RemoveTeamMember(ctx context.Context, teamID, memberID, removerUserID xid.ID) error

func (*Service) RemoveUserFromAllOrganizations

func (s *Service) RemoveUserFromAllOrganizations(ctx context.Context, userID xid.ID) error

func (*Service) RequireAdmin

func (s *Service) RequireAdmin(ctx context.Context, orgID, userID xid.ID) error

func (*Service) RequireOwner

func (s *Service) RequireOwner(ctx context.Context, orgID, userID xid.ID) error

func (*Service) ResendInvitation

func (s *Service) ResendInvitation(ctx context.Context, id, resenderUserID xid.ID) (*Invitation, error)

func (*Service) UpdateMember

func (s *Service) UpdateMember(ctx context.Context, id xid.ID, req *UpdateMemberRequest, updaterUserID xid.ID) (*Member, error)

func (*Service) UpdateOrganization

func (s *Service) UpdateOrganization(ctx context.Context, id xid.ID, req *UpdateOrganizationRequest) (*Organization, error)

func (*Service) UpdateTeam

func (s *Service) UpdateTeam(ctx context.Context, id xid.ID, req *UpdateTeamRequest, updaterUserID xid.ID) (*Team, error)

type Team

type Team struct {
	ID             xid.ID                 `json:"id"`
	OrganizationID xid.ID                 `json:"organizationID"`
	Name           string                 `json:"name"`
	Description    string                 `json:"description,omitempty"`
	Metadata       map[string]interface{} `json:"metadata,omitempty"`
	// Provisioning tracking
	ProvisionedBy *string `json:"provisionedBy,omitempty"` // e.g., "scim"
	ExternalID    *string `json:"externalID,omitempty"`    // External system ID
	// Audit fields
	CreatedAt time.Time  `json:"createdAt"`
	UpdatedAt time.Time  `json:"updatedAt"`
	DeletedAt *time.Time `json:"deletedAt,omitempty"`
}

Team represents an organization team entity DTO (Data Transfer Object) This is separate from schema.OrganizationTeam to maintain proper separation of concerns

func FromSchemaTeam

func FromSchemaTeam(st *schema.OrganizationTeam) *Team

FromSchemaTeam converts a schema.OrganizationTeam model to Team DTO

func FromSchemaTeams

func FromSchemaTeams(teams []*schema.OrganizationTeam) []*Team

FromSchemaTeams converts a slice of schema.OrganizationTeam to Team DTOs

func (*Team) ToSchema

func (t *Team) ToSchema() *schema.OrganizationTeam

ToSchema converts the Team DTO to a schema.OrganizationTeam model

type TeamMember

type TeamMember struct {
	ID       xid.ID    `json:"id"`
	TeamID   xid.ID    `json:"teamID"`
	MemberID xid.ID    `json:"memberID"` // References OrganizationMember
	JoinedAt time.Time `json:"joinedAt"`
	// Provisioning tracking
	ProvisionedBy *string `json:"provisionedBy,omitempty"` // e.g., "scim"
	// Audit fields
	CreatedAt time.Time  `json:"createdAt"`
	UpdatedAt time.Time  `json:"updatedAt"`
	DeletedAt *time.Time `json:"deletedAt,omitempty"`
}

TeamMember represents a team member entity DTO

func FromSchemaTeamMember

func FromSchemaTeamMember(stm *schema.OrganizationTeamMember) *TeamMember

FromSchemaTeamMember converts a schema.OrganizationTeamMember model to TeamMember DTO

func FromSchemaTeamMembers

func FromSchemaTeamMembers(teamMembers []*schema.OrganizationTeamMember) []*TeamMember

FromSchemaTeamMembers converts a slice of schema.OrganizationTeamMember to TeamMember DTOs

func (*TeamMember) ToSchema

func (tm *TeamMember) ToSchema() *schema.OrganizationTeamMember

ToSchema converts the TeamMember DTO to a schema.OrganizationTeamMember model

type TeamOperations

type TeamOperations interface {
	// CreateTeam creates a new team within an organization
	CreateTeam(ctx context.Context, orgID xid.ID, req *CreateTeamRequest, creatorUserID xid.ID) (*Team, error)

	// FindTeamByID retrieves a team by its ID
	FindTeamByID(ctx context.Context, id xid.ID) (*Team, error)

	// FindTeamByName retrieves a team by name within an organization
	FindTeamByName(ctx context.Context, orgID xid.ID, name string) (*Team, error)

	// ListTeams retrieves a paginated list of teams in an organization
	ListTeams(ctx context.Context, filter *ListTeamsFilter) (*pagination.PageResponse[*Team], error)

	// UpdateTeam updates a team's details
	UpdateTeam(ctx context.Context, id xid.ID, req *UpdateTeamRequest, updaterUserID xid.ID) (*Team, error)

	// DeleteTeam deletes a team
	DeleteTeam(ctx context.Context, id, deleterUserID xid.ID) error

	// AddTeamMember adds a member to a team
	AddTeamMember(ctx context.Context, teamID, memberID, adderUserID xid.ID) error

	// RemoveTeamMember removes a member from a team
	RemoveTeamMember(ctx context.Context, teamID, memberID, removerUserID xid.ID) error

	// ListTeamMembers retrieves a paginated list of team members
	ListTeamMembers(ctx context.Context, filter *ListTeamMembersFilter) (*pagination.PageResponse[*TeamMember], error)

	// IsTeamMember checks if a member belongs to a team
	IsTeamMember(ctx context.Context, teamID, memberID xid.ID) (bool, error)
}

TeamOperations defines team management operations

type TeamRepository

type TeamRepository interface {
	// Create creates a new team
	Create(ctx context.Context, team *Team) error

	// FindByID retrieves a team by its ID
	FindByID(ctx context.Context, id xid.ID) (*Team, error)

	// FindByName retrieves a team by name within an organization
	FindByName(ctx context.Context, orgID xid.ID, name string) (*Team, error)

	// ListByOrganization retrieves a paginated list of teams in an organization
	ListByOrganization(ctx context.Context, filter *ListTeamsFilter) (*pagination.PageResponse[*Team], error)

	// Update updates an existing team
	Update(ctx context.Context, team *Team) error

	// Delete deletes a team by ID
	Delete(ctx context.Context, id xid.ID) error

	// CountByOrganization counts the number of teams in an organization
	CountByOrganization(ctx context.Context, orgID xid.ID) (int, error)

	// AddMember adds a member to a team (part of team aggregate)
	AddMember(ctx context.Context, tm *TeamMember) error

	// RemoveMember removes a member from a team
	RemoveMember(ctx context.Context, teamID, memberID xid.ID) error

	// ListMembers retrieves a paginated list of team members
	ListMembers(ctx context.Context, filter *ListTeamMembersFilter) (*pagination.PageResponse[*TeamMember], error)

	// CountMembers counts the number of members in a team
	CountMembers(ctx context.Context, teamID xid.ID) (int, error)

	// IsTeamMember checks if a member belongs to a team
	IsTeamMember(ctx context.Context, teamID, memberID xid.ID) (bool, error)
}

TeamRepository defines the interface for organization team data access

type TeamService

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

TeamService handles team aggregate operations

func NewTeamService

func NewTeamService(repo TeamRepository, memberRepo MemberRepository, cfg Config, rbacSvc *rbac.Service) *TeamService

NewTeamService creates a new team service

func (*TeamService) AddTeamMember

func (s *TeamService) AddTeamMember(ctx context.Context, teamID, memberID, adderUserID xid.ID) error

AddTeamMember adds a member to a team

func (*TeamService) CreateTeam

func (s *TeamService) CreateTeam(ctx context.Context, orgID xid.ID, req *CreateTeamRequest, creatorUserID xid.ID) (*Team, error)

CreateTeam creates a new team in an organization

func (*TeamService) DeleteTeam

func (s *TeamService) DeleteTeam(ctx context.Context, id, deleterUserID xid.ID) error

DeleteTeam deletes a team

func (*TeamService) FindTeamByID

func (s *TeamService) FindTeamByID(ctx context.Context, id xid.ID) (*Team, error)

FindTeamByID retrieves a team by ID

func (*TeamService) FindTeamByName

func (s *TeamService) FindTeamByName(ctx context.Context, orgID xid.ID, name string) (*Team, error)

FindTeamByName retrieves a team by name within an organization

func (*TeamService) IsSCIMManaged added in v0.0.2

func (s *TeamService) IsSCIMManaged(team *Team) bool

IsSCIMManaged checks if a team is managed via SCIM provisioning

func (*TeamService) IsTeamMember

func (s *TeamService) IsTeamMember(ctx context.Context, teamID, memberID xid.ID) (bool, error)

IsTeamMember checks if a member belongs to a team

func (*TeamService) IsTeamMemberSCIMManaged added in v0.0.2

func (s *TeamService) IsTeamMemberSCIMManaged(teamMember *TeamMember) bool

IsTeamMemberSCIMManaged checks if a team membership is managed via SCIM provisioning

func (*TeamService) ListTeamMembers

ListTeamMembers lists members of a team

func (*TeamService) ListTeams

func (s *TeamService) ListTeams(ctx context.Context, filter *ListTeamsFilter) (*pagination.PageResponse[*Team], error)

ListTeams lists teams in an organization

func (*TeamService) RemoveTeamMember

func (s *TeamService) RemoveTeamMember(ctx context.Context, teamID, memberID, removerUserID xid.ID) error

RemoveTeamMember removes a member from a team

func (*TeamService) UpdateTeam

func (s *TeamService) UpdateTeam(ctx context.Context, id xid.ID, req *UpdateTeamRequest, updaterUserID xid.ID) (*Team, error)

UpdateTeam updates a team

type UpdateMemberRequest

type UpdateMemberRequest struct {
	Role   *string `json:"role,omitempty" validate:"omitempty,oneof=owner admin member"`
	Status *string `json:"status,omitempty" validate:"omitempty,oneof=active suspended pending"`
}

UpdateMemberRequest represents an update member request

type UpdateOrganizationRequest

type UpdateOrganizationRequest struct {
	Name     *string                `json:"name,omitempty" validate:"omitempty,min=1,max=100"`
	Metadata map[string]interface{} `json:"metadata,omitempty"`
}

UpdateOrganizationRequest represents an update organization request

type UpdateTeamRequest

type UpdateTeamRequest struct {
	Name        *string                `json:"name,omitempty" validate:"omitempty,min=1,max=100"`
	Description *string                `json:"description,omitempty"`
	Metadata    map[string]interface{} `json:"metadata,omitempty"`
}

UpdateTeamRequest represents a request to update a team

Jump to

Keyboard shortcuts

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