Documentation
¶
Overview ¶
Package invite provides organization invitation management.
Index ¶
- Constants
- Variables
- type API
- type APIConfig
- type AcceptInviteInput
- type AcceptInviteRequest
- type AcceptInviteResponse
- type CreateInviteInput
- type CreateInviteRequest
- type CreateInviteResponse
- type DeclineInviteRequest
- type DeclineInviteResponse
- type DefaultService
- func (s *DefaultService) Accept(ctx context.Context, input AcceptInviteInput) (*Invite, error)
- func (s *DefaultService) Create(ctx context.Context, input CreateInviteInput) (*InviteResult, error)
- func (s *DefaultService) Decline(ctx context.Context, token string) (*Invite, error)
- func (s *DefaultService) ExpireOld(ctx context.Context) (int, error)
- func (s *DefaultService) GetByID(ctx context.Context, id uuid.UUID) (*Invite, error)
- func (s *DefaultService) GetByToken(ctx context.Context, token string) (*Invite, error)
- func (s *DefaultService) HasPendingInvite(ctx context.Context, organizationID uuid.UUID, email string) (bool, error)
- func (s *DefaultService) List(ctx context.Context, input ListInvitesInput) ([]*Invite, error)
- func (s *DefaultService) ListPendingForEmail(ctx context.Context, email string) ([]*Invite, error)
- func (s *DefaultService) PrincipalEmail(ctx context.Context, principalID uuid.UUID) (string, error)
- func (s *DefaultService) Resend(ctx context.Context, id uuid.UUID) (*InviteResult, error)
- func (s *DefaultService) Revoke(ctx context.Context, id uuid.UUID) error
- type GetInviteByTokenRequest
- type GetInviteByTokenResponse
- type Invite
- type InviteResponse
- type InviteResult
- type InviteResultResponse
- type ListInvitesInput
- type ListInvitesRequest
- type ListInvitesResponse
- type ListPendingInvitesForEmailRequest
- type ListPendingInvitesForEmailResponse
- type PrincipalEmailFunc
- type ResendInviteRequest
- type ResendInviteResponse
- type RevokeInviteRequest
- type Service
- type ServiceOption
- type Status
Constants ¶
const DefaultInviteExpiry = 7 * 24 * time.Hour // 7 days
Default invite expiration time.
Variables ¶
var ErrAppRoleRequired = errors.New("invite: choose an application role for at least one entitled application")
ErrAppRoleRequired means an admin or member invitation chose no application role although the organization is entitled to applications (ADR-007: nobody gets into an application by being a member alone, and an invitation must open at least one).
var ErrResourceInvite = errors.New("invite: invalid resource target")
ErrResourceInvite means an invitation's resource target is incomplete, is not for a collaborator, or cannot be honored by the service.
Functions ¶
This section is empty.
Types ¶
type API ¶
type API struct {
// contains filtered or unexported fields
}
API provides HTTP handlers for Invite management.
type APIConfig ¶
type APIConfig struct {
// BasePath is the base path for all endpoints (default: "/api/v1").
BasePath string
// Logger is the logger to use (default: slog.Default()).
Logger *slog.Logger
// Authorizer checks the caller's organization permissions; managing
// an organization's invites needs authz.PermOrgInviteMember. Until it
// is set, those endpoints answer 501.
Authorizer authz.Authorizer
// Caller identifies the authenticated principal (default:
// requestprincipal.PrincipalUUID, set by requestprincipal.Middleware).
Caller func(ctx context.Context) (uuid.UUID, error)
// PrincipalEmail returns the caller's email, which an invite must be
// addressed to (default: the service's PrincipalEmail, when it has
// one, as DefaultService does).
PrincipalEmail PrincipalEmailFunc
}
APIConfig configures the Invite API.
func DefaultAPIConfig ¶
func DefaultAPIConfig() APIConfig
DefaultAPIConfig returns the default API configuration.
type AcceptInviteInput ¶
type AcceptInviteInput struct {
Token string
PrincipalID uuid.UUID // The principal accepting the invite
}
AcceptInviteInput contains input for accepting an invite.
type AcceptInviteRequest ¶
type AcceptInviteRequest struct {
Token string `path:"token"`
Body struct {
PrincipalID string `` /* 169-byte string literal not displayed */
}
}
AcceptInviteRequest is the request for accepting an invite.
type AcceptInviteResponse ¶
type AcceptInviteResponse struct {
Body *InviteResponse
}
AcceptInviteResponse is the response for accepting an invite.
type CreateInviteInput ¶
type CreateInviteInput struct {
OrganizationID uuid.UUID
InviterPrincipalID uuid.UUID
Email string
Role string
// AppRoles are the application roles to grant on acceptance:
// application identifier to role. None is preselected; an inviter
// chooses each. With an approle service configured (WithAppRoles),
// an admin or member invitation to an organization entitled to any
// application must name at least one (ErrAppRoleRequired).
AppRoles map[string]string
// ResourceType, ResourceID and ResourceRole target the invite at one
// resource (ADR-008); set all three, or none. They require Role to be
// "collaborator" and the service to be built with WithResourceGrants.
// A personal organization accepts only resource-targeted invites.
ResourceType string
ResourceID string
ResourceRole string
Message *string
ExpiresIn time.Duration // How long until expiry (default: 7 days)
}
CreateInviteInput contains input for creating an invite.
type CreateInviteRequest ¶
type CreateInviteRequest struct {
Slug string `path:"slug"`
Body struct {
Email string `json:"email" required:"true" format:"email"`
Role string `json:"role" required:"true" enum:"owner,admin,member,collaborator"`
AppRoles map[string]string `` /* 126-byte string literal not displayed */
ResourceType string `` /* 179-byte string literal not displayed */
ResourceID string `json:"resource_id,omitempty" doc:"The application's identifier of the resource"`
ResourceRole string `json:"resource_role,omitempty" enum:"viewer,contributor,maintainer" doc:"The resource role granted on acceptance"`
Message *string `json:"message,omitempty"`
InviterPrincipalID string `` /* 165-byte string literal not displayed */
ExpiresInHours int `json:"expires_in_hours,omitempty" minimum:"1" maximum:"720"`
}
}
CreateInviteRequest is the request for creating an invite.
type CreateInviteResponse ¶
type CreateInviteResponse struct {
Body *InviteResultResponse
}
CreateInviteResponse is the response for creating an invite.
type DeclineInviteRequest ¶
type DeclineInviteRequest struct {
Token string `path:"token"`
}
DeclineInviteRequest is the request for declining an invite.
type DeclineInviteResponse ¶
type DeclineInviteResponse struct {
Body *InviteResponse
}
DeclineInviteResponse is the response for declining an invite.
type DefaultService ¶
type DefaultService struct {
// contains filtered or unexported fields
}
DefaultService implements the Service interface.
func (*DefaultService) Accept ¶
func (s *DefaultService) Accept(ctx context.Context, input AcceptInviteInput) (*Invite, error)
Accept accepts an invite and creates the membership.
func (*DefaultService) Create ¶
func (s *DefaultService) Create(ctx context.Context, input CreateInviteInput) (*InviteResult, error)
Create creates a new invite.
func (*DefaultService) ExpireOld ¶
func (s *DefaultService) ExpireOld(ctx context.Context) (int, error)
ExpireOld expires invites that have passed their expiration time.
func (*DefaultService) GetByToken ¶
GetByToken retrieves an invite by its token.
func (*DefaultService) HasPendingInvite ¶
func (s *DefaultService) HasPendingInvite(ctx context.Context, organizationID uuid.UUID, email string) (bool, error)
HasPendingInvite checks if there's already a pending invite for this email/org.
func (*DefaultService) List ¶
func (s *DefaultService) List(ctx context.Context, input ListInvitesInput) ([]*Invite, error)
List lists invites with optional filters.
func (*DefaultService) ListPendingForEmail ¶
ListPendingForEmail lists pending invites for an email address.
func (*DefaultService) PrincipalEmail ¶ added in v0.14.0
PrincipalEmail returns a principal's email from the identity database, or "" when it has none. It is the API's default PrincipalEmailFunc.
func (*DefaultService) Resend ¶
func (s *DefaultService) Resend(ctx context.Context, id uuid.UUID) (*InviteResult, error)
Resend resends an invite with a new token.
type GetInviteByTokenRequest ¶
type GetInviteByTokenRequest struct {
Token string `path:"token"`
}
GetInviteByTokenRequest is the request for getting an invite by token.
type GetInviteByTokenResponse ¶
type GetInviteByTokenResponse struct {
Body *InviteResponse
}
GetInviteByTokenResponse is the response for getting an invite.
type Invite ¶
type Invite struct {
ID uuid.UUID
OrganizationID uuid.UUID
InviterPrincipalID uuid.UUID
Email string
Role string
// AppRoles are the application roles granted when the invite is
// accepted: application identifier to role. Empty means none.
AppRoles map[string]string
// ResourceType, ResourceID and ResourceRole, all set or all empty,
// target the invite at one resource (ADR-008): accepting it makes the
// invitee a collaborator of the organization and grants ResourceRole on
// the resource in one transaction. Role is then "collaborator".
ResourceType string
ResourceID string
ResourceRole string
Status Status
Message *string
ExpiresAt time.Time
AcceptedAt *time.Time
AcceptedByPrincipalID *uuid.UUID
ResendCount int
LastSentAt time.Time
CreatedAt time.Time
UpdatedAt time.Time
}
Invite represents an invitation to join an organization.
type InviteResponse ¶
type InviteResponse struct {
ID string `json:"id"`
OrganizationID string `json:"organization_id"`
InviterPrincipalID string `json:"inviter_principal_id"`
Email string `json:"email"`
Role string `json:"role"`
AppRoles map[string]string `json:"app_roles,omitempty"`
ResourceType string `json:"resource_type,omitempty"`
ResourceID string `json:"resource_id,omitempty"`
ResourceRole string `json:"resource_role,omitempty"`
Status string `json:"status"`
Message *string `json:"message,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
AcceptedAt *time.Time `json:"accepted_at,omitempty"`
AcceptedByPrincipalID *string `json:"accepted_by_principal_id,omitempty"`
ResendCount int `json:"resend_count"`
LastSentAt time.Time `json:"last_sent_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
InviteResponse is the API representation of an invite.
type InviteResult ¶
type InviteResult struct {
Invite *Invite
// InviteURL is the full URL to accept the invite
InviteURL string
}
InviteResult contains the result of invite operations.
type InviteResultResponse ¶
type InviteResultResponse struct {
Invite *InviteResponse `json:"invite"`
InviteURL string `json:"invite_url"`
}
InviteResultResponse includes the invite URL.
type ListInvitesInput ¶
type ListInvitesInput struct {
OrganizationID *uuid.UUID
Email *string
Status *Status
Limit int
Offset int
}
ListInvitesInput contains filters for listing invites.
type ListInvitesRequest ¶
type ListInvitesRequest struct {
Slug string `path:"slug"`
// Huma does not support pointer parameters; empty lists every status.
Status string `query:"status" enum:"pending,accepted,declined,expired,revoked"`
Limit int `query:"limit" default:"20" minimum:"1" maximum:"100"`
Offset int `query:"offset" default:"0" minimum:"0"`
}
ListInvitesRequest is the request for listing invites.
type ListInvitesResponse ¶
type ListInvitesResponse struct {
Body struct {
Invites []*InviteResponse `json:"invites"`
}
}
ListInvitesResponse is the response for listing invites.
type ListPendingInvitesForEmailRequest ¶
type ListPendingInvitesForEmailRequest struct {
// Email is deprecated: the invites listed are the caller's. When
// present it must be the caller's email.
Email string `` /* 130-byte string literal not displayed */
}
ListPendingInvitesForEmailRequest is the request for listing pending invites by email.
type ListPendingInvitesForEmailResponse ¶
type ListPendingInvitesForEmailResponse struct {
Body struct {
Invites []*InviteResponse `json:"invites"`
}
}
ListPendingInvitesForEmailResponse is the response for listing pending invites.
type PrincipalEmailFunc ¶ added in v0.14.0
PrincipalEmailFunc returns a principal's email, or "" when it has none (a managed principal).
type ResendInviteRequest ¶
type ResendInviteRequest struct {
Slug string `path:"slug"`
InviteID string `path:"invite_id" format:"uuid"`
}
ResendInviteRequest is the request for resending an invite.
type ResendInviteResponse ¶
type ResendInviteResponse struct {
Body *InviteResultResponse
}
ResendInviteResponse is the response for resending an invite.
type RevokeInviteRequest ¶
type RevokeInviteRequest struct {
Slug string `path:"slug"`
InviteID string `path:"invite_id" format:"uuid"`
}
RevokeInviteRequest is the request for revoking an invite.
type Service ¶
type Service interface {
// Create creates a new invite.
Create(ctx context.Context, input CreateInviteInput) (*InviteResult, error)
// GetByToken retrieves an invite by its token.
GetByToken(ctx context.Context, token string) (*Invite, error)
// GetByID retrieves an invite by ID.
GetByID(ctx context.Context, id uuid.UUID) (*Invite, error)
// Accept accepts an invite and creates the membership.
Accept(ctx context.Context, input AcceptInviteInput) (*Invite, error)
// Decline declines an invite.
Decline(ctx context.Context, token string) (*Invite, error)
// Revoke revokes an invite.
Revoke(ctx context.Context, id uuid.UUID) error
// Resend resends an invite with a new token.
Resend(ctx context.Context, id uuid.UUID) (*InviteResult, error)
// List lists invites with optional filters.
List(ctx context.Context, input ListInvitesInput) ([]*Invite, error)
// ListPendingForEmail lists pending invites for an email address.
ListPendingForEmail(ctx context.Context, email string) ([]*Invite, error)
// ExpireOld expires invites that have passed their expiration time.
ExpireOld(ctx context.Context) (int, error)
// HasPendingInvite checks if there's already a pending invite for this email/org.
HasPendingInvite(ctx context.Context, organizationID uuid.UUID, email string) (bool, error)
}
Service defines the invite service interface.
func NewService ¶
func NewService(client *ent.Client, baseURL string, opts ...ServiceOption) Service
NewService creates a new invite service.
type ServiceOption ¶ added in v0.14.0
type ServiceOption func(*DefaultService)
ServiceOption configures a DefaultService.
func WithAppRoles ¶ added in v0.14.0
func WithAppRoles(svc *approle.Service) ServiceOption
WithAppRoles lets invitations carry application roles: Create validates them and Accept grants them in the same transaction as the membership. Without it, an invitation's AppRoles are rejected.
func WithAuthzSyncer ¶ added in v0.14.0
func WithAuthzSyncer(syncer authz.RelationshipSyncer) ServiceOption
WithAuthzSyncer sets the authorization syncer used to register accepted memberships in the authorization graph.
func WithLogger ¶ added in v0.14.0
func WithLogger(logger *slog.Logger) ServiceOption
WithLogger sets the logger for the service.
func WithResourceGrants ¶ added in v0.14.0
func WithResourceGrants(svc *resourcegrant.Service) ServiceOption
WithResourceGrants lets invitations target a resource (ADR-008): Create validates the target against the grant service's rules and Accept creates the collaborator membership and the grant in one transaction, through the service's GrantInTx. Without it, a resource target is refused. Memberships are written to the authorization graph through this service's own syncer, grants through the grant service's.
func WithSyncMode ¶ added in v0.14.0
func WithSyncMode(mode authz.SyncMode) ServiceOption
WithSyncMode sets the sync mode (strict or eventual).