security-express
Version:
security-express
406 lines (405 loc) • 12.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function handleToken(res, secret, name, t, verify, buildErr) {
if (t.error) {
res.status(401).end(t.error);
return Promise.resolve({ error: t.error, end: true });
}
else {
return verify(t.token, secret)
.then(function (payload) {
res.locals[name] = payload;
return Promise.resolve({ payload: payload, token: t.token });
})
.catch(function (err) {
var _a = buildErr(err), status = _a.status, body = _a.body;
res.status(status).end(body);
return Promise.resolve({ token: t.token, error: t.error, end: true });
});
}
}
exports.handleToken = handleToken;
function fromCookies(req, name) {
if (!req.cookies) {
return { token: "", error: "Require cookies" };
}
else {
var token = req.cookies[name];
if (!token) {
return { token: "", error: "Require '" + name + "' in cookies" };
}
else {
return { token: token };
}
}
}
exports.fromCookies = fromCookies;
function fromAuthorization(req, prefix) {
var data = req.headers["authorization"];
if (data) {
if (!data.startsWith(prefix)) {
return { token: "", error: "Authorization must start with '" + prefix.trim() + "'" };
}
else {
var token = data.substring(prefix.length);
return { token: token };
}
}
else {
return { token: "", error: "Require 'Authorization' in header" };
}
}
exports.fromAuthorization = fromAuthorization;
var LocalsToken = (function () {
function LocalsToken(token) {
this.token = token ? token : "token";
this.getToken = this.getToken.bind(this);
}
LocalsToken.prototype.getToken = function (req, res) {
var payload = res.locals[this.token];
return Promise.resolve({ payload: payload });
};
return LocalsToken;
}());
exports.LocalsToken = LocalsToken;
var CookiesToken = (function () {
function CookiesToken(secret, verify, buildErr, payload, token) {
this.secret = secret;
this.verify = verify;
this.token = token ? token : "token";
this.payload = payload ? payload : "token";
this.buildError = buildErr ? buildErr : buildError;
this.getToken = this.getToken.bind(this);
}
CookiesToken.prototype.getToken = function (req, res) {
var t = fromCookies(req, this.token);
return handleToken(res, this.secret, this.payload, t, this.verify, this.buildError);
};
return CookiesToken;
}());
exports.CookiesToken = CookiesToken;
var AuthorizationToken = (function () {
function AuthorizationToken(secret, verify, buildErr, payload, prefix) {
this.secret = secret;
this.verify = verify;
this.prefix = prefix ? prefix : "Bearer ";
this.payload = payload ? payload : "token";
this.buildError = buildErr ? buildErr : buildError;
this.getToken = this.getToken.bind(this);
}
AuthorizationToken.prototype.getToken = function (req, res) {
var t = fromAuthorization(req, this.prefix);
return handleToken(res, this.secret, this.payload, t, this.verify, this.buildError);
};
return AuthorizationToken;
}());
exports.AuthorizationToken = AuthorizationToken;
var TokenService = (function () {
function TokenService(secret, verify, buildErr, payload, token, prefix) {
this.secret = secret;
this.verify = verify;
this.prefix = prefix ? prefix : "Bearer ";
this.token = token ? token : "token";
this.payload = payload ? payload : "token";
this.buildError = buildErr ? buildErr : buildError;
this.getToken = this.getToken.bind(this);
}
TokenService.prototype.getToken = function (req, res) {
var t = fromCookies(req, this.token);
if (t.error) {
t = fromAuthorization(req, this.prefix);
}
return handleToken(res, this.secret, this.payload, t, this.verify, this.buildError);
};
return TokenService;
}());
exports.TokenService = TokenService;
function useToken(secret, verify, buildErr, cookie, payload, token, prefix) {
if (cookie === true) {
return new CookiesToken(secret, verify, buildErr, payload, token).getToken;
}
else if (cookie === false) {
return new AuthorizationToken(secret, verify, buildErr, payload, prefix).getToken;
}
else {
return new TokenService(secret, verify, buildErr, payload, token, prefix).getToken;
}
}
exports.useToken = useToken;
exports.getToken = useToken;
var Handler = (function () {
function Handler(secret, verify, prefix, token, payload) {
this.secret = secret;
this.verify = verify;
this.prefix = prefix ? prefix : "Bearer ";
this.token = token ? token : "token";
this.payload = payload ? payload : "token";
this.handle = this.handle.bind(this);
}
Handler.prototype.handle = function () {
var _this = this;
return function (req, res, next) {
var t = fromCookies(req, _this.token);
if (t.error) {
t = fromAuthorization(req, _this.prefix);
}
if (t.error) {
next();
}
else {
_this.verify(t.token, _this.secret)
.then(function (payload) {
res.locals[_this.payload] = payload;
next();
})
.catch(function (err) {
next();
});
}
};
};
return Handler;
}());
exports.Handler = Handler;
exports.AuthorizationHandler = Handler;
var AuthorizationChecker = (function () {
function AuthorizationChecker(gt) {
this.getToken = gt;
this.check = this.check.bind(this);
this.require = this.require.bind(this);
}
AuthorizationChecker.prototype.require = function () {
var _this = this;
return function (req, res, next) {
_this.getToken(req, res).then(function (t) {
if (!t.end) {
next();
}
});
};
};
AuthorizationChecker.prototype.check = function () {
return this.require();
};
return AuthorizationChecker;
}());
exports.AuthorizationChecker = AuthorizationChecker;
function exist(obj, arr) {
if (Array.isArray(obj)) {
for (var _i = 0, obj_1 = obj; _i < obj_1.length; _i++) {
var o = obj_1[_i];
for (var _a = 0, arr_1 = arr; _a < arr_1.length; _a++) {
var v = arr_1[_a];
if (o == v) {
return true;
}
}
}
}
else {
for (var _b = 0, arr_2 = arr; _b < arr_2.length; _b++) {
var v = arr_2[_b];
if (obj == v) {
return true;
}
}
}
return false;
}
exports.exist = exist;
var Checker = (function () {
function Checker(gt, key) {
this.getToken = gt;
this.key = key ? key : "id";
this.check = this.check.bind(this);
}
Checker.prototype.check = function (v) {
var _this = this;
return function (req, res, next) {
_this.getToken(req, res).then(function (t) {
if (!t.end) {
if (t.payload) {
var obj = t.payload[_this.key];
if (!obj) {
res.status(403).end("Payload must contain " + _this.key);
}
else {
if (exist(obj, v)) {
next();
}
else {
res.status(403).end("invalid " + _this.key);
}
}
}
else {
res.status(403).end("Payload cannot be undefined");
}
}
});
};
};
return Checker;
}());
exports.Checker = Checker;
var Authorizer = (function () {
function Authorizer(gt, privilege, buildErr, exact, payloadId, userId, permissions) {
this.privilege = privilege;
this.getToken = gt;
this.buildError = buildErr ? buildErr : buildError;
this.payloadId = payloadId ? payloadId : "id";
this.userId = userId ? userId : "userId";
this.permissions = permissions ? permissions : "permissions";
this.exact = exact !== undefined ? exact : true;
this.authorize = this.authorize.bind(this);
}
Authorizer.prototype.authorize = function (privilege, action) {
var _this = this;
return function (req, res, next) {
_this.getToken(req, res).then(function (t) {
if (!t.end) {
var payload = t.payload;
if (payload === undefined) {
res.status(401).end("Payload cannot be undefined");
}
else {
var userId_1 = payload[_this.payloadId];
if (!userId_1) {
res.status(403).end("Payload must contain " + _this.payloadId);
}
else {
_this.privilege(userId_1, privilege)
.then(function (p) {
if (p === exports.none) {
res.status(403).end("no permission for " + userId_1);
}
else {
res.locals[_this.userId] = userId_1;
res.locals[_this.permissions] = p;
if (!action) {
next();
}
else {
if (_this.exact) {
var sum = action & p;
if (sum === action) {
return next();
}
else {
res.status(403).end("no permission");
}
}
else {
if (p >= action) {
return next();
}
else {
res.status(403).end("no permission");
}
}
}
}
})
.catch(function (err) {
var _a = _this.buildError(err), status = _a.status, body = _a.body;
res.status(status).end(body);
});
}
}
}
});
};
};
return Authorizer;
}());
exports.Authorizer = Authorizer;
exports.none = 0;
exports.read = 1;
exports.write = 2;
exports.approve = 4;
exports.all = 2147483647;
var PrivilegeLoader = (function () {
function PrivilegeLoader(sql, query) {
this.sql = sql;
this.query = query;
this.privilege = this.privilege.bind(this);
}
PrivilegeLoader.prototype.privilege = function (userId, privilegeId) {
return this.query(this.sql, [userId, privilegeId]).then(function (v) {
if (!v || v.length === 0) {
return exports.none;
}
var keys = Object.keys(v[0]);
if (keys.length === 0) {
return exports.all;
}
var k = keys[0];
var permissions = 0;
var ok = false;
for (var _i = 0, v_1 = v; _i < v_1.length; _i++) {
var p = v_1[_i];
var x = p[k];
if (typeof x === "number") {
permissions = permissions | x;
ok = true;
}
}
return ok ? permissions : exports.all;
});
};
return PrivilegeLoader;
}());
exports.PrivilegeLoader = PrivilegeLoader;
function buildError(err) {
return { status: 401, body: "Invalid token: " + toString(err) };
}
exports.buildError = buildError;
function toString(err) {
return typeof err === "string" ? err : JSON.stringify(err);
}
exports.toString = toString;
function get(app, path, authorize, handle, secure) {
if (secure) {
app.get(path, authorize, handle);
}
else {
app.get(path, handle);
}
}
exports.get = get;
function post(app, path, authorize, handle, secure) {
if (secure) {
app.post(path, authorize, handle);
}
else {
app.post(path, handle);
}
}
exports.post = post;
function put(app, path, authorize, handle, secure) {
if (secure) {
app.put(path, authorize, handle);
}
else {
app.put(path, handle);
}
}
exports.put = put;
function patch(app, path, authorize, handle, secure) {
if (secure) {
app.patch(path, authorize, handle);
}
else {
app.patch(path, handle);
}
}
exports.patch = patch;
function del(app, path, authorize, handle, secure) {
if (secure) {
app.delete(path, authorize, handle);
}
else {
app.delete(path, handle);
}
}
exports.del = del;