Eliminando middleware legado do Clerk e corrigindo rotas/controllers para Logto
This commit is contained in:
@@ -14,7 +14,7 @@ import geometryTypeRoutes from '../src/server/routes/geometryTypeRoutes.js';
|
||||
import stockRoutes from '../src/server/routes/stockRoutes.js';
|
||||
import notificationRoutes from '../src/server/routes/notificationRoutes.js';
|
||||
import instrumentRoutes from '../src/server/routes/instrumentRoutes.js';
|
||||
import { extractUser } from '../src/server/middleware/roleMiddleware.js';
|
||||
import { extractUser } from '../src/server/middleware/authMiddleware.js';
|
||||
import path from 'path';
|
||||
|
||||
const app = express();
|
||||
@@ -22,7 +22,7 @@ const app = express();
|
||||
app.use(cors({
|
||||
origin: '*', // Be more specific in production
|
||||
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'x-clerk-user-id', 'x-organization-id', 'x-organization-name']
|
||||
allowedHeaders: ['Content-Type', 'Authorization', 'x-organization-id', 'x-organization-name']
|
||||
}));
|
||||
app.use(express.json());
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Request, Response } from 'express';
|
||||
import * as appRecordService from '../services/applicationRecordService.js';
|
||||
import '../middleware/roleMiddleware.js'; // Ensure type augmentation
|
||||
import '../middleware/authMiddleware.js'; // Ensure type augmentation
|
||||
|
||||
export const createApplicationRecord = async (req: Request, res: Response) => {
|
||||
try {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Request, Response } from 'express';
|
||||
import * as dataSheetService from '../services/dataSheetService.js';
|
||||
import fs from 'fs';
|
||||
import * as pdfExtractionService from '../services/pdfExtractionService.js';
|
||||
import { IAppUser } from '../middleware/roleMiddleware.js';
|
||||
import { IAppUser } from '../middleware/authMiddleware.js';
|
||||
import { notificationService } from '../services/notificationService.js';
|
||||
|
||||
interface AuthRequest extends Request {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Request, Response } from 'express';
|
||||
import GeometryType from '../models/GeometryType.js';
|
||||
import { IAppUser } from '../middleware/roleMiddleware.js';
|
||||
import { IAppUser } from '../middleware/authMiddleware.js';
|
||||
|
||||
interface AuthRequest extends Request {
|
||||
appUser?: IAppUser;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Request, Response } from 'express';
|
||||
import * as inspectionService from '../services/inspectionService.js';
|
||||
import { notificationService } from '../services/notificationService.js';
|
||||
import '../middleware/roleMiddleware.js'; // Ensure type augmentation
|
||||
import '../middleware/authMiddleware.js'; // Ensure type augmentation
|
||||
|
||||
export const createInspection = async (req: Request, res: Response) => {
|
||||
try {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Request, Response } from 'express';
|
||||
import Instrument from '../models/Instrument.js';
|
||||
import { IAppUser } from '../middleware/roleMiddleware.js';
|
||||
import { IAppUser } from '../middleware/authMiddleware.js';
|
||||
|
||||
interface AuthRequest extends Request {
|
||||
appUser?: IAppUser;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Request, Response } from 'express';
|
||||
import * as partService from '../services/partService.js';
|
||||
import { IAppUser } from '../middleware/roleMiddleware.js';
|
||||
import { IAppUser } from '../middleware/authMiddleware.js';
|
||||
|
||||
interface AuthRequest extends Request {
|
||||
appUser?: IAppUser;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Request, Response } from 'express';
|
||||
import * as projectService from '../services/projectService.js';
|
||||
import { IAppUser } from '../middleware/roleMiddleware.js';
|
||||
import { IAppUser } from '../middleware/authMiddleware.js';
|
||||
import { notificationService } from '../services/notificationService.js';
|
||||
|
||||
interface AuthRequest extends Request {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Request, Response } from 'express';
|
||||
import StockItem from '../models/StockItem.js';
|
||||
import StockMovement from '../models/StockMovement.js';
|
||||
|
||||
import { IAppUser } from '../middleware/roleMiddleware.js';
|
||||
import { IAppUser } from '../middleware/authMiddleware.js';
|
||||
import { notificationService } from '../services/notificationService.js';
|
||||
|
||||
interface AuthRequest extends Request {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Request, Response, NextFunction } from 'express';
|
||||
import { authenticateRequest } from './logtoAuth.js';
|
||||
import { findOneGpi } from '../config/supabase.js';
|
||||
|
||||
export interface AppUser {
|
||||
export interface IAppUser {
|
||||
id: string;
|
||||
logtoId: string;
|
||||
email: string;
|
||||
@@ -14,7 +14,7 @@ export interface AppUser {
|
||||
|
||||
declare module 'express-serve-static-core' {
|
||||
interface Request {
|
||||
appUser?: any;
|
||||
appUser?: IAppUser;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
import { createRemoteJWKSet, jwtVerify } from 'jose';
|
||||
import { supabase, findOneGpi } from '../config/supabase.js';
|
||||
import { IAppUser } from './authMiddleware.js';
|
||||
|
||||
const LOGTO_URL = process.env.LOGTO_URL || 'https://logto-admin-bzlued1boxl3t8ewsyn99an9.187.77.227.172.sslip.io';
|
||||
const APP_ID = process.env.LOGTO_APP_ID || 'gpi-app-001';
|
||||
const jwks = createRemoteJWKSet(new URL(`${LOGTO_URL}/oidc/jwks`));
|
||||
|
||||
export interface AppUser {
|
||||
id: string;
|
||||
logtoId: string;
|
||||
email: string;
|
||||
name: string;
|
||||
role: string;
|
||||
}
|
||||
export type AppUser = IAppUser;
|
||||
|
||||
export async function authenticateRequest(req: any): Promise<AppUser | null> {
|
||||
export async function authenticateRequest(req: any): Promise<IAppUser | null> {
|
||||
const authHeader = req.headers.authorization;
|
||||
|
||||
if (!authHeader?.startsWith('Bearer ')) {
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import User, { IUser } from '../models/User.js';
|
||||
import OrganizationMember, { OrgRole } from '../models/OrganizationMember.js';
|
||||
import Organization from '../models/Organization.js';
|
||||
|
||||
// Extended user info with organization context
|
||||
export interface IAppUser extends IUser {
|
||||
organizationId?: string;
|
||||
organizationRole?: OrgRole;
|
||||
organizationBanned?: boolean;
|
||||
}
|
||||
|
||||
// Module augmentation for Express Request
|
||||
declare module 'express-serve-static-core' {
|
||||
interface Request {
|
||||
appUser?: IAppUser;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware to extract and verify user from Clerk ID header
|
||||
* Also loads organization-specific role if organization context is provided
|
||||
*/
|
||||
export const extractUser = async (req: Request, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const clerkId = req.headers['x-clerk-user-id'] as string;
|
||||
const organizationId = req.headers['x-organization-id'] as string;
|
||||
|
||||
if (!clerkId) {
|
||||
return next(); // No user, continue without
|
||||
}
|
||||
|
||||
const user = await User.findOne({ clerkId });
|
||||
|
||||
if (user) {
|
||||
if (user.isBanned) {
|
||||
return res.status(403).json({ error: 'Conta bloqueada. Entre em contato com o administrador.' });
|
||||
}
|
||||
|
||||
// Create extended user object
|
||||
const appUser: IAppUser = user.toObject() as IAppUser;
|
||||
appUser.organizationId = organizationId;
|
||||
|
||||
// If organization context, get org-specific role
|
||||
if (organizationId) {
|
||||
// Check if Organization is globally banned (subscription specific, etc.)
|
||||
const orgStatus = await Organization.findOne({ clerkId: organizationId });
|
||||
const orgName = req.headers['x-organization-name'] ? decodeURIComponent(req.headers['x-organization-name'] as string) : undefined;
|
||||
|
||||
if (orgStatus) {
|
||||
// Update name if different and present
|
||||
if (orgName && orgStatus.name !== orgName) {
|
||||
try {
|
||||
await Organization.updateOne(
|
||||
{ clerkId: organizationId },
|
||||
{ name: orgName }
|
||||
);
|
||||
} catch (err) {
|
||||
console.warn('Failed to update organization name', err);
|
||||
}
|
||||
}
|
||||
|
||||
if (orgStatus.isBanned) {
|
||||
return res.status(403).json({
|
||||
error: 'Acesso bloqueado: Esta organização está suspensa. Entre em contato com o suporte.'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Create new org with name if present
|
||||
try {
|
||||
await Organization.create({
|
||||
clerkId: organizationId,
|
||||
name: orgName
|
||||
});
|
||||
} catch (_e) {
|
||||
console.warn('Organization auto-create race condition', _e);
|
||||
}
|
||||
}
|
||||
|
||||
const member = await OrganizationMember.findOne({ clerkUserId: clerkId, organizationId });
|
||||
if (member) {
|
||||
if (member.isBanned) {
|
||||
return res.status(403).json({ error: 'Acesso bloqueado nesta organização.' });
|
||||
}
|
||||
appUser.organizationRole = member.role;
|
||||
appUser.role = member.role; // Override global role with org role
|
||||
} else {
|
||||
// User exists but is not a member of this org yet
|
||||
appUser.organizationRole = 'guest';
|
||||
appUser.role = 'guest';
|
||||
}
|
||||
}
|
||||
|
||||
req.appUser = appUser;
|
||||
// console.log(`✅ Request authenticated as: ${appUser.name} (${appUser.role})`);
|
||||
} else {
|
||||
console.warn(`⚠️ User with Clerk ID ${clerkId} not found in MongoDB. Sync required.`);
|
||||
}
|
||||
|
||||
next();
|
||||
} catch (error) {
|
||||
console.error('Error extracting user:', error);
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Middleware to require specific roles for a route
|
||||
* @param allowedRoles Array of roles that can access the route
|
||||
*/
|
||||
export const requireRole = (allowedRoles: OrgRole[]) => {
|
||||
return (req: Request, res: Response, next: NextFunction) => {
|
||||
if (!req.appUser) {
|
||||
return res.status(401).json({ error: 'Autenticação necessária.' });
|
||||
}
|
||||
|
||||
// DEV Bypass: Developer has full power
|
||||
if (req.appUser.email === 'admtracksteel@gmail.com') {
|
||||
return next();
|
||||
}
|
||||
|
||||
const effectiveRole = req.appUser.organizationRole || req.appUser.role;
|
||||
|
||||
if (!allowedRoles.includes(effectiveRole as OrgRole)) {
|
||||
return res.status(403).json({ error: 'Acesso negado. Permissões insuficientes.' });
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Middleware to require admin role
|
||||
*/
|
||||
export const requireAdmin = requireRole(['admin']);
|
||||
|
||||
/**
|
||||
* Middleware to require at least user role (user or admin)
|
||||
*/
|
||||
export const requireUser = requireRole(['user', 'admin']);
|
||||
|
||||
/**
|
||||
* Middleware to check if user can edit (user or admin, not guest)
|
||||
*/
|
||||
export const canEdit = (req: Request, res: Response, next: NextFunction) => {
|
||||
if (!req.appUser) {
|
||||
return res.status(401).json({ error: 'Autenticação necessária.' });
|
||||
}
|
||||
|
||||
const effectiveRole = req.appUser.organizationRole || req.appUser.role;
|
||||
|
||||
if (effectiveRole === 'guest') {
|
||||
return res.status(403).json({ error: 'Convidados não podem editar. Solicite acesso ao administrador.' });
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
|
||||
/**
|
||||
* Middleware to require Developer (Super Admin) access
|
||||
* Hardcoded to specific email for security
|
||||
*/
|
||||
export const requireDeveloper = (req: Request, res: Response, next: NextFunction) => {
|
||||
if (!req.appUser) {
|
||||
return res.status(401).json({ error: 'Autenticação necessária.' });
|
||||
}
|
||||
|
||||
if (req.appUser.email !== 'admtracksteel@gmail.com') {
|
||||
console.warn(`⛔ Attempted unauthorized developer access by: ${req.appUser.email}`);
|
||||
return res.status(403).json({ error: 'Acesso restrito ao desenvolvedor.' });
|
||||
}
|
||||
|
||||
next();
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from 'express';
|
||||
import * as appRecordController from '../controllers/applicationRecordController.js';
|
||||
import { extractUser, requireUser } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireUser } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { backupService } from '../services/backupService.js';
|
||||
import { requireRole } from '../middleware/roleMiddleware.js';
|
||||
import { requireRole } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import multer from 'multer';
|
||||
import path from 'path';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import * as dataSheetController from '../controllers/dataSheetController.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/authMiddleware.js';
|
||||
import os from 'os';
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from 'express';
|
||||
import * as geometryTypeController from '../controllers/geometryTypeController.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from 'express';
|
||||
import * as inspectionController from '../controllers/inspectionController.js';
|
||||
import { extractUser, requireUser } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireUser } from '../middleware/authMiddleware.js';
|
||||
import multer from 'multer';
|
||||
import path from 'path';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from 'express';
|
||||
import * as instrumentController from '../controllers/instrumentController.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import express from 'express';
|
||||
import { sendMessage, getUnreadMessages, markMessageAsRead, getMyPendingMessages, deleteMessage, archiveMessage, recipientDeleteMessage } from '../controllers/messageController.js';
|
||||
import { extractUser } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from 'express';
|
||||
import * as paintingSchemeController from '../controllers/paintingSchemeController.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from 'express';
|
||||
import * as partController from '../controllers/partController.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from 'express';
|
||||
import * as projectController from '../controllers/projectController.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from 'express';
|
||||
import * as stockController from '../controllers/stockController.js';
|
||||
import { extractUser, requireAdmin, requireUser } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireAdmin, requireUser } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import express from 'express';
|
||||
import { getSettings, updateSettings, uploadLogo, serveLogo } from '../controllers/systemSettingsController.js';
|
||||
import { extractUser, requireDeveloper } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireDeveloper } from '../middleware/authMiddleware.js';
|
||||
import { uploadLogoDetails } from '../middleware/uploadMiddleware.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import express from 'express';
|
||||
import { syncUser, getCurrentUser, getAllUsers, updateUserRole, toggleBanUser, heartbeat, getActiveUsers, deleteUser } from '../controllers/userController.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Router } from 'express';
|
||||
import * as yieldStudyController from '../controllers/yieldStudyController.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/roleMiddleware.js';
|
||||
import { extractUser, requireAdmin } from '../middleware/authMiddleware.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user