feat: per-user museum and channel access control

- PATCH /api/users/:id route to update user permissions
- Auth session stores and returns allowedMuseums/allowedChannels
- User type gains AllowedMuseums/AllowedChannels (JSON string fields)
- parseAllowed() with fail-closed semantics (empty string → null → no data)
- Dashboard/Comparison apply permission base filter before user filters
- Filter dropdowns (museums, channels, years, districts) derived from
  permission-filtered data — restricted users only see their allowed options
- Settings UserRow component with inline checkbox pickers for access config
- Access badges in users table showing current restriction summary

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
fahed
2026-04-08 18:03:19 +03:00
parent d4ce5b6478
commit e41cff831b
10 changed files with 259 additions and 51 deletions
+2 -2
View File
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
import { useLanguage } from '../contexts/LanguageContext';
interface LoginProps {
onLogin: (name: string, role: string) => void;
onLogin: (name: string, role: string, allowedMuseums: string, allowedChannels: string) => void;
}
function Login({ onLogin }: LoginProps) {
@@ -31,7 +31,7 @@ function Login({ onLogin }: LoginProps) {
}
const data = await res.json();
onLogin(data.name || '', data.role || 'viewer');
onLogin(data.name || '', data.role || 'viewer', data.allowedMuseums ?? '[]', data.allowedChannels ?? '[]');
} catch {
setError(t('login.error'));
setLoading(false);