organization

package
v0.27.0 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package organization defines event names and typed event payloads published by the Organization plugin on the global EventBus.

Package organization provides multi-tenancy, role-based access control (RBAC), team structures, and invitation management capabilities for the go-modular-auth ecosystem.

Index

Constants

View Source
const (
	// Organization Events
	EventOrgCreateBefore    = "org:create:before"
	EventOrgCreateAfter     = "org:create:after"
	EventOrgUpdateBefore    = "org:update:before"
	EventOrgUpdateAfter     = "org:update:after"
	EventOrgDeleteBefore    = "org:delete:before"
	EventOrgDeleteAfter     = "org:delete:after"
	EventOrgSetActiveBefore = "org:set_active:before"
	EventOrgSetActiveAfter  = "org:set_active:after"

	// Member Events
	EventMemberAddBefore        = "org:member:add:before"
	EventMemberAddAfter         = "org:member:add:after"
	EventMemberRemoveBefore     = "org:member:remove:before"
	EventMemberRemoveAfter      = "org:member:remove:after"
	EventMemberRoleUpdateBefore = "org:member:role_update:before"
	EventMemberRoleUpdateAfter  = "org:member:role_update:after"
	EventMemberLeaveBefore      = "org:member:leave:before"
	EventMemberLeaveAfter       = "org:member:leave:after"

	// Invitation Events
	EventInvitationCreateBefore = "org:invitation:create:before"
	EventInvitationCreateAfter  = "org:invitation:create:after"
	EventInvitationAcceptBefore = "org:invitation:accept:before"
	EventInvitationAcceptAfter  = "org:invitation:accept:after"
	EventInvitationRejectBefore = "org:invitation:reject:before"
	EventInvitationRejectAfter  = "org:invitation:reject:after"
	EventInvitationCancelBefore = "org:invitation:cancel:before"
	EventInvitationCancelAfter  = "org:invitation:cancel:after"

	// Team Events
	EventTeamCreateBefore       = "org:team:create:before"
	EventTeamCreateAfter        = "org:team:create:after"
	EventTeamUpdateBefore       = "org:team:update:before"
	EventTeamUpdateAfter        = "org:team:update:after"
	EventTeamDeleteBefore       = "org:team:delete:before"
	EventTeamDeleteAfter        = "org:team:delete:after"
	EventTeamMemberAddBefore    = "org:team_member:add:before"
	EventTeamMemberAddAfter     = "org:team_member:add:after"
	EventTeamMemberRemoveBefore = "org:team_member:remove:before"
	EventTeamMemberRemoveAfter  = "org:team_member:remove:after"
	EventTeamSetActiveBefore    = "org:team:set_active:before"
	EventTeamSetActiveAfter     = "org:team:set_active:after"

	// Dynamic Role Events
	EventRoleCreateBefore = "org:role:create:before"
	EventRoleCreateAfter  = "org:role:create:after"
	EventRoleUpdateBefore = "org:role:update:before"
	EventRoleUpdateAfter  = "org:role:update:after"
	EventRoleDeleteBefore = "org:role:delete:before"
	EventRoleDeleteAfter  = "org:role:delete:after"
)

Event Name Constants

View Source
const (
	// RoleOwner represents the highest administrative role in an organization with full control.
	RoleOwner = "owner"

	// RoleAdmin represents an administrative role with elevated management privileges.
	RoleAdmin = "admin"

	// RoleMember represents a standard member role with default read permissions.
	RoleMember = "member"
)

Standard predefined role names within an organization.

View Source
const (
	// ResourceOrganization targets organization-level entities and properties.
	ResourceOrganization = "organization"

	// ResourceMember targets organization membership entities.
	ResourceMember = "member"

	// ResourceInvitation targets member invitations.
	ResourceInvitation = "invitation"

	// ResourceTeam targets organizational team entities.
	ResourceTeam = "team"

	// ResourceAccessControl targets dynamic role and permission configurations.
	ResourceAccessControl = "ac"
)

Standard RBAC resource identifiers for access control statements.

View Source
const (
	// ActionCreate represents permission to create new resources.
	ActionCreate = "create"

	// ActionRead represents permission to view or inspect resources.
	ActionRead = "read"

	// ActionUpdate represents permission to modify existing resources.
	ActionUpdate = "update"

	// ActionDelete represents permission to remove resources.
	ActionDelete = "delete"

	// ActionCancel represents permission to cancel invitations or operations.
	ActionCancel = "cancel"
)

Standard RBAC action identifiers for access control statements.

View Source
const (
	// ExtraKeyOrgID stores the organization identifier in dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyOrgID = "org_id"

	// ExtraKeyOrgSlug stores the organization URL-friendly slug in dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyOrgSlug = "org_slug"

	// ExtraKeyOrgName stores the organization display name in dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyOrgName = "org_name"

	// ExtraKeyMemberRole stores the role assigned to a member in dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyMemberRole = "member_role"

	// ExtraKeyTeamID stores the team identifier in dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyTeamID = "team_id"

	// ExtraKeyInviterID stores the user ID of the inviter in dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyInviterID = "inviter_id"

	// ExtraKeyInvitationID stores the invitation identifier in dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyInvitationID = "invitation_id"

	// ExtraKeyUserID stores the associated user identifier in dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyUserID = "user_id"

	// ExtraKeyEmail stores the targeted email address in dynamic Extra metadata.
	// Expected type: string.
	ExtraKeyEmail = "email"
)

Standard Extra metadata keys that can be set or consumed in organization operations and events.

View Source
const (
	// ContextKeyActiveOrgPrefix is the key prefix used when tracking a user's active organization in plugin.Context.
	ContextKeyActiveOrgPrefix = "org:active:"

	// ContextKeyActiveTeamPrefix is the key prefix used when tracking a user's active team in plugin.Context.
	ContextKeyActiveTeamPrefix = "org:team:active:"
)

Shared plugin context key prefixes used for active tenant context in plugin.Context.

View Source
const (
	MemberContextKey       contextKey = "org_member"
	OrganizationContextKey contextKey = "org_entity"
)
View Source
const PluginID = "organization"

PluginID is the unique string identifier for the Organization plugin ("organization").

Variables

View Source
var (
	// ErrOrganizationNotFound is returned when an organization matching the specified criteria does not exist.
	ErrOrganizationNotFound = errors.New("organization not found")

	// ErrOrganizationAlreadyExists is returned when attempting to create an organization that already exists.
	ErrOrganizationAlreadyExists = errors.New("organization already exists")

	// ErrSlugAlreadyExists is returned when the requested slug is already taken by another organization.
	ErrSlugAlreadyExists = errors.New("organization slug already exists")

	// ErrMemberNotFound is returned when a user is not a member of the specified organization.
	ErrMemberNotFound = errors.New("member not found in organization")

	// ErrMemberAlreadyExists is returned when attempting to add a user who is already a member of the organization.
	ErrMemberAlreadyExists = errors.New("member already exists in organization")

	// ErrCannotRemoveLastOwner is returned when attempting to remove or demote the last remaining owner in an organization.
	ErrCannotRemoveLastOwner = errors.New("cannot remove or demote the last owner of the organization")

	// ErrCannotLeaveAsLastOwner is returned when the last owner attempts to leave the organization without transferring ownership.
	ErrCannotLeaveAsLastOwner = errors.New("cannot leave organization as the last owner without transferring ownership")

	// ErrInvitationNotFound is returned when an invitation cannot be found by ID or email.
	ErrInvitationNotFound = errors.New("invitation not found")

	// ErrInvitationExpired is returned when attempting to accept or process an expired invitation.
	ErrInvitationExpired = errors.New("invitation has expired")

	// ErrInvitationAlreadyExists is returned when a pending invitation already exists for the email in the organization.
	ErrInvitationAlreadyExists = errors.New("a pending invitation already exists for this email in the organization")

	// ErrInvalidInvitationStatus is returned when an action requires an invitation in 'pending' status but found otherwise.
	ErrInvalidInvitationStatus = errors.New("invitation status is invalid for this operation")

	// ErrTeamNotFound is returned when a team does not exist in the organization.
	ErrTeamNotFound = errors.New("team not found")

	// ErrTeamAlreadyExists is returned when a team name already exists within the organization.
	ErrTeamAlreadyExists = errors.New("team already exists in organization")

	// ErrTeamMemberNotFound is returned when a user is not a member of the specified team.
	ErrTeamMemberNotFound = errors.New("team member not found")

	// ErrTeamMemberAlreadyExists is returned when a user is already assigned to the specified team.
	ErrTeamMemberAlreadyExists = errors.New("user is already a member of the team")

	// ErrCannotRemoveAllTeams is returned when attempting to delete the last team while AllowRemovingAllTeams is false.
	ErrCannotRemoveAllTeams = errors.New("cannot remove all teams from organization")

	// ErrRoleNotFound is returned when a dynamic role cannot be found in the organization.
	ErrRoleNotFound = errors.New("dynamic role not found")

	// ErrRoleAlreadyExists is returned when a role with the given name already exists in the organization.
	ErrRoleAlreadyExists = errors.New("role name already exists in organization")

	// ErrPermissionDenied is returned when the current user's role lacks sufficient permissions to execute an action.
	ErrPermissionDenied = errors.New("permission denied")

	// ErrOrganizationLimitReached is returned when a user exceeds the allowed limit of created organizations.
	ErrOrganizationLimitReached = errors.New("maximum number of organizations reached")

	// ErrMembershipLimitReached is returned when an organization exceeds its maximum allowed members.
	ErrMembershipLimitReached = errors.New("maximum number of organization members reached")

	// ErrInvitationLimitReached is returned when an organization exceeds its maximum allowed pending invitations.
	ErrInvitationLimitReached = errors.New("maximum number of pending invitations reached")

	// ErrTeamsLimitReached is returned when an organization exceeds its maximum allowed teams.
	ErrTeamsLimitReached = errors.New("maximum number of teams reached")

	// ErrTeamMembersLimitReached is returned when a team exceeds its maximum allowed members.
	ErrTeamMembersLimitReached = errors.New("maximum number of team members reached")

	// ErrRolesLimitReached is returned when an organization exceeds its maximum allowed dynamic roles.
	ErrRolesLimitReached = errors.New("maximum number of dynamic roles reached")

	// ErrTeamsNotEnabled is returned when attempting team operations while the teams sub-module is disabled.
	ErrTeamsNotEnabled = errors.New("teams module is not enabled")

	// ErrDynamicACNotEnabled is returned when attempting dynamic role operations while dynamic AC is disabled.
	ErrDynamicACNotEnabled = errors.New("dynamic access control is not enabled")

	// ErrEmailNotVerified is returned when email verification is required before sending or accepting invitations.
	ErrEmailNotVerified = errors.New("email verification is required for invitations")

	// ErrInvalidParameter is returned when an invalid argument or parameter is supplied to an operation.
	ErrInvalidParameter = errors.New("invalid parameter provided")
)
View Source
var DefaultRoles = map[string]Permissions{
	RoleOwner: {
		ResourceOrganization:  {ActionUpdate, ActionDelete},
		ResourceMember:        {ActionCreate, ActionUpdate, ActionDelete},
		ResourceInvitation:    {ActionCreate, ActionCancel},
		ResourceTeam:          {ActionCreate, ActionUpdate, ActionDelete},
		ResourceAccessControl: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
	},
	RoleAdmin: {
		ResourceOrganization:  {ActionUpdate},
		ResourceMember:        {ActionCreate, ActionUpdate, ActionDelete},
		ResourceInvitation:    {ActionCreate, ActionCancel},
		ResourceTeam:          {ActionCreate, ActionUpdate, ActionDelete},
		ResourceAccessControl: {ActionCreate, ActionRead, ActionUpdate, ActionDelete},
	},
	RoleMember: {
		ResourceAccessControl: {ActionRead},
	},
}

