From 9a25bb26b1d06980ae4b525355e52487d0e2062f Mon Sep 17 00:00:00 2001 From: Alexander Borg Date: Sat, 13 Sep 2025 22:30:56 +0200 Subject: [PATCH] Fix jwt-token --- client/src/pages/Settings.jsx | 116 ++++++++++++++++++++++++++++------ server/routes/tenant.js | 78 +++++++++++++++++++++++ 2 files changed, 174 insertions(+), 20 deletions(-) diff --git a/client/src/pages/Settings.jsx b/client/src/pages/Settings.jsx index 43b3b93..a74cbb7 100644 --- a/client/src/pages/Settings.jsx +++ b/client/src/pages/Settings.jsx @@ -10,7 +10,9 @@ import { GlobeAltIcon, KeyIcon, EyeIcon, - EyeSlashIcon + EyeSlashIcon, + TrashIcon, + PencilIcon } from '@heroicons/react/24/outline'; import { hasPermission, canAccessSettings } from '../utils/rbac'; @@ -1099,6 +1101,8 @@ const UsersSettings = ({ tenantConfig, onRefresh }) => { const [showCreateUser, setShowCreateUser] = useState(false); const [showEditUser, setShowEditUser] = useState(false); const [editingUser, setEditingUser] = useState(null); + const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); + const [deletingUser, setDeletingUser] = useState(null); const authProvider = tenantConfig?.auth_provider; const isLocalAuth = authProvider === 'local'; @@ -1260,25 +1264,41 @@ const UsersSettings = ({ tenantConfig, onRefresh }) => { {(canEditUsers || canDeleteUsers) && ( - {canEditUsers && ( - - )} - {canDeleteUsers && ( - - )} +
+ {canEditUsers && ( + + )} + {canDeleteUsers && ( + + )} + {canDeleteUsers && ( + + )} +
)} @@ -1349,6 +1369,43 @@ const UsersSettings = ({ tenantConfig, onRefresh }) => { }} /> )} + + {/* Delete Confirmation Modal */} + {showDeleteConfirm && deletingUser && ( +
+
+
+
+ +
+

Delete User

+
+

+ Are you sure you want to delete {deletingUser.username}? + This action cannot be undone and will permanently remove the user and all associated data. +

+
+
+ + +
+
+
+
+ )} ); @@ -1369,6 +1426,25 @@ const UsersSettings = ({ tenantConfig, onRefresh }) => { toast.error('Failed to update user status'); } }; + + const handleDeleteUser = (user) => { + setDeletingUser(user); + setShowDeleteConfirm(true); + }; + + const confirmDeleteUser = async () => { + if (!deletingUser) return; + + try { + await api.delete(`/tenant/users/${deletingUser.id}`); + toast.success('User deleted successfully'); + fetchUsers(); + setShowDeleteConfirm(false); + setDeletingUser(null); + } catch (error) { + toast.error('Failed to delete user'); + } + }; }; // Create User Modal Component (for local auth only) diff --git a/server/routes/tenant.js b/server/routes/tenant.js index eeac267..ee75327 100644 --- a/server/routes/tenant.js +++ b/server/routes/tenant.js @@ -673,6 +673,84 @@ router.put('/users/:userId', authenticateToken, requirePermissions(['users.edit' } }); +/** + * DELETE /tenant/users/:userId + * Delete user permanently (user admin or higher, local auth only) + */ +router.delete('/users/:userId', authenticateToken, requirePermissions(['users.delete']), async (req, res) => { + try { + // Determine tenant from request + const tenantId = await multiAuth.determineTenant(req); + if (!tenantId) { + return res.status(400).json({ + success: false, + message: 'Unable to determine tenant' + }); + } + + const tenant = await Tenant.findOne({ where: { slug: tenantId } }); + if (!tenant) { + return res.status(404).json({ + success: false, + message: 'Tenant not found' + }); + } + + // Check if tenant uses local authentication + if (tenant.auth_provider !== 'local') { + return res.status(400).json({ + success: false, + message: `User management is only available for local authentication. This tenant uses ${tenant.auth_provider}.` + }); + } + + const { userId } = req.params; + + // Find user in this tenant + const user = await User.findOne({ + where: { + id: userId, + tenant_id: tenant.id + } + }); + + if (!user) { + return res.status(404).json({ + success: false, + message: 'User not found in this tenant' + }); + } + + // Prevent self-deletion + if (user.id === req.user.id) { + return res.status(400).json({ + success: false, + message: 'Cannot delete your own user account' + }); + } + + // Store username for logging before deletion + const deletedUsername = user.username; + + // Delete the user permanently + await user.destroy(); + + console.log(`⚠️ User "${deletedUsername}" permanently deleted from tenant "${tenantId}" by admin "${req.user.username}"`); + + res.json({ + success: true, + message: 'User deleted successfully' + }); + + } catch (error) { + console.error('Error deleting user:', error); + res.status(500).json({ + success: false, + message: 'Failed to delete user' + }); + } +}); + /** * GET /tenant/auth * Get authentication configuration (auth admins or higher)