organization

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Mar 8, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package organization provides organization management services.

Index

Constants

View Source
const (
	RoleOwner  = "owner"
	RoleAdmin  = "admin"
	RoleMember = "member"
)

MembershipRole constants for common roles.

Variables

This section is empty.

Functions

This section is empty.

Types

type API

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

API provides HTTP handlers for Organization management.

func NewAPI

func NewAPI(service Service, config APIConfig) *API

NewAPI creates a new Organization API.

func (*API) Router

func (a *API) Router() chi.Router

Router returns the Chi router.

func (*API) ServeHTTP

func (a *API) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler.

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
}

APIConfig configures the Organization API.

func DefaultAPIConfig

func DefaultAPIConfig() APIConfig

DefaultAPIConfig returns the default API configuration.

type AddMemberInput

type AddMemberInput struct {
	OrganizationID uuid.UUID
	PrincipalID    uuid.UUID
	Role           string
	Permissions    []string
}

AddMemberInput contains input for adding a member to an organization.

type AddMemberRequest

type AddMemberRequest struct {
	Slug string `path:"slug"`
	Body struct {
		PrincipalID string   `json:"principal_id" required:"true" format:"uuid"`
		Role        string   `json:"role" required:"true" enum:"owner,admin,member"`
		Permissions []string `json:"permissions,omitempty"`
	}
}

AddMemberRequest is the request for adding a member.

type AddMemberResponse

type AddMemberResponse struct {
	Body *MemberResponse
}

AddMemberResponse is the response for adding a member.

type CheckSlugInput

type CheckSlugInput struct {
	Slug string `path:"slug"`
}

CheckSlugInput is the request for checking slug availability.

type CheckSlugOutput

type CheckSlugOutput struct {
	Body struct {
		Available bool   `json:"available"`
		Slug      string `json:"slug"`
	}
}

CheckSlugOutput is the response for checking slug availability.

type CreateOrgInput

type CreateOrgInput struct {
	Body struct {
		Name        string         `json:"name" required:"true" minLength:"1" maxLength:"100"`
		Slug        string         `json:"slug" required:"true" minLength:"3" maxLength:"63" pattern:"^[a-z][a-z0-9-]*[a-z0-9]$"`
		OrgType     string         `json:"org_type,omitempty" enum:"personal,team,enterprise" default:"team"`
		LogoURL     *string        `json:"logo_url,omitempty"`
		Description *string        `json:"description,omitempty"`
		WebsiteURL  *string        `json:"website_url,omitempty"`
		Plan        string         `json:"plan,omitempty" enum:"free,starter,pro,enterprise" default:"free"`
		Settings    map[string]any `json:"settings,omitempty"`
	}
}

CreateOrgInput is the request body for creating an organization.

type CreateOrgOutput

type CreateOrgOutput struct {
	Body *OrgResponse
}

CreateOrgOutput is the response for creating an organization.

type CreateOrganizationInput

type CreateOrganizationInput struct {
	Name             string
	Slug             string
	OrgType          OrgType
	OwnerPrincipalID *uuid.UUID // Required for personal orgs
	LogoURL          *string
	Description      *string
	WebsiteURL       *string
	Settings         map[string]any
	Plan             Plan
}

CreateOrganizationInput contains input for creating an organization.

type CreatePersonalOrgInput

type CreatePersonalOrgInput struct {
	OwnerPrincipalID uuid.UUID
	Name             string  // Display name (usually user's name)
	Slug             string  // URL-safe username
	LogoURL          *string // Optional avatar
}

CreatePersonalOrgInput contains input for creating a personal organization.

type DefaultService

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

DefaultService implements the Service interface.

func (*DefaultService) AddMember

func (s *DefaultService) AddMember(ctx context.Context, input AddMemberInput) (*Membership, error)

AddMember adds a principal as a member of an organization.

func (*DefaultService) Create

Create creates a new organization.

func (*DefaultService) CreatePersonalOrg

func (s *DefaultService) CreatePersonalOrg(ctx context.Context, input CreatePersonalOrgInput) (*Organization, error)

