UNPKG

stackpress

Version:

Incept is a content management framework.

116 lines (115 loc) 3.35 kB
import jwt from 'jsonwebtoken'; import Exception from '../Exception'; import { matchAnyEvent, matchAnyRoute } from './helpers'; export default class SessionServer { static _access = {}; static _expires = 0; static _key = 'session'; static _seed = 'abc123'; static get access() { return this._access; } static get seed() { return this._seed; } static get key() { return this._key; } static set expires(value) { this._expires = value; } static configure(key, seed, access) { this._key = key; this._seed = seed; this._access = access; return this; } static authorize(req, res, permits = []) { const session = this.load(req); permits.unshift({ method: req.method.toUpperCase(), route: req.url.pathname }); if (!session.can(...permits)) { res.setError(Exception .for('Unauthorized') .withCode(401) .toResponse()); return false; } res.setResults(session.authorization); return true; } static create(data) { if (!this._expires) { return jwt.sign(data, this.seed); } return jwt.sign(data, this.seed, { expiresIn: this._expires }); } static token(req) { if (req.session.has(this.key)) { return req.session(this.key); } return null; } static load(token) { if (typeof token === 'string') { return new SessionServer(token); } return new SessionServer(this.token(token) || ''); } token; _data; get authorization() { return { id: 0, roles: ['GUEST'], ...(this.data || {}), token: this.token, permits: this.permits() }; } get data() { if (typeof this._data === 'undefined') { this._data = null; if (this.token.length) { try { const response = jwt.verify(this.token, SessionServer.seed); this._data = typeof response === 'string' ? JSON.parse(response) : response; } catch (e) { } } } return this._data; } get guest() { return this.data === null; } constructor(token) { this.token = token; } can(...permits) { if (permits.length === 0) { return true; } const permissions = this.permits(); const events = permissions.filter(permission => typeof permission === 'string'); const routes = permissions.filter(permission => typeof permission !== 'string'); return Array.isArray(permits) && permits.every(permit => typeof permit === 'string' ? matchAnyEvent(permit, events) : matchAnyRoute(permit, routes)); } permits() { const roles = this.data?.roles || ['GUEST']; return roles.map(role => SessionServer.access[role] || []).flat().filter((value, index, self) => self.indexOf(value) === index); } save(res) { res.session.set(SessionServer.key, this.token); return this; } } ;