permisos de agenda: selector de acciones por usuario (ver, agendar, editar, eliminar, visitas)
- roles.py: AGENDA_PERMS, AGENDA_PERM_KEYS, WRITE_RANK_MIN, agenda_defaults_for, resolve_agenda_perms, AGENDA_STATUS_PERM, AGENDA_STATE_PERM, _agenda_status_perm - frontend_user.py: campo agenda_perms, _agenda_perms_list(), to_public_dict() expone agenda_perms y agenda_perms_custom - auth.py: require_agenda(perm) decorador + agenda_perm_error() - frontend.py: @require_agenda aplicado a 22 endpoints + branch en update_appointment_status por accion - auth_users_update: whitelist acepta agenda_perms - Odoo upgrade: columna skeen_frontend_user.agenda_perms - Frontend: types AgendaPerm, AGENDA_PERM_ITEMS, canAgenda() en auth.tsx - UsuariosPanel: checkboxes de permisos de agenda en modal de permisos - Agenda.tsx: gates por permiso en crear/editar/eliminar/visitas/dragdrop/bloqueos - EstadoChecklist/BloqueosModal/ListaEspera: hide actions without permission Verificacion API: 18/18 tests OK (admin hereda, recorte=403, lect=403, restore=null)
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { createContext, useContext, useEffect, useState, useCallback } from 'react';
|
||||
import type { FC, ReactNode } from 'react';
|
||||
import { odooApi, type FrontendUser, type FrontendRole } from '../services/odoo';
|
||||
import { odooApi, type FrontendUser, type FrontendRole, type AgendaPerm } from '../services/odoo';
|
||||
|
||||
const TOKEN_KEY = 'skeen_token';
|
||||
const USER_KEY = 'skeen_user';
|
||||
@@ -75,6 +75,7 @@ interface AuthContextValue {
|
||||
logout: () => Promise<void>;
|
||||
hasRole: (min: FrontendRole) => boolean;
|
||||
canSee: (href: string) => boolean;
|
||||
canAgenda: (perm: AgendaPerm) => boolean;
|
||||
}
|
||||
|
||||
const AuthContext = createContext<AuthContextValue | undefined>(undefined);
|
||||
@@ -219,8 +220,19 @@ export const AuthProvider: FC<{ children: ReactNode }> = ({ children }) => {
|
||||
return true;
|
||||
};
|
||||
|
||||
// Acciones dentro de la Agenda. El backend resuelve la herencia del rol y
|
||||
// manda la lista efectiva en user.agenda_perms; el fallback por rango cubre
|
||||
// la sesión cacheada anterior al despliegue.
|
||||
const canAgenda = (perm: AgendaPerm): boolean => {
|
||||
if (!user) return false;
|
||||
const todas: AgendaPerm[] = ['ver', 'agendar', 'editar', 'eliminar', 'visitas'];
|
||||
const perms = user.agenda_perms
|
||||
?? (ROLE_RANK[user.role] >= ROLE_RANK.recepcion ? todas : ['ver']);
|
||||
return perms.includes(perm);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ user, token, loading, bootError, retryBoot, login, logout, hasRole, canSee }}>
|
||||
<AuthContext.Provider value={{ user, token, loading, bootError, retryBoot, login, logout, hasRole, canSee, canAgenda }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user