Aller au contenu principal

Multi-Tenant Architecture Implementation

🎯 Overview

This implementation provides a complete multi-tenant architecture for the Baldr platform, allowing a single codebase, API, and database to serve thousands of isolated clients (tenants).

📋 What Has Been Implemented

✅ Backend (API)

  1. Tenant Model (BaldrTs/src/models/tenant.model.ts)

    • Complete tenant management
    • Status tracking (active, suspended, inactive)
    • Feature/module assignment
    • Metadata support
  2. Updated Credential Model (BaldrTs/src/models/credential.model.ts)

    • Added tenantId field for client association
    • Added isInleed flag to distinguish internal admins from clients
    • Created compound indexes for performance
  3. Authentication Updates (BaldrTs/src/services/core/credential.service.ts)

    • Login now returns tenant information
    • User creation supports tenant assignment
    • Token includes tenant context
  4. Tenant Isolation Middleware (BaldrTs/src/middlewares/tenantIsolation.middleware.ts)

    • Automatically extracts tenant context
    • Inleed users can override tenant via query/header
    • Client users always scoped to their tenant
    • Three variants: tenantIsolation, requireTenant, optionalTenant
  5. Tenant Management Endpoints (BaldrTs/src/controllers/tenant.controller.ts)

    • POST /api/tenant - Create tenant (Inleed only)
    • GET /api/tenant - List all tenants with pagination (Inleed only)
    • GET /api/tenant/:id - Get tenant details
    • PUT /api/tenant/:id - Update tenant (Inleed only)
    • DELETE /api/tenant/:id - Delete tenant (Inleed only)
    • GET /api/tenant/:id/stats - Get tenant statistics
  6. Migration Script (BaldrTs/src/scripts/migrate-to-multitenant.ts)

    • Creates default tenant
    • Assigns tenantId to existing credentials
    • Sets isInleed flag based on role
    • Idempotent and safe to run multiple times

✅ Frontend (Back Office)

  1. Tenant Context (Baldr-Bo/app/context/tenant.context.tsx)

    • Manages selected tenant state
    • Persists selection in localStorage
    • Provides methods to switch tenants
  2. Updated User Context (Baldr-Bo/app/context/user.context.tsx)

    • Handles dual authentication flow
    • Inleed users → Tenant selection page
    • Client users → Direct to dashboard
  3. Tenant Selection Page (Baldr-Bo/app/pages/tenants/tenantSelection.page.tsx)

    • Paginated tenant list
    • Search functionality (debounced)
    • Status indicators
    • Click to select tenant
  4. Tenant API (Baldr-Bo/app/api/tenant.api.ts)

    • Complete tenant management client
    • Handles all CRUD operations
    • Includes statistics fetching
  5. Updated Interfaces

    • ICredential now includes tenantId and isInleed
    • New ITenant interface
    • ITenantListResponse for pagination

📚 Documentation

  1. API Migration Guide (BaldrTs/documents/MULTI_TENANT_MIGRATION.md)

    • Complete implementation details
    • Step-by-step model migration guide
    • Security considerations
    • Index requirements
  2. Back Office Guide (Baldr-Bo/docs/MULTI_TENANT_BACKOFFICE.md)

    • User flow diagrams
    • Component documentation
    • API call patterns
    • Testing scenarios

🚀 Quick Start

1. Run Database Migration

cd BaldrTs
npm run migrate:multitenant
# or
npx ts-node src/scripts/migrate-to-multitenant.ts

This will:

  • Create a default tenant
  • Assign all existing users to the default tenant
  • Set isInleed flags based on user roles

2. Configure Default Tenant

Edit BaldrTs/src/scripts/migrate-to-multitenant.ts:

const MIGRATION_CONFIG: MigrationConfig = {
defaultTenant: {
name: "Your Company Name",
slug: "your-company",
contactEmail: "admin@yourcompany.com",
status: TenantStatus.ACTIVE,
},
inleedRoles: ["inleedMaster", "inleedSlave"],
};

3. Test the Implementation

Create a Test Tenant (as Inleed user)

curl -X POST http://localhost:3000/api/tenant \
-H "Authorization: Bearer YOUR_INLEED_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Test Client",
"slug": "test-client",
"contactEmail": "test@client.com",
"status": "active"
}'

Create a User for the Tenant

curl -X POST http://localhost:3000/api/credential \
-H "Authorization: Bearer YOUR_INLEED_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"userName": "testuser",
"email": "user@test-client.com",
"password": "SecurePass123!",
"firstName": "Test",
"lastName": "User",
"role": "commonMaster",
"tenantId": "TENANT_ID_FROM_PREVIOUS_STEP",
"isInleed": false
}'

Test Login Flows

Inleed User Login:

  1. Login → Should redirect to /tenants/selection
  2. Select a tenant
  3. Should redirect to /dashboard
  4. All data scoped to selected tenant

Client User Login:

  1. Login → Should redirect directly to /dashboard
  2. Cannot access tenant selection
  3. All data automatically scoped to their tenant

⚠️ What Still Needs to Be Done

