N. Carpeta « srv »

Versión para imprimir.

A. Carpeta « srv / const »

Versión para imprimir.

1. srv / const / CUE.php

1<?php
2
3const CUE = "cue";

2. srv / const / ROL_ADMINISTRADOR.php

1<?php
2
3const ROL_ADMINISTRADOR = "Administrador";
4

3. srv / const / ROL_CLIENTE.php

1<?php
2
3const ROL_CLIENTE = "Cliente";

4. srv / const / ROL_IDS.php

1<?php
2
3const ROL_IDS = "rolIds";

B. Carpeta « srv / modelo »

Versión para imprimir.

1. srv / modelo / Rol.php

1<?php
2
3require_once __DIR__ . "/../../lib/php/ProblemDetails.php";
4
5class Rol
6{
7
8 public string $id;
9 public string $descripcion;
10
11 public function __construct(string $descripcion = "", string $id = "")
12 {
13 $this->id = $id;
14 $this->descripcion = $descripcion;
15 }
16
17 public function valida()
18 {
19
20 if ($this->id === "")
21 throw new ProblemDetails(
22 status: ProblemDetails::BadRequest,
23 type: "/error/faltaid.html",
24 title: "Falta el id.",
25 );
26
27 if ($this->descripcion === "")
28 throw new ProblemDetails(
29 status: ProblemDetails::BadRequest,
30 type: "/error/faltadescripcion.html",
31 title: "Falta la descripción.",
32 );
33 }
34}
35

2. srv / modelo / Usuario.php

1<?php
2
3require_once __DIR__ . "/../../lib/php/ProblemDetails.php";
4require_once __DIR__ . "/Rol.php";
5
6class Usuario
7{
8
9 public int $id;
10 public string $cue;
11 public string $match;
12 /** @var Rol[] */
13 public array $roles;
14
15 public function __construct(
16 string $cue = "",
17 string $match = "",
18 array $roles = [],
19 int $id = 0
20 ) {
21 $this->id = $id;
22 $this->cue = $cue;
23 $this->match = $match;
24 $this->roles = $roles;
25 }
26
27 public function valida()
28 {
29
30 if ($this->cue === "")
31 throw new ProblemDetails(
32 status: ProblemDetails::BadRequest,
33 type: "/error/faltacue.html",
34 title: "Falta el cue.",
35 );
36
37 if ($this->match === "")
38 throw new ProblemDetails(
39 status: ProblemDetails::BadRequest,
40 type: "/error/faltamatch.html",
41 title: "Falta el match.",
42 );
43
44 foreach ($this->roles as $rol) {
45 if (!($rol instanceof Rol))
46 throw new ProblemDetails(
47 status: ProblemDetails::BadRequest,
48 type: "/error/rolincorrecto.html",
49 title: "Tipo incorrecto para un rol.",
50 );
51 }
52 }
53}
54

C. srv / protege.php

1<?php
2
3require_once __DIR__ . "/../lib/php/ejecutaServicio.php";
4require_once __DIR__ . "/../lib/php/ProblemDetails.php";
5require_once __DIR__ . "/const/CUE.php";
6require_once __DIR__ . "/const/ROL_IDS.php";
7require_once __DIR__ . "/const/ROL_CLIENTE.php";
8require_once __DIR__ . "/Sesion.php";
9
10const NO_AUTORIZADO = 401;
11
12function protege(?array $rolIdsPermitidos = null)
13{
14 session_start();
15 $cue = isset($_SESSION[CUE])
16 ? $_SESSION[CUE]
17 : "";
18 $rolIds = isset($_SESSION[ROL_IDS])
19 ? $_SESSION[ROL_IDS]
20 : [];
21 $sesion = new Sesion($cue, $rolIds);
22 if ($rolIdsPermitidos === null) {
23 return $sesion;
24 } else {
25 foreach ($rolIdsPermitidos as $rolId) {
26 if (array_search($rolId, $rolIds, true) !== false) {
27 return $sesion;
28 }
29 }
30 throw new ProblemDetails(
31 status: NO_AUTORIZADO,
32 type: "/error/noautorizado.html",
33 title: "No autorizado.",
34 detail: "No está autorizado para usar este recurso.",
35 );
36 }
37}
38

D. srv / Sesion.php

1<?php
2
3class Sesion
4{
5
6 public string $cue;
7 public array $rolIds;
8
9 public function __construct(string $cue, array $rolIds)
10 {
11 $this->cue = $cue;
12 $this->rolIds = $rolIds;
13 }
14}
15

E. srv / srvLogin.php

