fix(backend): route alerts admin scoping through isTradingAdmin

Made-with: Cursor
This commit is contained in:
Saravana Achu Mac 2026-04-04 18:58:06 -07:00
parent b306f3264e
commit 12cedd12da
2 changed files with 7 additions and 3 deletions

View File

@ -9,7 +9,6 @@ import path from 'path';
import { ManualTrader } from './ManualTrader.js';
import { applyDynamicConfigEntries, config, loadDynamicConfig } from '../config/index.js';
import { AIClient } from './aiClient.js';
import { supabaseService } from './SupabaseService.js';
import { healthTracker, HealthSnapshot, TradingControlSnapshot } from './healthTracker.js';
import { observabilityService } from './observabilityService.js';
import { isTradingAdmin, verifyTradingAccessToken } from './platformAuthService.js';
@ -1438,13 +1437,14 @@ export class ApiServer {
});
this.app.get('/api/alerts', this.requireAuth, async (req, res) => {
const authUserId = (req as AuthenticatedRequest).authUserId;
const authReq = req as AuthenticatedRequest;
const authUserId = authReq.authUserId;
if (!authUserId) {
res.status(401).json({ error: 'Unauthorized' });
return;
}
const limit = parseInt(req.query.limit as string) || 50;
const isAdmin = await supabaseService.isAdmin(authUserId);
const isAdmin = await isTradingAdmin(authUserId, authReq.authRole);
const scopedState = this.getScopedState(authUserId, isAdmin);
const alerts = scopedState.alerts;
res.json(alerts.slice(-limit));

View File

@ -98,6 +98,10 @@ export async function verifyTradingAccessToken(token: string): Promise<VerifiedT
};
}
/**
* Authoritative admin check for trading API scoping: platform JWT role first, then legacy user-store admin flag.
* Call sites should use this instead of SupabaseService.isAdmin so platform sessions stay consistent.
*/
export async function isTradingAdmin(userId: string, tokenRole?: string | null): Promise<boolean> {
const normalizedRole = normalizeRole(tokenRole);
if (normalizedRole === 'admin' || normalizedRole === 'super_admin') {