Phases 3 & 4: Complete data access architecture migration
Phase 3 — eliminated ApplicationDbContext from all non-exempt controllers, routing all data access through IUnitOfWork. Added IPlainRepository<T> for the four platform entities (Announcement, BannedIp, DashboardTip, ReleaseNote) that intentionally don't extend BaseEntity and therefore can't use the constrained IRepository<T>. Added permanent-exception comments to the 18 controllers that legitimately retain direct DbContext access (Identity infra, cross-tenant platform ops, bulk streaming exports). Phase 4 — added EnforceDataAccessArchitecture() to Program.cs, a startup gate that reflects over every Controller subclass and throws at boot if any non-exempt controller injects ApplicationDbContext. The app cannot start with a violation. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -41,14 +41,14 @@ public class UnitOfWork : IUnitOfWork
|
||||
private IRepository<AiItemPrediction>? _aiItemPredictions;
|
||||
|
||||
// Powder Insights
|
||||
private IRepository<PowderUsageLog>? _powderUsageLogs;
|
||||
private IPowderUsageLogRepository? _powderUsageLogs;
|
||||
|
||||
// Core repositories
|
||||
private ICustomerRepository? _customers;
|
||||
private IJobRepository? _jobs;
|
||||
private IRepository<JobDailyPriority>? _jobDailyPriorities;
|
||||
private IRepository<JobItem>? _jobItems;
|
||||
private IRepository<JobItemCoat>? _jobItemCoats;
|
||||
private IJobItemCoatRepository? _jobItemCoats;
|
||||
private IRepository<JobItemPrepService>? _jobItemPrepServices;
|
||||
private IRepository<JobChangeHistory>? _jobChangeHistories;
|
||||
private IRepository<JobPrepService>? _jobPrepServices;
|
||||
@@ -59,13 +59,13 @@ public class UnitOfWork : IUnitOfWork
|
||||
private IRepository<QuoteItemPrepService>? _quoteItemPrepServices;
|
||||
private IRepository<QuoteChangeHistory>? _quoteChangeHistories;
|
||||
private IRepository<InventoryItem>? _inventoryItems;
|
||||
private IRepository<InventoryTransaction>? _inventoryTransactions;
|
||||
private IInventoryTransactionRepository? _inventoryTransactions;
|
||||
private IRepository<Equipment>? _equipment;
|
||||
private IRepository<OvenCost>? _ovenCosts;
|
||||
private IRepository<CompanyBlastSetup>? _blastSetups;
|
||||
private IRepository<MaintenanceRecord>? _maintenanceRecords;
|
||||
private IRepository<Vendor>? _vendors;
|
||||
private IRepository<JobPhoto>? _jobPhotos;
|
||||
private IJobPhotoRepository? _jobPhotos;
|
||||
private IRepository<JobNote>? _jobNotes;
|
||||
private IRepository<CustomerNote>? _customerNotes;
|
||||
private IRepository<JobStatusHistory>? _jobStatusHistory;
|
||||
@@ -97,13 +97,21 @@ public class UnitOfWork : IUnitOfWork
|
||||
private IRepository<SubscriptionPlanConfig>? _subscriptionPlanConfigs;
|
||||
|
||||
// Job Templates
|
||||
private IRepository<JobTemplate>? _jobTemplates;
|
||||
private IJobTemplateRepository? _jobTemplates;
|
||||
private IRepository<JobTemplateItem>? _jobTemplateItems;
|
||||
private IRepository<JobTemplateItemCoat>? _jobTemplateItemCoats;
|
||||
private IRepository<JobTemplateItemPrepService>? _jobTemplateItemPrepServices;
|
||||
|
||||
// Platform content
|
||||
private IPlainRepository<Announcement>? _announcements;
|
||||
private IPlainRepository<BannedIp>? _bannedIps;
|
||||
private IPlainRepository<DashboardTip>? _dashboardTips;
|
||||
private IRepository<InAppNotification>? _inAppNotifications;
|
||||
private IPlainRepository<ReleaseNote>? _releaseNotes;
|
||||
|
||||
// Bug Reports
|
||||
private IRepository<BugReport>? _bugReports;
|
||||
private IRepository<BugReportAttachment>? _bugReportAttachments;
|
||||
private IRepository<ContactSubmission>? _contactSubmissions;
|
||||
private IRepository<ManufacturerLookupPattern>? _manufacturerLookupPatterns;
|
||||
|
||||
@@ -169,8 +177,8 @@ public class UnitOfWork : IUnitOfWork
|
||||
|
||||
// Powder Insights
|
||||
/// <summary>Repository for <see cref="PowderUsageLog"/> records capturing per-coat powder consumption; used by powder-usage analytics.</summary>
|
||||
public IRepository<PowderUsageLog> PowderUsageLogs =>
|
||||
_powderUsageLogs ??= new Repository<PowderUsageLog>(_context);
|
||||
public IPowderUsageLogRepository PowderUsageLogs =>
|
||||
_powderUsageLogs ??= new PowderUsageLogRepository(_context);
|
||||
|
||||
// Core repositories
|
||||
/// <summary>Repository for <see cref="Customer"/> records (commercial and non-commercial); tenant-filtered with soft delete.</summary>
|
||||
@@ -190,8 +198,8 @@ public class UnitOfWork : IUnitOfWork
|
||||
_jobItems ??= new Repository<JobItem>(_context);
|
||||
|
||||
/// <summary>Repository for <see cref="JobItemCoat"/> powder coat passes; tenant-filtered with soft delete.</summary>
|
||||
public IRepository<JobItemCoat> JobItemCoats =>
|
||||
_jobItemCoats ??= new Repository<JobItemCoat>(_context);
|
||||
public IJobItemCoatRepository JobItemCoats =>
|
||||
_jobItemCoats ??= new JobItemCoatRepository(_context);
|
||||
public IRepository<JobItemPrepService> JobItemPrepServices =>
|
||||
_jobItemPrepServices ??= new Repository<JobItemPrepService>(_context);
|
||||
|
||||
@@ -232,8 +240,8 @@ public class UnitOfWork : IUnitOfWork
|
||||
_inventoryItems ??= new Repository<InventoryItem>(_context);
|
||||
|
||||
/// <summary>Repository for <see cref="InventoryTransaction"/> stock movements; tenant-filtered with soft delete.</summary>
|
||||
public IRepository<InventoryTransaction> InventoryTransactions =>
|
||||
_inventoryTransactions ??= new Repository<InventoryTransaction>(_context);
|
||||
public IInventoryTransactionRepository InventoryTransactions =>
|
||||
_inventoryTransactions ??= new InventoryTransactionRepository(_context);
|
||||
|
||||
/// <summary>Repository for <see cref="Equipment"/> records (ovens, sandblasters, booths); tenant-filtered with soft delete.</summary>
|
||||
public IRepository<Equipment> Equipment =>
|
||||
@@ -256,8 +264,8 @@ public class UnitOfWork : IUnitOfWork
|
||||
_vendors ??= new Repository<Vendor>(_context);
|
||||
|
||||
/// <summary>Repository for <see cref="JobPhoto"/> attachments; tenant-filtered with soft delete.</summary>
|
||||
public IRepository<JobPhoto> JobPhotos =>
|
||||
_jobPhotos ??= new Repository<JobPhoto>(_context);
|
||||
public IJobPhotoRepository JobPhotos =>
|
||||
_jobPhotos ??= new JobPhotoRepository(_context);
|
||||
|
||||
/// <summary>Repository for <see cref="JobNote"/> free-text staff notes on jobs; tenant-filtered with soft delete.</summary>
|
||||
public IRepository<JobNote> JobNotes =>
|
||||
@@ -372,11 +380,35 @@ public class UnitOfWork : IUnitOfWork
|
||||
public IRepository<SubscriptionPlanConfig> SubscriptionPlanConfigs =>
|
||||
_subscriptionPlanConfigs ??= new Repository<SubscriptionPlanConfig>(_context);
|
||||
|
||||
// Platform content
|
||||
/// <summary>Repository for <see cref="Announcement"/> platform-wide announcements; no tenant filter, no soft delete.</summary>
|
||||
public IPlainRepository<Announcement> Announcements =>
|
||||
_announcements ??= new PlainRepository<Announcement>(_context);
|
||||
|
||||
/// <summary>Repository for <see cref="BannedIp"/> IP ban records; no tenant filter, no soft delete.</summary>
|
||||
public IPlainRepository<BannedIp> BannedIps =>
|
||||
_bannedIps ??= new PlainRepository<BannedIp>(_context);
|
||||
|
||||
/// <summary>Repository for <see cref="DashboardTip"/> rotating tip-of-the-day entries; no tenant filter, no soft delete.</summary>
|
||||
public IPlainRepository<DashboardTip> DashboardTips =>
|
||||
_dashboardTips ??= new PlainRepository<DashboardTip>(_context);
|
||||
|
||||
/// <summary>Repository for <see cref="InAppNotification"/> bell-notification records; tenant-filtered with soft delete.</summary>
|
||||
public IRepository<InAppNotification> InAppNotifications =>
|
||||
_inAppNotifications ??= new Repository<InAppNotification>(_context);
|
||||
|
||||
/// <summary>Repository for <see cref="ReleaseNote"/> platform changelog entries; no tenant filter, no soft delete.</summary>
|
||||
public IPlainRepository<ReleaseNote> ReleaseNotes =>
|
||||
_releaseNotes ??= new PlainRepository<ReleaseNote>(_context);
|
||||
|
||||
// Bug Reports
|
||||
/// <summary>Repository for <see cref="BugReport"/> user-submitted bug reports; tenant-filtered with soft delete.</summary>
|
||||
public IRepository<BugReport> BugReports =>
|
||||
_bugReports ??= new Repository<BugReport>(_context);
|
||||
|
||||
public IRepository<BugReportAttachment> BugReportAttachments =>
|
||||
_bugReportAttachments ??= new Repository<BugReportAttachment>(_context);
|
||||
|
||||
// Contact Us
|
||||
/// <summary>Repository for <see cref="ContactSubmission"/> contact form submissions; platform admins see all, company users see their own.</summary>
|
||||
public IRepository<ContactSubmission> ContactSubmissions =>
|
||||
@@ -397,8 +429,8 @@ public class UnitOfWork : IUnitOfWork
|
||||
|
||||
// Job Templates
|
||||
/// <summary>Repository for <see cref="JobTemplate"/> reusable job blueprints; tenant-filtered with soft delete.</summary>
|
||||
public IRepository<JobTemplate> JobTemplates =>
|
||||
_jobTemplates ??= new Repository<JobTemplate>(_context);
|
||||
public IJobTemplateRepository JobTemplates =>
|
||||
_jobTemplates ??= new JobTemplateRepository(_context);
|
||||
|
||||
/// <summary>Repository for <see cref="JobTemplateItem"/> item definitions within a job template.</summary>
|
||||
public IRepository<JobTemplateItem> JobTemplateItems =>
|
||||
|
||||
Reference in New Issue
Block a user