Added Permission Middleware, Renaming
This commit is contained in:
40
package-lock.json
generated
40
package-lock.json
generated
@@ -2539,6 +2539,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jsonpath-plus": {
|
||||||
|
"version": "0.18.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-0.18.1.tgz",
|
||||||
|
"integrity": "sha512-4yQiuV641HROc4z9YGvnsr8yAdmzbu8JjdAen8WfiXsXewKvTG4ie2bSygF2maek9PcbtROmS6aLQs31BD+oNQ=="
|
||||||
|
},
|
||||||
"jsprim": {
|
"jsprim": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||||
@@ -2620,6 +2625,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
|
||||||
},
|
},
|
||||||
|
"lodash.clonedeep": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||||
|
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
|
||||||
|
},
|
||||||
|
"lodash.flattendeep": {
|
||||||
|
"version": "4.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
|
||||||
|
"integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI="
|
||||||
|
},
|
||||||
"logform": {
|
"logform": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz",
|
||||||
@@ -2673,6 +2688,14 @@
|
|||||||
"integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=",
|
"integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"matcher": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==",
|
||||||
|
"requires": {
|
||||||
|
"escape-string-regexp": "^1.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"media-typer": {
|
"media-typer": {
|
||||||
"version": "0.3.0",
|
"version": "0.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||||
@@ -2923,6 +2946,11 @@
|
|||||||
"validate-npm-package-license": "^3.0.1"
|
"validate-npm-package-license": "^3.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"notation": {
|
||||||
|
"version": "1.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/notation/-/notation-1.3.6.tgz",
|
||||||
|
"integrity": "sha512-DIuJmrP/Gg1DcXKaApsqcjsJD6jEccqKSfmU3BUx/f1GHsMiTJh70cERwYc64tOmTRTARCeMwkqNNzjh3AHhiw=="
|
||||||
|
},
|
||||||
"npmlog": {
|
"npmlog": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
||||||
@@ -3598,6 +3626,18 @@
|
|||||||
"glob": "^7.1.3"
|
"glob": "^7.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"role-acl": {
|
||||||
|
"version": "4.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/role-acl/-/role-acl-4.5.4.tgz",
|
||||||
|
"integrity": "sha512-T7baCc5BCFzLaxUrtAEIDcfK8HM/WTt6l2SLiMts6zLADSp7wOrrU3op0HVKhwjKi01d0Q6T4NeZ0jdLii9WuQ==",
|
||||||
|
"requires": {
|
||||||
|
"jsonpath-plus": "^0.18.0",
|
||||||
|
"lodash.clonedeep": "^4.5.0",
|
||||||
|
"lodash.flattendeep": "^4.4.0",
|
||||||
|
"matcher": "^1.0.0",
|
||||||
|
"notation": "^1.3.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"run-parallel": {
|
"run-parallel": {
|
||||||
"version": "1.1.10",
|
"version": "1.1.10",
|
||||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz",
|
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"lint-fix": "eslint . --ext .ts --fix",
|
"lint-fix": "eslint . --ext .ts --fix",
|
||||||
"update-client-hash": "node -e \"require('fs').writeFileSync('public/misc/hash.txt', require('randomstring').generate())\"",
|
"update-client-hash": "node -e \"require('fs').writeFileSync('public/misc/hash.txt', require('randomstring').generate())\"",
|
||||||
"debug-client": "tsc-watch --project ./public/js-source",
|
"debug-client": "tsc-watch --project ./public/js-source",
|
||||||
"debug-server": "tsc-watch --onSuccess \"node --enable-source-maps --use-openssl-ca --unhandled-rejections=strict ./out/index\"",
|
"debug-server": "tsc-watch --project ./src --onSuccess \"node --enable-source-maps --use-openssl-ca --unhandled-rejections=strict ./out/index\"",
|
||||||
"debug": "concurrently npm:debug-*",
|
"debug": "concurrently npm:debug-*",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"production": "node --use-openssl-ca --unhandled-rejections=strict ./out/index",
|
"production": "node --use-openssl-ca --unhandled-rejections=strict ./out/index",
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
"proper-url-join": "^2.1.1",
|
"proper-url-join": "^2.1.1",
|
||||||
"pug": "^3.0.0",
|
"pug": "^3.0.0",
|
||||||
"redis": "^3.0.2",
|
"redis": "^3.0.2",
|
||||||
|
"role-acl": "^4.5.4",
|
||||||
"threads": "^1.6.3",
|
"threads": "^1.6.3",
|
||||||
"tiny-worker": "^2.3.0",
|
"tiny-worker": "^2.3.0",
|
||||||
"uuid": "^8.3.1",
|
"uuid": "^8.3.1",
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ module.exports = {
|
|||||||
"comma-dangle": ["error", "always-multiline"],
|
"comma-dangle": ["error", "always-multiline"],
|
||||||
"comma-style": "error",
|
"comma-style": "error",
|
||||||
"semi": "error",
|
"semi": "error",
|
||||||
|
"no-implicit-coercion": "error",
|
||||||
|
|
||||||
"no-restricted-imports": ["error",
|
"no-restricted-imports": ["error",
|
||||||
"assert", "buffer", "child_process", "cluster", "crypto", "dgram", "dns", "domain", "events", "freelist",
|
"assert", "buffer", "child_process", "cluster", "crypto", "dgram", "dns", "domain", "events", "freelist",
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ module.exports = {
|
|||||||
"comma-dangle": ["error", "always-multiline"],
|
"comma-dangle": ["error", "always-multiline"],
|
||||||
"comma-style": "error",
|
"comma-style": "error",
|
||||||
"semi": "error",
|
"semi": "error",
|
||||||
|
"no-implicit-coercion": "error",
|
||||||
|
|
||||||
"promise/always-return": "off",
|
"promise/always-return": "off",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
24
src/app.ts
24
src/app.ts
@@ -2,13 +2,10 @@ import * as createError from 'http-errors';
|
|||||||
import * as express from 'express';
|
import * as express from 'express';
|
||||||
import {NextFunction, Request, Response} from 'express';
|
import {NextFunction, Request, Response} from 'express';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as redisStore from 'connect-redis';
|
|
||||||
import * as session from 'express-session';
|
|
||||||
import * as sassMiddleware from 'node-sass-middleware';
|
import * as sassMiddleware from 'node-sass-middleware';
|
||||||
import * as compression from 'compression';
|
import * as compression from 'compression';
|
||||||
import indexRouter from './routes';
|
import indexRouter from './routes';
|
||||||
import {HttpLogger, Redis, Config, setupAuthProxy, getReloadRouter, polyfillRoute} from './utils';
|
import {HttpLogger, Config, AuthProxy, AutoReloader, Polyfill, Session} from './utils';
|
||||||
import {Store} from 'express-session';
|
|
||||||
|
|
||||||
export const app = express();
|
export const app = express();
|
||||||
|
|
||||||
@@ -31,26 +28,15 @@ app.use(express.urlencoded({extended: false}));
|
|||||||
app.use(compression());
|
app.use(compression());
|
||||||
|
|
||||||
// auth proxy middleware
|
// auth proxy middleware
|
||||||
router.use(setupAuthProxy);
|
router.use(AuthProxy.router);
|
||||||
// auto reloader (when running in debug mode)
|
// auto reloader (when running in debug mode)
|
||||||
router.use(getReloadRouter());
|
router.use(AutoReloader.router);
|
||||||
|
|
||||||
// session
|
// session
|
||||||
let sessionStore: Store|undefined = undefined;
|
router.use(Session.getRouter());
|
||||||
if (Redis.client) {
|
|
||||||
const RedisStore = redisStore(session);
|
|
||||||
sessionStore = new RedisStore({client: Redis.client});
|
|
||||||
}
|
|
||||||
router.use(session({
|
|
||||||
store: sessionStore,
|
|
||||||
secret: Config.SESSION_SECRET,
|
|
||||||
resave: false,
|
|
||||||
saveUninitialized: true,
|
|
||||||
cookie: {secure: false},
|
|
||||||
}));
|
|
||||||
|
|
||||||
// static config
|
// static config
|
||||||
router.use("/js/polyfill.js", polyfillRoute);
|
router.use("/js/polyfill.js", Polyfill.router);
|
||||||
router.use(sassMiddleware({
|
router.use(sassMiddleware({
|
||||||
src: path.join(__dirname, '../public'),
|
src: path.join(__dirname, '../public'),
|
||||||
dest: path.join(__dirname, '../public'),
|
dest: path.join(__dirname, '../public'),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {Resolvable} from './helpers/resolvable';
|
|||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
import {urlJoin} from './helpers/urlJoin';
|
import {urlJoin} from './helpers/urlJoin';
|
||||||
|
|
||||||
export const setupAuthProxy: RequestHandler = (req: Request, res, next) => {
|
const router: RequestHandler = (req: Request, res, next) => {
|
||||||
const resolvable = new Resolvable(async () => {
|
const resolvable = new Resolvable(async () => {
|
||||||
if (!Config.USERINFO_HEADER) {
|
if (!Config.USERINFO_HEADER) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -34,3 +34,7 @@ export const setupAuthProxy: RequestHandler = (req: Request, res, next) => {
|
|||||||
};
|
};
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const AuthProxy = {
|
||||||
|
router,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
import {Router} from 'express';
|
import {Router} from 'express';
|
||||||
import {Config} from './config';
|
import {Config, Logger} from '.';
|
||||||
import {Logger} from './logging';
|
|
||||||
import {urlJoin} from './helpers/urlJoin';
|
import {urlJoin} from './helpers/urlJoin';
|
||||||
import {v4} from 'uuid';
|
import {v4} from 'uuid';
|
||||||
import Timeout = NodeJS.Timeout;
|
import Timeout = NodeJS.Timeout;
|
||||||
|
|
||||||
export function getReloadRouter(): Router {
|
const router = Router();
|
||||||
const reloadRouter = Router();
|
|
||||||
if (!Config.isProduction) {
|
if (!Config.isProduction) {
|
||||||
let uuid = v4();
|
let uuid = v4();
|
||||||
let updateTimeout: Timeout|undefined = undefined;
|
let updateTimeout: Timeout|undefined = undefined;
|
||||||
import("node-watch").then((watch) => {
|
import("node-watch").then((watch) => {
|
||||||
watch.default('public', {recursive: true}, (evt, name) => {
|
watch.default('public', {recursive: true}, () => {
|
||||||
if (updateTimeout !== undefined) clearTimeout(updateTimeout);
|
if (updateTimeout !== undefined) clearTimeout(updateTimeout);
|
||||||
updateTimeout = setTimeout(() => {
|
updateTimeout = setTimeout(() => {
|
||||||
uuid = v4();
|
uuid = v4();
|
||||||
@@ -19,7 +17,7 @@ export function getReloadRouter(): Router {
|
|||||||
});
|
});
|
||||||
}).catch((err) => { Logger.error(err); });
|
}).catch((err) => { Logger.error(err); });
|
||||||
|
|
||||||
reloadRouter.get("/auto-reload/client.js", (req, res) => {
|
router.get("/auto-reload/client.js", (req, res) => {
|
||||||
Logger.debug(req.url, req.originalUrl, req.baseUrl);
|
Logger.debug(req.url, req.originalUrl, req.baseUrl);
|
||||||
res.setHeader('Content-Type', "application/javascript");
|
res.setHeader('Content-Type', "application/javascript");
|
||||||
// language=JavaScript
|
// language=JavaScript
|
||||||
@@ -54,11 +52,12 @@ export function getReloadRouter(): Router {
|
|||||||
`.replace(/\t/g, ""));
|
`.replace(/\t/g, ""));
|
||||||
});
|
});
|
||||||
|
|
||||||
reloadRouter.get("/auto-reload", (req, res) => {
|
router.get("/auto-reload", (req, res) => {
|
||||||
req.noLogging = true;
|
req.noLogging = true;
|
||||||
res.json({uuid});
|
res.json({uuid});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return reloadRouter;
|
export const AutoReloader = {
|
||||||
}
|
router,
|
||||||
|
};
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ const envs = {
|
|||||||
// external base url
|
// external base url
|
||||||
EXTERNAL_BASE_URL: env.get('EXTERNAL_BASE_URL').asString(),
|
EXTERNAL_BASE_URL: env.get('EXTERNAL_BASE_URL').asString(),
|
||||||
|
|
||||||
// url of redis session store
|
// url of redis session store (required in production using InMemory)
|
||||||
REDIS_URL: env.get('REDIS_URL').required(isProduction).asString() || undefined,
|
REDIS_URL: env.get('REDIS_URL').asString() || undefined,
|
||||||
// cookie secret for the session id
|
// cookie secret for the session id (required in production using Session)
|
||||||
SESSION_SECRET: env.get('REDIS_URL').required(isProduction).default('keyboard cat').asString(),
|
SESSION_SECRET: env.get('SESSION_SECRET').asString() || undefined,
|
||||||
|
|
||||||
// header where user info token is stored to request auth proxy
|
// header where user info token is stored to request auth proxy
|
||||||
USERINFO_HEADER: env.get('USERINFO_HEADER').asString() || undefined,
|
USERINFO_HEADER: env.get('USERINFO_HEADER').asString() || undefined,
|
||||||
@@ -29,14 +29,17 @@ const envs = {
|
|||||||
AUTH_PROXY_USERINFO_URL: env.get('AUTH_PROXY_USERINFO_URL').asString() || undefined,
|
AUTH_PROXY_USERINFO_URL: env.get('AUTH_PROXY_USERINFO_URL').asString() || undefined,
|
||||||
// override base url to init a logout
|
// override base url to init a logout
|
||||||
AUTH_PROXY_INIT_LOGOUT_URL: env.get('AUTH_PROXY_INIT_LOGOUT_URL').asString() || undefined,
|
AUTH_PROXY_INIT_LOGOUT_URL: env.get('AUTH_PROXY_INIT_LOGOUT_URL').asString() || undefined,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function requireEnv(name: string, onlyInProduction = false): void {
|
||||||
|
env.get(name).required(!onlyInProduction || isProduction);
|
||||||
|
}
|
||||||
|
|
||||||
export const Config = {
|
export const Config = {
|
||||||
...envs,
|
...envs,
|
||||||
isProduction,
|
|
||||||
EXTERNAL_BASE_URL:
|
EXTERNAL_BASE_URL:
|
||||||
envs.EXTERNAL_BASE_URL ||
|
envs.EXTERNAL_BASE_URL ||
|
||||||
urlJoin(`http://${envs.HOSTNAME}${envs.PORT !== 80 ? `:${envs.PORT}` : ""}`, envs.BASE_PATH),
|
urlJoin(`http://${envs.HOSTNAME}${envs.PORT !== 80 ? `:${envs.PORT}` : ""}`, envs.BASE_PATH),
|
||||||
}
|
isProduction,
|
||||||
|
requireEnv,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
export {Config} from './config';
|
export {Config} from './config';
|
||||||
export {Redis} from './redis';
|
export {Redis} from './redis';
|
||||||
export {Logger, HttpLogger} from './logging';
|
export {Logger, HttpLogger} from './logging';
|
||||||
export {setupAuthProxy} from './auth-proxy';
|
export {AuthProxy} from './auth-proxy';
|
||||||
export {Resolvable, WaitForSync} from './helpers/resolvable';
|
export {Resolvable, WaitForSync} from './helpers/resolvable';
|
||||||
export {getReloadRouter} from './auto-reload';
|
export {AutoReloader} from './auto-reload';
|
||||||
export {polyfillRoute} from './polyfill';
|
export {Polyfill} from './polyfill';
|
||||||
|
export {Session} from './session';
|
||||||
|
export {Permissions} from './permissions';
|
||||||
|
|||||||
85
src/utils/permissions.ts
Normal file
85
src/utils/permissions.ts
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import {AccessControl, AccessControlError, IQueryInfo, Permission, Query} from 'role-acl';
|
||||||
|
import {Request, RequestHandler} from 'express';
|
||||||
|
|
||||||
|
// see https://www.npmjs.com/package/role-acl
|
||||||
|
class PermissionManager extends AccessControl {
|
||||||
|
public can(roleOrRequest: Request|string|string[]|IQueryInfo): PermQuery {
|
||||||
|
return new PermQuery(this.getGrants(), roleOrRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getRouter(resource: string, opts: Partial<RermRouterOpts>): RequestHandler {
|
||||||
|
return async (req: Request, res, next) => {
|
||||||
|
let query = this.can(req);
|
||||||
|
if (opts.context)
|
||||||
|
query = query.context(opts.context);
|
||||||
|
if (opts.action)
|
||||||
|
query = query.execute(opts.action);
|
||||||
|
if (opts.skipConditions)
|
||||||
|
query = query.skipConditions(opts.skipConditions);
|
||||||
|
const permission = await query.on(resource);
|
||||||
|
if (permission.granted) {
|
||||||
|
req.permissionDetails = permission;
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
res.sendStatus(403);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RermRouterOpts = {
|
||||||
|
context: unknown,
|
||||||
|
action: string,
|
||||||
|
skipConditions: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PermQuery extends Query {
|
||||||
|
protected resolveRequest: Request|undefined;
|
||||||
|
|
||||||
|
constructor(grants: unknown, roleOrRequest: Request|string|string[]|IQueryInfo) {
|
||||||
|
function isRequest(obj: unknown): obj is Request {
|
||||||
|
// eslint-disable-next-line no-prototype-builtins
|
||||||
|
return typeof obj === 'object' && obj && obj.hasOwnProperty('path') || false;
|
||||||
|
}
|
||||||
|
if (isRequest(roleOrRequest)) {
|
||||||
|
super(grants, []);
|
||||||
|
this.resolveRequest = roleOrRequest;
|
||||||
|
} else {
|
||||||
|
super(grants, roleOrRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async on(resource: string, skipConditions?: boolean): Promise<Permission> {
|
||||||
|
if (this.resolveRequest) {
|
||||||
|
const userInfo = await this.resolveRequest.getUserInfo();
|
||||||
|
this.role(userInfo?.groups ?? []);
|
||||||
|
}
|
||||||
|
return super.on(resource, skipConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public context(context: unknown): PermQuery {
|
||||||
|
super.context(context);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public skipConditions(value: boolean): PermQuery {
|
||||||
|
super.skipConditions(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public with(context: unknown): PermQuery {
|
||||||
|
super.with(context);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public execute(action: string): PermQuery {
|
||||||
|
super.execute(action);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public sync(): PermQuery {
|
||||||
|
throw new AccessControlError("Sync method is not allowed on PermissionManager!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Permissions = new PermissionManager();
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
import {RequestHandler} from 'express';
|
import {RequestHandler} from 'express';
|
||||||
import * as polyfillLibrary from 'polyfill-library';
|
import * as polyfillLibrary from 'polyfill-library';
|
||||||
import {Config} from './config';
|
import {Config, Logger} from '.';
|
||||||
import {PolyfillFeatureList} from 'polyfill-library';
|
import {PolyfillFeatureList} from 'polyfill-library';
|
||||||
import {Logger} from './logging';
|
|
||||||
import {WaitForSync} from './helpers/resolvable';
|
import {WaitForSync} from './helpers/resolvable';
|
||||||
import {spawn, Thread, Worker} from 'threads';
|
import {spawn, Thread, Worker} from 'threads';
|
||||||
import {WorkerFunction} from 'threads/dist/types/worker';
|
import {WorkerFunction} from 'threads/dist/types/worker';
|
||||||
@@ -23,7 +22,7 @@ const features = new WaitForSync<PolyfillFeatureList>();
|
|||||||
.catch(err => features.setError(err));
|
.catch(err => features.setError(err));
|
||||||
|
|
||||||
|
|
||||||
export const polyfillRoute: RequestHandler = async (req, res) => {
|
const router: RequestHandler = async (req, res) => {
|
||||||
const polyfillBundle = await polyfillLibrary.getPolyfillString({
|
const polyfillBundle = await polyfillLibrary.getPolyfillString({
|
||||||
uaString: req.header("user-agent"),
|
uaString: req.header("user-agent"),
|
||||||
features: await features.resolve(),
|
features: await features.resolve(),
|
||||||
@@ -34,3 +33,7 @@ export const polyfillRoute: RequestHandler = async (req, res) => {
|
|||||||
res.setHeader('Content-Type', 'text/javascript');
|
res.setHeader('Content-Type', 'text/javascript');
|
||||||
res.send(polyfillBundle);
|
res.send(polyfillBundle);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const Polyfill = {
|
||||||
|
router: router,
|
||||||
|
};
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import * as redis from 'redis';
|
|||||||
import {Config} from '.';
|
import {Config} from '.';
|
||||||
import {promisify} from 'util';
|
import {promisify} from 'util';
|
||||||
|
|
||||||
|
Config.requireEnv('REDIS_URL', true);
|
||||||
|
|
||||||
const redisClient = Config.REDIS_URL && redis.createClient({url: Config.REDIS_URL});
|
const redisClient = Config.REDIS_URL && redis.createClient({url: Config.REDIS_URL});
|
||||||
const inMemory: {[key: string]: string} = {};
|
const inMemory: {[key: string]: string} = {};
|
||||||
|
|
||||||
|
|||||||
28
src/utils/session.ts
Normal file
28
src/utils/session.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import {Store} from 'express-session';
|
||||||
|
import {Redis, Config} from '.';
|
||||||
|
import * as redisStore from "connect-redis";
|
||||||
|
import * as session from 'express-session';
|
||||||
|
import {RequestHandler} from 'express';
|
||||||
|
|
||||||
|
Config.requireEnv('SESSION_SECRET', true);
|
||||||
|
|
||||||
|
let sessionStore: Store|undefined = undefined;
|
||||||
|
|
||||||
|
function getRouter(options?: Partial<session.SessionOptions>): RequestHandler {
|
||||||
|
if (Redis.client && sessionStore !== undefined) {
|
||||||
|
const RedisStore = redisStore(session);
|
||||||
|
sessionStore = new RedisStore({client: Redis.client});
|
||||||
|
}
|
||||||
|
return session({
|
||||||
|
store: sessionStore,
|
||||||
|
secret: Config.SESSION_SECRET || 'keyboard cat',
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: true,
|
||||||
|
cookie: {secure: false},
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Session = {
|
||||||
|
getRouter,
|
||||||
|
};
|
||||||
5
src/utils/types/permissions.d.ts
vendored
Normal file
5
src/utils/types/permissions.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
declare namespace Express {
|
||||||
|
interface Request {
|
||||||
|
permissionDetails?: import('role-acl').Permission;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,16 +3,16 @@
|
|||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"outDir": "out",
|
"outDir": "./out",
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"noImplicitReturns": true,
|
"noImplicitReturns": true,
|
||||||
"strict": true
|
"strict": true
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts"
|
"./src/**/*.ts"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"./node_modules",
|
||||||
"public"
|
"./public"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user