All files / src/tools/auth0/handlers guardianPhoneFactorMessageTypes.ts

96.55% Statements 28/29
95.23% Branches 20/21
100% Functions 4/4
100% Lines 27/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 851x 1x     1x                           1x 3x   1x   2x               1x   1x     1x       137x               9x       1x     8x   8x 8x   3x   2x   1x     5x         2x     2x   1x 1x 1x 1x 1x      
import DefaultHandler from './default';
import constants from '../../constants';
import { Asset, Assets } from '../../../types';
 
export const schema = {
  type: 'object',
  properties: {
    message_types: {
      type: 'array',
      items: {
        type: 'string',
        enum: constants.GUARDIAN_PHONE_MESSAGE_TYPES,
      },
    },
  },
  additionalProperties: false,
};
 
const isFeatureUnavailableError = (err): boolean => {
  if (err.statusCode === 404) {
    // Older Management API version where the endpoint is not available.
    return true;
  }
  if (
    err.statusCode === 403 &&
    err.originalError &&
    err.originalError.response &&
    err.originalError.response.body &&
    err.originalError.response.body.errorCode === 'voice_mfa_not_allowed'
  ) {
    // Recent Management API version, but with feature explicitly disabled.
    return true;
  }
  return false;
};
 
export default class GuardianPhoneMessageTypesHandler extends DefaultHandler {
  existing: Asset[];
 
  constructor(options: DefaultHandler) {
    super({
      ...options,
      type: 'guardianPhoneFactorMessageTypes',
    });
  }
 
  async getType(): Promise<Asset[] | {}> {
    // in case client version does not support the operation
    if (
      !this.client.guardian ||
      typeof this.client.guardian.getPhoneFactorMessageTypes !== 'function'
    ) {
      return {};
    }
 
    Iif (this.existing) return this.existing;
 
    try {
      this.existing = await this.client.guardian.getPhoneFactorMessageTypes();
    } catch (e) {
      if (isFeatureUnavailableError(e)) {
        // Gracefully skip processing this configuration value.
        return {};
      }
      throw e;
    }
 
    return this.existing;
  }
 
  async processChanges(assets: Assets): Promise<void> {
    // No API to delete or create guardianPhoneFactorMessageTypes, we can only update.
    const { guardianPhoneFactorMessageTypes } = assets;
 
    // Do nothing if not set
    if (!guardianPhoneFactorMessageTypes || !guardianPhoneFactorMessageTypes.message_types) return;
 
    const params = {};
    const data = guardianPhoneFactorMessageTypes;
    await this.client.guardian.updatePhoneFactorMessageTypes(params, data);
    this.updated += 1;
    this.didUpdate(guardianPhoneFactorMessageTypes);
  }
}