adsasdasd
This commit is contained in:
453
SYSTEM-AUDIT-REPORT-2025-12-08.md
Normal file
453
SYSTEM-AUDIT-REPORT-2025-12-08.md
Normal file
@@ -0,0 +1,453 @@
|
||||
# Complete System Audit Report
|
||||
**Date:** December 8, 2025
|
||||
**Scope:** Full stack audit - Backend models, permissions, middleware, frontend, documentation
|
||||
**Status:** 🔴 CRITICAL ISSUES FOUND
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
### Overall System State: 🔴 BROKEN
|
||||
|
||||
Your multi-tenancy system has **5 CRITICAL ISSUES** that are causing widespread failures:
|
||||
|
||||
1. **Superuser Access Broken** - Session auth blocked on API, no bypass logic working
|
||||
2. **Permission System Contradictions** - Multiple conflicting permission classes
|
||||
3. **Missing Bypass Logic** - Superuser/developer checks removed from critical paths
|
||||
4. **Account Validation Too Strict** - Blocks all users including system accounts
|
||||
5. **Paid Plan Signup Missing** - No path for users to subscribe to paid plans
|
||||
|
||||
**Impact:** Neither regular tenants NOR superusers can access the application.
|
||||
|
||||
---
|
||||
|
||||
## Critical Issue #1: Superuser Access COMPLETELY BROKEN
|
||||
|
||||
### Problem
|
||||
Superusers cannot access the application at all due to conflicting middleware logic.
|
||||
|
||||
### Root Cause
|
||||
**File:** `backend/igny8_core/auth/middleware.py:35-41`
|
||||
|
||||
```python
|
||||
# Block superuser access via session on non-admin routes (JWT required)
|
||||
auth_header = request.META.get('HTTP_AUTHORIZATION', '')
|
||||
if request.user.is_superuser and not auth_header.startswith('Bearer '):
|
||||
logout(request)
|
||||
return JsonResponse(
|
||||
{'success': False, 'error': 'Session authentication not allowed for API. Use JWT.'},
|
||||
status=status.HTTP_403_FORBIDDEN,
|
||||
)
|
||||
```
|
||||
|
||||
**This blocks ALL superuser access** because:
|
||||
- Superusers login via Django admin (session-based)
|
||||
- Session cookies are sent to API automatically
|
||||
- Middleware detects superuser + no JWT = LOGOUT + 403 error
|
||||
- Even WITH JWT, there's no bypass logic downstream
|
||||
|
||||
### Evidence
|
||||
1. Middleware forces JWT-only for superusers
|
||||
2. No JWT generation on login (traditional Django session auth)
|
||||
3. Permission classes have `is_superuser` checks BUT middleware blocks before reaching them
|
||||
4. Admin panel uses session auth, but API rejects it
|
||||
|
||||
### Impact
|
||||
- Superusers cannot access ANY page in the app
|
||||
- Developer account cannot debug issues
|
||||
- System administration impossible
|
||||
|
||||
---
|
||||
|
||||
## Critical Issue #2: Permission System Has CONTRADICTIONS
|
||||
|
||||
### Problem
|
||||
Three different permission modules with conflicting logic:
|
||||
|
||||
#### Module A: `backend/igny8_core/auth/permissions.py`
|
||||
```python
|
||||
class IsOwnerOrAdmin(permissions.BasePermission):
|
||||
def has_permission(self, request, view):
|
||||
if getattr(user, "is_superuser", False):
|
||||
return True # ✅ Superuser allowed
|
||||
return user.role in ['owner', 'admin', 'developer']
|
||||
```
|
||||
|
||||
#### Module B: `backend/igny8_core/api/permissions.py`
|
||||
```python
|
||||
class HasTenantAccess(permissions.BasePermission):
|
||||
def has_permission(self, request, view):
|
||||
# NO superuser bypass ❌
|
||||
# Regular users must have account access
|
||||
if account:
|
||||
return user_account == account
|
||||
return False # Denies superusers without account match
|
||||
```
|
||||
|
||||
#### Module C: `backend/igny8_core/admin/base.py`
|
||||
```python
|
||||
class AccountAdminMixin:
|
||||
def get_queryset(self, request):
|
||||
if request.user.is_superuser or request.user.is_developer():
|
||||
return qs # ✅ Bypass for superuser/developer
|
||||
```
|
||||
|
||||
### The Contradiction
|
||||
- **auth/permissions.py** - Allows superuser bypass
|
||||
- **api/permissions.py** - NO superuser bypass (strict tenant-only)
|
||||
- **admin/base.py** - Allows superuser/developer bypass
|
||||
- **ViewSets** - Use MIXED permission classes from different modules
|
||||
|
||||
### Example of Broken ViewSet
|
||||
**File:** `backend/igny8_core/auth/views.py:144`
|
||||
|
||||
```python
|
||||
class UsersViewSet(AccountModelViewSet):
|
||||
permission_classes = [
|
||||
IsAuthenticatedAndActive, # From api/permissions - no bypass
|
||||
HasTenantAccess, # From api/permissions - no bypass
|
||||
IsOwnerOrAdmin # From auth/permissions - has bypass
|
||||
]
|
||||
```
|
||||
|
||||
**Result:** Permission denied because `HasTenantAccess` (2nd check) fails before `IsOwnerOrAdmin` (3rd check) runs.
|
||||
|
||||
### Impact
|
||||
- Inconsistent behavior across endpoints
|
||||
- Some endpoints work, some don't
|
||||
- Debugging is impossible - which permission is denying?
|
||||
|
||||
---
|
||||
|
||||
## Critical Issue #3: Account Validation TOO STRICT
|
||||
|
||||
### Problem
|
||||
Middleware validation blocks even system accounts and developers.
|
||||
|
||||
**File:** `backend/igny8_core/auth/middleware.py:148-170` + `auth/utils.py:133-195`
|
||||
|
||||
```python
|
||||
def _validate_account_and_plan(self, request, user):
|
||||
from .utils import validate_account_and_plan
|
||||
is_valid, error_message, http_status = validate_account_and_plan(user)
|
||||
if not is_valid:
|
||||
return self._deny_request(request, error_message, http_status)
|
||||
```
|
||||
|
||||
```python
|
||||
def validate_account_and_plan(user_or_account):
|
||||
account = getattr(user_or_account, 'account', None)
|
||||
if not account:
|
||||
return (False, 'Account not configured', 403)
|
||||
|
||||
if account.status in ['suspended', 'cancelled']:
|
||||
return (False, f'Account is {account.status}', 403)
|
||||
|
||||
plan = getattr(account, 'plan', None)
|
||||
if not plan:
|
||||
return (False, 'No subscription plan', 402)
|
||||
|
||||
if not plan.is_active:
|
||||
return (False, 'Active subscription required', 402)
|
||||
|
||||
return (True, None, None)
|
||||
```
|
||||
|
||||
### The Problem
|
||||
**NO bypass for:**
|
||||
- Superusers (is_superuser=True)
|
||||
- Developer role (role='developer')
|
||||
- System accounts (aws-admin, default-account)
|
||||
|
||||
Even the developer account (dev@igny8.com) gets blocked if:
|
||||
- Their account doesn't have a plan
|
||||
- Their plan is inactive
|
||||
- Their account status is suspended
|
||||
|
||||
### Impact
|
||||
- Cannot fix issues even with superuser access
|
||||
- System accounts get blocked
|
||||
- No emergency access path
|
||||
|
||||
---
|
||||
|
||||
## Critical Issue #4: Missing Bypass Logic in Core Components
|
||||
|
||||
### AccountModelViewSet - NO Bypass
|
||||
**File:** `backend/igny8_core/api/base.py:17-42`
|
||||
|
||||
```python
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
if hasattr(queryset.model, 'account'):
|
||||
# Filter by account
|
||||
if account:
|
||||
queryset = queryset.filter(account=account)
|
||||
else:
|
||||
return queryset.none() # ❌ Blocks everyone without account
|
||||
```
|
||||
|
||||
**Missing:**
|
||||
- No check for `is_superuser`
|
||||
- No check for `role='developer'`
|
||||
- No check for system accounts
|
||||
|
||||
### HasTenantAccess Permission - NO Bypass
|
||||
**File:** `backend/igny8_core/api/permissions.py:23-52`
|
||||
|
||||
```python
|
||||
class HasTenantAccess(permissions.BasePermission):
|
||||
def has_permission(self, request, view):
|
||||
# NO superuser bypass
|
||||
if account:
|
||||
return user_account == account
|
||||
return False # ❌ Denies superusers
|
||||
```
|
||||
|
||||
### Impact
|
||||
Every API endpoint using these base classes is broken for superusers.
|
||||
|
||||
---
|
||||
|
||||
## Critical Issue #5: Paid Plan Signup Path MISSING
|
||||
|
||||
### Problem
|
||||
Marketing page shows paid plans ($89, $139, $229) but all signup buttons go to free trial.
|
||||
|
||||
**File:** `tenancy-accounts-payments-still-have issues/PRICING-TO-PAID-SIGNUP-GAP.md`
|
||||
|
||||
### Gap Analysis
|
||||
- ✅ Free trial signup works
|
||||
- ❌ Paid plan signup does NOT exist
|
||||
- ❌ No payment page
|
||||
- ❌ No plan selection on signup
|
||||
- ❌ No payment method collection
|
||||
|
||||
### Missing Components
|
||||
1. Payment page UI (frontend)
|
||||
2. Plan parameter routing (/signup?plan=starter)
|
||||
3. Payment method selection
|
||||
4. Pending payment account creation
|
||||
5. Bank transfer confirmation flow
|
||||
|
||||
---
|
||||
|
||||
## Models & Database State
|
||||
|
||||
### ✅ What's Working
|
||||
1. **Models are well-designed:**
|
||||
- Account, User, Plan, Subscription, Site, Sector
|
||||
- Credit system (CreditTransaction, CreditUsageLog)
|
||||
- Payment/Invoice models exist
|
||||
- Proper relationships (ForeignKey, OneToOne)
|
||||
|
||||
2. **Database has data:**
|
||||
- 5 plans (free, starter, growth, scale, enterprise)
|
||||
- 8 accounts actively using system
|
||||
- 280+ credit transactions
|
||||
- Credit tracking working
|
||||
|
||||
3. **Soft delete implemented:**
|
||||
- SoftDeletableModel base class
|
||||
- Retention policies
|
||||
- Restore functionality
|
||||
|
||||
### ❌ What's Broken
|
||||
1. **Missing field in Account model:**
|
||||
- `payment_method` field defined in model but NOT in database (migration missing)
|
||||
|
||||
2. **Subscription table empty:**
|
||||
- No subscriptions exist despite Subscription model
|
||||
- Users operating on credits without subscription tracking
|
||||
|
||||
3. **Payment system incomplete:**
|
||||
- Models exist but no data
|
||||
- No payment gateway integration
|
||||
- No invoice generation in use
|
||||
|
||||
---
|
||||
|
||||
## Documentation Issues
|
||||
|
||||
### Problem: Scattered & Contradictory
|
||||
|
||||
**Three separate doc folders:**
|
||||
1. `master-docs/` - Structured, organized, but may be outdated
|
||||
2. `old-docs/` - Legacy docs, unclear what's still valid
|
||||
3. `tenancy-accounts-payments-still-have issues/` - Recent fixes, most accurate
|
||||
|
||||
### Contradictions Found
|
||||
1. **Superuser bypass:** Docs say it exists, code shows it was removed
|
||||
2. **Payment methods:** Docs describe manual payment flow, but frontend doesn't implement it
|
||||
3. **Plan allocation:** Docs show complex fallback logic, implementation shows it was simplified
|
||||
4. **Session auth:** Docs don't mention JWT requirement for API
|
||||
|
||||
### Missing from Docs
|
||||
1. Current state of superuser access (broken)
|
||||
2. Which permission module is canonical
|
||||
3. Middleware validation rules
|
||||
4. Account.payment_method migration status
|
||||
|
||||
---
|
||||
|
||||
## Frontend Analysis
|
||||
|
||||
### ✅ Frontend Code Quality: GOOD
|
||||
- Well-structured React/TypeScript
|
||||
- Proper state management (Zustand)
|
||||
- Error handling hooks exist
|
||||
- API service layer organized
|
||||
|
||||
### ❌ Frontend Issues
|
||||
1. **No paid plan signup page** - Missing `/payment` route
|
||||
2. **No error display for permission denied** - Silent failures
|
||||
3. **No JWT token generation** - Still using session auth
|
||||
4. **No superuser indicator** - Users don't know why access is denied
|
||||
|
||||
---
|
||||
|
||||
## ROOT CAUSE ANALYSIS
|
||||
|
||||
### Timeline of What Happened
|
||||
|
||||
1. **Initially:** Superuser had full bypass, everything worked
|
||||
2. **Tenancy work started:** Added strict tenant isolation
|
||||
3. **Security concern:** Removed some bypass logic to prevent session contamination
|
||||
4. **Over-correction:** Removed TOO MUCH bypass logic
|
||||
5. **Now:** Neither tenants nor superusers can access anything
|
||||
|
||||
### The Core Problem
|
||||
|
||||
**Attempted to fix security issue but broke fundamental access:**
|
||||
- Session contamination IS a real issue
|
||||
- JWT-only for API IS correct approach
|
||||
- BUT: Removed all bypass logic instead of fixing authentication method
|
||||
- AND: Middleware blocks before permission classes can allow bypass
|
||||
|
||||
---
|
||||
|
||||
## RECOMMENDATIONS
|
||||
|
||||
I have **TWO OPTIONS** for you:
|
||||
|
||||
### Option 1: QUICK FIX (2-4 hours) ⚡
|
||||
**Restore superuser access immediately, patch critical flows**
|
||||
|
||||
**Pros:**
|
||||
- Fastest path to working system
|
||||
- Superuser can access app today
|
||||
- Tenant system keeps working
|
||||
|
||||
**Cons:**
|
||||
- Technical debt remains
|
||||
- Documentation still messy
|
||||
- Some inconsistencies persist
|
||||
|
||||
**What gets fixed:**
|
||||
1. Add superuser bypass to middleware
|
||||
2. Add developer role bypass to HasTenantAccess
|
||||
3. Add system account bypass to AccountModelViewSet
|
||||
4. Generate JWT tokens on login
|
||||
5. Update frontend to use JWT
|
||||
|
||||
**Estimated time:** 2-4 hours
|
||||
**Effort:** LOW
|
||||
**Risk:** LOW
|
||||
|
||||
---
|
||||
|
||||
### Option 2: PROPER REBUILD (2-3 days) 🏗️
|
||||
**Redesign tenancy system with clean architecture**
|
||||
|
||||
**Pros:**
|
||||
- Clean, maintainable code
|
||||
- Consistent permission logic
|
||||
- Proper documentation
|
||||
- All flows working correctly
|
||||
- Future-proof architecture
|
||||
|
||||
**Cons:**
|
||||
- Takes 2-3 days
|
||||
- Requires careful testing
|
||||
- Must migrate existing data
|
||||
|
||||
**What gets rebuilt:**
|
||||
1. **Unified permission system** - One module, clear hierarchy
|
||||
2. **Clean middleware** - Proper bypass logic for all roles
|
||||
3. **JWT authentication** - Token generation + refresh
|
||||
4. **Paid plan signup** - Complete payment flow
|
||||
5. **Consolidated docs** - Single source of truth
|
||||
6. **Account migration** - Add missing payment_method field
|
||||
7. **Subscription system** - Link accounts to subscriptions
|
||||
8. **Test suite** - Cover all permission scenarios
|
||||
|
||||
**Estimated time:** 2-3 days
|
||||
**Effort:** MEDIUM
|
||||
**Risk:** MEDIUM (with proper testing)
|
||||
|
||||
---
|
||||
|
||||
## MY RECOMMENDATION
|
||||
|
||||
### Start with Option 1 (Quick Fix), then Option 2
|
||||
|
||||
**Why:**
|
||||
1. You need access NOW - can't wait 3 days
|
||||
2. Quick fix restores functionality in hours
|
||||
3. Then properly rebuild when system is accessible
|
||||
4. Less risk - incremental improvement
|
||||
|
||||
**Action Plan:**
|
||||
1. **NOW:** Quick fix (2-4 hours) - restore superuser access
|
||||
2. **Tomorrow:** Test all flows, document issues
|
||||
3. **Next 2-3 days:** Proper rebuild with clean architecture
|
||||
4. **End result:** Production-ready multi-tenancy system
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
**Please confirm which option you want:**
|
||||
|
||||
**Option A:** Quick fix now (I'll start immediately)
|
||||
**Option B:** Full rebuild (2-3 days, but cleaner)
|
||||
**Option C:** Quick fix now + full rebuild after (RECOMMENDED)
|
||||
|
||||
Once you confirm, I'll begin implementation with detailed progress updates.
|
||||
|
||||
---
|
||||
|
||||
## File Inventory (Issues Found)
|
||||
|
||||
### Backend Files with Issues
|
||||
1. ✅ `/backend/igny8_core/auth/middleware.py` - Blocks superusers
|
||||
2. ✅ `/backend/igny8_core/auth/utils.py` - No bypass in validation
|
||||
3. ✅ `/backend/igny8_core/api/permissions.py` - No superuser bypass
|
||||
4. ✅ `/backend/igny8_core/api/base.py` - No bypass in queryset filter
|
||||
5. ⚠️ `/backend/igny8_core/auth/models.py` - Missing payment_method migration
|
||||
6. ✅ `/backend/igny8_core/auth/views.py` - Mixed permission classes
|
||||
|
||||
### Frontend Files with Issues
|
||||
7. ⚠️ `/frontend/src/services/api.ts` - No JWT token handling
|
||||
8. ❌ `/frontend/src/pages/Payment.tsx` - MISSING (paid signup)
|
||||
9. ⚠️ `/frontend/src/components/auth/SignUpForm.tsx` - No plan parameter
|
||||
|
||||
### Documentation Issues
|
||||
10. ⚠️ `master-docs/` - May be outdated
|
||||
11. ⚠️ `old-docs/` - Unclear what's valid
|
||||
12. ✅ `tenancy-accounts-payments-still-have issues/` - Most accurate
|
||||
|
||||
**Legend:**
|
||||
- ✅ = Critical issue, must fix
|
||||
- ⚠️ = Important but not blocking
|
||||
- ❌ = Missing component
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
Your system has **good architecture** but **broken implementation** due to over-correction during security fixes. The models are solid, the database is working, but the permission/access layer is preventing anyone (including you) from using the app.
|
||||
|
||||
**The good news:** This is fixable in a few hours with targeted changes.
|
||||
|
||||
**Waiting for your decision on which option to proceed with...**
|
||||
Reference in New Issue
Block a user