Skip to main content

Requisitos del proyecto

Requisito común: relación con empleados

Todas las aplicaciones deberán trabajar con empleados del sistema.

La información de los empleados no se duplicará en la base de datos propia de cada aplicación.
Cada aplicación guardará únicamente el identificador del empleado (id_empleado) cuando necesite relacionar una acción, solicitud, registro o elemento con un usuario.

La información completa del empleado se obtendrá mediante una petición HTTP al servidor Flask.

Para consultar los datos de un empleado, la aplicación deberá llamar a la ruta protegida correspondiente del servicio Flask.
Esta consulta solo podrá realizarse si el usuario tiene rol ADMIN.

  • La base de datos de cada aplicación tendrá campos como id_empleado.
  • Los datos personales del empleado se consultarán desde Flask.
  • El acceso a la información de empleados estará protegido.
  • Solo los usuarios con rol ADMIN podrán consultar información completa de empleados.

Ejemplo: aplicación de mantenimiento

En una aplicación de mantenimiento, el administrador puede registrar incidencias y asignarlas a un empleado.

La base de datos propia de la aplicación no guarda los datos completos del empleado.
Solo guarda el identificador del empleado asignado.

Ejemplo de tabla incidencias:

id_incidenciatitulodescripcionestadoid_empleado_asignado
1Proyector no funcionaEl proyector del aula 204 no enciendePendiente5

En este caso, la incidencia está asignada al empleado con id_empleado = 5.

Para mostrar los datos completos del empleado asignado, la aplicación realiza una petición HTTP al servidor Flask:

GET /empleados/5

El servidor Flask comprueba que el usuario que realiza la petición tiene rol ADMIN.

Si tiene permiso, devuelve los datos del empleado en formato JSON:

{
"id_empleado": 5,
"nombre": "Laura",
"apellidos": "García López",
"correo": "laura.garcia@ercitech.dam",
"id_departamento": 2,
"id_sede": 4
}
  • El administrador asigna la incidencia a un empleado.
  • La aplicación guarda solo el id_empleado_asignado.
  • Los datos completos del empleado se consultan desde Flask.
  • La consulta está protegida y requiere rol ADMIN.
empleados

Requisito común: sedes y departamentos

Las sedes y departamentos son recursos comunes compartidos por todas las aplicaciones del proyecto.

La información de sedes y departamentos se obtendrá mediante peticiones HTTP a la API correspondiente.

Las aplicaciones no deben guardar el nombre completo de la sede o departamento en sus tablas principales.
Únicamente se almacenarán sus identificadores:

  • id_sede
  • id_departamento

Por ejemplo, al registrar un nuevo empleado desde el panel de administración:

  1. La aplicación realizará una petición HTTP para obtener la lista de sedes.
  2. La aplicación realizará una petición HTTP para obtener la lista de departamentos.
  3. El administrador seleccionará una sede y un departamento.
  4. La aplicación almacenará únicamente sus identificadores en la base de datos.

Ejemplo:

GET http://info.empresa.dam.es:8055/items/sedes
GET http://info.empresa.dam.es:8055/items/departamentos

Ejemplo de respuesta JSON:

{
"data": [
{
"id": 1,
"nombre": "Recursos Humanos",
"descripcion": "Gestión de personal, contratación y desarrollo profesional"
},
{
"id": 2,
"nombre": "Consultoría",
"descripcion": "Asesoramiento técnico y estratégico a clientes"
},
{
"id": 3,
"nombre": "Calidad",
"descripcion": "Control de calidad, auditorías y mejora continua"
},
{
"id": 4,
"nombre": "Eventos",
"descripcion": "Organización y gestión de eventos corporativos"
}
]
}

Ejemplo de tabla empleados:

id_empleadonombreid_departamentoid_sede
5Laura12

En este caso:

  • id_departamento = 1
  • id_sede = 2
  • La aplicación deberá consultar la información completa mediante la API cuando necesite mostrar el nombre del departamento o la sede.

  • Para consultar una sede o departamento concreto hay que pasar el id en la propia ruta. Por ejemplo si quiero la sede con id=3, pondría:

GET http://info.empresa.dam.es:8055/items/sedes/3

Retorna:

