@micha.bigler/ui-core-micha 1.4.41 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,6 +5,13 @@ import { useSearchParams } from 'react-router-dom';
5
5
  import { Tabs, Tab, Box, Typography, Alert, CircularProgress } from '@mui/material';
6
6
  import { useTranslation } from 'react-i18next';
7
7
  // Internal Library Components
8
+ // Stellen Sie sicher, dass diese Pfade korrekt auf Ihre Library zeigen!
9
+ // Da Sie '@micha.bigler/ui-core-micha' nutzen, sollten die Imports ggf. so aussehen:
10
+ import { AuthContext,
11
+ // ... andere Komponenten aus der Lib importieren, falls sie dort exportiert sind
12
+ // Wenn sie lokal sind, lassen Sie die relativen Pfade.
13
+ } from '@micha.bigler/ui-core-micha';
14
+ // Falls die Komponenten noch lokal sind:
8
15
  import { WidePage } from '../layout/PageLayout';
9
16
  import { ProfileComponent } from '../components/ProfileComponent';
10
17
  import { SecurityComponent } from '../components/SecurityComponent';
@@ -12,14 +19,7 @@ import { UserListComponent } from '../components/UserListComponent';
12
19
  import { UserInviteComponent } from '../components/UserInviteComponent';
13
20
  import { AccessCodeManager } from '../components/AccessCodeManager';
14
21
  import { SupportRecoveryRequestsTab } from '../components/SupportRecoveryRequestsTab';