CreatePersonalOrg creates a personal organization for a user.

func (*DefaultService) Delete

func (s *DefaultService) Delete(ctx context.Context, id uuid.UUID) error

Delete soft-deletes an organization.

func (*DefaultService) GenerateSlug

func (s *DefaultService) GenerateSlug(ctx context.Context, name string) (string, error)

GenerateSlug generates a unique slug from a name.

func (*DefaultService) GetByID

func (s *DefaultService) GetByID(ctx context.Context, id uuid.UUID) (*Organization, error)

GetByID retrieves an organization by ID.

func (*DefaultService) GetBySlug

func (s *DefaultService) GetBySlug(ctx context.Context, slug string) (*Organization, error)

GetBySlug retrieves an organization by slug.

func (*DefaultService) GetMembership

func (s *DefaultService) GetMembership(ctx context.Context, organizationID, principalID uuid.UUID) (*Membership, error)

GetMembership retrieves a specific membership.

func (*DefaultService) GetPersonalOrg

func (s *DefaultService) GetPersonalOrg(ctx context.Context, principalID uuid.UUID) (*Organization, error)

GetPersonalOrg retrieves a principal's personal organization.

func (*DefaultService) List

List lists organizations with optional filters.

func (*DefaultService) ListMembers

func (s *DefaultService) ListMembers(ctx context.Context, organizationID uuid.UUID) ([]*Membership, error)

ListMembers lists all members of an organization.

func (*DefaultService) ListMemberships

func (s *DefaultService) ListMemberships(ctx context.Context, principalID uuid.UUID) ([]*Membership, error)

ListMemberships lists all organizations a principal belongs to.

func (*DefaultService) RemoveMember

func (s *DefaultService) RemoveMember(ctx context.Context, organizationID, principalID uuid.UUID) error

RemoveMember removes a principal from an organization.

func (*DefaultService) SlugAvailable

func (s *DefaultService) SlugAvailable(ctx context.Context, slug string) (bool, error)

SlugAvailable checks if a slug is available.

func (*DefaultService) Update

Update updates an organization.

func (*DefaultService) UpdateMember

func (s *DefaultService) UpdateMember(ctx context.Context, membershipID uuid.UUID, input UpdateMemberInput) (*Membership, error)

UpdateMember updates a membership.

type DeleteOrgInput

type DeleteOrgInput struct {
	Slug string `path:"slug"`
}

DeleteOrgInput is the request for deleting an organization.

type GetMemberInput

type GetMemberInput struct {
	Slug        string `path:"slug"`
	PrincipalID string `path:"principal_id" format:"uuid"`
}

GetMemberInput is the request for getting a specific member.

type GetMemberOutput

type GetMemberOutput struct {
	Body *MemberResponse
}

GetMemberOutput is the response for getting a member.

type GetOrgInput

type GetOrgInput struct {
	Slug string `path:"slug"`
}

GetOrgInput is the request for getting an organization.

type GetOrgOutput

type GetOrgOutput struct {
	Body *OrgResponse
}

GetOrgOutput is the response for getting an organization.

type ListMembersInput

type ListMembersInput struct {
	Slug string `path:"slug"`
}

ListMembersInput is the request for listing members.

type ListMembersOutput

type ListMembersOutput struct {
	Body struct {
		Members []*MemberResponse `json:"members"`
	}
}

ListMembersOutput is the response for listing members.

type ListOrganizationsInput

type ListOrganizationsInput struct {
	OrgType *OrgType
	Plan    *Plan
	Active  *bool
	Limit   int
	Offset  int
}

ListOrganizationsInput contains filters for listing organizations.

type ListOrgsInput

type ListOrgsInput struct {
	OrgType *string `query:"org_type" enum:"personal,team,enterprise"`
	Plan    *string `query:"plan" enum:"free,starter,pro,enterprise"`
	Active  *bool   `query:"active"`
	Limit   int     `query:"limit" default:"20" minimum:"1" maximum:"100"`
	Offset  int     `query:"offset" default:"0" minimum:"0"`
}