DefaultRoles defines the baseline permission matrix for built-in roles (owner, admin, member).

Functions

func ActiveOrgContextKey

func ActiveOrgContextKey(userID string) string

ActiveOrgContextKey formats the context store key used to track a user's active organization.

func ActiveTeamContextKey

func ActiveTeamContextKey(userID string) string

ActiveTeamContextKey formats the context store key used to track a user's active team.

func EvaluatePermissions

func EvaluatePermissions(granted, required Permissions) bool

EvaluatePermissions checks if a granted permissions matrix satisfies all required permissions.

func HasAction

func HasAction(actions []string, targetAction string) bool

HasAction checks if a target action is present in an action list (or matches wildcard "*").

Types

type AcceptInvitationParams

type AcceptInvitationParams struct {
	InvitationID string `json:"invitation_id"`
	UserID       string `json:"user_id"`
	plugin.ExtraContainer
}

type AcceptInvitationResult

type AcceptInvitationResult struct {
	Invitation   *Invitation   `json:"invitation"`
	Member       *Member       `json:"member"`
	Organization *Organization `json:"organization"`
}

type AddMemberParams

type AddMemberParams struct {
	OrganizationID string `json:"organization_id"`
	UserID         string `json:"user_id"`
	Role           string `json:"role"`
	InvokingUserID string `json:"invoking_user_id,omitempty"`
	plugin.ExtraContainer
}

type AddMemberResult

type AddMemberResult struct {
	Member *Member `json:"member"`
}

type AddTeamMemberParams

type AddTeamMemberParams struct {
	TeamID         string `json:"team_id"`
	UserID         string `json:"user_id"`
	InvokingUserID string `json:"invoking_user_id,omitempty"`
	plugin.ExtraContainer
}

type AddTeamMemberResult

type AddTeamMemberResult struct {
	TeamMember *TeamMember `json:"team_member"`
}

type AllowOrgCreationFunc

type AllowOrgCreationFunc func(ctx context.Context, userID string) (bool, error)

AllowOrgCreationFunc defines a callback to authorize whether a specific user is permitted to create new organizations.

type CancelInvitationParams

type CancelInvitationParams struct {
	InvitationID string `json:"invitation_id"`
	UserID       string `json:"user_id,omitempty"`
	plugin.ExtraContainer
}

type CancelInvitationResult

type CancelInvitationResult struct {
	Invitation *Invitation `json:"invitation"`
}

type CheckSlugParams

type CheckSlugParams struct {
	Slug string `json:"slug"`
	plugin.ExtraContainer
}

type CheckSlugResult

type CheckSlugResult struct {
	Available bool `json:"available"`
}

type Config

type Config struct {
	// AllowUserToCreateOrganization determines whether a user is authorized to create a new organization.
	AllowUserToCreateOrganization AllowOrgCreationFunc

	// OrganizationLimit restricts the maximum number of organizations a user can create.
	OrganizationLimit OrgLimitFunc

	// CreatorRole specifies the initial role assigned to the user creating an organization (default: "owner").
	CreatorRole string

	// MembershipLimit restricts the maximum number of members per organization.
	MembershipLimit MembershipLimitFunc

	// InvitationExpiresIn defines the validity duration for issued member invitations (default: 48 hours).
	InvitationExpiresIn time.Duration

	// InvitationLimit restricts the maximum number of pending invitations per organization.
	InvitationLimit InvitationLimitFunc

	// CancelPendingInvitationsOnReInvite automatically cancels previous pending invitations when re-inviting the same email.
	CancelPendingInvitationsOnReInvite bool

	// RequireEmailVerificationOnInvitation enforces that the invited recipient email must be verified.
	RequireEmailVerificationOnInvitation bool

	// SendInvitationEmail is an optional delivery callback invoked whenever an invitation is created.
	SendInvitationEmail SendInvitationEmailFunc

	// TeamsEnabled enables the sub-module for organizational teams and team memberships.
	TeamsEnabled bool

	// DefaultTeamEnabled automatically creates an initial default team upon organization creation.
	DefaultTeamEnabled bool

	// AllowRemovingAllTeams permits deleting all teams in an organization (default: true).
	AllowRemovingAllTeams bool

	// MaximumTeams restricts the maximum number of teams per organization.
	MaximumTeams MaxTeamsFunc

	// MaximumMembersPerTeam restricts the maximum number of members per team.
	MaximumMembersPerTeam MaxMembersPerTeamFunc

	// DynamicAccessControlEnabled enables database-persisted dynamic roles and custom permission matrices.
	DynamicAccessControlEnabled bool

	// MaximumRolesPerOrganization restricts the maximum number of dynamic roles per organization.
	MaximumRolesPerOrganization MaxRolesFunc

	// CustomRoles defines static custom roles and their granted permission matrices.
	CustomRoles map[string]Permissions
}

Config holds all configuration settings and callbacks for the Organization plugin.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns baseline production-ready defaults for the Organization plugin.

type CreateInvitationParams

type CreateInvitationParams struct {
	OrganizationID string  `json:"organization_id"`
	InviterID      string  `json:"inviter_id"`
	Email          string  `json:"email"`
	Role           string  `json:"role"`
	TeamID         *string `json:"team_id,omitempty"`
	plugin.ExtraContainer
}

type CreateInvitationResult

type CreateInvitationResult struct {
	Invitation *Invitation `json:"invitation"`
}

type CreateOrganizationParams

type CreateOrganizationParams struct {
	UserID   string         `json:"user_id"`
	Name     string         `json:"name"`
	Slug     string         `json:"slug,omitempty"`
	Metadata map[string]any `json:"metadata,omitempty"`
	plugin.ExtraContainer
}

type CreateOrganizationResult

type CreateOrganizationResult struct {
	Organization *Organization `json:"organization"`
	Member       *Member       `json:"member"`
}

type CreateRoleParams

type CreateRoleParams struct {
	OrganizationID string              `json:"organization_id"`
	UserID         string              `json:"user_id,omitempty"`
	Role           string              `json:"role"`
	Permissions    map[string][]string `json:"permissions"`
	plugin.ExtraContainer
}

type CreateRoleResult

type CreateRoleResult struct {
	Role *OrganizationRole `json:"role"`
}

type CreateTeamParams

type CreateTeamParams struct {
	OrganizationID string `json:"organization_id"`
	UserID         string `json:"user_id,omitempty"`
	Name           string `json:"name"`
	plugin.ExtraContainer
}

type CreateTeamResult

type CreateTeamResult struct {
	Team *Team `json:"team"`
}

type DeleteOrganizationParams

type DeleteOrganizationParams struct {
	OrganizationID string `json:"organization_id"`
	UserID         string `json:"user_id,omitempty"`
	plugin.ExtraContainer
}

type DeleteOrganizationResult

type DeleteOrganizationResult struct {
	Success bool `json:"success"`
}

type DeleteRoleParams

type DeleteRoleParams struct {
	RoleID string `json:"role_id"`
	UserID string `json:"user_id,omitempty"`
	plugin.ExtraContainer
}

type DeleteRoleResult

type DeleteRoleResult struct {
	Success bool `json:"success"`
}

type DeleteTeamParams

type DeleteTeamParams struct {
	TeamID string `json:"team_id"`
	UserID string `json:"user_id,omitempty"`
	plugin.ExtraContainer
}

type DeleteTeamResult

type DeleteTeamResult struct {
	Success bool `json:"success"`
}

type GetActiveMemberParams

type GetActiveMemberParams struct {
	UserID         string `json:"user_id"`
	OrganizationID string `json:"organization_id,omitempty"`
	plugin.ExtraContainer
}

type GetActiveMemberResult

type GetActiveMemberResult struct {
	Member *Member `json:"member"`
}

type GetActiveMemberRoleParams

type GetActiveMemberRoleParams struct {
	UserID         string `json:"user_id"`
	OrganizationID string `json:"organization_id,omitempty"`
	plugin.ExtraContainer
}

type GetActiveMemberRoleResult

type GetActiveMemberRoleResult struct {
	Role string `json:"role"`
}

type GetActiveOrganizationParams

type GetActiveOrganizationParams struct {
	UserID string `json:"user_id"`
	plugin.ExtraContainer
}

type GetActiveOrganizationResult

type GetActiveOrganizationResult struct {
	Organization *Organization `json:"organization"`
	Member       *Member       `json:"member"`
}