High Priority

  1. Update All Business Models

    • Add tenantId field to all business collections
    • Models that need updating:
      • command.model.ts
      • page.model.ts
      • product.model.ts
      • category.model.ts
      • gallery.model.ts
      • news.model.ts
      • newsletter.model.ts
      • And all other business models
  2. Update All Controllers

    • Apply tenantIsolation middleware to all protected routes
    • Update queries to include tenantId filter
    • Validate tenant ownership before updates/deletes
  3. Update All Services

    • Accept tenantId parameter in service methods
    • Scope all database queries by tenant
    • Update create operations to include tenantId
  4. Data Migration for Other Collections

    • Create migration scripts for each business collection
    • Assign default tenant to existing records
    • Verify data integrity

Medium Priority

  1. Add Tenant Indicator to UI

    • Show current tenant in header (for Inleed users)
    • Add tenant switching button
    • Display tenant info for client users
  2. Update All React Components

    • Check for tenant selection before data fetching
    • Handle "no tenant selected" state
    • Include tenant context in API calls
  3. Add Route Guards

    • Protect tenant-specific routes
    • Ensure Inleed users have selected a tenant
    • Redirect appropriately
  4. Testing

    • Unit tests for tenant isolation
    • Integration tests for cross-tenant security
    • E2E tests for both user flows

Low Priority

  1. Analytics & Monitoring

    • Track tenant usage
    • Monitor cross-tenant access attempts
    • Dashboard for tenant statistics
  2. Additional Features

    • Tenant switching history
    • Recent tenants list
    • Tenant search in header
    • Bulk tenant operations

📖 Usage Examples

Backend: Securing a Route

import { authenticate } from '../middlewares/authentication.middleware';
import { tenantIsolation, requireTenant } from '../middlewares/tenantIsolation.middleware';

// Apply middleware chain
router.get(
'/products',
authenticate, // 1. Verify user authentication
tenantIsolation, // 2. Extract tenant context
requireTenant, // 3. Ensure tenant is present
productController.getAll
);

// In controller
async getAll(req: Request, res: Response) {
// req.tenantId is now available and verified
const products = await Product.find({
tenantId: req.tenantId,
active: true
});
res.json(products);
}

Frontend: Using Tenant Context

import { useUser } from "~/context/user.context";
import { useTenant } from "~/context/tenant.context";

function ProductList() {
const { user } = useUser();
const { currentTenant } = useTenant();
const [products, setProducts] = useState([]);

useEffect(() => {
// For Inleed users, ensure tenant is selected
if (user?.isInleed && !currentTenant) {
return;
}

// Fetch products (tenant context handled by API)
ProductApi.getAll().then(setProducts);
}, [user, currentTenant]);

if (user?.isInleed && !currentTenant) {
return <SelectTenantMessage />;
}

return <DataTable value={products} />;
}

🔒 Security Checklist

  • ✅ Tenant isolation middleware created
  • ✅ Authentication includes tenant info
  • ✅ JWT tokens include tenant context
  • ⚠️ All routes protected with middleware (needs implementation)
  • ⚠️ All queries scoped by tenantId (needs implementation)
  • ⚠️ Cross-tenant access prevented (needs testing)
  • ⚠️ Inleed actions logged (needs implementation)

📊 Performance Considerations

Implemented

  • ✅ Compound indexes on credentials (tenantId + other fields)
  • ✅ Tenant list pagination
  • ✅ Debounced search in tenant selection
  • ✅ LocalStorage persistence for tenant selection

To Implement

  • ⚠️ Compound indexes on all business collections
  • ⚠️ Query optimization for tenant-scoped data
  • ⚠️ Caching strategies per tenant
  • ⚠️ Connection pooling per tenant (if needed)

🆘 Troubleshooting

"User not associated with any tenant"

Cause: Client user doesn't have tenantId Solution: Run migration script or manually assign tenant

"Tenant context required for this operation"

Cause: Inleed user hasn't selected a tenant Solution: Ensure user selects tenant before accessing protected routes

"Only Inleed users can create tenants"

Cause: Client user attempting tenant management Solution: Verify user has isInleed: true flag

Redirect loop in Back Office

Cause: User context or tenant context not loading properly Solution: Clear localStorage and cookies, re-login

📞 Support

For questions or issues:

  1. Check documentation in /documents/ and /docs/
  2. Review the migration guides
  3. Contact the development team

🎓 Learning Resources

  • API Architecture: BaldrTs/documents/MULTI_TENANT_MIGRATION.md
  • Back Office: Baldr-Bo/docs/MULTI_TENANT_BACKOFFICE.md
  • Tenant Model: BaldrTs/src/models/tenant.model.ts
  • Tenant Context: Baldr-Bo/app/context/tenant.context.tsx
  • Migration Script: BaldrTs/src/scripts/migrate-to-multitenant.ts

🚧 Development Roadmap

Phase 1: Core Implementation ✅ COMPLETE

  • Create tenant model
  • Update credential model
  • Implement tenant isolation middleware
  • Create tenant management API
  • Build tenant selection UI
  • Update authentication flow

Phase 2: Model Migration ⚠️ IN PROGRESS

  • Update all business models
  • Add compound indexes
  • Migrate existing data
  • Update all controllers

Phase 3: Frontend Integration ⚠️ IN PROGRESS

  • Update all components
  • Add tenant indicators
  • Implement route guards
  • Comprehensive testing

Phase 4: Polish & Production 🔜 UPCOMING

  • Performance optimization
  • Security audit
  • Documentation review
  • Production deployment

Version: 1.0.0
Last Updated: January 2026
Status: Core implementation complete, model migration in progress