Initial commit
This commit is contained in:
@@ -0,0 +1,261 @@
|
||||
# Multi-Tenancy Deployment Guide
|
||||
|
||||
## Pre-Deployment Checklist
|
||||
|
||||
- [ ] Code review completed
|
||||
- [ ] All tests passing
|
||||
- [ ] Database backup created
|
||||
- [ ] Rollback plan prepared
|
||||
- [ ] Downtime window scheduled (if needed)
|
||||
|
||||
## Deployment Steps
|
||||
|
||||
### Step 1: Backup Database
|
||||
|
||||
```bash
|
||||
# SQL Server backup example
|
||||
BACKUP DATABASE PowderCoatingDb
|
||||
TO DISK = 'C:\Backups\PowderCoatingDb_PreMultiTenancy.bak'
|
||||
WITH FORMAT, COMPRESSION;
|
||||
```
|
||||
|
||||
### Step 2: Build Solution
|
||||
|
||||
```bash
|
||||
cd Y:\PCC\PowderCoatingApp
|
||||
dotnet build
|
||||
```
|
||||
|
||||
Ensure no build errors.
|
||||
|
||||
### Step 3: Review Migration
|
||||
|
||||
Check the migration file to understand what will happen:
|
||||
```bash
|
||||
# View the migration
|
||||
cat src/PowderCoating.Infrastructure/Migrations/20260205220415_AddMultiTenancy.cs
|
||||
```
|
||||
|
||||
The migration will:
|
||||
- Create `Companies` table
|
||||
- Add `CompanyId` columns to all entities
|
||||
- Add `CompanyRole` to `AspNetUsers`
|
||||
- Create foreign keys and indexes
|
||||
|
||||
### Step 4: Apply Migration
|
||||
|
||||
```bash
|
||||
cd src/PowderCoating.Web
|
||||
dotnet ef database update --project ../PowderCoating.Infrastructure
|
||||
```
|
||||
|
||||
**Expected output:**
|
||||
```
|
||||
Applying migration '20260205220415_AddMultiTenancy'.
|
||||
Done.
|
||||
```
|
||||
|
||||
### Step 5: Run Seed Data
|
||||
|
||||
The seed data will run automatically on application startup and will:
|
||||
- Create default "Demo Company"
|
||||
- Create SuperAdmin user
|
||||
- Create CompanyAdmin user
|
||||
- Create Manager user
|
||||
|
||||
Start the application:
|
||||
```bash
|
||||
dotnet run --project src/PowderCoating.Web
|
||||
```
|
||||
|
||||
Watch the logs for:
|
||||
```
|
||||
Company 'Demo Company' created
|
||||
User 'superadmin@powdercoating.com' created
|
||||
User 'admin@demo.com' created
|
||||
User 'manager@demo.com' created
|
||||
```
|
||||
|
||||
### Step 6: Verify Migration Success
|
||||
|
||||
Connect to the database and verify:
|
||||
|
||||
```sql
|
||||
-- Check Companies table exists
|
||||
SELECT * FROM Companies;
|
||||
|
||||
-- Check CompanyId added to entities
|
||||
SELECT TOP 5 Id, CompanyId FROM Customers;
|
||||
SELECT TOP 5 Id, CompanyId FROM Jobs;
|
||||
|
||||
-- Check ApplicationUser has CompanyId
|
||||
SELECT TOP 5 Id, Email, CompanyId, CompanyRole FROM AspNetUsers;
|
||||
|
||||
-- Verify foreign keys
|
||||
SELECT
|
||||
fk.name AS ForeignKeyName,
|
||||
OBJECT_NAME(fk.parent_object_id) AS TableName,
|
||||
COL_NAME(fkc.parent_object_id, fkc.parent_column_id) AS ColumnName,
|
||||
OBJECT_NAME (fk.referenced_object_id) AS ReferencedTableName
|
||||
FROM
|
||||
sys.foreign_keys AS fk
|
||||
INNER JOIN sys.foreign_key_columns AS fkc
|
||||
ON fk.object_id = fkc.constraint_object_id
|
||||
WHERE
|
||||
OBJECT_NAME(fk.referenced_object_id) = 'Companies';
|
||||
```
|
||||
|
||||
### Step 7: Test Login
|
||||
|
||||
Test each user account:
|
||||
|
||||
1. **SuperAdmin Login**
|
||||
- URL: https://localhost:5001/Identity/Account/Login
|
||||
- Email: superadmin@powdercoating.com
|
||||
- Password: SuperAdmin123!
|
||||
- Should see: "Companies" menu in Platform Management
|
||||
|
||||
2. **Company Admin Login**
|
||||
- URL: https://localhost:5001/Identity/Account/Login
|
||||
- Email: admin@demo.com
|
||||
- Password: CompanyAdmin123!
|
||||
- Should see: "Manage Users" menu in Company Settings
|
||||
- Should see: "Demo Company" badge in header
|
||||
|
||||
3. **Manager Login**
|
||||
- URL: https://localhost:5001/Identity/Account/Login
|
||||
- Email: manager@demo.com
|
||||
- Password: Manager123!
|
||||
- Should see: "Demo Company" badge in header
|
||||
- Should NOT see: "Manage Users" menu
|
||||
|
||||
### Step 8: Verify Data Isolation
|
||||
|
||||
1. As **SuperAdmin**, create a second company:
|
||||
- Navigate to Companies → Create New Company
|
||||
- Company Name: "Test Company"
|
||||
- Create admin user for Test Company
|
||||
|
||||
2. Login as **Test Company Admin**
|
||||
- Verify you only see Test Company data
|
||||
- Create a test customer
|
||||
|
||||
3. Login as **Demo Company Admin**
|
||||
- Verify you CANNOT see Test Company customer
|
||||
- Verify you only see Demo Company data
|
||||
|
||||
4. Login as **SuperAdmin**
|
||||
- Navigate to Customers
|
||||
- Should see customers from BOTH companies
|
||||
|
||||
## Post-Deployment Verification
|
||||
|
||||
### Functional Tests
|
||||
|
||||
- [ ] SuperAdmin can create new companies
|
||||
- [ ] SuperAdmin can see all companies' data
|
||||
- [ ] Company Admin can create users in their company
|
||||
- [ ] Company Admin cannot see other companies' data
|
||||
- [ ] Users can only see data from their own company
|
||||
- [ ] New entities automatically get CompanyId assigned
|
||||
- [ ] Query filters work correctly
|
||||
|
||||
### Performance Tests
|
||||
|
||||
- [ ] Page load times are acceptable
|
||||
- [ ] No N+1 query issues
|
||||
- [ ] Indexes are being used (check query plans)
|
||||
|
||||
### Security Tests
|
||||
|
||||
- [ ] Cannot access other company's data by changing IDs in URL
|
||||
- [ ] Authorization policies enforce correctly
|
||||
- [ ] Query filters cannot be bypassed by regular users
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: Migration Fails
|
||||
|
||||
**Error: Foreign key constraint conflicts**
|
||||
|
||||
This means existing data has CompanyId=0 which doesn't exist.
|
||||
|
||||
**Solution:**
|
||||
```sql
|
||||
-- Check if default company exists
|
||||
SELECT * FROM Companies WHERE Id = 1;
|
||||
|
||||
-- If no company exists, seed data didn't run
|
||||
-- Run application to trigger seed, OR manually:
|
||||
INSERT INTO Companies (CompanyName, CompanyCode, PrimaryContactName, PrimaryContactEmail,
|
||||
IsActive, SubscriptionStartDate, CreatedAt, CompanyId)
|
||||
VALUES ('Demo Company', 'DEMO', 'Admin', 'admin@demo.com',
|
||||
1, GETUTCDATE(), GETUTCDATE(), 0);
|
||||
|
||||
-- Update CompanyId to self-reference
|
||||
UPDATE Companies SET CompanyId = Id WHERE Id = 1;
|
||||
|
||||
-- Update existing data
|
||||
UPDATE Customers SET CompanyId = 1 WHERE CompanyId = 0;
|
||||
UPDATE Jobs SET CompanyId = 1 WHERE CompanyId = 0;
|
||||
-- ... repeat for all entities
|
||||
```
|
||||
|
||||
### Issue: Users Can't Login
|
||||
|
||||
**Error: "Unable to determine your company"**
|
||||
|
||||
This means the user's CompanyId is not set or CompanyId claim is missing.
|
||||
|
||||
**Solution:**
|
||||
```sql
|
||||
-- Check user's CompanyId
|
||||
SELECT Id, Email, CompanyId FROM AspNetUsers WHERE Email = 'user@example.com';
|
||||
|
||||
-- Update if needed
|
||||
UPDATE AspNetUsers SET CompanyId = 1 WHERE CompanyId = 0 OR CompanyId IS NULL;
|
||||
```
|
||||
|
||||
Then ensure user re-logs in to get fresh claims.
|
||||
|
||||
### Issue: Seeing Other Company's Data
|
||||
|
||||
This means query filters aren't working.
|
||||
|
||||
**Check:**
|
||||
1. Is `ITenantContext` registered in DI?
|
||||
2. Is `ApplicationDbContext` receiving `IHttpContextAccessor` and `IServiceProvider`?
|
||||
3. Are query filters being applied in `OnModelCreating`?
|
||||
4. Is the user authenticated and has CompanyId claim?
|
||||
|
||||
## Rollback Procedure
|
||||
|
||||
If critical issues occur:
|
||||
|
||||
```bash
|
||||
# Rollback migration
|
||||
cd src/PowderCoating.Web
|
||||
dotnet ef database update 20260205163837_InitialCreate --project ../PowderCoating.Infrastructure
|
||||
|
||||
# Restore database backup
|
||||
RESTORE DATABASE PowderCoatingDb
|
||||
FROM DISK = 'C:\Backups\PowderCoatingDb_PreMultiTenancy.bak'
|
||||
WITH REPLACE;
|
||||
|
||||
# Revert code changes
|
||||
git revert <commit-hash>
|
||||
```
|
||||
|
||||
## Support Contacts
|
||||
|
||||
- Lead Developer: [Your Name]
|
||||
- Database Admin: [DBA Name]
|
||||
- DevOps: [DevOps Contact]
|
||||
|
||||
## Post-Deployment Tasks
|
||||
|
||||
- [ ] Monitor application logs for errors
|
||||
- [ ] Monitor database performance
|
||||
- [ ] Update documentation
|
||||
- [ ] Train users on new multi-tenancy features
|
||||
- [ ] Schedule follow-up review (1 week)
|
||||
Reference in New Issue
Block a user