type GetActiveTeamParams

type GetActiveTeamParams struct {
	UserID string `json:"user_id"`
	plugin.ExtraContainer
}

type GetActiveTeamResult

type GetActiveTeamResult struct {
	Team *Team `json:"team"`
}

type GetFullOrganizationParams

type GetFullOrganizationParams struct {
	OrganizationID string `json:"organization_id"`
	plugin.ExtraContainer
}

type GetFullOrganizationResult

type GetFullOrganizationResult struct {
	Organization *Organization `json:"organization"`
	Members      []*Member     `json:"members"`
	Invitations  []*Invitation `json:"invitations"`
	Teams        []*Team       `json:"teams,omitempty"`
}

type GetInvitationParams

type GetInvitationParams struct {
	InvitationID string `json:"invitation_id"`
	plugin.ExtraContainer
}

type GetInvitationResult

type GetInvitationResult struct {
	Invitation *Invitation `json:"invitation"`
}

type GetMemberParams

type GetMemberParams struct {
	OrganizationID string `json:"organization_id"`
	UserID         string `json:"user_id"`
	plugin.ExtraContainer
}

type GetMemberResult

type GetMemberResult struct {
	Member *Member `json:"member"`
}

type GetOrganizationBySlugParams

type GetOrganizationBySlugParams struct {
	Slug string `json:"slug"`
	plugin.ExtraContainer
}

type GetOrganizationBySlugResult

type GetOrganizationBySlugResult struct {
	Organization *Organization `json:"organization"`
}

type GetOrganizationParams

type GetOrganizationParams struct {
	OrganizationID string `json:"organization_id"`
	plugin.ExtraContainer
}

type GetOrganizationResult

type GetOrganizationResult struct {
	Organization *Organization `json:"organization"`
}

type GetRoleParams

type GetRoleParams struct {
	RoleID string `json:"role_id"`
	plugin.ExtraContainer
}

type GetRoleResult

type GetRoleResult struct {
	Role *OrganizationRole `json:"role"`
}

type GetTeamParams

type GetTeamParams struct {
	TeamID string `json:"team_id"`
	plugin.ExtraContainer
}

type GetTeamResult

type GetTeamResult struct {
	Team *Team `json:"team"`
}

type HasPermissionParams

type HasPermissionParams struct {
	OrganizationID string      `json:"organization_id"`
	UserID         string      `json:"user_id,omitempty"`
	Role           string      `json:"role,omitempty"`
	Permissions    Permissions `json:"permissions"`
	plugin.ExtraContainer
}

type HasPermissionResult

type HasPermissionResult struct {
	HasPermission bool `json:"has_permission"`
}

type Invitation

type Invitation struct {
	// ID is the unique invitation identifier.
	ID string `json:"id"`

	// OrganizationID identifies the organization to which the user is invited.
	OrganizationID string `json:"organizationId"`

	// Email is the recipient email address.
	Email string `json:"email"`

	// Role is the role to be assigned upon accepting the invitation.
	Role string `json:"role"`

	// Status indicates the current lifecycle status of the invitation.
	Status InvitationStatus `json:"status"`

	// TeamID optionally associates an initial team assignment upon accepting.
	TeamID *string `json:"teamId,omitempty"`

	// InviterID identifies the user who dispatched the invitation.
	InviterID string `json:"inviterId"`

	// ExpiresAt specifies the exact timestamp when the invitation expires.
	ExpiresAt time.Time `json:"expiresAt"`

	// CreatedAt marks when the invitation was issued.
	CreatedAt time.Time `json:"createdAt"`
}

Invitation represents an email invitation dispatched to invite a user into an organization.

type InvitationAcceptAfterEventPayload

type InvitationAcceptAfterEventPayload struct {
	Invitation   *Invitation
	Member       *Member
	Organization *Organization
	plugin.ExtraContainer
}

type InvitationAcceptBeforeEventPayload

type InvitationAcceptBeforeEventPayload struct {
	InvitationID string
	UserID       string
	plugin.ExtraContainer
}

type InvitationCancelAfterEventPayload

type InvitationCancelAfterEventPayload struct {
	Invitation *Invitation
	plugin.ExtraContainer
}

type InvitationCancelBeforeEventPayload

type InvitationCancelBeforeEventPayload struct {
	InvitationID string
	UserID       string
	plugin.ExtraContainer
}

type InvitationCreateAfterEventPayload

type InvitationCreateAfterEventPayload struct {
	Invitation *Invitation
	plugin.ExtraContainer
}

type InvitationCreateBeforeEventPayload

type InvitationCreateBeforeEventPayload struct {
	OrganizationID string
	InviterID      string
	Email          string
	Role           string
	TeamID         *string
	plugin.ExtraContainer
}

type InvitationEmailData

type InvitationEmailData struct {
	// Invitation is the newly created invitation record.
	Invitation *Invitation

	// Organization is the organization domain record.
	Organization *Organization

	// InviterID is the user ID of the inviter.
	InviterID string

	// InviterEmail is the email of the inviter if resolved.
	InviterEmail string

	// InviterName is the display name of the inviter if resolved.
	InviterName string
}

InvitationEmailData holds payload information passed to SendInvitationEmailFunc when an invitation is dispatched.

type InvitationLimitFunc

type InvitationLimitFunc func(ctx context.Context, orgID string) (int, error)

InvitationLimitFunc defines a callback returning the maximum number of active pending invitations for an organization.

type InvitationRejectAfterEventPayload

type InvitationRejectAfterEventPayload struct {
	Invitation *Invitation
	plugin.ExtraContainer
}

type InvitationRejectBeforeEventPayload

type InvitationRejectBeforeEventPayload struct {
	InvitationID string
	UserID       string
	plugin.ExtraContainer
}

type InvitationStatus

type InvitationStatus string

InvitationStatus represents the lifecycle state of a member invitation.

const (
	// InvitationStatusPending indicates an invitation is awaiting acceptance or rejection.
	InvitationStatusPending InvitationStatus = "pending"

	// InvitationStatusAccepted indicates an invitation has been accepted by the recipient.
	InvitationStatusAccepted InvitationStatus = "accepted"

	// InvitationStatusRejected indicates an invitation has been explicitly declined.
	InvitationStatusRejected InvitationStatus = "rejected"

	// InvitationStatusCanceled indicates an invitation was revoked by an organization admin.
	InvitationStatusCanceled InvitationStatus = "canceled"
)

type LeaveOrganizationParams

type LeaveOrganizationParams struct {
	OrganizationID string `json:"organization_id"`
	UserID         string `json:"user_id"`
	plugin.ExtraContainer
}

type LeaveOrganizationResult

type LeaveOrganizationResult struct {
	Success bool `json:"success"`
}

type ListInvitationsParams

type ListInvitationsParams struct {
	OrganizationID string            `json:"organization_id"`
	Status         *InvitationStatus `json:"status,omitempty"`
	plugin.ExtraContainer
}

type ListInvitationsResult

type ListInvitationsResult struct {
	Invitations []*Invitation `json:"invitations"`
}

type ListMembersParams

type ListMembersParams struct {
	OrganizationID string `json:"organization_id"`
	Limit          int    `json:"limit,omitempty"`
	Offset         int    `json:"offset,omitempty"`
	plugin.ExtraContainer
}

type ListMembersResult

type ListMembersResult struct {
	Members []*Member `json:"members"`
	Total   int       `json:"total"`
}

type ListOrganizationsParams

type ListOrganizationsParams struct {
	UserID string `json:"user_id"`
	plugin.ExtraContainer
}

type ListOrganizationsResult

type ListOrganizationsResult struct {
	Organizations []*Organization `json:"organizations"`
}

type ListRolesParams

type ListRolesParams struct {
	OrganizationID string `json:"organization_id"`
	plugin.ExtraContainer
}

type ListRolesResult

type ListRolesResult struct {
	Roles []*OrganizationRole `json:"roles"`
}

type ListTeamMembersParams

type ListTeamMembersParams struct {
	TeamID string `json:"team_id"`
	plugin.ExtraContainer
}

type ListTeamMembersResult

type ListTeamMembersResult struct {
	Members []*TeamMember `json:"members"`
}

type ListTeamsParams

type ListTeamsParams struct {
	OrganizationID string `json:"organization_id"`
	UserID         string `json:"user_id,omitempty"`
	plugin.ExtraContainer
}

type ListTeamsResult

type ListTeamsResult struct {
	Teams []*Team `json:"teams"`
}

type ListUserInvitationsParams

type ListUserInvitationsParams struct {
	Email  string            `json:"email"`
	Status *InvitationStatus `json:"status,omitempty"`
	plugin.ExtraContainer
}

type ListUserInvitationsResult

type ListUserInvitationsResult struct {
	Invitations []*Invitation `json:"invitations"`
}

type MaxMembersPerTeamFunc

type MaxMembersPerTeamFunc func(ctx context.Context, teamID string) (int, error)

MaxMembersPerTeamFunc defines a callback returning the maximum number of members a team can hold.

type MaxRolesFunc

type MaxRolesFunc func(ctx context.Context, orgID string) (int, error)

MaxRolesFunc defines a callback returning the maximum number of dynamic roles an organization can configure.

type MaxTeamsFunc

type MaxTeamsFunc func(ctx context.Context, orgID string) (int, error)

MaxTeamsFunc defines a callback returning the maximum number of teams an organization can create.

type Member

type Member struct {
	// ID is the unique identifier for the membership record.
	ID string `json:"id"`

	// OrganizationID identifies the parent organization.
	OrganizationID string `json:"organizationId"`

	// UserID identifies the associated user.
	UserID string `json:"userId"`

	// Role is the assigned role name (e.g. "owner", "admin", "member", or comma-separated compound roles).
	Role string `json:"role"`

	// CreatedAt marks when the user joined the organization.
	CreatedAt time.Time `json:"createdAt"`

	// UpdatedAt marks when the membership record was last updated.
	UpdatedAt *time.Time `json:"updatedAt,omitempty"`

	// User contains enriched user profile information when populated.
	User *UserInfo `json:"user,omitempty"`
}

