diff --git a/CHANGELOG_SESSION.md b/CHANGELOG_SESSION.md index e812aba..1a7bce9 100644 --- a/CHANGELOG_SESSION.md +++ b/CHANGELOG_SESSION.md @@ -12,7 +12,7 @@ * Manual de despliegue en producción con arquitectura WSGI (Gunicorn), Nginx como proxy inverso, Systemd unit y contenedorización Docker / Docker Compose. * **Archivos Base:** * Creación de `.env.example` con todas las variables requeridas (PostgreSQL, Flask, Secret Key, Babel). - * Creación de `init_db.py` para bootstrap inicial seguro de base de datos y usuario administrador por defecto (`admin@edu-space.com` / `admin123`). + * Creación y posterior actualización de `init_db.py` para bootstrap inicial seguro de base de datos, roles RBAC y usuario administrador por defecto (`admin@edu-space.com` / `admin123`). --- @@ -20,65 +20,234 @@ * **Preferencia de Idioma Persistente:** * Migración en PostgreSQL agregando la columna `preferred_language VARCHAR(10)` a la tabla `users`. * Actualización del modelo `User` en `app/models/user.py` con el campo `preferred_language`. +* **Preferencia de Tema Visual Persistente:** + * Migración agregando la columna `theme_preference VARCHAR(10) DEFAULT 'auto' NOT NULL` a la tabla `users`. + * Soporte en el modelo `User` para valores `'auto'`, `'light'` y `'dark'`. +* **Control de Acceso Basado en Roles (RBAC):** + * Migración creando las tablas `roles` y `permissions`, y agregando la clave foránea `role_id` a la tabla `users`. + * Modelos `Role` y `Permission` en `app/models/role.py`. + * Métodos `has_permission(module, min_level)` y `can_manage()` en `User`. --- -## 3. Implementación de Vistas y Plantillas Faltantes +## 3. Implementación de Vistas y Plantillas * **Perfil de Usuario (`app/templates/auth/profile.html`):** * Vista completa con datos del usuario, rol, estado, fecha de registro y reservas recientes. - * Formulario interactivo para configurar la **Preferencia de Idioma** (*Detectar automáticamente del navegador*, *Español*, *English*). + * Formulario integral para configurar **Idioma de la interfaz** (*Detectar automáticamente del navegador*, *Español*, *English*) y **Tema visual** (*Automático*, *Modo Claro*, *Modo Oscuro*). * **Cambio de Contraseña (`app/templates/auth/change_password.html`):** * Formulario seguro para actualización de credenciales. * **Manejo de Errores (`app/templates/auth/403.html`):** - * Pantalla de error 403 Forbidden estilizada. + * Pantalla de error 403 Forbidden estilizada e integrada con el sistema de diseño. --- -## 4. Correcciones de UX y Bugs de Rutas +## 4. Correcciones de UX, Linter y Bugs de Rutas * **Navbar Limpio (`app/templates/base.html`):** * Eliminación del bloque duplicado del menú de usuario `System Administrator`. * **Corrección de BuildError en Comisiones:** * En `app/routes/classrooms.py`, se agregó el alias de ruta `@classrooms_bp.route('/', endpoint='index')` para resolver enlaces a `classrooms.index`. * En `app/templates/schedule/commissions.html`, se reemplazó el filtro inválido de Django `truncatewords(20)` por el filtro estándar de Jinja2 `truncate(100)`. * **Corrección Visual en `/genetic-optimizer` (`app/templates/genetic_optimizer.html`):** - * Se agregó el espaciado `pt-5 mt-4` evitando que la barra de navegación fija superior (`fixed-top`) se monte sobre el contenido. + * Se agregó el espaciado `pt-5 mt-4` evitando que la barra fija superior se monte sobre el contenido. * Rediseño de tarjeta hero con contraste óptimo y reemplazo de iconos faltantes por Bootstrap Icons (`bi bi-...`). -* **Corrección en Calendario (`app/templates/schedule/calendar.html`):** - * Inclusión de contenedor con espaciado superior y bundle de localización `locales-all.min.js` para FullCalendar. +* **Corrección de Errores del Linter en `schedule/add.html` y `schedule/view.html`:** + * En `add.html`: Desacople de iteraciones Jinja a ` +{% endblock %} diff --git a/app/templates/admin/roles/edit.html b/app/templates/admin/roles/edit.html new file mode 100644 index 0000000..293548d --- /dev/null +++ b/app/templates/admin/roles/edit.html @@ -0,0 +1,191 @@ +{% extends "base.html" %} + +{% block title %}{% if role %}{% trans %}Editar Rol{% endtrans %}: {{ role.name }}{% else %}{% trans %}Nuevo Rol{% endtrans %}{% endif %} - Edu-Space Admin{% endblock %} + +{% block content %} +
+ +
+
+

