248 lines
8.1 KiB
JavaScript
248 lines
8.1 KiB
JavaScript
const { PERMISSIONS, normalizePermissionKeys } = require('../../rbac');
|
|
const { fetchPagedRows } = require('../../data/utils');
|
|
|
|
function parseCsvIds(value) {
|
|
return String(value || '')
|
|
.split(',')
|
|
.map(function (item) {
|
|
return Number(item);
|
|
})
|
|
.filter(function (item) {
|
|
return Number.isInteger(item) && item > 0;
|
|
});
|
|
}
|
|
|
|
async function fetchPermissions(pool) {
|
|
const [rows] = await pool.query('SELECT id, permission_key, name, section_name, description FROM permissions ORDER BY section_name ASC, name ASC');
|
|
return rows || [];
|
|
}
|
|
|
|
async function fetchRoles(pool) {
|
|
const [rows] = await pool.query(
|
|
`SELECT r.id, r.role_key, r.name, r.description, r.created_at, r.modified_at,
|
|
(SELECT COUNT(*) FROM user_roles ur WHERE ur.role_id = r.id) AS user_count,
|
|
(SELECT COUNT(*) FROM role_permissions rp WHERE rp.role_id = r.id) AS permission_count
|
|
FROM roles r
|
|
ORDER BY r.name ASC`
|
|
);
|
|
return rows || [];
|
|
}
|
|
|
|
async function fetchRolesPage(pool, page, pageSize) {
|
|
const paged = await fetchPagedRows(pool, {
|
|
selectSql: `SELECT r.id, r.role_key, r.name, r.description, r.created_at, r.modified_at,
|
|
(SELECT COUNT(*) FROM user_roles ur WHERE ur.role_id = r.id) AS user_count,
|
|
(SELECT COUNT(*) FROM role_permissions rp WHERE rp.role_id = r.id) AS permission_count
|
|
FROM roles r
|
|
ORDER BY r.name ASC`,
|
|
countSql: 'SELECT COUNT(*) AS count FROM roles',
|
|
page: page,
|
|
pageSize: pageSize
|
|
});
|
|
|
|
return Object.assign({ roles: paged.rows }, paged);
|
|
}
|
|
|
|
async function fetchRoleById(pool, roleId) {
|
|
const [rows] = await pool.query(
|
|
`SELECT r.id, r.role_key, r.name, r.description, r.created_at, r.modified_at,
|
|
(SELECT COUNT(*) FROM user_roles ur WHERE ur.role_id = r.id) AS user_count,
|
|
(SELECT COUNT(*) FROM role_permissions rp WHERE rp.role_id = r.id) AS permission_count
|
|
FROM roles r
|
|
WHERE r.id = ?
|
|
LIMIT 1`,
|
|
[roleId]
|
|
);
|
|
return rows[0] || null;
|
|
}
|
|
|
|
async function fetchRolePermissionKeys(pool, roleId) {
|
|
const [rows] = await pool.query(
|
|
`SELECT p.permission_key
|
|
FROM role_permissions rp
|
|
JOIN permissions p ON p.id = rp.permission_id
|
|
WHERE rp.role_id = ?
|
|
ORDER BY p.section_name ASC, p.name ASC`,
|
|
[roleId]
|
|
);
|
|
return (rows || []).map(function (row) {
|
|
return String(row.permission_key || '').trim();
|
|
}).filter(Boolean);
|
|
}
|
|
|
|
async function fetchRoleUserIds(pool, roleId) {
|
|
const [rows] = await pool.query(
|
|
`SELECT ur.user_id
|
|
FROM user_roles ur
|
|
WHERE ur.role_id = ?
|
|
ORDER BY ur.user_id ASC`,
|
|
[roleId]
|
|
);
|
|
return (rows || []).map(function (row) {
|
|
return Number(row.user_id);
|
|
}).filter(function (userId) {
|
|
return Number.isInteger(userId) && userId > 0;
|
|
});
|
|
}
|
|
|
|
async function fetchRolesForUser(pool, userId) {
|
|
const [rows] = await pool.query(
|
|
`SELECT r.id, r.role_key, r.name, r.description
|
|
FROM user_roles ur
|
|
JOIN roles r ON r.id = ur.role_id
|
|
WHERE ur.user_id = ?
|
|
ORDER BY r.name ASC`,
|
|
[userId]
|
|
);
|
|
return rows || [];
|
|
}
|
|
|
|
async function fetchUsersWithRoles(pool) {
|
|
const [rows] = await pool.query(
|
|
`SELECT u.id, u.name, u.username, u.created_at, u.modified_at,
|
|
COALESCE(role_data.role_names, '') AS role_names,
|
|
COALESCE(role_data.role_ids_csv, '') AS role_ids_csv
|
|
FROM users u
|
|
LEFT JOIN (
|
|
SELECT ur.user_id,
|
|
GROUP_CONCAT(DISTINCT r.name ORDER BY r.name SEPARATOR ', ') AS role_names,
|
|
GROUP_CONCAT(DISTINCT r.id ORDER BY r.name SEPARATOR ',') AS role_ids_csv
|
|
FROM user_roles ur
|
|
JOIN roles r ON r.id = ur.role_id
|
|
GROUP BY ur.user_id
|
|
) role_data ON role_data.user_id = u.id
|
|
ORDER BY u.id ASC`
|
|
);
|
|
|
|
return (rows || []).map(function (row) {
|
|
return Object.assign({}, row, {
|
|
roleIds: parseCsvIds(row.role_ids_csv),
|
|
roleNames: String(row.role_names || '').trim()
|
|
});
|
|
});
|
|
}
|
|
|
|
async function fetchUsersWithRolesPage(pool, page, pageSize) {
|
|
const paged = await fetchPagedRows(pool, {
|
|
selectSql: `SELECT u.id, u.name, u.username, u.created_at, u.modified_at,
|
|
COALESCE(role_data.role_names, '') AS role_names,
|
|
COALESCE(role_data.role_ids_csv, '') AS role_ids_csv
|
|
FROM users u
|
|
LEFT JOIN (
|
|
SELECT ur.user_id,
|
|
GROUP_CONCAT(DISTINCT r.name ORDER BY r.name SEPARATOR ', ') AS role_names,
|
|
GROUP_CONCAT(DISTINCT r.id ORDER BY r.name SEPARATOR ',') AS role_ids_csv
|
|
FROM user_roles ur
|
|
JOIN roles r ON r.id = ur.role_id
|
|
GROUP BY ur.user_id
|
|
) role_data ON role_data.user_id = u.id
|
|
ORDER BY u.id ASC`,
|
|
countSql: 'SELECT COUNT(*) AS count FROM users',
|
|
page: page,
|
|
pageSize: pageSize
|
|
});
|
|
|
|
return {
|
|
users: (paged.rows || []).map(function (row) {
|
|
return Object.assign({}, row, {
|
|
roleIds: parseCsvIds(row.role_ids_csv),
|
|
roleNames: String(row.role_names || '').trim()
|
|
});
|
|
}),
|
|
totalItems: paged.totalItems,
|
|
totalPages: paged.totalPages,
|
|
currentPage: paged.currentPage,
|
|
pageSize: paged.pageSize
|
|
};
|
|
}
|
|
|
|
async function fetchUserWithRoles(pool, userId) {
|
|
const [rows] = await pool.query(
|
|
`SELECT u.id, u.name, u.username, u.created_at, u.modified_at,
|
|
COALESCE(role_data.role_names, '') AS role_names,
|
|
COALESCE(role_data.role_ids_csv, '') AS role_ids_csv
|
|
FROM users u
|
|
LEFT JOIN (
|
|
SELECT ur.user_id,
|
|
GROUP_CONCAT(DISTINCT r.name ORDER BY r.name SEPARATOR ', ') AS role_names,
|
|
GROUP_CONCAT(DISTINCT r.id ORDER BY r.name SEPARATOR ',') AS role_ids_csv
|
|
FROM user_roles ur
|
|
JOIN roles r ON r.id = ur.role_id
|
|
GROUP BY ur.user_id
|
|
) role_data ON role_data.user_id = u.id
|
|
WHERE u.id = ?
|
|
LIMIT 1`,
|
|
[userId]
|
|
);
|
|
|
|
if (!rows.length) {
|
|
return null;
|
|
}
|
|
|
|
return Object.assign({}, rows[0], {
|
|
roleIds: parseCsvIds(rows[0].role_ids_csv),
|
|
roleNames: String(rows[0].role_names || '').trim()
|
|
});
|
|
}
|
|
|
|
async function syncUserRoles(pool, userId, roleIds) {
|
|
const uniqueRoleIds = Array.from(new Set((Array.isArray(roleIds) ? roleIds : []).map(function (roleId) {
|
|
return Number(roleId);
|
|
}).filter(function (roleId) {
|
|
return Number.isInteger(roleId) && roleId > 0;
|
|
})));
|
|
|
|
await pool.query('DELETE FROM user_roles WHERE user_id = ?', [userId]);
|
|
for (const roleId of uniqueRoleIds) {
|
|
await pool.query('INSERT IGNORE INTO user_roles (user_id, role_id, created_by, modified_by) VALUES (?, ?, ?, ?)', [userId, roleId, null, null]);
|
|
}
|
|
}
|
|
|
|
async function syncRoleUsers(pool, roleId, userIds) {
|
|
const uniqueUserIds = Array.from(new Set((Array.isArray(userIds) ? userIds : []).map(function (userId) {
|
|
return Number(userId);
|
|
}).filter(function (userId) {
|
|
return Number.isInteger(userId) && userId > 0;
|
|
})));
|
|
|
|
await pool.query('DELETE FROM user_roles WHERE role_id = ?', [roleId]);
|
|
for (const userId of uniqueUserIds) {
|
|
await pool.query('INSERT IGNORE INTO user_roles (user_id, role_id, created_by, modified_by) VALUES (?, ?, ?, ?)', [userId, roleId, null, null]);
|
|
}
|
|
}
|
|
|
|
async function syncRolePermissions(pool, roleId, permissionKeys) {
|
|
const uniquePermissionKeys = normalizePermissionKeys(permissionKeys);
|
|
|
|
if (!uniquePermissionKeys.length) {
|
|
await pool.query('DELETE FROM role_permissions WHERE role_id = ?', [roleId]);
|
|
return;
|
|
}
|
|
|
|
const [permissionRows] = await pool.query('SELECT id, permission_key FROM permissions WHERE permission_key IN (?)', [uniquePermissionKeys]);
|
|
if (permissionRows.length !== uniquePermissionKeys.length) {
|
|
throw new Error('One or more selected permissions are invalid.');
|
|
}
|
|
|
|
await pool.query('DELETE FROM role_permissions WHERE role_id = ?', [roleId]);
|
|
for (const permissionRow of permissionRows) {
|
|
await pool.query('INSERT IGNORE INTO role_permissions (role_id, permission_id, created_by, modified_by) VALUES (?, ?, ?, ?)', [roleId, Number(permissionRow.id), null, null]);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
PERMISSIONS,
|
|
fetchPermissions,
|
|
fetchRoles,
|
|
fetchRolesPage,
|
|
fetchRoleById,
|
|
fetchRolePermissionKeys,
|
|
fetchRoleUserIds,
|
|
fetchRolesForUser,
|
|
fetchUsersWithRoles,
|
|
fetchUsersWithRolesPage,
|
|
fetchUserWithRoles,
|
|
syncUserRoles,
|
|
syncRoleUsers,
|
|
syncRolePermissions
|
|
}; |