Member represents the membership relation connecting a user to an organization with an assigned role.

type MemberAddAfterEventPayload

type MemberAddAfterEventPayload struct {
	Member *Member
	plugin.ExtraContainer
}

type MemberAddBeforeEventPayload

type MemberAddBeforeEventPayload struct {
	OrganizationID string
	UserID         string
	Role           string
	plugin.ExtraContainer
}

type MemberLeaveAfterEventPayload

type MemberLeaveAfterEventPayload struct {
	OrganizationID string
	UserID         string
	plugin.ExtraContainer
}

type MemberLeaveBeforeEventPayload

type MemberLeaveBeforeEventPayload struct {
	OrganizationID string
	UserID         string
	plugin.ExtraContainer
}

type MemberRemoveAfterEventPayload

type MemberRemoveAfterEventPayload struct {
	OrganizationID string
	UserID         string
	plugin.ExtraContainer
}

type MemberRemoveBeforeEventPayload

type MemberRemoveBeforeEventPayload struct {
	OrganizationID string
	UserID         string
	plugin.ExtraContainer
}

type MemberRoleUpdateAfterEventPayload

type MemberRoleUpdateAfterEventPayload struct {
	Member *Member
	plugin.ExtraContainer
}

type MemberRoleUpdateBeforeEventPayload

type MemberRoleUpdateBeforeEventPayload struct {
	OrganizationID string
	UserID         string
	NewRole        string
	plugin.ExtraContainer
}

type MembershipLimitFunc

type MembershipLimitFunc func(ctx context.Context, orgID string) (int, error)

MembershipLimitFunc defines a callback returning the maximum number of members an organization can have.

type Option

type Option func(*Config)

Option configures the Organization plugin.

func WithAllowUserToCreateOrganization

func WithAllowUserToCreateOrganization(fn AllowOrgCreationFunc) Option

WithAllowUserToCreateOrganization sets a functional callback to validate organization creation permission.

func WithCancelPendingInvitationsOnReInvite

func WithCancelPendingInvitationsOnReInvite(cancel bool) Option

WithCancelPendingInvitationsOnReInvite controls whether existing pending invitations are auto-canceled on re-invitations.

func WithCreatorRole

func WithCreatorRole(role string) Option

WithCreatorRole sets the default role assigned to the user creating an organization.

func WithCustomRoles

func WithCustomRoles(roles map[string]Permissions) Option

WithCustomRoles registers custom static roles and their permission matrices.

func WithDynamicAccessControl

func WithDynamicAccessControl(enabled bool) Option

WithDynamicAccessControl enables or disables dynamic organization-scoped roles.

func WithDynamicAccessControlLimits

func WithDynamicAccessControlLimits(maxRoles MaxRolesFunc) Option

WithDynamicAccessControlLimits sets dynamic callbacks for role limits per organization.

func WithInvitationExpiresIn

func WithInvitationExpiresIn(duration time.Duration) Option

WithInvitationExpiresIn sets the expiration duration for issued member invitations.

func WithInvitationLimit

func WithInvitationLimit(limit int) Option

WithInvitationLimit sets a static maximum number of pending invitations per organization.

func WithInvitationLimitFunc

func WithInvitationLimitFunc(fn InvitationLimitFunc) Option

WithInvitationLimitFunc sets a dynamic callback to calculate pending invitation limits.

func WithMembershipLimit

func WithMembershipLimit(limit int) Option

WithMembershipLimit sets a static maximum limit of members per organization.

func WithMembershipLimitFunc

func WithMembershipLimitFunc(fn MembershipLimitFunc) Option

WithMembershipLimitFunc sets a dynamic callback to calculate membership limits.

func WithOrganizationLimit

func WithOrganizationLimit(limit int) Option

WithOrganizationLimit sets a static maximum number of organizations a user can create.

func WithOrganizationLimitFunc

func WithOrganizationLimitFunc(fn OrgLimitFunc) Option

WithOrganizationLimitFunc sets a dynamic callback to calculate organization creation limits per user.

func WithRequireEmailVerificationOnInvitation

func WithRequireEmailVerificationOnInvitation(require bool) Option

WithRequireEmailVerificationOnInvitation controls whether email verification is required for invitations.

func WithSendInvitationEmail

func WithSendInvitationEmail(fn SendInvitationEmailFunc) Option

WithSendInvitationEmail configures an external delivery callback for dispatching invitation emails.

func WithTeams

func WithTeams(enabled, defaultTeam, allowRemovingAll bool) Option

WithTeams configures the teams sub-module, default team creation, and deletion rules.

func WithTeamsLimits

func WithTeamsLimits(maxTeams MaxTeamsFunc, maxMembers MaxMembersPerTeamFunc) Option

WithTeamsLimits sets dynamic callbacks for team and team-membership limits.

type OrgCreateAfterEventPayload

type OrgCreateAfterEventPayload struct {
	Organization *Organization
	Member       *Member
	plugin.ExtraContainer
}

type OrgCreateBeforeEventPayload

type OrgCreateBeforeEventPayload struct {
	UserID   string
	Name     string
	Slug     string
	Metadata map[string]any
	plugin.ExtraContainer
}

type OrgDeleteAfterEventPayload

type OrgDeleteAfterEventPayload struct {
	OrganizationID string
	plugin.ExtraContainer
}

type OrgDeleteBeforeEventPayload

type OrgDeleteBeforeEventPayload struct {
	OrganizationID string
	plugin.ExtraContainer
}

type OrgLimitFunc

type OrgLimitFunc func(ctx context.Context, userID string) (int, error)

OrgLimitFunc defines a callback returning the maximum number of organizations a user can create.

type OrgSetActiveAfterEventPayload

type OrgSetActiveAfterEventPayload struct {
	UserID         string
	OrganizationID string
	Organization   *Organization
	Member         *Member
	plugin.ExtraContainer
}

type OrgSetActiveBeforeEventPayload

type OrgSetActiveBeforeEventPayload struct {
	UserID         string
	OrganizationID string
	plugin.ExtraContainer
}

type OrgUpdateAfterEventPayload

type OrgUpdateAfterEventPayload struct {
	Organization *Organization
	plugin.ExtraContainer
}

type OrgUpdateBeforeEventPayload

type OrgUpdateBeforeEventPayload struct {
	OrganizationID string
	Name           *string
	Slug           *string
	Metadata       map[string]any
	plugin.ExtraContainer
}

type Organization

type Organization struct {
	// ID is the unique string identifier for the organization.
	ID string `json:"id"`

	// Name is the display name of the organization.
	Name string `json:"name"`

	// Slug is the unique URL-friendly slug identifier for the organization.
	Slug string `json:"slug"`

	Logo string `json:"logo,omitempty"`

	// Metadata holds arbitrary key-value properties associated with the organization.
	Metadata map[string]any `json:"metadata,omitempty"`

	// CreatedAt marks the timestamp when the organization was created.
	CreatedAt time.Time `json:"createdAt"`

	// UpdatedAt marks the timestamp when the organization was last modified.
	UpdatedAt *time.Time `json:"updatedAt,omitempty"`
}

Organization represents a tenant boundary containing members, teams, invitations, and custom roles.

type OrganizationRole

type OrganizationRole struct {
	// ID is the unique role identifier.
	ID string `json:"id"`

	// OrganizationID identifies the parent organization owning the role.
	OrganizationID string `json:"organizationId"`

	// Role is the unique role name within the organization.
	Role string `json:"role"`

	// Permissions maps resource names to lists of granted actions (e.g. "member": ["create", "update"]).
	Permissions map[string][]string `json:"permissions"`

	// CreatedAt marks when the role was created.
	CreatedAt time.Time `json:"createdAt"`

	// UpdatedAt marks when the role was last updated.
	UpdatedAt *time.Time `json:"updatedAt,omitempty"`
}

OrganizationRole represents a dynamic, organization-scoped custom role and its permission matrix.

type Permissions

type Permissions map[string][]string

Permissions maps resource identifiers to lists of granted actions (e.g. "member": ["create", "update"]).

func ClonePermissions

func ClonePermissions(p Permissions) Permissions

ClonePermissions creates a deep copy of a Permissions map.

func MergePermissions

func MergePermissions(dst, src Permissions) Permissions

MergePermissions combines source permissions into destination permissions without duplicates.

type Plugin

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

Plugin implements multi-tenancy, member, team, and invitation management capabilities.

func New

func New(repo Repository, opts ...Option) *Plugin

New creates a new Organization plugin instance configured with a repository and functional options.

func (*Plugin) AcceptInvitation

func (p *Plugin) AcceptInvitation(ctx context.Context, params AcceptInvitationParams) (*AcceptInvitationResult, error)

AcceptInvitation accepts an active pending invitation, creates a new membership record, assigns team if specified, and marks the invitation accepted.

func (*Plugin) AddMember

func (p *Plugin) AddMember(ctx context.Context, params AddMemberParams) (*AddMemberResult, error)

AddMember adds a user as a member to an organization with a specified role after checking membership limits and RBAC permissions.

func (*Plugin) AddTeamMember

func (p *Plugin) AddTeamMember(ctx context.Context, params AddTeamMemberParams) (*AddTeamMemberResult, error)

AddTeamMember adds an existing organization member to a team after checking team member limits.

func (*Plugin) CancelInvitation

func (p *Plugin) CancelInvitation(ctx context.Context, params CancelInvitationParams) (*CancelInvitationResult, error)

CancelInvitation cancels a pending invitation after verifying user cancellation permissions.

func (*Plugin) CheckPermission

func (p *Plugin) CheckPermission(ctx context.Context, orgID, userRole string, required Permissions) (bool, error)

CheckPermission evaluates whether a user role possesses all required permissions in an organization.

func (*Plugin) CheckSlug

func (p *Plugin) CheckSlug(ctx context.Context, params CheckSlugParams) (*CheckSlugResult, error)

CheckSlug checks whether an organization slug is available for registration.

func (*Plugin) Config

func (p *Plugin) Config() Config

Config returns the active configuration settings of the Organization plugin.

func (*Plugin) CreateInvitation

