multiapp

package
v0.0.15 Latest Latest
Warning

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

Go to latest
Published: Feb 11, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

README

Multiapp Plugin

The Multiapp plugin provides multi-tenancy support for AuthSome, enabling applications to support multiple isolated tenant apps with their own users, teams, and configurations.

Overview

This plugin enables both Standalone Mode and SaaS Mode:

  • Standalone Mode: Single default app with all users belonging to it
  • SaaS Mode: Multiple tenant apps with isolated data and configurations

Features

  • App Management: Create, update, and manage tenant apps
  • Member Management: Add users to apps with role-based access (owner, admin, member)
  • Team Management: Organize members into teams within apps
  • Invitation System: Invite users to join apps via secure tokens
  • Environment Support: Multiple environments per app (development, staging, production)
  • Config Overrides: App-specific configuration overrides
  • Service Decoration: Enhances core services with multi-tenancy awareness

Architecture

The plugin follows a clean architecture pattern:

plugins/multiapp/
├── service.go          # AppService implementation
├── plugin.go           # Plugin registration and initialization
├── handlers/           # HTTP request handlers
│   ├── app.go
│   ├── member.go
│   └── team.go
├── decorators/         # Service decorators for multi-tenancy
│   ├── user.go
│   ├── session.go
│   └── auth.go
├── config/             # Config service for app-specific overrides
└── middleware/         # App context middleware

Data Model

Core Entities

All entities use schema.* types from the global schema package:

  • App (schema.App): Tenant application
  • Member (schema.Member): User membership in an app
  • Team (schema.Team): Team within an app
  • TeamMember (schema.TeamMember): Team membership
  • Invitation (schema.Invitation): App invitation
  • Environment (schema.Environment): App environment (dev, staging, prod)
Repository Layer

Repositories are consolidated in the main repository/ package:

  • repository.AppRepository: App data access
  • repository.MemberRepository: Member data access
  • repository.TeamRepository: Team data access
  • repository.InvitationRepository: Invitation data access
  • repository.EnvironmentRepository: Environment data access

Usage

Installation

Add the plugin to your AuthSome initialization:

import (
    "github.com/xraph/authsome"
    "github.com/xraph/authsome/plugins/multiapp"
)

auth := authsome.New(
    authsome.WithDatabase(db),
    authsome.WithPlugins(
        multiapp.NewPlugin(
            multiapp.WithEnableAppCreation(true),
            multiapp.WithMaxMembersPerApp(100),
            multiapp.WithMaxTeamsPerApp(10),
        ),
    ),
)
Configuration
auth:
  multiapp:
    platformAppId: ""  # Auto-set during initialization
    defaultAppName: "Platform App"
    enableAppCreation: true  # Enable SaaS mode
    maxMembersPerApp: 1000
    maxTeamsPerApp: 100
    requireInvitation: false
    invitationExpiryHours: 72
    autoCreateDefaultApp: true
    defaultEnvironmentName: "Development"
API Routes

The plugin registers the following routes:

Apps
  • POST /apps - Create new app
  • GET /apps - List apps
  • GET /apps/:appId - Get app details
  • PUT /apps/:appId - Update app
  • DELETE /apps/:appId - Delete app
Members
  • GET /apps/:appId/members - List app members
  • POST /apps/:appId/members/invite - Invite member
  • PUT /apps/:appId/members/:memberId - Update member role/status
  • DELETE /apps/:appId/members/:memberId - Remove member
Teams
  • GET /apps/:appId/teams - List teams
  • POST /apps/:appId/teams - Create team
  • GET /apps/:appId/teams/:teamId - Get team details
  • PUT /apps/:appId/teams/:teamId - Update team
  • DELETE /apps/:appId/teams/:teamId - Delete team
  • POST /apps/:appId/teams/:teamId/members - Add team member
  • DELETE /apps/:appId/teams/:teamId/members/:memberId - Remove team member
Invitations
  • GET /invitations/:token - Get invitation details
  • POST /invitations/:token/accept - Accept invitation
  • POST /invitations/:token/decline - Decline invitation

Service Decorators

The plugin decorates core services to add multi-tenancy awareness:

User Service Decorator
// Automatically adds new users to the appropriate app
// Handles first user as platform owner
decoratedUserService := decorators.NewMultiTenantUserService(
    userService,
    appService,
)
Session Service Decorator
// Adds app context to sessions
// Validates app membership on session creation
decoratedSessionService := decorators.NewMultiTenantSessionService(
    sessionService,
    appService,
)
Auth Service Decorator
// Ensures authentication respects app boundaries
// Validates app membership on sign-in
decoratedAuthService := decorators.NewMultiTenantAuthService(
    authService,
    appService,
)

Hooks

The plugin registers hooks to handle multi-tenancy events:

  • AfterUserCreate: Assigns new users to appropriate apps
  • AfterUserDelete: Removes user from all apps
  • AfterSessionCreate: Logs session creation for audit

Environment Management

Each app can have multiple environments:

// Bootstrap creates a default "Development" environment
// Additional environments can be created via the Environment service

envService := registry.EnvironmentService()
env, err := envService.Create(ctx, &environment.CreateEnvironmentRequest{
    AppID: appID,
    Name: "Production",
    Type: "production",
})

