App Logo
Plugins

Organizations Plugin

Manage multi-tenant organizations, members and teams. Enables team collaboration, and email-based invitations.

Overview

The Organizations plugin provides multi-tenancy and team management capabilities. It enables users to create organizations, manage members with roles, organize members into teams, and send email-based invitations.

Core Entities

  • Organizations: Owner-based organizational units
  • Invitations: Email-based invitations for joining organizations
  • Members: Users assigned to organizations with roles
  • Teams: Group members into teams within organizations
  • Team Members: Users assigned to teams within organizations

Features

  • Multi-tenant organization management
  • Role-based member management within organizations
  • Team organization and management within organizations
  • Email-based member invitations with configurable expiration
  • Team member management
  • Full lifecycle management (create, read, update, delete operations)

NOTE

This plugin has a dependency on the Access Control plugin for role-based access control. Make sure to configure the Access Control plugin to utilize all features of the Organizations plugin.


Configuration

Standalone Mode:

[plugins.organizations]
enabled = true
organizations_limit = 10 # Optional limit on number of organizations (set to 0 for unlimited)
members_limit = 100 # Optional limit on number of members per organization (set to 0 for unlimited)
invitations_limit = 100 # Optional limit on number of invitations sent to a user (100 by default)
invitation_expires_in = "24h" # Expiration time for organization invitations (24h = 1 day by default)
require_email_verified_on_invitation = true # Whether to require the invited user's email to be verified before accepting or rejecting an organization invitation (false by default)

Library Mode:

import (
  "time"

  authulamodels "github.com/Authula/authula/models"
  organizationsplugin "github.com/Authula/authula/plugins/organizations"
  organizationsplugintypes "github.com/Authula/authula/plugins/organizations/types"
)

organizationsplugin.New(organizationsplugintypes.OrganizationsPluginConfig{
  Enabled:                          true,
  OrganizationsLimit:               new(10),
  MembersLimit:                     new(100),
  InvitationsLimit:                 new(100),
  InvitationExpiresIn:              7 * 24 * time.Hour,
  RequireEmailVerifiedOnInvitation: true,
  ServiceHooks: &organizationsplugintypes.OrganizationsServiceHooksConfig{
    // Optional service hooks for custom logic on organization lifecycle events
  },
  SendOrganizationInvitationEmail: func(
    params organizationsplugintypes.SendOrganizationInvitationEmailParams,
    reqCtx *authulamodels.RequestContext,
  ) error {
    // Optionally handle email sending here...
    return nil
  },
})

API Reference

Each endpoint in this plugin requires the caller to have a specific hardcoded permission assigned to their role(s).

Organizations

HTTP MethodRoute PathDescriptionRequired Permission
POST/organizationsCreate organizationNone
GET/organizationsList user's organizationsNone
GET/organizations/{organization_id}Get organizationorganizations:read
PATCH/organizations/{organization_id}Update organizationorganizations:update
DELETE/organizations/{organization_id}Delete organizationorganizations:delete

Invitations

HTTP MethodRoute PathDescriptionRequired Permission
POST/organizations/{organization_id}/invitationsCreate invitationorganizations:invitations:create
GET/organizations/{organization_id}/invitationsList invitationsorganizations:invitations:list
GET/organizations/{organization_id}/invitations/{invitation_id}Get invitationorganizations:invitations:read
PATCH/organizations/{organization_id}/invitations/{invitation_id}/revokeRevoke invitationorganizations:invitations:revoke
PATCH/organizations/{organization_id}/invitations/{invitation_id}/acceptAccept invitationNone
PATCH/organizations/{organization_id}/invitations/{invitation_id}/rejectReject invitationNone

Members

HTTP MethodRoute PathDescriptionRequired Permission
POST/organizations/{organization_id}/membersAdd memberorganizations:members:add
GET/organizations/{organization_id}/membersList membersorganizations:members:list
GET/organizations/{organization_id}/members/{member_id}Get memberorganizations:members:read
GET/organizations/{organization_id}/members/by-user/{user_id}Get member by user IDorganizations:members:read
PATCH/organizations/{organization_id}/members/{member_id}Update memberorganizations:members:update
DELETE/organizations/{organization_id}/members/{member_id}Remove memberorganizations:members:remove

Teams

HTTP MethodRoute PathDescriptionRequired Permission
POST/organizations/{organization_id}/teamsCreate teamorganizations:teams:create
GET/organizations/{organization_id}/teamsList teamsorganizations:teams:list
GET/organizations/{organization_id}/teams/{team_id}Get teamorganizations:teams:read
PATCH/organizations/{organization_id}/teams/{team_id}Update teamorganizations:teams:update
DELETE/organizations/{organization_id}/teams/{team_id}Delete teamorganizations:teams:delete

Team Members

HTTP MethodRoute PathDescriptionRequired Permission
POST/organizations/{organization_id}/teams/{team_id}/membersAdd member to teamorganizations:team-members:add
GET/organizations/{organization_id}/teams/{team_id}/membersList team membersorganizations:team-members:list
GET/organizations/{organization_id}/teams/{team_id}/members/{member_id}Get team memberorganizations:team-members:read
DELETE/organizations/{organization_id}/teams/{team_id}/members/{member_id}Remove member from teamorganizations:team-members:remove

Database Schema

This plugin creates the following database tables:

Table: organizations

