UNPKG

@okta-dfuhriman/okta-auth-js

Version:
129 lines (110 loc) 4.68 kB
/*! * Copyright (c) 2021-Present, Okta, Inc. and/or its affiliates. All rights reserved. * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.") * * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and limitations under the License. */ /* eslint-disable max-len */ // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-nocheck import { OktaAuthIdxInterface } from '../../types'; // auth-js/types import { generateRemediationFunctions } from './remediationParser'; import generateIdxAction from './generateIdxAction'; import { jsonpath } from '../../../util/jsonpath'; import { AuthSdkError } from '../../../errors'; const SKIP_FIELDS = Object.fromEntries([ 'remediation', // remediations are put into proceed/neededToProceed 'context', // the API response of 'context' isn't externally useful. We ignore it and put all non-action (contextual) info into idxState.context ].map( (field) => [ field, !!'skip this field' ] )); export const parseNonRemediations = function parseNonRemediations( authClient: OktaAuthIdxInterface, idxResponse, toPersist = {} ) { const actions = {}; const context = {}; Object.keys(idxResponse) .filter( field => !SKIP_FIELDS[field]) .forEach( field => { const fieldIsObject = typeof idxResponse[field] === 'object' && !!idxResponse[field]; if ( !fieldIsObject ) { // simple fields are contextual info context[field] = idxResponse[field]; return; } if ( idxResponse[field].rel ) { // top level actions actions[idxResponse[field].name] = generateIdxAction(authClient, idxResponse[field], toPersist); return; } const { value: fieldValue, type, ...info} = idxResponse[field]; context[field] = { type, ...info}; // add the non-action parts as context if ( type !== 'object' ) { // only object values hold actions context[field].value = fieldValue; return; } // We are an object field containing an object value context[field].value = {}; Object.entries(fieldValue) .forEach( ([subField, value]) => { if (value.rel) { // is [field].value[subField] an action? // add any "action" value subfields to actions actions[`${field}-${subField.name || subField}`] = generateIdxAction(authClient, value, toPersist); } else { // add non-action value subfields to context context[field].value[subField] = value; } }); }); return { context, actions }; }; const expandRelatesTo = (idxResponse, value) => { Object.keys(value).forEach(k => { if (k === 'relatesTo') { const query = Array.isArray(value[k]) ? value[k][0] : value[k]; if (typeof query === 'string') { const result = jsonpath({ path: query, json: idxResponse })[0]; if (result) { value[k] = result; return; } else { throw new AuthSdkError(`Cannot resolve relatesTo: ${query}`); } } } if (Array.isArray(value[k])) { value[k].forEach(innerValue => expandRelatesTo(idxResponse, innerValue)); } }); }; const convertRemediationAction = (authClient: OktaAuthIdxInterface, remediation, toPersist) => { // Only remediation that has `rel` field (indicator for form submission) can have http action if (remediation.rel) { const remediationActions = generateRemediationFunctions( authClient, [remediation], toPersist ); const actionFn = remediationActions[remediation.name]; return { ...remediation, action: actionFn, }; } return remediation; }; export const parseIdxResponse = function parseIdxResponse( authClient: OktaAuthIdxInterface, idxResponse, toPersist = {} ): { remediations: IdxRemediation[]; context: IdxContext; actions: IdxActions; } { const remediationData = idxResponse.remediation?.value || []; remediationData.forEach( remediation => expandRelatesTo(idxResponse, remediation) ); const remediations = remediationData.map(remediation => convertRemediationAction( authClient, remediation, toPersist )); const { context, actions } = parseNonRemediations( authClient, idxResponse, toPersist ); return { remediations, context, actions, }; };