func (p *Plugin) CreateInvitation(ctx context.Context, params CreateInvitationParams) (*CreateInvitationResult, error)

CreateInvitation generates a new pending invitation for a target email address, enforcing invitation limits, checking authorization permissions, calculating expiration, and optionally dispatching an email notification.

func (*Plugin) CreateOrganization

func (p *Plugin) CreateOrganization(ctx context.Context, params CreateOrganizationParams) (*CreateOrganizationResult, error)

CreateOrganization creates a new tenant organization, registers the creator as its initial owner member, optionally spins up a default team, and marks the organization as active for the user.

func (*Plugin) CreateRole

func (p *Plugin) CreateRole(ctx context.Context, params CreateRoleParams) (*CreateRoleResult, error)

CreateRole creates a new dynamic organization-scoped custom role and its permission matrix.

func (*Plugin) CreateTeam

func (p *Plugin) CreateTeam(ctx context.Context, params CreateTeamParams) (*CreateTeamResult, error)

CreateTeam creates a new team within an organization after checking module enablement, limits, and RBAC permissions.

func (*Plugin) DeleteOrganization

func (p *Plugin) DeleteOrganization(ctx context.Context, params DeleteOrganizationParams) (*DeleteOrganizationResult, error)

DeleteOrganization removes an organization after verifying user delete permissions.

func (*Plugin) DeleteRole

func (p *Plugin) DeleteRole(ctx context.Context, params DeleteRoleParams) (*DeleteRoleResult, error)

DeleteRole deletes a dynamic role from an organization.

func (*Plugin) DeleteTeam

func (p *Plugin) DeleteTeam(ctx context.Context, params DeleteTeamParams) (*DeleteTeamResult, error)

DeleteTeam deletes a team from an organization, enforcing AllowRemovingAllTeams safety.

func (*Plugin) GetActiveMember

func (p *Plugin) GetActiveMember(ctx context.Context, params GetActiveMemberParams) (*GetActiveMemberResult, error)

GetActiveMember retrieves the membership record for a user in their active (or specified) organization.

func (*Plugin) GetActiveMemberRole

func (p *Plugin) GetActiveMemberRole(ctx context.Context, params GetActiveMemberRoleParams) (*GetActiveMemberRoleResult, error)

GetActiveMemberRole retrieves the assigned role name of a user in their active (or specified) organization.

func (*Plugin) GetActiveOrganization

func (p *Plugin) GetActiveOrganization(ctx context.Context, params GetActiveOrganizationParams) (*GetActiveOrganizationResult, error)

GetActiveOrganization retrieves the currently active organization and membership for a user.

func (*Plugin) GetActiveTeam

func (p *Plugin) GetActiveTeam(ctx context.Context, params GetActiveTeamParams) (*GetActiveTeamResult, error)

GetActiveTeam retrieves the currently active team for a user.

func (*Plugin) GetFullOrganization

func (p *Plugin) GetFullOrganization(ctx context.Context, params GetFullOrganizationParams) (*GetFullOrganizationResult, error)

GetFullOrganization retrieves the complete organization details along with members, active invitations, and teams.

func (*Plugin) GetInvitation

func (p *Plugin) GetInvitation(ctx context.Context, params GetInvitationParams) (*GetInvitationResult, error)

GetInvitation retrieves an invitation by its unique identifier.

func (*Plugin) GetMember

func (p *Plugin) GetMember(ctx context.Context, params GetMemberParams) (*GetMemberResult, error)

GetMember retrieves a membership record by organization ID and user ID.

func (*Plugin) GetOrganization

func (p *Plugin) GetOrganization(ctx context.Context, params GetOrganizationParams) (*GetOrganizationResult, error)

GetOrganization retrieves an organization by its unique identifier.

func (*Plugin) GetOrganizationBySlug

func (p *Plugin) GetOrganizationBySlug(ctx context.Context, params GetOrganizationBySlugParams) (*GetOrganizationBySlugResult, error)

GetOrganizationBySlug retrieves an organization by its URL-friendly slug.

func (*Plugin) GetRole

func (p *Plugin) GetRole(ctx context.Context, params GetRoleParams) (*GetRoleResult, error)

GetRole retrieves a dynamic role by its unique identifier.

func (*Plugin) GetTeam

func (p *Plugin) GetTeam(ctx context.Context, params GetTeamParams) (*GetTeamResult, error)

GetTeam retrieves a team by its unique identifier.

func (*Plugin) HasPermission

func (p *Plugin) HasPermission(ctx context.Context, params HasPermissionParams) (*HasPermissionResult, error)

HasPermission checks whether a specified user or role possesses the required permissions in an organization.

func (*Plugin) ID

func (p *Plugin) ID() string

ID returns the unique identifier for the Organization plugin ("organization").

func (*Plugin) Init

func (p *Plugin) Init(ctx *plugin.Context) error

Init initializes the plugin within the global GoModularAuth context.

func (*Plugin) LeaveOrganization

func (p *Plugin) LeaveOrganization(ctx context.Context, params LeaveOrganizationParams) (*LeaveOrganizationResult, error)

LeaveOrganization allows a user to voluntarily leave an organization, preventing the last owner from leaving without transferring ownership.

func (*Plugin) ListInvitations

func (p *Plugin) ListInvitations(ctx context.Context, params ListInvitationsParams) (*ListInvitationsResult, error)

ListInvitations retrieves all invitations for an organization, optionally filtered by status.

func (*Plugin) ListMembers

func (p *Plugin) ListMembers(ctx context.Context, params ListMembersParams) (*ListMembersResult, error)

ListMembers retrieves a paginated list of members belonging to the specified organization.

func (*Plugin) ListOrganizations

func (p *Plugin) ListOrganizations(ctx context.Context, params ListOrganizationsParams) (*ListOrganizationsResult, error)

ListOrganizations returns all organizations where the specified user is a member.

func (*Plugin) ListRoles

func (p *Plugin) ListRoles(ctx context.Context, params ListRolesParams) (*ListRolesResult, error)

ListRoles retrieves all dynamic roles configured for an organization.

func (*Plugin) ListTeamMembers

func (p *Plugin) ListTeamMembers(ctx context.Context, params ListTeamMembersParams) (*ListTeamMembersResult, error)

ListTeamMembers retrieves all members assigned to a team.

func (*Plugin) ListTeams

func (p *Plugin) ListTeams(ctx context.Context, params ListTeamsParams) (*ListTeamsResult, error)

ListTeams retrieves all teams in an organization or all teams where a user participates.

func (*Plugin) ListUserInvitations

func (p *Plugin) ListUserInvitations(ctx context.Context, params ListUserInvitationsParams) (*ListUserInvitationsResult, error)

ListUserInvitations retrieves all invitations targeted to a given email address.

func (*Plugin) RejectInvitation

func (p *Plugin) RejectInvitation(ctx context.Context, params RejectInvitationParams) (*RejectInvitationResult, error)

RejectInvitation marks a pending invitation as rejected.

func (*Plugin) RemoveMember

func (p *Plugin) RemoveMember(ctx context.Context, params RemoveMemberParams) (*RemoveMemberResult, error)

RemoveMember deletes a user's membership from an organization, enforcing last-owner safety protection.

func (*Plugin) RemoveTeamMember

func (p *Plugin) RemoveTeamMember(ctx context.Context, params RemoveTeamMemberParams) (*RemoveTeamMemberResult, error)

RemoveTeamMember removes a user from a team.

func (*Plugin) Repository

func (p *Plugin) Repository() Repository

Repository returns the underlying storage repository instance.

func (*Plugin) RequireMember added in v0.20.0

func (p *Plugin) RequireMember(headerName ...string) func(next http.Handler) http.Handler

RequireMember returns a net/http middleware handler verifying that the user belongs to the target organization.

func (*Plugin) RequirePermission added in v0.20.0

func (p *Plugin) RequirePermission(requiredPermissions Permissions, headerName ...string) func(next http.Handler) http.Handler

RequirePermission returns a net/http middleware handler verifying organization membership and required permissions.

func (*Plugin) ResolveRolePermissions

func (p *Plugin) ResolveRolePermissions(ctx context.Context, orgID, roleStr string) (Permissions, error)

ResolveRolePermissions collects all permissions granted to a given role string, resolving built-in roles, custom static roles, and dynamic organization roles when enabled. Supports compound roles (e.g. "admin,billing").

func (*Plugin) SetActiveOrganization

func (p *Plugin) SetActiveOrganization(ctx context.Context, params SetActiveOrganizationParams) (*SetActiveOrganizationResult, error)

SetActiveOrganization stores the active organization context for a user in the shared context store.

func (*Plugin) SetActiveTeam

func (p *Plugin) SetActiveTeam(ctx context.Context, params SetActiveTeamParams) (*SetActiveTeamResult, error)

SetActiveTeam stores the active team context for a user in the shared context store.

func (*Plugin) UpdateMemberRole

func (p *Plugin) UpdateMemberRole(ctx context.Context, params UpdateMemberRoleParams) (*UpdateMemberRoleResult, error)

UpdateMemberRole updates the role assigned to a member, enforcing last-owner safety protection.

func (*Plugin) UpdateOrganization

func (p *Plugin) UpdateOrganization(ctx context.Context, params UpdateOrganizationParams) (*UpdateOrganizationResult, error)

UpdateOrganization modifies properties of an existing organization after verifying user update permissions.

func (*Plugin) UpdateRole

func (p *Plugin) UpdateRole(ctx context.Context, params UpdateRoleParams) (*UpdateRoleResult, error)

UpdateRole updates the name or permissions of an existing dynamic role.

func (*Plugin) UpdateTeam

func (p *Plugin) UpdateTeam(ctx context.Context, params UpdateTeamParams) (*UpdateTeamResult, error)

UpdateTeam modifies properties of an existing team after verifying user permissions.

type RejectInvitationParams

type RejectInvitationParams struct {
	InvitationID string `json:"invitation_id"`
	UserID       string `json:"user_id,omitempty"`
	plugin.ExtraContainer
}

type RejectInvitationResult

type RejectInvitationResult struct {
	Invitation *Invitation `json:"invitation"`
}

type RemoveMemberParams

