@spotify/backstage-plugin-rbac 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/alpha/package.json +2 -2
  3. package/dist/alpha/apis.esm.js +2 -0
  4. package/dist/alpha/pages.esm.js +2 -0
  5. package/dist/alpha/plugin.esm.js +2 -0
  6. package/dist/alpha.esm.js +1 -1
  7. package/dist/api.esm.js +2 -0
  8. package/dist/components/Auth/Authorized.esm.js +2 -0
  9. package/dist/components/ConfirmationDialog/ConfirmationDialog.esm.js +2 -0
  10. package/dist/components/DecisionDialog/ConditionalDecisionForm/AddConditionSelector.esm.js +2 -0
  11. package/dist/components/DecisionDialog/ConditionalDecisionForm/ConditionCard.esm.js +2 -0
  12. package/dist/components/DecisionDialog/ConditionalDecisionForm/ConditionTree.esm.js +2 -0
  13. package/dist/components/DecisionDialog/ConditionalDecisionForm/ConditionTypeSelector.esm.js +2 -0
  14. package/dist/components/DecisionDialog/ConditionalDecisionForm/ConditionalDecisionForm.esm.js +2 -0
  15. package/dist/components/DecisionDialog/ConditionalDecisionForm/CriteriaSummary/ConditionLevelSummary.esm.js +2 -0
  16. package/dist/components/DecisionDialog/ConditionalDecisionForm/CriteriaSummary/ConditionSummary.esm.js +2 -0
  17. package/dist/components/DecisionDialog/ConditionalDecisionForm/CriteriaSummary/ConditionalDecisionBox.esm.js +2 -0
  18. package/dist/components/DecisionDialog/ConditionalDecisionForm/CriteriaSummary/CriteriaSummary.esm.js +2 -0
  19. package/dist/components/DecisionDialog/ConditionalDecisionForm/CriteriaSummary/Indent.esm.js +2 -0
  20. package/dist/components/DecisionDialog/ConditionalDecisionForm/CriteriaSummary/MonospaceText.esm.js +2 -0
  21. package/dist/components/DecisionDialog/ConditionalDecisionForm/utils.esm.js +2 -0
  22. package/dist/components/DecisionDialog/DecisionDialog.esm.js +2 -0
  23. package/dist/components/DecisionDialog/MatchByActions.esm.js +2 -0
  24. package/dist/components/DecisionDialog/MatchByName.esm.js +2 -0
  25. package/dist/components/DecisionDialog/MatchByResourceType.esm.js +2 -0
  26. package/dist/components/DecisionDialog/ParamsForm/ParamsForm.esm.js +2 -0
  27. package/dist/components/DecisionDialog/ParamsForm/ParamsFormArrayInput.esm.js +2 -0
  28. package/dist/components/DecisionDialog/ParamsForm/ParamsFormBooleanInput.esm.js +2 -0
  29. package/dist/components/DecisionDialog/ParamsForm/ParamsFormInput.esm.js +2 -0
  30. package/dist/components/DecisionDialog/ParamsForm/ParamsFormInputRouter.esm.js +2 -0
  31. package/dist/components/DecisionDialog/ParamsForm/ParamsFormJSONEditor.esm.js +2 -0
  32. package/dist/components/DecisionDialog/ParamsForm/ParamsFormStandard.esm.js +2 -0
  33. package/dist/components/DecisionDialog/ToggleButton.esm.js +2 -0
  34. package/dist/components/DecisionDialog/ToggleButtonGroup.esm.js +2 -0
  35. package/dist/components/DecisionDialog/VerticalSelection.esm.js +2 -0
  36. package/dist/components/DecisionDialog/computeMatchResult.esm.js +2 -0
  37. package/dist/components/DecisionDialog/conditionConstants.esm.js +2 -0
  38. package/dist/components/DecisionDialog/decisionDataMappers.esm.js +2 -0
  39. package/dist/components/DecisionDialog/utils.esm.js +2 -0
  40. package/dist/components/Diffing/DiffBadge.esm.js +2 -0
  41. package/dist/components/Diffing/DiffSummary.esm.js +2 -0
  42. package/dist/components/Diffing/getPolicyDiff/getMembersDiff.esm.js +2 -0
  43. package/dist/components/Diffing/getPolicyDiff/getOptionsDiff.esm.js +2 -0
  44. package/dist/components/Diffing/getPolicyDiff/getPermissionsDiff.esm.js +2 -0
  45. package/dist/components/Diffing/getPolicyDiff/getPolicyDiff.esm.js +2 -0
  46. package/dist/components/Diffing/getPolicyDiff/getRolesDiff.esm.js +2 -0
  47. package/dist/components/Diffing/getPolicyDiff/utils.esm.js +2 -0
  48. package/dist/components/Diffing/usePolicyDiff.esm.js +2 -0
  49. package/dist/components/Diffing/utils.esm.js +2 -0
  50. package/dist/components/EditableInput/EditableInput.esm.js +2 -0
  51. package/dist/components/Home/HomePage.esm.js +2 -0
  52. package/dist/components/Home/HomePageContent.esm.js +2 -0
  53. package/dist/components/Home/HomePageEmptyState.esm.js +2 -0
  54. package/dist/components/Layout/Breadcrumbs.esm.js +2 -0
  55. package/dist/components/Layout/EmptyStateImageWrapper.esm.js +2 -0
  56. package/dist/components/Layout/PageWrapper.esm.js +2 -0
  57. package/dist/components/Layout/Title.esm.js +2 -0
  58. package/dist/components/Members/MemberOptionsProvider.esm.js +2 -0
  59. package/dist/components/Members/MembersAutocomplete.esm.js +2 -0
  60. package/dist/components/Members/MembersAutocompleteListBox.esm.js +2 -0
  61. package/dist/components/Members/MembersTable.esm.js +2 -0
  62. package/dist/components/Members/MembersTableBody.esm.js +2 -0
  63. package/dist/components/Permission/PermissionName.esm.js +2 -0
  64. package/dist/components/Permissions/PermissionsMetadataContext.esm.js +2 -0
  65. package/dist/components/Permissions/PermissionsTable.esm.js +2 -0
  66. package/dist/components/Permissions/utils.esm.js +2 -0
  67. package/dist/components/Policies/PoliciesProvider.esm.js +2 -0
  68. package/dist/components/Policies/PoliciesTable.esm.js +2 -0
  69. package/dist/components/Policies/useFetchPolicies.esm.js +2 -0
  70. package/dist/components/Policy/EmptyRolesCard.esm.js +2 -0
  71. package/dist/components/Policy/PolicyCard.esm.js +2 -0
  72. package/dist/components/Policy/PolicyConflictDialog.esm.js +2 -0
  73. package/dist/components/Policy/PolicyImportButton.esm.js +2 -0
  74. package/dist/components/Policy/PolicyInvalidDialog.esm.js +2 -0
  75. package/dist/components/Policy/PolicyMenu.esm.js +2 -0
  76. package/dist/components/Policy/PolicyOptionCard.esm.js +2 -0
  77. package/dist/components/Policy/PolicyOptionsPage.esm.js +2 -0
  78. package/dist/components/Policy/PolicyPage.esm.js +2 -0
  79. package/dist/components/Policy/PolicyProvider.esm.js +2 -0
  80. package/dist/components/Policy/PolicyPublishButton.esm.js +2 -0
  81. package/dist/components/Policy/PolicyPublishConfirmationDialog.esm.js +2 -0
  82. package/dist/components/Policy/PolicyPublishSuccessDialog.esm.js +2 -0
  83. package/dist/components/Policy/PolicyStatusChip.esm.js +2 -0
  84. package/dist/components/Policy/exportPolicy.esm.js +3 -0
  85. package/dist/components/Policy/getActivityDescriptions.esm.js +2 -0
  86. package/dist/components/Policy/getLatestPolicy.esm.js +2 -0
  87. package/dist/components/Policy/useDeleteDraftPolicy.esm.js +2 -0
  88. package/dist/components/Policy/useDuplicatePolicy.esm.js +2 -0
  89. package/dist/components/Policy/useLocalDraftPolicy.esm.js +2 -0
  90. package/dist/components/Policy/usePublishPolicy.esm.js +2 -0
  91. package/dist/components/PolicyTester/DecisionBreakdownTable/CellText.esm.js +2 -0
  92. package/dist/components/PolicyTester/DecisionBreakdownTable/DecidingRoleCell.esm.js +2 -0
  93. package/dist/components/PolicyTester/DecisionBreakdownTable/DecisionBreakdownTable.esm.js +2 -0
  94. package/dist/components/PolicyTester/DecisionBreakdownTable/DecisionCell.esm.js +2 -0
  95. package/dist/components/PolicyTester/DecisionBreakdownTable/PermissionNameCell.esm.js +2 -0
  96. package/dist/components/PolicyTester/DecisionBreakdownTable/RoleNameCell.esm.js +2 -0
  97. package/dist/components/PolicyTester/DecisionBreakdownTable/TableHeaderCell.esm.js +2 -0
  98. package/dist/components/PolicyTester/DecisionBreakdownTable/UserIconCell.esm.js +2 -0
  99. package/dist/components/PolicyTester/DecisionIcon.esm.js +2 -0
  100. package/dist/components/PolicyTester/DecisionInfo.esm.js +2 -0
  101. package/dist/components/PolicyTester/PolicyTestResultDetails.esm.js +2 -0
  102. package/dist/components/PolicyTester/PolicyTester.esm.js +2 -0
  103. package/dist/components/PolicyTester/PolicyTesterFieldset.esm.js +2 -0
  104. package/dist/components/PolicyTester/PolicyTesterPermissionSelect.esm.js +2 -0
  105. package/dist/components/PolicyTester/PolicyTesterResultRow.esm.js +2 -0
  106. package/dist/components/PolicyTester/PolicyTesterResults.esm.js +2 -0
  107. package/dist/components/PolicyTester/PolicyTesterRoleSelect.esm.js +2 -0
  108. package/dist/components/PolicyTester/StatusChip.esm.js +2 -0
  109. package/dist/components/PolicyTester/usePolicyTestResult.esm.js +2 -0
  110. package/dist/components/PolicyTester/usePolicyTesterLocalStorageStrings.esm.js +2 -0
  111. package/dist/components/RBACSidebarItem.esm.js +2 -0
  112. package/dist/components/RelativeTime/RelativeTime.esm.js +2 -0
  113. package/dist/components/ReorderControls/ReorderControls.esm.js +2 -0
  114. package/dist/components/ReorderControls/ReorderInfo.esm.js +2 -0
  115. package/dist/components/ReorderControls/shiftPositionInArray.esm.js +2 -0
  116. package/dist/components/Role/RolePage.esm.js +2 -0
  117. package/dist/components/Roles/RolesTable.esm.js +2 -0
  118. package/dist/components/Root.esm.js +2 -0
  119. package/dist/index.esm.js +1 -1
  120. package/dist/plugin.esm.js +2 -0
  121. package/dist/routes.esm.js +2 -0
  122. package/dist/utils/assert.esm.js +2 -0
  123. package/dist/utils/errors.esm.js +2 -0
  124. package/dist/utils/getZodValidationToKeyMap.esm.js +2 -0
  125. package/package.json +31 -23
  126. package/dist/esm/Authorized-BwbJLswg.esm.js +0 -2
  127. package/dist/esm/RBACSidebarItem-DRxQHRoM.esm.js +0 -2
  128. package/dist/esm/Root-DUzXpmaE.esm.js +0 -3
  129. package/dist/esm/routes-DldYB8_w.esm.js +0 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @spotify/backstage-plugin-rbac
2
2
 
3
+ ## 0.6.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependency `uuid` to `^10.0.0`.
8
+ - Added additional plugin metadata to `package.json`.
9
+ - Upgraded Backstage to v1.28.2
10
+ - Updated dependencies
11
+ - @spotify/backstage-plugin-core@0.7.2
12
+ - @spotify/backstage-plugin-rbac-common@0.5.14
13
+
3
14
  ## 0.6.2
4
15
 
5
16
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
- "name": "@spotify/backstage-plugin-rbac",
3
- "version": "0.6.2",
2
+ "name": "@spotify/backstage-plugin-rbac__alpha",
3
+ "version": "0.6.3",
4
4
  "main": "../dist/alpha.esm.js",
5
5
  "module": "../dist/alpha.esm.js",
6
6
  "types": "../dist/alpha.d.ts"
