Add 3-level role permissions, organismos operadores, and Histórico de Tomas page
Implements the full ADMIN → ORGANISMO_OPERADOR → OPERATOR permission hierarchy with scope-filtered data access across all backend services. Adds organismos operadores management (ADMIN only) and a new Histórico page for viewing per-meter reading history with chart, consumption stats, and CSV export. Key changes: - Backend: 3-level scope filtering on all services (meters, readings, projects, users) - Backend: Protect GET /meters routes with authenticateToken for role-based filtering - Backend: Pass requestingUser to reading service for scoped meter readings - Frontend: New HistoricoPage with meter selector, AreaChart, paginated table - Frontend: Consumption cards (Actual, Pasado, Diferencial) above date filters - Frontend: Meter search by name, serial, location, CESPT account, cadastral key - Frontend: OrganismosPage, updated Sidebar with 3-level visibility - SQL migrations for organismos_operadores table and FK columns Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -76,7 +76,7 @@ export interface PaginatedResult<T> {
|
||||
export async function getAll(
|
||||
filters?: ConcentratorFilters,
|
||||
pagination?: PaginationOptions,
|
||||
requestingUser?: { roleName: string; projectId?: string | null }
|
||||
requestingUser?: { roleName: string; projectId?: string | null; organismoOperadorId?: string | null }
|
||||
): Promise<PaginatedResult<Concentrator>> {
|
||||
const page = pagination?.page || 1;
|
||||
const limit = pagination?.limit || 10;
|
||||
@@ -89,15 +89,19 @@ export async function getAll(
|
||||
const params: unknown[] = [];
|
||||
let paramIndex = 1;
|
||||
|
||||
// Role-based filtering: OPERATOR users can only see their assigned project
|
||||
if (requestingUser && requestingUser.roleName !== 'ADMIN' && requestingUser.projectId) {
|
||||
// Role-based filtering: 3-level hierarchy
|
||||
if (requestingUser && requestingUser.roleName === 'ORGANISMO_OPERADOR' && requestingUser.organismoOperadorId) {
|
||||
conditions.push(`project_id IN (SELECT id FROM projects WHERE organismo_operador_id = $${paramIndex})`);
|
||||
params.push(requestingUser.organismoOperadorId);
|
||||
paramIndex++;
|
||||
} else if (requestingUser && requestingUser.roleName !== 'ADMIN' && requestingUser.projectId) {
|
||||
conditions.push(`project_id = $${paramIndex}`);
|
||||
params.push(requestingUser.projectId);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
// Additional filter by project_id (only applies if user is ADMIN or no user context)
|
||||
if (filters?.project_id && (!requestingUser || requestingUser.roleName === 'ADMIN')) {
|
||||
// Additional filter by project_id (applies if user is ADMIN, ORGANISMO_OPERADOR, or no user context)
|
||||
if (filters?.project_id && (!requestingUser || requestingUser.roleName === 'ADMIN' || requestingUser.roleName === 'ORGANISMO_OPERADOR')) {
|
||||
conditions.push(`project_id = $${paramIndex}`);
|
||||
params.push(filters.project_id);
|
||||
paramIndex++;
|
||||
|
||||
Reference in New Issue
Block a user