From 37cc1b2acbf21ceb996639140ab328423b14c37c Mon Sep 17 00:00:00 2001 From: admtracksteel Date: Thu, 19 Mar 2026 22:05:47 +0000 Subject: [PATCH] refactor: Standardize user and organization ID properties, update Vite proxy port, and refactor data sheet file serving. --- src/client/context/AuthContext.tsx | 2 +- src/client/main.tsx | 4 +++- .../applicationRecordController.ts | 6 ++--- src/server/controllers/authController.ts | 3 +-- src/server/controllers/dataSheetController.ts | 18 +++++--------- .../controllers/inspectionController.ts | 6 ++--- src/server/controllers/messageController.ts | 14 +++++------ src/server/controllers/stockController.ts | 24 +++++++++---------- src/server/services/notificationService.ts | 12 ++++++++++ vite.config.ts | 4 ++-- 10 files changed, 50 insertions(+), 43 deletions(-) diff --git a/src/client/context/AuthContext.tsx b/src/client/context/AuthContext.tsx index 392f1e3..07a73b9 100644 --- a/src/client/context/AuthContext.tsx +++ b/src/client/context/AuthContext.tsx @@ -34,7 +34,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children const fetchTokenAndUser = async () => { if (isAuthenticated) { try { - const accessToken = await getAccessToken(); + const accessToken = await getAccessToken(import.meta.env.VITE_LOGTO_RESOURCE || 'https://gpi.reifonas.cloud/api'); if (accessToken) { setToken(accessToken); setApiToken(accessToken); diff --git a/src/client/main.tsx b/src/client/main.tsx index e9a845b..1a39c5f 100644 --- a/src/client/main.tsx +++ b/src/client/main.tsx @@ -7,7 +7,9 @@ import type { LogtoConfig } from '@logto/react'; // Require the user to define VITE_LOGTO_APP_ID in Coolify const config: LogtoConfig = { endpoint: 'https://logto.reifonas.cloud', - appId: import.meta.env.VITE_LOGTO_APP_ID || '', // Replace or add via Envs! + appId: import.meta.env.VITE_LOGTO_APP_ID || '', + scopes: ['email', 'profile', 'organizations'], + resources: [import.meta.env.VITE_LOGTO_RESOURCE || 'https://gpi.reifonas.cloud/api'], }; // Force service worker cache clearing because of persistent Clerk error diff --git a/src/server/controllers/applicationRecordController.ts b/src/server/controllers/applicationRecordController.ts index 8f16f19..fd3cd72 100644 --- a/src/server/controllers/applicationRecordController.ts +++ b/src/server/controllers/applicationRecordController.ts @@ -5,7 +5,7 @@ import '../middleware/roleMiddleware.js'; // Ensure type augmentation export const createApplicationRecord = async (req: Request, res: Response) => { try { const organizationId = req.appUser?.organizationId; - const createdBy = req.appUser?.externalId; + const createdBy = req.appUser?.id; const record = await appRecordService.createApplicationRecord({ ...req.body, organizationId, createdBy }); res.status(201).json(record); } catch (error: unknown) { @@ -29,7 +29,7 @@ export const getApplicationRecordsByProject = async (req: Request, res: Response export const updateApplicationRecord = async (req: Request, res: Response) => { try { const organizationId = req.appUser?.organizationId; - const userId = req.appUser?.externalId; + const userId = req.appUser?.id; const userRole = req.appUser?.organizationRole || req.appUser?.role; const isDeveloper = req.appUser?.email === 'admtracksteel@gmail.com'; @@ -52,7 +52,7 @@ export const updateApplicationRecord = async (req: Request, res: Response) => { export const deleteApplicationRecord = async (req: Request, res: Response) => { try { const organizationId = req.appUser?.organizationId; - const userId = req.appUser?.externalId; + const userId = req.appUser?.id; const userRole = req.appUser?.organizationRole || req.appUser?.role; const isDeveloper = req.appUser?.email === 'admtracksteel@gmail.com'; diff --git a/src/server/controllers/authController.ts b/src/server/controllers/authController.ts index 20fa20d..8a6ff46 100644 --- a/src/server/controllers/authController.ts +++ b/src/server/controllers/authController.ts @@ -115,11 +115,10 @@ export const getMe = async (req: Request, res: Response): Promise => { } res.status(200).json({ - id: req.appUser._id, + id: req.appUser.id, name: req.appUser.name, email: req.appUser.email, role: req.appUser.role, - externalId: req.appUser.externalId, organizationId: req.appUser.organizationId }); } catch (error) { diff --git a/src/server/controllers/dataSheetController.ts b/src/server/controllers/dataSheetController.ts index 54d9e29..f6cccad 100644 --- a/src/server/controllers/dataSheetController.ts +++ b/src/server/controllers/dataSheetController.ts @@ -267,18 +267,12 @@ export const getFile = async (req: Request, res: Response) => { } // Fallback to file system (legacy) - const stream = dataSheetService.getFileStream(id_or_filename); - - stream.on('file', (file) => { - res.set('Content-Type', 'application/pdf'); - res.set('Content-Disposition', `inline; filename="${file.filename}"`); - }); - - stream.on('error', () => { - res.status(404).json({ error: 'File not found' }); - }); - - stream.pipe(res); + const file = await dataSheetService.getFileStream(id_or_filename); + res.set('Content-Type', file.content_type || 'application/pdf'); + res.set('Content-Disposition', `inline; filename="${file.filename}"`); + res.set('Access-Control-Allow-Origin', '*'); + res.set('Cache-Control', 'public, max-age=3600'); + res.send(file.data); } catch (error: unknown) { const message = error instanceof Error ? error.message : 'Unknown error'; console.error('Error getting file:', error); diff --git a/src/server/controllers/inspectionController.ts b/src/server/controllers/inspectionController.ts index fefe91d..0a0dc48 100644 --- a/src/server/controllers/inspectionController.ts +++ b/src/server/controllers/inspectionController.ts @@ -6,7 +6,7 @@ import '../middleware/roleMiddleware.js'; // Ensure type augmentation export const createInspection = async (req: Request, res: Response) => { try { const organizationId = req.appUser?.organizationId; - const createdBy = req.appUser?.externalId; + const createdBy = req.appUser?.id; const inspection = await inspectionService.createInspection({ ...req.body, organizationId, @@ -46,7 +46,7 @@ export const getInspectionsByProject = async (req: Request, res: Response) => { export const updateInspection = async (req: Request, res: Response) => { try { const organizationId = req.appUser?.organizationId; - const userId = req.appUser?.externalId; + const userId = req.appUser?.id; const userRole = req.appUser?.organizationRole || req.appUser?.role; const isDeveloper = req.appUser?.email === 'admtracksteel@gmail.com'; @@ -69,7 +69,7 @@ export const updateInspection = async (req: Request, res: Response) => { export const deleteInspection = async (req: Request, res: Response) => { try { const organizationId = req.appUser?.organizationId; - const userId = req.appUser?.externalId; + const userId = req.appUser?.id; const userRole = req.appUser?.organizationRole || req.appUser?.role; const isDeveloper = req.appUser?.email === 'admtracksteel@gmail.com'; diff --git a/src/server/controllers/messageController.ts b/src/server/controllers/messageController.ts index 0c7ec25..a8af1c4 100644 --- a/src/server/controllers/messageController.ts +++ b/src/server/controllers/messageController.ts @@ -6,7 +6,7 @@ import OrganizationMember from '../models/OrganizationMember.js'; export const sendMessage = async (req: Request, res: Response) => { try { const { toUserId, message } = req.body; - const fromUserId = req.appUser?.externalId; + const fromUserId = req.appUser?.id; const organizationId = req.headers['x-organization-id'] as string; if (!organizationId) { @@ -60,7 +60,7 @@ export const sendMessage = async (req: Request, res: Response) => { // Get unread messages for current user export const getUnreadMessages = async (req: Request, res: Response) => { try { - const toUserId = req.appUser?.externalId; + const toUserId = req.appUser?.id; const organizationId = req.headers['x-organization-id'] as string; if (!organizationId) { @@ -101,7 +101,7 @@ export const getUnreadMessages = async (req: Request, res: Response) => { export const markMessageAsRead = async (req: Request, res: Response) => { try { const { id } = req.params; - const userId = req.appUser?.externalId; + const userId = req.appUser?.id; const organizationId = req.headers['x-organization-id'] as string; if (!organizationId) { @@ -136,7 +136,7 @@ export const markMessageAsRead = async (req: Request, res: Response) => { // Get my pending (unread) sent messages export const getMyPendingMessages = async (req: Request, res: Response) => { try { - const fromUserId = req.appUser?.externalId; + const fromUserId = req.appUser?.id; const organizationId = req.headers['x-organization-id'] as string; if (!organizationId) { @@ -175,7 +175,7 @@ export const getMyPendingMessages = async (req: Request, res: Response) => { export const deleteMessage = async (req: Request, res: Response) => { try { const { id } = req.params; - const userId = req.appUser?.externalId; + const userId = req.appUser?.id; const organizationId = req.headers['x-organization-id'] as string; if (!organizationId) { @@ -209,7 +209,7 @@ export const deleteMessage = async (req: Request, res: Response) => { export const archiveMessage = async (req: Request, res: Response) => { try { const { id } = req.params; - const userId = req.appUser?.externalId; + const userId = req.appUser?.id; const organizationId = req.headers['x-organization-id'] as string; const message = await Message.findOne({ _id: id, toUserId: userId, organizationId }); @@ -228,7 +228,7 @@ export const archiveMessage = async (req: Request, res: Response) => { export const recipientDeleteMessage = async (req: Request, res: Response) => { try { const { id } = req.params; - const userId = req.appUser?.externalId; + const userId = req.appUser?.id; const organizationId = req.headers['x-organization-id'] as string; const message = await Message.findOne({ _id: id, toUserId: userId, organizationId }); diff --git a/src/server/controllers/stockController.ts b/src/server/controllers/stockController.ts index 7cca743..b696da2 100644 --- a/src/server/controllers/stockController.ts +++ b/src/server/controllers/stockController.ts @@ -9,7 +9,7 @@ interface AuthRequest extends Request { export const createStockItem = async (req: AuthRequest, res: Response) => { try { - const organizationId = req.appUser?.organization_id; + const organizationId = req.appUser?.organizationId; const userName = req.appUser?.name || req.appUser?.email || 'Unknown User'; const { dataSheetId, @@ -97,7 +97,7 @@ export const createStockItem = async (req: AuthRequest, res: Response) => { export const updateStockItem = async (req: AuthRequest, res: Response) => { try { const { id } = req.params; - const organizationId = req.appUser?.organization_id; + const organizationId = req.appUser?.organizationId; const { quantity, ...otherData } = req.body; if (quantity !== undefined) { @@ -118,7 +118,7 @@ export const updateStockItem = async (req: AuthRequest, res: Response) => { const updated = await stockService.updateStockItem(id as string, otherData, organizationId); if (!updated) return res.status(404).json({ error: 'Item não encontrado.' }); - await notificationService.checkLowStock(id); + await notificationService.checkLowStock(id as string); res.json(updated); } catch (error: any) { res.status(500).json({ error: error.message }); @@ -128,7 +128,7 @@ export const updateStockItem = async (req: AuthRequest, res: Response) => { export const adjustStock = async (req: AuthRequest, res: Response) => { try { const { id } = req.params; - const organizationId = req.appUser?.organization_id; + const organizationId = req.appUser?.organizationId; const { quantityDelta, reason } = req.body; if (!reason) return res.status(400).json({ error: 'Motivo é obrigatório para ajustes técnicos.' }); @@ -143,7 +143,7 @@ export const adjustStock = async (req: AuthRequest, res: Response) => { reason }); - await notificationService.checkLowStock(id); + await notificationService.checkLowStock(id as string); res.json(adjustment); } catch (error: any) { res.status(500).json({ error: error.message }); @@ -153,7 +153,7 @@ export const adjustStock = async (req: AuthRequest, res: Response) => { export const consumeStock = async (req: AuthRequest, res: Response) => { try { const { id } = req.params; - const organizationId = req.appUser?.organization_id; + const organizationId = req.appUser?.organizationId; const { quantityConsumed, requester, date } = req.body; if (!requester) return res.status(400).json({ error: 'Solicitante é obrigatório.' }); @@ -168,7 +168,7 @@ export const consumeStock = async (req: AuthRequest, res: Response) => { reason: `Consumo por ${requester}` }); - await notificationService.checkLowStock(id); + await notificationService.checkLowStock(id as string); res.json({ message: 'Consumo registrado com sucesso.' }); } catch (error: any) { res.status(500).json({ error: error.message }); @@ -178,7 +178,7 @@ export const consumeStock = async (req: AuthRequest, res: Response) => { export const deleteStockItem = async (req: AuthRequest, res: Response) => { try { const { id } = req.params; - const organizationId = req.appUser?.organization_id; + const organizationId = req.appUser?.organizationId; await stockService.deleteStockItem(id as string, organizationId); res.status(204).send(); } catch (error: any) { @@ -188,7 +188,7 @@ export const deleteStockItem = async (req: AuthRequest, res: Response) => { export const getStockItems = async (req: AuthRequest, res: Response) => { try { - const organizationId = req.appUser?.organization_id; + const organizationId = req.appUser?.organizationId; const items = await stockService.getStockItems(organizationId); res.json(items); } catch (error: any) { @@ -199,7 +199,7 @@ export const getStockItems = async (req: AuthRequest, res: Response) => { export const getStockItemById = async (req: AuthRequest, res: Response) => { try { const { id } = req.params; - const organizationId = req.appUser?.organization_id; + const organizationId = req.appUser?.organizationId; const result = await query( `SELECT si.*, tds.name as data_sheet_name FROM stock_items si @@ -217,8 +217,8 @@ export const getStockItemById = async (req: AuthRequest, res: Response) => { export const getStockMovements = async (req: AuthRequest, res: Response) => { try { const { id } = req.params; - const organizationId = req.appUser?.organization_id; - const movements = await stockService.getMovementsByItem(id, organizationId); + const organizationId = req.appUser?.organizationId; + const movements = await stockService.getMovementsByItem(id as string, organizationId); res.json(movements); } catch (error: any) { res.status(500).json({ error: error.message }); diff --git a/src/server/services/notificationService.ts b/src/server/services/notificationService.ts index c706396..094206f 100644 --- a/src/server/services/notificationService.ts +++ b/src/server/services/notificationService.ts @@ -102,6 +102,18 @@ export const notificationService = { } }, + async clearAll(userId: string, organizationId: string) { + try { + await query( + 'DELETE FROM notifications WHERE organization_id = $1 AND (user_id = $2 OR user_id IS NULL)', + [organizationId, userId] + ); + } catch (error) { + console.error('Error clearing all notifications:', error); + throw error; + } + }, + async archive(id: string, userId: string) { try { const check = await query('SELECT * FROM notifications WHERE id = $1', [id]); diff --git a/vite.config.ts b/vite.config.ts index 0e8476c..678386a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -46,12 +46,12 @@ export default defineConfig({ server: { proxy: { '/api': { - target: 'http://127.0.0.1:3001', + target: 'http://127.0.0.1:3005', changeOrigin: true, secure: false, }, '/uploads': { - target: 'http://127.0.0.1:3001', + target: 'http://127.0.0.1:3005', changeOrigin: true, secure: false, },