type RemoveMemberParams struct {
	OrganizationID string `json:"organization_id"`
	UserID         string `json:"user_id"`
	InvokingUserID string `json:"invoking_user_id,omitempty"`
	plugin.ExtraContainer
}

type RemoveMemberResult

type RemoveMemberResult struct {
	Success bool `json:"success"`
}

type RemoveTeamMemberParams

type RemoveTeamMemberParams struct {
	TeamID         string `json:"team_id"`
	UserID         string `json:"user_id"`
	InvokingUserID string `json:"invoking_user_id,omitempty"`
	plugin.ExtraContainer
}

type RemoveTeamMemberResult

type RemoveTeamMemberResult struct {
	Success bool `json:"success"`
}

type Repository

type Repository interface {

	// CreateOrganization persists a new organization tenant boundary in storage.
	//
	// Function:
	//   Called during CreateOrganization API endpoint or flow.
	//
	// Storage:
	//   Database (GORM / SQL) - Relational organization creation.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - org: Organization domain entity to persist.
	//
	// Returns:
	//   - error: ErrOrganizationAlreadyExists or ErrSlugAlreadyExists on unique constraint violation.
	//
	// Example SQL:
	//   INSERT INTO organizations (id, name, slug, logo, metadata, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6, $7);
	CreateOrganization(ctx context.Context, org *Organization) error

	// GetOrganizationByID retrieves an organization record by its unique ID.
	//
	// Function:
	//   Used in organization context resolution, active organization lookup, and org management.
	//
	// Storage:
	//   Database (GORM / SQL) - Relational lookup by organization ID.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - id: Unique organization primary key.
	//
	// Returns:
	//   - *Organization: Matching entity if found.
	//   - error: ErrOrganizationNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, name, slug, logo, metadata, created_at, updated_at FROM organizations WHERE id = $1 LIMIT 1;
	GetOrganizationByID(ctx context.Context, id string) (*Organization, error)

	// GetOrganizationBySlug retrieves an organization record by its unique URL slug.
	//
	// Function:
	//   Used during slug-based organization routing or slug availability validation.
	//
	// Storage:
	//   Database (GORM / SQL) - Query organization by slug index.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - slug: URL-friendly organization slug.
	//
	// Returns:
	//   - *Organization: Matching entity if found.
	//   - error: ErrOrganizationNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, name, slug, logo, metadata, created_at, updated_at FROM organizations WHERE slug = $1 LIMIT 1;
	GetOrganizationBySlug(ctx context.Context, slug string) (*Organization, error)

	// UpdateOrganization updates mutable fields of an organization.
	//
	// Function:
	//   Called when updating organization settings, name, slug, logo, or metadata.
	//
	// Storage:
	//   Database (GORM / SQL) - Organization record update.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - org: Modified Organization entity.
	//
	// Returns:
	//   - error: Nil on success, or database error.
	//
	// Example SQL:
	//   UPDATE organizations SET name = $1, slug = $2, logo = $3, metadata = $4, updated_at = $5 WHERE id = $6;
	UpdateOrganization(ctx context.Context, org *Organization) error

	// DeleteOrganization permanently removes an organization record and cascades related data.
	//
	// Function:
	//   Called during organization removal by an owner.
	//
	// Storage:
	//   Database (GORM / SQL) - Organization deletion with cascade.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - id: Target organization ID.
	//
	// Returns:
	//   - error: Nil on success, or database error.
	//
	// Example SQL:
	//   DELETE FROM organizations WHERE id = $1;
	DeleteOrganization(ctx context.Context, id string) error

	// ListOrganizationsByUserID retrieves all organizations in which a user holds active membership.
	//
	// Function:
	//   Used during user organization switcher or listing user tenant access.
	//
	// Storage:
	//   Database (GORM / SQL) - Joined organizations and members query.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - userID: Target user identifier.
	//
	// Returns:
	//   - []*Organization: Slice of organizations.
	//   - error: Nil on success, or database error.
	//
	// Example SQL:
	//   SELECT o.id, o.name, o.slug, o.logo, o.metadata, o.created_at, o.updated_at
	//   FROM organizations o JOIN organization_members m ON o.id = m.organization_id WHERE m.user_id = $1;
	ListOrganizationsByUserID(ctx context.Context, userID string) ([]*Organization, error)

	// CreateMember adds a user to an organization with an assigned role.
	//
	// Function:
	//   Called during initial organization creation (adding creator as owner) or accepting an invitation.
	//
	// Storage:
	//   Database (GORM / SQL) - Member relation insertion.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - member: Member entity to persist.
	//
	// Returns:
	//   - error: ErrMemberAlreadyExists if already joined.
	//
	// Example SQL:
	//   INSERT INTO organization_members (id, organization_id, user_id, role, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6);
	CreateMember(ctx context.Context, member *Member) error

	// GetMember retrieves a membership record linking a user to an organization.
	//
	// Function:
	//   Used during permission authorization checks to verify user role in an org.
	//
	// Storage:
	//   Database (GORM / SQL) - Member record lookup by org & user ID.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization identifier.
	//   - userID: User identifier.
	//
	// Returns:
	//   - *Member: Matching membership record if found.
	//   - error: ErrMemberNotFound if user is not in org.
	//
	// Example SQL:
	//   SELECT id, organization_id, user_id, role, created_at, updated_at FROM organization_members WHERE organization_id = $1 AND user_id = $2 LIMIT 1;
	GetMember(ctx context.Context, orgID, userID string) (*Member, error)

	// GetMemberByID retrieves a membership record by its primary key ID.
	//
	// Function:
	//   Used in member detail views or administrative operations.
	//
	// Storage:
	//   Database (GORM / SQL) - Member primary key lookup.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - memberID: Membership record primary key.
	//
	// Returns:
	//   - *Member: Matching membership record.
	//   - error: ErrMemberNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, organization_id, user_id, role, created_at, updated_at FROM organization_members WHERE id = $1 LIMIT 1;
	GetMemberByID(ctx context.Context, memberID string) (*Member, error)

	// UpdateMember updates the assigned role of an organization member.
	//
	// Function:
	//   Called when promoting or demoting member roles.
	//
	// Storage:
	//   Database (GORM / SQL) - Member role update.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - member: Modified Member entity.
	//
	// Returns:
	//   - error: Nil on success, or database error.
	//
	// Example SQL:
	//   UPDATE organization_members SET role = $1, updated_at = $2 WHERE id = $3;
	UpdateMember(ctx context.Context, member *Member) error

	// DeleteMember removes a member from an organization.
	//
	// Function:
	//   Called when removing a member or when a member leaves an organization.
	//
	// Storage:
	//   Database (GORM / SQL) - Member record removal.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//   - userID: User ID to remove.
	//
	// Returns:
	//   - error: ErrCannotRemoveLastOwner if attempting to remove the sole remaining owner.
	//
	// Example SQL:
	//   DELETE FROM organization_members WHERE organization_id = $1 AND user_id = $2;
	DeleteMember(ctx context.Context, orgID, userID string) error

	// ListMembers retrieves a paginated list of organization members with enriched user profiles.
	//
	// Function:
	//   Used in team settings / member directory UI.
	//
	// Storage:
	//   Database (GORM / SQL) - Paginated joined member profiles query.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//   - limit: Page size limit.
	//   - offset: Pagination offset.
	//
	// Returns:
	//   - []*Member: Slice of members.
	//   - int: Total member count.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT m.id, m.organization_id, m.user_id, m.role, m.created_at, m.updated_at, u.email, u.name
	//   FROM organization_members m JOIN users u ON m.user_id = u.id WHERE m.organization_id = $1 LIMIT $2 OFFSET $3;
	ListMembers(ctx context.Context, orgID string, limit, offset int) ([]*Member, int, error)

	// CountMembersByRole returns the number of members holding a specific role in an organization.
	//
	// Function:
	//   Used to enforce minimum owner rules before demoting or removing members.
	//
	// Storage:
	//   Database (GORM / SQL) - Count members matching role.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//   - role: Target role string (e.g. "owner").
	//
	// Returns:
	//   - int: Member count with target role.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT COUNT(*) FROM organization_members WHERE organization_id = $1 AND role = $2;
	CountMembersByRole(ctx context.Context, orgID, role string) (int, error)

	// CountMembers returns the total member count in an organization.
	//
	// Function:
	//   Used to enforce organization membership quota limits.
	//
	// Storage:
	//   Database (GORM / SQL) - Total organization members count.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//
	// Returns:
	//   - int: Total count.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT COUNT(*) FROM organization_members WHERE organization_id = $1;
	CountMembers(ctx context.Context, orgID string) (int, error)

	// CreateInvitation persists a new email invitation to join an organization.
	//
	// Function:
	//   Called when an admin/owner invites a user by email.
	//
	// Storage:
	//   Database (GORM / SQL) - Invitation record creation.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - invitation: Invitation entity to store.
	//
	// Returns:
	//   - error: ErrInvitationAlreadyExists if a pending invitation already exists for the email.
	//
	// Example SQL:
	//   INSERT INTO organization_invitations (id, organization_id, email, role, status, team_id, inviter_id, expires_at, created_at) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9);
	CreateInvitation(ctx context.Context, invitation *Invitation) error

	// GetInvitationByID retrieves an invitation record by ID.
	//
	// Function:
	//   Called when accepting or rejecting an invitation using an invitation link/token.
	//
	// Storage:
	//   Database (GORM / SQL) - Invitation record query by ID.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - id: Invitation ID.
	//
	// Returns:
	//   - *Invitation: Matching record if found.
	//   - error: ErrInvitationNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, organization_id, email, role, status, team_id, inviter_id, expires_at, created_at FROM organization_invitations WHERE id = $1 LIMIT 1;
	GetInvitationByID(ctx context.Context, id string) (*Invitation, error)

	// GetPendingInvitation retrieves an active pending invitation by organization ID and email.
	//
	// Function:
	//   Used to check for duplicate pending invitations before issuing a new one.
	//
	// Storage:
	//   Database (GORM / SQL) - Pending invitation lookup.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//   - email: Recipient email address.
	//
	// Returns:
	//   - *Invitation: Pending invitation if found.
	//   - error: ErrInvitationNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, organization_id, email, role, status, team_id, inviter_id, expires_at, created_at FROM organization_invitations WHERE organization_id = $1 AND email = $2 AND status = 'pending' LIMIT 1;
	GetPendingInvitation(ctx context.Context, orgID, email string) (*Invitation, error)

	// UpdateInvitation updates the status (e.g. accepted, revoked, expired) of an invitation.
	//
	// Function:
	//   Called during invitation state transitions.
	//
	// Storage:
	//   Database (GORM / SQL) - Invitation status update.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - invitation: Modified Invitation entity.
	//
	// Returns:
	//   - error: Nil on success.
	//
	// Example SQL:
	//   UPDATE organization_invitations SET status = $1 WHERE id = $2;
	UpdateInvitation(ctx context.Context, invitation *Invitation) error

	// DeleteInvitation removes an invitation record from storage.
	//
	// Function:
	//   Called when cancelling or revoking an invitation.
	//
	// Storage:
	//   Database (GORM / SQL) - Invitation record deletion.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - id: Invitation ID.
	//
	// Returns:
	//   - error: Nil on success.
	//
	// Example SQL:
	//   DELETE FROM organization_invitations WHERE id = $1;
	DeleteInvitation(ctx context.Context, id string) error

	// ListInvitationsByOrgID lists invitations for an organization, optionally filtered by status.
	//
	// Function:
	//   Used in organization settings to view pending/sent invitations.
	//
	// Storage:
	//   Database (GORM / SQL) - Relational invitations list query.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//   - status: Optional status filter pointer.
	//
	// Returns:
	//   - []*Invitation: List of matching invitations.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT id, organization_id, email, role, status, team_id, inviter_id, expires_at, created_at FROM organization_invitations WHERE organization_id = $1 AND status = $2;
	ListInvitationsByOrgID(ctx context.Context, orgID string, status *InvitationStatus) ([]*Invitation, error)

	// ListInvitationsByEmail lists invitations sent to a user's email across all organizations.
	//
	// Function:
	//   Used in user dashboard to display pending organization invites for the logged-in user.
	//
	// Storage:
	//   Database (GORM / SQL) - User invitations list query.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - email: Recipient email address.
	//   - status: Optional status filter.
	//
	// Returns:
	//   - []*Invitation: List of invitations.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT id, organization_id, email, role, status, team_id, inviter_id, expires_at, created_at FROM organization_invitations WHERE email = $1 AND status = $2;
	ListInvitationsByEmail(ctx context.Context, email string, status *InvitationStatus) ([]*Invitation, error)

	// CountPendingInvitations returns the count of active pending invitations for an org.
	//
	// Function:
	//   Used to enforce pending invitation limits.
	//
	// Storage:
	//   Database (GORM / SQL) - Pending invitations count.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//
	// Returns:
	//   - int: Pending count.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT COUNT(*) FROM organization_invitations WHERE organization_id = $1 AND status = 'pending';
	CountPendingInvitations(ctx context.Context, orgID string) (int, error)

	// CreateTeam creates a sub-team within an organization.
	//
	// Function:
	//   Called when creating a team within an organization.
	//
	// Storage:
	//   Database (GORM / SQL) - Team entity creation.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - team: Team entity to persist.
	//
	// Returns:
	//   - error: ErrTeamAlreadyExists if team name is taken in org.
	//
	// Example SQL:
	//   INSERT INTO organization_teams (id, organization_id, name, created_at, updated_at) VALUES ($1, $2, $3, $4, $5);
	CreateTeam(ctx context.Context, team *Team) error

	// GetTeamByID retrieves a team by ID.
	//
	// Function:
	//   Used in team management endpoints.
	//
	// Storage:
	//   Database (GORM / SQL) - Team lookup by ID.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - id: Team ID.
	//
	// Returns:
	//   - *Team: Team entity if found.
	//   - error: ErrTeamNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, organization_id, name, created_at, updated_at FROM organization_teams WHERE id = $1 LIMIT 1;
	GetTeamByID(ctx context.Context, id string) (*Team, error)

	// UpdateTeam updates mutable team attributes.
	//
	// Function:
	//   Called when renaming a team.
	//
	// Storage:
	//   Database (GORM / SQL) - Team record update.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - team: Modified Team entity.
	//
	// Returns:
	//   - error: Nil on success.
	//
	// Example SQL:
	//   UPDATE organization_teams SET name = $1, updated_at = $2 WHERE id = $3;
	UpdateTeam(ctx context.Context, team *Team) error

	// DeleteTeam removes a team and unassigns members.
	//
	// Function:
	//   Called during team deletion.
	//
	// Storage:
	//   Database (GORM / SQL) - Team deletion.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - id: Team ID.
	//
	// Returns:
	//   - error: Nil on success.
	//
	// Example SQL:
	//   DELETE FROM organization_teams WHERE id = $1;
	DeleteTeam(ctx context.Context, id string) error

	// ListTeamsByOrgID lists all teams belonging to an organization.
	//
	// Function:
	//   Used in team directory views.
	//
	// Storage:
	//   Database (GORM / SQL) - Teams list query.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//
	// Returns:
	//   - []*Team: List of teams.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT id, organization_id, name, created_at, updated_at FROM organization_teams WHERE organization_id = $1;
	ListTeamsByOrgID(ctx context.Context, orgID string) ([]*Team, error)

	// ListTeamsByUserID lists teams in an organization to which a user belongs.
	//
	// Function:
	//   Used to filter user team memberships.
	//
	// Storage:
	//   Database (GORM / SQL) - User teams list query.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//   - userID: Target user ID.
	//
	// Returns:
	//   - []*Team: List of teams.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT t.id, t.organization_id, t.name, t.created_at, t.updated_at
	//   FROM organization_teams t JOIN organization_team_members tm ON t.id = tm.team_id WHERE t.organization_id = $1 AND tm.user_id = $2;
	ListTeamsByUserID(ctx context.Context, orgID, userID string) ([]*Team, error)

	// CountTeams returns the count of teams in an organization.
	//
	// Function:
	//   Used to enforce team limit quotas.
	//
	// Storage:
	//   Database (GORM / SQL) - Organization teams count.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//
	// Returns:
	//   - int: Count.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT COUNT(*) FROM organization_teams WHERE organization_id = $1;
	CountTeams(ctx context.Context, orgID string) (int, error)

	// AddTeamMember assigns a user to a team.
	//
	// Function:
	//   Called when adding an org member to a team.
	//
	// Storage:
	//   Database (GORM / SQL) - Team member mapping creation.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - teamMember: TeamMember entity.
	//
	// Returns:
	//   - error: ErrTeamMemberAlreadyExists if user is already in team.
	//
	// Example SQL:
	//   INSERT INTO organization_team_members (id, team_id, user_id, created_at) VALUES ($1, $2, $3, $4);
	AddTeamMember(ctx context.Context, teamMember *TeamMember) error

	// RemoveTeamMember unassigns a user from a team.
	//
	// Function:
	//   Called when removing a user from a team.
	//
	// Storage:
	//   Database (GORM / SQL) - Team member mapping deletion.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - teamID: Team ID.
	//   - userID: User ID.
	//
	// Returns:
	//   - error: ErrTeamMemberNotFound if user was not in team.
	//
	// Example SQL:
	//   DELETE FROM organization_team_members WHERE team_id = $1 AND user_id = $2;
	RemoveTeamMember(ctx context.Context, teamID, userID string) error

	// GetTeamMember retrieves a team member mapping record.
	//
	// Function:
	//   Used to check team membership.
	//
	// Storage:
	//   Database (GORM / SQL) - Team member mapping lookup.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - teamID: Team ID.
	//   - userID: User ID.
	//
	// Returns:
	//   - *TeamMember: Team member record.
	//   - error: ErrTeamMemberNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, team_id, user_id, created_at FROM organization_team_members WHERE team_id = $1 AND user_id = $2 LIMIT 1;
	GetTeamMember(ctx context.Context, teamID, userID string) (*TeamMember, error)

	// ListTeamMembers lists all member assignments for a team.
	//
	// Function:
	//   Used in team member listing.
	//
	// Storage:
	//   Database (GORM / SQL) - Team members list query.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - teamID: Team ID.
	//
	// Returns:
	//   - []*TeamMember: Slice of team members.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT id, team_id, user_id, created_at FROM organization_team_members WHERE team_id = $1;
	ListTeamMembers(ctx context.Context, teamID string) ([]*TeamMember, error)

	// CountTeamMembers counts members assigned to a team.
	//
	// Function:
	//   Used to check team capacity limits.
	//
	// Storage:
	//   Database (GORM / SQL) - Team members count.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - teamID: Team ID.
	//
	// Returns:
	//   - int: Count.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT COUNT(*) FROM organization_team_members WHERE team_id = $1;
	CountTeamMembers(ctx context.Context, teamID string) (int, error)

	// CreateRole creates a dynamic custom role within an organization.
	//
	// Function:
	//   Called when defining custom organization roles.
	//
	// Storage:
	//   Database (GORM / SQL) - Dynamic role creation.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - role: OrganizationRole entity.
	//
	// Returns:
	//   - error: ErrRoleAlreadyExists if role name is taken.
	//
	// Example SQL:
	//   INSERT INTO organization_roles (id, organization_id, role_name, permissions, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $6);
	CreateRole(ctx context.Context, role *OrganizationRole) error

	// GetRoleByID retrieves a custom dynamic role by ID.
	//
	// Function:
	//   Used in role permission evaluation.
	//
	// Storage:
	//   Database (GORM / SQL) - Dynamic role lookup by ID.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - id: Role ID.
	//
	// Returns:
	//   - *OrganizationRole: Role entity if found.
	//   - error: ErrRoleNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, organization_id, role_name, permissions, created_at, updated_at FROM organization_roles WHERE id = $1 LIMIT 1;
	GetRoleByID(ctx context.Context, id string) (*OrganizationRole, error)

	// GetRoleByName retrieves a dynamic role by name within an organization.
	//
	// Function:
	//   Used during member role permission verification.
	//
	// Storage:
	//   Database (GORM / SQL) - Dynamic role lookup by name.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//   - roleName: Role identifier string.
	//
	// Returns:
	//   - *OrganizationRole: Role entity.
	//   - error: ErrRoleNotFound if missing.
	//
	// Example SQL:
	//   SELECT id, organization_id, role_name, permissions, created_at, updated_at FROM organization_roles WHERE organization_id = $1 AND role_name = $2 LIMIT 1;
	GetRoleByName(ctx context.Context, orgID, roleName string) (*OrganizationRole, error)

	// UpdateRole updates dynamic role permissions.
	//
	// Function:
	//   Called when modifying custom role permissions.
	//
	// Storage:
	//   Database (GORM / SQL) - Dynamic role permissions update.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - role: Modified OrganizationRole entity.
	//
	// Returns:
	//   - error: Nil on success.
	//
	// Example SQL:
	//   UPDATE organization_roles SET permissions = $1, updated_at = $2 WHERE id = $3;
	UpdateRole(ctx context.Context, role *OrganizationRole) error

	// DeleteRole removes a custom dynamic role.
	//
	// Function:
	//   Called when removing custom roles.
	//
	// Storage:
	//   Database (GORM / SQL) - Dynamic role deletion.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - id: Role ID.
	//
	// Returns:
	//   - error: Nil on success.
	//
	// Example SQL:
	//   DELETE FROM organization_roles WHERE id = $1;
	DeleteRole(ctx context.Context, id string) error

	// ListRolesByOrgID lists all custom dynamic roles defined in an organization.
	//
	// Function:
	//   Used in role management UI.
	//
	// Storage:
	//   Database (GORM / SQL) - Dynamic roles list query.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//
	// Returns:
	//   - []*OrganizationRole: List of roles.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT id, organization_id, role_name, permissions, created_at, updated_at FROM organization_roles WHERE organization_id = $1;
	ListRolesByOrgID(ctx context.Context, orgID string) ([]*OrganizationRole, error)

	// CountRoles counts custom dynamic roles defined in an organization.
	//
	// Function:
	//   Used to enforce dynamic role limits.
	//
	// Storage:
	//   Database (GORM / SQL) - Dynamic roles count.
	//
	// Arguments:
	//   - ctx: Request cancellation context.
	//   - orgID: Organization ID.
	//
	// Returns:
	//   - int: Count.
	//   - error: Nil on success.
	//
	// Example SQL:
	//   SELECT COUNT(*) FROM organization_roles WHERE organization_id = $1;
	CountRoles(ctx context.Context, orgID string) (int, error)
}

