{"version":3,"file":"rbac.mjs","sources":["../../../../../../core/src/rbac.ts"],"sourcesContent":["export const WILDCARD_ACTION = '*';\n\nexport type RBACPolicyRole = {\n  role_id: string;\n  description: string;\n  permissions: {\n    resource_id: string;\n    actions: string[];\n  }[];\n};\n\nexport type RBACPolicyScope = {\n  scope: string;\n  description: string;\n  permissions: {\n    resource_id: string;\n    actions: string[];\n  }[];\n};\n\nexport type RBACPolicyResource = {\n  resource_id: string;\n  description: string;\n  actions: string[];\n};\n\nexport type RBACPolicyRaw = {\n  roles: RBACPolicyRole[];\n  resources: RBACPolicyResource[];\n  scopes: RBACPolicyScope[];\n};\n\n/**\n * RBACPolicy represents an instance of a parsed Stytch RBAC policy object\n * It contains methods for computing outcomes for various permissions questions\n */\nexport class RBACPolicy {\n  private rolesByID: Record<string, RBACPolicyRole>;\n\n  constructor(\n    public roles: RBACPolicyRole[],\n    public resources: RBACPolicyResource[],\n  ) {\n    this.rolesByID = {};\n    roles.forEach((role) => (this.rolesByID[role.role_id] = role));\n  }\n\n  static fromJSON(input: RBACPolicyRaw): RBACPolicy {\n    return new RBACPolicy(input.roles, input.resources);\n  }\n\n  /**\n   * Merges organization custom roles with this project policy.\n   * Custom roles are additive - they add additional roles on top of the base project policy.\n   * Resources remain from the project policy, roles are combined.\n   * @param customRoles Array of custom organization roles to add\n   * @returns A new RBACPolicy instance with merged roles\n   */\n  mergeWithCustomRoles(customRoles: RBACPolicyRole[]): RBACPolicy {\n    const mergedRoles = [...this.roles, ...customRoles];\n\n    // Resources come from the project policy - custom roles don't define new resources\n    return new RBACPolicy(mergedRoles, this.resources);\n  }\n\n  /**\n   * isAuthorized returns whether or not a user with a specific set of roles can perform a desired action\n   * @example\n   *  const canDoIt = policy.callerIsAuthorized(roles, 'files', 'create')\n   *  console.log(canDoIt) // true\n   */\n  callerIsAuthorized(memberRoles: string[], resourceId: string, action: string): boolean {\n    return !!memberRoles\n      .map((roleId) => this.rolesByID[roleId])\n      // Defense in depth: filter out null/undefined in case memberRoles contains a role that doesn't match the policy\n      // This may happen if the member is loaded _before_ a fresh RBAC policy is loaded\n      .filter((v) => v)\n      .flatMap((role) => role.permissions)\n      .filter((permission) => permission.resource_id === resourceId)\n      .find((permission) => permission.actions.includes(action) || permission.actions.includes(WILDCARD_ACTION));\n  }\n\n  /**\n   * allPermissions generates a map that allows quick lookup of all the permissions available to the user\n   * @example\n   *   const perms = policy.allPermissions(roles)\n   *   console.log(perms.files.create) // true\n   *   console.log(perms.files.delete) // false\n   */\n  allPermissionsForCaller(memberRoles: string[]): Record<string, Record<string, boolean>> {\n    const allPermsMap: Record<string, Record<string, boolean>> = Object.create(null);\n    this.resources.forEach((resource) => {\n      allPermsMap[resource.resource_id] = {};\n      resource.actions.forEach((action) => {\n        allPermsMap[resource.resource_id][action] = this.callerIsAuthorized(memberRoles, resource.resource_id, action);\n      });\n    });\n    return allPermsMap;\n  }\n}\n"],"names":["WILDCARD_ACTION","RBACPolicy","rolesByID","resources","roles","forEach","role","role_id","fromJSON","input","mergeWithCustomRoles","customRoles","mergedRoles","callerIsAuthorized","memberRoles","resourceId","action","map","roleId","filter","v","flatMap","permissions","permission","resource_id","find","actions","includes","allPermissionsForCaller","allPermsMap","Object","create","resource"],"mappings":"AAAO,MAAMA,kBAAkB;AAgC/B;;;AAGC,IACM,MAAMC,UAAAA,CAAAA;;;IACHC,SAAAA;AAER,IAAA,WAAA,CACE,KAA8B,EACvBC,SAA+B,CACtC;aAFOC,KAAAA,GAAAA,KAAAA;aACAD,SAAAA,GAAAA,SAAAA;QAEP,IAAI,CAACD,SAAS,GAAG,EAAC;QAClBE,KAAAA,CAAMC,OAAO,CAAC,CAACC,IAAAA,GAAU,IAAI,CAACJ,SAAS,CAACI,IAAAA,CAAKC,OAAO,CAAC,GAAGD,IAAAA,CAAAA;AAC1D,IAAA;IAEA,OAAOE,QAAAA,CAASC,KAAoB,EAAc;AAChD,QAAA,OAAO,IAAIR,UAAAA,CAAWQ,KAAAA,CAAML,KAAK,EAAEK,MAAMN,SAAS,CAAA;AACpD,IAAA;AAEA;;;;;;MAOAO,oBAAAA,CAAqBC,WAA6B,EAAc;AAC9D,QAAA,MAAMC,WAAAA,GAAc;AAAI,YAAA,GAAA,IAAI,CAACR,KAAK;AAAKO,YAAAA,GAAAA;AAAY,SAAA;;AAGnD,QAAA,OAAO,IAAIV,UAAAA,CAAWW,WAAAA,EAAa,IAAI,CAACT,SAAS,CAAA;AACnD,IAAA;AAEA;;;;;AAKC,MACDU,mBAAmBC,WAAqB,EAAEC,UAAkB,EAAEC,MAAc,EAAW;AACrF,QAAA,OAAO,CAAC,CAACF,WAAAA,CACNG,GAAG,CAAC,CAACC,MAAAA,GAAW,IAAI,CAAChB,SAAS,CAACgB,MAAAA,CAAO,CACvC;;AAECC,SAAAA,MAAM,CAAC,CAACC,CAAAA,GAAMA,CAAAA,CAAAA,CACdC,OAAO,CAAC,CAACf,IAAAA,GAASA,IAAAA,CAAKgB,WAAW,CAAA,CAClCH,MAAM,CAAC,CAACI,UAAAA,GAAeA,UAAAA,CAAWC,WAAW,KAAKT,UAAAA,CAAAA,CAClDU,IAAI,CAAC,CAACF,aAAeA,UAAAA,CAAWG,OAAO,CAACC,QAAQ,CAACX,MAAAA,CAAAA,IAAWO,UAAAA,CAAWG,OAAO,CAACC,QAAQ,CAAC3B,eAAAA,CAAAA,CAAAA;AAC7F,IAAA;AAEA;;;;;;MAOA4B,uBAAAA,CAAwBd,WAAqB,EAA2C;QACtF,MAAMe,WAAAA,GAAuDC,MAAAA,CAAOC,MAAM,CAAC,IAAA,CAAA;AAC3E,QAAA,IAAI,CAAC5B,SAAS,CAACE,OAAO,CAAC,CAAC2B,QAAAA,GAAAA;AACtBH,YAAAA,WAAW,CAACG,QAAAA,CAASR,WAAW,CAAC,GAAG,EAAC;AACrCQ,YAAAA,QAAAA,CAASN,OAAO,CAACrB,OAAO,CAAC,CAACW,MAAAA,GAAAA;AACxBa,gBAAAA,WAAW,CAACG,QAAAA,CAASR,WAAW,CAAC,CAACR,MAAAA,CAAO,GAAG,IAAI,CAACH,kBAAkB,CAACC,WAAAA,EAAakB,QAAAA,CAASR,WAAW,EAAER,MAAAA,CAAAA;AACzG,YAAA,CAAA,CAAA;AACF,QAAA,CAAA,CAAA;QACA,OAAOa,WAAAA;AACT,IAAA;AACF;;;;"}