Fase 2: read-only user role with per-category view toggles

Adds a third account type 'user' alongside super/admin: no create/edit/delete
rights on qr codes, view access to dynamic/static lists gated per-account by
two admin-controlled toggles (can_view_static, can_view_dynamic), and always
full visibility into the dashboard/reports regardless of those toggles.

- New columns can_view_static/can_view_dynamic on users (migrations/003)
- Users class + form_users.php: 'user' type option with the two toggles
- Access control: dynamic_qrcode.php/static_qrcode.php/bulk_action.php reject
  all mutations for type=user; dynamic_qrcodes.php/static_qrcodes.php enforce
  the view toggle and show all codes (no owner scoping, since 'user' owns none)
- Sidebar and list tables hide add/edit/delete/bulk UI for the read-only role
- index.php dashboard stats are unscoped for both 'super' and 'user'

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-08 16:37:25 +02:00
parent feb5380b28
commit a1ab16d54c
15 changed files with 163 additions and 15 deletions
+16 -1
View File
@@ -35,9 +35,18 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
exit();
}
if ($_SESSION['type'] === 'user') {
$view_flag = $type === 'dynamic' ? 'can_view_dynamic' : 'can_view_static';
if (empty($_SESSION[$view_flag] ?? null)) {
http_response_code(403);
echo json_encode(['data' => 'Not allowed to view this qr code type.', 'status' => 403]);
exit();
}
}
foreach ($params as $param) {
$db->where('id', $param);
if ($_SESSION['type'] !== 'super') {
if ($_SESSION['type'] === 'admin') {
$db->where('id_owner', $_SESSION['user_id']);
$db->orWhere('id_owner', NULL, 'IS');
}
@@ -69,6 +78,12 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
]);
exit();
} else if($json["action"] == "delete") {
if ($_SESSION['type'] === 'user') {
http_response_code(403);
echo json_encode(['data' => 'The "user" role is read-only.', 'status' => 403]);
exit();
}
$params = $json['params'];
if (isset($json['type']) && in_array($json['type'], $allowed_types, true)) {