Update
This commit is contained in:
@@ -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,27 +786,26 @@ 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={
|
||||
maintenanceActive ||
|
||||
securityPhraseLoading ||
|
||||
renewingSecurityPhrase
|
||||
}
|
||||
>
|
||||
{renewingSecurityPhrase ? "Erneuert ..." : "Schlüssel erneuern"}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
color="red"
|
||||
className="normal-case"
|
||||
onClick={handleRenewSecurityPhrase}
|
||||
disabled={
|
||||
!canRenewSecurityPhrase ||
|
||||
maintenanceActive ||
|
||||
securityPhraseLoading ||
|
||||
renewingSecurityPhrase
|
||||
}
|
||||
>
|
||||
{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>
|
||||
)}
|
||||
<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