"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.UserCheckers = void 0; const tslib_1 = require("tslib"); const relation_1 = require("oak-domain/lib/store/relation"); const types_1 = require("oak-domain/lib/types"); const filter_1 = require("oak-domain/lib/store/filter"); const validator_1 = require("oak-domain/lib/utils/validator"); const executor_1 = require("oak-domain/lib/utils/executor"); const assert_1 = tslib_1.__importDefault(require("assert")); const Exception_1 = require("../types/Exception"); const user_1 = require("../utils/user"); const checkers = [ { type: 'row', action: 'remove', entity: 'user', filter: { userState: 'shadow', } }, { type: 'logical', action: ['remove', 'disable', 'enable'], entity: 'user', checker: (operation, context) => { // 只有root才能进行操作 if (!context.isRoot()) { throw new types_1.OakOperationUnpermittedException('user', { id: 'disable', action: 'disable', data: {} }); } } }, { type: 'data', action: 'grant', entity: 'user', checker: (data) => { if (Object.keys(data).filter(ele => !ele.includes('$')).length > 0) { throw new types_1.OakInputIllegalException('user', Object.keys(data), '授权不允许传入其它属性'); } } }, { type: 'row', action: 'disable', entity: 'user', filter: { isRoot: false, }, errMsg: '不能禁用root用户', }, { type: 'logicalData', action: 'verify', entity: 'user', checker(operation, context) { const { data, filter } = operation; const { idCardType, idNumber, extraFile$entity: photos, name } = data; (0, assert_1.default)(typeof filter.id === 'string'); const system = context.getApplication().system; const { config } = system; return (0, executor_1.pipeline)(() => context.select('user', { data: { id: 1, name: 1, idCardType: 1, idNumber: 1, extraFile$entity: { $entity: 'extraFile', data: { id: 1, tag1: 1, tag2: 1, } }, }, filter: { id: filter.id, } }, {}), (users) => { const [user] = users; const idCardType = data.idCardType || user.idCardType; const idNumber = data.idNumber || user.idNumber; const name = data.name || user.name; const photo1 = data.extraFile$entity && data.extraFile$entity.find(ele => ele.action === 'create' && ele.data.tag1 === idCardType && ele.data.tag2 === 'file1') || user.extraFile$entity && user.extraFile$entity.find(ele => ele.tag1 === idCardType && ele.tag2 === 'file1'); const photo2 = data.extraFile$entity && data.extraFile$entity.find(ele => ele.action === 'create' && ele.data.tag1 === idCardType && ele.data.tag2 === 'file2') || user.extraFile$entity && user.extraFile$entity.find(ele => ele.tag1 === idCardType && ele.tag2 === 'file2'); if (!name) { throw new types_1.OakInputIllegalException('user', ['name'], 'error::user.verifyNameEmpty'); } if (!idCardType) { throw new types_1.OakInputIllegalException('user', ['idCardType'], 'error::user.verifyIdCardTypeEmpty'); } if (!idNumber) { throw new types_1.OakInputIllegalException('user', ['idNumber'], 'error::user.verifyIdNumberTypeEmpty'); } if (config.App.needUploadIDCardPhoto) { if (!photo1) { throw new types_1.OakInputIllegalException('user', ['extraFile$entity'], 'error::user.verifyLackOfPhoto1'); } if (!photo2) { throw new types_1.OakInputIllegalException('user', ['extraFile$entity'], 'error::user.verifyLackOfPhoto2'); } } switch (idCardType) { case 'ID-Card': { if (!(0, validator_1.isIdCardNumber)(idNumber)) { throw new types_1.OakInputIllegalException('user', ['idNumber'], 'error::user.verifyIdNumberIllegal'); } break; } case 'Mainland-passport': { if (!(0, validator_1.isHkCardNumber)(idNumber) && (0, validator_1.isTwCardNumber)(idNumber) && (0, validator_1.isAmCardNumber)(idNumber)) { throw new types_1.OakInputIllegalException('user', ['idNumber'], 'error::user.verifyIdNumberIllegal'); } break; } case 'passport': { if (!(0, validator_1.isPassportNumber)(idNumber)) { throw new types_1.OakInputIllegalException('user', ['idNumber'], 'error::user.verifyIdNumberIllegal'); } break; } } }); } }, { type: 'row', entity: 'user', action: 'update', filter(operation, context) { const isRoot = context.isRoot(); if (isRoot) { return undefined; } const { data } = operation; if (data?.hasOwnProperty('password')) { return (0, user_1.getUserSafetyFilter)(context); } }, err: Exception_1.OakHasToVerifyPassword, }, { type: 'row', entity: 'user', action: 'update', filter(operation, context) { const isRoot = context.isRoot(); if (isRoot) { return undefined; } const { data } = operation; if (data?.hasOwnProperty('name') || data?.hasOwnProperty('idCardType') || data?.hasOwnProperty('idNumber') || data?.hasOwnProperty('gender') || data?.hasOwnProperty('birth')) { return { idState: { $nin: ['verified'], }, }; } }, err: Exception_1.OakHasToVerifyPassword, } ]; exports.default = checkers; exports.UserCheckers = [ { entity: 'user', action: 'update', type: 'logical', checker: (operation, context) => { // 在大部分应用中,除了root,其他人不应该有权利更新其他人信息,但是shadow用户应当除外 // 但这些条件不一定对所有的应用都成立,应用如果有更复杂的用户相互更新策略,就不要引入这个checker // 这也是个例子,如何对user这样的特殊对象进行权限控制 const userId = context.getCurrentUserId(); if (context.isRoot()) { return; } const { filter, data } = operation; for (const attr in data) { const rel = (0, relation_1.judgeRelation)(context.getSchema(), 'user', attr); if (rel !== 1) { throw new types_1.OakOperationUnpermittedException('user', operation, '您不能更新他人信息'); } } const result = (0, filter_1.checkFilterContains)('user', context, { id: userId, }, filter, true); if (result instanceof Promise) { return result.then((r) => { if (!r) { throw new types_1.OakOperationUnpermittedException('user', operation, '您不能更新他人信息'); } }); } if (!result) { throw new types_1.OakOperationUnpermittedException('user', operation, '您不能更新他人信息'); } }, } ];