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

94.59% Statements 35/37
84.61% Branches 11/13
100% Functions 10/10
96.87% Lines 31/32

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 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 1181x 1x       1x                                             1x       142x                     6x       14x     14x       14x   14x   14x         1x 9x     9x   9x 9x 9x     9x 11x 14x 11x 11x       9x   9x         9x 36x 8x   13x         28x     9x                     9x          
import DefaultHandler, { order } from './default';
import { convertClientNamesToIds } from '../../utils';
import { Asset, Assets, CalculatedChanges } from '../../../types';
import DefaultAPIHandler from './default';
 
export const schema = {
  type: 'array',
  items: {
    type: 'object',
    properties: {
      client_id: { type: 'string' },
      audience: { type: 'string' },
      scope: {
        type: 'array',
        items: { type: 'string' },
        uniqueItems: true,
      },
    },
    required: ['client_id', 'scope', 'audience'],
  },
};
 
export type ClientGrant = {
  client_id: string;
  audience: string;
  scope: string[];
};
 
export default class ClientGrantsHandler extends DefaultHandler {
  existing: ClientGrant[] | null;
 
  constructor(config: DefaultAPIHandler) {
    super({
      ...config,
      type: 'clientGrants',
      id: 'id',
      //@ts-ignore because not sure why two-dimensional array passed in
      identifiers: ['id', ['client_id', 'audience']],
      stripUpdateFields: ['audience', 'client_id'],
    });
  }
 
  objString(item): string {
    return super.objString({ id: item.id, client_id: item.client_id, audience: item.audience });
  }
 
  async getType(): Promise<ClientGrant[]> {
    Iif (this.existing) {
      return this.existing;
    }
    this.existing = await this.client.clientGrants.getAll({ paginate: true, include_totals: true });
 
    // Always filter out the client we are using to access Auth0 Management API
    // As it could cause problems if the grants are deleted or updated etc
    const currentClient = this.config('AUTH0_CLIENT_ID');
 
    this.existing = this.existing.filter((grant) => grant.client_id !== currentClient);
 
    return this.existing;
  }
 
  // Run after clients are updated so we can convert client_id names to id's
  @order('60')
  async processChanges(assets: Assets): Promise<void> {
    const { clientGrants } = assets;
 
    // Do nothing if not set
    Iif (!clientGrants) return;
 
    const clients = await this.client.clients.getAll({ paginate: true, include_totals: true });
    const excludedClientsByNames = (assets.exclude && assets.exclude.clients) || [];
    const excludedClients = convertClientNamesToIds(excludedClientsByNames, clients);
 
    // Convert clients by name to the id
    const formatted = clientGrants.map((clientGrant) => {
      const grant = { ...clientGrant };
      const found = clients.find((c) => c.name === grant.client_id);
      if (found) grant.client_id = found.client_id;
      return grant;
    });
 
    // Always filter out the client we are using to access Auth0 Management API
    const currentClient = this.config('AUTH0_CLIENT_ID');
 
    const { del, update, create, conflicts } = await this.calcChanges({
      ...assets,
      clientGrants: formatted,
    });
 
    const filterGrants = (list: { client_id: string }[]) => {
      if (excludedClients.length) {
        return list.filter(
          (item) =>
            item.client_id !== currentClient &&
            ![...excludedClientsByNames, ...excludedClients].includes(item.client_id)
        );
      }
 
      return list.filter((item) => item.client_id !== currentClient);
    };
 
    const changes: CalculatedChanges = {
      //@ts-ignore because this expects `client_id` and that's not yet typed on Asset
      del: filterGrants(del),
      //@ts-ignore because this expects `client_id` and that's not yet typed on Asset
      update: filterGrants(update),
      //@ts-ignore because this expects `client_id` and that's not yet typed on Asset
      create: filterGrants(create),
      //@ts-ignore because this expects `client_id` and that's not yet typed on Asset
      conflicts: filterGrants(conflicts),
    };
 
    await super.processChanges(assets, {
      ...changes,
    });
  }
}