integreat
Version:
Node.js integration layer
96 lines • 4.67 kB
JavaScript
import { validateRoleOrIdent } from './authAction.js';
import getField from '../../utils/getField.js';
import { arrayIncludes } from '../../utils/array.js';
import { isTypedData, isNullOrUndefined, isRootIdent } from '../../utils/is.js';
const isStringOrArray = (value) => typeof value === 'string' || Array.isArray(value);
function getValueAndCompare(item, fieldPath, compareValue) {
const values = getField(item, fieldPath);
return isStringOrArray(values) && arrayIncludes(compareValue, values);
}
const isIdentFromFieldOrIdentOk = (item, field, present) => field && getValueAndCompare(item, field, present);
const isItemAuthorized = (item, access, ident) => (!access.identFromField && !access.roleFromField) ||
validateRoleOrIdent(access.role, ident?.roles) ||
validateRoleOrIdent(access.ident, ident?.id) ||
isIdentFromFieldOrIdentOk(item, access.identFromField, ident?.id) ||
isIdentFromFieldOrIdentOk(item, access.roleFromField, ident?.roles);
const authorizeItem = (schemas, actionType, allowRaw, ident) => (item) => {
if (!isTypedData(item)) {
return allowRaw ? undefined : 'RAW_DATA';
}
const schema = schemas.get(item.$type);
if (!schema) {
return 'NO_SCHEMA';
}
const access = schema.accessForAction(actionType);
if (isItemAuthorized(item, access, ident)) {
return undefined;
}
else {
return access.identFromField ? 'WRONG_IDENT' : 'MISSING_ROLE';
}
};
const generateWarning = (removedCount, isToService) => removedCount > 0
? `${removedCount} item${removedCount === 1 ? ' was' : 's were'} removed from ${isToService ? 'request' : 'response'} data due to lack of access`
: undefined;
const generateErrorAndReason = (reason, data, isToService, service) => reason === 'RAW_DATA'
? `Authentication was refused for raw ${isToService ? 'request' : 'response'} data${service ? ` ${isToService ? 'to' : 'from'} service '${service}'` : ''}`
: `Authentication was refused for type '${data.$type}'${service ? ` on service '${service}'` : ''}`;
function authorizeDataArrayAndWrapInResponse(data, authItemFn, isToService) {
const authed = data.filter((data) => authItemFn(data) === undefined);
const warning = generateWarning(data.length - authed.length, isToService);
return { data: authed, warning };
}
function authorizeDataItemAndWrapInResponse(data, authItemFn, isToService, service) {
if (!isNullOrUndefined(data)) {
const reason = authItemFn(data);
if (typeof reason === 'string') {
const error = generateErrorAndReason(reason, data, isToService, service);
return {
data: undefined,
status: 'noaccess',
error,
reason,
origin: 'auth:data',
};
}
}
return { data };
}
const authorizeDataAndWrapInResponse = (data, authItemFn, isToService, service) => Array.isArray(data)
? authorizeDataArrayAndWrapInResponse(data, authItemFn, isToService)
: authorizeDataItemAndWrapInResponse(data, authItemFn, isToService, service);
const isError = (status) => typeof status === 'string' && status !== 'ok';
const authorizeDataBase = (schemas, isToService) => function authorizeData(action, allowRaw = false) {
if (isRootIdent(action.meta?.ident)) {
return action;
}
const { type: actionType, payload: { targetService }, meta: { ident } = {}, } = action;
const { data, status: authedStatus, error, reason, warning, } = authorizeDataAndWrapInResponse(isToService ? action.payload.data : action.response?.data, authorizeItem(schemas, actionType, allowRaw, ident), isToService, targetService);
const status = isError(action.response?.status) || !authedStatus
? action.response?.status
: authedStatus;
const response = status !== undefined || warning
? {
...action.response,
...(!isToService && { data }),
...(!action.response?.error && error && { error }),
...(!action.response?.error && reason && { reason }),
...(warning && { warning }),
...(isError(status)
? { origin: action.response?.origin || 'auth:data' }
: {}),
status,
}
: undefined;
return {
...action,
payload: {
...action.payload,
...(isToService && { data }),
},
...(response && { response }),
};
};
export const fromService = (schemas) => authorizeDataBase(schemas, false);
export const toService = (schemas) => authorizeDataBase(schemas, true);
//# sourceMappingURL=authData.js.map