Skip to content

Commit 19d59fe

Browse files
committed
add option to diable signup
1 parent 4aa14b9 commit 19d59fe

2 files changed

Lines changed: 151 additions & 17 deletions

File tree

‎src/Pages/Admin/UserManagement.jsx‎

Lines changed: 129 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ import DialogTitle from '@mui/material/DialogTitle';
3333
import DialogContent from '@mui/material/DialogContent';
3434
import DialogContentText from '@mui/material/DialogContentText';
3535
import DialogActions from '@mui/material/DialogActions';
36+
import FormControlLabel from '@mui/material/FormControlLabel';
37+
import Checkbox from '@mui/material/Checkbox';
38+
import Divider from '@mui/material/Divider';
39+
import BlockIcon from '@mui/icons-material/Block';
40+
import HowToRegIcon from '@mui/icons-material/HowToReg';
3641

3742
export default function UserManagement() {
3843
const { auth } = useAuth();
@@ -45,9 +50,14 @@ export default function UserManagement() {
4550
const [savingId, setSavingId] = useState(null);
4651
const [deletingId, setDeletingId] = useState(null);
4752

53+
// Signup toggle state
54+
const [signupEnabled, setSignupEnabled] = useState(true);
55+
const [signupToggleLoading, setSignupToggleLoading] = useState(false);
56+
4857
// Confirmation dialog state
4958
const [confirmOpen, setConfirmOpen] = useState(false);
5059
const [userToDelete, setUserToDelete] = useState(null);
60+
const [deleteForumPosts, setDeleteForumPosts] = useState(false);
5161

5262
const isAuthorized = auth?.JWT && (auth.roles === 'Admin' || auth.roles === 'Vorstand');
5363

@@ -80,6 +90,10 @@ export default function UserManagement() {
8090
return;
8191
}
8292
fetchUsers();
93+
// Fetch initial signup status
94+
api.get('/user/signup-status')
95+
.then(res => setSignupEnabled(res.data.signupEnabled))
96+
.catch(err => console.error('Failed to fetch signup status', err));
8397
}, [auth, navigate]);
8498

