UNPKG

@wepublish/api-db-mongodb

Version:

We.publish Database adapter for mongoDB

252 lines (214 loc) 7 kB
import { DBUserRoleAdapter, CreateUserRoleArgs, OptionalUserRole, UserRole, SortOrder, UpdateUserRoleArgs, DeleteUserRoleArgs, GetUserRolesArgs, ConnectionResult, LimitType, InputCursorType, UserRoleSort } from '@wepublish/api' import {Collection, Db, FilterQuery, MongoCountPreferences} from 'mongodb' import {CollectionName, DBUserRole} from './schema' import {MaxResultsPerPage} from './defaults' import {Cursor} from './cursor' import {escapeRegExp, isNonNull} from '../utility' export class MongoDBUserRoleAdapter implements DBUserRoleAdapter { private userRoles: Collection<DBUserRole> private locale: string constructor(db: Db, locale: string) { this.userRoles = db.collection(CollectionName.UserRoles) this.locale = locale } async createUserRole({input}: CreateUserRoleArgs): Promise<OptionalUserRole> { const {insertedId: id} = await this.userRoles.insertOne({ createdAt: new Date(), modifiedAt: new Date(), name: input.name, description: input.description || '', systemRole: false, //always False because only the system can create system roles permissionIDs: input.permissionIDs // Test if they exist }) const userRole = await this.userRoles.findOne({_id: id}) if (!userRole) { throw new Error('Could not create UserRole') } return { id: userRole._id, name: userRole.name, description: userRole.description, systemRole: userRole.systemRole, permissionIDs: userRole.permissionIDs } } async updateUserRole({id, input}: UpdateUserRoleArgs): Promise<OptionalUserRole> { const userRole = await this.getUserRoleByID(id) if (userRole?.systemRole) { throw new Error('Can not change SystemRoles') } const {value} = await this.userRoles.findOneAndUpdate( {_id: id}, { $set: { modifiedAt: new Date(), name: input.name, description: input.description, permissionIDs: input.permissionIDs } }, {returnOriginal: false} ) if (!value) return null const {_id: outID} = value return this.getUserRoleByID(outID) } async deleteUserRole({id}: DeleteUserRoleArgs): Promise<string | null> { const userRole = await this.getUserRoleByID(id) if (userRole?.systemRole) { throw new Error('Can not delete SystemRoles') } const {deletedCount} = await this.userRoles.deleteOne({_id: id}) return deletedCount !== 0 ? id : null } async getUserRole(name: string): Promise<OptionalUserRole> { const userRole = await this.userRoles.findOne({name}) if (userRole) { return { id: userRole._id, name: userRole.name, description: userRole.description, systemRole: userRole.systemRole, permissionIDs: userRole.permissionIDs } } else { return null } } async getUserRoleByID(id: string): Promise<OptionalUserRole> { const userRole = await this.userRoles.findOne({_id: id}) if (userRole) { return { id: userRole._id, name: userRole.name, description: userRole.description, systemRole: userRole.systemRole, permissionIDs: userRole.permissionIDs } } else { return null } } async getUserRolesByID(ids: string[]): Promise<OptionalUserRole[]> { const userRoles = await this.userRoles.find({_id: {$in: ids}}).toArray() return userRoles.map<OptionalUserRole>(userRole => ({ id: userRole._id, name: userRole.name, description: userRole.description, systemRole: userRole.systemRole, permissionIDs: userRole.permissionIDs })) } async getNonOptionalUserRolesByID(ids: string[]): Promise<UserRole[]> { const roles = await this.getUserRolesByID(ids) return roles ? roles.filter(isNonNull) : [] } async getUserRoles({ filter, sort, order, cursor, limit }: GetUserRolesArgs): Promise<ConnectionResult<UserRole>> { const limitCount = Math.min(limit.count, MaxResultsPerPage) const sortDirection = limit.type === LimitType.First ? order : -order const cursorData = cursor.type !== InputCursorType.None ? Cursor.from(cursor.data) : undefined const expr = order === SortOrder.Ascending ? cursor.type === InputCursorType.After ? '$gt' : '$lt' : cursor.type === InputCursorType.After ? '$lt' : '$gt' const sortField = userRoleSortFieldForSort(sort) const cursorFilter = cursorData ? { $or: [ {[sortField]: {[expr]: cursorData.date}}, {_id: {[expr]: cursorData.id}, [sortField]: cursorData.date} ] } : {} let textFilter: FilterQuery<any> = {} // TODO: Rename to search if (filter?.name != undefined) { textFilter['$or'] = [{name: {$regex: escapeRegExp(filter.name), $options: 'i'}}] } const [totalCount, userRoles] = await Promise.all([ this.userRoles.countDocuments(textFilter, { collation: {locale: this.locale, strength: 2} } as MongoCountPreferences), // MongoCountPreferences doesn't include collation this.userRoles .aggregate([], {collation: {locale: this.locale, strength: 2}}) .match(textFilter) .match(cursorFilter) .sort({[sortField]: sortDirection, _id: sortDirection}) .limit(limitCount + 1) .toArray() ]) const nodes = userRoles.slice(0, limitCount) if (limit.type === LimitType.Last) { nodes.reverse() } const hasNextPage = limit.type === LimitType.First ? userRoles.length > limitCount : cursor.type === InputCursorType.Before ? true : false const hasPreviousPage = limit.type === LimitType.Last ? userRoles.length > limitCount : cursor.type === InputCursorType.After ? true : false const firstUserRole = nodes[0] const lastUserRole = nodes[nodes.length - 1] const startCursor = firstUserRole ? new Cursor(firstUserRole._id, userRoleDateForSort(firstUserRole, sort)).toString() : null const endCursor = lastUserRole ? new Cursor(lastUserRole._id, userRoleDateForSort(lastUserRole, sort)).toString() : null return { nodes: nodes.map<UserRole>(({_id: id, ...userRole}) => ({id, ...userRole})), pageInfo: { startCursor, endCursor, hasNextPage, hasPreviousPage }, totalCount } } } function userRoleSortFieldForSort(sort: UserRoleSort) { switch (sort) { case UserRoleSort.CreatedAt: return 'createdAt' case UserRoleSort.ModifiedAt: return 'modifiedAt' } } function userRoleDateForSort(userRole: DBUserRole, sort: UserRoleSort): Date { switch (sort) { case UserRoleSort.CreatedAt: return userRole.createdAt case UserRoleSort.ModifiedAt: return userRole.modifiedAt } }