UNPKG

shyft

Version:

Model driven GraphQL API framework

970 lines (969 loc) 49.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.processActionPermissions = exports.processViewEntityPermissions = exports.processEntityPermissions = exports.findEmptyEntityPermissions = exports.hasEmptyPermissions = exports.checkPermissionAdvanced = exports.buildActionPermissionFilter = exports.buildPermissionFilter = exports.buildPermissionFilterSingle = exports.buildLookupsPermissionFilter = exports.buildValuesPermissionFilter = exports.buildStatesPermissionFilter = exports.buildUserAttributesPermissionFilter = exports.isPermissionSimple = exports.checkPermissionSimple = exports.generatePermissionDescription = exports.validateActionLookupPermission = exports.findMissingPermissionStates = exports.findMissingPermissionAttributes = exports.findInvalidPermissionAttributes = exports.isPermissionsArray = exports.isPermission = exports.Permission = void 0; var _ = __importStar(require("lodash")); var util_1 = require("../util"); var Entity_1 = require("../entity/Entity"); var DataTypeUser_1 = require("../datatype/DataTypeUser"); var Mutation_1 = require("../mutation/Mutation"); var Subscription_1 = require("../subscription/Subscription"); var DataTypeState_1 = require("../datatype/DataTypeState"); /* all permission rules are ... - combined with OR on the same type level - combined with AND among all types - combined with OR among Permission objects */ var compatibilityList = [ ['everyone', 'lookup', 'value', 'state'], ['authenticated', 'role', 'userAttribute', 'lookup', 'value', 'state'], ['role', 'userAttribute', 'lookup', 'value', 'state'], ]; var Permission = /** @class */ (function () { /* eslint-enable no-undef */ function Permission() { this.isEmpty = true; this.everyoneCanAccess = false; this.authenticatedCanAccess = false; this.types = {}; this.roles = []; this.userAttributes = []; this.lookups = []; this.values = []; this.states = []; return this; } Permission.prototype._checkCompatibility = function (type) { var _this = this; this.types[type] = true; var found = compatibilityList.find(function (list) { var allFound = true; Object.keys(_this.types).map(function (key) { if (!list.includes(key)) { allFound = false; } }); return allFound; }); util_1.passOrThrow(found, function () { return "Permission type '" + type + "' is incompatible with other types"; }); }; Permission.prototype.everyone = function () { this.isEmpty = false; this._checkCompatibility('everyone'); this.everyoneCanAccess = true; return this; }; Permission.prototype.authenticated = function () { this.isEmpty = false; this._checkCompatibility('authenticated'); this.authenticatedCanAccess = true; return this; }; Permission.prototype.role = function (name) { this.isEmpty = false; this._checkCompatibility('role'); util_1.passOrThrow(name, function () { return "Permission type 'role' expects a role name"; }); this.roles.push(name); util_1.passOrThrow(this.roles.length === _.uniq(this.roles).length, function () { return "Duplicate role '" + name + "' for permission type 'role'"; }); return this; }; Permission.prototype.userAttribute = function (attributeName) { this.isEmpty = false; this._checkCompatibility('userAttribute'); util_1.passOrThrow(attributeName, function () { return "Permission type 'userAttribute' expects an attribute name"; }); this.userAttributes.push(attributeName); util_1.passOrThrow(this.userAttributes.length === _.uniq(this.userAttributes).length, function () { return "Duplicate attribute name '" + attributeName + "' for permission type 'userAttribute'"; }); return this; }; Permission.prototype.lookup = function (entity, lookupMap) { this.isEmpty = false; this._checkCompatibility('lookup'); util_1.passOrThrow(util_1.isFunction(entity) || Entity_1.isEntity(entity), function () { return "Permission type 'lookup' expects an entity"; }); util_1.passOrThrow(util_1.isMap(lookupMap, true), function () { return "Permission type 'lookup' expects a lookupMap"; }); this.lookups.push({ entity: entity, lookupMap: lookupMap, }); return this; }; Permission.prototype.value = function (attributeName, value) { this.isEmpty = false; this._checkCompatibility('value'); util_1.passOrThrow(attributeName, function () { return "Permission type 'value' expects an attribute name"; }); util_1.passOrThrow(typeof value !== 'undefined', function () { return "Permission type 'value' expects a value"; }); this.values.push({ attributeName: attributeName, value: value, }); return this; }; Permission.prototype.state = function (stateName) { this.isEmpty = false; this._checkCompatibility('state'); util_1.passOrThrow(stateName, function () { return "Permission type 'state' expects a state name"; }); this.states.push(stateName); return this; }; Permission.prototype.toString = function () { return 'Permission Object'; }; /* eslint-disable no-undef */ Permission.EVERYONE = new Permission().everyone(); Permission.AUTHENTICATED = new Permission().authenticated(); return Permission; }()); exports.Permission = Permission; var isPermission = function (obj) { return obj instanceof Permission; }; exports.isPermission = isPermission; var isPermissionsArray = function (obj) { if (util_1.isArray(obj, true)) { return obj.reduce(function (prev, permission) { return prev && exports.isPermission(permission); }, true); } return false; }; exports.isPermissionsArray = isPermissionsArray; var findInvalidPermissionAttributes = function (permission, entity) { var attributes = entity.getAttributes(); permission.userAttributes.map(function (userAttribute) { var attribute = attributes[userAttribute]; var attributeTypeAsEntity = attribute.type; var entityAsEntity = entity; util_1.passOrThrow(attribute && (DataTypeUser_1.isDataTypeUser(attribute.type) || (entityAsEntity.isUserEntity && entityAsEntity.getPrimaryAttribute() === attribute) || (Entity_1.isEntity(attribute.type) && attributeTypeAsEntity.isUserEntity)), function () { return "Cannot use attribute '" + userAttribute + "' in '" + entity.name + ".permissions' as 'userAttribute' as it is not a reference to the User entity"; }); }); }; exports.findInvalidPermissionAttributes = findInvalidPermissionAttributes; var findMissingPermissionAttributes = function (permission, permissionEntity, mutation) { var entityAttributeNames = Object.keys(permissionEntity.getAttributes()); var missinguserAttribute = permission.userAttributes.find(function (userAttribute) { return !entityAttributeNames.includes(userAttribute); }); if (missinguserAttribute) { return missinguserAttribute; } var missingLookupAttribute; permission.lookups.map(function (lookup) { var _entity = lookup.entity, lookupMap = lookup.lookupMap; var entity = _entity; if (util_1.isFunction(_entity)) { entity = lookup.entity = _entity(); } var lookupEntityAttributes = entity.getAttributes(); var lookupEntityAttributeNames = Object.keys(lookupEntityAttributes); _.forEach(lookupMap, function (sourceAttribute, targetAttribute) { if (!util_1.isFunction(sourceAttribute) && !entityAttributeNames.includes(sourceAttribute)) { missingLookupAttribute = sourceAttribute; return; } else if (!lookupEntityAttributeNames.includes(targetAttribute)) { missingLookupAttribute = entity.name + "." + targetAttribute; return; } if (Mutation_1.isMutation(mutation) && mutation.type === Mutation_1.MUTATION_TYPE_CREATE && !util_1.isFunction(sourceAttribute)) { throw new Error("'lookup' type permission used in 'create' type mutation '" + mutation.name + "' can only have mappings to value functions"); } }); }); if (missingLookupAttribute) { return missingLookupAttribute; } var missingValueAttribute = permission.values.find(function (_a) { var attributeName = _a.attributeName; return !entityAttributeNames.includes(attributeName); }); if (missingValueAttribute) { return missingValueAttribute.attributeName; } return false; }; exports.findMissingPermissionAttributes = findMissingPermissionAttributes; var findMissingPermissionStates = function (permission, permissionEntity) { var entityStates = permissionEntity.getStates(); if (entityStates) { var missingState = permission.states.find(function (state) { return !entityStates[state]; }); if (missingState) { return missingState; } } return false; }; exports.findMissingPermissionStates = findMissingPermissionStates; var validateActionLookupPermission = function (permission, permissionAction) { permission.lookups.map(function (lookup) { var _entity = lookup.entity, lookupMap = lookup.lookupMap; var entity = _entity; if (util_1.isFunction(_entity)) { entity = lookup.entity = _entity(); } var lookupEntityAttributes = entity.getAttributes(); var lookupEntityAttributeNames = Object.keys(lookupEntityAttributes); _.forEach(lookupMap, function (sourceAttribute, targetAttribute) { util_1.passOrThrow(util_1.isFunction(sourceAttribute), function () { return "Only functions are allowed in '" + permissionAction.name + ".permissions' for value lookups"; }); util_1.passOrThrow(lookupEntityAttributeNames.includes(targetAttribute), function () { return "Cannot use attribute '" + targetAttribute + "' in '" + permissionAction.name + ".permissions' as it does not exist"; }); }); }); }; exports.validateActionLookupPermission = validateActionLookupPermission; var generatePermissionDescription = function (permissions) { var descriptions = []; var permissionsArray = util_1.isArray(permissions) ? permissions : [permissions]; permissionsArray.map(function (permission) { var lines = []; util_1.passOrThrow(exports.isPermission(permission), function () { return 'generatePermissionDescription needs a valid permission object'; }); if (permission.everyoneCanAccess) { lines.push('everyone'); } if (permission.authenticatedCanAccess) { lines.push('authenticated'); } if (permission.roles.length > 0) { lines.push("roles: " + permission.roles.join(', ')); } if (permission.userAttributes.length > 0) { lines.push("userAttributes: " + permission.userAttributes.join(', ')); } if (permission.states.length > 0) { lines.push("states: " + permission.states.join(', ')); } if (permission.lookups.length > 0) { var lookupBullets = permission.lookups.reduce(function (lprev, _a) { var entity = _a.entity, lookupMap = _a.lookupMap; var attributeBullets = _.reduce(lookupMap, function (aprev, target, source) { return aprev + "\n - " + source + " -> " + (util_1.isFunction(target) ? 'λ' : target); }, ''); return lprev + "\n - Entity: " + entity + " " + attributeBullets; }, ''); lines.push("lookups: " + lookupBullets); } if (permission.values.length > 0) { var valueBullets = permission.values.reduce(function (prev, _a) { var attributeName = _a.attributeName, value = _a.value; return prev + "\n - " + attributeName + " = " + value; }, ''); lines.push("values: " + valueBullets); } if (lines.length > 0) { var bullets = lines.reduce(function (prev, next) { return prev + "\n- " + next; }, ''); descriptions.push(bullets); } }); if (descriptions.length > 0) { var text = '\n***\n**Permissions:**\n'; return text + descriptions.join('\n\n---'); } return false; }; exports.generatePermissionDescription = generatePermissionDescription; var checkPermissionSimple = function (permission, userId, userRoles) { if (userId === void 0) { userId = null; } if (userRoles === void 0) { userRoles = []; } util_1.passOrThrow(exports.isPermission(permission), function () { return 'checkPermissionSimple needs a valid permission object'; }); util_1.passOrThrow(!userRoles || util_1.isArray(userRoles), function () { return 'checkPermissionSimple needs a valid list of assigned user roles'; }); if (!permission.everyoneCanAccess && !permission.authenticatedCanAccess && !permission.roles.length) { return true; } if (userId && userRoles) { var foundRole_1 = false; permission.roles.map(function (role) { if (userRoles.includes(role)) { foundRole_1 = true; } }); if (foundRole_1) { return true; } } if (permission.authenticatedCanAccess && userId && !permission.roles.length) { return true; } if (permission.everyoneCanAccess) { return true; } return false; }; exports.checkPermissionSimple = checkPermissionSimple; var isPermissionSimple = function (permission) { if (!exports.isPermission(permission)) { throw new Error('isPermissionSimple needs a valid permission object'); } return (!permission.userAttributes.length && !permission.states.length && !permission.lookups.length && !permission.values.length); }; exports.isPermissionSimple = isPermissionSimple; var buildUserAttributesPermissionFilter = function (_a) { var permission = _a.permission, userId = _a.userId; var where; if (permission.userAttributes.length > 0) { util_1.passOrThrow(userId, function () { return 'missing userId in permission object'; }); where = {}; permission.userAttributes.map(function (attributeName) { var _a; var userAttrFilter = (_a = {}, _a[attributeName] = userId, _a); if (!where.$or) { where = { $or: [userAttrFilter] }; } else { where.$or.push(userAttrFilter); } }); } return where; }; exports.buildUserAttributesPermissionFilter = buildUserAttributesPermissionFilter; var buildStatesPermissionFilter = function (_a) { var permission = _a.permission, entity = _a.entity; var where; if (permission.states.length > 0) { util_1.passOrThrow(entity, function () { return 'missing entity in permission object'; }); where = {}; var states_1 = entity.getStates(); var stateIds = permission.states.map(function (stateName) { var state = states_1[stateName]; util_1.passOrThrow(state, function () { return "unknown state name '" + stateName + "' used in permission object"; }); return state; }); where.$or = [ { state: { $in: stateIds, }, }, ]; } return where; }; exports.buildStatesPermissionFilter = buildStatesPermissionFilter; var buildValuesPermissionFilter = function (_a) { var permission = _a.permission; var where; if (permission.values.length > 0) { where = {}; permission.values.map(function (_a) { var _b; var attributeName = _a.attributeName, value = _a.value; var filter = (_b = {}, _b[attributeName] = value, _b); if (!where.$or) { where = { $or: [filter] }; } else { where.$or.push(filter); } }); } return where; }; exports.buildValuesPermissionFilter = buildValuesPermissionFilter; var buildLookupsPermissionFilter = function (_a) { var permission = _a.permission, userId = _a.userId, userRoles = _a.userRoles, input = _a.input, context = _a.context; return __awaiter(void 0, void 0, void 0, function () { var where; return __generator(this, function (_b) { switch (_b.label) { case 0: if (!(permission.lookups.length > 0)) return [3 /*break*/, 2]; where = {}; return [4 /*yield*/, Promise.all(permission.lookups.map(function (_a) { var entity = _a.entity, lookupMap = _a.lookupMap; return __awaiter(void 0, void 0, void 0, function () { var condition, targetAttributes, filter; return __generator(this, function (_b) { switch (_b.label) { case 0: condition = []; targetAttributes = Object.keys(lookupMap); return [4 /*yield*/, Promise.all(targetAttributes.map(function (targetAttribute) { return __awaiter(void 0, void 0, void 0, function () { var sourceAttribute, operator, value, attr, states_2; return __generator(this, function (_a) { switch (_a.label) { case 0: sourceAttribute = lookupMap[targetAttribute]; operator = '$eq'; if (!util_1.isFunction(sourceAttribute)) return [3 /*break*/, 2]; return [4 /*yield*/, sourceAttribute({ userId: userId, userRoles: userRoles, input: input, context: context, })]; case 1: value = _a.sent(); attr = entity.getAttributes(); if (attr && attr[targetAttribute] && DataTypeState_1.isDataTypeState(attr[targetAttribute].type)) { states_2 = entity.getStates(); value = util_1.isArray(value) ? value.map(function (stateName) { return states_2[stateName] || stateName; }) : states_2[value] || value; } if (util_1.isArray(value)) { operator = '$in'; } condition.push({ targetAttribute: targetAttribute, operator: operator, value: value, }); return [3 /*break*/, 3]; case 2: condition.push({ targetAttribute: targetAttribute, operator: operator, sourceAttribute: sourceAttribute, }); _a.label = 3; case 3: return [2 /*return*/]; } }); }); }))]; case 1: _b.sent(); filter = { $sub: { entity: entity.name, condition: condition, }, }; if (!where.$or) { where.$or = [filter]; } else { where.$or.push(filter); } return [2 /*return*/]; } }); }); }))]; case 1: _b.sent(); _b.label = 2; case 2: return [2 /*return*/, where]; } }); }); }; exports.buildLookupsPermissionFilter = buildLookupsPermissionFilter; var buildPermissionFilterSingle = function (permission, userId, userRoles, entity, input, context) { return __awaiter(void 0, void 0, void 0, function () { var where, params, permissionFilters, _a; return __generator(this, function (_b) { switch (_b.label) { case 0: params = { permission: permission, userId: userId, userRoles: userRoles, entity: entity, input: input, context: context }; _a = [exports.buildUserAttributesPermissionFilter(params), exports.buildStatesPermissionFilter(params), exports.buildValuesPermissionFilter(params)]; return [4 /*yield*/, exports.buildLookupsPermissionFilter(params)]; case 1: permissionFilters = _a.concat([ _b.sent() ]); permissionFilters.map(function (permissionFilter) { if (permissionFilter) { where = where || {}; // where.$and = where.$and || []; if (!where.$and) { where.$and = [permissionFilter]; } else { where.$and.push(permissionFilter); } } }); return [2 /*return*/, where]; } }); }); }; exports.buildPermissionFilterSingle = buildPermissionFilterSingle; var buildPermissionFilter = function (_permissions, userId, userRoles, entity, input, context) { return __awaiter(void 0, void 0, void 0, function () { var where, permissions, foundSimplePermission; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!_permissions) { return [2 /*return*/, where]; } permissions = util_1.isArray(_permissions) ? _permissions : [_permissions]; foundSimplePermission = false; return [4 /*yield*/, util_1.asyncForEach(permissions, function (permission) { return __awaiter(void 0, void 0, void 0, function () { var initialPass, permissionFilter; return __generator(this, function (_a) { switch (_a.label) { case 0: if (foundSimplePermission) { return [2 /*return*/]; } initialPass = exports.checkPermissionSimple(permission, userId, userRoles); if (!initialPass) return [3 /*break*/, 2]; // it's a simple permission and permission check passed so let's skip any further checks and give direct access if (exports.isPermissionSimple(permission)) { foundSimplePermission = true; where = {}; return [2 /*return*/]; } return [4 /*yield*/, exports.buildPermissionFilterSingle(permission, userId, userRoles, entity, input, context)]; case 1: permissionFilter = _a.sent(); if (permissionFilter) { where = where || {}; // where.$or = where.$or || []; if (!where.$or) { where.$or = [permissionFilter]; } else { where.$or.push(permissionFilter); } } _a.label = 2; case 2: return [2 /*return*/]; } }); }); })]; case 1: _a.sent(); return [2 /*return*/, where]; } }); }); }; exports.buildPermissionFilter = buildPermissionFilter; var buildActionPermissionFilter = function (_permissions, userId, userRoles, action, // action: Action, input, context) { if (userId === void 0) { userId = null; } if (userRoles === void 0) { userRoles = []; } return __awaiter(void 0, void 0, void 0, function () { var where, lookupPermissionEntity, permissions, permissionFn, permissionResult, foundSimplePermission; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!_permissions) { // return where; return [2 /*return*/, undefined]; } if (util_1.isFunction(_permissions)) { permissionFn = _permissions; permissionResult = permissionFn(); permissions = util_1.isArray(permissionResult) ? permissionResult : [permissionResult]; } else if (util_1.isArray(_permissions)) { permissions = _permissions; } else { permissions = [_permissions]; } foundSimplePermission = false; return [4 /*yield*/, Promise.all(permissions.map(function (permission) { return __awaiter(void 0, void 0, void 0, function () { var initialPass, params, permissionFilter; return __generator(this, function (_a) { switch (_a.label) { case 0: if (foundSimplePermission) { return [2 /*return*/]; } initialPass = exports.checkPermissionSimple(permission, userId, userRoles); if (!initialPass) return [3 /*break*/, 2]; // it's a simple permission and permission check passed so let's skip any further checks and give direct access if (exports.isPermissionSimple(permission)) { foundSimplePermission = true; where = {}; return [2 /*return*/]; } params = { permission: permission, userId: userId, userRoles: userRoles, action: action, input: input, context: context, }; return [4 /*yield*/, exports.buildLookupsPermissionFilter(params)]; case 1: permissionFilter = _a.sent(); if (permissionFilter) { where = where || {}; // where.$or = where.$or || []; if (!where.$or) { where.$or = [permissionFilter]; } else { where.$or.push(permissionFilter); } lookupPermissionEntity = permission.lookups[0].entity; } _a.label = 2; case 2: return [2 /*return*/]; } }); }); }))]; case 1: _a.sent(); return [2 /*return*/, { where: where, lookupPermissionEntity: lookupPermissionEntity, }]; } }); }); }; exports.buildActionPermissionFilter = buildActionPermissionFilter; var checkPermissionAdvanced = function (data, permission, userId) { if (userId === void 0) { userId = null; } util_1.passOrThrow(exports.isPermission(permission), function () { return 'checkPermissionAdvanced needs a valid permission object'; }); if (permission.userAttributes.length > 0) { if (!userId) { return false; } var matchesUser = permission.userAttributes.find(function (attributeName) { return data[attributeName] === userId; }); return matchesUser; } return false; }; exports.checkPermissionAdvanced = checkPermissionAdvanced; var validatePermissionAttributesAndStates = function (entity, permissions, _mutation) { // const permissionsArray = isArray(permissions) ? permissions : [permissions]; var permissionsArray = util_1.isArray(permissions) ? permissions : [permissions]; var mutation = Mutation_1.isMutation(_mutation) ? _mutation : null; var mutationAsMutation = _mutation; var mutationName = Mutation_1.isMutation(_mutation) ? mutationAsMutation.name : String(_mutation); permissionsArray.map(function (permission) { var invalidAttribute = exports.findMissingPermissionAttributes(permission, entity, mutation); util_1.passOrThrow(!invalidAttribute, function () { return "Cannot use attribute '" + invalidAttribute + "' in '" + entity.name + ".permissions' for '" + mutationName + "' as it does not exist"; }); exports.findInvalidPermissionAttributes(permission, entity); var entityAsEntity = entity; if (entityAsEntity.getStates) { var invalidState_1 = exports.findMissingPermissionStates(permission, entity); util_1.passOrThrow(!invalidState_1, function () { return "Cannot use state '" + invalidState_1 + "' in '" + entity.name + ".permissions' for '" + mutationName + "' as it does not exist"; }); } }); }; var validatePermissionMutationTypes = function (entity, permissions, mutation) { if (mutation.type === Mutation_1.MUTATION_TYPE_CREATE) { // const permissionsArray = isArray(permissions) ? permissions : [permissions]; var permissionsArray = util_1.isArray(permissions) ? permissions : [permissions]; permissionsArray.map(function (permission) { util_1.passOrThrow(!permission.userAttributes.length && !permission.states.length && !permission.values.length, function () { return "Create type mutation permission '" + mutation.name + "' in '" + entity.name + ".permissions' can only be of type 'authenticated', 'everyone', 'role' or 'lookup'"; }); }); } }; var validatePermissionSubscriptionTypes = function (entity, permissions, subscription) { if (subscription.type === Subscription_1.SUBSCRIPTION_TYPE_CREATE) { var permissionsArray = util_1.isArray(permissions) ? permissions : [permissions]; permissionsArray.map(function (permission) { util_1.passOrThrow(!permission.userAttributes.length && !permission.states.length && !permission.values.length, function () { return "Create type subscription permission '" + subscription.name + "' in '" + entity.name + ".permissions' can only be of type 'authenticated', 'everyone', 'role' or 'lookup'"; }); }); } }; var hasEmptyPermissions = function (_permissions) { if (exports.isPermissionsArray(_permissions)) { var permissions = _permissions; var foundEmpty = permissions.find(function (_a) { var isEmpty = _a.isEmpty; return isEmpty; }); return !!foundEmpty; } var permission = _permissions; return permission.isEmpty; }; exports.hasEmptyPermissions = hasEmptyPermissions; var findEmptyEntityPermissions = function (permissions) { var emptyPermissionsIn = []; if (permissions.read && exports.hasEmptyPermissions(permissions.read)) { emptyPermissionsIn.push('read'); } if (permissions.find && exports.hasEmptyPermissions(permissions.find)) { emptyPermissionsIn.push('find'); } if (permissions.mutations) { var mutationNames = Object.keys(permissions.mutations); mutationNames.map(function (mutationName) { if (permissions.mutations[mutationName] && exports.hasEmptyPermissions(permissions.mutations[mutationName])) { emptyPermissionsIn.push("mutations." + mutationName); } }); } if (permissions.subscriptions) { var subscriptionNames = Object.keys(permissions.subscriptions); subscriptionNames.map(function (subscriptionName) { if (permissions.subscriptions[subscriptionName] && exports.hasEmptyPermissions(permissions.subscriptions[subscriptionName])) { emptyPermissionsIn.push("subscriptions." + subscriptionName); } }); } return emptyPermissionsIn; }; exports.findEmptyEntityPermissions = findEmptyEntityPermissions; var processEntityPermissions = function (entity, permissions, defaultPermissions) { util_1.passOrThrow(util_1.isMap(permissions), function () { return "Entity '" + entity.name + "' permissions definition needs to be an object"; }); if (permissions.read) { util_1.passOrThrow(exports.isPermission(permissions.read) || exports.isPermissionsArray(permissions.read), function () { return "Invalid 'read' permission definition for entity '" + entity.name + "'"; }); } else if (defaultPermissions) { permissions.read = defaultPermissions.read; } if (permissions.find) { util_1.passOrThrow(exports.isPermission(permissions.find) || exports.isPermissionsArray(permissions.find), function () { return "Invalid 'find' permission definition for entity '" + entity.name + "'"; }); } else if (defaultPermissions) { permissions.find = defaultPermissions.find; } var entityMutations = entity.getMutations(); if (!permissions.mutations && defaultPermissions) { permissions.mutations = {}; } if (permissions.mutations) { util_1.passOrThrow(util_1.isMap(permissions.mutations), function () { return "Entity '" + entity.name + "' permissions definition for mutations needs to be a map of mutations and permissions"; }); var mutationNames = Object.keys(permissions.mutations); mutationNames.map(function (mutationName, idx) { util_1.passOrThrow(exports.isPermission(permissions.mutations[mutationName]) || exports.isPermissionsArray(permissions.mutations[mutationName]), function () { return "Invalid mutation permission definition for entity '" + entity.name + "' at position '" + idx + "'"; }); }); if (defaultPermissions) { entityMutations.map(function (_a) { var mutationName = _a.name; if (defaultPermissions.mutations) { permissions.mutations[mutationName] = permissions.mutations[mutationName] || defaultPermissions.mutations[mutationName] || defaultPermissions.mutations._default; } }); } } var entitySubscriptions = entity.getSubscriptions(); if (!permissions.subscriptions && defaultPermissions) { permissions.subscriptions = {}; } if (permissions.subscriptions) { util_1.passOrThrow(util_1.isMap(permissions.subscriptions), function () { return "Entity '" + entity.name + "' permissions definition for subscriptions needs to be a map of subscriptions and permissions"; }); var subscriptionNames = Object.keys(permissions.subscriptions); subscriptionNames.map(function (subscriptionName, idx) { util_1.passOrThrow(exports.isPermission(permissions.subscriptions[subscriptionName]) || exports.isPermissionsArray(permissions.subscriptions[subscriptionName]), function () { return "Invalid subscription permission definition for entity '" + entity.name + "' at position '" + idx + "'"; }); }); if (defaultPermissions) { entitySubscriptions.map(function (_a) { var subscriptionName = _a.name; if (defaultPermissions.subscriptions) { permissions.subscriptions[subscriptionName] = permissions.subscriptions[subscriptionName] || defaultPermissions.subscriptions[subscriptionName] || defaultPermissions.subscriptions._default; } }); } } if (permissions.find) { validatePermissionAttributesAndStates(entity, permissions.find, 'find'); } if (permissions.read) { validatePermissionAttributesAndStates(entity, permissions.read, 'read'); } if (permissions.mutations && entityMutations) { var permissionMutationNames = Object.keys(permissions.mutations); var mutationNames_1 = entityMutations.map(function (mutation) { return mutation.name; }); permissionMutationNames.map(function (permissionMutationName) { util_1.passOrThrow(mutationNames_1.includes(permissionMutationName), function () { return "Unknown mutation '" + permissionMutationName + "' used for permissions in entity '" + entity.name + "'"; }); }); entityMutations.map(function (mutation) { var mutationName = mutation.name; var permission = permissions.mutations[mutationName]; if (permission) { validatePermissionMutationTypes(entity, permission, mutation); validatePermissionAttributesAndStates(entity, permission, mutation); } }); } if (permissions.subscriptions && entitySubscriptions) { var permissionSubscriptionNames = Object.keys(permissions.subscriptions); var subscriptionNames_1 = entitySubscriptions.map(function (subscription) { return subscription.name; }); permissionSubscriptionNames.map(function (permissionSubscriptionName) { util_1.passOrThrow(subscriptionNames_1.includes(permissionSubscriptionName), function () { return "Unknown subscription '" + permissionSubscriptionName + "' used for permissions in entity '" + entity.name + "'"; }); }); entitySubscriptions.map(function (subscription) { var subscriptionName = subscription.name; var permission = permissions.subscriptions[subscriptionName]; if (permission) { // not sure it's needed for subscription validatePermissionSubscriptionTypes(entity, permission, subscription); validatePermissionAttributesAndStates(entity, permission, subscription.type); } }); } var emptyPermissionsIn = exports.findEmptyEntityPermissions(permissions); util_1.passOrThrow(emptyPermissionsIn.length === 0, function () { return "Entity '" + entity.name + "' has one or more empty permission definitions in: " + emptyPermissionsIn.join(', '); }); return permissions; }; exports.processEntityPermissions = processEntityPermissions; var processViewEntityPermissions = function (entity, permissions, defaultPermissions) { util_1.passOrThrow(util_1.isMap(permissions), function () { return "ViewEntity '" + entity.name + "' permissions definition needs to be an object"; }); if (permissions.read) { util_1.passOrThrow(exports.isPermission(permissions.read) || exports.isPermissionsArray(permissions.read), function () { return "Invalid 'read' permission definition for entity '" + entity.name + "'"; }); } else if (defaultPermissions) { permissions.read = defaultPermissions.read; } if (permissions.find) { util_1.passOrThrow(exports.isPermission(permissions.find) || exports.isPermissionsArray(permissions.find), function () { return "Invalid 'find' permission definition for entity '" + entity.name + "'"; }); } else if (defaultPermissions) { permissions.find = defaultPermissions.find; } if (permissions.find) { validatePermissionAttributesAndStates(entity, permissions.find, 'find'); } if (permissions.read) { validatePermissionAttributesAndStates(entity, permissions.read, 'read'); } var emptyPermissionsIn = exports.findEmptyEntityPermissions(permissions); util_1.passOrThrow(emptyPermissionsIn.length === 0, function () { return "ViewEntity '" + entity.name + "' has one or more empty permission definitions in: " + emptyPermissionsIn.join(', '); }); return permissions; }; exports.processViewEntityPermissions = processViewEntityPermissions; var processActionPermissions = function (action, permissions) { util_1.passOrThrow(exports.isPermission(permissions) || exports.isPermissionsArray(permissions), function () { return "Invalid permission definition for action '" + action.name + "'"; }); // const permissionsArray = isArray(permissions) ? permissions : [permissions]; var permissionsArray = util_1.isArray(permissions) ? permissions : [permissions]; permissionsArray.map(function (permission) { util_1.passOrThrow(!permission.userAttributes.length && !permission.values.length && !permission.states.length, function () { return "Incompatible permission definition for action '" + action.name + "'"; }); exports.validateActionLookupPermission(permission, action); }); util_1.passOrThrow(!exports.hasEmptyPermissions(permissions), function () { return "Action '" + action.name + "' has one or more empty permission definitions"; }); return permissions; }; exports.processActionPermissions = processActionPermissions;