UNPKG

@coko/server

Version:

Reusable server for use by Coko's projects

241 lines 8.95 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const objection_1 = require("objection"); const logger_1 = __importDefault(require("../../logger")); const base_model_1 = __importDefault(require("../base.model")); const teamMember_model_1 = __importDefault(require("../teamMember/teamMember.model")); const user_model_1 = __importDefault(require("../user/user.model")); const teams_1 = require("../../utils/teams"); const types_1 = require("../_helpers/types"); const config_1 = __importDefault(require("../../configManager/config")); const useTransaction_1 = __importDefault(require("../useTransaction")); class Team extends base_model_1.default { objectId; objectType; displayName; role; global; members; users; constructor() { super(); this.type = 'team'; } static get tableName() { return 'teams'; } static get relationMappings() { return { members: { relation: base_model_1.default.HasManyRelation, modelClass: teamMember_model_1.default, join: { from: 'teams.id', to: 'team_members.teamId', }, }, users: { relation: base_model_1.default.ManyToManyRelation, modelClass: user_model_1.default, join: { from: 'teams.id', through: { modelClass: teamMember_model_1.default, from: 'team_members.teamId', to: 'team_members.userId', }, to: 'users.id', }, }, }; } static get schema() { const rolesEnum = (0, teams_1.teamRolesEnum)(); const displayNamesEnum = (0, teams_1.teamDisplayNamesEnum)(); return { type: 'object', required: ['role', 'displayName'], properties: { objectId: types_1.idNullable, objectType: types_1.stringNullable, displayName: { type: 'string', enum: displayNamesEnum, }, role: { type: 'string', enum: rolesEnum, }, global: types_1.booleanDefaultFalse, }, }; } /* eslint-disable-next-line class-methods-use-this */ $beforeValidate(jsonSchema, json) { let validTeamChoice; let validCombinationOfRoleAndName = true; const { global, role, displayName } = json; if (global) { const globalTeams = config_1.default.get('teams.global'); validTeamChoice = globalTeams.find(t => t.role === role); if (displayName && validTeamChoice) { validCombinationOfRoleAndName = validTeamChoice.displayName === displayName; } } else { const nonGlobalTeams = config_1.default.get('teams.nonGlobal'); validTeamChoice = nonGlobalTeams.find(t => t.role === role); if (displayName && validTeamChoice) { validCombinationOfRoleAndName = validTeamChoice.displayName === displayName; } } if (!validTeamChoice) { const errorMessage = `Role ${role} is not valid for ${global ? '' : 'non-'}global teams`; throw new objection_1.ValidationError({ type: 'ModelValidation', message: errorMessage, }); } if (!validCombinationOfRoleAndName) { const errorMessage = `Display name ${displayName} does not correspond to the provided role ${role} of ${global ? '' : 'non-'}global teams`; throw new objection_1.ValidationError({ type: 'ModelValidation', message: errorMessage, }); } return jsonSchema; } static async findAllGlobalTeams(options = {}) { try { return (0, useTransaction_1.default)(async (tr) => { return this.query(tr).where({ global: true }); }, { trx: options.trx, passedTrxOnly: true }); } catch (e) { logger_1.default.error('Team model: findAllGlobalTeams failed', e); throw e; } } static async findGlobalTeamByRole(role, options = {}) { try { return (0, useTransaction_1.default)(async (tr) => { return this.query(tr).findOne({ role, global: true, }); }, { trx: options.trx, passedTrxOnly: true }); } catch (e) { logger_1.default.error('Team model: findGlobalTeamByRole failed', e); throw e; } } static async findTeamByRoleAndObject(role, objectId, options = {}) { try { return (0, useTransaction_1.default)(async (tr) => { return this.query(tr).findOne({ role, objectId, }); }, { trx: options.trx, passedTrxOnly: true }); } catch (e) { logger_1.default.error('Team model: findTeamByRoleAndObject failed', e); throw e; } } /** * Members should be an array of user ids */ static async updateMembershipByTeamId(teamId, members, options = {}) { const queries = async (trx) => { const existingMembers = await teamMember_model_1.default.query(trx).where({ teamId }); const existingMemberUserIds = existingMembers.map(m => m.userId); // add members that exist in the incoming array, but not in the db const toAdd = members.filter(id => !existingMemberUserIds.includes(id)); await Promise.all(toAdd.map(userId => Team.addMember(teamId, userId, { trx, ...(options.status && { status: options.status }), }))); // delete members that exist in the db, but not in the incoming array const toDelete = existingMemberUserIds.filter(id => !members.includes(id)); await Promise.all(toDelete.map(userId => Team.removeMember(teamId, userId, { trx }))); return Team.findById(teamId, { trx }); }; return (0, useTransaction_1.default)(queries, { trx: options.trx }); } static async addMember(teamId, userId, options = {}) { const data = { teamId, userId, status: options.status, }; const add = async (trx) => { await teamMember_model_1.default.query(trx).insert(data); return Team.findById(teamId, { trx }); }; const trxOptions = { trx: options.trx, passedTrxOnly: true, }; try { return (0, useTransaction_1.default)(add, trxOptions); } catch (e) { logger_1.default.error('Team Model: Add member: Insert failed!'); throw e; } } static async removeMember(teamId, userId, options = {}) { const remove = async (trx) => { await teamMember_model_1.default.query(trx) .delete() .where({ teamId, userId, }) .throwIfNotFound(); return Team.findById(teamId, { trx }); }; try { return (0, useTransaction_1.default)(remove, { trx: options.trx, passedTrxOnly: true }); } catch (e) { logger_1.default.error('Team model: Remove member: Transaction failed! Rolling back...'); throw e; } } static async addMemberToGlobalTeam(userId, role, options = {}) { try { const team = await Team.findOne({ role, global: true, }, { trx: options.trx }); return Team.addMember(team.id, userId, options); } catch (e) { logger_1.default.error(`Team model: Add member to global team: ${e.message}`); throw e; } } static async removeMemberFromGlobalTeam(userId, role, options = {}) { try { const team = await Team.findOne({ role, global: true, }, { trx: options.trx }); return Team.removeMember(team.id, userId, options); } catch (e) { logger_1.default.error(`Team model: Remove member from global team: ${e.message}`); throw e; } } } exports.default = Team; //# sourceMappingURL=team.model.js.map