UNPKG

gypsum

Version:

Simple and easy lightweight typescript server side framework on Node.js.

209 lines 9.97 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; Object.defineProperty(exports, "__esModule", { value: true }); const Validall = require("validall"); const MongoDB = require("mongodb"); const object_1 = require("tools-box/object"); const decorators_1 = require("../decorators"); const models_1 = require("../models"); const types_1 = require("../types"); const state_1 = require("../state"); const util_1 = require("../util"); let Authorization = class Authorization extends models_1.Model { _mGetUserRolesFromGroups(id) { return new Promise((resolve, reject) => { let groups = this.app.$getModel('groups'); groups.find({ users: { $in: [id] } }) .then(res => { let results = res.data; if (results && results.length) resolve(results.reduce((prev, current) => { return prev.push(...current.roles); }, [])); else resolve([]); }); }); } _mGetUserPermissionsFromRules(id, extraRules = []) { return new Promise((resolve, reject) => { let roles = this.app.$getModel('roles'); roles.find({ $or: [{ users: { $in: [id] } }, { name: { $in: extraRules } }] }) .then(res => { let results = res.data; if (results && results.length) { let permissions = []; results.forEach((result) => { permissions.push(...result.permissions); }, []); resolve(permissions); } else resolve([]); }); }); } _mFetchData(appName, modelName, options, ctx) { return new Promise((resolve, reject) => { if (!options) return reject({ message: 'invalid options', code: types_1.RESPONSE_CODES.BAD_REQUEST }); let model = state_1.State.getModel(`${appName}.${modelName}`); if (!model) return reject({ message: `model ${appName}.${modelName} not found`, code: types_1.RESPONSE_CODES.BAD_REQUEST }); model.find(options.fetch.query, options.fetch.options) .then((res) => { if (!res || !res.data) return reject({ message: 'document not found', code: types_1.RESPONSE_CODES.BAD_REQUEST }); let docs = res.data; for (let i = 0; i < docs.length; i++) { let matchParts = options.match.split('|'); let isAuth = false; for (let j = 0; j < matchParts.length; j++) { if (matchParts[j] && matchParts[j].trim()) { let currentPart = matchParts[j].trim(); let compareValue = object_1.getValue(docs[i], currentPart); if (compareValue instanceof MongoDB.ObjectID) compareValue = compareValue.toString(); if (ctx.user._id.toString() === compareValue) { isAuth = true; break; } } } if (!isAuth) return reject({ message: 'user not authorized', code: types_1.RESPONSE_CODES.UNAUTHORIZED }); } ctx.set('fetchedData', docs); resolve(); }) .catch((err) => reject(err)); }); } authorize(options, ctx) { let appName = ctx._appName.toLowerCase(); let modelName = ctx.model.name.toLowerCase(); let serviceName = ctx.service.__name.toLowerCase(); return new Promise((resolve, reject) => { this.$logger.info(`authorizing service:`); console.log(`${appName}${modelName}${serviceName}`); this.$logger.info(`options:`); console.log(options); this.$logger.debug('params:'); console.log(ctx.params); this.$logger.debug('query:'); console.log(ctx.query); this.$logger.debug('body:'); console.log(ctx.body); if (!ctx.user) return reject({ message: 'user not logged in', code: types_1.RESPONSE_CODES.UNAUTHORIZED }); if (Validall.Types.object(options) && options.match) { if (!options.fetch) { let matchValue = ''; if (options.match.charAt(0) === '$') matchValue = object_1.getValue(ctx, options.match.slice(1)); else matchValue = options.match; if (ctx.user._id.toString() !== matchValue) return reject({ message: 'user not authorized', code: types_1.RESPONSE_CODES.UNAUTHORIZED }); return resolve(); } else { let fetchObj = { query: {} }; if (typeof options.fetch === 'string') { if (options.fetch.charAt(0) === "$") fetchObj = object_1.getValue(ctx, options.fetch.slice(1)); else return reject({ message: 'invalid authorization options', code: types_1.RESPONSE_CODES.BAD_REQUEST }); } else { if (typeof options.fetch.query === 'string') { if (options.fetch.query.charAt(0) === '$') fetchObj.query = object_1.getValue(ctx, options.fetch.query.slice(1)); else return reject({ message: 'invalid authorization options', code: types_1.RESPONSE_CODES.BAD_REQUEST }); } else { for (let prop in options.fetch.query) if (typeof options.fetch.query[prop] === 'string' && options.fetch.query[prop].charAt(0) === '$') fetchObj.query[prop] = object_1.getValue(ctx, options.fetch.query[prop].slice(1)); } if (typeof options.fetch.options === 'string') { if (options.fetch.options.charAt(0) === '$') fetchObj.options = object_1.getValue(ctx, options.fetch.options.slice(1)); else return reject({ message: 'invalid authorization options', code: types_1.RESPONSE_CODES.BAD_REQUEST }); } } fetchObj.query = util_1.toObjectID(fetchObj.query); return this._mFetchData(appName, modelName, { fetch: fetchObj, match: options.match }, ctx) .then(() => resolve()) .catch(err => reject(err)); } } this.$logger.debug('getting user rules...'); this._mGetUserRolesFromGroups(ctx.user._id) .then(roles => this._mGetUserPermissionsFromRules(ctx.user._id, roles)) .then((permissions) => { if (permissions.length) { for (let i = 0; i < permissions.length; i++) { let parts = permissions[i].split('/'); if (parts[0] === '*' || parts[0] === appName && parts[1] === '*' || parts[1] === modelName && parts[2] === '*' || parts[2] === serviceName) { return resolve(); } } } reject({ message: 'user not authorized', code: types_1.RESPONSE_CODES.UNAUTHORIZED }); }) .catch(error => reject({ message: 'Error authorizing user', original: error, code: types_1.RESPONSE_CODES.UNKNOWN_ERROR })); }); } }; __decorate([ decorators_1.HOOK() ], Authorization.prototype, "authorize", null); Authorization = __decorate([ decorators_1.MODEL() ], Authorization); exports.Authorization = Authorization; //# sourceMappingURL=authorization.js.map