gypsum
Version:
Simple and easy lightweight typescript server side framework on Node.js.
209 lines • 9.97 kB
JavaScript
;
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