ListOrgsInput is the request for listing organizations.

type ListOrgsOutput

type ListOrgsOutput struct {
	Body struct {
		Organizations []*OrgResponse `json:"organizations"`
		Total         int            `json:"total"`
	}
}

ListOrgsOutput is the response for listing organizations.

type MemberResponse

type MemberResponse struct {
	ID             string    `json:"id"`
	PrincipalID    string    `json:"principal_id"`
	OrganizationID string    `json:"organization_id"`
	Role           string    `json:"role"`
	Permissions    []string  `json:"permissions,omitempty"`
	Active         bool      `json:"active"`
	CreatedAt      time.Time `json:"created_at"`
	UpdatedAt      time.Time `json:"updated_at"`
}

MemberResponse is the API representation of a membership.

type Membership

type Membership struct {
	ID             uuid.UUID
	PrincipalID    uuid.UUID
	OrganizationID uuid.UUID
	Role           string
	Permissions    []string
	Active         bool
	CreatedAt      time.Time
	UpdatedAt      time.Time
}

Membership represents a principal's membership in an organization.

type OrgResponse

type OrgResponse struct {
	ID               string         `json:"id"`
	Name             string         `json:"name"`
	Slug             string         `json:"slug"`
	OrgType          string         `json:"org_type"`
	OwnerPrincipalID *string        `json:"owner_principal_id,omitempty"`
	LogoURL          *string        `json:"logo_url,omitempty"`
	Description      *string        `json:"description,omitempty"`
	WebsiteURL       *string        `json:"website_url,omitempty"`
	Plan             string         `json:"plan"`
	Active           bool           `json:"active"`
	Settings         map[string]any `json:"settings,omitempty"`
	CreatedAt        time.Time      `json:"created_at"`
	UpdatedAt        time.Time      `json:"updated_at"`
}

OrgResponse is the API representation of an organization.

type OrgType

type OrgType string

OrgType represents the type of organization.

const (
	OrgTypePersonal   OrgType = "personal"   // Personal namespace for a user
	OrgTypeTeam       OrgType = "team"       // Shared team organization
	OrgTypeEnterprise OrgType = "enterprise" // Enterprise organization
)

type Organization

type Organization struct {
	ID               uuid.UUID
	Name             string
	Slug             string
	OrgType          OrgType
	OwnerPrincipalID *uuid.UUID // For personal orgs
	LogoURL          *string
	Description      *string
	WebsiteURL       *string
	Settings         map[string]any
	Plan             Plan
	Active           bool
	CreatedAt        time.Time
	UpdatedAt        time.Time
}

Organization represents an organization in the system.

func (*Organization) IsPersonal

func (o *Organization) IsPersonal() bool

IsPersonal returns true if this is a personal organization.

type Plan

type Plan string

Plan represents the organization's subscription plan.

const (
	PlanFree       Plan = "free"
	PlanStarter    Plan = "starter"
	PlanPro        Plan = "pro"
	PlanEnterprise Plan = "enterprise"
)

type RemoveMemberInput

type RemoveMemberInput struct {
	Slug        string `path:"slug"`
	PrincipalID string `path:"principal_id" format:"uuid"`
}

RemoveMemberInput is the request for removing a member.

type Service

