Tauler d'administració: diferència entre les revisions
| (Hi ha 2 revisions intermèdies que no es mostren del mateix usuari) | |||
| Línia 36: | Línia 36: | ||
Les obtindrem mitjançant una consulta a la taula activitat, on realitzarem la suma de registres que coincideixin amb la paraula clau de la seva respectiva acció<pre> | Les obtindrem mitjançant una consulta a la taula activitat, on realitzarem la suma de registres que coincideixin amb la paraula clau de la seva respectiva acció<pre> | ||
// Consulta SQL per obtenir les estadístiques | // Consulta SQL per obtenir les estadístiques | ||
$stmt = $pdo->query(" | |||
SELECT | |||
-- Autenticacions correctes (login + auto-login) de tothom | |||
SUM(a.accio IN ('login', 'auto-login')) AS total_autenticacions, | |||
-- Logins erronis de tothom | |||
SUM(a.accio = 'error-login') AS total_error_logins, | |||
-- Restabliments de contrasenyes | |||
SUM(a.accio = 'restablir-contrasenya') AS total_restabliment_contrasenyes, | |||
-- Autenticacions correctes d'usuaris normals | |||
SUM( | |||
a.accio IN ('login', 'auto-login') | |||
AND u.rol = 'usuari' | |||
) AS auth_usuaris, | |||
-- Logins erronis d'usuaris normals | |||
SUM( | |||
a.accio = 'error-login' | |||
AND u.rol = 'usuari' | |||
) AS errors_usuaris, | |||
-- Restabliment de contrasenyes d'usuaris normals | |||
SUM( | |||
a.accio = 'restablir-contrasenya' | |||
AND u.rol = 'usuari' | |||
) AS restabliments_contrasenya_usuaris, | |||
-- Autenticacions correctes d'administradors | |||
SUM( | |||
a.accio IN ('login', 'auto-login') | |||
AND u.rol IN ('ed_admin', 'vi_admin') | |||
) AS auth_admins, | |||
-- Logins erronis d'administradors | |||
SUM( | |||
a.accio = 'error-login' | |||
AND u.rol IN ('ed_admin', 'vi_admin') | |||
) AS errors_admins, | |||
-- Restabliment de contrasenyes d'administradors | |||
SUM( | |||
a.accio = 'restablir-contrasenya' | |||
AND u.rol IN ('ed_admin', 'vi_admin') | |||
) AS restabliments_contrasenya_admins | |||
FROM activitat a | |||
JOIN usuaris u ON u.id = a.usuari_id | |||
"); | |||
$autenticacions = $stmt->fetch(); | |||
</pre> | </pre> | ||
| Línia 92: | Línia 92: | ||
Per mostrar-les, únicament recuperarem les dades de la consulta i les afegirem en HTML, sempre escapant sortides.<pre> | Per mostrar-les, únicament recuperarem les dades de la consulta i les afegirem en HTML, sempre escapant sortides.<pre> | ||
<section class="stats-section"> | <section class="stats-section"> | ||
<h2 class="section-title">Estadístiques globals</h2> | |||
<div class="stats-grid-top"> | |||
<div class="stat-card main"> | |||
<span class="label">Total Autenticacions</span> | |||
<span class="value"><?= $autenticacions['total_autenticacions'] ?? 0 ?></span> | |||
</div> | |||
<div class="stat-card error"> | |||
<span class="label">Logins Erronis</span> | |||
<span class="value"><?= $autenticacions['total_error_logins'] ?? 0 ?></span> | |||
</div> | |||
<div class="stat-card warn"> | |||
<span class="label">Restabliments</span> | |||
<span class="value"><?= $autenticacions['total_restabliment_contrasenyes'] ?? 0 ?></span> | |||
</div> | |||
</div> | |||
<div class="stats-grid-secondary"> | |||
<div class="stat-group"> | |||
<h3>Usuaris normals</h3> | |||
<div class="row"><span>Autenticacions:</span> <strong><?= $autenticacions['auth_usuaris'] ?? 0 ?></strong></div> | |||
<div class="row"><span>Errors d'autenticació:</span> <strong><?= $autenticacions['errors_usuaris'] ?? 0 ?></strong></div> | |||
<div class="row"><span>Restabliments de contrasenyes:</span> <strong><?= $autenticacions['restabliments_contrasenya_usuaris'] ?? 0 ?></strong></div> | |||
</div> | |||
<div class="stat-group"> | |||
<h3>Administradors</h3> | |||
<div class="row"><span>Autenticacions:</span> <strong><?= $autenticacions['auth_admins'] ?? 0 ?></strong></div> | |||
<div class="row"><span>Errors d'autenticació:</span> <strong><?= $autenticacions['errors_admins'] ?? 0 ?></strong></div> | |||
<div class="row"><span>Restabliments de contrasenyes:</span> <strong><?= $autenticacions['restabliments_contrasenya_admins'] ?? 0 ?></strong></div> | |||
</div> | |||
</div> | |||
</section> | |||
</pre>Les estadístiques globals es visualitzarien de la següent manera | </pre>Les estadístiques globals es visualitzarien de la següent manera | ||
[[Fitxer:EstadistiquesGlobals.png|center|miniatura|768x768px]] | [[Fitxer:EstadistiquesGlobals.png|center|miniatura|768x768px]] | ||
| Línia 133: | Línia 133: | ||
Per poder verificar si l'usuari és administrador editor, fem servir la funció [[Funcions de la pràctica 5.3#es admin ed|es_admin_ed]]. | Per poder verificar si l'usuari és administrador editor, fem servir la funció [[Funcions de la pràctica 5.3#es admin ed|es_admin_ed]]. | ||
'''<?php if (es_admin_ed()): ?>''' | '''<?php if (es_admin_ed()): ?>''' | ||
<section class="management-section"> | |||
<nowiki><div class="danger-zone"></nowiki> | |||
<form method="post"> | |||
<input type="hidden" name="borrar_activitat" value="1"> | |||
<button type="submit" class="btn-danger" onclick="return confirm('Segur que vols borrar tot el historial?');"> | |||
Borrar tot el registre d'activitats | |||
</button> | |||
</ | </form> | ||
<nowiki></div></nowiki> | |||
<nowiki><h2 class="section-title">Gestió d'accés d'usuaris</h2></nowiki> | |||
<nowiki><div class="management-grid"></nowiki> | |||
<nowiki><div class="tool-card"></nowiki> | |||
<nowiki><h3>Restablir contrasenya</h3></nowiki> | |||
<form method="post"> | |||
<nowiki><div class="input-group"></nowiki> | |||
<label>Nom d'usuari</label> | |||
<input type="text" name="usuari_nom" required> | |||
<nowiki></div></nowiki> | <nowiki></div></nowiki> | ||
<nowiki><div class="input-group"></nowiki> | |||
<label>Nova contrasenya</label> | |||
<input type="password" name="nova_contrasenya" required> | |||
<nowiki></div></nowiki> | |||
<button type="submit" class="btn-action">Restablir ara</button> | |||
</form> | |||
<?php if ($missatge): ?> | |||
<nowiki><p class="msg success"><?= $missatge ?></p></nowiki> | |||
<?php endif; ?> | |||
<?php if ($error): ?> | |||
<nowiki><p class="msg error"><?= $error ?></p></nowiki> | |||
<?php endif; ?> | |||
<nowiki></div></nowiki> | |||
<nowiki><div class="tool-card"></nowiki> | |||
<nowiki><h3>Desbloquejar compte</h3></nowiki> | |||
<form method="POST"> | |||
<nowiki><div class="input-group"></nowiki> | |||
<label>Nom d'usuari</label> | |||
<input type="text" name="usuari_nom_desbloquejar" required> | |||
<nowiki></div></nowiki> | <nowiki></div></nowiki> | ||
</section> | <button type="submit" name="desbloquejar" class="btn-action secondary">Desbloquejar usuari</button> | ||
<?php if ($missatgeDesbloqueig): ?> | |||
<nowiki><p class="msg success"><?= $missatgeDesbloqueig ?></p></nowiki> | |||
<?php endif; ?> | |||
</form> | |||
<nowiki></div></nowiki> | |||
<nowiki></div></nowiki> | |||
</section> | |||
<?php endif; ?> | |||
=== Formulari de restabliment de contrasenyes === | === Formulari de restabliment de contrasenyes === | ||
| Línia 185: | Línia 190: | ||
El formulari es visualitzaria de la següent manera | El formulari es visualitzaria de la següent manera | ||
[[Fitxer:FormulariAdminRestablimentContrasenya.png|center|miniatura]] | [[Fitxer:FormulariAdminRestablimentContrasenya.png|center|miniatura]] | ||
Un cop es respon al formulari de restabliment de contrasenya, recollim els paràmetres i els desem a una variable, per posteriorment verificar que no estan buits, ja que al ser un formulari opcional, en l'HTML no els requerim i es poden enviar perfectament buits<pre> | Un cop es respon al formulari de restabliment de contrasenya, recollim els paràmetres i els desem a una variable, per posteriorment verificar que no estan buits, ja que al ser un formulari opcional, en l'HTML no els requerim i es poden enviar perfectament buits<pre> | ||
$usuari_nom = trim($_POST['usuari_nom']); | |||
if ($usuari_nom === '') { // Verifiquem que el nom d'usuari tingui un valor | |||
$error = "Indica un nom d'usuari."; | |||
} elseif (empty($_POST['nova_contrasenya'])) { // Verifiquem que la contrasenya tingui un valor | |||
$error = "Indica una contrasenya."; | |||
} else { | |||
</pre>Seguidament, comprovem que l'usuari existeixi realitzant una consulta SQL on es cerca un usuari amb el mateix nom d'usuari<pre> | </pre>Seguidament, comprovem que l'usuari existeixi realitzant una consulta SQL on es cerca un usuari amb el mateix nom d'usuari<pre> | ||
// Ens assegurem que el nom d'usuari existeixi | // Ens assegurem que el nom d'usuari existeixi | ||
$stmt = $pdo->prepare("SELECT id FROM usuaris WHERE nom_usuari = ?"); | |||
$stmt->execute([$usuari_nom]); | |||
$usuari = $stmt->fetch(); | |||
if (!$usuari) { | |||
$error = "Usuari no trobat."; | |||
} else { | |||
</pre>Si l'usuari existeix encriptarem la contrasenya i la actualitzarem a la BD. Posteriorment, restablirem els intents de login a 0 per a més a més desbloquejar el compte i afegirem una acció nomenada "restablir-contrasenya" a aquell usuari<pre> | </pre>Si l'usuari existeix encriptarem la contrasenya i la actualitzarem a la BD. Posteriorment, restablirem els intents de login a 0 per a més a més desbloquejar el compte i afegirem una acció nomenada "restablir-contrasenya" a aquell usuari<pre> | ||
// Si l'usuari existeix, actualitzem contrasenya i nombre d'intents | |||
if (isset($_POST['nova_contrasenya']) && $_POST['nova_contrasenya'] !== '') { | |||
// Recuperem la contrasenya del formulari | |||
$nova_contrasenya = trim($_POST['nova_contrasenya']); | |||
// Encriptem la contrasenya | |||
$hash = password_hash($nova_contrasenya, PASSWORD_DEFAULT); | |||
// Inserim la nova contrasenya | |||
$stmt = $pdo->prepare("UPDATE usuaris SET contrasenya = ? WHERE id = ?"); | |||
$stmt->execute([$hash, $usuari['id']]); | |||
// Reiniciem el número d'intents a 0, així també desbloquejem l'usuari | |||
$stmt = $pdo->prepare("UPDATE usuaris SET intents_login = 0, ultim_intent = NULL WHERE id = ?"); | |||
$stmt->execute([$usuari['id']]); | |||
// Definim missatge i registrem activitat | |||
$missatge = "Contrasenya restablerta correctament."; | |||
registrar_activitat($pdo, $usuari['id'], 'restablir-contrasenya'); | |||
</pre> | </pre> | ||
| Línia 233: | Línia 236: | ||
El formulari es visualitzaria de la següent manera | El formulari es visualitzaria de la següent manera | ||
[[Fitxer:FormulariAdminDesbloqueigUsuari.png|center|miniatura]] | [[Fitxer:FormulariAdminDesbloqueigUsuari.png|center|miniatura]] | ||
Quan es respon al formulari de desbloqueig d'usuari, es recupera el nom d'usuari introduit i ens assegurem que no estigui buit, ja que al ser un formulari opcional, en l'HTML no els requerim i es poden enviar perfectament buits<pre> | Quan es respon al formulari de desbloqueig d'usuari, es recupera el nom d'usuari introduit i ens assegurem que no estigui buit, ja que al ser un formulari opcional, en l'HTML no els requerim i es poden enviar perfectament buits<pre> | ||
$usuari_nom = trim($_POST['usuari_nom_desbloquejar']); | $usuari_nom = trim($_POST['usuari_nom_desbloquejar']); | ||
if ($usuari_nom === '') { // Verifiquem que l'usuari tingui un valor | |||
$error = "Omple el nom d'usuari per desbloquejar."; | |||
</pre>Seguidament, comprovem que l'usuari existeixi realitzant una consulta SQL on es cerca un usuari amb el mateix nom d'usuari<pre> | </pre>Seguidament, comprovem que l'usuari existeixi realitzant una consulta SQL on es cerca un usuari amb el mateix nom d'usuari<pre> | ||
// Verifiquem que l'usuari existeixi | |||
$stmt = $pdo->prepare("SELECT id FROM usuaris WHERE nom_usuari = ?"); | |||
$stmt->execute([$usuari_nom]); | |||
$usuari = $stmt->fetch(); | |||
if (!$usuari) { | |||
$error = "Usuari no trobat."; | |||
</pre>Si l'usuari existeix, actualitzem el seu número d'intents de login a 0 i registrem una acció nomenada "desbloquejar-compte"<pre> | </pre>Si l'usuari existeix, actualitzem el seu número d'intents de login a 0 i registrem una acció nomenada "desbloquejar-compte"<pre> | ||
} else { | } else { | ||
// Si existeix, definim el nombre d'intents de login a 0 i registrem l'acció "desbloquejar-compte" | |||
$stmt = $pdo->prepare("UPDATE usuaris SET intents_login = 0, ultim_intent = NULL WHERE id = ?"); | |||
$stmt->execute([$usuari['id']]); | |||
$missatgeDesbloqueig = "Compte desbloquejat correctament."; | |||
registrar_activitat($pdo, $usuari['id'], 'desbloquejar-compte'); | |||
} | |||
</pre> | </pre> | ||
Revisió de 02:29, 12 gen 2026
Tauler d'administració
Tots els usuaris administradors tenen accés a un tauler d'administració on es pot consultar les estadístiques globals de l'aplicació. A més a més, si l'usuari és administrador editor, pot accedir a uns formularis de gestió d'usuaris
Inicialització de la sessió i connexió a la BD
Sempre que es treballa amb sessions, el primer que hem de fer és iniciar-la abans d'escriure el codi HTML
session_start();
A més, hem de requerir el fitxer amb les funcions i una connexió a la BD. En aquest cas, com hem de modificar dades d'usuaris i per tant actualitzar registres de la BD farem servir la connexió d'escriptura.
require 'funcions.php'; require './connexioBD/connexioRW.php';
Requerir autenticació i ser administrador
Per accedir a aquesta pàgina, és imperatiu que l'usuari estigui autenticat, en cas contrari no hi pot accedir. Per verificar que l'usuari està autenticat, farem servir la funció requerir_autenticacio
// Requerir autenticació per accedir a la pàgina requerir_autenticacio();
A més, per accedir a aquesta pàgina l'usuari ha de tenir el rol d'administrador editor o administrador lector. Per comprovar-ho farem servir la funció es_admin
Mostra d'estadístiques globals
Obtenció d'estadístiques globals
Les estadístiques globals són:
- De tots els usuaris
- Autenticacions exitoses
- Autenticacions errònies
- Restabliments de contrasenyes
- Dels usuaris normals
- Autenticacions exitoses
- Autenticacions errònies
- Restabliments de contrasenyes
- Dels administradors (editors i visualitzadors)
- Autenticacions exitoses
- Autenticacions errònies
- Restabliments de contrasenyes
Les obtindrem mitjançant una consulta a la taula activitat, on realitzarem la suma de registres que coincideixin amb la paraula clau de la seva respectiva acció
// Consulta SQL per obtenir les estadístiques
$stmt = $pdo->query("
SELECT
-- Autenticacions correctes (login + auto-login) de tothom
SUM(a.accio IN ('login', 'auto-login')) AS total_autenticacions,
-- Logins erronis de tothom
SUM(a.accio = 'error-login') AS total_error_logins,
-- Restabliments de contrasenyes
SUM(a.accio = 'restablir-contrasenya') AS total_restabliment_contrasenyes,
-- Autenticacions correctes d'usuaris normals
SUM(
a.accio IN ('login', 'auto-login')
AND u.rol = 'usuari'
) AS auth_usuaris,
-- Logins erronis d'usuaris normals
SUM(
a.accio = 'error-login'
AND u.rol = 'usuari'
) AS errors_usuaris,
-- Restabliment de contrasenyes d'usuaris normals
SUM(
a.accio = 'restablir-contrasenya'
AND u.rol = 'usuari'
) AS restabliments_contrasenya_usuaris,
-- Autenticacions correctes d'administradors
SUM(
a.accio IN ('login', 'auto-login')
AND u.rol IN ('ed_admin', 'vi_admin')
) AS auth_admins,
-- Logins erronis d'administradors
SUM(
a.accio = 'error-login'
AND u.rol IN ('ed_admin', 'vi_admin')
) AS errors_admins,
-- Restabliment de contrasenyes d'administradors
SUM(
a.accio = 'restablir-contrasenya'
AND u.rol IN ('ed_admin', 'vi_admin')
) AS restabliments_contrasenya_admins
FROM activitat a
JOIN usuaris u ON u.id = a.usuari_id
");
$autenticacions = $stmt->fetch();
Mostra d'estadístiques globals
Per mostrar-les, únicament recuperarem les dades de la consulta i les afegirem en HTML, sempre escapant sortides.
<section class="stats-section">
<h2 class="section-title">Estadístiques globals</h2>
<div class="stats-grid-top">
<div class="stat-card main">
<span class="label">Total Autenticacions</span>
<span class="value"><?= $autenticacions['total_autenticacions'] ?? 0 ?></span>
</div>
<div class="stat-card error">
<span class="label">Logins Erronis</span>
<span class="value"><?= $autenticacions['total_error_logins'] ?? 0 ?></span>
</div>
<div class="stat-card warn">
<span class="label">Restabliments</span>
<span class="value"><?= $autenticacions['total_restabliment_contrasenyes'] ?? 0 ?></span>
</div>
</div>
<div class="stats-grid-secondary">
<div class="stat-group">
<h3>Usuaris normals</h3>
<div class="row"><span>Autenticacions:</span> <strong><?= $autenticacions['auth_usuaris'] ?? 0 ?></strong></div>
<div class="row"><span>Errors d'autenticació:</span> <strong><?= $autenticacions['errors_usuaris'] ?? 0 ?></strong></div>
<div class="row"><span>Restabliments de contrasenyes:</span> <strong><?= $autenticacions['restabliments_contrasenya_usuaris'] ?? 0 ?></strong></div>
</div>
<div class="stat-group">
<h3>Administradors</h3>
<div class="row"><span>Autenticacions:</span> <strong><?= $autenticacions['auth_admins'] ?? 0 ?></strong></div>
<div class="row"><span>Errors d'autenticació:</span> <strong><?= $autenticacions['errors_admins'] ?? 0 ?></strong></div>
<div class="row"><span>Restabliments de contrasenyes:</span> <strong><?= $autenticacions['restabliments_contrasenya_admins'] ?? 0 ?></strong></div>
</div>
</div>
</section>
Les estadístiques globals es visualitzarien de la següent manera

Administració d'usuaris (només per administradors editors)
Mostra de formularis d'administració d'usuaris
En cas de ser un usuari administrador editor, l'usuari té la possibilitat de visualitzar dos formularis a més de les estadístiques globals. Un per restablir la contrasenya d'un usuari i l'altre per desbloquejar el comtpe d'un usuari.
Per poder verificar si l'usuari és administrador editor, fem servir la funció es_admin_ed.
<?php if (es_admin_ed()): ?>
<section class="management-section">
<div class="danger-zone">
<form method="post">
<input type="hidden" name="borrar_activitat" value="1">
<button type="submit" class="btn-danger" onclick="return confirm('Segur que vols borrar tot el historial?');">
Borrar tot el registre d'activitats
</button>
</form>
</div>
<h2 class="section-title">Gestió d'accés d'usuaris</h2>
<div class="management-grid">
<div class="tool-card">
<h3>Restablir contrasenya</h3>
<form method="post">
<div class="input-group">
<label>Nom d'usuari</label>
<input type="text" name="usuari_nom" required>
</div>
<div class="input-group">
<label>Nova contrasenya</label>
<input type="password" name="nova_contrasenya" required>
</div>
<button type="submit" class="btn-action">Restablir ara</button>
</form>
<?php if ($missatge): ?>
<p class="msg success"><?= $missatge ?></p>
<?php endif; ?>
<?php if ($error): ?>
<p class="msg error"><?= $error ?></p>
<?php endif; ?>
</div>
<div class="tool-card">
<h3>Desbloquejar compte</h3>
<form method="POST">
<div class="input-group">
<label>Nom d'usuari</label>
<input type="text" name="usuari_nom_desbloquejar" required>
</div>
<button type="submit" name="desbloquejar" class="btn-action secondary">Desbloquejar usuari</button>
<?php if ($missatgeDesbloqueig): ?>
<p class="msg success"><?= $missatgeDesbloqueig ?></p>
<?php endif; ?>
</form>
</div>
</div>
</section>
<?php endif; ?>
Formulari de restabliment de contrasenyes
El formulari de restabliment de contrasenya incorpora dos entrades de text, una per el nom d'usuari i l'altre per la nova contrasenya.
A més, incorpora la mostra de missatges d'error o èxit segons el resultat de la operació
El formulari es visualitzaria de la següent manera

Un cop es respon al formulari de restabliment de contrasenya, recollim els paràmetres i els desem a una variable, per posteriorment verificar que no estan buits, ja que al ser un formulari opcional, en l'HTML no els requerim i es poden enviar perfectament buits
$usuari_nom = trim($_POST['usuari_nom']);
if ($usuari_nom === '') { // Verifiquem que el nom d'usuari tingui un valor
$error = "Indica un nom d'usuari.";
} elseif (empty($_POST['nova_contrasenya'])) { // Verifiquem que la contrasenya tingui un valor
$error = "Indica una contrasenya.";
} else {
Seguidament, comprovem que l'usuari existeixi realitzant una consulta SQL on es cerca un usuari amb el mateix nom d'usuari
// Ens assegurem que el nom d'usuari existeixi $stmt = $pdo->prepare("SELECT id FROM usuaris WHERE nom_usuari = ?"); $stmt->execute([$usuari_nom]); $usuari = $stmt->fetch();
if (!$usuari) {
$error = "Usuari no trobat.";} else {
Si l'usuari existeix encriptarem la contrasenya i la actualitzarem a la BD. Posteriorment, restablirem els intents de login a 0 per a més a més desbloquejar el compte i afegirem una acció nomenada "restablir-contrasenya" a aquell usuari
// Si l'usuari existeix, actualitzem contrasenya i nombre d'intents if (isset($_POST['nova_contrasenya']) && $_POST['nova_contrasenya'] !== '') {
// Recuperem la contrasenya del formulari $nova_contrasenya = trim($_POST['nova_contrasenya']);// Encriptem la contrasenya $hash = password_hash($nova_contrasenya, PASSWORD_DEFAULT);// Inserim la nova contrasenya $stmt = $pdo->prepare("UPDATE usuaris SET contrasenya = ? WHERE id = ?"); $stmt->execute([$hash, $usuari['id']]);// Reiniciem el número d'intents a 0, així també desbloquejem l'usuari $stmt = $pdo->prepare("UPDATE usuaris SET intents_login = 0, ultim_intent = NULL WHERE id = ?"); $stmt->execute([$usuari['id']]);// Definim missatge i registrem activitat $missatge = "Contrasenya restablerta correctament."; registrar_activitat($pdo, $usuari['id'], 'restablir-contrasenya');
Formulari de desbloqueig d'usuaris
El formulari de desbloqueig d'usuaris incorpora una única entrada de text per el nom d'usuari.
A més, incorpora la mostra de missatges d'error o èxit segons el resultat de la operació
El formulari es visualitzaria de la següent manera

Quan es respon al formulari de desbloqueig d'usuari, es recupera el nom d'usuari introduit i ens assegurem que no estigui buit, ja que al ser un formulari opcional, en l'HTML no els requerim i es poden enviar perfectament buits
$usuari_nom = trim($_POST['usuari_nom_desbloquejar']);
if ($usuari_nom === '') { // Verifiquem que l'usuari tingui un valor
$error = "Omple el nom d'usuari per desbloquejar.";
Seguidament, comprovem que l'usuari existeixi realitzant una consulta SQL on es cerca un usuari amb el mateix nom d'usuari
// Verifiquem que l'usuari existeixi $stmt = $pdo->prepare("SELECT id FROM usuaris WHERE nom_usuari = ?"); $stmt->execute([$usuari_nom]); $usuari = $stmt->fetch();
if (!$usuari) {
$error = "Usuari no trobat.";
Si l'usuari existeix, actualitzem el seu número d'intents de login a 0 i registrem una acció nomenada "desbloquejar-compte"
} else {
// Si existeix, definim el nombre d'intents de login a 0 i registrem l'acció "desbloquejar-compte" $stmt = $pdo->prepare("UPDATE usuaris SET intents_login = 0, ultim_intent = NULL WHERE id = ?"); $stmt->execute([$usuari['id']]); $missatgeDesbloqueig = "Compte desbloquejat correctament."; registrar_activitat($pdo, $usuari['id'], 'desbloquejar-compte');}
Eliminació d'estadístiques
Per últim, l'usuari administrador té la possibilitat d'esborrar totes les estadístiques de l'aplicació mitjançant un botó.
Al prémer el botó, es realitza una consulta SQL on s'elimina tots els registres de la taula activitat
// Borrar estadístiques
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['borrar_activitat']) && es_admin_ed()) { // Si rebem el formulari de borrar activitat i som admins editors
try {
$stmt = $pdo->prepare("DELETE FROM activitat"); // Esborrem tots els registres de la taula activitat
$stmt->execute();
header("Location: taulerAdmin.php");
exit;
} catch (PDOException $e) {
$error = "No s'ha pogut esborrar l'historial. Motiu: " . $e->getMessage();
}
}
El botó es visualitza de la següent manera

Codi complet
<?php
session_start();
require 'funcions.php';
require './connexioBD/connexioRW.php';
// Verificar que està autenticat
requerir_autenticacio();
// Verificar que l'usuari és administrador
if (!es_admin()) {
header("Location: privada.php");
exit;
}
// Inicialitzar les variables de missatges
$missatge = '';
$error = '';
$missatgeDesbloqueig = '';
try{
// Consulta SQL per obtenir les estadístiques
$stmt = $pdo->query("
SELECT
-- Autenticacions correctes (login + auto-login) de tothom
SUM(a.accio IN ('login', 'auto-login')) AS total_autenticacions,
-- Logins erronis de tothom
SUM(a.accio = 'error-login') AS total_error_logins,
-- Restabliments de contrasenyes
SUM(a.accio = 'restablir-contrasenya') AS total_restabliment_contrasenyes,
-- Autenticacions correctes d'usuaris normals
SUM(
a.accio IN ('login', 'auto-login')
AND u.rol = 'usuari'
) AS auth_usuaris,
-- Logins erronis d'usuaris normals
SUM(
a.accio = 'error-login'
AND u.rol = 'usuari'
) AS errors_usuaris,
-- Restabliment de contrasenyes d'usuaris normals
SUM(
a.accio = 'restablir-contrasenya'
AND u.rol = 'usuari'
) AS restabliments_contrasenya_usuaris,
-- Autenticacions correctes d'administradors
SUM(
a.accio IN ('login', 'auto-login')
AND u.rol IN ('ed_admin', 'vi_admin')
) AS auth_admins,
-- Logins erronis d'administradors
SUM(
a.accio = 'error-login'
AND u.rol IN ('ed_admin', 'vi_admin')
) AS errors_admins,
-- Restabliment de contrasenyes d'administradors
SUM(
a.accio = 'restablir-contrasenya'
AND u.rol IN ('ed_admin', 'vi_admin')
) AS restabliments_contrasenya_admins
FROM activitat a
JOIN usuaris u ON u.id = a.usuari_id
");
$autenticacions = $stmt->fetch();
}catch (PDOException $e) {
$error = "No s'ha pogut recuperar les estadístiques globals. Motiu: " . $e->getMessage();
}
// Borrar estadístiques
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['borrar_activitat']) && es_admin_ed()) { // Si rebem el formulari de borrar activitat i som admins editors
try {
$stmt = $pdo->prepare("DELETE FROM activitat"); // Esborrem tots els registres de la taula activitat
$stmt->execute();
header("Location: taulerAdmin.php");
exit;
} catch (PDOException $e) {
$error = "No s'ha pogut esborrar l'historial. Motiu: " . $e->getMessage();
}
}
// Restabliment de contrasenya
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['usuari_nom']) && es_admin_ed()) { // Si rebem el formulari de restabliment de contrasenya i som admins editors
$usuari_nom = trim($_POST['usuari_nom']);
if ($usuari_nom === '') { // Verifiquem que el nom d'usuari tingui un valor
$error = "Indica un nom d'usuari.";
} elseif (empty($_POST['nova_contrasenya'])) { // Verifiquem que la contrasenya tingui un valor
$error = "Indica una contrasenya.";
} else {
try {
// Ens assegurem que el nom d'usuari existeixi
$stmt = $pdo->prepare("SELECT id FROM usuaris WHERE nom_usuari = ?");
$stmt->execute([$usuari_nom]);
$usuari = $stmt->fetch();
if (!$usuari) {
$error = "Usuari no trobat.";
} else {
// Si l'usuari existeix, actualitzem contrasenya i nombre d'intents
if (isset($_POST['nova_contrasenya']) && $_POST['nova_contrasenya'] !== '') {
// Recuperem la contrasenya del formulari
$nova_contrasenya = trim($_POST['nova_contrasenya']);
// Encriptem la constrasenya
$hash = password_hash($nova_contrasenya, PASSWORD_DEFAULT);
// Inserim la nova contrasenya
$stmt = $pdo->prepare("UPDATE usuaris SET contrasenya = ? WHERE id = ?");
$stmt->execute([$hash, $usuari['id']]);
// Reiniciem el número d'intents a 0, així també desbloquejem l'usuari
$stmt = $pdo->prepare("UPDATE usuaris SET intents_login = 0, ultim_intent = NULL WHERE id = ?");
$stmt->execute([$usuari['id']]);
// Definim missatge i registrem activitat
$missatge = "Contrasenya restablerta correctament.";
registrar_activitat($pdo, $usuari['id'], 'restablir-contrasenya');
}
}
} catch (PDOException $e) {
$error = "Error intern, no s'ha pogut actualitzar l'usuari. Motiu: " . $e->getMessage();
}
}
}
// Desbloqueig d'usuari
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['usuari_nom_desbloquejar']) && es_admin_ed()) { // Si rebem el formulari de desbloquejar usuari i som admins editors
$usuari_nom = trim($_POST['usuari_nom_desbloquejar']);
if ($usuari_nom === '') { // Verifiquem que l'usuari tingui un valor
$error = "Omple el nom d'usuari per desbloquejar.";
} else {
try {
// Verifiquem que l'usuari existeixi
$stmt = $pdo->prepare("SELECT id FROM usuaris WHERE nom_usuari = ?");
$stmt->execute([$usuari_nom]);
$usuari = $stmt->fetch();
if (!$usuari) {
$error = "Usuari no trobat.";
} else {
// Si existeix, definim el nombre d'intents de login a 0 i registrem l'acció "desbloquejar-compte"
$stmt = $pdo->prepare("UPDATE usuaris SET intents_login = 0, ultim_intent = NULL WHERE id = ?");
$stmt->execute([$usuari['id']]);
$missatgeDesbloqueig = "Compte desbloquejat correctament.";
registrar_activitat($pdo, $usuari['id'], 'desbloquejar-compte');
}
} catch (PDOException $e) {
$error = "No s'ha pogut desbloquejar el compte. Motiu: " . $e->getMessage();
}
}
}
?>
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<title>Tauler d'Administració</title>
<link rel="stylesheet" href="./css/taulerAdmin.css">
</head>
<body>
<div class="admin-container">
<header class="admin-header">
<h1>Tauler d'Administració</h1>
<a href="privada.php" class="btn-back">← Tornar a la zona privada</a>
</header>
<section class="stats-section">
<h2 class="section-title">Estadístiques globals</h2>
<div class="stats-grid-top">
<div class="stat-card main">
<span class="label">Total Autenticacions</span>
<span class="value"><?= $autenticacions['total_autenticacions'] ?? 0 ?></span>
</div>
<div class="stat-card error">
<span class="label">Logins Erronis</span>
<span class="value"><?= $autenticacions['total_error_logins'] ?? 0 ?></span>
</div>
<div class="stat-card warn">
<span class="label">Restabliments</span>
<span class="value"><?= $autenticacions['total_restabliment_contrasenyes'] ?? 0 ?></span>
</div>
</div>
<div class="stats-grid-secondary">
<div class="stat-group">
<h3>Usuaris normals</h3>
<div class="row"><span>Autenticacions:</span> <strong><?= $autenticacions['auth_usuaris'] ?? 0 ?></strong></div>
<div class="row"><span>Errors d'autenticació:</span> <strong><?= $autenticacions['errors_usuaris'] ?? 0 ?></strong></div>
<div class="row"><span>Restabliments de contrasenyes:</span> <strong><?= $autenticacions['restabliments_contrasenya_usuaris'] ?? 0 ?></strong></div>
</div>
<div class="stat-group">
<h3>Administradors</h3>
<div class="row"><span>Autenticacions:</span> <strong><?= $autenticacions['auth_admins'] ?? 0 ?></strong></div>
<div class="row"><span>Errors d'autenticació:</span> <strong><?= $autenticacions['errors_admins'] ?? 0 ?></strong></div>
<div class="row"><span>Restabliments de contrasenyes:</span> <strong><?= $autenticacions['restabliments_contrasenya_admins'] ?? 0 ?></strong></div>
</div>
</div>
</section>
<?php if (es_admin_ed()): ?>
<section class="management-section">
<div class="danger-zone">
<form method="post">
<input type="hidden" name="borrar_activitat" value="1">
<button type="submit" class="btn-danger" onclick="return confirm('Segur que vols borrar tot el historial?');">
Borrar tot el registre d'activitats
</button>
</form>
</div>
<h2 class="section-title">Gestió d'accés d'usuaris</h2>
<div class="management-grid">
<div class="tool-card">
<h3>Restablir contrasenya</h3>
<form method="post">
<div class="input-group">
<label>Nom d'usuari</label>
<input type="text" name="usuari_nom" required>
</div>
<div class="input-group">
<label>Nova contrasenya</label>
<input type="password" name="nova_contrasenya" required>
</div>
<button type="submit" class="btn-action">Restablir ara</button>
</form>
<?php if ($missatge): ?> <p class="msg success"><?= $missatge ?></p> <?php endif; ?>
<?php if ($error): ?> <p class="msg error"><?= $error ?></p> <?php endif; ?>
</div>
<div class="tool-card">
<h3>Desbloquejar compte</h3>
<form method="POST">
<div class="input-group">
<label>Nom d'usuari</label>
<input type="text" name="usuari_nom_desbloquejar" required>
</div>
<button type="submit" name="desbloquejar" class="btn-action secondary">Desbloquejar usuari</button>
<?php if ($missatgeDesbloqueig): ?> <p class="msg success"><?= $missatgeDesbloqueig ?></p> <?php endif; ?>
</form>
</div>
</div>
</section>
<?php endif; ?>
</div>
</body>
</html>