rbac

package
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Nov 24, 2025 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Index

Constants

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

Role name constants These define the standard role names used across the platform

View Source
const (
	RolePrioritySuperAdmin = 100
	RolePriorityOwner      = 80
	RolePriorityAdmin      = 60
	RolePriorityMember     = 40
)

Role priority constants Higher priority roles override lower priority roles in the hierarchy

View Source
const (
	RoleDescSuperAdmin = "System Superadministrator (Platform Owner)"
	RoleDescOwner      = "Organization Owner"
	RoleDescAdmin      = "Organization Administrator"
	RoleDescMember     = "Regular User"
)

Role description constants

View Source
const (
	RoleIsPlatformSuperAdmin = true
	RoleIsPlatformOwner      = false
	RoleIsPlatformAdmin      = false
	RoleIsPlatformMember     = false
)

Role platform flag constants Platform roles can only be assigned in the platform organization

Variables

This section is empty.

Functions

func BuildPermissionName

func BuildPermissionName(action PermissionAction, resource PermissionResource) string

BuildPermissionName constructs a permission name from action and resource Example: BuildPermissionName(ActionView, ResourceUsers) => "view on users"

func ParsePermissionName

func ParsePermissionName(name string) (action PermissionAction, resource PermissionResource)

ParsePermissionName parses a permission name into action and resource Returns empty strings if the format is invalid

func RegisterDefaultPlatformRoles

func RegisterDefaultPlatformRoles(registry *RoleRegistry) error

RegisterDefaultPlatformRoles registers the default platform-wide roles This is called during AuthSome initialization before plugins register their roles Plugins can then extend or override these default roles

Types

type ConditionEvaluator

type ConditionEvaluator func(condition string, ctx *Context) bool

ConditionEvaluator evaluates a condition string against a Context. Returning true means the condition passes.

type Context

type Context struct {
	Subject  string            `json:"subject"`  // e.g. "user", "role:admin"
	Action   string            `json:"action"`   // e.g. "read"
	Resource string            `json:"resource"` // e.g. "project:123"
	Vars     map[string]string `json:"vars"`     // context variables used by conditions
}

Context captures what we're trying to authorize

type Evaluator

type Evaluator struct {
	EvaluateCondition ConditionEvaluator
}

Evaluator checks if a policy allows the given context.

func NewEvaluator

func NewEvaluator() *Evaluator

func (*Evaluator) Evaluate

func (e *Evaluator) Evaluate(policy *Policy, ctx *Context) bool

Evaluate returns true if the policy allows the action on the resource for the subject.

type Parser

type Parser struct{}

Parser parses RBAC policy expressions. Supported syntax:

"subject:action1,action2 on resource[:*] [where key = value]"

Examples:

"user:read on organization:123"
"project:* on organization:*"           // actions omitted -> invalid
"invoice:read,write on organization:* where role = admin"
"user:create,read,update,delete on *"

func NewParser

func NewParser() *Parser

func (*Parser) Parse

func (p *Parser) Parse(expression string) (*Policy, error)

Parse converts a policy expression string into a Policy struct.

type Permission

type Permission struct {
	ID             xid.ID  `json:"id"`
	OrganizationID *xid.ID `json:"organizationId"`
	Name           string  `json:"name"`
	Description    string  `json:"description"`
}

Permission represents a named permission; policies can reference or embed permissions

type PermissionAction

type PermissionAction string

PermissionAction represents common permission actions

const (
	// CRUD actions
	ActionView   PermissionAction = "view"
	ActionCreate PermissionAction = "create"
	ActionEdit   PermissionAction = "edit"
	ActionUpdate PermissionAction = "update"
	ActionDelete PermissionAction = "delete"

	// Management actions
	ActionManage  PermissionAction = "manage"  // Full control
	ActionList    PermissionAction = "list"    // List/index
	ActionRead    PermissionAction = "read"    // Read-only
	ActionWrite   PermissionAction = "write"   // Write access
	ActionExecute PermissionAction = "execute" // Execute/run

	// Special actions
	ActionAll PermissionAction = "*" // Wildcard - all actions
)

