stackpress
Version:
Incept is a content management framework.
132 lines (131 loc) • 4.94 kB
JavaScript
import { authorize, unauthorized, validData } from './helpers.js';
export default function plugin(ctx) {
if (!ctx.config.get('api'))
return;
ctx.on('listen', (_req, _res, ctx) => {
const { webhooks = [] } = ctx.config('api') || {};
for (const webhook of webhooks) {
ctx.on(webhook.event, async (req, res) => {
if (res.code !== 200)
return;
const data = webhook.data || {};
const params = req.data();
const results = res.toStatusResponse().results;
if (!validData(webhook.validity, results))
return;
await fetch(webhook.uri, {
method: webhook.method,
body: JSON.stringify({ data, params, results }),
});
}, -200);
}
});
ctx.on('route', (_req, _res, ctx) => {
const { endpoints = [] } = ctx.config('api') || {};
if (!Array.isArray(endpoints) || endpoints.length === 0)
return;
ctx.import.all('/auth/oauth/token', () => import('./pages/token.js'));
ctx.import.all('/auth/oauth', () => import('./pages/oauth.js'));
ctx.view.all('/auth/oauth', 'stackpress/esm/api/views/oauth', -100);
for (const endpoint of endpoints) {
cors(endpoint, ctx);
if (endpoint.type === 'session') {
session(endpoint, ctx);
}
else if (endpoint.type === 'app') {
app(endpoint, ctx);
}
else if (endpoint.type === 'public') {
open(endpoint, ctx);
}
}
});
}
;
export function cors(endpoint, ctx) {
let origin = endpoint.cors === true ? '*' : endpoint.cors;
if (typeof origin === 'string') {
origin = [origin];
}
if (!Array.isArray(origin))
return;
const cors = function CrossOrigin(req, res) {
if (origin.includes('*')) {
res.headers.set('Access-Control-Allow-Origin', '*');
}
else if (origin.includes(req.url.origin)) {
res.headers.set('Access-Control-Allow-Origin', req.url.origin);
}
else {
return;
}
const method = endpoint.method !== 'ALL' ? endpoint.method : '*';
res.headers.set('Access-Control-Request-Method', method);
res.headers.set('Access-Control-Allow-Methods', 'OPTIONS, GET');
res.headers.set('Access-Control-Allow-Headers', '*');
};
const preflight = function PreFlight(req, res) {
cors(req, res);
res.code = 200;
};
ctx.route('OPTIONS', endpoint.route, preflight, 1000);
ctx.route(endpoint.method, endpoint.route, cors, 1000);
}
export function session(endpoint, ctx) {
ctx.route(endpoint.method, endpoint.route, async function SessionAPI(req, res, ctx) {
const authorization = authorize(req, res);
if (!authorization) {
return;
}
const { id, secret } = authorization;
const response = await ctx.resolve('session-detail', { id });
if (!response || !response.results) {
return unauthorized(res);
}
const session = response.results;
if (req.method.toUpperCase() !== 'GET'
&& secret !== session.secret) {
return unauthorized(res);
}
const permits = endpoint.scopes || [];
if (!session.scopes.some(scope => permits.includes(scope))) {
return unauthorized(res);
}
req.data.set(endpoint.data || {});
req.data.set('profileId', session.profileId);
await ctx.emit(endpoint.event, req, res);
}, endpoint.priority || 0);
}
;
export function app(endpoint, ctx) {
ctx.route(endpoint.method, endpoint.route, async function AppAPI(req, res, ctx) {
const authorization = authorize(req, res);
if (!authorization) {
return;
}
const { id, secret } = authorization;
const response = await ctx.resolve('application-detail', { id });
if (!response || !response.results) {
return unauthorized(res);
}
const application = response.results;
if (req.method.toUpperCase() !== 'GET'
&& secret !== application.secret) {
return unauthorized(res);
}
const permits = endpoint.scopes || [];
if (!application.scopes.some(scope => permits.includes(scope))) {
return unauthorized(res);
}
req.data.set(endpoint.data || {});
await ctx.emit(endpoint.event, req, res);
}, endpoint.priority || 0);
}
;
export function open(endpoint, ctx) {
ctx.route(endpoint.method, endpoint.route, async function PublicAPI(req, res, ctx) {
req.data.set(endpoint.data || {});
await ctx.emit(endpoint.event, req, res);
}, endpoint.priority || 0);
}
;