Files
drone-detector/TENANT_LIMITS_IMPLEMENTATION.md
2025-09-23 13:55:10 +02:00

7.6 KiB

Tenant Limits Implementation

Overview

This document explains how tenant subscription limits are enforced in the UAM-ILS Drone Detection System. All the issues you identified have been resolved:

Issues Fixed

1. User Creation Limits

  • Problem: Tenants could create unlimited users regardless of their subscription limits
  • Solution: Added enforceUserLimit() middleware to POST /tenant/users
  • Implementation: Counts existing users and validates against tenant.features.max_users

2. Device Creation Limits

  • Problem: Tenants could add unlimited devices regardless of their subscription limits
  • Solution: Added enforceDeviceLimit() middleware to POST /devices
  • Implementation: Counts existing devices and validates against tenant.features.max_devices

3. API Rate Limiting

  • Problem: No proper API rate limiting per tenant shared among users
  • Solution: Implemented enforceApiRateLimit() middleware
  • Implementation:
    • Tracks actual API requests (not page views)
    • Rate limit is shared among ALL users in a tenant
    • Uses sliding window algorithm
    • Applied to all authenticated API endpoints

4. Data Retention

  • Problem: Old data was never cleaned up automatically
  • Solution: Created DataRetentionService with cron job
  • Implementation:
    • Runs daily at 2:00 AM UTC
    • Deletes detections, heartbeats, and logs older than tenant.features.data_retention_days
    • Respects unlimited retention (-1 value)
    • Provides preview endpoint to see what would be deleted

🔧 Technical Implementation

Middleware: server/middleware/tenant-limits.js

// User limit enforcement
enforceUserLimit() - Prevents user creation when limit reached
enforceDeviceLimit() - Prevents device creation when limit reached  
enforceApiRateLimit() - Rate limits API requests per tenant
getTenantLimitsStatus() - Returns current usage vs limits

Service: server/services/dataRetention.js

DataRetentionService {
  start() - Starts daily cron job
  performCleanup() - Cleans all tenants based on retention policies
  previewCleanup(tenantId) - Shows what would be deleted
  getStats() - Returns cleanup statistics
}

API Endpoints

GET /api/tenant/limits
# Returns current usage and limits for the tenant
{
  "users": { "current": 3, "limit": 5, "unlimited": false },
  "devices": { "current": 7, "limit": 10, "unlimited": false },
  "api_requests": { "current_minute": 45, "limit_per_minute": 1000 },
  "data_retention": { "days": 90, "unlimited": false }
}

GET /api/tenant/data-retention/preview
# Shows what data would be deleted by retention cleanup
{
  "tenantSlug": "tenant1",
  "retentionDays": 90,
  "cutoffDate": "2024-06-24T02:00:00.000Z",
  "toDelete": {
    "detections": 1250,
    "heartbeats": 4500,
    "logs": 89
  }
}

🚦 How Rate Limiting Works

API Rate Limiting Details

  • Granularity: Per tenant (shared among all users)
  • Window: 1 minute sliding window
  • Storage: In-memory with automatic cleanup
  • Headers: Standard rate limit headers included
  • Tracking: Only actual API requests count (not static files/page views)

Example Rate Limit Response

{
  "success": false,
  "message": "API rate limit exceeded. Maximum 1000 requests per 60 seconds for your tenant.",
  "error_code": "TENANT_API_RATE_LIMIT_EXCEEDED",
  "max_requests": 1000,
  "window_seconds": 60,
  "retry_after_seconds": 15
}

📊 Subscription Tiers

The system supports different subscription tiers with these default limits:

// Free tier
{
  max_devices: 2,
  max_users: 1,
  api_rate_limit: 100,
  data_retention_days: 7
}

// Pro tier  
{
  max_devices: 10,
  max_users: 5,
  api_rate_limit: 1000,
  data_retention_days: 90
}

// Business tier
{
  max_devices: 50,
  max_users: 20,
  api_rate_limit: 5000,
  data_retention_days: 365
}

// Enterprise tier
{
  max_devices: -1,    // Unlimited
  max_users: -1,      // Unlimited  
  api_rate_limit: -1, // Unlimited
  data_retention_days: -1 // Unlimited
}

🔒 Security Features

Limit Enforcement Security

  • All limit checks are done server-side (cannot be bypassed)
  • Security events are logged when limits are exceeded
  • Failed attempts include IP address, user agent, and user details
  • Graceful error messages prevent information disclosure

Error Response Format

{
  "success": false,
  "message": "Tenant has reached the maximum number of users (5). Please upgrade your subscription or remove existing users.",
  "error_code": "TENANT_USER_LIMIT_EXCEEDED",
  "current_count": 5,
  "max_allowed": 5
}

🕒 Data Retention Schedule

Cleanup Process

  1. Trigger: Daily at 2:00 AM UTC via cron job
  2. Process: For each active tenant:
    • Check tenant.features.data_retention_days
    • Skip if unlimited (-1)
    • Calculate cutoff date
    • Delete old detections, heartbeats, logs
    • Log security events for significant cleanups
  3. Performance: Batched operations with error handling per tenant

Manual Operations

// Preview what would be deleted
const service = new DataRetentionService();
const preview = await service.previewCleanup(tenantId);

// Manually trigger cleanup (admin only)
await service.triggerManualCleanup();

// Get cleanup statistics
const stats = service.getStats();

🔧 Docker Integration

Package Dependencies

Added to server/package.json:

{
  "dependencies": {
    "node-cron": "^3.0.2"
  }
}

Service Initialization

All services start automatically when the Docker container boots:

// In server/index.js
const dataRetentionService = new DataRetentionService();
dataRetentionService.start();
console.log('🗂️  Data retention service: ✅ Started');

🧪 Testing the Implementation

Test User Limits

# Create users until limit is reached
curl -X POST /api/tenant/users \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"username":"test6","email":"test6@example.com","password":"password"}'

# Should return 403 when limit exceeded

Test Device Limits

# Create devices until limit is reached  
curl -X POST /api/devices \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"id":"device-11","name":"Test Device 11"}'

# Should return 403 when limit exceeded

Test API Rate Limits

# Send rapid requests to trigger rate limit
for i in {1..1100}; do
  curl -X GET /api/detections -H "Authorization: Bearer $TOKEN" &
done

# Should return 429 after limit reached

Test Data Retention

# Preview what would be deleted
curl -X GET /api/tenant/data-retention/preview \
  -H "Authorization: Bearer $TOKEN"

# Check tenant limits status
curl -X GET /api/tenant/limits \
  -H "Authorization: Bearer $TOKEN"

📈 Monitoring & Logging

Security Logs

All limit violations are logged with full context:

  • User ID and username
  • Tenant ID and slug
  • IP address and user agent
  • Specific limit exceeded and current usage
  • Timestamp and action details

Performance Monitoring

  • Rate limit middleware tracks response times
  • Data retention service logs cleanup duration and counts
  • Memory usage monitoring for rate limit store
  • Database query performance for limit checks

🔄 Upgrade Path

When tenants upgrade their subscription:

  1. Update tenant.features with new limits
  2. Limits take effect immediately
  3. No restart required
  4. Historical data respects new retention policy on next cleanup

This comprehensive implementation ensures that tenant limits are properly enforced across all aspects of the system, preventing abuse while providing clear feedback to users about their subscription status.