func (PermissionAction) String

func (a PermissionAction) String() string

String returns the string representation of the action

type PermissionCategory

type PermissionCategory string

PermissionCategory groups permissions by functional area

const (
	// Pre-defined permission categories
	CategoryUsers         PermissionCategory = "users"
	CategorySettings      PermissionCategory = "settings"
	CategoryContent       PermissionCategory = "content"
	CategoryOrganizations PermissionCategory = "organizations"
	CategorySessions      PermissionCategory = "sessions"
	CategoryAPIKeys       PermissionCategory = "apikeys"
	CategoryAuditLogs     PermissionCategory = "audit_logs"
	CategoryRoles         PermissionCategory = "roles"
	CategoryPermissions   PermissionCategory = "permissions"
	CategoryDashboard     PermissionCategory = "dashboard"
	CategoryCustom        PermissionCategory = "custom"
)

func (PermissionCategory) IsValid

func (c PermissionCategory) IsValid() bool

IsValid checks if the category is a valid pre-defined category

func (PermissionCategory) String

func (c PermissionCategory) String() string

String returns the string representation of the category

type PermissionRepository

type PermissionRepository interface {
	Create(ctx context.Context, permission *schema.Permission) error
	Update(ctx context.Context, permission *schema.Permission) error
	Delete(ctx context.Context, permissionID xid.ID) error
	FindByID(ctx context.Context, permissionID xid.ID) (*schema.Permission, error)
	FindByName(ctx context.Context, name string, appID xid.ID, orgID *xid.ID) (*schema.Permission, error)
	ListByApp(ctx context.Context, appID xid.ID) ([]*schema.Permission, error)
	ListByOrg(ctx context.Context, orgID xid.ID) ([]*schema.Permission, error)
	ListByCategory(ctx context.Context, category string, appID xid.ID) ([]*schema.Permission, error)

	// Custom permissions
	CreateCustomPermission(ctx context.Context, name, description, category string, orgID xid.ID) (*schema.Permission, error)
}

PermissionRepository handles permission operations for RBAC

type PermissionResource

type PermissionResource string

PermissionResource represents common permission resources

const (
	// Core resources
	ResourceUsers         PermissionResource = "users"
	ResourceSessions      PermissionResource = "sessions"
	ResourceOrganizations PermissionResource = "organizations"
	ResourceRoles         PermissionResource = "roles"
	ResourcePermissions   PermissionResource = "permissions"
	ResourceAPIKeys       PermissionResource = "apikeys"
	ResourceSettings      PermissionResource = "settings"
	ResourceAuditLogs     PermissionResource = "audit_logs"
	ResourceDashboard     PermissionResource = "dashboard"
	ResourceProfile       PermissionResource = "profile"

	// Wildcard
	ResourceAll PermissionResource = "*"
)

func (PermissionResource) String

func (r PermissionResource) String() string

String returns the string representation of the resource

type Policy

type Policy struct {
	Subject   string   `json:"subject"`   // e.g. "user", "role:admin"
	Actions   []string `json:"actions"`   // e.g. ["read", "write"]
	Resource  string   `json:"resource"`  // e.g. "project:*"
	Condition string   `json:"condition"` // optional condition, e.g. "owner = true"
}

Policy represents a single RBAC rule parsed from an expression Example: "user:read,write on project:* where owner = true"

type PolicyRepository

type PolicyRepository interface {
	// ListAll returns all stored policy expressions
	ListAll(ctx context.Context) ([]string, error)
	// Create stores a new policy expression
	Create(ctx context.Context, expression string) error
}

PolicyRepository provides access to stored policy expressions

type Role