@@ -0,0 +1,2 @@
1
+ import{createApiExtension as i,createApiFactory as p,fetchApiRef as r,discoveryApiRef as c}from"@backstage/frontend-plugin-api";import{rbacApiRef as o,RBACApi as t}from"../api.esm.js";const A=i({factory:p({api:o,deps:{fetchApi:r,discoveryApi:c},factory:e=>new t(e)})});export{A as rbacApi};
2
+ //# sourceMappingURL=apis.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{convertLegacyRouteRef as e,compatWrapper as t}from"@backstage/core-compat-api";import{createPageExtension as r}from"@backstage/frontend-plugin-api";import a from"react";import{rootRouteRef as m}from"../routes.esm.js";const p=r({routeRef:e(m),defaultPath:"/rbac",loader:()=>import("../components/Root.esm.js").then(o=>t(a.createElement(o.RBACRoot,null)))});export{p as rbacPage};
2
+ //# sourceMappingURL=pages.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{createPlugin as r}from"@backstage/frontend-plugin-api";import{rbacApi as a}from"./apis.esm.js";import{rbacPage as i}from"./pages.esm.js";var o=r({id:"rbac",extensions:[i,a]});export{o as default};
2
+ //# sourceMappingURL=plugin.esm.js.map
package/dist/alpha.esm.js CHANGED
@@ -1,2 +1,2 @@
1
- import{createApiExtension as r,createApiFactory as t,fetchApiRef as o,discoveryApiRef as a,createPageExtension as i,createPlugin as p}from"@backstage/frontend-plugin-api";import{a as c,R as f,r as n}from"./esm/routes-DldYB8_w.esm.js";import{convertLegacyRouteRef as m,compatWrapper as s}from"@backstage/core-compat-api";import R from"react";import"@backstage/core-plugin-api";import"@backstage/errors";import"@spotify/backstage-plugin-rbac-common";const A=r({factory:t({api:c,deps:{fetchApi:o,discoveryApi:a},factory:e=>new f(e)})}),l=i({routeRef:m(n),defaultPath:"/rbac",loader:()=>import("./esm/Root-DUzXpmaE.esm.js").then(e=>s(R.createElement(e.RBACRoot,null)))});var u=p({id:"rbac",extensions:[l,A]});export{u as default};
1
+ import{default as o}from"./alpha/plugin.esm.js";export{o as default};
2
2
  //# sourceMappingURL=alpha.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{createApiRef as p}from"@backstage/core-plugin-api";import{ResponseError as h}from"@backstage/errors";import{PolicyResponseParser as l,PolicyParser as o,SearchMemberResponseParser as y,AuthorizeResponseParser as f,DraftResponseParser as c,TestPolicyDecisionResponseParser as d}from"@spotify/backstage-plugin-rbac-common";const w=p({id:"plugin.rbac"});class m{fetchApi;discoveryApi;constructor(i){this.fetchApi=i.fetchApi,this.discoveryApi=i.discoveryApi}async getPolicies(){const{fetch:i}=this.fetchApi,s=await i(`${await this.discoveryApi.getBaseUrl("rbac")}/policies`),t=await this.#i(s);return l.parse(t)}async getPolicy(i){const{fetch:s}=this.fetchApi,t=await s(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${i}`),e=await this.#i(t);return o.parse(e)}async getActivePolicy(){const{fetch:i}=this.fetchApi,s=await i(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/active`),t=await this.#i(s);return o.parse(t)}async searchMembers(i){const{fetch:s}=this.fetchApi,t=await s(`${await this.discoveryApi.getBaseUrl("rbac")}/members?query=${encodeURIComponent(i.query)}`),e=await this.#i(t);return y.parse(e)}async authorize(){const{fetch:i}=this.fetchApi,s=await i(`${await this.discoveryApi.getBaseUrl("rbac")}/authorize`),t=await this.#i(s);return f.parse(t)}async createDraft(i){const{fetch:s}=this.fetchApi,t=await s(`${await this.discoveryApi.getBaseUrl("rbac")}/policies`,{method:"POST",body:JSON.stringify(i),headers:{"Content-Type":"application/json"}}),e=await this.#i(t);return c.parse(e)}async updateDraft(i,s){const{fetch:t}=this.fetchApi,e=await t(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${i}`,{method:"PATCH",body:JSON.stringify(s),headers:{"Content-Type":"application/json"}}),a=await this.#i(e);return c.parse(a)}async deleteDraft(i){const{fetch:s}=this.fetchApi,t=await s(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${i}`,{method:"DELETE"});return await this.#i(t)}async publishPolicy(i,s){const{fetch:t}=this.fetchApi,e=await t(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${i}/publish`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});return await this.#i(e)}async testPolicyDecisions(i){return await Promise.all(i.map(async s=>{const{policyConfig:t,roleIds:e,permission:a}=s,{decision:r,decisionOrigin:n}=await this.#s(t,e,a);return{decision:r,permission:a,decisionOrigin:n}}))}async#s(i,s,t){const{fetch:e}=this.fetchApi,a=await e(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/test-policy-decision`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({policyConfig:i,roleIds:s,permission:t})}),r=await this.#i(a);return d.parse(r)}async fetchAllPermissionMetadata(i){const s=await Promise.all(i.map(t=>this.#t(t)));return{permissions:s.flatMap(({permissions:t})=>t),rules:s.flatMap(({rules:t})=>t)}}async#t(i){const s=await this.discoveryApi.getBaseUrl(i);let t;try{const r=await this.fetchApi.fetch(`${s}/.well-known/backstage/permissions/metadata`);t=await this.#i(r)}catch{return{permissions:[],rules:[]}}const e=t.permissions?.filter(Boolean)??[],a=t.rules?.filter(Boolean)??[];return{permissions:e,rules:a.map(r=>({...r,pluginId:i}))}}async#i(i){if(i.ok)return i.status===204?void 0:i.json();const s=await h.fromResponse(i);throw s.message=s.body.error.message??s.message??"Unknown error",s}}export{m as RBACApi,w as rbacApiRef};