+ + {% if role %}{% trans %}Editar Rol y Permisos de Acceso{% endtrans %}{% else %}{% trans %}Crear Rol y Permisos de Acceso{% endtrans %}{% endif %} +

+

{% trans %}Configure permisos granulares por módulo con la matriz de acceso estilo FortiGate.{% endtrans %}

+
+
+ + {% trans %}Volver a Roles{% endtrans %} + +
+
+ +
+
+ +
+
+
+
+ {% trans %}Información del Rol{% endtrans %} +
+
+
+
+ + + {% if role and role.is_system %} + + {% trans %}Rol del sistema protegido.{% endtrans %} + + {% endif %} +
+ +
+ + +
+ +
+ +
+ + + {% trans %}Cancelar{% endtrans %} + +
+
+
+
+ + +
+
+ +
+ + {% trans %}Permisos de Acceso{% endtrans %} + + + + +
+ + +
+ + + + + + + + + {% for mod in modules %} + {% set cur_level = current_perms.get(mod.id, 'none') %} + + + + + {% endfor %} + +
{% trans %}Módulo del Sistema{% endtrans %}{% trans %}Nivel de Permiso{% endtrans %}
+
+
+ +
+
+
{{ mod.name }}
+ {{ mod.description }} +
+
+
+ + + + +
+ + + +
+
+
+
+
+
+
+
+{% endblock %} + +{% block extra_js %} + +{% endblock %} diff --git a/app/templates/admin/roles/list.html b/app/templates/admin/roles/list.html new file mode 100644 index 0000000..9d49822 --- /dev/null +++ b/app/templates/admin/roles/list.html @@ -0,0 +1,124 @@ +{% extends "base.html" %} + +{% block title %}{% trans %}Roles y Grupos de Acceso{% endtrans %} - Edu-Space Admin{% endblock %} + +{% block content %} +
+ +
+
+

+ {% trans %}Roles y Grupos de Acceso{% endtrans %} +

+

{% trans %}Administración de perfiles de usuario y matriz granular de permisos por módulo del sistema.{% endtrans %}

+
+
+ + {% trans %}Nuevo Rol{% endtrans %} + +
+
+ + +
+
+ + + + + + + + + + + + {% for role in roles %} + + + + + + + + {% endfor %} + +
{% trans %}Nombre del Rol{% endtrans %}{% trans %}Descripción{% endtrans %}{% trans %}Integrantes{% endtrans %}{% trans %}Resumen de Permisos{% endtrans %}{% trans %}Acciones{% endtrans %}
+
+
+ +
+
+
{{ role.name }}
+ {% if role.is_system %} + {% trans %}Protegido del Sistema{% endtrans %} + {% endif %} +
+
+
+ {{ role.description or _('Sin descripción provista.') }} + + + {{ role.users|length }} {% trans %}usuarios{% endtrans %} + + +
+ {% for mod in modules %} + {% set p_level = role.get_permission(mod.id) %} + {% if p_level == 'read_write' %} + + {{ mod.name }}: RW + + {% elif p_level == 'read' %} + + {{ mod.name }}: R + + {% else %} + + {{ mod.name }}: - + + {% endif %} + {% endfor %} +
+
+
+ + {% trans %}Permisos{% endtrans %} + + {% if not role.is_system %} + + {% endif %} +
+ + {% if not role.is_system %} + + + {% endif %} +
+
+
+
+{% endblock %} diff --git a/app/templates/admin/users/form.html b/app/templates/admin/users/form.html new file mode 100644 index 0000000..19075ba --- /dev/null +++ b/app/templates/admin/users/form.html @@ -0,0 +1,107 @@ +{% extends "base.html" %} + +{% block title %}{% if user %}{% trans %}Edit User{% endtrans %}: {{ user.name }}{% else %}{% trans %}New User{% endtrans %}{% endif %} - Edu-Space Admin{% endblock %} + +{% block content %} +
+ +
+
+

+ + {% if user %}{% trans %}Edit User Account{% endtrans %}{% else %}{% trans %}Create User Account{% endtrans %}{% endif %} +

+

{% trans %}Configure user credentials, profile information, and role assignment.{% endtrans %}

+
+
+ + {% trans %}Back to Users{% endtrans %} + +
+
+ +
+
+
+
+
+ {% trans %}Account Details{% endtrans %} +
+
+
+
+
+ + +
+ +
+ + +
+ +
+ + + {% if user %} + + {% trans %}Only fill this in if you want to reset this user's password.{% endtrans %} + + {% endif %} +
+ +
+ + + + + {% trans %}View or manage roles and permissions{% endtrans %} + + +
+ +
+ + + + {% trans %}Inactive users are prevented from signing in to the platform.{% endtrans %} + + {% if user and user.id == current_user.id %} + + {% endif %} +
+ +
+ + {% trans %}Cancel{% endtrans %} + + +
+
+
+
+
+
+
+{% endblock %} diff --git a/app/templates/admin/users/list.html b/app/templates/admin/users/list.html new file mode 100644 index 0000000..88870f1 --- /dev/null +++ b/app/templates/admin/users/list.html @@ -0,0 +1,182 @@ +{% extends "base.html" %} + +{% block title %}{% trans %}User Management{% endtrans %} - Edu-Space Admin{% endblock %} + +{% block content %} +
+ +
+
+