1<?php
2
3require_once __DIR__ . "/../lib/php/ejecutaServicio.php";
4require_once __DIR__ . "/../lib/php/ProblemDetails.php";
5require_once __DIR__ . "/../lib/php/leeTexto.php";
6require_once __DIR__ . "/const/CUE.php";
7require_once __DIR__ . "/const/ROL_IDS.php";
8require_once __DIR__ . "/modelo/Rol.php";
9require_once __DIR__ . "/bd/usuarioVerifica.php";
10require_once __DIR__ . "/protege.php";
11
12ejecutaServicio(function () {
13 $sesion = protege();
14 if ($sesion->cue !== "") {
15 throw new ProblemDetails(
16 status: NO_AUTORIZADO,
17 type: "/error/sesioniniciada.html",
18 title: "Sesión iniciada.",
19 detail: "La sesión ya está iniciada.",
20 );
21 }
22 $cue = leeTexto("cue");
23 $match = leeTexto("match");
24 if ($cue === null || $cue === "")
25 throw new ProblemDetails(
26 status: ProblemDetails::BadRequest,
27 type: "/error/faltacue.html",
28 title: "Falta el cue.",
29 );
30
31 if ($match === null || $match === "")
32 throw new ProblemDetails(
33 status: ProblemDetails::BadRequest,
34 type: "/error/faltamatch.html",
35 title: "Falta el match.",
36 );
37
38 $usuario = usuarioVerifica(trim($cue), trim($match));
39 if ($usuario === false) {
40 throw new ProblemDetails(
41 status: ProblemDetails::BadRequest,
42 type: "/error/datosincorrectos.html",
43 title: "Datos incorrectos.",
44 detail: "El cue y/o el match proporcionados son incorrectos.",
45 );
46 } else {
47 $rolIds = [];
48 foreach ($usuario->roles as $rol) {
49 $rolIds[] = $rol->id;
50 }
51 $_SESSION[CUE] = $cue;
52 $_SESSION[ROL_IDS] = $rolIds;
53 return [
54 CUE => $cue,
55 ROL_IDS => $rolIds
56 ];
57 }
58});
59

F. srv / srvLogout.php

1<?php
2
3require_once __DIR__ . "/../lib/php/ejecutaServicio.php";
4require_once __DIR__ . "/const/CUE.php";
5require_once __DIR__ . "/const/ROL_IDS.php";
6
7ejecutaServicio(function () {
8 session_start();
9 if (isset($_SESSION[CUE])) {
10 unset($_SESSION[CUE]);
11 }
12 if (isset($_SESSION[ROL_IDS])) {
13 unset($_SESSION[ROL_IDS]);
14 }
15 session_destroy();
16 return [];
17});
18

G. srv / srvSaludoCliente.php

1<?php
2
3require_once __DIR__ . "/../lib/php/ejecutaServicio.php";
4require_once __DIR__ . "/const/ROL_CLIENTE.php";
5require_once __DIR__ . "/protege.php";
6
7ejecutaServicio(function () {
8 $sesion = protege([ROL_CLIENTE]);
9 return "Hola " . $sesion->cue;
10});
11

H. srv / srvSesion.php

1<?php
2
3require_once __DIR__ . "/../lib/php/ejecutaServicio.php";
4require_once __DIR__ . "/protege.php";
5
6ejecutaServicio(function () {
7 return protege();
8});
9

I. Carpeta « srv / bd »

Versión para imprimir.

1. srv / bd / bdCrea.php

1<?php
2
3function bdCrea(PDO $con)
4{
5 $con->exec(
6 'CREATE TABLE IF NOT EXISTS USUARIO (
7 USU_ID INTEGER,
8 USU_CUE TEXT NOT NULL,
9 USU_MATCH TEXT NOT NULL,
10 CONSTRAINT USU_PK
11 PRIMARY KEY(USU_ID),
12 CONSTRAINT USU_CUE_UNQ
13 UNIQUE(USU_CUE)
14 )'
15 );
16 $con->exec(
17 'CREATE TABLE IF NOT EXISTS ROL (
18 ROL_ID TEXT,
19 ROL_DESCRIPCION TEXT NOT NULL,
20 CONSTRAINT ROL_PK
21 PRIMARY KEY(ROL_ID),
22 CONSTRAINT ROL_DESCR_UNQ
23 UNIQUE(ROL_DESCRIPCION)
24 )'
25 );
26 $con->exec(
27 'CREATE TABLE IF NOT EXISTS USU_ROL (
28 USU_ID INTEGER NOT NULL,
29 ROL_ID TEXT NOT NULL,
30 CONSTRAINT USU_ROL_PK
31 PRIMARY KEY(USU_ID, ROL_ID),
32 CONSTRAINT USU_ROL_USU_FK
33 FOREIGN KEY (USU_ID) REFERENCES USUARIO(USU_ID),
34 CONSTRAINT USU_ROL_ROL_FK
35 FOREIGN KEY (ROL_ID) REFERENCES ROL(ROL_ID)
36 )'
37 );
38}
39

