Tenant Isolation Implementation Guide
Overview
This document tracks the implementation of tenant isolation across all business models in the Baldr platform.
Implementation Checklist
Core Principle
Every business collection MUST:
- Have a
tenantIdfield (ObjectId reference to Tenant) - Have compound indexes starting with
tenantId - Have all queries scoped by
tenantIdin controllers/services
Excluded Models (Platform-level)
These models are NOT tenant-scoped as they are platform-wide:
- ✅
tenant.model.ts- Tenant registry itself - ✅
credential.model.ts- Already implemented (users belong to tenants) - ✅
module.model.ts- Shared module definitions - ✅
language.model.ts- Shared language definitions - ⚠️
log.model.ts- System logs (keep but add optional tenantId for tracking)
Business Models Requiring tenantId
Content Management
-
page.model.ts- Website pages -
news.model.ts- News articles -
gallery.model.ts- Image galleries -
file.model.ts- File uploads
E-commerce
-
product.model.ts- Products -
command.model.ts- Orders/Commands -
category.model.ts- Product categories -
review.model.ts- Product reviews -
giftCard.model.ts- Gift cards -
cart.model.ts- Shopping carts
Hospitality
-
room.model.ts- Hotel rooms -
event.model.ts- Events -
vehicle.model.ts- Vehicles
Real Estate
-
realEstateProperty.model.ts- Properties
Food & Beverage
-
wine.model.ts- Wine products
Communication
-
contact.model.ts- Contact form submissions -
newsletter.model.ts- Newsletter campaigns -
newsletterSubscribers.model.ts- Newsletter subscribers -
group.model.ts- User groups
Company
-
job.model.ts- Job postings -
staff.model.ts- Staff members -
partner.model.ts- Partners
Configuration
-
websiteManagement.model.ts- Website settings (singleton per tenant) -
address.model.ts- Addresses -
redirect.model.ts- URL redirects -
user.model.ts- Frontend users -
poll.model.ts- Polls -
booklet.model.ts- Booklets -
faq.model.ts- FAQ entries -
mailSettings.model.ts- Mail settings -
tableorder.model.ts- Table order configuration -
giftCardSettings.model.ts- Gift card settings
Standard Implementation Pattern
// 1. Add tenantId field
const ModelSchema = new Schema<IModel>({
tenantId: {
type: Schema.Types.ObjectId,
ref: "Tenant",
required: true,
index: true,
},
// ... other fields
});
// 2. Add compound indexes starting with tenantId
ModelSchema.index({ tenantId: 1, createdAt: -1 });
ModelSchema.index({ tenantId: 1, active: 1 });
ModelSchema.index({ tenantId: 1, slug: 1 }, { unique: true }); // For unique per tenant
// 3. Update unique constraints to be tenant-scoped
// BEFORE: path: { unique: true }
// AFTER: Remove field-level unique, add compound unique index
ModelSchema.index({ tenantId: 1, path: 1 }, { unique: true });
Controller/Service Updates
Every query must include tenantId:
// Get from middleware (set by tenantIsolation middleware)
const tenantId = req.tenantId;
// All queries MUST filter by tenantId
await Model.find({ tenantId, ...otherFilters });
await Model.findOne({ tenantId, _id: id });
await Model.updateOne({ tenantId, _id: id }, update);
await Model.deleteOne({ tenantId, _id: id });
Migration Strategy
Phase 1: Model Updates (Current)
- Update all model schemas to include tenantId
- Add proper indexes
- Update unique constraints to be tenant-scoped
Phase 2: Data Migration
Create migration script to:
- Identify default/first tenant
- Add tenantId to all existing documents
- Verify data integrity
Phase 3: Middleware & Controller Updates
- Ensure tenantIsolation middleware is applied to all protected routes
- Update all controllers to scope queries by tenantId
- Add validation to ensure tenantId consistency
Phase 4: Testing
- Test CRUD operations for each model
- Verify tenant isolation (users can't access other tenant data)
- Performance testing with indexes
Progress Tracking
- Models updated: 0/35
- Interfaces updated: 0/35
- Controllers updated: 0/35
- Migration scripts created: 0/1
- Tests updated: 0/35