Repository defines the storage contract for persisting and querying organization-related domain entities. Implement this interface on your custom database adapter (e.g. PostgreSQL, MySQL, SQLite, MongoDB, GORM).

Implementation Example (GORM / database/sql):

type GormOrganizationRepository struct {
	db *gorm.DB
}

func (r *GormOrganizationRepository) GetOrganizationByID(ctx context.Context, id string) (*organization.Organization, error) {
	var org organization.Organization
	if err := r.db.WithContext(ctx).Where("id = ?", id).First(&org).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, organization.ErrOrganizationNotFound
		}
		return nil, err
	}
	return &org, nil
}

type RoleCreateAfterEventPayload

type RoleCreateAfterEventPayload struct {
	Role *OrganizationRole
	plugin.ExtraContainer
}

type RoleCreateBeforeEventPayload

type RoleCreateBeforeEventPayload struct {
	OrganizationID string
	Role           string
	Permissions    map[string][]string
	plugin.ExtraContainer
}

type RoleDeleteAfterEventPayload

type RoleDeleteAfterEventPayload struct {
	RoleID string
	plugin.ExtraContainer
}

type RoleDeleteBeforeEventPayload

type RoleDeleteBeforeEventPayload struct {
	RoleID string
	plugin.ExtraContainer
}