2
+ //# sourceMappingURL=api.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{useApi as i}from"@backstage/core-plugin-api";import e from"react";import m from"react-use/lib/useAsync";import{rbacApiRef as u}from"../../api.esm.js";function a({children:t,loading:n=null,unauthorized:o=null}){const l=i(u),r=m(()=>l.authorize(),[]);return r.loading?e.createElement(e.Fragment,null,n):r.value?.authorized?e.createElement(e.Fragment,null,t):e.createElement(e.Fragment,null,o)}export{a as Authorized};
2
+ //# sourceMappingURL=Authorized.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Dialog as s,DialogTitle as g,Box as u,DialogContent as E,DialogContentText as f,DialogActions as p,Button as l}from"@material-ui/core";import e,{useState as D}from"react";const d=({children:o,onConfirm:a,message:i,title:r})=>{const[c,t]=D(!1),n=()=>t(!1),m=()=>t(!0),C=()=>{a(),n()};return e.createElement(e.Fragment,null,o({onClick:m}),e.createElement(s,{open:c,onClose:n},e.createElement(g,null,e.createElement(u,{display:"flex",justifyContent:"space-between",alignItems:"center"},r)),e.createElement(E,null,e.createElement(f,null,i)),e.createElement(p,null,e.createElement(l,{"aria-label":"Cancel action",color:"primary",onClick:n},"Cancel"),e.createElement(l,{"aria-label":"Confirm action",color:"secondary",onClick:C,variant:"contained"},"Confirm"))))};export{d as ConfirmationDialog};
2
+ //# sourceMappingURL=ConfirmationDialog.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as d,Button as m,Menu as u,MenuItem as i}from"@material-ui/core";import t,{useRef as p,useState as s}from"react";import{CONDITION_TYPES as f,CONDITION_TYPE_DISPLAY_TEXT as E}from"../conditionConstants.esm.js";const I=d(()=>({addButton:{paddingLeft:40,paddingRight:40}}));function T({onSelect:a}){const l=I(),n=p(null),[c,o]=s(!1),r=()=>{o(e=>!e)};return t.createElement("div",null,t.createElement(m,{className:l.addButton,variant:"outlined",color:"primary",onClick:r,ref:n},"Add"),t.createElement(u,{anchorEl:n.current,open:c,onClose:r,BackdropProps:{}},f.map(e=>t.createElement(i,{key:e,onClick:()=>{a?.(e),o(!1)}},E[e]))))}export{T as default};
2
+ //# sourceMappingURL=AddConditionSelector.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as g,Box as a,Card as f,CardContent as C,InputLabel as h,TextField as y,Typography as i,Popper as x,IconButton as b}from"@material-ui/core";import v from"@material-ui/icons/Delete";import{Autocomplete as B}from"@material-ui/lab";import e,{useCallback as F}from"react";import{useAggregatedRules as I}from"../../Permissions/PermissionsMetadataContext.esm.js";import{ParamsForm as k}from"../ParamsForm/ParamsForm.esm.js";const D=g(n=>({conditionCard:{minWidth:n.spacing(63)},conditionCardBar:{height:n.spacing(1),backgroundImage:"linear-gradient(90deg, #007DFF 0%, #0057B2 100%)"},autocomplete:{flex:1}}));function N({ruleName:n,parameters:p,resourceType:u,onChange:r,onDelete:d}){const o=D(),m=I()?.filter(t=>t.resourceType===u)??[],c=m.find(t=>t.name===n),s=t=>{r(t,{})},E=F(t=>{r(n,t)},[r,n]);return e.createElement(a,{display:"flex",alignItems:"center"},e.createElement(f,{className:o.conditionCard},e.createElement("div",{className:o.conditionCardBar}),e.createElement(C,null,e.createElement(a,null,e.createElement(a,null,e.createElement(B,{className:o.autocomplete,"data-testid":"rule-select",getOptionLabel:t=>t.name,getOptionSelected:(t,l)=>t.name===l.name,options:m,onChange:(t,l)=>s(l?l.name:null),renderInput:t=>e.createElement(e.Fragment,null,e.createElement(a,{marginBottom:2},e.createElement(h,null,"Rule")),e.createElement(y,{...t,placeholder:"Select",variant:"outlined",size:"small",name:"rule"})),renderOption:t=>e.createElement(a,null,e.createElement(i,{variant:"body2"},t.name),e.createElement(i,{noWrap:!0,variant:"caption"},t.description)),value:c||null,PopperComponent:t=>e.createElement(x,{...t,style:{width:"auto"},placement:"bottom-start"})})),e.createElement(a,{flex:"1"},e.createElement(a,{display:"flex",flexDirection:"column"},e.createElement(k,{rule:c,onChange:E,value:p})))))),e.createElement(a,{ml:1},e.createElement(b,{"aria-label":"delete",onClick:d,size:"small"},e.createElement(v,null))))}export{N as default};
2
+ //# sourceMappingURL=ConditionCard.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as H,Box as c}from"@material-ui/core";import l,{useCallback as p,useMemo as v,Fragment as S}from"react";import{v4 as C}from"uuid";import{isConditionLevel as V,isNestedConditionType as z}from"../conditionConstants.esm.js";import F from"./AddConditionSelector.esm.js";import $ from"./ConditionCard.esm.js";import L from"./ConditionTypeSelector.esm.js";import{getNewCondition as f}from"./utils.esm.js";const k=H(e=>({treeVerticalSpacer:{width:e.spacing(2),borderLeft:`1px solid ${e.palette.status.aborted}`},treeHorizontalSpacer:{height:e.spacing(3),borderLeft:`1px solid ${e.palette.status.aborted}`},treeVerticalBranchHalf:{position:"absolute",height:"50%",borderLeft:`1px solid ${e.palette.status.aborted}`,alignSelf:"flex-start"},treeVerticalBranchFull:{borderLeft:`1px solid ${e.palette.status.aborted}`,alignSelf:"stretch"},treeHorizontalBranch:{width:e.spacing(2),borderTop:`1px solid ${e.palette.status.aborted}`}}));function E({level:e,resourceType:s,onChange:n,parentConditionType:h,isRoot:m=!1}){const a=k(),d=p((t,r)=>{const o=[...e.children];return o.splice(t,1,r),o},[e]),i=p(t=>{n({...e,children:t})},[n,e]),y=p(t=>{t===null?n(null):t==="not"&&e.children.length>1?n({...e,levelType:t,children:e.children.slice(0,1)}):n({...e,levelType:t})},[n,e]),u=p((t,r)=>{i(t===null?g(e.children,r):d(r,t))},[e,i,d]),N=t=>{const r=C();t==="condition"?i([...e.children,f()]):t==="not"?i([...e.children,{id:r,levelType:t,children:[]}]):z(t)&&i([...e.children,{id:r,levelType:t,children:[f()]}])},T=t=>{i(g(e.children,t))},b=v(()=>e.children.map((t,r)=>(o,x)=>{i(d(r,{...t,ruleName:o,parameters:x}))}),[e.children,i,d]),B=v(()=>e.children.map((t,r)=>o=>u(o,r)),[e.children,u]);return l.createElement("div",null,!m&&l.createElement("div",{className:a.treeHorizontalSpacer}),l.createElement(c,{display:"flex",alignItems:"center",position:"relative"},!m&&l.createElement(l.Fragment,null,l.createElement("div",{className:h==="not"?a.treeVerticalBranchHalf:a.treeVerticalBranchFull}),l.createElement("div",{className:a.treeHorizontalBranch})),l.createElement(L,{level:e,onSelect:y})),l.createElement(c,{display:"flex"},m||h==="not"?l.createElement(c,{pl:2}):l.createElement("div",{className:a.treeVerticalSpacer}),!m&&l.createElement(c,{pl:2}),l.createElement("div",null,e.children.map((t,r)=>V(t)?l.createElement(c,{key:t.id},l.createElement(E,{level:t,resourceType:s,parentConditionType:e.levelType,onChange:B[r]})):l.createElement(S,{key:t.id},l.createElement("div",{className:a.treeHorizontalSpacer}),l.createElement(c,{display:"flex",alignItems:"center",position:"relative"},l.createElement("div",{className:e.levelType==="not"?a.treeVerticalBranchHalf:a.treeVerticalBranchFull}),l.createElement("div",{className:a.treeHorizontalBranch}),l.createElement($,{ruleName:t.ruleName,parameters:t.parameters,resourceType:s,onChange:b[r],onDelete:()=>T(r)})))),!(e.levelType==="not"&&e.children.length>=1)&&l.createElement(l.Fragment,null,l.createElement("div",{className:a.treeHorizontalSpacer}),l.createElement(c,{display:"flex",alignItems:"center",position:"relative"},l.createElement("div",{className:a.treeVerticalBranchHalf}),l.createElement("div",{className:a.treeHorizontalBranch}),l.createElement(F,{onSelect:N}))))))}function g(e,s){const n=[...e];return n.splice(s,1),n}export{E as default};
2
+ //# sourceMappingURL=ConditionTree.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as c,Box as a,FormControl as i,Select as f,MenuItem as l,IconButton as s}from"@material-ui/core";import u from"@material-ui/icons/Delete";import e from"react";const y=c(t=>({conditionTypeFormControl:{minWidth:80,marginLeft:t.spacing(1)}}));function p({level:t,onSelect:n}){const o=y(),r=t.children.length>1;return e.createElement(a,{display:"flex",alignItems:"center"},e.createElement(i,{className:o.conditionTypeFormControl},e.createElement(f,{value:t.levelType,onChange:m=>n?.(m.target.value)},e.createElement(l,{key:"anyOf",value:"anyOf"},"Any of"),e.createElement(l,{key:"allOf",value:"allOf"},"All of"),e.createElement(l,{key:"not",value:"not",disabled:r},"Not"))),e.createElement(a,{ml:1},e.createElement(s,{"aria-label":"delete",onClick:()=>n?.(null),size:"small"},e.createElement(u,null))))}export{p as default};
2
+ //# sourceMappingURL=ConditionTypeSelector.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as C,Paper as y}from"@material-ui/core";import a,{useCallback as i}from"react";import{v4 as v}from"uuid";import{isCondition as T,isConditionLevel as h}from"../conditionConstants.esm.js";import E from"./AddConditionSelector.esm.js";import N from"./ConditionCard.esm.js";import k from"./ConditionTree.esm.js";import{CriteriaSummary as S}from"./CriteriaSummary/CriteriaSummary.esm.js";import{getNewCondition as p}from"./utils.esm.js";const b=C(e=>({paper:{backgroundColor:e.palette.background.default,padding:e.spacing(3),marginBottom:e.spacing(3),minHeight:e.spacing(48)}}));function D({permissionCriteria:e,resourceType:m,onUpdate:o,readonly:c=!1}){const s=b(),l=i(r=>{o(t=>({...t,...r}))},[o]),u=i(r=>{const t=v();l(r==="condition"?p():r==="not"?{id:t,levelType:r,children:[]}:{id:t,levelType:r,children:[p()]})},[l]),d=i((r,t)=>{o(g=>({...g,ruleName:r,parameters:t}))},[o]),f=i(()=>{o(null)},[o]);let n;return c?n=a.createElement(S,{permissionCriteria:e}):e===null?n=a.createElement(E,{onSelect:u}):T(e)?n=a.createElement(N,{ruleName:e.ruleName,parameters:e.parameters,resourceType:m,onChange:d,onDelete:f}):h(e)&&(n=a.createElement(k,{level:e,resourceType:m,onChange:o,isRoot:!0})),a.createElement(y,{variant:"outlined",className:s.paper},n)}export{D as default};
2
+ //# sourceMappingURL=ConditionalDecisionForm.esm.js.map
@@ -0,0 +1,2 @@
1
+ import e from"react";import{CONDITION_TYPE_DISPLAY_TEXT as n,isConditionLevel as m}from"../../conditionConstants.esm.js";import a from"./ConditionSummary.esm.js";import{Indent as i}from"./Indent.esm.js";import{MonospaceText as c}from"./MonospaceText.esm.js";function o({level:r}){return e.createElement(e.Fragment,null,e.createElement(c,null,n[r.levelType]),e.createElement(i,null,r.children.map((t,l)=>m(t)?e.createElement(o,{key:l,level:t}):e.createElement(a,{key:l,condition:t}))))}export{o as default};
2
+ //# sourceMappingURL=ConditionLevelSummary.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as o,Box as a}from"@material-ui/core";import t from"react";import{MonospaceText as l}from"./MonospaceText.esm.js";const n=o(e=>({rule:{color:e.palette.type==="light"?"#EB0014":"#FF8F9C"},parameters:{color:e.palette.type==="light"?"#E22134":"#EE96A0"}}));function m({condition:e}){const r=n();return t.createElement(l,null,t.createElement(a,{component:"span",className:r.rule},e.ruleName,"(",t.createElement(a,{component:"span",className:r.parameters},JSON.stringify(e.parameters,null,1)),")"))}export{m as default};
2
+ //# sourceMappingURL=ConditionSummary.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as i,Box as t}from"@material-ui/core";import r from"react";import{isCondition as n,isConditionLevel as s}from"../../conditionConstants.esm.js";import m from"./ConditionLevelSummary.esm.js";import a from"./ConditionSummary.esm.js";const l=i(e=>({resultsBox:{border:`1px solid ${e.palette.border}`,borderRadius:e.shape.borderRadius,padding:e.spacing(2)}}));function d({permissionCriteria:e}){const o=l();return r.createElement(t,{className:o.resultsBox},n(e)&&r.createElement(a,{condition:e}),s(e)&&r.createElement(m,{level:e}))}export{d as ConditionalDecisionBox};
2
+ //# sourceMappingURL=ConditionalDecisionBox.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as i,Typography as n}from"@material-ui/core";import t from"react";import{ConditionalDecisionBox as r}from"./ConditionalDecisionBox.esm.js";const a=i(e=>({conditionResultText:{color:e.palette.success.main},conditionDecisionText:{padding:`0 0 ${e.spacing(3)}px`}}));function s({permissionCriteria:e}){const o=a();return t.createElement("div",null,t.createElement(n,{component:"p",variant:"body1",className:o.conditionDecisionText},"If the below conditions are met then the action is"," ",t.createElement("strong",{className:o.conditionResultText},"allowed.")),t.createElement(r,{permissionCriteria:e}))}export{s as CriteriaSummary};
2
+ //# sourceMappingURL=CriteriaSummary.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Box as e}from"@material-ui/core";import r from"react";const t=({children:o})=>r.createElement(e,{pl:2},o);export{t as Indent};
2
+ //# sourceMappingURL=Indent.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as r,Typography as e}from"@material-ui/core";import a from"react";const n=r(()=>({root:{fontFamily:"monospace"}})),m=({children:o})=>{const t=n();return a.createElement(e,{variant:"body2",className:t.root},o)};export{m as MonospaceText};
2
+ //# sourceMappingURL=MonospaceText.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{v4 as e}from"uuid";function r(){return{id:e(),ruleName:null,parameters:{}}}export{r as getNewCondition};
2
+ //# sourceMappingURL=utils.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as W,Dialog as A,DialogTitle as F,Typography as j,Button as x,DialogContent as k,Box as r,Divider as M,FormHelperText as V,Tooltip as G}from"@material-ui/core";import H from"@material-ui/icons/Close";import L from"@material-ui/icons/Info";import e,{useState as T,useMemo as y,useEffect as O}from"react";import{usePermissions as U,useAggregatedRules as Y,useResourceTypeInfo as q}from"../Permissions/PermissionsMetadataContext.esm.js";import z from"./computeMatchResult.esm.js";import J from"./ConditionalDecisionForm/ConditionalDecisionForm.esm.js";import{getInitialValues as K,validateCriteria as Q,toRolePermission as X,getConditions as Z}from"./decisionDataMappers.esm.js";import _ from"./MatchByActions.esm.js";import $ from"./MatchByName.esm.js";import ee from"./MatchByResourceType.esm.js";import C from"./ToggleButton.esm.js";import oe from"./ToggleButtonGroup.esm.js";import{VerticalSelection as ie}from"./VerticalSelection.esm.js";const ne=W(a=>({dialogTitle:{display:"flex",alignItems:"center",justifyContent:"space-between"},fullWidth:{width:"100%","& > *":{flexGrow:1}},infoIcon:{position:"absolute",right:a.spacing(3)},content:{padding:a.spacing(7)},saveButton:{paddingLeft:a.spacing(5),paddingRight:a.spacing(5)},contentContainerConditional:{display:"flex",gap:a.spacing(5),maxWidth:1480}})),te={specificPermission:"Choose a specific permission",filter:"Filter by permission properties",all:"Match all permissions"},R="Choose the name of a resource permission or filter by resource type to set a conditional decision.";function ae({rolePermission:a,readonly:t=!1,onClose:b,onSave:D}){const s=ne(),{permissions:c}=U(),v=Y(),f=q(),p=K(a),[o,d]=T(p.match),[l,g]=T(p.decisionType),[u,I]=T(p.criteria),i=y(()=>z(c,o),[c,o]),m=l==="conditional",w=m?"xl":"sm";O(()=>{m&&c&&!i.commonResourceType&&g("allow")},[m,c,i.commonResourceType,g]);const N=n=>{n!==null&&g(n)},h=y(()=>o.method==="specificPermission"&&!o.name||o.method==="filter"&&!o.resourceType&&!o.actions,[o]),P=y(()=>i.permissions.length===0?!1:!h,[i,h]),S=y(()=>l!=="conditional"?!0:!(!i.commonResourceType||!f?.[i.commonResourceType].pluginId||!Q(u,v)),[l,i,f,u,v]),B=()=>{D?.(X(p.id,o,l==="conditional"?{resourceType:i.commonResourceType,pluginId:f[i.commonResourceType].pluginId,conditions:Z(u)}:l))};return e.createElement(A,{open:!0,maxWidth:w,onClose:b,fullWidth:!0},e.createElement(F,{disableTypography:!0,className:s.dialogTitle},e.createElement(j,{variant:"h4",component:"h2"},"New Permission Decision"),e.createElement(x,{startIcon:e.createElement(H,null),onClick:b},"Close")),e.createElement(k,{dividers:!0,className:s.content},e.createElement(r,{className:m?s.contentContainerConditional:void 0},e.createElement(r,{mb:5,flex:1},e.createElement(ie,{options:Object.entries(te).map(([n,E])=>({id:n,displayText:E})),selected:o.method,onChange:n=>d({method:n}),readonly:t})),e.createElement(r,{mb:5,height:189,flex:1},o.method==="specificPermission"&&e.createElement($,{name:o.name,readonly:t,onNameChange:n=>d({...o,name:n})}),o.method==="filter"&&e.createElement(e.Fragment,null,e.createElement(ee,{resourceType:o.resourceType,readonly:t,onResourceTypeChange:n=>d({...o,resourceType:n})}),e.createElement(_,{actions:o.actions,readonly:t,onActionsChange:n=>d({...o,actions:n.length?n:void 0})}),h?null:e.createElement(e.Fragment,null,e.createElement(r,{marginY:2},e.createElement(M,{variant:"middle"})),e.createElement(V,null,`Matched ${i.permissions.length} ${i.permissions.length===1?"permission":"permissions"}`)))),e.createElement(r,{mb:5,flex:1},e.createElement(r,{display:"flex",alignItems:"center"},e.createElement(oe,{value:l,exclusive:!0,fullWidth:!0,"aria-label":"Decision result",onChange:(n,E)=>N(E)},e.createElement(C,{value:"allow","aria-label":"Decision allowed",disabled:t},"Allow"),e.createElement(C,{value:"deny","aria-label":"Decision denied",disabled:t},"Deny"),e.createElement(C,{value:"conditional","aria-label":"Decision conditionally allowed",disabled:!i.commonResourceType||t},"Conditional")),!m&&!t&&e.createElement(G,{title:R},e.createElement(L,{className:s.infoIcon,color:"primary","aria-label":R}))))),l==="conditional"&&!!i.commonResourceType&&e.createElement(J,{permissionCriteria:u,resourceType:i.commonResourceType,onUpdate:I,readonly:t}),!t&&e.createElement(r,{display:"flex",justifyContent:"flex-end"},e.createElement(x,{variant:"contained",color:"primary",className:s.saveButton,onClick:B,disabled:!P||!S},"Save"))))}export{ae as DecisionDialog};
2
+ //# sourceMappingURL=DecisionDialog.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{TextField as i}from"@material-ui/core";import{Autocomplete as l}from"@material-ui/lab";import t from"react";const d="Action";function m({actions:o,readonly:n,onActionsChange:r}){return t.createElement(l,{multiple:!0,id:"match-by-attribute-dropdown",options:["create","read","update","delete"],getOptionLabel:e=>e,value:o??[],onChange:(e,a)=>r?.(a),filterSelectedOptions:!0,renderInput:e=>t.createElement(i,{...e,variant:"outlined",label:d,placeholder:"Choose attributes",margin:"normal"}),disabled:n})}export{m as default};
2
+ //# sourceMappingURL=MatchByActions.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as i,FormControl as s,InputLabel as d,Select as c,MenuItem as u}from"@material-ui/core";import a from"react";import{usePermissions as h}from"../Permissions/PermissionsMetadataContext.esm.js";const p=i(()=>({fullWidth:{width:"100%","& > *":{flexGrow:1}}})),n="Permission name";function f({name:m="",readonly:l,onNameChange:o}){const r=p(),{permissions:t}=h();return a.createElement(s,{className:r.fullWidth,variant:"outlined",disabled:l,"data-testid":"match-by-name-select"},a.createElement(d,{id:"match-by-name-dropdown"},n),a.createElement(c,{labelId:"match-by-name-dropdown",label:n,value:t?m:"",onChange:e=>o?.(e.target.value)},t?.map(e=>a.createElement(u,{key:e.name,value:e.name},e.name))))}export{f as default};
2
+ //# sourceMappingURL=MatchByName.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as m,FormControl as s,InputLabel as u,Select as d,MenuItem as p}from"@material-ui/core";import t from"react";import{useResourceTypeOptions as i}from"../Permissions/PermissionsMetadataContext.esm.js";const y=m(()=>({fullWidth:{width:"100%","& > *":{flexGrow:1}}})),o="Resource type";function b({resourceType:a="",readonly:l,onResourceTypeChange:n}){const c=y(),r=i();return t.createElement(s,{className:c.fullWidth,variant:"outlined",disabled:l,"data-testid":"match-by-resource-select"},t.createElement(u,{id:"match-by-resource-dropdown"},o),t.createElement(d,{labelId:"match-by-resource-dropdown",label:o,value:r?a:"",onChange:e=>n?.(e.target.value),displayEmpty:!0},r?.map(e=>t.createElement(p,{key:e,value:e},e))))}export{b as default};
2
+ //# sourceMappingURL=MatchByResourceType.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Button as d,Box as n,InputLabel as f,Tooltip as E}from"@material-ui/core";import e,{useState as g}from"react";import{isSupportedType as h}from"./ParamsFormInputRouter.esm.js";import{AdvancedParamsForm as v}from"./ParamsFormJSONEditor.esm.js";import{StandardParamsForm as x}from"./ParamsFormStandard.esm.js";const S=t=>!!t&&"properties"in t;function C({onChange:t,rule:i,value:m}){const[s,c]=g(!1),{paramsSchema:r}=i??{},p=()=>c(u=>!u);if(!S(r))return null;const a=!y(r),l=a||s,o=e.createElement(d,{size:"small",onClick:p,disabled:a},l?"Close editor":"Edit as JSON");return e.createElement(n,{marginTop:2},e.createElement("form",null,l?e.createElement(v,{onChange:t,schema:r,value:m}):e.createElement(e.Fragment,null,e.createElement(n,{marginBottom:2},e.createElement(f,null,"Parameters")),e.createElement(x,{onChange:t,schema:r,value:m}))),e.createElement(n,{display:"flex",flexDirection:"column",alignItems:"flex-end",marginTop:1},a?e.createElement(E,{title:"Only JSON editing is supported for this parameter",arrow:!0},e.createElement("span",null,o)):o))}function y(t){return Object.values(t.properties).every(h)}export{C as ParamsForm};
2
+ //# sourceMappingURL=ParamsForm.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{IconButton as h,Box as s,FormControlLabel as I,Checkbox as B,Tooltip as F}from"@material-ui/core";import P from"@material-ui/icons/Add";import v from"@material-ui/icons/Remove";import{BackstageUserPlaceholder as u}from"@spotify/backstage-plugin-rbac-common";import e,{useCallback as w,useEffect as z}from"react";import{ParamsFormInputRouter as D}from"./ParamsFormInputRouter.esm.js";const O=[];function S(m){const{onChange:n,schema:f,name:g}=m,{description:d,items:c}=f,[y,p]=e.useState(!1),t=Array.isArray(m.value)?m.value:O,r=t.includes(u),E=(a,l)=>{if(!Array.isArray(l)){const o=[...t];o[a]=l||"",n(o)}},i=w(()=>{n([...t,""])},[n,t]),C=a=>{n(t.filter((l,o)=>o!==a))},k=()=>{n(r?[]:[u])},b=()=>{r&&p(!0)},x=()=>{p(!1)};return z(()=>{t.length?r&&t.length>1&&n([u]):i()},[i,n,t,r]),!c||!("type"in c)?null:e.createElement(e.Fragment,null,(t??[]).map((a,l,{length:o})=>e.createElement(D,{allowEmptyStrings:!0,key:l,onChange:A=>E(l,A),name:l===0?g:"",schema:{description:l===o-1?d:"",type:c.type},value:a,controls:e.createElement(h,{size:"small",onClick:()=>C(l)},e.createElement(v,null))})),!!t?.length&&e.createElement(s,{alignItems:"center",display:"flex",flexDirection:"row",justifyContent:"space-between"},e.createElement(s,null,e.createElement(I,{control:e.createElement(B,{checked:r,onChange:k,name:"checkedB",color:"primary"}),label:"Use the claims from the logged in users token"})),e.createElement(s,null,e.createElement(F,{onClose:x,onOpen:b,open:y,title:"To add additional entries you must uncheck using the claims from the logged in user."},e.createElement("span",null,e.createElement(h,{disabled:r,size:"small",onClick:i},e.createElement(P,null)))))))}export{S as ParamsFormArrayInput};
2
+ //# sourceMappingURL=ParamsFormArrayInput.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Box as l,FormControlLabel as p,Checkbox as i,Typography as h}from"@material-ui/core";import e from"react";function b(t){const{onChange:a,schema:n,name:o,value:c}=t,{description:r}=n;return e.createElement(l,{mb:1},e.createElement(p,{control:e.createElement(i,{checked:c===!0,onChange:m=>{a(m.target.checked)},name:o,color:"primary"}),label:o}),r&&e.createElement(h,{display:"block",variant:"caption",color:"textSecondary"},r))}export{b as ParamsFormBooleanInput};
2
+ //# sourceMappingURL=ParamsFormBooleanInput.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Box as a,TextField as d,Typography as p}from"@material-ui/core";import{BackstageUserPlaceholder as u}from"@spotify/backstage-plugin-rbac-common";import r from"react";function g({allowEmptyStrings:e,controls:t,name:o,onChange:c,schema:l,value:n}){const m=s=>{c(v({value:s.currentTarget.value,type:l.type}))};return r.createElement(a,{mb:1},r.createElement(a,{display:"flex",gridGap:6},r.createElement(d,{fullWidth:!0,id:o,label:o,placeholder:"Enter",variant:"outlined",size:"small",value:f(n,e),onChange:i(n,e)?void 0:m,disabled:i(n,e)}),t&&r.createElement(a,{alignSelf:"center"},t)),l.description&&r.createElement(p,{variant:"caption",color:"textSecondary"},l.description,i(n)&&!e&&r.createElement(r.Fragment,null," (switch to JSON editor to edit)")))}function i(e,t=!1){return!t&&e===""||e===null||e===u}function f(e,t=!1){return!t&&e===""?"[empty string]":e===null?"[null]":e===u?"[BackstageUserClaims]":e||""}function v({value:e,type:t}){switch(t){case"string":return e===""?void 0:e;case"number":case"integer":return Number.isNaN(Number(e))?void 0:Number(e);case"null":return e==="null"?null:void 0;default:return}}export{g as ParamsFormInput};
2
+ //# sourceMappingURL=ParamsFormInput.esm.js.map
@@ -0,0 +1,2 @@
1
+ import e from"react";import{ParamsFormArrayInput as o}from"./ParamsFormArrayInput.esm.js";import{ParamsFormBooleanInput as p}from"./ParamsFormBooleanInput.esm.js";import{ParamsFormInput as y}from"./ParamsFormInput.esm.js";function n(r){return!!r&&"type"in r&&(r.type==="array"||r.type==="boolean"||r.type==="null"||r.type==="number"||r.type==="integer"||r.type==="string")}function a(r){return"type"in r&&r.type==="array"}function m(r){return"type"in r&&r.type==="boolean"}function u({schema:r,...t}){return n(r)?a(r)?e.createElement(o,{...t,schema:r}):m(r)?e.createElement(p,{...t,schema:r}):e.createElement(y,{...t,schema:r}):null}export{u as ParamsFormInputRouter,a as isArraySchemaType,m as isBooleanSchemaType,n as isSupportedType};
2
+ //# sourceMappingURL=ParamsFormInputRouter.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as c,TextField as u}from"@material-ui/core";import p from"ajv";import f,{useState as d,useMemo as h}from"react";const v=new p({allErrors:!0}),y=c({textarea:{fontFamily:"monospace"}});function g({onChange:a,schema:e,value:n}){const i=y(),[m,t]=d(!1),s=h(()=>v.compile(e),[e]);return f.createElement(u,{InputProps:{classes:{input:i.textarea}},multiline:!0,fullWidth:!0,variant:"outlined",minRows:3,error:m,defaultValue:JSON.stringify(n,void 0,2),onChange:l=>{const o=l.target.value;if(o)try{const r=JSON.parse(o);s(r)&&(t(!1),a(r))}catch{t(!0)}}})}export{g as AdvancedParamsForm};
2
+ //# sourceMappingURL=ParamsFormJSONEditor.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{FormHelperText as c}from"@material-ui/core";import u from"ajv";import t,{useMemo as n}from"react";import{ParamsFormInputRouter as f}from"./ParamsFormInputRouter.esm.js";const d=new u({allErrors:!0});function g({onChange:s,schema:r,value:m}){const o=n(()=>d.compile(r),[r]),i=n(()=>o(m),[o,m]),l=Object.entries(r.properties),p=e=>a=>{s({...m,[e]:a})};return t.createElement(t.Fragment,null,l.map(([e,a])=>t.createElement(f,{isRequired:r.required?.includes(e)||!1,key:e,name:e,onChange:p(e),schema:a,value:m?.[e]})),t.createElement(c,{error:!i},o.errors?.[0].message))}export{g as StandardParamsForm};
2
+ //# sourceMappingURL=ParamsFormStandard.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as r}from"@material-ui/core";import{ToggleButton as a}from"@material-ui/lab";import l from"react";import{getSelectedColor as m}from"./utils.esm.js";const i=r(e=>({toggleButton:{"&.Mui-selected":{backgroundColor:m(e),color:e.palette.primary.main},"&.Mui-selected:hover":{backgroundColor:"#97BBE8"},color:e.palette.primary.main,border:`1px solid ${e.palette.primary.main}`}}));function n({className:e,...o}){const t=i();return l.createElement(a,{className:`${t.toggleButton} ${e}`,...o})}export{n as default};
2
+ //# sourceMappingURL=ToggleButton.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as r}from"@material-ui/core";import{ToggleButtonGroup as m}from"@material-ui/lab";import f from"react";const u=r({fullWidth:{width:"100%","& > *":{flexGrow:1}}});function a({className:t,fullWidth:o,...e}){const l=u();return f.createElement(m,{className:`${o?l.fullWidth:""} ${t}`,...e})}export{a as default};
2
+ //# sourceMappingURL=ToggleButtonGroup.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as c,Tabs as d,Tab as m}from"@material-ui/core";import o from"react";import{getSelectedColor as s}from"./utils.esm.js";const p=c(e=>({indicator:{right:"unset"},tab:{maxWidth:"none","&.Mui-selected":{backgroundColor:s(e),color:e.palette.primary.main}}}));function b({options:e,selected:r,onChange:i,readonly:n=!1}){const a=p();return o.createElement(d,{orientation:"vertical",value:e.map(({id:t})=>t).indexOf(r),onChange:(t,l)=>i(e[l].id),indicatorColor:"primary",TabIndicatorProps:{className:a.indicator}},e.map(t=>o.createElement(m,{key:t.id,label:t.displayText.toUpperCase(),className:a.tab,disabled:n})))}export{b as VerticalSelection};
2
+ //# sourceMappingURL=VerticalSelection.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{isResourcePermission as e}from"@backstage/plugin-permission-common";import{isMatchingPermission as n}from"@spotify/backstage-plugin-rbac-common";import c from"lodash/uniqBy";import{toPermissionMatch as p}from"./decisionDataMappers.esm.js";function f(s,t){const i=(s??[]).filter(o=>n(o,p(t))),r=c(i,o=>e(o)?o.resourceType:void 0),m=r.length===1&&e(r[0])?r[0].resourceType:void 0;return{permissions:i,commonResourceType:m}}export{f as default};
2
+ //# sourceMappingURL=computeMatchResult.esm.js.map
@@ -0,0 +1,2 @@
1
+ const o=["condition","anyOf","allOf","not"],t={condition:"Condition",anyOf:"Any of",allOf:"All of",not:"Not"};function e(n){return n===null?!1:n.hasOwnProperty("id")&&n.hasOwnProperty("ruleName")&&n.hasOwnProperty("parameters")}function i(n){return n.hasOwnProperty("levelType")}function r(n){return n==="anyOf"||n==="allOf"||n==="not"}export{o as CONDITION_TYPES,t as CONDITION_TYPE_DISPLAY_TEXT,e as isCondition,i as isConditionLevel,r as isNestedConditionType};
2
+ //# sourceMappingURL=conditionConstants.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{isConditionalDecision as a,isAllOfPermissionCriteria as l,isAnyOfPermissionCriteria as d,isNotPermissionCriteria as p}from"@spotify/backstage-plugin-rbac-common";import u from"ajv";import{v4 as c}from"uuid";import{isConditionLevel as f,isCondition as h}from"./conditionConstants.esm.js";function y(i){return i?{id:i.id,match:T(i),decisionType:v(i),criteria:a(i.decision)?n(i.decision.conditions):null}:{id:c(),match:{method:"specificPermission"},decisionType:"allow",criteria:null}}function T(i){return i.match==="*"?{method:"all"}:i.match.name?{method:"specificPermission",name:i.match.name}:i.match.resourceType||i.match.actions?.length?{method:"filter",resourceType:i.match.resourceType,actions:i.match.actions}:{method:"specificPermission"}}function v(i){return typeof i.decision=="string"?i.decision:"conditional"}function n(i){const r=c();return l(i)?{id:r,levelType:"allOf",children:i.allOf.map(e=>n(e))}:d(i)?{id:r,levelType:"anyOf",children:i.anyOf.map(e=>n(e))}:p(i)?{id:r,levelType:"not",children:[n(i.not)]}:{id:r,ruleName:i.rule,parameters:i.params}}function s(i,r){if(!i)return!1;if(f(i))return i.children.length>0&&i.children.every(t=>s(t,r));if(!i.ruleName)return!1;const e=r?.find(({name:t})=>t===i.ruleName);return e?e.paramsSchema?new u({allErrors:!0}).compile(e.paramsSchema)(i.parameters):!0:!1}function C(i,r,e){return{id:i,match:m(r,e),decision:e}}function m({method:i,...r},e){return i==="all"?"*":e&&a(e)?{resourceType:e.resourceType,...r}:r}function o(i){return h(i)?{rule:i.ruleName,params:i.parameters}:i.levelType==="not"?{not:o(i.children[0])}:{[i.levelType]:i.children.map(r=>o(r))}}export{o as getConditions,n as getCriteria,y as getInitialValues,m as toPermissionMatch,C as toRolePermission,s as validateCriteria};
2
+ //# sourceMappingURL=decisionDataMappers.esm.js.map
@@ -0,0 +1,2 @@
1
+ function t(e){return`${e.palette.primary.main}50`}export{t as getSelectedColor};
2
+ //# sourceMappingURL=utils.esm.js.map
@@ -0,0 +1,2 @@
1
+ import t from"react";import{StatusChip as r}from"../PolicyTester/StatusChip.esm.js";import{getTextFromDiffOperation as i,getSeverityFromDiffOperation as n}from"./utils.esm.js";const p=e=>{const o=i(e.operation);return!e.operation||e.operation==="UNCHANGED"?null:t.createElement(r,{size:e.size,text:o,severity:n(e.operation),outlined:!0})};export{p as DiffBadge};
2
+ //# sourceMappingURL=DiffBadge.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as x,Box as f,Typography as M}from"@material-ui/core";import e,{Fragment as p}from"react";import{getMatchBy as D}from"../Permissions/utils.esm.js";import{usePolicyDiff as N}from"./usePolicyDiff.esm.js";import{getColorFromDiffOperation as R}from"./utils.esm.js";const V=x(m=>({root:({operation:l})=>({color:R(m,l)})})),o=m=>e.createElement(M,{...m,variant:"body2"}),t=m=>{const l=V(m);return e.createElement(f,{...m,className:l.root,component:"span",fontWeight:"fontWeightBold"})},B=({policy:m})=>{const l=N(m),d=l?.policy.operation==="CHANGED"||Object.values(l?.roles??{}).some(a=>a.role.operation!=="UNCHANGED")||l?.options?.resolutionStrategy.operation==="CHANGED";if(!l||!d)return e.createElement(f,null,"No changes");const b=!!l.policy.before&&!!l.policy.after&&l.policy.before.name!==l.policy.after.name,y=l.options.resolutionStrategy.operation==="CHANGED",A=({before:a,after:n})=>a&&n&&a.name!==n.name,h=({operation:a})=>a!=="ADDED"&&a!=="REMOVED";return e.createElement(f,null,b&&e.createElement(o,null,"Policy name ",e.createElement(t,{operation:"CHANGED"},"changed")," from"," ",e.createElement(t,null,'"',l.policy.before?.name,'"')," to"," ",e.createElement(t,null,'"',l.policy.after?.name,'"')),y&&e.createElement(o,null,"Resolution Strategy ",e.createElement(t,{operation:"CHANGED"},"changed")," ","from ",e.createElement(t,null,'"',l.options.resolutionStrategy.before,'"')," to"," ",e.createElement(t,null,'"',l.options.resolutionStrategy.after,'"')),Object.entries(l.roles).map(([a,{role:n,permissions:g,members:O}])=>e.createElement(p,{key:a},n.operation==="ADDED"&&e.createElement(o,null,"Role ",e.createElement(t,null,'"',n.after?.name,'"')," has been"," ",e.createElement(t,{operation:"ADDED"},"added")),n.operation==="REMOVED"&&e.createElement(o,null,"Role ",e.createElement(t,null,'"',n.before?.name,'"')," has been"," ",e.createElement(t,{operation:"REMOVED"},"removed")),A(n)&&e.createElement(o,null,"Role name changed from ",e.createElement(t,null,'"',n.before?.name,'"')," ","to ",e.createElement(t,null,'"',n.after?.name,'"')),n.indexAfter>n.indexBefore&&n.indexBefore!==-1&&e.createElement(o,null,"Role ",e.createElement(t,null,'"',n.after?.name,'"')," has been"," ",e.createElement(t,{operation:"MOVED_DOWN"},"moved down")," in priority"),n.indexAfter<n.indexBefore&&n.indexAfter!==-1&&e.createElement(o,null,"Role ",e.createElement(t,null,'"',n.after?.name,'"')," has been"," ",e.createElement(t,{operation:"MOVED_UP"},"moved up")," in priority"),h(n)&&e.createElement(e.Fragment,null,Object.entries(g).map(([c,r])=>{const{before:s,after:u}=r,E=s&&D(s),i=u&&D(u);return e.createElement(p,{key:c},r.operation==="ADDED"&&r.after&&e.createElement(o,null,"Permission decision"," ",e.createElement(t,null,'"',i,'"')," has been"," ",e.createElement(t,{operation:"ADDED"},"added")," to"," ",e.createElement(t,null,'"',n.after?.name,'"')),r.operation==="REMOVED"&&r.before&&e.createElement(o,null,"Permission decision"," ",e.createElement(t,null,'"',E,'"')," has been"," ",e.createElement(t,{operation:"REMOVED"},"removed")," ","from ",e.createElement(t,null,'"',n.after?.name,'"')),r.operation==="CHANGED"&&e.createElement(o,null,E!==i?e.createElement(e.Fragment,null,"Permission decision"," ",e.createElement(t,null,'"',E,'"')," has been"," ",e.createElement(t,{operation:"CHANGED"},"updated")," ","to ",e.createElement(t,null,'"',i,'"')):e.createElement(e.Fragment,null,"Permission decision"," ",e.createElement(t,null,'"',E,'"')," has been"," ",e.createElement(t,{operation:"CHANGED"},"updated"))," ","in ",e.createElement(t,null,'"',n.after?.name,'"')),r.indexAfter>r.indexBefore&&r.indexBefore!==-1&&e.createElement(o,null,"Permission decision"," ",e.createElement(t,null,'"',i,'"')," has been"," ",e.createElement(t,{operation:"MOVED_DOWN"},"moved down")," ","in priority in"," ",e.createElement(t,null,'"',n.after?.name,'"')),r.indexAfter<r.indexBefore&&r.indexAfter!==-1&&e.createElement(o,null,"Permission decision"," ",e.createElement(t,null,'"',i,'"')," has been"," ",e.createElement(t,{operation:"MOVED_UP"},"moved up")," ","in priority in"," ",e.createElement(t,null,'"',n.after?.name,'"')))}),Object.entries(O).map(([c,r])=>e.createElement(p,{key:c},r.operation==="ADDED"&&r.after&&e.createElement(o,null,"Member ",e.createElement(t,null,'"',r.after,'"')," has been"," ",e.createElement(t,{operation:"ADDED"},"added")," to"," ",e.createElement(t,null,'"',n.after?.name,'"')),r.operation==="REMOVED"&&r.before&&e.createElement(o,null,"Member ",e.createElement(t,null,'"',r.before,'"')," has been"," ",e.createElement(t,{operation:"REMOVED"},"removed")," from"," ",e.createElement(t,null,'"',n.after?.name,'"'))))))))};export{B as DiffSummary};
2
+ //# sourceMappingURL=DiffSummary.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{shiftDiffArrayIndexes as t}from"./utils.esm.js";const i=(n,o)=>{if(n==="*")return o==="*"?{"*":{operation:"UNCHANGED",after:"*",before:"*",indexAfter:0,indexBefore:0}}:{"*":{operation:"REMOVED",after:null,before:"*",indexAfter:-1,indexBefore:0},...Object.fromEntries(o.map((e,r)=>[e,{operation:"ADDED",after:e,before:null,indexAfter:r,indexBefore:-1}]))};if(o==="*")return{"*":{operation:"ADDED",after:"*",before:null,indexAfter:0,indexBefore:-1},...Object.fromEntries(n.map((e,r)=>[e,{operation:"REMOVED",after:null,before:e,indexAfter:-1,indexBefore:r}]))};const f=Object.fromEntries(o.map((e,r)=>[e,{operation:"ADDED",after:e,before:null,indexAfter:r,indexBefore:-1}]));for(let e=0;e<n.length;e++){const r=n[e];f[r]?(f[r].before=r,f[r].indexBefore=e,f[r].operation="UNCHANGED"):f[r]={operation:"REMOVED",after:null,before:r,indexAfter:-1,indexBefore:e}}return t(f,e=>e)};export{i as getMembersDiff};
2
+ //# sourceMappingURL=getMembersDiff.esm.js.map
@@ -0,0 +1,2 @@
1
+ const s=(e,r)=>{const t={resolutionStrategy:{operation:"UNCHANGED",before:e?.resolutionStrategy,after:r?.resolutionStrategy}};for(const n of Object.keys(t)){const o=n;t[o].before!==t[o].after&&(t[o].operation="CHANGED")}return t};export{s as getOptionsDiff};
2
+ //# sourceMappingURL=getOptionsDiff.esm.js.map
@@ -0,0 +1,2 @@
1
+ import d from"lodash/isEqual";import m from"lodash/keyBy";import{shiftDiffArrayIndexes as s}from"./utils.esm.js";const p=(i,t)=>{const f=m(t,"id"),r=Object.fromEntries(t.map((o,e)=>[o.id,{operation:"ADDED",indexAfter:e,indexBefore:-1,after:o,before:null}]));for(let o=0;o<i.length;o++){const e=i[o];if(r[e.id]){const n=!d(e,f[e.id]);r[e.id].before=e,r[e.id].indexBefore=o,r[e.id].operation=n?"CHANGED":"UNCHANGED"}else r[e.id]={operation:"REMOVED",after:null,before:e,indexAfter:-1,indexBefore:o}}return s(r,o=>o)};export{p as getPermissionsDiff};
2
+ //# sourceMappingURL=getPermissionsDiff.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{getOptionsDiff as i}from"./getOptionsDiff.esm.js";import{getRolesDiff as p}from"./getRolesDiff.esm.js";const l=(o,e)=>{const r=p(o?.roles||[],e.roles||[]),t=i(o?.options,e.options),n=o?.name!==e.name,s=Object.values(t).some(({operation:f})=>f!=="UNCHANGED");return{policy:{operation:n||s?"CHANGED":"UNCHANGED",before:o,after:e},roles:r,options:t}};export{l as getPolicyDiff};
2
+ //# sourceMappingURL=getPolicyDiff.esm.js.map
@@ -0,0 +1,2 @@
1
+ import A from"lodash/keyBy";import{getMembersDiff as m}from"./getMembersDiff.esm.js";import{getPermissionsDiff as n}from"./getPermissionsDiff.esm.js";import{shiftDiffArrayIndexes as E}from"./utils.esm.js";const c=(t=[],f=[])=>{const p=A(f,"id"),i=Object.fromEntries(f.map((r,e)=>[r.id,{role:{operation:"ADDED",indexAfter:e,indexBefore:-1,after:r,before:null},members:m([],r.members),permissions:n([],r.permissions)}]));for(let r=0;r<t.length;r++){const e=t[r];if(p[e.id]){const o=p[e.id],d=m(e.members,o.members),l=n(e.permissions,o.permissions),b=Object.values(l).some(({operation:s})=>s!=="UNCHANGED"),a=Object.values(d).some(({operation:s})=>s!=="UNCHANGED"),D=e.name!==o.name||b||a;i[e.id].role.before=e,i[e.id].role.indexBefore=r,i[e.id].role.operation=D?"CHANGED":"UNCHANGED",i[e.id].members=d,i[e.id].permissions=l}else i[e.id]={role:{operation:"REMOVED",after:null,before:e,indexAfter:-1,indexBefore:r},members:m(e.members,[]),permissions:n(e.permissions,[])}}return E(i,({role:r})=>r)};export{c as getRolesDiff};
2
+ //# sourceMappingURL=getRolesDiff.esm.js.map
@@ -0,0 +1,2 @@
1
+ const D=(i,n)=>{const r=Object.entries(i);for(const[,t]of r){const e=n(t);for(const[,f]of r){const o=n(f);o.operation!=="ADDED"&&o.operation!=="REMOVED"&&(e.operation==="ADDED"&&e.indexAfter<o.indexAfter?o.indexBefore+=1:e.operation==="REMOVED"&&e.indexBefore<o.indexBefore&&(o.indexBefore-=1))}}for(const[,t]of r){const e=n(t);e.operation==="UNCHANGED"&&e.indexAfter!==e.indexBefore&&(e.operation=e.indexAfter>e.indexBefore?"MOVED_DOWN":"MOVED_UP")}return i};export{D as shiftDiffArrayIndexes};
2
+ //# sourceMappingURL=utils.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{useApi as f}from"@backstage/core-plugin-api";import{useMemo as m}from"react";import p from"react-use/lib/useAsync";import{rbacApiRef as c}from"../../api.esm.js";import{getPolicyDiff as l}from"./getPolicyDiff/getPolicyDiff.esm.js";const u=r=>{const o=f(c),{value:i,loading:t,error:e}=p(()=>o.getActivePolicy(),[o]);return m(()=>r&&!t&&!e?l(i,r):null,[i,r,t,e])};export{u as usePolicyDiff};
2
+ //# sourceMappingURL=usePolicyDiff.esm.js.map
@@ -0,0 +1,2 @@
1
+ const t=(e,r)=>{switch(r){case"ADDED":return e.palette.success.main;case"REMOVED":return e.palette.errorText;case"CHANGED":return e.palette.infoText;case"MOVED_UP":case"MOVED_DOWN":return e.palette.infoText;case"UNCHANGED":default:return e.palette.text.primary}},a=e=>{switch(e){case"ADDED":return"success";case"REMOVED":return"error";case"CHANGED":return"info";case"MOVED_UP":case"MOVED_DOWN":return"info";case"UNCHANGED":default:return"info"}},D=e=>{switch(e){case"ADDED":return"New";case"REMOVED":return"Removed";case"CHANGED":return"Changed";case"MOVED_UP":return"Moved up";case"MOVED_DOWN":return"Moved down";case"UNCHANGED":default:return"No changes"}};export{t as getColorFromDiffOperation,a as getSeverityFromDiffOperation,D as getTextFromDiffOperation};
2
+ //# sourceMappingURL=utils.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as y,IconButton as E}from"@material-ui/core";import v from"@material-ui/icons/Check";import S from"@material-ui/icons/Edit";import e,{useState as p,useRef as k,useEffect as C,useLayoutEffect as W}from"react";const w=y(t=>({container:{display:"flex",position:"relative",alignItems:"center",gap:t.spacing(1),flexShrink:1,maxWidth:"100%",minWidth:0},input:({invalid:r})=>({boxSizing:"content-box",display:"block",maxWidth:"100%",padding:0,borderWidth:2,borderStyle:"solid",borderColor:r?t.palette.error.main:"transparent",borderRadius:t.shape.borderRadius,backgroundColor:"transparent",color:t.palette.textContrast,fontFamily:"inherit",fontSize:"inherit",lineHeight:"inherit",fontWeight:"inherit",textOverflow:"ellipsis"}),hiddenSpan:{position:"absolute",top:0,left:0,borderWidth:1,whiteSpace:"pre",opacity:0,pointerEvents:"none"}}));function R({invalid:t,name:r,value:a,onTextChange:f}){const o=w({invalid:t}),[u,s]=p(!1),[c,b]=p(null),n=k(null),[i,d]=p(a);C(()=>{d(a)},[a]),W(()=>{n.current&&c&&n.current.style.setProperty("width",`max(${c.getBoundingClientRect().width}px, 3ch)`)},[c,i]);const g=()=>{s(!1),d(a)},m=()=>{s(!1),f?.(i)},h=()=>{u?m():(s(!0),n.current?.focus())},x=l=>{l.key==="Enter"&&n.current?.blur(),l.key==="Escape"&&g()};return e.createElement(e.Fragment,null,e.createElement("div",{className:o.container},e.createElement("input",{"aria-label":r,className:o.input,name:r,ref:n,onChange:l=>d(l.target.value),onFocus:h,onBlur:m,onKeyDown:x,value:i}),e.createElement("span",{"aria-hidden":"true",className:o.hiddenSpan,ref:b},i),e.createElement(E,{onClick:h,size:"small"},u?e.createElement(v,{"aria-label":"Save title"}):e.createElement(S,{"aria-label":"Edit title"}))))}export{R as default};
2
+ //# sourceMappingURL=EditableInput.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Progress as l,ErrorPanel as n,ContentHeader as c}from"@backstage/core-components";import{Grid as p}from"@material-ui/core";import e from"react";import a from"react-use/lib/useMount";import{PageWrapper as s}from"../Layout/PageWrapper.esm.js";import{usePoliciesContext as f}from"../Policies/PoliciesProvider.esm.js";import{useFetchPolicies as E}from"../Policies/useFetchPolicies.esm.js";import{PolicyImportButton as P}from"../Policy/PolicyImportButton.esm.js";import u from"./HomePageContent.esm.js";import g from"./HomePageEmptyState.esm.js";function d(){const{policies:t}=f(),{loading:m,error:o,fetchPolicies:i}=E();a(()=>{t||i()});let r;return m?r=e.createElement(p,{item:!0,xs:12},e.createElement(l,null)):o?r=e.createElement(n,{error:o}):!t||t.length===0?r=e.createElement(g,null):r=e.createElement(u,{policies:t}),e.createElement(s,{pages:void 0,header:e.createElement(c,{title:"RBAC Policies"},e.createElement(P,null))},r)}export{d as HomePage};
2
+ //# sourceMappingURL=HomePage.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Grid as o,Button as a}from"@material-ui/core";import e from"react";import{useNavigate as f}from"react-router-dom";import{PoliciesTable as E}from"../Policies/PoliciesTable.esm.js";import{PolicyCard as c}from"../Policy/PolicyCard.esm.js";import{PolicyProvider as y}from"../Policy/PolicyProvider.esm.js";import{PolicyPublishButton as P}from"../Policy/PolicyPublishButton.esm.js";import{useDeleteDraftPolicy as v}from"../Policy/useDeleteDraftPolicy.esm.js";import{useDuplicatePolicy as D}from"../Policy/useDuplicatePolicy.esm.js";function g({policies:i}){const t=i.find(l=>l.status==="draft"),r=i.find(l=>l.status==="active"),[n,m]=D(),[s,d]=v(t),p=f(),u=b(i);return e.createElement(o,{container:!0,spacing:4},r?e.createElement(o,{item:!0,xs:12,md:6},e.createElement(c,{policy:r,to:`./versions/${r.id}`,actions:e.createElement(a,{color:"primary",disabled:n.loading||!!t,onClick:()=>m(r)},"Duplicate")})):null,t?e.createElement(o,{item:!0,xs:12,md:6},e.createElement(c,{policy:t,to:`./versions/${t.id}`,actions:e.createElement(e.Fragment,null,e.createElement(a,{onClick:()=>p(`versions/${t.id}`),color:"primary"},"Edit"),e.createElement(a,{color:"primary",disabled:s.loading,onClick:d},"Delete Draft"),e.createElement(y,{policyId:t.id},e.createElement(P,{color:"primary"})))})):null,e.createElement(o,{item:!0,xs:12},e.createElement(E,{data:u,canDuplicate:!t})))}function b(i){return i.filter(({status:t})=>t==="inactive")}export{g as default};
2
+ //# sourceMappingURL=HomePageContent.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{EmptyState as l}from"@backstage/core-components";import{useApi as c}from"@backstage/core-plugin-api";import{makeStyles as m,Card as s,CardContent as p,Box as a,Button as u}from"@material-ui/core";import e,{useEffect as d}from"react";import{useNavigate as f}from"react-router-dom";import y from"react-use/lib/useAsyncFn";import{rbacApiRef as b}from"../../api.esm.js";const g=m(o=>({cardContent:{padding:o.spacing(6,3),"& > *":{background:"transparent"}}}));function v(){const o=g(),n=c(b),r=f(),[t,i]=y(async()=>n.createDraft({roles:[],options:{resolutionStrategy:"any-allow"}}),[n]);return d(()=>{t.value&&r(`./versions/${t.value.id}`)},[r,t.value]),e.createElement(s,null,e.createElement(p,{className:o.cardContent},e.createElement(l,{missing:"content",title:"No policy configured",description:e.createElement(e.Fragment,null,e.createElement(a,{component:"span",display:"block",pb:2},"Until you've configured your policy, authorization will be denied for all permissions."),e.createElement(a,{component:"span",display:"block"},"Click the button below to create the first version of your policy.")),action:e.createElement(u,{variant:"contained",color:"primary",disabled:t.loading,onClick:i},"New version")})))}export{v as default};
2
+ //# sourceMappingURL=HomePageEmptyState.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Breadcrumbs as p,Link as o}from"@backstage/core-components";import{useRouteRef as n}from"@backstage/core-plugin-api";import{makeStyles as i,Typography as u}from"@material-ui/core";import e from"react";import{rootRouteRef as f}from"../../routes.esm.js";const l=i(r=>({breadcrumbs:{marginBottom:r.spacing(4)}}));function b({pages:r}){const a=n(f),c=l();return e.createElement(p,{className:c.breadcrumbs},e.createElement(o,{to:a()},"Home"),r.map(({title:m,path:t},s)=>t?e.createElement(o,{to:t,key:t,relative:"path"},m):e.createElement(u,{key:`${s}`},m)))}export{b as Breadcrumbs};
2
+ //# sourceMappingURL=Breadcrumbs.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as m}from"@material-ui/core";import r from"react";const o=m(()=>({emptyStateImage:{width:"95%",zIndex:2,position:"relative",left:"50%",top:"50%",transform:"translate(-50%, 15%)"}}));function n({src:t,alt:e}){const a=o();return r.createElement("img",{src:t,className:`${a.emptyStateImage} `,alt:e})}export{n as EmptyStateImageWrapper};
2
+ //# sourceMappingURL=EmptyStateImageWrapper.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Page as o,Header as i,Content as l}from"@backstage/core-components";import{Container as c,Grid as n}from"@material-ui/core";import{SpotifyLicenseBanner as m}from"@spotify/backstage-plugin-core";import e from"react";import{Breadcrumbs as p}from"./Breadcrumbs.esm.js";function s({children:r,header:a,pages:t}){return e.createElement(o,{themeId:"tool"},e.createElement(m,{backend:"rbac",invalidLicenseMessage:"Your existing policy will continue to apply, but you will be unable to make any changes until you enter a valid license."}),e.createElement(i,{title:"Role Based Access Control"}),e.createElement(l,null,e.createElement(c,{maxWidth:"lg"},e.createElement(n,{container:!0,spacing:4},e.createElement(n,{item:!0,xs:12},t&&e.createElement(p,{pages:t}),a),r))))}export{s as PageWrapper};
2
+ //# sourceMappingURL=PageWrapper.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as o,Typography as a}from"@material-ui/core";import n from"react";const t=o(e=>({titleWrapper:{display:"flex",alignItems:"center",gap:e.spacing(2)}}));function p({children:e}){const r=t();return n.createElement(a,{noWrap:!0,variant:"h4",component:"h2",color:"textSecondary",className:r.titleWrapper},e)}export{p as Title,t as useStyles};
2
+ //# sourceMappingURL=Title.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{useApi as i}from"@backstage/core-plugin-api";import m,{createContext as n,useContext as s}from"react";import p from"react-use/lib/useAsync";import{rbacApiRef as a}from"../../api.esm.js";const e=n({loading:!1}),c=({children:o})=>{const r=i(a),t=p(async()=>await r.searchMembers({query:""}),[r]);return m.createElement(e.Provider,{value:t},o)},u=()=>s(e);export{e as MemberOptionsContext,c as MemberOptionsProvider,u as useMemberOptions};
2
+ //# sourceMappingURL=MemberOptionsProvider.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{parseEntityRef as u,DEFAULT_NAMESPACE as A}from"@backstage/catalog-model";import{humanizeEntityRef as C}from"@backstage/plugin-catalog-react";import{makeStyles as S,Box as k,Checkbox as P,TextField as F,CircularProgress as M}from"@material-ui/core";import{Autocomplete as O}from"@material-ui/lab";import t,{useState as L,useReducer as N,useEffect as w}from"react";import{MembersAutocompleteListBox as B}from"./MembersAutocompleteListBox.esm.js";const I=S({autocomplete:{display:"flex",flex:1}});function T({members:o,options:r,namespaceOptions:n,loading:a=!1,disabled:f=!1,isMultiNamespaces:s=!1,onTextChange:i,onToggleMember:E,onChange:b}){const[c,l]=L(!1),g=I(),[h,y]=N(e=>e+1,0),x=(e,p)=>{p&&(E(p),y())};w(()=>{c&&i("")},[c,i]);const R=s?n.concat(r?.members||[]):r?.members||[];return t.createElement(k,{width:250},t.createElement(O,{key:`${h}`,open:c,onOpen:()=>{l(!0)},onClose:()=>{l(!1)},onChange:x,getOptionLabel:m,groupBy:$,ListboxComponent:B,renderOption:e=>t.createElement(t.Fragment,null,t.createElement(P,{id:`checkbox-${e.entityRef}`,checked:o.includes(e.entityRef),color:"primary"}),t.createElement("label",{htmlFor:`checkbox-${e.entityRef}`},s?m(e,!1):m(e))),options:R,openOnFocus:!0,disabled:f,loading:a,className:g.autocomplete,renderInput:e=>t.createElement(F,{...e,label:s?"Select members":"Select specific users/groups",variant:"standard",onChange:b,InputProps:{...e.InputProps,endAdornment:t.createElement(t.Fragment,null,a?t.createElement(M,{color:"inherit",size:20}):null,e.InputProps.endAdornment)}})}))}function m(o,r=!0){const n=u(o.entityRef);return n.name==="*"?n.namespace:C({...n,name:o.name??n.name},{defaultKind:n.kind,defaultNamespace:r?A:!1})}const d={user:"USERS",group:"GROUPS",namespace:"NAMESPACES"};function $(o){const{name:r,kind:n}=u(o.entityRef),a=r==="*"?"namespace":n;if(!d[a])throw new Error(`Group '${a}' is not supported for members in a policy`);return d[a]}export{T as MembersAutocomplete,m as getLabel};
2
+ //# sourceMappingURL=MembersAutocomplete.esm.js.map
@@ -0,0 +1,2 @@
1
+ import r,{useMemo as f,Children as s,isValidElement as t}from"react";import{List as u}from"react-virtualized";const w=r.forwardRef(function({children:n,role:h,...p},d){const l=f(()=>{const e=[];return s.forEach(n,o=>{if(t(o)){const c=o.props.children[0];t(c)&&e.push(c);const i=o.props.children[1];if(t(i)){const a=s.toArray(i.props.children).filter(t);e.push(...a)}}}),e},[n]),m=l.length;return r.createElement("div",{ref:d},r.createElement("ul",{...p},r.createElement(u,{height:250,width:250,rowHeight:54,overscanCount:5,rowCount:m,rowRenderer:e=>r.cloneElement(l[e.index],{style:{...e.style,whiteSpace:"nowrap"}}),role:h})))});export{w as MembersAutocompleteListBox};
2
+ //# sourceMappingURL=MembersAutocompleteListBox.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{parseEntityRef as S}from"@backstage/catalog-model";import{useApi as E}from"@backstage/core-plugin-api";import{catalogApiRef as k}from"@backstage/plugin-catalog-react";import{makeStyles as F,debounce as O,Table as j,TableHead as B,TableRow as D,TableCell as m,TableBody as H}from"@material-ui/core";import t,{useState as P,useRef as U,useMemo as V}from"react";import C from"react-use/lib/useAsync";import{rbacApiRef as q}from"../../api.esm.js";import{useMemberOptions as z}from"./MemberOptionsProvider.esm.js";import{MembersAutocomplete as G}from"./MembersAutocomplete.esm.js";import J from"./MembersTableBody.esm.js";const K=F(()=>({header:{display:"flex",flexDirection:"row",justifyContent:"space-between",paddingLeft:"1rem",paddingRight:"1rem",gap:"1rem"},actionCol:{width:48},typeIconCol:{paddingRight:"0.4rem"},nameCol:{paddingLeft:0}}));function Q({diff:s,policyId:n,role:a,onToggleMember:R,readonly:c=!1,debounceTime:p=1e3}){const h=E(q),f=E(k),o=K(),T=a.members==="*",[w,d]=P(""),{current:l}=U({}),u=e=>{l[e.entityRef]=e,R(e.entityRef)},b=e=>{if(l[e])return l[e];const r=S(e);return{entityRef:e,type:r.kind.toLowerCase(),name:r.name??e}},{value:M,loading:N}=z(),{loading:g,value:i}=C(async()=>{const e=await f.getEntityFacets({facets:["metadata.namespace"]}).then(r=>r.facets["metadata.namespace"].map(I=>I.value));return W(e)},[f]),y=i?i?.length>1:!1,L=i?i.filter(e=>e.entityRef.toLowerCase().includes(w)):[],v=V(()=>O(e=>{d(e.target.value.toLowerCase())},p),[d,p]),{loading:A,error:x}=C(async()=>{a.members==="*"||a.members.length===0||(await h.getPolicy(n)).roles.find(e=>e.id===a.id)===void 0||a.members.forEach(e=>{const r=b(e);l[r.entityRef]=r})},[n,T]);return t.createElement(t.Fragment,null,t.createElement("div",{className:o.header},t.createElement("h2",null,"Members"),t.createElement(G,{onToggleMember:u,members:a.members,disabled:c,options:M,namespaceOptions:L,isMultiNamespaces:y,loading:N||g,onTextChange:d,onChange:v})),t.createElement(j,{"data-testid":"membersTable"},t.createElement(B,null,t.createElement(D,null,t.createElement(m,{className:o.typeIconCol}),t.createElement(m,{className:o.nameCol},"Name"),t.createElement(m,null,"Type"),t.createElement(m,null),!c&&t.createElement(m,{className:o.actionCol}))),t.createElement(H,null,t.createElement(J,{diff:s,loading:A||g,isMultiNamespaces:y,error:x,members:Array.isArray(a.members)?a.members.map(b):a.members,onToggleMember:u,readonly:c}))))}function W(s){return s.map(n=>({name:"*",type:"user",entityRef:`user:${n}/*`})).sort((n,a)=>n.entityRef.toLowerCase().localeCompare(a.entityRef.toLowerCase()))}export{Q as MembersTable};
2
+ //# sourceMappingURL=MembersTable.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{parseEntityRef as s}from"@backstage/catalog-model";import{Progress as R}from"@backstage/core-components";import{makeStyles as b,TableRow as i,TableCell as a,IconButton as N}from"@material-ui/core";import h from"@material-ui/icons/Delete";import S from"@material-ui/icons/Group";import k from"@material-ui/icons/GroupWork";import B from"@material-ui/icons/Person";import e from"react";import{DiffBadge as u}from"../Diffing/DiffBadge.esm.js";import{getLabel as y}from"./MembersAutocomplete.esm.js";const M=b(m=>({actionCol:{width:48},typeIconCol:{paddingRight:"0.4rem"},nameCol:{paddingLeft:0},typeIcon:{color:m.palette.grey[500]}}));function T({diff:m,loading:g,isMultiNamespaces:l,members:f,error:E,onToggleMember:d,readonly:c=!1}){const r=M();if(g)return e.createElement(i,null,e.createElement(a,{scope:"row",colSpan:c?4:5},e.createElement(R,null)));if(E&&E.message,f==="*")return e.createElement(i,null,e.createElement(a,{colSpan:2,height:80},"All"),e.createElement(a,{colSpan:c?2:3},e.createElement(u,{operation:m?.members["*"].operation})));if(f.length===0)return e.createElement(i,null,e.createElement(a,{scope:"row",colSpan:c?4:5},"Select users or groups using the drop-down menu above."));const C=f.sort((t,n)=>{let o=0;l&&n.name==="*"&&t.name!=="*"?o=1:l&&t.name==="*"&&n.name!=="*"&&(o=-1);const p=t.type.localeCompare(n.type),w=s(t.entityRef).namespace.localeCompare(s(n.entityRef).namespace),I=s(t.entityRef).name.localeCompare(s(n.entityRef).name);return o||p||w||I});return e.createElement(e.Fragment,null,C.map(t=>{const{name:n,type:o,entityRef:p}=t;return e.createElement(i,{key:p},e.createElement(a,{className:r.typeIconCol},o==="group"&&e.createElement(S,{className:r.typeIcon})||l&&n==="*"&&e.createElement(k,{className:r.typeIcon})||e.createElement(B,{className:r.typeIcon})),e.createElement(a,{scope:"row",className:r.nameCol},(l?y(t,!1):y(t))??"Unknown"),e.createElement(a,{scope:"row"},n==="*"&&l?"namespace":o),e.createElement(a,null,n&&e.createElement(u,{operation:m?.members[p].operation})),!c&&e.createElement(a,{scope:"row",className:r.actionCol},e.createElement(N,{"aria-label":"Remove member",onClick:()=>d(t),size:"small"},e.createElement(h,null))))}))}export{T as default};
2
+ //# sourceMappingURL=MembersTableBody.esm.js.map
@@ -0,0 +1,2 @@
1
+ import e,{useMemo as a}from"react";const l=({name:t})=>{const m=a(()=>t.includes(".")?t.split(/(\.)/g).flatMap(n=>[n,e.createElement("wbr",null)]):[t],[t]);return e.createElement(e.Fragment,null,m.map((n,r)=>e.createElement(e.Fragment,{key:r},n)))};export{l as PermissionName};
2
+ //# sourceMappingURL=PermissionName.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{useApi as a,configApiRef as g,alertApiRef as y}from"@backstage/core-plugin-api";import{isResourcePermission as h}from"@backstage/plugin-permission-common";import{forEach as P,mapValues as A,groupBy as R,uniq as T}from"lodash";import v,{createContext as M,useState as b,useCallback as x,useMemo as w,useContext as C}from"react";import I from"react-use/lib/useAsync";import{rbacApiRef as S}from"../../api.esm.js";const l=M(null),L=({children:e})=>{const t=a(g),r=a(S),n=a(y),[s,o]=b(null),c=x(async()=>{if(!s){const p=await r.fetchAllPermissionMetadata(t.getOptionalStringArray("permission.permissionedPlugins")??[]),m=O(p.rules);P(m,u=>{u.length!==1&&n.post({message:`The plugin(s) ${u.slice(1).join(", ")} expose rules which are conflicting with rules exposed by the ${u[0]} plugin. These rules will not be available for use. Please contact RBAC support if you need assistance resolving this issue.`,severity:"error"})});const d=j(p,m);return o(d),d}return s},[n,s,r,t]);return v.createElement(l.Provider,{value:w(()=>({getMetadata:c}),[c])},e)};function i(){const e=C(l),{value:t,loading:r}=I(async()=>e?.getMetadata(),[e]);return{metadata:t,isLoading:r}}function $(){const{metadata:e}=i();return e?.rules??null}function B(){const{metadata:e,isLoading:t}=i();return{permissions:e?.permissions??null,isLoading:t}}function f(){const{metadata:e}=i();return e?[...new Set(e.permissions.filter(t=>h(t)).map(({resourceType:t})=>t))]:null}function E(){const{metadata:e}=i(),t=f();return!e||!t?null:t.reduce((r,n)=>{const s=e.rules.find(o=>o.resourceType===n);return s&&(r[n]={pluginId:s.pluginId}),r},{})}function O(e){return A(R(e,"resourceType"),t=>T(t.map(({pluginId:r})=>r)))}function j(e,t){return{...e,rules:e.rules.filter(({resourceType:r,pluginId:n})=>{const s=t[r];return n===s[0]})}}export{L as PermissionMetadataProvider,l as PermissionsMetadataContext,$ as useAggregatedRules,i as usePermissionMetadata,B as usePermissions,E as useResourceTypeInfo,f as useResourceTypeOptions};
2
+ //# sourceMappingURL=PermissionsMetadataContext.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{EmptyState as y}from"@backstage/core-components";import{Box as h,Typography as s,Button as c,Table as g,TableHead as b,TableRow as l,TableCell as t,TableBody as w,ButtonBase as C,IconButton as v}from"@material-ui/core";import B from"@material-ui/icons/Add";import R from"@material-ui/icons/Delete";import e from"react";import T from"../../images/no-permissions.svg";import{ConfirmationDialog as k}from"../ConfirmationDialog/ConfirmationDialog.esm.js";import{DiffBadge as D}from"../Diffing/DiffBadge.esm.js";import{EmptyStateImageWrapper as I}from"../Layout/EmptyStateImageWrapper.esm.js";import{ReorderControls as x}from"../ReorderControls/ReorderControls.esm.js";import{ReorderInfo as N}from"../ReorderControls/ReorderInfo.esm.js";import{getMatchBy as P,getDecisionDescription as S}from"./utils.esm.js";const A="Use the arrows to change the order in which permission decisions are evaluated.";function M({diff:p,permissions:n,onReorderPermissions:E,onNewPermissionClick:a,onOpenPermission:d,onRemovePermissionClick:u,anyAllow:m,readonly:r=!1}){return e.createElement(e.Fragment,null,e.createElement(h,{display:"flex",justifyContent:"space-between",padding:2},e.createElement(s,{variant:"h5"},"Permission Decisions"),!r&&n.length!==0&&e.createElement(c,{color:"primary",variant:"outlined",startIcon:e.createElement(B,null),onClick:a},"New")),e.createElement(g,{"data-testid":"permissionsTable"},e.createElement(b,null,e.createElement(l,null,!r&&!m&&e.createElement(t,{style:{width:0}},e.createElement(N,{helpText:A})),e.createElement(t,null,"Match by"),e.createElement(t,null,"Decision"),e.createElement(t,null),!r&&e.createElement(t,null))),e.createElement(w,null,n.length===0&&e.createElement(l,null,e.createElement(t,{colSpan:5},e.createElement(y,{title:"No permission decisions set",description:"Click the button below to create your first permission.",missing:{customImage:e.createElement(I,{src:T,alt:"No permission placeholder"})},action:e.createElement(c,{variant:"contained",color:"primary",onClick:a},"New permission decision")}))),n.map((i,o)=>e.createElement(l,{key:o},!r&&!m&&e.createElement(t,null,e.createElement(x,{array:n,index:o,onReorder:E})),e.createElement(t,null,e.createElement(C,{onClick:()=>d(o)},e.createElement(s,{variant:"body2",color:"primary"},P(i)))),e.createElement(t,null,S(i)),e.createElement(t,null,e.createElement(D,{operation:p?.permissions[i.id].operation})),!r&&e.createElement(t,{align:"right"},e.createElement(k,{message:"Are you sure you want to remove this permission decision?",onConfirm:()=>u(o),title:"Remove?"},f=>e.createElement(v,{...f,"aria-label":"Remove permission decision",size:"small"},e.createElement(R,null)))))))))}export{M as default};
2
+ //# sourceMappingURL=PermissionsTable.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{isConditionalDecision as o}from"@spotify/backstage-plugin-rbac-common";function e(n){return o(n.decision)?"Conditional":{allow:"Allow",deny:"Deny"}[n.decision]??"Unknown"}function c(n){if(n.match==="*")return"All";if(n.match.name)return n.match.name;const i=[];return n.match.resourceType&&i.push(n.match.resourceType),n.match.actions?.length&&i.push(n.match.actions.join(", ")),i.join(" | ")}export{e as getDecisionDescription,c as getMatchBy};
2
+ //# sourceMappingURL=utils.esm.js.map
@@ -0,0 +1,2 @@
1
+ import d,{createContext as p,useState as v,useCallback as l,useMemo as f,useContext as y}from"react";const a=p({hasDraftPolicy:!1,policies:void 0,setPolicies:()=>{},setPolicy:()=>{},getPolicy:()=>{},removePolicy:()=>{}}),m=()=>y(a);function x({children:t,initialState:s={policies:void 0,cache:{}}}){const[i,o]=v(s),r=l(e=>{o(c=>({...c,policies:e,cache:u(c.cache,e)}))},[]),n=l(e=>i.cache[e],[i.cache]),P=l(e=>o(c=>({...c,cache:{...c.cache,[e]:void 0},policies:void 0})),[]),h=l(e=>o(c=>({...c,policies:void 0,cache:u(c.cache,[e])})),[]);return d.createElement(a.Provider,{value:f(()=>({hasDraftPolicy:i.policies?.some(({status:e})=>e==="draft")||!1,policies:i.policies,setPolicies:r,setPolicy:h,getPolicy:n,removePolicy:P}),[i.policies,r,h,n,P])},t)}function u(t,s){if(!s)return t;const i={...t};return s.forEach(o=>{i[o.id]=o}),i}export{a as PoliciesContext,x as PoliciesProvider,m as usePoliciesContext};
2
+ //# sourceMappingURL=PoliciesProvider.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Table as y,Link as S}from"@backstage/core-components";import E from"@material-ui/icons/FilterNone";import C from"@material-ui/icons/Publish";import{DateTime as c}from"luxon";import t,{useState as m}from"react";import{assertNever as T}from"../../utils/assert.esm.js";import{PolicyPublishConfirmationDialog as A}from"../Policy/PolicyPublishConfirmationDialog.esm.js";import{PolicyPublishSuccessDialog as I}from"../Policy/PolicyPublishSuccessDialog.esm.js";import{useDuplicatePolicy as O}from"../Policy/useDuplicatePolicy.esm.js";import{usePublishPolicy as k}from"../Policy/usePublishPolicy.esm.js";import{useFetchPolicies as N}from"./useFetchPolicies.esm.js";const _=[{title:"Name",field:"name",render:e=>t.createElement(S,{to:`versions/${e.id}`},e.name)},{title:"Status",field:"status",render:e=>{switch(e.status){case"active":return"Active";case"draft":return"Draft";case"inactive":return"Inactive";default:return T(e.status)}}},{title:"Publish date",field:"lastPublishedAt",render:e=>e.lastPublishedAt?c.fromISO(e.lastPublishedAt).toLocaleString(c.DATETIME_MED_WITH_SECONDS):"",type:"datetime",defaultSort:"desc"},{title:"Published by",field:"lastPublishedBy"}];function w(e){const u=e.data.length>3,{fetchPolicies:d}=N(),[{loading:p},f]=O(),[{loading:b,value:s},P]=k(),[o,l]=m(void 0),[h,a]=m(!1),g=()=>{l(void 0),d()},n=o?.id===s?.id?s:void 0,v=[i=>{const{tableData:D,...r}=i;return{icon:C,tooltip:"Republish",onClick:()=>{l(r),a(!0)},disabled:b}},i=>{const{tableData:D,...r}=i;return{icon:E,tooltip:"Duplicate",disabled:p||!e.canDuplicate,onClick:()=>f(r)}}];return t.createElement(t.Fragment,null,t.createElement(y,{title:"Previous Versions",columns:_,data:e.data,options:{paging:u,pageSize:3,pageSizeOptions:[3,5,10,20],actionsColumnIndex:-1,loadingType:"linear"},actions:v}),o&&t.createElement(A,{open:h,onPublish:i=>{P(o,i),a(!1)},onClose:()=>{l(void 0),a(!1)},policy:o}),n&&t.createElement(I,{isOpen:!0,policy:n,onClose:g}))}export{w as PoliciesTable};
2
+ //# sourceMappingURL=PoliciesTable.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{useApi as m}from"@backstage/core-plugin-api";import{useCallback as a}from"react";import n from"react-use/lib/useAsyncFn";import{rbacApiRef as p}from"../../api.esm.js";import{usePoliciesContext as f}from"./PoliciesProvider.esm.js";const g=()=>{const i=m(p),{setPolicies:e,policies:o}=f(),[{loading:r,error:s},t]=n(()=>i.getPolicies(),[i],o?{loading:!1,value:{items:o,totalItems:o.length}}:{loading:!0}),l=a(async()=>{const c=await t();e(c.items)},[t,e]);return{loading:r,error:s,fetchPolicies:l}};export{g as useFetchPolicies};
2
+ //# sourceMappingURL=useFetchPolicies.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{EmptyState as o}from"@backstage/core-components";import{makeStyles as m,Card as c,CardHeader as s,CardContent as d,Button as p}from"@material-ui/core";import e from"react";import{useNavigate as f}from"react-router-dom";import g from"../../images/no-roles.svg";import{EmptyStateImageWrapper as u}from"../Layout/EmptyStateImageWrapper.esm.js";import{usePolicyContext as C}from"./PolicyProvider.esm.js";const y=m(t=>({cardHeader:{padding:t.spacing(3,3),borderBottom:`1px solid ${t.palette.border}`},cardContent:{padding:t.spacing(6,3),"& > *":{background:"transparent"}},emptyStateImage:{width:"95%",zIndex:2,position:"relative",left:"50%",top:"50%",transform:"translate(-50%, 15%)"}}));function E({readonly:t}){const r=y(),a=f(),{createNewRole:n}=C(),l=()=>{const i=n();a(`./roles/${i}`)};return e.createElement(c,null,e.createElement(s,{title:"Roles",className:r.cardHeader}),e.createElement(d,{className:r.cardContent},t?e.createElement(o,{title:"No roles configured",missing:"content"}):e.createElement(o,{title:"No roles yet",description:"Click the button below to create your first role.",missing:{customImage:e.createElement(u,{src:g,alt:"No roles placeholder"})},action:e.createElement(p,{variant:"contained",color:"primary",onClick:()=>l()},"New role")})))}export{E as default};
2
+ //# sourceMappingURL=EmptyRolesCard.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{Link as f}from"@backstage/core-components";import{makeStyles as b,Card as h,CardContent as v,Typography as i,List as C,ListItem as o,ListItemIcon as c,ListItemText as l,Box as m,CardActions as x}from"@material-ui/core";import D from"@material-ui/icons/CalendarToday";import L from"@material-ui/icons/Person";import e from"react";import{DiffSummary as k}from"../Diffing/DiffSummary.esm.js";import{RelativeTime as I}from"../RelativeTime/RelativeTime.esm.js";import{getActivityDescription as S}from"./getActivityDescriptions.esm.js";import{PolicyStatusChip as N}from"./PolicyStatusChip.esm.js";const T=b(t=>({card:a=>({backgroundImage:a.policy.status==="active"?"linear-gradient(256.15deg, #00782A 19.77%, #1DB954 100%)":"linear-gradient(256.15deg, #BDBDBD 19.77%, #EEEEEE 100%)",backgroundPosition:"top",backgroundSize:"100% 8px",backgroundRepeat:"no-repeat",paddingTop:"8px",height:"100%"}),diffSummaryContainer:{backgroundColor:t.palette.background.default,padding:t.spacing(2),borderWidth:"1px",borderStyle:"solid",borderColor:t.palette.divider,borderRadius:t.shape.borderRadius},header:{display:"flex",justifyContent:"space-between",alignItems:"center"},detailsHeader:{...t.typography.body1,paddingTop:t.spacing(2),color:t.palette.text.secondary},activityList:{color:t.palette.text.secondary},activityListItem:{padding:0},actions:{justifyContent:"flex-start"}}));function B(t){const a=T(t),{policy:r,to:s,withChangeSummary:d}=t,n=`${r.name} ${r.status==="draft"?"- Draft":""}`,p={created:"Created: ",published:"Published: ",updated:"Updated: "},u={created:"Created by ",published:"Published by ",updated:"Updated by "},{activityDateText:y,activityUser:E,timestamp:g}=S(r,p,u);return e.createElement(h,{className:a.card},e.createElement(v,null,e.createElement("div",{className:a.header},s?e.createElement(f,{to:`versions/${r.id}`},e.createElement(i,{variant:"h5",component:"h1"},n)):e.createElement(i,{variant:"h5",component:"h1"},n),r.status==="active"?e.createElement(N,{status:"active",size:"small"}):null),r.description?e.createElement(i,{variant:"body1",color:"textSecondary"},'"',r.description,'"'):null,e.createElement(i,{component:"h2",className:a.detailsHeader},"Details"),e.createElement(C,{className:a.activityList},e.createElement(o,{className:a.activityListItem},e.createElement(c,null,e.createElement(D,null)),e.createElement(l,{primary:e.createElement(I,{timestamp:g,description:y})})),e.createElement(o,{className:a.activityListItem},e.createElement(c,null,e.createElement(L,null)),e.createElement(l,{primary:E}))),d&&e.createElement(m,{paddingTop:2},e.createElement(i,{gutterBottom:!0,variant:"subtitle2"},"What's changed"),e.createElement(m,{className:a.diffSummaryContainer},e.createElement(k,{policy:r})))),t.actions?e.createElement(x,{className:a.actions},t.actions):null)}export{B as PolicyCard};
2
+ //# sourceMappingURL=PolicyCard.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as s,Dialog as p,DialogContent as y,Box as n,Typography as l,Button as r}from"@material-ui/core";import d from"@material-ui/icons/ReportProblemOutlined";import e from"react";import{PolicyCard as o}from"./PolicyCard.esm.js";const g=s(t=>({icon:{color:t.palette.warning.main,width:"2rem",height:"2rem"},label:{align:"center",display:"block",marginBottom:t.spacing(1),color:t.palette.text.secondary,fontSize:t.typography.caption.fontSize},policiesContainer:{display:"flex",gap:t.spacing(4),marginTop:t.spacing(4),marginBottom:t.spacing(4)},button:{marginTop:t.spacing(4)}})),f=({localPolicy:t,onSelectLocalPolicy:c,onSelectServerPolicy:i,serverPolicy:m})=>{const a=g();return e.createElement(p,{open:!0,maxWidth:"md"},e.createElement(y,null,e.createElement(n,{display:"flex",flexDirection:"column",gridGap:8},e.createElement(n,{display:"flex",justifyContent:"center"},e.createElement(d,{className:a.icon})),e.createElement(l,{align:"center",variant:"h6"},"There is a conflict with your drafts"),e.createElement(n,null,e.createElement(l,{align:"center"},"A newer version of the draft you are trying to edit has been recently saved."),e.createElement(l,{align:"center"},"Please review the changes and decide on a version to keep."))),e.createElement(n,{className:a.policiesContainer},e.createElement(n,{alignItems:"center",display:"flex",flexDirection:"column",flex:"1 1 0%"},e.createElement(l,{className:a.label,variant:"button"},"Your local draft"),e.createElement(o,{policy:t,withChangeSummary:!0}),e.createElement(r,{className:a.button,color:"primary",onClick:c,variant:"outlined"},"Keep local draft")),e.createElement(n,{alignItems:"center",display:"flex",flexDirection:"column",flex:"1 1 0%"},e.createElement(l,{className:a.label,variant:"button"},"Recently saved draft"),e.createElement(o,{policy:m,withChangeSummary:!0}),e.createElement(r,{className:a.button,color:"primary",onClick:i,variant:"outlined"},"Keep recently saved draft")))))};export{f as PolicyConflictDialog};
2
+ //# sourceMappingURL=PolicyConflictDialog.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{useApi as n,alertApiRef as g}from"@backstage/core-plugin-api";import{Button as v}from"@material-ui/core";import{PolicyConfigParser as P}from"@spotify/backstage-plugin-rbac-common";import A from"js-yaml";import c from"react";import{useNavigate as w}from"react-router-dom";import{rbacApiRef as b}from"../../api.esm.js";function h(){const t=n(b),l=w(),e=n(g);function m(p){const r=p.target?.files?.[0],o=new FileReader;r&&(o.readAsText(r,"utf-8"),o.onload=async f=>{const i=f.target?.result?.toString();if(i){let s=null;try{s=A.load(i)}catch{e.post({message:"YAML file is invalid",severity:"error"});return}const a=P.safeParse(s);if(!a.success){e.post({message:"Imported policy is invalid",severity:"error"});return}const u=a.data;if((await t.getPolicies()).items.some(d=>d.status==="draft")){e.post({message:"Unable to import new policy due to existing draft policy",severity:"error"});return}const y=await t.createDraft(u);l(`./versions/${y.id}`),e.post({message:"Policy imported successfully",severity:"success"})}})}return c.createElement(v,{variant:"outlined",color:"primary",component:"label"},"Import",c.createElement("input",{role:"input",type:"file",hidden:!0,onChange:m,accept:".yaml"}))}export{h as PolicyImportButton};
2
+ //# sourceMappingURL=PolicyImportButton.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as c,Dialog as m,DialogContent as p,Box as t,Typography as n,Button as r}from"@material-ui/core";import d from"@material-ui/icons/ReportProblemOutlined";import e from"react";import{exportPolicy as f}from"./exportPolicy.esm.js";const s=c(o=>({icon:{color:o.palette.warning.main,width:"2rem",height:"2rem"}})),g=({onConfirm:o,policy:a})=>{const i=s(),l=()=>{f(a)};return e.createElement(m,{open:!0},e.createElement(p,null,e.createElement(t,{display:"flex",flexDirection:"column",gridGap:16},e.createElement(t,{display:"flex",flexDirection:"column",gridGap:4},e.createElement(t,{display:"flex",justifyContent:"center"},e.createElement(d,{className:i.icon})),e.createElement(n,{align:"center",variant:"h6"},"Invalid local draft")),e.createElement(t,{display:"flex",flexDirection:"column",gridGap:8},e.createElement(n,{align:"center"},"You have a local draft that is no longer compatible or has become corrupted."),e.createElement(n,{align:"center"},"Click export to download your draft. You can attempt to restore your draft by importing this file on the RBAC home page."),e.createElement(n,{align:"center"},"Clicking continue will discard your draft."," ",e.createElement(t,{component:"span",fontWeight:"fontWeightBold"},"This action cannot be undone."))),e.createElement(t,{display:"flex",justifyContent:"center",gridGap:8,marginY:3},e.createElement(r,{color:"primary",onClick:l,variant:"outlined"},"Export"),e.createElement(r,{color:"primary",onClick:o,variant:"contained"},"Discard and continue")))))};export{g as PolicyInvalidDialog};
2
+ //# sourceMappingURL=PolicyInvalidDialog.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{ButtonGroup as S,Button as l,Menu as D,MenuList as c,MenuItem as n,ListItemIcon as r,ListItemText as o,Typography as x,Divider as u}from"@material-ui/core";import z from"@material-ui/icons/MoreHoriz";import L from"@material-ui/icons/Save";import I from"@material-ui/icons/Settings";import M from"@material-ui/icons/Undo";import T from"@material-ui/icons/VerticalAlignTop";import e,{useState as B}from"react";import{useNavigate as A}from"react-router-dom";import{usePoliciesContext as O}from"../Policies/PoliciesProvider.esm.js";import{usePolicyContext as w}from"./PolicyProvider.esm.js";import{useDuplicatePolicy as F}from"./useDuplicatePolicy.esm.js";function G(){const[m,s]=B(null),{hasDraftPolicy:E}=O(),{isValid:a,discardLocalDraft:p,exportPolicy:d,hasChanges:i,policy:t,saveLocalDraftToServer:f,saveAndPublish:h,publish:y}=w(),C=A(),[v,g]=F(),b=k=>{s(k.currentTarget)},P=()=>{s(null)};return e.createElement(e.Fragment,null,e.createElement(S,{variant:"contained",color:"primary"},t.status==="draft"&&e.createElement(l,{disabled:!a,onClick:()=>f()},"Save"),t.status==="inactive"&&e.createElement(l,{onClick:()=>y()},"Republish"),t.status==="active"&&e.createElement(l,{disabled:E||v.loading,onClick:()=>g(t)},"Duplicate"),e.createElement(l,{color:"primary",title:"options",size:"small",onClick:b},e.createElement(z,null))),e.createElement(D,{getContentAnchorEl:null,anchorEl:m,anchorOrigin:{vertical:"bottom",horizontal:"right"},open:!!m,onClose:P,PaperProps:{style:{width:240}}},t.status==="draft"&&e.createElement(c,null,e.createElement(n,{disabled:!a,onClick:()=>h()},e.createElement(r,null,e.createElement(L,{fontSize:"small"})),e.createElement(o,null,"Save & Publish")),e.createElement(n,{disabled:!i,onClick:()=>p()},e.createElement(r,null,e.createElement(M,{color:i?"secondary":"inherit",fontSize:"small"})),e.createElement(o,null,e.createElement(x,{color:i?"secondary":"inherit"},"Discard changes"))),e.createElement(u,null)),e.createElement(c,null,e.createElement(n,{onClick:()=>d()},e.createElement(r,null,e.createElement(T,{fontSize:"small"})),e.createElement(o,null,"Export"))),e.createElement(u,null),e.createElement(c,null,e.createElement(n,{disabled:!a,onClick:()=>C("./options")},e.createElement(r,null,e.createElement(I,{fontSize:"small"})),e.createElement(o,null,"Options")))))}export{G as PolicyMenu};
2
+ //# sourceMappingURL=PolicyMenu.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{makeStyles as s,Card as m,CardActionArea as p,CardContent as g,CardHeader as h,Radio as f,Typography as u,Chip as C}from"@material-ui/core";import t from"react";const y=s(e=>({card:a=>({marginTop:e.spacing(3),height:"100%","&:hover":a.readonly?{pointerEvents:"none"}:{}}),cardHeader:{paddingBottom:e.spacing(2),alignItems:"flex-start"},defaultChip:{marginLeft:e.spacing(1),marginBottom:0},title:{display:"flex",alignItems:"center",paddingTop:e.spacing(.5),paddingBottom:e.spacing(1)}}));function E(e){const a=y(e),{title:r,description:i,active:l,changeResolutionStrategy:o,defaultOption:c,readonly:n}=e,d=()=>{n||o()};return t.createElement(m,{className:`${a.card}`,onClick:d},t.createElement(p,{disabled:n},t.createElement(g,null,t.createElement(h,{className:a.cardHeader,avatar:t.createElement(f,{checked:l,color:"primary",disabled:n}),title:t.createElement("div",{className:a.title},t.createElement(u,{variant:"h6",component:"h2"},r),c?t.createElement(C,{label:"Default",size:"small",className:a.defaultChip}):null),subheader:i}))))}export{E as PolicyOptionCard};
2
+ //# sourceMappingURL=PolicyOptionCard.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{ContentHeader as m}from"@backstage/core-components";import{makeStyles as d,Button as h,Grid as y,Typography as a,Chip as g}from"@material-ui/core";import{invariant as u}from"@spotify/backstage-plugin-core";import e from"react";import{useParams as f,useNavigate as E}from"react-router-dom";import{PageWrapper as v}from"../Layout/PageWrapper.esm.js";import{PolicyOptionCard as r}from"./PolicyOptionCard.esm.js";import{PolicyProvider as w,usePolicyContext as x}from"./PolicyProvider.esm.js";const P=d(t=>({title:{display:"flex",alignItems:"center",paddingBottom:t.spacing(2)},maxWidthWrapper:{maxWidth:"800px"},readOnlyChip:{marginLeft:t.spacing(1)},paragraph:{paddingBottom:t.spacing(1)}}));function b(){const{versionId:t}=f();return u(t),e.createElement(w,{policyId:t},e.createElement(l,null))}function l(){const t=P(),{policy:o,updateLocalDraft:s}=x(),c=E(),i=o.status!=="draft",n=p=>{s({...o,options:{...o.options,resolutionStrategy:p}})};return e.createElement(v,{pages:[{title:o.name,path:".."},{title:"Options"}],header:e.createElement(m,{title:"Options"},e.createElement(h,{variant:"outlined",color:"primary",onClick:()=>c("..",{relative:"path"})},"Back to policy"))},e.createElement(y,{item:!0,xs:12,className:t.maxWidthWrapper},e.createElement("div",null,e.createElement("div",{className:t.title},e.createElement(a,{variant:"h5",component:"h1"},"Decision resolution strategy"),i?e.createElement(g,{label:"Read only",className:t.readOnlyChip}):null),e.createElement(a,{variant:"body2",component:"p",className:t.paragraph},"Multiple decisions from multiple roles could be applicable to a single user when authorizing a permission request. Please select the decision resolution strategy that makes sense for your policy."),e.createElement(a,{variant:"body2",component:"p",className:t.paragraph},"Please note this strategy will be applied to the whole policy and greatly affects the outcome of permission decisions."),e.createElement(r,{title:"Any-allow",changeResolutionStrategy:()=>n("any-allow"),readonly:i,defaultOption:!0,description:e.createElement(e.Fragment,null,e.createElement(a,{variant:"body2",color:"textSecondary",component:"p",className:t.paragraph},"The first allow decision from all of the roles and decisions is the final result. A single explicit allow or an allow as a result of a conditional decision would result in a final allow decision, otherwise the decision is deny."),e.createElement(a,{variant:"body2",color:"textSecondary",component:"p",className:t.paragraph},"With this option, the order of roles and decisions does not matter.")),active:o.options.resolutionStrategy==="any-allow"}),e.createElement(r,{title:"First match",changeResolutionStrategy:()=>n("first-match"),readonly:i,description:e.createElement(e.Fragment,null,e.createElement(a,{variant:"body2",color:"textSecondary",component:"p",className:t.paragraph},"The first matching decision from the first matching role that is applicable to the user is the final result, regardless if that decision is an allow, deny or conditional."),e.createElement(a,{variant:"body2",color:"textSecondary",component:"p",className:t.paragraph},"With this option, the order in which you define roles and decisions matters.")),active:o.options.resolutionStrategy==="first-match"}))))}export{b as PolicyOptionsPage,l as PolicyOptionsPageContent};
2
+ //# sourceMappingURL=PolicyOptionsPage.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{ContentHeader as p}from"@backstage/core-components";import{Grid as m,Typography as i}from"@material-ui/core";import{invariant as s}from"@spotify/backstage-plugin-core";import{UpdateDraftRequestParser as u}from"@spotify/backstage-plugin-rbac-common";import e from"react";import{useParams as f}from"react-router-dom";import{getZodValidationToKeyMap as d}from"../../utils/getZodValidationToKeyMap.esm.js";import y from"../EditableInput/EditableInput.esm.js";import{PageWrapper as E}from"../Layout/PageWrapper.esm.js";import{Title as P}from"../Layout/Title.esm.js";import{PolicyTester as g}from"../PolicyTester/PolicyTester.esm.js";import{RelativeTime as v}from"../RelativeTime/RelativeTime.esm.js";import{RolesTable as T}from"../Roles/RolesTable.esm.js";import b from"./EmptyRolesCard.esm.js";import{getActivityDescription as h}from"./getActivityDescriptions.esm.js";import{PolicyMenu as C}from"./PolicyMenu.esm.js";import{PolicyProvider as x,usePolicyContext as D}from"./PolicyProvider.esm.js";import{PolicyStatusChip as $}from"./PolicyStatusChip.esm.js";function L(){const{versionId:t}=f();return s(t),e.createElement(x,{policyId:t},e.createElement(l,null))}function l(){const{policy:t,updateLocalDraft:a}=D(),o=c=>{a({...t,name:c})},n=d(u.safeParse(t)).name,r=t.status!=="draft";return e.createElement(E,{pages:[{title:t.name}],header:e.createElement(p,{title:t.name,titleComponent:e.createElement(e.Fragment,null,e.createElement(P,null,r?t.name:e.createElement(y,{invalid:n,name:"Policy name",value:t.name,onTextChange:o}),e.createElement($,{status:t.status})),R(t))},e.createElement(C,null))},e.createElement(m,{container:!0,spacing:4},e.createElement(m,{item:!0,xs:12},t.roles.length>0?e.createElement(T,null):e.createElement(b,{readonly:r})),e.createElement(m,{item:!0,xs:12},e.createElement(g,null))))}function R(t){const a={created:"Created by ",published:"Last published by ",updated:"Last updated by "},{activityDateText:o,activityUser:n,timestamp:r}=h(t,a);return e.createElement(i,{variant:"body2"},e.createElement(i,{component:"span",display:"inline",variant:"body2"},`${o} ${n} `),e.createElement(v,{timestamp:r}))}export{L as PolicyPage,l as PolicyPageContent};
2
+ //# sourceMappingURL=PolicyPage.esm.js.map