added main permission group feature

This commit is contained in:
2025-11-21 00:28:53 +01:00
parent 1234fbda00
commit 9c2d649adf
7 changed files with 1326 additions and 65 deletions

View File

@@ -4,6 +4,7 @@ import { useAuth } from '../contexts/AuthContext'
const Users = () => {
const { authFetch } = useAuth()
const [users, setUsers] = useState([])
const [groups, setGroups] = useState([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState('')
const [showForm, setShowForm] = useState(false)
@@ -13,11 +14,13 @@ const Users = () => {
email: '',
oldPassword: '',
password: '',
confirmPassword: ''
confirmPassword: '',
groupIds: []
})
useEffect(() => {
fetchUsers()
fetchGroups()
}, [])
const fetchUsers = async () => {
@@ -36,6 +39,18 @@ const Users = () => {
}
}
const fetchGroups = async () => {
try {
const response = await authFetch('/api/permission-groups')
if (response.ok) {
const data = await response.json()
setGroups(Array.isArray(data) ? data : [])
}
} catch (err) {
console.error('Error fetching permission groups:', err)
}
}
const handleSubmit = async (e) => {
e.preventDefault()
setError('')
@@ -68,12 +83,14 @@ const Users = () => {
...(formData.password && {
password: formData.password,
oldPassword: formData.oldPassword
})
}),
...(formData.groupIds !== undefined && { groupIds: formData.groupIds })
}
: {
username: formData.username,
email: formData.email,
password: formData.password
password: formData.password,
groupIds: formData.groupIds || []
}
const response = await authFetch(url, {
@@ -86,7 +103,7 @@ const Users = () => {
if (response.ok) {
await fetchUsers()
setFormData({ username: '', email: '', oldPassword: '', password: '', confirmPassword: '' })
setFormData({ username: '', email: '', oldPassword: '', password: '', confirmPassword: '', groupIds: [] })
setShowForm(false)
setEditingUser(null)
} else {
@@ -108,7 +125,8 @@ const Users = () => {
email: user.email,
oldPassword: '',
password: '',
confirmPassword: ''
confirmPassword: '',
groupIds: user.groupIds || []
})
setShowForm(true)
}
@@ -142,6 +160,30 @@ const Users = () => {
})
}
const handleGroupToggle = (groupId) => {
setFormData(prev => {
const groupIds = prev.groupIds || []
if (groupIds.includes(groupId)) {
return { ...prev, groupIds: groupIds.filter(id => id !== groupId) }
} else {
return { ...prev, groupIds: [...groupIds, groupId] }
}
})
}
const getPermissionLabel = (permission) => {
switch (permission) {
case 'READ':
return 'Lesen'
case 'READ_WRITE':
return 'Lesen/Schreiben'
case 'FULL_ACCESS':
return 'Vollzugriff'
default:
return permission
}
}
return (
<div className="p-8 min-h-full bg-gradient-to-r from-slate-700 to-slate-900">
<div className="max-w-4xl mx-auto">
@@ -156,7 +198,7 @@ const Users = () => {
onClick={() => {
setShowForm(!showForm)
setEditingUser(null)
setFormData({ username: '', email: '', oldPassword: '', password: '', confirmPassword: '' })
setFormData({ username: '', email: '', oldPassword: '', password: '', confirmPassword: '', groupIds: [] })
}}
className="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-lg shadow-lg hover:shadow-xl transition-all duration-200"
>
@@ -284,6 +326,40 @@ const Users = () => {
<p className="mt-1 text-xs text-green-400"> Passwörter stimmen überein</p>
)}
</div>
<div>
<label className="block text-sm font-medium text-slate-200 mb-2">
Berechtigungsgruppen
</label>
<div className="bg-slate-700/50 border border-slate-600 rounded-lg p-4 max-h-60 overflow-y-auto">
{groups.length === 0 ? (
<p className="text-slate-400 text-sm">Keine Berechtigungsgruppen vorhanden</p>
) : (
<div className="space-y-2">
{groups.map(group => (
<label key={group.id} className="flex items-start cursor-pointer hover:bg-slate-600/50 p-2 rounded">
<input
type="checkbox"
checked={formData.groupIds?.includes(group.id) || false}
onChange={() => handleGroupToggle(group.id)}
className="w-4 h-4 text-blue-600 bg-slate-600 border-slate-500 rounded focus:ring-blue-500 mt-1"
/>
<div className="ml-3 flex-1">
<div className="flex items-center gap-2">
<span className="text-slate-300 font-medium">{group.name}</span>
<span className="px-2 py-0.5 bg-blue-600/20 text-blue-300 rounded text-xs">
{getPermissionLabel(group.permission)}
</span>
</div>
{group.description && (
<p className="text-xs text-slate-400 mt-1">{group.description}</p>
)}
</div>
</label>
))}
</div>
)}
</div>
</div>
{error && (
<div className="p-3 bg-red-500/20 border border-red-500/50 rounded-lg text-red-300 text-sm">
{error}
@@ -302,7 +378,7 @@ const Users = () => {
onClick={() => {
setShowForm(false)
setEditingUser(null)
setFormData({ username: '', email: '', oldPassword: '', password: '', confirmPassword: '' })
setFormData({ username: '', email: '', oldPassword: '', password: '', confirmPassword: '', groupIds: [] })
setError('')
}}
className="px-6 py-2 bg-slate-600 hover:bg-slate-700 text-white font-semibold rounded-lg transition-colors duration-200"
@@ -347,6 +423,21 @@ const Users = () => {
{user.username}
</h3>
<p className="text-slate-300 mb-2">{user.email}</p>
{user.groupIds && user.groupIds.length > 0 && (
<div className="mb-2">
<p className="text-sm text-slate-300 mb-1">Berechtigungsgruppen:</p>
<div className="flex flex-wrap gap-2">
{user.groupIds.map(groupId => {
const group = groups.find(g => g.id === groupId)
return group ? (
<span key={groupId} className="px-2 py-1 bg-blue-600/20 text-blue-300 rounded text-xs">
{group.name} ({getPermissionLabel(group.permission)})
</span>
) : null
})}
</div>
</div>
)}
<p className="text-xs text-slate-400">
Erstellt: {user.createdAt ? new Date(user.createdAt).toLocaleString('de-DE') : 'Unbekannt'}
</p>