Organizations & Teams
Concordia uses Better Auth’s organization plugin to provide multi-tenant team management with role-based access control, member management, and invitation workflows.Overview
Organizations are implemented insrc/database/schemas/auth-schema.ts using Better Auth’s built-in organization features. This provides:
- Multi-user organizations with hierarchical roles
- Member invitation system
- Active organization context per session
- Organization-scoped resources (blogs, services, etc.)
Organization Schema
Fromsrc/database/schemas/auth-schema.ts (lines 94-105):
Organization Fields
text
required
Unique identifier for the organization
text
required
Display name of the organizationExample:
"Acme Corporation"text
required
Unique URL-friendly identifierExample:
"acme-corp"text
URL to organization logo image
timestamp
required
When the organization was created
text
JSON string for additional custom data
The
slug field has a unique index ensuring no two organizations share the same URL path.Member Management
Fromauth-schema.ts (lines 107-124):
Member Fields
text
required
Unique member relationship ID
text
required
Reference to the organizationOn Delete: CASCADE - members are deleted when organization is deleted
text
required
Reference to the userOn Delete: CASCADE - membership is removed when user is deleted
text
default:"member"
Member’s role within the organizationCommon roles:
owner, admin, membertimestamp
required
When the user joined the organization
Member Indexes
Two indexes optimize member queries:- By Organization:
member_organizationId_idx- Fast lookup of all members in an org - By User:
member_userId_idx- Fast lookup of all orgs a user belongs to
Invitation System
Fromauth-schema.ts (lines 126-146):
Invitation Fields
text
required
Unique invitation identifier
text
required
Organization the invitation is for
text
required
Email address of the invitee
text
Role the invitee will have upon accepting
text
default:"pending"
Invitation status:
pending, accepted, rejected, expiredtimestamp
required
Expiration date/time for the invitation
timestamp
required
When the invitation was created
text
required
User who sent the invitation (must be org admin/owner)
Invitation Indexes
- By Organization:
invitation_organizationId_idx- List all invitations for an org - By Email:
invitation_email_idx- Find pending invitations for a user
Session Context
Fromauth-schema.ts (lines 32-51), sessions track the active organization:
text
ID of the organization currently active in this sessionAllows users to switch between organizations they belong to
Users can belong to multiple organizations. The
activeOrganizationId determines which org context is used for creating resources.Relationships
Fromauth-schema.ts (lines 176-201), Drizzle relations define the connections:
Relationship Diagram
Organization Roles
Better Auth organization plugin supports hierarchical roles:Default Roles
role
Full control over organization, including deletion
- Manage all members and invitations
- Delete organization
- Change organization settings
- Create and manage all resources
role
Administrative privileges
- Invite and manage members
- Manage organization settings
- Create and manage resources
- Cannot delete organization
role
Basic member access
- View organization resources
- Create resources under organization
- Cannot invite users
- Cannot change settings
Custom roles can be defined in Better Auth configuration to match your specific permission requirements.
Organization-Scoped Resources
Blog Posts
Fromblog_posts.schema.ts:
Service Listings
Fromservices_listings.schema.ts:
Authors
Fromblog_authors.schema.ts:
The
worksForId field links authors to organizations, establishing organizational attribution for content.Invitation Workflow
- Create Invitation: Admin/owner creates invitation with email and role
- Send Email: System sends invitation link to email address
- User Accepts: User clicks link and accepts invitation
- Create Membership: System creates
memberrecord with specified role - Update Invitation: Invitation status changes to
accepted
Example Invitation Flow
Multi-Tenancy Pattern
Organizations enable multi-tenancy where:- Users can belong to multiple organizations
- Resources can be scoped to an organization
- Sessions track active organization context
- Permissions are enforced per organization
Switching Organizations
Users switch active organization by updating their session:Best Practices
Member Management
- Always verify user’s role before allowing privileged actions
- Use cascade deletes to maintain referential integrity
- Index lookups by both
organizationIdanduserIdfor performance
Invitation Security
- Set reasonable expiration times (7-14 days)
- Verify invitation status before acceptance
- Check that email matches authenticated user
- Clean up expired invitations periodically
Organization Isolation
- Always filter queries by organization ID
- Use session’s
activeOrganizationIdfor context - Validate user has access to organization before showing resources
- Consider using RLS (Row Level Security) policies
Integration with Better Auth
The organization plugin is configured in Better Auth setup and provides:- Automatic organization context in auth session
- Built-in member and invitation management APIs
- Role-based access control helpers
- Organization switching functionality