Release v2.4.2

This commit is contained in:
2026-08-03 12:45:27 +01:00
parent 2b9cabdab2
commit e95928f31c
141 changed files with 7694 additions and 5078 deletions
+38 -8
View File
@@ -129,14 +129,19 @@
return groups;
}
async function buildRoleCreateViewModel(formValues, selectedPermissionKeys) {
async function buildRoleCreateViewModel(formValues, selectedPermissionKeys, selectedUserIds, page, search, sort, direction, currentUserId) {
const permissionRows = await rbacData.fetchPermissions(pool);
const data = await rbacData.fetchUsersWithRolesPage(pool, page, LIST_PAGE_SIZE, search, sort, direction, {
excludeUserId: currentUserId
});
return {
formValues: {
name: String(formValues && formValues.name || '').trim(),
description: String(formValues && formValues.description || '').trim()
},
permissionGroups: buildPermissionGroups(mapPermissionsForView(permissionRows, selectedPermissionKeys))
permissionGroups: buildPermissionGroups(mapPermissionsForView(permissionRows, selectedPermissionKeys)),
users: mapUsersForView(data.users, selectedUserIds),
pagination: buildPagination(data.totalItems, data.currentPage, 'page', { search: search, sort: sort, direction: direction }, LIST_PAGE_SIZE, 'users', 'User pages')
};
}
@@ -177,11 +182,16 @@
});
app.get('/rbac/new', requirePermission('rbac.create'), function (req, res, next) {
const page = Math.max(1, Math.floor(Number(req.query.page) || 1));
const search = common.getSearchQuery(req);
const sort = common.getSortQuery(req);
const direction = common.getSortDirectionQuery(req);
const currentUserId = req.currentUser ? Number(req.currentUser.id) : null;
buildRoleCreateViewModel({
name: String(req.query.name || '').trim(),
description: String(req.query.description || '').trim()
}, []).then(function (viewModel) {
res.send(pages.renderRbacAddPage(req.query.message ? String(req.query.message) : '', req.currentUser, viewModel.formValues, viewModel.permissionGroups, 'primary'));
}, [], [], page, search, sort, direction, currentUserId).then(function (viewModel) {
res.send(pages.renderRbacAddPage(req.query.message ? String(req.query.message) : '', req.currentUser, viewModel.formValues, viewModel.permissionGroups, viewModel.users, viewModel.pagination, 'primary'));
}).catch(function (error) {
next(error);
});
@@ -191,6 +201,10 @@
try {
const name = String(req.body.name || '').trim();
const description = String(req.body.description || '').trim();
const selectedUserIds = Object.prototype.hasOwnProperty.call(req.body || {}, 'users_present')
? readArrayField(req.body, ['user_ids[]', 'user_ids'])
: [];
const normalizedUserIds = normalizeSelectedIds(selectedUserIds);
const selectedPermissionKeys = normalizePermissionKeys(Array.isArray(req.body['permission_keys[]'])
? req.body['permission_keys[]']
: req.body.permission_keys
@@ -199,18 +213,33 @@
const validPermissionKeys = new Set(permissions.map(function (permission) {
return String(permission.key || '').trim();
}));
const createViewModel = await buildRoleCreateViewModel({ name: name, description: description }, selectedPermissionKeys);
const page = Math.max(1, Math.floor(Number(req.query.page) || 1));
const search = common.getSearchQuery(req);
const sort = common.getSortQuery(req);
const direction = common.getSortDirectionQuery(req);
const currentUserId = req.currentUser ? Number(req.currentUser.id) : null;
const createViewModel = await buildRoleCreateViewModel({ name: name, description: description }, selectedPermissionKeys, selectedUserIds, page, search, sort, direction, currentUserId);
if (!name) {
return res.status(400).send(pages.renderRbacAddPage('Role name is required.', req.currentUser, createViewModel.formValues, createViewModel.permissionGroups, 'warning'));
return res.status(400).send(pages.renderRbacAddPage('Role name is required.', req.currentUser, createViewModel.formValues, createViewModel.permissionGroups, createViewModel.users, createViewModel.pagination, 'warning'));
}
if (await common.fetchDuplicateName(pool, 'a_roles', name)) {
return res.status(400).send(pages.renderRbacAddPage('A role with that name already exists.', req.currentUser, createViewModel.formValues, createViewModel.permissionGroups, 'warning'));
return res.status(400).send(pages.renderRbacAddPage('A role with that name already exists.', req.currentUser, createViewModel.formValues, createViewModel.permissionGroups, createViewModel.users, createViewModel.pagination, 'warning'));
}
if (selectedPermissionKeys.some(function (permissionKey) {
return !validPermissionKeys.has(permissionKey);
})) {
return res.status(400).send(pages.renderRbacAddPage('One or more selected permissions are invalid.', req.currentUser, createViewModel.formValues, createViewModel.permissionGroups, 'warning'));
return res.status(400).send(pages.renderRbacAddPage('One or more selected permissions are invalid.', req.currentUser, createViewModel.formValues, createViewModel.permissionGroups, createViewModel.users, createViewModel.pagination, 'warning'));
}
const availableUsers = await rbacData.fetchUsersWithRoles(pool);
const availableUserIds = new Set(availableUsers.map(function (user) {
return Number(user.id);
}));
if (normalizedUserIds.some(function (userId) {
return !availableUserIds.has(userId);
})) {
return res.status(400).send(pages.renderRbacAddPage('One or more selected users are invalid.', req.currentUser, createViewModel.formValues, createViewModel.permissionGroups, createViewModel.users, createViewModel.pagination, 'warning'));
}
const roleKey = await createUniqueRoleKey(name);
@@ -227,6 +256,7 @@
if (selectedPermissionKeys.length) {
await rbacData.syncRolePermissions(connection, insertedRoleId, selectedPermissionKeys);
}
await rbacData.syncRoleUsers(connection, insertedRoleId, normalizedUserIds);
await connection.commit();
} catch (error) {
await connection.rollback();