Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import { head, isEmpty, keys, mapKeys, omit, pick, uniqBy } from 'lodash';
- import {
- actionsColumns,
- actionsTable,
- roleActionsColumns,
- roleActionsTable,
- rolesColumns,
- rolesTable,
- userRolesColumns,
- userRolesTable,
- } from './tables';
- export const tableName = userRolesTable;
- export const columnsByProperties = userRolesColumns;
- const addRolePrefix = (string) => `role_${string}`;
- const removeRolePrefix = (string) => string.substring('role_'.length);
- const prefixedRolesColumnsByProperties = mapKeys(rolesColumns, (v, k) =>
- addRolePrefix(k)
- );
- const roleSelectColumns = selectColumnsAsProperties(
- prefixedRolesColumnsByProperties,
- rolesTable
- );
- const actionSelectColumns = selectColumnsAsProperties(
- actionsColumns,
- actionsTable
- );
- function rowToRoleAssignment(row) {
- if (!row) {
- return undefined;
- }
- return {
- id: row.id,
- scope: row.scope,
- userId: row.userId,
- role: mapKeys(pick(row, keys(prefixedRolesColumnsByProperties)), (v, k) =>
- removeRolePrefix(k)
- ),
- };
- }
- class UserRoles extends DAO {
- // returns query builder prepared for selecting assignments with roles. Note
- // that the .select() must still be called for the final query to work.
- withRole(filter) {
- // since we're joining we need to use the fully qualified column name.
- const whereClause = mapKeys(
- this.prepare(omit(filter, ['scope'])),
- (v, k) => `${tableName}.${k}`
- );
- const query = this.tx(this.tableName)
- .leftJoin(rolesTable, columnsByProperties.roleId, `${rolesTable}.id`)
- .where(whereClause);
- if (filter.scope) {
- query.where('scope', '@>', filter.scope);
- }
- return query;
- }
- actionsJoinQuery(filter) {
- // since we're joining we need to use the fully qualified column name.
- const whereClause = mapKeys(
- this.prepare(filter),
- (v, k) => `${tableName}.${k}`
- );
- return this.tx(this.tableName)
- .distinct()
- .leftJoin(
- roleActionsTable,
- `${tableName}.${columnsByProperties.roleId}`,
- `${roleActionsTable}.${roleActionsColumns.roleId}`
- )
- .leftJoin(
- actionsTable,
- `${roleActionsTable}.${roleActionsColumns.actionId}`,
- `${actionsTable}.id`
- )
- .where(whereClause);
- }
- /**
- * Returns the users roles with the full role already resolved.
- *
- * @param {object} filter
- */
- selectWithRole(filter = {}) {
- return this.withRole(filter)
- .select([
- ...roleSelectColumns,
- 'scope',
- 'user_id as userId',
- 'user_roles.id as id',
- 'user_roles.role_id as roleId',
- ])
- .then((results) => results.map(rowToRoleAssignment));
- }
- /**
- * Count the number of user roles matching the given filter.
- *
- * @param {object} filter
- */
- count(filter = {}) {
- return this.withRole(filter)
- .count('*')
- .then(head)
- .then((row) => Number(row.count));
- }
- /**
- * Count the number of user matching the given filter.
- *
- * @param {object} filter
- */
- countUniqueUsers(filter = {}) {
- const subQuery = this.withRole(filter);
- return this.tx
- .count('*')
- .from(subQuery.distinct(columnsByProperties.userId).as('users'))
- .then(head)
- .then((row) => Number(row.count));
- }
- /**
- * Returns the first role assignment matching the given filter.
- *
- * @param {object} filter
- */
- selectFirstWithRole(filter = {}) {
- return this.withRole(filter)
- .first([...roleSelectColumns, 'user_id as userId', 'user_roles.id as id'])
- .then(rowToRoleAssignment);
- }
- /**
- * Select all actions in any role matching the filter.
- */
- selectActions(filter = {}) {
- return this.actionsJoinQuery(filter)
- .select(actionSelectColumns)
- .orderBy('name');
- }
- studyUsers({ filter, pagination = {} }) {
- const builder = this.tx('user_roles').select(['user_id AS id']);
- const { studyId, siteId, roleIds, roleNames, userIds } = filter;
- if (studyId) {
- switch (filter.studyIdRestriction) {
- // Only one ID allowed. Users with more ids or * are excluded.
- case 'SINGLE':
- builder.whereRaw("scope ->> 'studies' = ?", [`["${studyId}"]`]);
- break;
- // Only one ID or * allowed. Users with more ids are excluded.
- case 'SINGLE_OR_WILDCARD':
- builder.where((qbStudy) =>
- qbStudy
- .whereRaw("scope ->> 'studies' = ?", [`["${studyId}"]`])
- .orWhereRaw(`scope ->> 'studies' = '["*"]'`)
- );
- break;
- // Wildcard * is not allowed. However users with multiple IDs are included.
- case 'NO_WILDCARD':
- builder.where('scope', '@>', { studies: Array.of(studyId) });
- break;
- // No restrictions (= single id, multiple ids, wildcard included)
- case 'NONE':
- default:
- builder.where((qbStudy) =>
- qbStudy
- .where('scope', '@>', { studies: Array.of(studyId) })
- .orWhere('scope', '@>', { studies: Array.of('*') })
- );
- break;
- }
- }
- if (siteId) {
- switch (filter.siteIdRestriction) {
- // Only one ID allowed. Users with more ids or * are excluded.
- case 'SINGLE':
- builder.whereRaw("scope ->> 'sites' = ?", [`["${siteId}"]`]);
- break;
- // Only one ID or * allowed. Users with more ids are excluded.
- case 'SINGLE_OR_WILDCARD':
- builder.where((qbStudy) =>
- qbStudy
- .whereRaw("scope ->> 'sites' = ?", [`["${siteId}"]`])
- .orWhereRaw(`scope ->> 'sites' = '["*"]'`)
- );
- break;
- // Wildcard * is not allowed. However users with multiple IDs are included.
- case 'NO_WILDCARD':
- builder.where('scope', '@>', { sites: Array.of(siteId) });
- break;
- // No restrictions (= single id, multiple ids, wildcard included)
- case 'NONE':
- default:
- builder.where((qbStudy) =>
- qbStudy
- .where('scope', '@>', { sites: Array.of(siteId) })
- .orWhere('scope', '@>', { sites: Array.of('*') })
- );
- break;
- }
- }
- if (!isEmpty(roleIds)) {
- builder.whereIn(columnsByProperties.roleId, roleIds);
- }
- if (!isEmpty(userIds)) {
- builder.whereIn(columnsByProperties.userId, userIds);
- }
- if (!isEmpty(roleNames)) {
- builder
- .leftJoin(rolesTable, columnsByProperties.roleId, `${rolesTable}.id`)
- .whereIn(`${rolesTable}.${rolesColumns.name}`, roleNames);
- }
- const { skip, limit } = pagination;
- if (skip) builder.offset(skip);
- if (limit) builder.limit(limit);
- return builder.then((x) => uniqBy(x, 'id'));
- }
- /**
- * Select all actions in any role matching the filter.
- */
- countActions(filter = {}) {
- return this.actionsJoinQuery(filter)
- .countDistinct('actions.id')
- .then(head)
- .then((row) => Number(row.count));
- }
- insertAll({ userId, assignments }) {
- return this.tx(tableName)
- .returning(this.selectColumns)
- .insert(
- assignments.map((assignment) => this.prepare({ userId, ...assignment }))
- );
- }
- }
- export default function userRoles(tx) {
- return new UserRoles({ tx, tableName, columnsByProperties });
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement