refactor: Standardize user and organization ID properties, update Vite proxy port, and refactor data sheet file serving.

This commit is contained in:
2026-03-19 22:05:47 +00:00
parent 0b81094050
commit 37cc1b2acb
10 changed files with 50 additions and 43 deletions

View File

@@ -34,7 +34,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
const fetchTokenAndUser = async () => { const fetchTokenAndUser = async () => {
if (isAuthenticated) { if (isAuthenticated) {
try { try {
const accessToken = await getAccessToken(); const accessToken = await getAccessToken(import.meta.env.VITE_LOGTO_RESOURCE || 'https://gpi.reifonas.cloud/api');
if (accessToken) { if (accessToken) {
setToken(accessToken); setToken(accessToken);
setApiToken(accessToken); setApiToken(accessToken);

View File

@@ -7,7 +7,9 @@ import type { LogtoConfig } from '@logto/react';
// Require the user to define VITE_LOGTO_APP_ID in Coolify // Require the user to define VITE_LOGTO_APP_ID in Coolify
const config: LogtoConfig = { const config: LogtoConfig = {
endpoint: 'https://logto.reifonas.cloud', 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 // Force service worker cache clearing because of persistent Clerk error

View File

@@ -5,7 +5,7 @@ import '../middleware/roleMiddleware.js'; // Ensure type augmentation
export const createApplicationRecord = async (req: Request, res: Response) => { export const createApplicationRecord = async (req: Request, res: Response) => {
try { try {
const organizationId = req.appUser?.organizationId; const organizationId = req.appUser?.organizationId;
const createdBy = req.appUser?.externalId; const createdBy = req.appUser?.id;
const record = await appRecordService.createApplicationRecord({ ...req.body, organizationId, createdBy }); const record = await appRecordService.createApplicationRecord({ ...req.body, organizationId, createdBy });
res.status(201).json(record); res.status(201).json(record);
} catch (error: unknown) { } catch (error: unknown) {
@@ -29,7 +29,7 @@ export const getApplicationRecordsByProject = async (req: Request, res: Response
export const updateApplicationRecord = async (req: Request, res: Response) => { export const updateApplicationRecord = async (req: Request, res: Response) => {
try { try {
const organizationId = req.appUser?.organizationId; const organizationId = req.appUser?.organizationId;
const userId = req.appUser?.externalId; const userId = req.appUser?.id;
const userRole = req.appUser?.organizationRole || req.appUser?.role; const userRole = req.appUser?.organizationRole || req.appUser?.role;
const isDeveloper = req.appUser?.email === 'admtracksteel@gmail.com'; 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) => { export const deleteApplicationRecord = async (req: Request, res: Response) => {
try { try {
const organizationId = req.appUser?.organizationId; const organizationId = req.appUser?.organizationId;
const userId = req.appUser?.externalId; const userId = req.appUser?.id;
const userRole = req.appUser?.organizationRole || req.appUser?.role; const userRole = req.appUser?.organizationRole || req.appUser?.role;
const isDeveloper = req.appUser?.email === 'admtracksteel@gmail.com'; const isDeveloper = req.appUser?.email === 'admtracksteel@gmail.com';

View File

@@ -115,11 +115,10 @@ export const getMe = async (req: Request, res: Response): Promise<void> => {
} }
res.status(200).json({ res.status(200).json({
id: req.appUser._id, id: req.appUser.id,
name: req.appUser.name, name: req.appUser.name,
email: req.appUser.email, email: req.appUser.email,
role: req.appUser.role, role: req.appUser.role,
externalId: req.appUser.externalId,
organizationId: req.appUser.organizationId organizationId: req.appUser.organizationId
}); });
} catch (error) { } catch (error) {

View File

@@ -267,18 +267,12 @@ export const getFile = async (req: Request, res: Response) => {
} }
// Fallback to file system (legacy) // Fallback to file system (legacy)
const stream = dataSheetService.getFileStream(id_or_filename); const file = await dataSheetService.getFileStream(id_or_filename);
res.set('Content-Type', file.content_type || 'application/pdf');
stream.on('file', (file) => {
res.set('Content-Type', 'application/pdf');
res.set('Content-Disposition', `inline; filename="${file.filename}"`); res.set('Content-Disposition', `inline; filename="${file.filename}"`);
}); res.set('Access-Control-Allow-Origin', '*');
res.set('Cache-Control', 'public, max-age=3600');
stream.on('error', () => { res.send(file.data);
res.status(404).json({ error: 'File not found' });
});
stream.pipe(res);
} catch (error: unknown) { } catch (error: unknown) {
const message = error instanceof Error ? error.message : 'Unknown error'; const message = error instanceof Error ? error.message : 'Unknown error';
console.error('Error getting file:', error); console.error('Error getting file:', error);

View File

@@ -6,7 +6,7 @@ import '../middleware/roleMiddleware.js'; // Ensure type augmentation
export const createInspection = async (req: Request, res: Response) => { export const createInspection = async (req: Request, res: Response) => {
try { try {
const organizationId = req.appUser?.organizationId; const organizationId = req.appUser?.organizationId;
const createdBy = req.appUser?.externalId; const createdBy = req.appUser?.id;
const inspection = await inspectionService.createInspection({ const inspection = await inspectionService.createInspection({
...req.body, ...req.body,
organizationId, organizationId,
@@ -46,7 +46,7 @@ export const getInspectionsByProject = async (req: Request, res: Response) => {
export const updateInspection = async (req: Request, res: Response) => { export const updateInspection = async (req: Request, res: Response) => {
try { try {
const organizationId = req.appUser?.organizationId; const organizationId = req.appUser?.organizationId;
const userId = req.appUser?.externalId; const userId = req.appUser?.id;
const userRole = req.appUser?.organizationRole || req.appUser?.role; const userRole = req.appUser?.organizationRole || req.appUser?.role;
const isDeveloper = req.appUser?.email === 'admtracksteel@gmail.com'; 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) => { export const deleteInspection = async (req: Request, res: Response) => {
try { try {
const organizationId = req.appUser?.organizationId; const organizationId = req.appUser?.organizationId;
const userId = req.appUser?.externalId; const userId = req.appUser?.id;
const userRole = req.appUser?.organizationRole || req.appUser?.role; const userRole = req.appUser?.organizationRole || req.appUser?.role;
const isDeveloper = req.appUser?.email === 'admtracksteel@gmail.com'; const isDeveloper = req.appUser?.email === 'admtracksteel@gmail.com';

View File

@@ -6,7 +6,7 @@ import OrganizationMember from '../models/OrganizationMember.js';
export const sendMessage = async (req: Request, res: Response) => { export const sendMessage = async (req: Request, res: Response) => {
try { try {
const { toUserId, message } = req.body; const { toUserId, message } = req.body;
const fromUserId = req.appUser?.externalId; const fromUserId = req.appUser?.id;
const organizationId = req.headers['x-organization-id'] as string; const organizationId = req.headers['x-organization-id'] as string;
if (!organizationId) { if (!organizationId) {
@@ -60,7 +60,7 @@ export const sendMessage = async (req: Request, res: Response) => {
// Get unread messages for current user // Get unread messages for current user
export const getUnreadMessages = async (req: Request, res: Response) => { export const getUnreadMessages = async (req: Request, res: Response) => {
try { try {
const toUserId = req.appUser?.externalId; const toUserId = req.appUser?.id;
const organizationId = req.headers['x-organization-id'] as string; const organizationId = req.headers['x-organization-id'] as string;
if (!organizationId) { if (!organizationId) {
@@ -101,7 +101,7 @@ export const getUnreadMessages = async (req: Request, res: Response) => {
export const markMessageAsRead = async (req: Request, res: Response) => { export const markMessageAsRead = async (req: Request, res: Response) => {
try { try {
const { id } = req.params; const { id } = req.params;
const userId = req.appUser?.externalId; const userId = req.appUser?.id;
const organizationId = req.headers['x-organization-id'] as string; const organizationId = req.headers['x-organization-id'] as string;
if (!organizationId) { if (!organizationId) {
@@ -136,7 +136,7 @@ export const markMessageAsRead = async (req: Request, res: Response) => {
// Get my pending (unread) sent messages // Get my pending (unread) sent messages
export const getMyPendingMessages = async (req: Request, res: Response) => { export const getMyPendingMessages = async (req: Request, res: Response) => {
try { try {
const fromUserId = req.appUser?.externalId; const fromUserId = req.appUser?.id;
const organizationId = req.headers['x-organization-id'] as string; const organizationId = req.headers['x-organization-id'] as string;
if (!organizationId) { if (!organizationId) {
@@ -175,7 +175,7 @@ export const getMyPendingMessages = async (req: Request, res: Response) => {
export const deleteMessage = async (req: Request, res: Response) => { export const deleteMessage = async (req: Request, res: Response) => {
try { try {
const { id } = req.params; const { id } = req.params;
const userId = req.appUser?.externalId; const userId = req.appUser?.id;
const organizationId = req.headers['x-organization-id'] as string; const organizationId = req.headers['x-organization-id'] as string;
if (!organizationId) { if (!organizationId) {
@@ -209,7 +209,7 @@ export const deleteMessage = async (req: Request, res: Response) => {
export const archiveMessage = async (req: Request, res: Response) => { export const archiveMessage = async (req: Request, res: Response) => {
try { try {
const { id } = req.params; const { id } = req.params;
const userId = req.appUser?.externalId; const userId = req.appUser?.id;
const organizationId = req.headers['x-organization-id'] as string; const organizationId = req.headers['x-organization-id'] as string;
const message = await Message.findOne({ _id: id, toUserId: userId, organizationId }); 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) => { export const recipientDeleteMessage = async (req: Request, res: Response) => {
try { try {
const { id } = req.params; const { id } = req.params;
const userId = req.appUser?.externalId; const userId = req.appUser?.id;
const organizationId = req.headers['x-organization-id'] as string; const organizationId = req.headers['x-organization-id'] as string;
const message = await Message.findOne({ _id: id, toUserId: userId, organizationId }); const message = await Message.findOne({ _id: id, toUserId: userId, organizationId });

View File

@@ -9,7 +9,7 @@ interface AuthRequest extends Request {
export const createStockItem = async (req: AuthRequest, res: Response) => { export const createStockItem = async (req: AuthRequest, res: Response) => {
try { try {
const organizationId = req.appUser?.organization_id; const organizationId = req.appUser?.organizationId;
const userName = req.appUser?.name || req.appUser?.email || 'Unknown User'; const userName = req.appUser?.name || req.appUser?.email || 'Unknown User';
const { const {
dataSheetId, dataSheetId,
@@ -97,7 +97,7 @@ export const createStockItem = async (req: AuthRequest, res: Response) => {
export const updateStockItem = async (req: AuthRequest, res: Response) => { export const updateStockItem = async (req: AuthRequest, res: Response) => {
try { try {
const { id } = req.params; const { id } = req.params;
const organizationId = req.appUser?.organization_id; const organizationId = req.appUser?.organizationId;
const { quantity, ...otherData } = req.body; const { quantity, ...otherData } = req.body;
if (quantity !== undefined) { 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); const updated = await stockService.updateStockItem(id as string, otherData, organizationId);
if (!updated) return res.status(404).json({ error: 'Item não encontrado.' }); 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); res.json(updated);
} catch (error: any) { } catch (error: any) {
res.status(500).json({ error: error.message }); 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) => { export const adjustStock = async (req: AuthRequest, res: Response) => {
try { try {
const { id } = req.params; const { id } = req.params;
const organizationId = req.appUser?.organization_id; const organizationId = req.appUser?.organizationId;
const { quantityDelta, reason } = req.body; const { quantityDelta, reason } = req.body;
if (!reason) return res.status(400).json({ error: 'Motivo é obrigatório para ajustes técnicos.' }); 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 reason
}); });
await notificationService.checkLowStock(id); await notificationService.checkLowStock(id as string);
res.json(adjustment); res.json(adjustment);
} catch (error: any) { } catch (error: any) {
res.status(500).json({ error: error.message }); 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) => { export const consumeStock = async (req: AuthRequest, res: Response) => {
try { try {
const { id } = req.params; const { id } = req.params;
const organizationId = req.appUser?.organization_id; const organizationId = req.appUser?.organizationId;
const { quantityConsumed, requester, date } = req.body; const { quantityConsumed, requester, date } = req.body;
if (!requester) return res.status(400).json({ error: 'Solicitante é obrigatório.' }); 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}` reason: `Consumo por ${requester}`
}); });
await notificationService.checkLowStock(id); await notificationService.checkLowStock(id as string);
res.json({ message: 'Consumo registrado com sucesso.' }); res.json({ message: 'Consumo registrado com sucesso.' });
} catch (error: any) { } catch (error: any) {
res.status(500).json({ error: error.message }); 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) => { export const deleteStockItem = async (req: AuthRequest, res: Response) => {
try { try {
const { id } = req.params; const { id } = req.params;
const organizationId = req.appUser?.organization_id; const organizationId = req.appUser?.organizationId;
await stockService.deleteStockItem(id as string, organizationId); await stockService.deleteStockItem(id as string, organizationId);
res.status(204).send(); res.status(204).send();
} catch (error: any) { } catch (error: any) {
@@ -188,7 +188,7 @@ export const deleteStockItem = async (req: AuthRequest, res: Response) => {
export const getStockItems = async (req: AuthRequest, res: Response) => { export const getStockItems = async (req: AuthRequest, res: Response) => {
try { try {
const organizationId = req.appUser?.organization_id; const organizationId = req.appUser?.organizationId;
const items = await stockService.getStockItems(organizationId); const items = await stockService.getStockItems(organizationId);
res.json(items); res.json(items);
} catch (error: any) { } catch (error: any) {
@@ -199,7 +199,7 @@ export const getStockItems = async (req: AuthRequest, res: Response) => {
export const getStockItemById = async (req: AuthRequest, res: Response) => { export const getStockItemById = async (req: AuthRequest, res: Response) => {
try { try {
const { id } = req.params; const { id } = req.params;
const organizationId = req.appUser?.organization_id; const organizationId = req.appUser?.organizationId;
const result = await query( const result = await query(
`SELECT si.*, tds.name as data_sheet_name `SELECT si.*, tds.name as data_sheet_name
FROM stock_items si FROM stock_items si
@@ -217,8 +217,8 @@ export const getStockItemById = async (req: AuthRequest, res: Response) => {
export const getStockMovements = async (req: AuthRequest, res: Response) => { export const getStockMovements = async (req: AuthRequest, res: Response) => {
try { try {
const { id } = req.params; const { id } = req.params;
const organizationId = req.appUser?.organization_id; const organizationId = req.appUser?.organizationId;
const movements = await stockService.getMovementsByItem(id, organizationId); const movements = await stockService.getMovementsByItem(id as string, organizationId);
res.json(movements); res.json(movements);
} catch (error: any) { } catch (error: any) {
res.status(500).json({ error: error.message }); res.status(500).json({ error: error.message });

View File

@@ -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) { async archive(id: string, userId: string) {
try { try {
const check = await query('SELECT * FROM notifications WHERE id = $1', [id]); const check = await query('SELECT * FROM notifications WHERE id = $1', [id]);

View File

@@ -46,12 +46,12 @@ export default defineConfig({
server: { server: {
proxy: { proxy: {
'/api': { '/api': {
target: 'http://127.0.0.1:3001', target: 'http://127.0.0.1:3005',
changeOrigin: true, changeOrigin: true,
secure: false, secure: false,
}, },
'/uploads': { '/uploads': {
target: 'http://127.0.0.1:3001', target: 'http://127.0.0.1:3005',
changeOrigin: true, changeOrigin: true,
secure: false, secure: false,
}, },