type Role struct {
	ID             xid.ID  `json:"id"`
	OrganizationID *xid.ID `json:"organizationId"`
	Name           string  `json:"name"`
	Description    string  `json:"description"`
}

Role represents a named role, optionally scoped to an organization

type RoleCustomization

type RoleCustomization struct {
	Name               *string  `json:"name,omitempty"`               // Override template name
	Description        *string  `json:"description,omitempty"`        // Override template description
	PermissionIDs      []xid.ID `json:"permissionIDs,omitempty"`      // Specific permissions to clone (if empty, clone all)
	ExcludePermissions []xid.ID `json:"excludePermissions,omitempty"` // Permissions to exclude from template
}

RoleCustomization contains customization options when cloning a role template

type RoleDefinition

type RoleDefinition struct {
	Name         string   // Role name (e.g., "superadmin", "owner", "admin", "member")
	Description  string   // Human-readable description
	Permissions  []string // Permission expressions: "action on resource" or "* on *"
	IsPlatform   bool     // Platform-level role (superadmin) vs org-level (owner, admin, member)
	InheritsFrom string   // Parent role to inherit permissions from (for role hierarchy)
	Priority     int      // Higher priority roles override lower priority (superadmin=100, owner=80, admin=60, member=40)
}

RoleDefinition declares a role and its permissions Plugins register these during Init() to contribute to the platform RBAC system

type RolePermissionRepository

type RolePermissionRepository interface {
	AssignPermission(ctx context.Context, roleID, permissionID xid.ID) error
	UnassignPermission(ctx context.Context, roleID, permissionID xid.ID) error
	GetRolePermissions(ctx context.Context, roleID xid.ID) ([]*schema.Permission, error)
	GetPermissionRoles(ctx context.Context, permissionID xid.ID) ([]*schema.Role, error)
	ReplaceRolePermissions(ctx context.Context, roleID xid.ID, permissionIDs []xid.ID) error
}

RolePermissionRepository handles role-permission relationships

type RoleRegistry

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

