Documentation
¶
Index ¶
- Constants
- func AssertActorCanChangeRoles(actorRole string) error
- func AssertSoleOwnerSafe(actorUserID, targetUserID, targetRole, newRole string, ownerCount int) error
- func AssertSoleTeamOwnerSafe(targetRole, newRole string, ownerCount int) error
- func CanAccessTeam(ctx context.Context, teams TeamRepository, orgs OrganizationRepository, ...) (bool, error)
- func CanChangeTeamRoles(ctx context.Context, teams TeamRepository, orgs OrganizationRepository, ...) (bool, error)
- func CanManageTeam(ctx context.Context, teams TeamRepository, orgs OrganizationRepository, ...) (bool, error)
- func HashInviteToken(raw string) string
- func IsOrgAdmin(ctx context.Context, repo OrganizationRepository, userID, orgID string) (bool, error)
- func IsOrgAdminRole(role string) bool
- func IsOrgOwner(ctx context.Context, repo OrganizationRepository, userID, orgID string) (bool, error)
- func IsTeamManagerRole(role string) bool
- func NewInviteToken() (raw, hash string, err error)
- func NormalizeEmail(email string) string
- func NormalizeEnvironmentSlug(slug string) string
- func RemoveTeamMember(ctx context.Context, teams TeamRepository, teamID, targetUserID string) error
- func RevokeInvite(ctx context.Context, invites InviteRepository, orgID, inviteID string) error
- func ShouldDemoteActorOnOwnerTransfer(actorUserID, targetUserID, newRole string) bool
- func ValidateEnvironmentSlug(slug string) error
- func ValidateOrgRole(role string) error
- func ValidateTeamRole(role string) error
- type AcceptInviteInput
- type Environment
- type EnvironmentRepository
- type InviteOutcome
- type InvitePreview
- type InviteRepository
- type OrgInvite
- type OrgMember
- func AcceptInvite(ctx context.Context, orgs OrganizationRepository, invites InviteRepository, ...) (*OrgMember, *identity.User, error)
- func AddOrgMemberByEmail(ctx context.Context, orgs OrganizationRepository, users UserLookup, ...) (*OrgMember, error)
- func UpdateOrgMemberRole(ctx context.Context, repo OrganizationRepository, ...) (*OrgMember, error)
- type OrgRole
- type Organization
- type OrganizationRepository
- type Project
- func CreateProject(ctx context.Context, repo ProjectRepository, id, orgID, teamID, name string) (*Project, error)
- func ListVisibleProjects(ctx context.Context, projects ProjectRepository, orgs OrganizationRepository, ...) ([]Project, error)
- func NewProject(id, orgID, teamID, name string, now time.Time) (*Project, error)
- type ProjectRepository
- type Team
- type TeamMember
- type TeamRepository
- type TeamRole
- type UserCreator
- type UserLookup
Constants ¶
const ( OrgRoleOwner = "owner" OrgRoleAdmin = "admin" OrgRoleMember = "member" TeamRoleOwner = "owner" TeamRoleAdmin = "admin" TeamRoleMember = "member" )
const ( InviteStatusPending = "pending" InviteStatusAccepted = "accepted" InviteStatusRevoked = "revoked" InviteStatusExpired = "expired" )
Variables ¶
This section is empty.
Functions ¶
func AssertActorCanChangeRoles ¶
AssertActorCanChangeRoles requires the actor to be the org owner.
func AssertSoleOwnerSafe ¶
func AssertSoleOwnerSafe(actorUserID, targetUserID, targetRole, newRole string, ownerCount int) error
AssertSoleOwnerSafe blocks demoting the last owner.
func AssertSoleTeamOwnerSafe ¶
AssertSoleTeamOwnerSafe blocks demoting the last team owner.
func CanAccessTeam ¶
func CanAccessTeam(ctx context.Context, teams TeamRepository, orgs OrganizationRepository, teamID, userID string) (bool, error)
CanAccessTeam reports whether the user may view the team (org admin or team member).
func CanChangeTeamRoles ¶
func CanChangeTeamRoles(ctx context.Context, teams TeamRepository, orgs OrganizationRepository, teamID, userID string) (bool, error)
CanChangeTeamRoles reports whether the user may change team member roles (org admin or team owner — not team admin).
func CanManageTeam ¶
func CanManageTeam(ctx context.Context, teams TeamRepository, orgs OrganizationRepository, teamID, userID string) (bool, error)
CanManageTeam reports whether the user may add/remove team members (org admin, or team owner/admin).
func HashInviteToken ¶
HashInviteToken returns the hex-encoded SHA-256 of the raw token.
func IsOrgAdmin ¶
func IsOrgAdmin(ctx context.Context, repo OrganizationRepository, userID, orgID string) (bool, error)
IsOrgAdmin reports whether the user has admin privileges in the org.
func IsOrgAdminRole ¶
IsOrgAdminRole reports whether the role grants admin privileges.
func IsOrgOwner ¶
func IsOrgOwner(ctx context.Context, repo OrganizationRepository, userID, orgID string) (bool, error)
IsOrgOwner reports whether the user is the org owner.
func IsTeamManagerRole ¶
IsTeamManagerRole reports whether the team role may manage team members.
func NewInviteToken ¶
NewInviteToken generates an opaque invite token and its hash.
func NormalizeEmail ¶
NormalizeEmail trims and lowercases an email address.
func NormalizeEnvironmentSlug ¶
NormalizeEnvironmentSlug lowercases and trims a slug.
func RemoveTeamMember ¶
func RemoveTeamMember(ctx context.Context, teams TeamRepository, teamID, targetUserID string) error
RemoveTeamMember removes a user from the team. Cannot remove the sole team owner.
func RevokeInvite ¶
func RevokeInvite(ctx context.Context, invites InviteRepository, orgID, inviteID string) error
RevokeInvite marks a pending invite revoked.
func ShouldDemoteActorOnOwnerTransfer ¶
ShouldDemoteActorOnOwnerTransfer is true when promoting someone else to owner.
func ValidateEnvironmentSlug ¶
ValidateEnvironmentSlug ensures slug is lowercase alnum with -/_ and length ≤ 64.
func ValidateOrgRole ¶
ValidateOrgRole checks role is owner/admin/member.
func ValidateTeamRole ¶
ValidateTeamRole checks role is owner/admin/member.
Types ¶
type AcceptInviteInput ¶
type AcceptInviteInput struct {
Name string
PasswordHash string // bcrypt hash for new users; unused when user exists
}
AcceptInviteInput is the accept payload for new users.
type Environment ¶
type Environment struct {
ID string `json:"id"`
OrganizationID string `json:"organization_id"`
ProjectID string `json:"project_id"`
Name string `json:"name"`
Slug string `json:"slug"`
CreatedAt time.Time `json:"created_at"`
}
Environment is a named deployment stage under a project (dev/stage/prod/…).
func CreateEnvironment ¶
func CreateEnvironment(ctx context.Context, repo EnvironmentRepository, projects ProjectRepository, id, orgID, projectID, name, slug string) (*Environment, error)
CreateEnvironment validates and persists an environment under a project.
func NewEnvironment ¶
func NewEnvironment(id, orgID, projectID, name, slug string, now time.Time) (*Environment, error)
NewEnvironment builds a validated environment entity.
type EnvironmentRepository ¶
type EnvironmentRepository interface {
ListByProject(ctx context.Context, projectID string) ([]Environment, error)
Get(ctx context.Context, environmentID string) (*Environment, error)
Insert(ctx context.Context, e Environment) error
Delete(ctx context.Context, environmentID string) error
OrgID(ctx context.Context, environmentID string) (string, error)
}
EnvironmentRepository persists project environments.
type InviteOutcome ¶
type InviteOutcome struct {
Status string `json:"status"` // "added" | "invited"
Member *OrgMember `json:"member,omitempty"`
Invite *OrgInvite `json:"invite,omitempty"`
}
InviteOutcome is returned by InviteOrgMember.
func InviteOrgMember ¶
func InviteOrgMember( ctx context.Context, orgs OrganizationRepository, invites InviteRepository, users UserLookup, inviteID, orgID, email, invitedByUserID string, ) (outcome *InviteOutcome, rawToken string, err error)
InviteOrgMember adds an existing user or creates/resends a pending invite. When Status is "invited", rawToken is the plaintext accept token (shown once).
type InvitePreview ¶
type InvitePreview struct {
Email string `json:"email"`
OrganizationID string `json:"organization_id"`
OrganizationName string `json:"organization_name"`
ExpiresAt time.Time `json:"expires_at"`
UserExists bool `json:"user_exists"`
}
InvitePreview is the public view of an invite token.
func PreviewInvite ¶
func PreviewInvite(ctx context.Context, invites InviteRepository, users UserLookup, rawToken string) (*InvitePreview, error)
PreviewInvite resolves a raw token for the accept UI.
type InviteRepository ¶
type InviteRepository interface {
Get(ctx context.Context, inviteID string) (*OrgInvite, error)
GetPendingByOrgEmail(ctx context.Context, orgID, email string) (*OrgInvite, error)
GetByTokenHash(ctx context.Context, tokenHash string) (*OrgInvite, string, error) // invite, raw org name
ListByOrg(ctx context.Context, orgID string) ([]OrgInvite, error)
Insert(ctx context.Context, inv OrgInvite, tokenHash string) error
UpdateToken(ctx context.Context, inviteID, tokenHash string, expiresAt time.Time) error
MarkAccepted(ctx context.Context, inviteID string, at time.Time) error
MarkRevoked(ctx context.Context, inviteID string) error
}
InviteRepository persists organization invites.
type OrgInvite ¶
type OrgInvite struct {
ID string `json:"id"`
OrganizationID string `json:"organization_id"`
Email string `json:"email"`
Role string `json:"role"`
InvitedByUserID string `json:"invited_by_user_id"`
Status string `json:"status"`
ExpiresAt time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
AcceptedAt *time.Time `json:"accepted_at,omitempty"`
}
OrgInvite is a pending (or historical) organization membership invite.
func ResendInvite ¶
func ResendInvite(ctx context.Context, invites InviteRepository, orgID, inviteID string) (inv *OrgInvite, rawToken string, err error)
ResendInvite rotates the token for a pending invite.
type OrgMember ¶
type OrgMember struct {
UserID string `json:"user_id"`
Email string `json:"email"`
Name string `json:"name"`
Role string `json:"role"`
}
OrgMember is a user membership within an organization.
func AcceptInvite ¶
func AcceptInvite( ctx context.Context, orgs OrganizationRepository, invites InviteRepository, users UserLookup, creator UserCreator, rawToken string, in AcceptInviteInput, newUserID string, ) (*OrgMember, *identity.User, error)
AcceptInvite consumes a pending invite and ensures org membership.
func AddOrgMemberByEmail ¶
func AddOrgMemberByEmail(ctx context.Context, orgs OrganizationRepository, users UserLookup, orgID, email string) (*OrgMember, error)
AddOrgMemberByEmail invites an existing user as a member.
func UpdateOrgMemberRole ¶
func UpdateOrgMemberRole(ctx context.Context, repo OrganizationRepository, orgID, actorUserID, targetUserID, role string) (*OrgMember, error)
UpdateOrgMemberRole applies ownership/admin/member transitions with sole-owner guards.
type OrgRole ¶
type OrgRole string
OrgRole is a typed organization membership role.
func ParseOrgRole ¶
ParseOrgRole validates an organization role string.
func (OrgRole) CanChangeRoles ¶
CanChangeRoles reports whether the role may change other members' roles.
type Organization ¶
type Organization struct {
ID string `json:"id"`
Name string `json:"name"`
MailProvider string `json:"mail_provider,omitempty"`
BYOKSelectorHeader string `json:"byok_selector_header,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
Organization is a tenant root.
func CreateOrganization ¶
func CreateOrganization(ctx context.Context, repo OrganizationRepository, id, name, creatorUserID string) (*Organization, error)
CreateOrganization creates an org and assigns the creator as owner.
func NewOrganization ¶
func NewOrganization(id, name string, now time.Time) (*Organization, error)
NewOrganization builds a validated org entity.
type OrganizationRepository ¶
type OrganizationRepository interface {
Count(ctx context.Context) (int64, error)
Get(ctx context.Context, orgID string) (*Organization, error)
ListForUser(ctx context.Context, userID string) ([]Organization, error)
CreateWithOwner(ctx context.Context, org Organization, ownerUserID string) error
ListMembers(ctx context.Context, orgID string) ([]OrgMember, error)
AddMember(ctx context.Context, orgID, userID, role string) error
GetMemberRole(ctx context.Context, userID, orgID string) (string, error)
CountOwners(ctx context.Context, orgID string) (int, error)
ApplyRoleChange(ctx context.Context, orgID, actorUserID, targetUserID, newRole string, demoteActor bool) error
GetMember(ctx context.Context, orgID, userID string) (*OrgMember, error)
SetMailProvider(ctx context.Context, orgID, provider string) error
}
OrganizationRepository persists organizations and membership.
type Project ¶
type Project struct {
ID string `json:"id"`
OrganizationID string `json:"organization_id"`
TeamID string `json:"team_id,omitempty"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Project belongs to an organization (optionally a team).
func CreateProject ¶
func CreateProject(ctx context.Context, repo ProjectRepository, id, orgID, teamID, name string) (*Project, error)
CreateProject validates and persists a project.
func ListVisibleProjects ¶
func ListVisibleProjects(ctx context.Context, projects ProjectRepository, orgs OrganizationRepository, orgID, userID string) ([]Project, error)
ListVisibleProjects returns all org projects for admins, otherwise projects on the user's teams.
type ProjectRepository ¶
type ProjectRepository interface {
ListByOrg(ctx context.Context, orgID string) ([]Project, error)
ListByOrgForUser(ctx context.Context, orgID, userID string) ([]Project, error)
Insert(ctx context.Context, p Project) error
OrgID(ctx context.Context, projectID string) (string, error)
}
ProjectRepository persists projects.
type Team ¶
type Team struct {
ID string `json:"id"`
TeamID string `json:"team_id"`
OrganizationID string `json:"organization_id"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Team belongs to an organization.
func CreateTeam ¶
func CreateTeam(ctx context.Context, repo TeamRepository, id, orgID, name, creatorUserID string) (*Team, error)
CreateTeam creates a team and assigns the creator as team owner.
func ListVisibleTeams ¶
func ListVisibleTeams(ctx context.Context, teams TeamRepository, orgs OrganizationRepository, orgID, userID string) ([]Team, error)
ListVisibleTeams returns all org teams for admins, otherwise only teams the user belongs to.
type TeamMember ¶
type TeamMember struct {
UserID string `json:"user_id"`
Name string `json:"name"`
Email string `json:"email"`
Role string `json:"role"`
}
TeamMember is a user membership within a team.
func AddTeamMember ¶
func AddTeamMember(ctx context.Context, teams TeamRepository, orgs OrganizationRepository, teamID, userID string) (*TeamMember, error)
AddTeamMember adds an existing org member to the team as a member.
func UpdateTeamMemberRole ¶
func UpdateTeamMemberRole(ctx context.Context, teams TeamRepository, orgs OrganizationRepository, teamID, actorUserID, targetUserID, role string) (*TeamMember, error)
UpdateTeamMemberRole sets a team member's role. Only org admins and team owners may change roles. Cannot demote the sole team owner.
type TeamRepository ¶
type TeamRepository interface {
ListByOrg(ctx context.Context, orgID string) ([]Team, error)
ListByOrgForUser(ctx context.Context, orgID, userID string) ([]Team, error)
Get(ctx context.Context, teamID string) (*Team, error)
OrgID(ctx context.Context, teamID string) (string, error)
ListMembers(ctx context.Context, teamID string) ([]TeamMember, error)
GetMember(ctx context.Context, teamID, userID string) (*TeamMember, error)
GetMemberRole(ctx context.Context, teamID, userID string) (string, error)
AddMember(ctx context.Context, teamID, userID, role string) error
RemoveMember(ctx context.Context, teamID, userID string) error
SetMemberRole(ctx context.Context, teamID, userID, role string) error
CountOwners(ctx context.Context, teamID string) (int, error)
CreateWithOwner(ctx context.Context, team Team, ownerUserID string) error
}
TeamRepository persists teams.
type TeamRole ¶
type TeamRole string
TeamRole is a typed team membership role.
func ParseTeamRole ¶
ParseTeamRole validates a team role string.
func (TeamRole) CanChangeRoles ¶
CanChangeRoles reports whether the team role may change other members' roles. Team admins manage membership but cannot promote/demote roles.