integreat
Version:
Node.js integration layer
115 lines • 4.55 kB
JavaScript
import pProgress from 'p-progress';
import { setErrorOnAction, setActionIds } from '../../utils/action.js';
import { createErrorResponse, setOrigin } from '../../utils/response.js';
import { isObject } from '../../utils/is.js';
import { completeIdent } from '../../utils/completeIdent.js';
const identityFromIntegreat = Symbol('identityFromIntegreat');
const setServiceIdAsSourceServiceOnAction = (action, serviceId) => ({
...action,
payload: {
...action.payload,
sourceService: serviceId,
},
});
const isIdent = (ident) => isObject(ident) &&
(typeof ident.id === 'string' ||
typeof ident.withToken === 'string' ||
(Array.isArray(ident.withToken) && typeof ident.withToken[0] === 'string'));
const isKnownIdent = (ident) => ident[identityFromIntegreat] === true;
function markIdentAsKnown(response) {
const ident = response.access?.ident;
if (isIdent(ident)) {
return {
...response,
access: {
...response.access,
ident: { ...ident, [identityFromIntegreat]: true },
},
};
}
else {
return response;
}
}
const removeKnownIdentMarker = ({ [identityFromIntegreat]: _, ...identWithoutMarker }) => identWithoutMarker;
async function authorizeIncoming(action, serviceId) {
if (typeof action.response?.status === 'string') {
return action;
}
const ident = action.meta?.ident;
if (!isIdent(ident)) {
return setErrorOnAction(action, 'Authentication was refused. No ident', `auth:service:${serviceId}`, 'noaccess');
}
else {
return {
...action,
meta: {
...action.meta,
ident: isKnownIdent(ident) ? removeKnownIdentMarker(ident) : undefined,
auth: undefined,
},
};
}
}
const dispatchWithProgress = (dispatch, setProgress, serviceId) => async function (action) {
const p = dispatch(action);
p.onProgress(setProgress);
const response = await p;
return setOrigin(response, `service:${serviceId}`);
};
async function runAuths(auths, authentication, action, dispatch) {
let response = undefined;
for (const auth of auths) {
response = await auth.validate(authentication, action, dispatch);
if (response.status !== 'noaccess' && response.access?.ident) {
return response;
}
}
return response || { status: 'noaccess', error: 'No authentication was run' };
}
async function getAuthsFromAction(service, action) {
if (!action) {
return undefined;
}
const endpoint = await service.endpointFromAction(action, true);
return endpoint?.incomingAuth;
}
async function runAuthsAndCompleteIdent(dispatch, authentication, shouldCompleteIdent, auths, action) {
const response = await runAuths(auths, authentication, action || null, dispatch);
if (shouldCompleteIdent) {
return await completeIdent(response.access?.ident, dispatch);
}
else {
return response;
}
}
export const authenticateCallback = (service, dispatch, shouldCompleteIdent, incomingAuth) => async function authenticateFromListen(authentication, action) {
const auths = (await getAuthsFromAction(service, action)) || incomingAuth;
if (auths) {
const response = await runAuthsAndCompleteIdent(dispatch, authentication, shouldCompleteIdent, auths, action);
return setOrigin(markIdentAsKnown(response), `auth:service:${service.id}`, true);
}
else {
return createErrorResponse(`Could not authenticate. Service '${service.id}' has no incoming authenticator`, `auth:service:${service.id}`, 'noaction');
}
};
export function dispatchIncoming(dispatch, middleware, serviceId) {
return (action) => pProgress(async (setProgress) => {
if (action) {
const authorizedAction = await authorizeIncoming(setServiceIdAsSourceServiceOnAction(setActionIds(action), serviceId), serviceId);
const response = await middleware(dispatchWithProgress(dispatch, setProgress, serviceId))(authorizedAction);
return (setOrigin(response, `middleware:service:${serviceId}`) || {
status: 'error',
origin: `service:${serviceId}`,
});
}
else {
return {
status: 'noaction',
error: 'No action was dispatched',
origin: `service:${serviceId}`,
};
}
});
}
//# sourceMappingURL=incoming.js.map