RoleRegistry collects role definitions from core and plugins Supports: - Override semantics (later registrations override earlier ones) - Role inheritance (roles inherit from parent roles) - Cross-plugin modification (plugins can extend other plugins' roles)

func NewRoleRegistry

func NewRoleRegistry() *RoleRegistry

NewRoleRegistry creates a new role registry

func (*RoleRegistry) Bootstrap

func (r *RoleRegistry) Bootstrap(ctx context.Context, db *bun.DB, rbacService *Service, platformOrgID xid.ID) error

Bootstrap applies all registered roles to the platform organization Called once during server startup AFTER: - Database migrations have run - Plugins have initialized and registered their roles

This creates/updates: 1. Role records in the database 2. Permission records in the database 3. RBAC policy expressions in the policy engine

func (*RoleRegistry) GetRole

func (r *RoleRegistry) GetRole(name string) (*RoleDefinition, bool)

GetRole retrieves a role definition by name

func (*RoleRegistry) GetRoleHierarchy

func (r *RoleRegistry) GetRoleHierarchy() []*RoleDefinition

GetRoleHierarchy returns roles in descending priority order (highest first)

func (*RoleRegistry) ListRoles

func (r *RoleRegistry) ListRoles() []*RoleDefinition

ListRoles returns all registered role definitions

func (*RoleRegistry) RegisterRole

func (r *RoleRegistry) RegisterRole(role *RoleDefinition) error

RegisterRole registers or updates a role definition Override semantics: If a role with the same name exists, permissions are merged with the new permissions taking precedence

func (*RoleRegistry) ValidateRoleAssignment

func (r *RoleRegistry) ValidateRoleAssignment(roleName string, isPlatformOrg bool) error

ValidateRoleAssignment checks if a role can be assigned to a user in an organization Platform roles (IsPlatform=true) can only be assigned in the platform organization

type RoleRegistryInterface

type RoleRegistryInterface interface {
	// RegisterRole registers or updates a role definition
	// Override semantics: If a role with the same name exists, permissions are merged
	RegisterRole(role *RoleDefinition) error

	// GetRole retrieves a role definition by name
	GetRole(name string) (*RoleDefinition, bool)

	// ListRoles returns all registered role definitions
	ListRoles() []*RoleDefinition

	// Bootstrap applies all registered roles to the platform organization
	// Called once during server startup after database migrations and plugin initialization
	Bootstrap(ctx context.Context, db *bun.DB, rbacService *Service, platformOrgID xid.ID) error

	// ValidateRoleAssignment checks if a role can be assigned to a user in an organization
	// Platform roles (IsPlatform=true) can only be assigned in the platform organization
	ValidateRoleAssignment(roleName string, isPlatformOrg bool) error

	// GetRoleHierarchy returns roles in descending priority order (highest first)
	GetRoleHierarchy() []*RoleDefinition
}

RoleRegistryInterface defines the contract for role registration and management This interface enables: - Mock implementations for testing - Alternative implementations (cached, remote, etc.) - Dependency injection and loose coupling

type RoleRepository

type RoleRepository interface {
	Create(ctx context.Context, role *schema.Role) error
	Update(ctx context.Context, role *schema.Role) error
	Delete(ctx context.Context, roleID xid.ID) error
	FindByID(ctx context.Context, roleID xid.ID) (*schema.Role, error)
	FindByNameAndApp(ctx context.Context, name string, appID xid.ID) (*schema.Role, error)
	ListByOrg(ctx context.Context, orgID *string) ([]schema.Role, error)

	// Template operations
	GetRoleTemplates(ctx context.Context, appID xid.ID) ([]*schema.Role, error)
	GetOwnerRole(ctx context.Context, appID xid.ID) (*schema.Role, error)

	// Organization-scoped roles
	GetOrgRoles(ctx context.Context, orgID xid.ID) ([]*schema.Role, error)
	GetOrgRoleWithPermissions(ctx context.Context, roleID xid.ID) (*schema.Role, error)

	// Role cloning
	CloneRole(ctx context.Context, templateID xid.ID, orgID xid.ID, customName *string) (*schema.Role, error)
}

RoleRepository handles role operations for RBAC

type RoleTemplate

type RoleTemplate struct {
	*schema.Role
	PermissionCount int  `json:"permissionCount"`
	CanModify       bool `json:"canModify"` // Whether this template can be modified
}

RoleTemplate represents a role template with metadata for cloning

type RoleWithPermissions

type RoleWithPermissions struct {
	*schema.Role
	Permissions []*schema.Permission `json:"permissions"`
}

RoleWithPermissions represents a role with its associated permissions

type Service

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

Service provides in-memory management of RBAC policies and role/permission operations. Storage-backed repositories can be added later via repository interfaces.

func NewService

func NewService() *Service

func NewServiceWithRepositories

func NewServiceWithRepositories(
	roleRepo RoleRepository,
	permissionRepo PermissionRepository,
	rolePermissionRepo RolePermissionRepository,
	userRoleRepo UserRoleRepository,
) *Service

NewServiceWithRepositories creates a service with repository dependencies

func (*Service) AddExpression

func (s *Service) AddExpression(expression string) error

func (*Service) AddPolicy

func (s *Service) AddPolicy(p *Policy)

func (*Service) Allowed

func (s *Service) Allowed(ctx *Context) bool

Allowed checks whether any registered policy allows the context.

func (*Service) AllowedWithRoles

func (s *Service) AllowedWithRoles(ctx *Context, roles []string) bool

AllowedWithRoles checks policies against a subject plus assigned roles. If a policy subject is of form "role:<name>", it will be evaluated when that role is present in the provided roles slice.

func (*Service) AssignOwnerRole

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

AssignOwnerRole assigns the owner role to a user in an organization

func (*Service) AssignPermissionsToRole

func (s *Service) AssignPermissionsToRole(ctx context.Context, roleID xid.ID, permissionIDs []xid.ID) error

AssignPermissionsToRole assigns permissions to a role

func (*Service) BootstrapOrgRoles

func (s *Service) BootstrapOrgRoles(ctx context.Context, orgID xid.ID, templateIDs []xid.ID, customizations map[xid.ID]*RoleCustomization) error

BootstrapOrgRoles clones selected role templates for a new organization

func (*Service) CreateCustomPermission

func (s *Service) CreateCustomPermission(ctx context.Context, name, description, category string, orgID xid.ID) (*schema.Permission, error)

CreateCustomPermission creates a custom permission for an organization

func (*Service) DeleteOrgRole

func (s *Service) DeleteOrgRole(ctx context.Context, roleID xid.ID) error

DeleteOrgRole deletes an organization-specific role

func (*Service) GetAppPermissions

func (s *Service) GetAppPermissions(ctx context.Context, appID xid.ID) ([]*schema.Permission, error)

GetAppPermissions gets all app-level permissions

func (*Service) GetOrgPermissions

func (s *Service) GetOrgPermissions(ctx context.Context, orgID xid.ID) ([]*schema.Permission, error)

GetOrgPermissions gets all org-specific permissions

func (*Service) GetOrgRoleWithPermissions

func (s *Service) GetOrgRoleWithPermissions(ctx context.Context, roleID xid.ID) (*RoleWithPermissions, error)

GetOrgRoleWithPermissions gets a role with its permissions loaded

func (*Service) GetOrgRoles

func (s *Service) GetOrgRoles(ctx context.Context, orgID xid.ID) ([]*schema.Role, error)

GetOrgRoles gets all roles specific to an organization

func (*Service) GetOwnerRole

func (s *Service) GetOwnerRole(ctx context.Context, appID xid.ID) (*schema.Role, error)

GetOwnerRole gets the role marked as the owner role for an app

func (*Service) GetPermissionsByCategory

func (s *Service) GetPermissionsByCategory(ctx context.Context, category string, appID xid.ID) ([]*schema.Permission, error)

GetPermissionsByCategory gets permissions by category

func (*Service) GetRolePermissions

func (s *Service) GetRolePermissions(ctx context.Context, roleID xid.ID) ([]*schema.Permission, error)

GetRolePermissions gets all permissions for a role

func (*Service) GetRoleTemplates

func (s *Service) GetRoleTemplates(ctx context.Context, appID xid.ID) ([]*schema.Role, error)

GetRoleTemplates gets all role templates for an app

func (*Service) LoadPolicies

func (s *Service) LoadPolicies(ctx context.Context, repo PolicyRepository) error

LoadPolicies loads and parses all stored policy expressions from a repository

func (*Service) RemovePermissionsFromRole

func (s *Service) RemovePermissionsFromRole(ctx context.Context, roleID xid.ID, permissionIDs []xid.ID) error

RemovePermissionsFromRole removes permissions from a role

func (*Service) SetRepositories

func (s *Service) SetRepositories(
	roleRepo RoleRepository,
	permissionRepo PermissionRepository,
	rolePermissionRepo RolePermissionRepository,
	userRoleRepo UserRoleRepository,
)

SetRepositories sets the repository dependencies (for services created with NewService())

func (*Service) UpdateOrgRole

func (s *Service) UpdateOrgRole(ctx context.Context, roleID xid.ID, name, description string, permissionIDs []xid.ID) error

UpdateOrgRole updates an organization-specific role

type UserRoleRepository

type UserRoleRepository interface {
	Assign(ctx context.Context, userID, roleID, orgID xid.ID) error
	Unassign(ctx context.Context, userID, roleID, orgID xid.ID) error
	ListRolesForUser(ctx context.Context, userID xid.ID, orgID *xid.ID) ([]schema.Role, error)
}

UserRoleRepository handles user-role assignments for RBAC

Jump to

Keyboard shortcuts

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