15
- import { AuthContext } from '../auth/AuthContext';
16
- import { updateUserProfile } from '../auth/authApi';
17
- /**
18
- * Complete, self-configuring Account Page.
19
- * Architecture:
20
- * - Permissions: Read from user.ui_permissions (from Backend).
21
- * - Roles: Read from user.available_roles (from Backend).
22
- */
22
+ import { updateUserProfile } from '../auth/authApi'; // Ggf. Pfad anpassen
23
23
  export function AccountPage() {
24
24
  const { t } = useTranslation();
25
25
  const { user, login, loading } = useContext(AuthContext);
@@ -28,9 +28,11 @@ export function AccountPage() {
28
28
  const currentTab = searchParams.get('tab') || 'profile';
29
29
  const fromRecovery = searchParams.get('from') === 'recovery';
30
30
  const fromWeakLogin = searchParams.get('from') === 'weak_login';
31
- // 2. Data & Permissions (Single Source of Truth)
31
+ // 2. Data & Permissions
32
32
  const activeRoles = (user === null || user === void 0 ? void 0 : user.available_roles) || [];
33
33
  const perms = (user === null || user === void 0 ? void 0 : user.ui_permissions) || {};
34
+ // NEU: Superuser-Flag prüfen
35
+ const isSuperUser = (user === null || user === void 0 ? void 0 : user.is_superuser) || false;
34
36
  const handleTabChange = (_event, newValue) => {
35
37
  setSearchParams({ tab: newValue });
36
38
  };
@@ -38,7 +40,7 @@ export function AccountPage() {
38
40
  const updatedUser = await updateUserProfile(payload);
39
41
  login(updatedUser);
40
42
  };
41
- // 3. Dynamic Tabs
43
+ // 3. Dynamic Tabs (angepasst für Superuser)
42
44
  const tabs = useMemo(() => {
43
45
  if (!user)
44
46
  return [];
@@ -46,20 +48,21 @@ export function AccountPage() {
46
48
  { value: 'profile', label: t('Account.TAB_PROFILE', 'Profile') },
47
49
  { value: 'security', label: t('Account.TAB_SECURITY', 'Security') },
48
50
  ];
49
- if (perms.can_view_users) {
51
+ // Logik: Superuser darf ALLES, sonst gelten die spezifischen Permissions
52
+ if (isSuperUser || perms.can_view_users) {
50
53
  list.push({ value: 'users', label: t('Account.TAB_USERS', 'Users') });
51
54
  }
52
- if (perms.can_invite) {
55
+ if (isSuperUser || perms.can_invite) {
53
56
  list.push({ value: 'invite', label: t('Account.TAB_INVITE', 'Invite') });
54
57
  }
55
- if (perms.can_manage_access_codes) {
58
+ if (isSuperUser || perms.can_manage_access_codes) {
56
59
  list.push({ value: 'access', label: t('Account.TAB_ACCESS_CODES', 'Access Codes') });
57
60
  }
58
- if (perms.can_view_support) {
61
+ if (isSuperUser || perms.can_view_support) {
59
62
  list.push({ value: 'support', label: t('Account.TAB_SUPPORT', 'Support') });
60
63
  }
61
64
  return list;
62
- }, [user, perms, t]);
65
+ }, [user, perms, t, isSuperUser]);
63
66
  // 4. Loading & Auth Checks
64
67
  if (loading) {
65
68
  return (_jsx(Box, { sx: { display: 'flex', justifyContent: 'center', mt: 10 }, children: _jsx(CircularProgress, {}) }));
@@ -69,6 +72,7 @@ export function AccountPage() {
69
72
  }
70
73
  // 5. Security Check: Is the active tab allowed?
71
74
  const activeTabExists = tabs.some(t => t.value === currentTab);
75
+ // Falls der Tab nicht erlaubt ist (z.B. manuell in URL eingegeben), Fallback auf 'profile'
72
76
  const safeTab = activeTabExists ? currentTab : 'profile';
73
77
  return (_jsxs(WidePage, { title: t('Account.TITLE', 'Account & Administration'), children: [_jsx(Helmet, { children: _jsxs("title", { children: [t('Account.PAGE_TITLE', 'Account'), " \u2013 ", user.email] }) }), _jsx(Tabs, { value: safeTab, onChange: handleTabChange, variant: "scrollable", scrollButtons: "auto", sx: { mb: 3, borderBottom: 1, borderColor: 'divider' }, children: tabs.map((tab) => (_jsx(Tab, { label: tab.label, value: tab.value }, tab.value))) }), safeTab === 'profile' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(ProfileComponent, { onSubmit: handleProfileSubmit, showName: true, showPrivacy: true, showCookies: true }) })), safeTab === 'security' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(SecurityComponent, { fromRecovery: fromRecovery, fromWeakLogin: fromWeakLogin }) })), safeTab === 'users' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(UserListComponent, { roles: activeRoles, currentUser: user }) })), safeTab === 'invite' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(UserInviteComponent, {}) })), safeTab === 'access' && (_jsxs(Box, { sx: { mt: 2 }, children: [_jsx(Typography, { variant: "body2", sx: { mb: 2, color: 'text.secondary' }, children: t('Account.ACCESS_CODES_HINT', 'Manage access codes for self-registration.') }), _jsx(AccessCodeManager, {})] })), safeTab === 'support' && (_jsx(Box, { sx: { mt: 2 }, children: _jsx(SupportRecoveryRequestsTab, {}) }))] }));