2. srv / bd / Bd.php

1<?php
2
3require_once __DIR__ . "/../const/ROL_CLIENTE.php";
4require_once __DIR__ . "/../const/ROL_ADMINISTRADOR.php";
5require_once __DIR__ . "/../modelo/Rol.php";
6require_once __DIR__ . "/../modelo/Usuario.php";
7require_once __DIR__ . "/bdCrea.php";
8require_once __DIR__ . "/usuarioBuscaCue.php";
9require_once __DIR__ . "/usuarioAgrega.php";
10require_once __DIR__ . "/rolConsulta.php";
11require_once __DIR__ . "/rolAgrega.php";
12require_once __DIR__ . "/rolBusca.php";
13
14class Bd
15{
16
17 private static ?PDO $conexion = null;
18
19 static function getConexion(): PDO
20 {
21 if (self::$conexion === null) {
22
23 self::$conexion = new PDO(
24 // cadena de conexión
25 "sqlite:srvaut.db",
26 // usuario
27 null,
28 // contraseña
29 null,
30 // Opciones: conexiones persistentes y lanza excepciones.
31 [PDO::ATTR_PERSISTENT => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
32 );
33
34 bdCrea(self::$conexion);
35
36 if (rolBusca(ROL_ADMINISTRADOR) === false) {
37 $administrador = new Rol(
38 id: ROL_ADMINISTRADOR,
39 descripcion: "Administra el sistema."
40 );
41 rolAgrega($administrador);
42 }
43
44 if (rolBusca("Cliente") === false) {
45 $cliente = new Rol(
46 id: "Cliente",
47 descripcion: "Realiza compras."
48 );
49 rolAgrega($cliente);
50 }
51
52 if (usuarioBuscaCue("pepito") === false) {
53 $usuario = new Usuario(
54 cue: "pepito",
55 match: "cuentos",
56 roles: [$cliente]
57 );
58 usuarioAgrega($usuario);
59 }
60
61 if (usuarioBuscaCue("susana") === false) {
62 $usuario = new Usuario(
63 cue: "susana",
64 match: "alegria",
65 roles: [$administrador]
66 );
67 usuarioAgrega($usuario);
68 }
69
70 if (usuarioBuscaCue("bebe") === false) {
71 $usuario = new Usuario(
72 cue: "bebe",
73 match: "saurio",
74 roles: [$administrador, $cliente]
75 );
76 usuarioAgrega($usuario);
77 }
78 }
79
80 return self::$conexion;
81 }
82}
83

3. srv / bd / rolAgrega.php

1<?php
2
3require_once __DIR__ . "/../modelo/Rol.php";
4require_once __DIR__ . "/Bd.php";
5
6function rolAgrega(Rol $modelo)
7{
8 $modelo->valida();
9 $con = Bd::getConexion();
10 $stmt = $con->prepare(
11 "INSERT INTO ROL
12 (ROL_ID, ROL_DESCRIPCION)
13 VALUES
14 (:id, :descripcion)"
15 );
16 $stmt->execute([
17 ":id" => $modelo->id,
18 ":descripcion" => $modelo->descripcion
19 ]);
20}
21

4. srv / bd / rolBusca.php

1<?php
2
3require_once __DIR__ . "/../modelo/Rol.php";
4require_once __DIR__ . "/Bd.php";
5require_once __DIR__ . "/usuRolConsulta.php";
6
7function rolBusca(string $id) : false|Rol
8{
9 $con = Bd::getConexion();
10 $stmt = $con->prepare(
11 "SELECT
12 ROL_ID as id,
13 ROL_DESCRIPCION as descripcion
14 FROM ROL
15 WHERE ROL_ID = :id"
16 );
17 $stmt->execute([":id" => $id]);
18 $stmt->setFetchMode(
19 PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE,
20 Rol::class
21 );
22 return $stmt->fetch();
23}
24

5. srv / bd / rolConsulta.php

1<?php
2
3require_once __DIR__ . "/../../lib/php/recibeFetchAll.php";
4require_once __DIR__ . "/../modelo/Rol.php";
5require_once __DIR__ . "/Bd.php";
6
7/** @return Rol[] */
8function rolConsulta()
9{
10 $con = Bd::getConexion();
11 $stmt = $con->query(
12 "SELECT
13 ROL_ID as id,
14 ROL_DESCRIPCION as descripcion
15 FROM ROL
16 ORDER BY ROL_ID"
17 );
18 $resultado = $stmt->fetchAll(
19 PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE,
20 Rol::class
21 );
22 return recibeFetchAll($resultado);
23}
24

6. srv / bd / usuarioAgrega.php

1<?php
2
3require_once __DIR__ . "/../modelo/Usuario.php";
4require_once __DIR__ . "/Bd.php";
5require_once __DIR__ . "/usuRolAgrega.php";
6
7function usuarioAgrega(Usuario $modelo)
8{
9 $modelo->valida();
10 $con = Bd::getConexion();
11 $con->beginTransaction();
12 $stmt = $con->prepare(
13 "INSERT INTO USUARIO
14 (USU_CUE, USU_MATCH)
15 VALUES
16 (:cue, :match)"
17 );
18 $stmt->execute([
19 ":cue" => $modelo->cue,
20 ":match" => password_hash($modelo->match, PASSWORD_DEFAULT)
21 ]);
22 /* Si usas una secuencia para generar el id,
23 * pasa como parámetro de lastInsertId el
24 * nombre de dicha secuencia. */
25 $modelo->id = $con->lastInsertId();
26 usuRolAgrega($modelo);
27 $con->commit();
28}
29

7. srv / bd / usuarioBuscaCue.php

1<?php
2
3require_once __DIR__ . "/../modelo/Usuario.php";
4require_once __DIR__ . "/Bd.php";
5require_once __DIR__ . "/usuRolConsulta.php";
6
7function usuarioBuscaCue(string $cue)
8{
9 $con = Bd::getConexion();
10 $stmt = $con->prepare(
11 "SELECT
12 USU_ID as id,
13 USU_CUE as cue,
14 USU_MATCH as match
15 FROM USUARIO
16 WHERE USU_CUE = :cue"
17 );
18 $stmt->execute([":cue" => $cue]);
19 $stmt->setFetchMode(
20 PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE,
21 Usuario::class
22 );
23 /** @var false|Usuario */
24 $usuario = $stmt->fetch();
25 if ($usuario === false) {
26 return false;
27 } else {
28 $usuario->roles = usuRolConsulta($usuario->id);
29 return $usuario;
30 }
31}
32

8. srv / bd / usuarioVerifica.php

1<?php
2
3require_once __DIR__ . "/usuarioBuscaCue.php";
4
5function usuarioVerifica(string $cue, string $match)
6{
7 $usuario = usuarioBuscaCue($cue);
8 if ($usuario !== false && password_verify($match, $usuario->match)) {
9 return $usuario;
10 } else {
11 return false;
12 }
13}
14

9. srv / bd / usuRolAgrega.php

1<?php
2
3require_once __DIR__ . "/../modelo/Usuario.php";
4require_once __DIR__ . "/Bd.php";
5
6function usuRolAgrega(Usuario $usuario) {
7 $roles = $usuario->roles;
8 if (sizeof($roles) > 0) {
9 $con = Bd::getConexion();
10 $stmt = $con->prepare(
11 "INSERT INTO USU_ROL
12 (USU_ID, ROL_ID)
13 VALUES
14 (:usuId, :rolId)"
15 );
16 foreach ($roles as $rol) {
17 $stmt->execute(
18 [
19 ":usuId" => $usuario->id,
20 ":rolId" => $rol->id
21 ]
22 );
23 }
24 }
25}
26

10. srv / bd / usuRolConsulta.php

1<?php
2
3require_once __DIR__ . "/../../lib/php/recibeFetchAll.php";
4require_once __DIR__ . "/../modelo/Rol.php";
5require_once __DIR__ . "/Bd.php";
6
7/** @return Rol[] */
8function usuRolConsulta(int $usuId)
9{
10 $con = Bd::getConexion();
11 $stmt = $con->query(
12 "SELECT
13 UR.ROL_ID AS id,
14 R.ROL_DESCRIPCION AS descripcion
15 FROM USU_ROL UR, ROL R
16 WHERE
17 UR.ROL_ID = R.ROL_ID
18 AND UR.USU_ID = :usuId
19 ORDER BY UR.ROL_ID"
20 );
21 $stmt->execute([":usuId" => $usuId]);
22 $resultado = $stmt->fetchAll(
23 PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE,
24 Rol::class
25 );
26 return recibeFetchAll($resultado);
27}
28