+ {% trans %}User Management{% endtrans %} +

+

{% trans %}Manage user accounts, assign roles, and control active status.{% endtrans %}

+
+
+ + {% trans %}New User{% endtrans %} + +
+
+ + +
+
+
+
+
+ + + + +
+
+
+ +
+
+ +
+
+ + {% if search or role_filter or status_filter %} + + + + {% endif %} +
+
+
+
+ + +
+
+ + + + + + + + + + + + + {% for u in users %} + + + + + + + + + {% else %} + + + + {% endfor %} + +
{% trans %}User{% endtrans %}{% trans %}Email{% endtrans %}{% trans %}Role / Group{% endtrans %}{% trans %}Status{% endtrans %}{% trans %}Last Login{% endtrans %}{% trans %}Actions{% endtrans %}
+
+
+ {{ (u.first_name[0] if u.first_name else 'U')|upper }} +
+
+
{{ u.name }}
+ ID: #{{ u.id }} +
+
+
+ {{ u.email }} + + {% if u.role_obj %} + + {{ u.role_obj.name }} + + {% else %} + + {{ u.role or _('No Role') }} + + {% endif %} + + {% if u.is_active %} + + {% trans %}Active{% endtrans %} + + {% else %} + + {% trans %}Inactive{% endtrans %} + + {% endif %} + + + {% if u.last_login %} + {{ format_datetime(u.last_login, format='short') }} + {% else %} + {% trans %}Never{% endtrans %} + {% endif %} + + +
+ + + + {% if u.id != current_user.id %} +
+ +
+ {% endif %} +
+
+ + {% trans %}No users found matching the criteria.{% endtrans %} +
+
+ + + {% if pagination.pages > 1 %} + + {% endif %} +
+
+{% endblock %} diff --git a/app/templates/auth/login.html b/app/templates/auth/login.html index 9ffc30b..6de8322 100644 --- a/app/templates/auth/login.html +++ b/app/templates/auth/login.html @@ -1,114 +1,115 @@ - + {% trans %}Login - Edu-Space Admin{% endtrans %} + + + + + + + + - + + -
-
-
- {% include 'partials/language_switcher.html' %} -
- -

Edu-Space Admin

-

{% trans %}Classroom Management System{% endtrans %}

-
- -
- {% with messages = get_flashed_messages(with_categories=true) %} - {% if messages %} - {% for category, message in messages %} - - {% endfor %} - {% endif %} - {% endwith %} - -
- {{ form.hidden_tag() }} - -
- -
- - -
- {% for error in form.email.errors %} -
{{ error }}
- {% endfor %} -
- -
- -
- - -
- {% for error in form.password.errors %} -
{{ error }}
- {% endfor %} -
- -
- {{ form.remember_me(class="form-check-input") }} - -
- -
- + {% include 'partials/language_switcher.html' %}
-
+ + +

Edu-Space Admin

+

{% trans %}Classroom Management System{% endtrans %}

+
-
- - - {% trans %}Secure Login • All access is logged{% endtrans %} - +
+ + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} + + {% endfor %} + {% endif %} + {% endwith %} + +
+ {{ form.hidden_tag() }} + +
+ +
+ + + + +
+ {% for error in form.email.errors %} +
{{ error }}
+ {% endfor %} +
+ +
+ +
+ + + + +
+ {% for error in form.password.errors %} +
{{ error }}
+ {% endfor %} +
+ +
+ {{ form.remember_me(class="form-check-input") }} + +
+ +
+ +
+
+ +
+ + + {% trans %}Secure Login • All access is logged{% endtrans %} + +
+ \ No newline at end of file diff --git a/app/templates/auth/profile.html b/app/templates/auth/profile.html index d4a9279..60b9d5b 100644 --- a/app/templates/auth/profile.html +++ b/app/templates/auth/profile.html @@ -76,17 +76,19 @@
- +
- -

- {% trans %}If set, this language overrides the browser configuration for all your sessions.{% endtrans %} -

-
-
- @@ -97,13 +99,38 @@ English + + {% trans %}If set, this language overrides the browser configuration for all your sessions.{% endtrans %} +
-
- + + +
+ + + + {% trans %}Choose your preferred visual theme.{% endtrans %} +
+ +
+ +