{
"data": {
"id": 3,
"nombre": "Delegación Barcelona",
"direccion": "Carrer Diagonal 200",
"ciudad": "Barcelona"
}
}
A TENER EN CUENTA

Las respuestas de la API siempre devuelven un objeto principal llamado data

Por tanto, para acceder a la información real será necesario acceder primero a la clave data

Adaptaciones en Flask

1. Importar dependencias necesarias

Para realizar peticiones HTTP a la API:

import requests

Para retornar respuestas JSON desde Flask:

from flask import jsonify

También puedes añadir jsonify al import principal de Flask:

from flask import Flask, render_template, request, redirect, url_for, session, jsonify

2. Instalar dependencias

Con el entorno virtual activado, ejecutar:

pip install requests

El paquete correcto es requests, no request.


3. Actualizar archivo requirements.txt

Desde la raíz del proyecto ejecutar:

pip freeze > requirements.txt

4. Adaptar el método que carga el formulario de registro

La aplicación debe obtener la lista de sedes y departamentos mediante peticiones HTTP a la API.

Ejemplo:

@app.route("/form", methods=['GET'])
def form():

print("Has entrado en el formulario")

# Obtener sedes
url = "http://info.empresa.dam.es:8055/items/sedes"
respuesta = requests.get(url)
datosSedes = respuesta.json()

# Obtener departamentos
url = "http://info.empresa.dam.es:8055/items/departamentos"
respuesta = requests.get(url)
datosDepartamentos = respuesta.json()

return render_template(
"formulario.html",
departamentos=datosDepartamentos['data'],
sedes=datosSedes['data']
)

5. Uso de sedes y departamentos en HTML

La API retorna un JSON con una estructura similar a esta:

{
"data": [
{
"id": 1,
"nombre": "Mantenimiento"
}
]
}

Por tanto, será necesario acceder a la clave data.


Sedes

<select name="id_sede" id="id_sede">

{% for sede in sedes %}

<option value="{{ sede.id }}">
{{ sede.nombre }}
</option>

{% endfor %}

</select>

Departamentos

<select name="id_dpto" id="id_dpto">

{% for dpto in departamentos %}

<option value="{{ dpto.id }}">
{{ dpto.nombre }}
</option>

{% endfor %}

</select>

6. Capturar datos enviados desde el formulario

Ejemplo:

id_dpto = int(request.form.get("id_dpto"))
id_sede = int(request.form.get("id_sede"))

Estos valores corresponden a los identificadores seleccionados en los <select> del formulario.

note

Será necesario adaptar el procedimiento almacenado para aceptar estos nuevos parámetros.


Obtener empleados mediante API Flask

La información de empleados debe obtenerse mediante la API desarrollada en Flask.

La aplicación no debe acceder directamente a la base de datos de empleados desde otros servicios.


Ejemplo de ruta protegida

@app.route("/usuarios", methods=["GET"])
@login_requerido
def usuarios():

if session.get("user") == "admin" and session.get("roles") == "admin":

with get_conn() as conn:
with conn.cursor() as cur:

cur.execute("SELECT * FROM usuarios;")

filas = cur.fetchall()

return jsonify(filas)

else:
return f"No tienes permisos {session.get('user')}"

Funcionamiento

  1. El cliente realiza una petición GET a la ruta /usuarios.
  2. La ruta está protegida mediante @login_requerido.
  3. Flask comprueba que existe una sesión activa.
  4. Se obtienen los datos guardados en session.
  5. Se verifica que el usuario tenga rol ADMIN.
  6. Si tiene permisos:
    • Se consulta la base de datos.
    • Se retornan los datos en formato JSON.
  7. Si no tiene permisos:
    • Se bloquea el acceso.

Decorador @login_requerido

El decorador @login_requerido permite proteger rutas privadas.

Su objetivo es comprobar que el usuario ha iniciado sesión antes de acceder a determinadas páginas o recursos.

Ejemplo:

@login_requerido

Si no existe sesión activa:

  • El usuario no podrá acceder.
  • Flask podrá redirigir al login o bloquear el acceso.

Uso de session

Durante el login se almacenan datos en la sesión:

session["user"] = usuario
session["roles"] = rol

Estos valores pueden utilizarse posteriormente para:

  • Comprobar permisos.
  • Identificar al usuario autenticado.
  • Restringir acceso a rutas privadas.
  • Mostrar información personalizada.