Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions backend/src/routes/risk-score.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import express, { Response } from 'express';
import { riskDetectionService } from '../services/risk-detection/risk-detection-service';
import { riskNotificationService } from '../services/risk-detection/risk-notification-service';
import { authenticate, AuthenticatedRequest } from '../middleware/auth';
import { adminAuth } from '../middleware/admin';
import logger from '../config/logger';

const router = express.Router();
Expand Down Expand Up @@ -155,8 +156,10 @@ router.get('/', async (req: AuthenticatedRequest, res: Response) => {
* description: Recalculation result
* 401:
* description: Unauthorized
* 403:
* description: Forbidden - Admin access required
*/
router.post('/recalculate', async (req: AuthenticatedRequest, res: Response) => {
router.post('/recalculate', adminAuth, async (req: AuthenticatedRequest, res: Response) => {
try {
const userId = req.user?.id;

Expand All @@ -167,9 +170,6 @@ router.post('/recalculate', async (req: AuthenticatedRequest, res: Response) =>
});
}

// TODO: Add admin check
// For now, allow any authenticated user to trigger recalculation

logger.info('Manual risk recalculation triggered', { user_id: userId });

const result = await riskDetectionService.recalculateAllRisks();
Expand Down
19 changes: 11 additions & 8 deletions client/lib/security-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,16 @@ export class SessionManager {
}
}

// Secure storage wrapper
export const secureStorage = {
set(key: string, value: any): void {
// Base64-encoded localStorage wrapper.
// WARNING: This is NOT encryption. Values can be trivially decoded with atob().
// Do NOT use for API keys, tokens, passwords, or any sensitive data.
// For sensitive data, use server-side storage or the Web Crypto API.
export const encodedStorage = {
set(key: string, value: unknown): void {
if (typeof window === "undefined") return
try {
const encrypted = btoa(JSON.stringify(value))
localStorage.setItem(key, encrypted)
const encoded = btoa(JSON.stringify(value))
localStorage.setItem(key, encoded)
} catch (error) {
console.error("Failed to store data:", error)
}
Expand All @@ -182,9 +185,9 @@ export const secureStorage = {
get<T>(key: string): T | null {
if (typeof window === "undefined") return null
try {
const encrypted = localStorage.getItem(key)
if (!encrypted) return null
return JSON.parse(atob(encrypted)) as T
const encoded = localStorage.getItem(key)
if (!encoded) return null
return JSON.parse(atob(encoded)) as T
} catch (error) {
console.error("Failed to retrieve data:", error)
return null
Expand Down