type Service interface {
	// Create creates a new organization.
	Create(ctx context.Context, input CreateOrganizationInput) (*Organization, error)

	// CreatePersonalOrg creates a personal organization for a user.
	CreatePersonalOrg(ctx context.Context, input CreatePersonalOrgInput) (*Organization, error)

	// GetByID retrieves an organization by ID.
	GetByID(ctx context.Context, id uuid.UUID) (*Organization, error)

	// GetBySlug retrieves an organization by slug.
	GetBySlug(ctx context.Context, slug string) (*Organization, error)

	// GetPersonalOrg retrieves a principal's personal organization.
	GetPersonalOrg(ctx context.Context, principalID uuid.UUID) (*Organization, error)

	// Update updates an organization.
	Update(ctx context.Context, id uuid.UUID, input UpdateOrganizationInput) (*Organization, error)

	// Delete soft-deletes an organization.
	Delete(ctx context.Context, id uuid.UUID) error

	// List lists organizations with optional filters.
	List(ctx context.Context, input ListOrganizationsInput) ([]*Organization, error)

	// AddMember adds a principal as a member of an organization.
	AddMember(ctx context.Context, input AddMemberInput) (*Membership, error)

	// UpdateMember updates a membership.
	UpdateMember(ctx context.Context, membershipID uuid.UUID, input UpdateMemberInput) (*Membership, error)

	// RemoveMember removes a principal from an organization.
	RemoveMember(ctx context.Context, organizationID, principalID uuid.UUID) error

	// GetMembership retrieves a specific membership.
	GetMembership(ctx context.Context, organizationID, principalID uuid.UUID) (*Membership, error)

	// ListMembers lists all members of an organization.
	ListMembers(ctx context.Context, organizationID uuid.UUID) ([]*Membership, error)

	// ListMemberships lists all organizations a principal belongs to.
	ListMemberships(ctx context.Context, principalID uuid.UUID) ([]*Membership, error)

	// SlugAvailable checks if a slug is available.
	SlugAvailable(ctx context.Context, slug string) (bool, error)

	// GenerateSlug generates a unique slug from a name.
	GenerateSlug(ctx context.Context, name string) (string, error)
}

Service defines the organization service interface.

func NewService

func NewService(client *ent.Client, opts ...ServiceOption) Service

NewService creates a new organization service.

type ServiceOption

type ServiceOption func(*DefaultService)

ServiceOption configures a DefaultService.

func WithAuthzSyncer

func WithAuthzSyncer(syncer authz.RelationshipSyncer) ServiceOption

WithAuthzSyncer sets the authorization syncer for keeping authz in sync with identity changes.

func WithLogger

func WithLogger(logger *slog.Logger) ServiceOption

WithLogger sets the logger for the service.

func WithSyncMode

func WithSyncMode(mode authz.SyncMode) ServiceOption

WithSyncMode sets the sync mode (strict or eventual).

type UpdateMemberInput

type UpdateMemberInput struct {
	Role        *string
	Permissions []string
	Active      *bool
}

UpdateMemberInput contains input for updating a membership.

type UpdateMemberRequest

type UpdateMemberRequest struct {
	Slug        string `path:"slug"`
	PrincipalID string `path:"principal_id" format:"uuid"`
	Body        struct {
		Role        *string  `json:"role,omitempty" enum:"owner,admin,member"`
		Permissions []string `json:"permissions,omitempty"`
		Active      *bool    `json:"active,omitempty"`
	}
}

UpdateMemberRequest is the request for updating a member.

type UpdateMemberResponse

type UpdateMemberResponse struct {
	Body *MemberResponse
}

UpdateMemberResponse is the response for updating a member.

type UpdateOrgInput

type UpdateOrgInput struct {
	Slug string `path:"slug"`
	Body struct {
		Name        *string        `json:"name,omitempty" maxLength:"100"`
		LogoURL     *string        `json:"logo_url,omitempty"`
		Description *string        `json:"description,omitempty"`
		WebsiteURL  *string        `json:"website_url,omitempty"`
		Plan        *string        `json:"plan,omitempty" enum:"free,starter,pro,enterprise"`
		Settings    map[string]any `json:"settings,omitempty"`
	}
}

UpdateOrgInput is the request for updating an organization.

type UpdateOrgOutput

type UpdateOrgOutput struct {
	Body *OrgResponse
}

UpdateOrgOutput is the response for updating an organization.

type UpdateOrganizationInput

type UpdateOrganizationInput struct {
	Name        *string
	LogoURL     *string
	Description *string
	WebsiteURL  *string
	Settings    map[string]any
	Plan        *Plan
}

UpdateOrganizationInput contains input for updating an organization.

Jump to

Keyboard shortcuts

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