74
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@micha.bigler/ui-core-micha",
3
- "version": "1.4.41",
3
+ "version": "2.1.1",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "private": false,
@@ -12,6 +12,15 @@ import {
12
12
  import { useTranslation } from 'react-i18next';
13
13
 
14
14
  // Internal Library Components
15
+ // Stellen Sie sicher, dass diese Pfade korrekt auf Ihre Library zeigen!
16
+ // Da Sie '@micha.bigler/ui-core-micha' nutzen, sollten die Imports ggf. so aussehen:
17
+ import {
18
+ AuthContext,
19
+ // ... andere Komponenten aus der Lib importieren, falls sie dort exportiert sind
20
+ // Wenn sie lokal sind, lassen Sie die relativen Pfade.
21
+ } from '@micha.bigler/ui-core-micha';
22
+
23
+ // Falls die Komponenten noch lokal sind:
15
24
  import { WidePage } from '../layout/PageLayout';
16
25
  import { ProfileComponent } from '../components/ProfileComponent';
17
26
  import { SecurityComponent } from '../components/SecurityComponent';
@@ -19,15 +28,8 @@ import { UserListComponent } from '../components/UserListComponent';
19
28
  import { UserInviteComponent } from '../components/UserInviteComponent';
20
29
  import { AccessCodeManager } from '../components/AccessCodeManager';
21
30
  import { SupportRecoveryRequestsTab } from '../components/SupportRecoveryRequestsTab';
22
- import { AuthContext } from '../auth/AuthContext';
23
- import { updateUserProfile } from '../auth/authApi';
24
-
25
- /**
26
- * Complete, self-configuring Account Page.
27
- * Architecture:
28
- * - Permissions: Read from user.ui_permissions (from Backend).
29
- * - Roles: Read from user.available_roles (from Backend).
30
- */
31
+ import { updateUserProfile } from '../auth/authApi'; // Ggf. Pfad anpassen
32
+
31
33
  export function AccountPage() {
32
34
  const { t } = useTranslation();
33
35
  const { user, login, loading } = useContext(AuthContext);
@@ -38,9 +40,12 @@ export function AccountPage() {
38
40
  const fromRecovery = searchParams.get('from') === 'recovery';
39
41
  const fromWeakLogin = searchParams.get('from') === 'weak_login';
40
42
 
41
- // 2. Data & Permissions (Single Source of Truth)
43
+ // 2. Data & Permissions
42
44
  const activeRoles = user?.available_roles || [];
43
45
  const perms = user?.ui_permissions || {};
46
+
47
+ // NEU: Superuser-Flag prüfen
48
+ const isSuperUser = user?.is_superuser || false;
44
49
 
45
50
  const handleTabChange = (_event, newValue) => {
46
51
  setSearchParams({ tab: newValue });
@@ -51,7 +56,7 @@ export function AccountPage() {
51
56
  login(updatedUser);
52
57
  };
53
58
 
54
- // 3. Dynamic Tabs
59
+ // 3. Dynamic Tabs (angepasst für Superuser)
55
60
  const tabs = useMemo(() => {
56
61
  if (!user) return [];
57
62
 
@@ -60,24 +65,26 @@ export function AccountPage() {
60
65
  { value: 'security', label: t('Account.TAB_SECURITY', 'Security') },
61
66
  ];
62
67
 
63
- if (perms.can_view_users) {
68
+ // Logik: Superuser darf ALLES, sonst gelten die spezifischen Permissions
69
+
70
+ if (isSuperUser || perms.can_view_users) {
64
71
  list.push({ value: 'users', label: t('Account.TAB_USERS', 'Users') });
65
72
  }
66
73
 
67
- if (perms.can_invite) {
74
+ if (isSuperUser || perms.can_invite) {
68
75
  list.push({ value: 'invite', label: t('Account.TAB_INVITE', 'Invite') });
69
76
  }
70
77
 
71
- if (perms.can_manage_access_codes) {
78
+ if (isSuperUser || perms.can_manage_access_codes) {
72
79
  list.push({ value: 'access', label: t('Account.TAB_ACCESS_CODES', 'Access Codes') });
73
80
  }
74
81
 
75
- if (perms.can_view_support) {
82
+ if (isSuperUser || perms.can_view_support) {
76
83
  list.push({ value: 'support', label: t('Account.TAB_SUPPORT', 'Support') });
77
84
  }
78
85
 
79
86
  return list;
80
- }, [user, perms, t]);
87
+ }, [user, perms, t, isSuperUser]);
81
88
 
82
89
  // 4. Loading & Auth Checks
83
90
  if (loading) {
@@ -100,6 +107,7 @@ export function AccountPage() {
100
107
 
101
108
  // 5. Security Check: Is the active tab allowed?
102
109
  const activeTabExists = tabs.some(t => t.value === currentTab);
110
+ // Falls der Tab nicht erlaubt ist (z.B. manuell in URL eingegeben), Fallback auf 'profile'
103
111
  const safeTab = activeTabExists ? currentTab : 'profile';
104
112
 
105
113
  return (