8599
const handleRoleChange = (userId, newRole) => {
@@ -135,34 +149,75 @@ export default function UserManagement() {
135149

136150
const handleDeleteClick = (user) => {
137151
setUserToDelete(user);
152+
setDeleteForumPosts(false);
138153
setConfirmOpen(true);
139154
};
140155

141156
const handleDeleteCancel = () => {
142157
setConfirmOpen(false);
143158
setUserToDelete(null);
159+
setDeleteForumPosts(false);
144160
};
145161

146162
const handleDeleteConfirm = () => {
147163
if (!userToDelete) return;
148164
const user = userToDelete;
165+
const shouldDeletePosts = deleteForumPosts;
149166
setConfirmOpen(false);
150167
setUserToDelete(null);
168+
setDeleteForumPosts(false);
151169
setDeletingId(user.id);
152170

153-
api.delete(`/user/${user.id}`)
154-
.then(() => {
155-
setUsers(prev => prev.filter(u => u.id !== user.id));
156-
alertsManagerRef.current.showAlert('success', `Benutzer ${user.userName} erfolgreich gelöscht.`);
171+
const doDelete = () =>
172+
api.delete(`/user/${user.id}`)
173+
.then(() => {
174+
setUsers(prev => prev.filter(u => u.id !== user.id));
175+
alertsManagerRef.current.showAlert('success', `Benutzer ${user.userName} erfolgreich gelöscht.`);
176+
})
177+
.catch(err => {
178+
console.error('Error deleting user', err);
179+
const msg = err.response?.data || 'Fehler beim Löschen.';
180+
alertsManagerRef.current.showAlert('error', `Löschen fehlgeschlagen: ${msg}`);
181+
})
182+
.finally(() => {
183+
setDeletingId(null);
184+
});
185+
186+
if (shouldDeletePosts) {
187+
api.delete(`/user/${user.id}/posts`)
188+
.then(() => {
189+
alertsManagerRef.current.showAlert('info', `Forumsbeiträge von ${user.userName} gelöscht.`);
190+
})
191+
.catch(err => {
192+
console.error('Error deleting posts', err);
193+
alertsManagerRef.current.showAlert('error', 'Forumsbeiträge konnten nicht gelöscht werden.');
194+
})
195+
.finally(() => {
196+
doDelete();
197+
});
198+
} else {
199+
doDelete();
200+
}
201+
};
202+
203+
const handleSignupToggle = () => {
204+
setSignupToggleLoading(true);
205+
const newValue = !signupEnabled;
206+
api.post(`/user/signup-enabled?enabled=${newValue}`)
207+
.then(res => {
208+
setSignupEnabled(res.data.signupEnabled);
209+
alertsManagerRef.current.showAlert(
210+
'success',
211+
res.data.signupEnabled
212+
? 'Registrierung wurde wieder aktiviert.'
213+
: 'Registrierung wurde deaktiviert.'
214+
);
157215
})
158216
.catch(err => {
159-
console.error("Error deleting user", err);
160-
const msg = err.response?.data || 'Fehler beim Löschen.';
161-
alertsManagerRef.current.showAlert('error', `Löschen fehlgeschlagen: ${msg}`);
217+
console.error('Failed to toggle signup', err);
218+
alertsManagerRef.current.showAlert('error', 'Fehler beim Ändern der Registrierungseinstellung.');
162219
})
163-
.finally(() => {
164-
setDeletingId(null);
165-
});
220+
.finally(() => setSignupToggleLoading(false));
166221
};
167222

168223
const getUserEventsCurrentYear = (userName) => {
@@ -214,6 +269,46 @@ export default function UserManagement() {
214269
</Button>
215270
</Stack>
216271

272+
{/* Signup Toggle Card */}
273+
<Card sx={{ mb: 3, border: '1px solid rgba(255, 255, 255, 0.08)', bgcolor: 'background.paper', borderRadius: 2 }}>
274+
<CardContent sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', py: 2, '&:last-child': { pb: 2 } }}>
275+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
276+
{signupEnabled
277+
? <HowToRegIcon sx={{ color: 'success.main', fontSize: 28, flexShrink: 0 }} />
278+
: <BlockIcon sx={{ color: 'error.main', fontSize: 28, flexShrink: 0 }} />}
279+
<Box>
280+
<Typography variant="subtitle1" sx={{ fontWeight: 'bold', lineHeight: 1.3 }}>
281+
Registrierung neuer Benutzer
282+
</Typography>
283+
<Typography variant="body2" color="text.secondary">
284+
{signupEnabled
285+
? 'Neue Benutzer können sich derzeit registrieren.'
286+
: 'Die Registrierung ist derzeit deaktiviert.'}
287+
</Typography>
288+
</Box>
289+
</Box>
290+
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
291+
<Chip
292+
label={signupEnabled ? 'Aktiv' : 'Deaktiviert'}
293+
color={signupEnabled ? 'success' : 'error'}
294+
variant="outlined"
295+
size="small"
296+
/>
297+
<Tooltip title={signupEnabled ? 'Registrierung deaktivieren' : 'Registrierung aktivieren'}>
298+
<span style={{ display: 'flex', alignItems: 'center' }}>
299+
<Switch
300+
checked={signupEnabled}
301+
onChange={handleSignupToggle}
302+
disabled={signupToggleLoading}
303+
color={signupEnabled ? 'success' : 'error'}
304+
id="signup-toggle"
305+
/>
306+
</span>
307+
</Tooltip>
308+
</Box>
309+
</CardContent>
310+
</Card>
311+
217312
<Card sx={{ border: '1px solid rgba(255, 255, 255, 0.08)', bgcolor: 'background.paper', borderRadius: 2 }}>
218313
<CardContent sx={{ p: 0 }}>
219314
{loading ? (
@@ -349,7 +444,7 @@ export default function UserManagement() {
349444
bgcolor: 'background.paper',
350445
border: '1px solid rgba(255,255,255,0.1)',
351446
borderRadius: 2,
352-
minWidth: 360,
447+
minWidth: 400,
353448
}
354449
}
355450
}}
@@ -358,13 +453,34 @@ export default function UserManagement() {
358453
Benutzer löschen
359454
</DialogTitle>
360455
<DialogContent>
361-
<DialogContentText sx={{ color: 'text.secondary' }}>
456+
<DialogContentText sx={{ color: 'text.secondary', mb: 2 }}>
362457
Bist du sicher, dass du den Benutzer{' '}
363458
<Box component="span" sx={{ fontWeight: 'bold', color: 'text.primary' }}>
364459
{userToDelete?.userName}
365460
</Box>{' '}
366461
unwiderruflich löschen möchtest? Alle zugehörigen Daten werden entfernt.
367462
</DialogContentText>
463+
<Divider sx={{ mb: 2, borderColor: 'rgba(255,255,255,0.08)' }} />
464+
<FormControlLabel
465+
control={
466+
<Checkbox
467+
checked={deleteForumPosts}
468+
onChange={e => setDeleteForumPosts(e.target.checked)}
469+
color="error"
470+
id="delete-forum-posts-checkbox"
471+
/>
472+
}
473+
label={
474+
<Box>
475+
<Typography variant="body2" sx={{ fontWeight: 'bold', color: deleteForumPosts ? 'error.main' : 'text.primary' }}>
476+
Alle Forumsbeiträge löschen
477+
</Typography>
478+
<Typography variant="caption" color="text.secondary">
479+
Entfernt sämtliche Posts dieses Benutzers im Forum (z.B. bei Spam-Accounts).
480+
</Typography>
481+
</Box>
482+
}
483+
/>
368484
</DialogContent>
369485
<DialogActions sx={{ px: 3, pb: 2, gap: 1 }}>
370486
<Button onClick={handleDeleteCancel} variant="outlined" color="inherit">
@@ -377,7 +493,7 @@ export default function UserManagement() {
377493
startIcon={<DeleteIcon />}
378494
autoFocus
379495
>
380-
Endgültig löschen
496+
{deleteForumPosts ? 'Posts + Account löschen' : 'Endgültig löschen'}
381497
</Button>
382498
</DialogActions>
383499
</Dialog>

‎src/components/User/SignUpForm.jsx‎

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import { useNavigate } from 'react-router-dom';
33
import { useForm } from 'react-hook-form';
44
import { yupResolver } from '@hookform/resolvers/yup';
@@ -11,15 +11,23 @@ import TextField from '@mui/material/TextField';
1111
import Grid from '@mui/material/Grid';
1212
import Box from '@mui/material/Box';
1313
import Typography from '@mui/material/Typography';
14-
15-
// Feedback
1614
import Alert from '@mui/material/Alert';
1715
import Stack from '@mui/material/Stack';
16+
import BlockIcon from '@mui/icons-material/Block';
1817

1918
function SignUpForm() {
2019
const [state, setState] = useState({ resCode: null, resData: null });
20+
const [signupEnabled, setSignupEnabled] = useState(true);
21+
const [signupStatusLoading, setSignupStatusLoading] = useState(true);
2122
const navigate = useNavigate();
2223

24+
useEffect(() => {
25+
api.get('/user/signup-status')
26+
.then(res => setSignupEnabled(res.data.signupEnabled))
27+
.catch(() => setSignupEnabled(true)) // fail open
28+
.finally(() => setSignupStatusLoading(false));
29+
}, []);
30+
2331
const handleSubmit = async (formData) => {
2432
await api.put('/user', {
2533
firstName: formData.firstName,
@@ -79,6 +87,16 @@ function SignUpForm() {
7987
</Typography>
8088
</Box>
8189

90+
{!signupStatusLoading && !signupEnabled && (
91+
<Alert
92+
severity="error"
93+
icon={<BlockIcon />}
94+
sx={{ mb: 3, fontWeight: 'bold' }}
95+
>
96+
Die Registrierung ist derzeit deaktiviert. Bitte wende dich an einen Administrator.
97+
</Alert>
98+
)}
99+
82100
<Grid container spacing={2}>
83101
<Grid size={{ xs: 12, sm: 6 }}>
84102
<TextField
@@ -152,7 +170,7 @@ function SignUpForm() {
152170
color="primary"
153171
fullWidth
154172
size="large"
155-
disabled={isSubmitting}
173+
disabled={isSubmitting || !signupEnabled || signupStatusLoading}
156174
type="submit"
157175
sx={{ py: 1.5, fontWeight: 'bold' }}
158176
>

0 commit comments

Comments
 (0)