App Context

Use context helpers to work with app context in handlers:

import "github.com/xraph/authsome/core/interfaces"

// Get app ID from context
appID, err := interfaces.GetAppID(ctx)

// Set app ID in context
ctx = interfaces.WithAppID(ctx, appID)

Best Practices

  1. Always validate app membership before allowing access to app resources
  2. Use service decorators instead of modifying core services directly
  3. Leverage app context for multi-tenant aware operations
  4. Configure appropriate limits for members and teams per app
  5. Enable invitations for controlled app access in SaaS mode

Migration from Legacy Organization System

If migrating from the old organization-based system:

  1. The organizations table has been renamed to apps
  2. All references to "organization" in code now use "app"
  3. Schema models are now in the global schema package
  4. Repository implementations are in the main repository package
  5. The plugin ID changed from "multitenancy" to "multiapp"

License

See main AuthSome LICENSE file.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AppsListResponse

type AppsListResponse []app.App

AppsListResponse represents a list of apps.

type Config

type Config struct {
	// PlatformAppID is the ID of the platform app
	PlatformAppID xid.ID `json:"platformAppId"`

	// DefaultAppName is the name of the default app in standalone mode
	DefaultAppName string `json:"defaultAppName"`

	// EnableAppCreation allows users to create new apps (multitenancy mode)
	EnableAppCreation bool `json:"enableAppCreation"`

	// MaxMembersPerApp limits the number of members per app
	MaxMembersPerApp int `json:"maxMembersPerApp"`

	// MaxTeamsPerApp limits the number of teams per app
	MaxTeamsPerApp int `json:"maxTeamsPerApp"`

	// RequireInvitation requires invitation for joining apps
	RequireInvitation bool `json:"requireInvitation"`

	// InvitationExpiryHours sets how long invitations are valid
	InvitationExpiryHours int `json:"invitationExpiryHours"`

	// AutoCreateDefaultApp auto-creates default app on server start
	AutoCreateDefaultApp bool `json:"autoCreateDefaultApp"`

	// DefaultEnvironmentName is the name of the default dev environment
	DefaultEnvironmentName string `json:"defaultEnvironmentName"`
}

Config holds the multi-tenancy plugin configuration.

type MembersListResponse

type MembersListResponse []app.Member

MembersListResponse represents a list of members.

type MultitenancyErrorResponse

type MultitenancyErrorResponse struct {
	Error string `example:"Error message" json:"error"`
}

MultitenancyErrorResponse represents an error response.

type MultitenancyStatusResponse

type MultitenancyStatusResponse struct {
	Status string `example:"success" json:"status"`
}

MultitenancyStatusResponse represents a status response.

type Plugin

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

Plugin implements the multi-tenancy plugin.

func NewPlugin

func NewPlugin(opts ...PluginOption) *Plugin

NewPlugin creates a new multi-tenancy plugin instance with optional configuration.

func (*Plugin) ID

func (p *Plugin) ID() string

ID returns the plugin identifier.

func (*Plugin) Init

func (p *Plugin) Init(authInstance core.Authsome) error

Init initializes the plugin with dependencies.

func (*Plugin) Migrate

func (p *Plugin) Migrate() error

Migrate runs the plugin's database migrations.

func (*Plugin) RegisterHooks

func (p *Plugin) RegisterHooks(hooks *hooks.HookRegistry) error

RegisterHooks registers the plugin's hooks.

func (*Plugin) RegisterRoutes

func (p *Plugin) RegisterRoutes(router forge.Router) error

RegisterRoutes registers the plugin's HTTP routes.

func (*Plugin) RegisterServiceDecorators

func (p *Plugin) RegisterServiceDecorators(services *registry.ServiceRegistry) error

RegisterServiceDecorators replaces core services with multi-tenant aware versions.

type PluginOption

type PluginOption func(*Plugin)

PluginOption is a functional option for configuring the plugin.

func WithDefaultAppName

func WithDefaultAppName(name string) PluginOption

WithDefaultAppName sets the default app name.

func WithDefaultConfig

func WithDefaultConfig(cfg Config) PluginOption

WithDefaultConfig sets the default configuration for the plugin.

func WithEnableAppCreation

func WithEnableAppCreation(enabled bool) PluginOption

WithEnableAppCreation sets whether app creation is enabled.

func WithInvitationExpiryHours

func WithInvitationExpiryHours(hours int) PluginOption

WithInvitationExpiryHours sets the invitation expiry hours.

func WithMaxMembersPerApp

func WithMaxMembersPerApp(max int) PluginOption

WithMaxMembersPerApp sets the maximum members per app.

func WithMaxTeamsPerApp

func WithMaxTeamsPerApp(max int) PluginOption

WithMaxTeamsPerApp sets the maximum teams per app.

func WithPlatformAppID

func WithPlatformAppID(id xid.ID) PluginOption

WithPlatformAppID sets the platform app ID.

func WithRequireInvitation

func WithRequireInvitation(required bool) PluginOption

WithRequireInvitation sets whether invitation is required.

type TeamsListResponse

type TeamsListResponse []app.Team

TeamsListResponse represents a list of teams.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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