FieldTypeKeyDescription
iduuidPKUnique identifier for the organization
owner_iduuidFKReference to the organization owner (user)
namestring-Organization name
slugstring-URL-friendly organization identifier (unique)
logostring?-Organization logo URL
metadataJSON-Additional organization metadata
created_attimestamp-Record creation time
updated_attimestamp-Record last update time

Table: organization_invitations

FieldTypeKeyDescription
iduuidPKUnique identifier for the invitation
organization_iduuidFKReference to the organization
inviter_iduuidFKReference to the user who sent the invitation
emailstring-Email address being invited
rolestring-Role assigned to the invited member
statusstring-Invitation status
expires_attimestamp-Invitation expiration time
created_attimestamp-Record creation time

Table: organization_members

FieldTypeKeyDescription
iduuidPKUnique identifier for the member record
organization_iduuidFKReference to the organization
user_iduuidFKReference to the user
rolestring-Member's role within the organization
created_attimestamp-Record creation time
updated_attimestamp-Record last update time

Table: organization_teams

FieldTypeKeyDescription
iduuidPKUnique identifier for the team
organization_iduuidFKReference to the organization
namestring-Team name
slugstring-URL-friendly identifier
descriptionstring?-Description
metadataJSON-Additional metadata
created_attimestamp-Record creation time
updated_attimestamp-Record last update time

Table: organization_team_members

FieldTypeKeyDescription
iduuidPKUnique identifier for the team member record
team_iduuidFKReference to the team
member_iduuidFKReference to the organization member
created_attimestamp-Record creation time

Migrations are automatically handled when the plugin is initialized.

Service Hooks

This plugin supports service-level hooks, providing lifecycle callbacks with access to the actor context. Hooks are only supported in Library Mode.

The following hook configurations are available via OrganizationsServiceHooksConfig:

OrganizationsOrganizationServiceHooksConfig:

HookSignature
BeforeCreatefunc(ctx, actor *models.Actor, organization *Organization) error
AfterCreatefunc(ctx, actor *models.Actor, organization *Organization) error
BeforeUpdatefunc(ctx, actor *models.Actor, organization *Organization) error
AfterUpdatefunc(ctx, actor *models.Actor, organization *Organization) error
BeforeDeletefunc(ctx, actor *models.Actor, organization *Organization) error
AfterDeletefunc(ctx, actor *models.Actor, organization *Organization) error

MembersOrganizationMemberServiceHooksConfig:

HookSignature
BeforeCreatefunc(ctx, actor *models.Actor, member *OrganizationMember) error
AfterCreatefunc(ctx, actor *models.Actor, member *OrganizationMember) error
BeforeUpdatefunc(ctx, actor *models.Actor, member *OrganizationMember) error
AfterUpdatefunc(ctx, actor *models.Actor, member *OrganizationMember) error
BeforeDeletefunc(ctx, actor *models.Actor, member *OrganizationMember) error
AfterDeletefunc(ctx, actor *models.Actor, member *OrganizationMember) error

InvitationsOrganizationInvitationServiceHooksConfig:

HookSignature
BeforeCreatefunc(ctx, actor *models.Actor, invitation *OrganizationInvitation) error
AfterCreatefunc(ctx, actor *models.Actor, invitation *OrganizationInvitation) error
BeforeUpdatefunc(ctx, actor *models.Actor, invitation *OrganizationInvitation) error
AfterUpdatefunc(ctx, actor *models.Actor, invitation *OrganizationInvitation) error

TeamsOrganizationTeamServiceHooksConfig:

HookSignature
BeforeCreatefunc(ctx, actor *models.Actor, team *OrganizationTeam) error
AfterCreatefunc(ctx, actor *models.Actor, team *OrganizationTeam) error
BeforeUpdatefunc(ctx, actor *models.Actor, team *OrganizationTeam) error
AfterUpdatefunc(ctx, actor *models.Actor, team *OrganizationTeam) error
BeforeDeletefunc(ctx, actor *models.Actor, team *OrganizationTeam) error
AfterDeletefunc(ctx, actor *models.Actor, team *OrganizationTeam) error

Team MembersOrganizationTeamMemberServiceHooksConfig:

HookSignature
BeforeCreatefunc(ctx, actor *models.Actor, member *OrganizationTeamMember) error
AfterCreatefunc(ctx, actor *models.Actor, member *OrganizationTeamMember) error
BeforeDeletefunc(ctx, actor *models.Actor, member *OrganizationTeamMember) error
AfterDeletefunc(ctx, actor *models.Actor, member *OrganizationTeamMember) error

NOTE

Service hooks are only supported in Library Mode.


Plugin Capabilities

Service hooks can be used to execute custom logic at various points in the organization, member, invitation, team, and team member lifecycle. See the Service Hooks section for a full list of available hooks.


Security Recommendations

  • Ensure that the Access Control plugin is properly configured to manage permissions for organization-related actions.
  • Regularly review organization members and their roles to maintain proper access control.
  • Make sure to always require authentication for all organization-related API routes and enforce role-based access control for certain routes.

Client Plugin

If you're using the Authula SDK, add the plugin to the client instance as follows:

import { createClient } from "authula";
import { OrganizationsPlugin } from "authula/plugins";

export const authulaClient = createClient({
  url: "http://localhost:8080/auth",
  plugins: [new OrganizationsPlugin()],
});

On this page