Update
This commit is contained in:
@@ -645,7 +645,7 @@ const seedPermissions = () => {
|
||||
label: 'Sicherheitsschlüssel',
|
||||
sortOrder: 3,
|
||||
defaultLevel: 'none',
|
||||
levels: ['full', 'read', 'none'],
|
||||
levels: ['full', 'none'],
|
||||
isRequired: 0,
|
||||
dependencies: [
|
||||
{
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -34,8 +34,8 @@
|
||||
<script defer data-site="YOUR_DOMAIN_HERE" src="https://api.nepcha.com/js/nepcha-analytics.js"></script>
|
||||
|
||||
|
||||
<script type="module" crossorigin src="/assets/index-f91011a0.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-f6cd1c87.css">
|
||||
<script type="module" crossorigin src="/assets/index-65b35a5f.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-328d6adf.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -119,8 +119,8 @@ export function UserDetails() {
|
||||
|
||||
const canEditUsers = Boolean(authUser?.isSuperuser || hasPermission("users-edit", "full"));
|
||||
const canReadUsers = Boolean(authUser?.isSuperuser || hasPermission("users-edit", "read"));
|
||||
const canViewSecurityPhrase = Boolean(authUser?.isSuperuser || hasPermission("users-security-phrase", "read"));
|
||||
const canRenewSecurityPhrase = Boolean(authUser?.isSuperuser || hasPermission("users-security-phrase", "full"));
|
||||
const canManageSecurityPhrase = Boolean(authUser?.isSuperuser || hasPermission("users-security-phrase", "full"));
|
||||
const canRenewSecurityPhrase = canManageSecurityPhrase;
|
||||
|
||||
if (!canReadUsers) {
|
||||
return null;
|
||||
@@ -393,7 +393,7 @@ export function UserDetails() {
|
||||
}, [canEditUsers, user, hasChanges, formValues, showToast, isSuperuserUser]);
|
||||
|
||||
const fetchSecurityPhrase = useCallback(async () => {
|
||||
if (!canViewSecurityPhrase || !numericUserId) {
|
||||
if (!canManageSecurityPhrase || !numericUserId) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -423,14 +423,17 @@ export function UserDetails() {
|
||||
} finally {
|
||||
setSecurityPhraseLoading(false);
|
||||
}
|
||||
}, [canViewSecurityPhrase, numericUserId]);
|
||||
}, [canManageSecurityPhrase, numericUserId]);
|
||||
|
||||
const handleReloadSecurityPhrase = useCallback(() => {
|
||||
if (!canRenewSecurityPhrase) {
|
||||
return;
|
||||
}
|
||||
if (securityPhraseLoading || renewingSecurityPhrase) {
|
||||
return;
|
||||
}
|
||||
fetchSecurityPhrase();
|
||||
}, [fetchSecurityPhrase, renewingSecurityPhrase, securityPhraseLoading]);
|
||||
}, [canRenewSecurityPhrase, fetchSecurityPhrase, renewingSecurityPhrase, securityPhraseLoading]);
|
||||
|
||||
const handleRenewSecurityPhrase = useCallback(async () => {
|
||||
if (!canRenewSecurityPhrase || !numericUserId || maintenanceActive || renewingSecurityPhrase) {
|
||||
@@ -546,7 +549,7 @@ export function UserDetails() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!canViewSecurityPhrase || !numericUserId) {
|
||||
if (!canManageSecurityPhrase || !numericUserId) {
|
||||
setSecurityPhraseWords([]);
|
||||
setSecurityPhraseDownloadedAt(null);
|
||||
setSecurityPhraseError("");
|
||||
@@ -555,7 +558,7 @@ export function UserDetails() {
|
||||
}
|
||||
|
||||
fetchSecurityPhrase();
|
||||
}, [hasLoaded, canViewSecurityPhrase, fetchSecurityPhrase, numericUserId]);
|
||||
}, [hasLoaded, canManageSecurityPhrase, fetchSecurityPhrase, numericUserId]);
|
||||
|
||||
const inputDisabled = maintenanceActive || savingUser || !user || !canEditUsers;
|
||||
const selectDisabled = maintenanceActive || savingUser || !user || groupsLoading || !canEditUsers || isSuperuserUser;
|
||||
@@ -765,7 +768,7 @@ export function UserDetails() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{canViewSecurityPhrase && (
|
||||
{canManageSecurityPhrase && (
|
||||
<div className="mt-10 border-t border-blue-gray-50 pt-8">
|
||||
<div className="mb-4 flex flex-wrap items-center justify-between gap-4">
|
||||
<div>
|
||||
@@ -783,19 +786,19 @@ export function UserDetails() {
|
||||
className="normal-case"
|
||||
onClick={handleReloadSecurityPhrase}
|
||||
disabled={
|
||||
!canViewSecurityPhrase ||
|
||||
!canRenewSecurityPhrase ||
|
||||
securityPhraseLoading ||
|
||||
renewingSecurityPhrase
|
||||
}
|
||||
>
|
||||
Aktualisieren
|
||||
</Button>
|
||||
{canRenewSecurityPhrase && (
|
||||
<Button
|
||||
color="red"
|
||||
className="normal-case"
|
||||
onClick={handleRenewSecurityPhrase}
|
||||
disabled={
|
||||
!canRenewSecurityPhrase ||
|
||||
maintenanceActive ||
|
||||
securityPhraseLoading ||
|
||||
renewingSecurityPhrase
|
||||
@@ -803,7 +806,6 @@ export function UserDetails() {
|
||||
>
|
||||
{renewingSecurityPhrase ? "Erneuert ..." : "Schlüssel erneuern"}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{securityPhraseLoading ? (
|
||||
@@ -820,7 +822,11 @@ export function UserDetails() {
|
||||
color="red"
|
||||
className="normal-case"
|
||||
onClick={handleReloadSecurityPhrase}
|
||||
disabled={securityPhraseLoading || renewingSecurityPhrase}
|
||||
disabled={
|
||||
!canRenewSecurityPhrase ||
|
||||
securityPhraseLoading ||
|
||||
renewingSecurityPhrase
|
||||
}
|
||||
>
|
||||
Erneut laden
|
||||
</Button>
|
||||
@@ -850,11 +856,9 @@ export function UserDetails() {
|
||||
Kein Sicherheitsschlüssel verfügbar.
|
||||
</Typography>
|
||||
)}
|
||||
{canRenewSecurityPhrase && (
|
||||
<Typography className="mt-3 text-sm text-blue-gray-500">
|
||||
Nach dem Erneuern muss der Benutzer den neuen Sicherheitsschlüssel erneut herunterladen.
|
||||
</Typography>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -126,16 +126,24 @@ export function UserGroupDetail() {
|
||||
if (!item || typeof item !== "object") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const key = item.key || "";
|
||||
const defaultLevel =
|
||||
typeof item.defaultLevel === "string" && item.defaultLevel ? item.defaultLevel : "none";
|
||||
defaults[item.key] = defaultLevel;
|
||||
const assigned = rawValues[item.key];
|
||||
initialSelection[item.key] = typeof assigned === "string" && assigned ? assigned : defaultLevel;
|
||||
defaults[key] = defaultLevel;
|
||||
|
||||
const assigned = rawValues[key];
|
||||
let normalizedAssigned =
|
||||
typeof assigned === "string" && assigned ? assigned : defaultLevel;
|
||||
|
||||
const availableLevels =
|
||||
Array.isArray(item.availableLevels) && item.availableLevels.length
|
||||
? item.availableLevels
|
||||
: LEVEL_OPTIONS.map((option) => option.value);
|
||||
if (!availableLevels.includes(normalizedAssigned)) {
|
||||
normalizedAssigned = defaultLevel;
|
||||
}
|
||||
initialSelection[key] = normalizedAssigned;
|
||||
|
||||
const dependencies = Array.isArray(item.dependencies) ? item.dependencies : [];
|
||||
|
||||
@@ -359,10 +367,6 @@ export function UserGroupDetail() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (permissionsChanged && isSuperuserGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (detailsChanged && !canEditGroupDetails) {
|
||||
setSaveError("Dir fehlt die Berechtigung, diese Gruppe zu bearbeiten.");
|
||||
return;
|
||||
@@ -397,10 +401,14 @@ export function UserGroupDetail() {
|
||||
}
|
||||
}
|
||||
|
||||
if (permissionsChanged && !isSuperuserGroup) {
|
||||
if (permissionsChanged) {
|
||||
await axios.put(`/api/groups/${group.id}/permissions`, {
|
||||
values: permissionSelection
|
||||
});
|
||||
setPermissionSelection((prev) => ({
|
||||
...prev,
|
||||
...permissionSelection
|
||||
}));
|
||||
setInitialPermissionSelection({ ...permissionSelection });
|
||||
}
|
||||
|
||||
@@ -577,6 +585,7 @@ export function UserGroupDetail() {
|
||||
? row.availableLevels
|
||||
: LEVEL_OPTIONS.map((option) => option.value)
|
||||
);
|
||||
const levelOptions = LEVEL_OPTIONS;
|
||||
|
||||
return (
|
||||
<div key={`${ownerKey}-${row.key}`} className={rowClasses}>
|
||||
@@ -584,7 +593,7 @@ export function UserGroupDetail() {
|
||||
{row.label}
|
||||
</div>
|
||||
<List className="flex-col gap-1.5 md:ml-auto md:flex-row md:flex-nowrap md:w-1/2 md:items-center md:justify-end md:gap-3">
|
||||
{LEVEL_OPTIONS.map((option) => {
|
||||
{levelOptions.map((option) => {
|
||||
const optionId = `${rowName}-${option.value}`;
|
||||
const checked = currentValue === option.value;
|
||||
const disabled =
|
||||
|
||||
Reference in New Issue
Block a user