All files / lib/utils hasRestrictingFields.ts

100% Statements 23/23
100% Branches 18/18
100% Functions 4/4
100% Lines 21/21

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  1x   1x     103x 47x 47x 73x 47x     1x   216x 152x         64x   69x       64x     216x 34x     182x   176x         116x   60x       6x     1x
import { AnyAbility, Subject } from "@casl/ability";
import { permittedFieldsOf, PermittedFieldsOptions } from "@casl/ability/extra";
import { HasRestrictingFieldsOptions } from "../types";
import getMinimalFields from "./getMinimalFields";
 
function areSameArray<T>(arr1: T[], arr2: T[]): boolean {
  if (arr1.length != arr2.length) { return false; }
  const arr1test = arr1.slice().sort();
  const arr2test = arr2.slice().sort();
  const result = !arr1test.some((val, idx) => val !== arr2test[idx]);
  return result;
}
 
const hasRestrictingFields = (ability: AnyAbility, action: string, subject: Subject, options?: HasRestrictingFieldsOptions): boolean|string[] => {
  let fields: string[];
  if (typeof subject !== "string") {
    fields = getMinimalFields(ability, action, subject as Record<string, unknown>, {
      availableFields: options.availableFields,
      checkCan: false
    });
  } else {
    const permittedFieldsOfOptions: PermittedFieldsOptions<AnyAbility> = {
      fieldsFrom: (rule) => {
        return rule.fields || options.availableFields || [];
      }
    };
 
    fields = permittedFieldsOf(ability, action, subject, permittedFieldsOfOptions);
  }
 
  if (fields.length === 0 && !options.availableFields) {
    return false;
  }
 
  if (fields.length > 0) {
    // check if fields is restricting at all or just complete array
    if (
      options.availableFields === fields ||
      (options.availableFields && areSameArray(fields, options.availableFields))
    ) {
      // arrays are the same -> no restrictions
      return false;
    } else {
      return fields;
    }
  }
 
  return true;
};
 
export default hasRestrictingFields;