agmission/server/docs/archived/PARTNER_AUTH_REFACTORING_VISUAL.md

336 lines
18 KiB
Markdown

# Partner Authentication Refactoring - Visual Guide
## Before vs After Architecture
### ❌ Before Refactoring
```
┌──────────────────────────────────────────────────────────┐
│ testPartnerAuth_post() Controller │
│ (Testing authentication) │
└────────────────────┬─────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ authenticateAndCache() │
│ ┌────────────────────────────────────────────┐ │
│ │ 1. Make API call to SatLoc │ │
│ │ 2. Validate response │ │
│ │ 3. Build auth data │ │
│ │ 4. Cache in Redis ← ⚠️ SIDE EFFECT │ │
│ │ 5. Return auth data │ │
│ └────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
┌────────────────┐
│ Redis Cache │ ← ⚠️ Polluted during testing
└────────────────┘
⚠️ Problems:
- Testing pollutes cache
- Tight coupling of concerns
- Side effects in test endpoints
```
### ✅ After Refactoring
```
┌──────────────────────────────────────────────────────────┐
│ testPartnerAuth_post() Controller │
│ (Testing authentication) │
└────────────────────┬─────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ authenticate() │
│ ┌────────────────────────────────────────────┐ │
│ │ 1. Make API call to SatLoc │ │
│ │ 2. Validate response │ │
│ │ 3. Build auth data │ │
│ │ 4. Return auth data │ │
│ │ │ │
│ │ ✅ NO CACHING - Pure function │ │
│ └────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ Production Flow │
└────────────────────┬─────────────────────────────────────┘
┌──────────────────────────────────────────────────────────┐
│ authenticateAndCache() │
│ ┌────────────────────────────────────────────┐ │
│ │ 1. Call authenticate() ← REUSES │ │
│ │ 2. Cache result in Redis │ │
│ │ 3. Return auth data │ │
│ └────────────────────────────────────────────┘ │
└──────────────────────┬───────────────────────────────────┘
┌────────────────┐
│ Redis Cache │ ← ✅ Only cached in production
└────────────────┘
✅ Benefits:
- Separation of concerns
- No cache pollution during testing
- Code reusability
- Single source of truth
```
## Method Comparison
### authenticate() - Pure Authentication
```
┌─────────────────────────────────────────────┐
│ authenticate(credentials) │
├─────────────────────────────────────────────┤
│ │
│ INPUT: │
│ • credentials { username, password } │
│ • customerId (for logging) │
│ │
│ PROCESS: │
│ 1. Call SatLoc API /AuthenticateAPIUser │
│ 2. Parse response │
│ 3. Build auth data structure │
│ 4. Return auth data │
│ │
│ OUTPUT: │
│ { │
│ userId: "...", │
│ companyId: "...", │
│ expiresAt: 1234567890, │
│ lastHealthCheck: 1234567890, │
│ originalResponse: {...} │
│ } │
│ │
│ SIDE EFFECTS: None ✅ │
│ │
└─────────────────────────────────────────────┘
```
### authenticateAndCache() - With Caching
```
┌─────────────────────────────────────────────┐
│ authenticateAndCache(credentials) │
├─────────────────────────────────────────────┤
│ │
│ INPUT: │
│ • credentials { username, password } │
│ • customerId (for caching key) │
│ │
│ PROCESS: │
│ 1. Call authenticate() ← REUSES │
│ └─ Returns auth data │
│ 2. Calculate TTL from expiresAt │
│ 3. Store in Redis with TTL │
│ 4. Return auth data │
│ │
│ OUTPUT: │
│ { │
│ userId: "...", │
│ companyId: "...", │
│ expiresAt: 1234567890, │
│ lastHealthCheck: 1234567890, │
│ originalResponse: {...} │
│ } │
│ │
│ SIDE EFFECTS: │
│ • Stores auth data in Redis ✅ │
│ • Sets TTL on cache entry ✅ │
│ │
└─────────────────────────────────────────────┘
```
## Usage Decision Tree
```
Need to authenticate?
┌───────────────────────┐
│ What's the use case? │
└───────────┬───────────┘
┌───────────────┼───────────────┐
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ Testing? │ │ Production? │
│ Validation? │ │ Normal flow? │
└───────┬───────┘ └───────┬───────┘
│ │
▼ ▼
┌────────────────────┐ ┌────────────────────┐
│ authenticate() │ │authenticateAndCache│
│ │ │ │
│ ✅ No caching │ │ ✅ With caching │
│ ✅ Pure function │ │ ✅ Reuses auth() │
│ ✅ For testing │ │ ✅ For production │
└────────────────────┘ └────────────────────┘
```
## Code Examples
### Example 1: Testing Endpoint
```javascript
// controllers/partner.js
async function testPartnerAuth_post(req, res) {
const { customerId, partnerId, username, password } = req.body;
// Validate partner system user
const partnerSystemUser = await findAndValidatePartnerSystemUser(
customerId, partnerId, { requireActive: true, username, password }
);
// Get partner service
const partnerService = partnerServiceFactory.getService(partnerCode);
const credentials = partnerConfig.getApiCredentials(partnerSystemUser, partnerCode);
// ✅ Use authenticate() - no caching for testing
const authResult = await partnerService.authenticate(credentials, customerId);
res.json({
authSuccess: true,
userId: authResult.userId,
companyId: authResult.companyId
});
}
```
### Example 2: Production Flow
```javascript
// services/partner_sync_service.js
async function syncPartnerData(customerId, partnerId) {
const partnerService = partnerServiceFactory.getService('SATLOC');
const credentials = getCredentials(customerId);
// ✅ Use authenticateAndCache() - with caching for production
const authData = await partnerService.authenticateAndCache(credentials, customerId);
// Use authData for API calls
const aircraftList = await partnerService.getAircraftList(authData);
return aircraftList;
}
```
### Example 3: Getting Cached or Fresh Auth
```javascript
// services/satloc_service.js
async getApiCredentials(credentials, customerId) {
// Check cache first
const cached = await this.cache.getAuth(this.partnerCode, customerId);
if (cached && cached.expiresAt > Date.now()) {
// ✅ Return cached auth
return cached;
}
// Cache miss - authenticate and cache
// ✅ Uses authenticateAndCache() internally
const authData = await this.authenticateAndCache(credentials, customerId);
return authData;
}
```
## Sequence Diagrams
### Testing Flow (No Caching)
```
┌──────────┐ ┌────────────┐ ┌─────────┐ ┌───────────┐
│ Client │ │ Controller │ │ Service │ │ SatLoc API│
└────┬─────┘ └─────┬──────┘ └────┬────┘ └─────┬─────┘
│ │ │ │
│ POST testAuth │ │ │
│──────────────>│ │ │
│ │ │ │
│ │ authenticate()│ │
│ │──────────────>│ │
│ │ │ │
│ │ │ GET /Auth... │
│ │ │─────────────>│
│ │ │ │
│ │ │ Success │
│ │ │<─────────────│
│ │ │ │
│ │ authData │ │
│ │<──────────────│ │
│ │ │ │
│ 200 OK │ │ │
│<──────────────│ │ │
│ │ │ │
✅ NO CACHE OPERATIONS - Clean test
```
### Production Flow (With Caching)
```
┌──────────┐ ┌─────────┐ ┌─────────┐ ┌───────────┐ ┌───────┐
│ Sync Job │ │ Service │ │ Service │ │ SatLoc API│ │ Redis │
└────┬─────┘ └────┬────┘ └────┬────┘ └─────┬─────┘ └───┬───┘
│ │ │ │ │
│ sync data │ │ │ │
│─────────────>│ │ │ │
│ │ │ │ │
│ │authenticateAn│ │ │
│ │dCache() │ │ │
│ │─────────────>│ │ │
│ │ │ │ │
│ │ │authenticate()│ │
│ │ │─────────────>│ │
│ │ │ │ │
│ │ │ GET /Auth... │ │
│ │ │─────────────>│ │
│ │ │ │ │
│ │ │ Success │ │
│ │ │<─────────────│ │
│ │ │ │ │
│ │ │ authData │ │
│ │ │<─────────────│ │
│ │ │ │ │
│ │ │ setAuth() │ │
│ │ │──────────────────────────>│
│ │ │ │ │
│ │ │ OK │ │
│ │ │<──────────────────────────│
│ │ │ │ │
│ │ authData │ │ │
│ │<─────────────│ │ │
│ │ │ │ │
│ data synced │ │ │ │
│<─────────────│ │ │ │
│ │ │ │ │
✅ CACHED FOR REUSE - Efficient production flow
```
## Benefits Summary
| Aspect | Before | After |
|--------|--------|-------|
| **Test Isolation** | ❌ Tests pollute cache | ✅ Tests are isolated |
| **Code Reuse** | ❌ Duplicated logic | ✅ Shared authenticate() |
| **Maintainability** | ❌ Coupled concerns | ✅ Separated concerns |
| **Debugging** | ❌ Cache interference | ✅ Clear flow |
| **Performance** | ❌ Unnecessary caching | ✅ Cache only when needed |
| **Testing** | ❌ Complex mocking | ✅ Simple unit tests |
---
This refactoring provides a cleaner, more maintainable architecture while maintaining full backward compatibility!