type RoleUpdateAfterEventPayload

type RoleUpdateAfterEventPayload struct {
	Role *OrganizationRole
	plugin.ExtraContainer
}

type RoleUpdateBeforeEventPayload

type RoleUpdateBeforeEventPayload struct {
	RoleID      string
	Role        *string
	Permissions map[string][]string
	plugin.ExtraContainer
}

type SendInvitationEmailFunc

type SendInvitationEmailFunc func(ctx context.Context, data InvitationEmailData) error

SendInvitationEmailFunc defines a delivery callback to dispatch invitation emails via external email services (SMTP, Resend, etc.).

type SetActiveOrganizationParams

type SetActiveOrganizationParams struct {
	UserID         string `json:"user_id"`
	OrganizationID string `json:"organization_id"`
	plugin.ExtraContainer
}

type SetActiveOrganizationResult

type SetActiveOrganizationResult struct {
	Organization *Organization `json:"organization"`
	Member       *Member       `json:"member"`
}

type SetActiveTeamParams

type SetActiveTeamParams struct {
	UserID string `json:"user_id"`
	TeamID string `json:"team_id"`
	plugin.ExtraContainer
}

type SetActiveTeamResult

type SetActiveTeamResult struct {
	Team *Team `json:"team"`
}

type Team

type Team struct {
	// ID is the unique team identifier.
	ID string `json:"id"`

	// OrganizationID identifies the parent organization.
	OrganizationID string `json:"organizationId"`

	// Name is the display name of the team.
	Name string `json:"name"`

	// CreatedAt marks when the team was created.
	CreatedAt time.Time `json:"createdAt"`

	// UpdatedAt marks when the team was last updated.
	UpdatedAt *time.Time `json:"updatedAt,omitempty"`
}

Team represents a sub-unit or squad within an organization.

type TeamCreateAfterEventPayload

type TeamCreateAfterEventPayload struct {
	Team *Team
	plugin.ExtraContainer
}

type TeamCreateBeforeEventPayload

type TeamCreateBeforeEventPayload struct {
	OrganizationID string
	Name           string
	plugin.ExtraContainer
}

type TeamDeleteAfterEventPayload

type TeamDeleteAfterEventPayload struct {
	TeamID string
	plugin.ExtraContainer
}

type TeamDeleteBeforeEventPayload

type TeamDeleteBeforeEventPayload struct {
	TeamID string
	plugin.ExtraContainer
}

type TeamMember

type TeamMember struct {
	// ID is the unique identifier for the team membership record.
	ID string `json:"id"`

	// TeamID identifies the team.
	TeamID string `json:"teamId"`

	// UserID identifies the member user.
	UserID string `json:"userId"`

	// CreatedAt marks when the user joined the team.
	CreatedAt time.Time `json:"createdAt"`
}

TeamMember represents the membership relation connecting a user to a specific team.

type TeamMemberAddAfterEventPayload

type TeamMemberAddAfterEventPayload struct {
	TeamMember *TeamMember
	plugin.ExtraContainer
}

type TeamMemberAddBeforeEventPayload

type TeamMemberAddBeforeEventPayload struct {
	TeamID string
	UserID string
	plugin.ExtraContainer
}

type TeamMemberRemoveAfterEventPayload

type TeamMemberRemoveAfterEventPayload struct {
	TeamID string
	UserID string
	plugin.ExtraContainer
}

type TeamMemberRemoveBeforeEventPayload

type TeamMemberRemoveBeforeEventPayload struct {
	TeamID string
	UserID string
	plugin.ExtraContainer
}

type TeamSetActiveAfterEventPayload

type TeamSetActiveAfterEventPayload struct {
	UserID string
	TeamID string
	Team   *Team
	plugin.ExtraContainer
}

type TeamSetActiveBeforeEventPayload

type TeamSetActiveBeforeEventPayload struct {
	UserID string
	TeamID string
	plugin.ExtraContainer
}

type TeamUpdateAfterEventPayload

type TeamUpdateAfterEventPayload struct {
	Team *Team
	plugin.ExtraContainer
}

type TeamUpdateBeforeEventPayload

type TeamUpdateBeforeEventPayload struct {
	TeamID string
	Name   string
	plugin.ExtraContainer
}

type UpdateMemberRoleParams

type UpdateMemberRoleParams struct {
	OrganizationID string `json:"organization_id"`
	UserID         string `json:"user_id"`
	Role           string `json:"role"`
	InvokingUserID string `json:"invoking_user_id,omitempty"`
	plugin.ExtraContainer
}

type UpdateMemberRoleResult

type UpdateMemberRoleResult struct {
	Member *Member `json:"member"`
}

type UpdateOrganizationParams

type UpdateOrganizationParams struct {
	OrganizationID string         `json:"organization_id"`
	UserID         string         `json:"user_id,omitempty"`
	Name           *string        `json:"name,omitempty"`
	Slug           *string        `json:"slug,omitempty"`
	Metadata       map[string]any `json:"metadata,omitempty"`
	plugin.ExtraContainer
}

type UpdateOrganizationResult

type UpdateOrganizationResult struct {
	Organization *Organization `json:"organization"`
}

type UpdateRoleParams

type UpdateRoleParams struct {
	RoleID      string              `json:"role_id"`
	UserID      string              `json:"user_id,omitempty"`
	Role        *string             `json:"role,omitempty"`
	Permissions map[string][]string `json:"permissions,omitempty"`
	plugin.ExtraContainer
}

type UpdateRoleResult

type UpdateRoleResult struct {
	Role *OrganizationRole `json:"role"`
}

type UpdateTeamParams

type UpdateTeamParams struct {
	TeamID string `json:"team_id"`
	UserID string `json:"user_id,omitempty"`
	Name   string `json:"name"`
	plugin.ExtraContainer
}

type UpdateTeamResult

type UpdateTeamResult struct {
	Team *Team `json:"team"`
}

type UserInfo

type UserInfo struct {
	// ID is the unique user identifier.
	ID string `json:"id"`

	// Email is the user's primary email address.
	Email string `json:"email"`

	// Name is the user's display name.
	Name string `json:"name"`

	// Image is an optional avatar or profile image URL.
	Image string `json:"image,omitempty"`
}

UserInfo represents enriched user identity information attached to member records.

Jump to

Keyboard shortcuts

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