@spotify/backstage-plugin-rbac 0.7.4 → 0.7.6
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.
- package/CHANGELOG.md +23 -0
- package/dist/alpha.d.ts +2 -3
- package/dist/api.esm.js +1 -1
- package/dist/components/DecisionDialog/ConditionalDecisionForm/ConditionCard.esm.js +1 -1
- package/dist/components/DecisionDialog/DecisionDialog.esm.js +1 -1
- package/dist/components/DecisionDialog/MatchByActions.esm.js +1 -1
- package/dist/components/DecisionDialog/MatchByResourceType.esm.js +1 -1
- package/dist/components/DecisionDialog/ParamsForm/ParamsFormArrayInput.esm.js +1 -1
- package/dist/components/Diffing/DiffSummary.esm.js +1 -1
- package/dist/components/Diffing/getPolicyDiff/getRolesDiff.esm.js +1 -1
- package/dist/components/Diffing/usePolicyDiff.esm.js +1 -1
- package/dist/components/Diffing/utils.esm.js +1 -1
- package/dist/components/Home/HomePage.esm.js +1 -1
- package/dist/components/Home/HomePageEmptyState.esm.js +1 -1
- package/dist/components/Members/MemberLabel.esm.js +2 -0
- package/dist/components/Members/MembersAutocomplete.esm.js +1 -1
- package/dist/components/Members/MembersTable.esm.js +1 -1
- package/dist/components/Members/MembersTableBody.esm.js +1 -1
- package/dist/components/Permissions/PermissionsTable.esm.js +1 -1
- package/dist/components/Policies/PoliciesProvider.esm.js +1 -1
- package/dist/components/Policies/useFetchPolicies.esm.js +1 -1
- package/dist/components/Policy/PolicyCard.esm.js +1 -1
- package/dist/components/Policy/PolicyPage.esm.js +1 -1
- package/dist/components/Policy/PolicyProvider.esm.js +1 -1
- package/dist/components/Policy/getActivityDetails.esm.js +2 -0
- package/dist/components/Policy/useDeleteDraftPolicy.esm.js +1 -1
- package/dist/components/Policy/usePublishPolicy.esm.js +1 -1
- package/dist/components/Role/RolePage.esm.js +1 -1
- package/dist/components/Roles/RolesTable.esm.js +1 -1
- package/package.json +26 -23
- package/dist/components/Policy/getActivityDescriptions.esm.js +0 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @spotify/backstage-plugin-rbac
|
|
2
2
|
|
|
3
|
+
## 0.7.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Update to Backstage `v1.36.0`
|
|
8
|
+
- In line with the open source Backstage framework, support for React 16 has been dropped.
|
|
9
|
+
- Improved the first-time user experience when using the `permission.rbac.fallbackPolicy` configuration.
|
|
10
|
+
- UI updates to make it clearer that `create` actions do not apply to `resource` permissions.
|
|
11
|
+
- The role members table and members search now shows entity display names instead of refs when available.
|
|
12
|
+
- Added the ability to provide descriptions for roles.
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
- @spotify/backstage-plugin-core@0.8.6
|
|
15
|
+
- @spotify/backstage-plugin-rbac-common@0.6.6
|
|
16
|
+
|
|
17
|
+
## 0.7.5
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Update to Backstage `v1.35.0`
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
- @spotify/backstage-plugin-core@0.8.5
|
|
24
|
+
- @spotify/backstage-plugin-rbac-common@0.6.5
|
|
25
|
+
|
|
3
26
|
## 0.7.4
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
package/dist/alpha.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
|
|
4
|
-
import * as _backstage_core_plugin_api_index from '@backstage/core-plugin-api/index';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* @public
|
|
@@ -12,10 +11,10 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{}, {}, {
|
|
|
12
11
|
name: undefined;
|
|
13
12
|
config: {};
|
|
14
13
|
configInput: {};
|
|
15
|
-
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<
|
|
14
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
16
15
|
inputs: {};
|
|
17
16
|
params: {
|
|
18
|
-
factory:
|
|
17
|
+
factory: _backstage_frontend_plugin_api.AnyApiFactory;
|
|
19
18
|
};
|
|
20
19
|
}>;
|
|
21
20
|
"page:rbac": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
package/dist/api.esm.js
CHANGED
|
@@ -1,2 +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
|
|
1
|
+
import{createApiRef as p}from"@backstage/core-plugin-api";import{ResponseError as h}from"@backstage/errors";import{PolicyResponseParser as l,PolicyParser as c,SearchMemberResponseParser as y,AuthorizeResponseParser as f,DraftResponseParser as o,TestPolicyDecisionResponseParser as d}from"@spotify/backstage-plugin-rbac-common";const w=p({id:"plugin.rbac"});class A{fetchApi;discoveryApi;constructor(i){this.fetchApi=i.fetchApi,this.discoveryApi=i.discoveryApi}async getPolicies(){const{fetch:i}=this.fetchApi,t=await i(`${await this.discoveryApi.getBaseUrl("rbac")}/policies`),s=await this.#i(t);return l.parse(s)}async getPolicy(i){const{fetch:t}=this.fetchApi,s=await t(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${i}`),e=await this.#i(s);return c.parse(e)}async getActivePolicy(){const{fetch:i}=this.fetchApi,t=await i(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/active`),s=await this.#i(t);return c.parse(s)}async getFallbackPolicy(){const{fetch:i}=this.fetchApi,t=await i(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/fallback`);if(t.status!==404)return await this.#i(t)}async searchMembers(i){const{fetch:t}=this.fetchApi,s=await t(`${await this.discoveryApi.getBaseUrl("rbac")}/members?query=${encodeURIComponent(i.query)}`),e=await this.#i(s);return y.parse(e)}async authorize(){const{fetch:i}=this.fetchApi,t=await i(`${await this.discoveryApi.getBaseUrl("rbac")}/authorize`),s=await this.#i(t);return f.parse(s)}async createDraft(i){const{fetch:t}=this.fetchApi,s=await t(`${await this.discoveryApi.getBaseUrl("rbac")}/policies`,{method:"POST",body:JSON.stringify(i),headers:{"Content-Type":"application/json"}}),e=await this.#i(s);return o.parse(e)}async updateDraft(i,t){const{fetch:s}=this.fetchApi,e=await s(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${i}`,{method:"PATCH",body:JSON.stringify(t),headers:{"Content-Type":"application/json"}}),a=await this.#i(e);return o.parse(a)}async deleteDraft(i){const{fetch:t}=this.fetchApi,s=await t(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${i}`,{method:"DELETE"});return await this.#i(s)}async publishPolicy(i,t){const{fetch:s}=this.fetchApi,e=await s(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${i}/publish`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});return await this.#i(e)}async testPolicyDecisions(i){return await Promise.all(i.map(async t=>{const{policyConfig:s,roleIds:e,permission:a}=t,{decision:r,decisionOrigin:n}=await this.#t(s,e,a);return{decision:r,permission:a,decisionOrigin:n}}))}async#t(i,t,s){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:t,permission:s})}),r=await this.#i(a);return d.parse(r)}async fetchAllPermissionMetadata(i){const t=await Promise.all(i.map(s=>this.#s(s)));return{permissions:t.flatMap(({permissions:s})=>s),rules:t.flatMap(({rules:s})=>s)}}async#s(i){const t=await this.discoveryApi.getBaseUrl(i);let s;try{const r=await this.fetchApi.fetch(`${t}/.well-known/backstage/permissions/metadata`);s=await this.#i(r)}catch{return{permissions:[],rules:[]}}const e=s.permissions?.filter(Boolean)??[],a=s.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 t=await h.fromResponse(i);throw t.message=t.body.error.message??t.message??"Unknown error",t}}export{A as RBACApi,w as rbacApiRef};
|
|
2
2
|
//# sourceMappingURL=api.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{makeStyles as g,Box as a,Card as f,CardContent as C,InputLabel as y,TextField as h,Typography as i,Popper as x,IconButton as b}from"@material-ui/core";import v from"@material-ui/icons/Delete";import{Autocomplete as
|
|
1
|
+
import{makeStyles as g,Box as a,Card as f,CardContent as C,InputLabel as y,TextField as h,Typography as i,Popper as x,IconButton as b}from"@material-ui/core";import v from"@material-ui/icons/Delete";import{Autocomplete as k}from"@material-ui/lab";import e,{useCallback as B}from"react";import{useAggregatedRules as I}from"../../Permissions/PermissionsMetadataContext.esm.js";import{ParamsForm as N}from"../ParamsForm/ParamsForm.esm.js";const S=g(n=>({conditionCard:{minWidth:n.spacing(63)},conditionCardBar:{height:n.spacing(1),backgroundColor:n.palette.primary.main},autocomplete:{flex:1}}));function T({ruleName:n,parameters:p,resourceType:u,onChange:r,onDelete:s}){const o=S(),m=I()?.filter(t=>t.resourceType===u)??[],c=m.find(t=>t.name===n),d=t=>{r(t,{})},E=B(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(k,{className:o.autocomplete,"data-testid":"rule-select",getOptionLabel:t=>t.name,getOptionSelected:(t,l)=>t.name===l.name,options:m,onChange:(t,l)=>d(l?l.name:null),renderInput:t=>e.createElement(e.Fragment,null,e.createElement(a,{marginBottom:2},e.createElement(y,null,"Rule")),e.createElement(h,{...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(N,{rule:c,onChange:E,value:p})))))),e.createElement(a,{ml:1},e.createElement(b,{"aria-label":"delete",onClick:s,size:"small"},e.createElement(v,null))))}export{T as default};
|
|
2
2
|
//# sourceMappingURL=ConditionCard.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{makeStyles as
|
|
1
|
+
import{makeStyles as B,Dialog as W,DialogTitle as A,Typography as F,Button as x,DialogContent as j,Box as r,Divider as k,FormHelperText as M,Tooltip as V}from"@material-ui/core";import G from"@material-ui/icons/Close";import H from"@material-ui/icons/Info";import{ToggleButton as T}from"@material-ui/lab";import e,{useState as C,useMemo as g,useEffect as L}from"react";import{usePermissions as O,useAggregatedRules as U,useResourceTypeInfo as Y}from"../Permissions/PermissionsMetadataContext.esm.js";import q from"./computeMatchResult.esm.js";import z from"./ConditionalDecisionForm/ConditionalDecisionForm.esm.js";import{getInitialValues as J,validateCriteria as K,toRolePermission as Q,getConditions as X}from"./decisionDataMappers.esm.js";import Z from"./MatchByActions.esm.js";import _ from"./MatchByName.esm.js";import ee from"./MatchByResourceType.esm.js";import oe from"./ToggleButtonGroup.esm.js";import{VerticalSelection as ie}from"./VerticalSelection.esm.js";const ne=B(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}=O(),v=U(),y=Y(),p=J(a),[o,d]=C(p.match),[l,f]=C(p.decisionType),[u,I]=C(p.criteria),i=g(()=>q(c,o),[c,o]),m=l==="conditional",w=m?"xl":"sm";L(()=>{m&&c&&!i.commonResourceType&&f("allow")},[m,c,i.commonResourceType,f]);const N=n=>{n!==null&&f(n)},h=g(()=>o.method==="specificPermission"&&!o.name||o.method==="filter"&&!o.resourceType&&!o.actions,[o]),P=g(()=>i.permissions.length===0?!1:!h,[i,h]),S=g(()=>l!=="conditional"?!0:!(!i.commonResourceType||!y?.[i.commonResourceType].pluginId||!K(u,v)),[l,i,y,u,v]),$=()=>{D?.(Q(p.id,o,l==="conditional"?{resourceType:i.commonResourceType,pluginId:y[i.commonResourceType].pluginId,conditions:X(u)}:l))};return e.createElement(W,{open:!0,maxWidth:w,onClose:b,fullWidth:!0},e.createElement(A,{disableTypography:!0,className:s.dialogTitle},e.createElement(F,{variant:"h4",component:"h2"},t?"":"New"," Permission Decision"),e.createElement(x,{startIcon:e.createElement(G,null),onClick:b},"Close")),e.createElement(j,{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(Z,{actions:o.actions,readonly:t,resourceSelected:o.resourceType!==void 0,onActionsChange:n=>d({...o,actions:n.length?n:void 0})}),h?null:e.createElement(e.Fragment,null,e.createElement(r,{marginY:2},e.createElement(k,{variant:"middle"})),e.createElement(M,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(T,{value:"allow","aria-label":"Decision allowed",disabled:t},"Allow"),e.createElement(T,{value:"deny","aria-label":"Decision denied",disabled:t},"Deny"),e.createElement(T,{value:"conditional","aria-label":"Decision conditionally allowed",disabled:!i.commonResourceType||t},"Conditional")),!m&&!t&&e.createElement(V,{title:R},e.createElement(H,{className:s.infoIcon,"aria-label":R}))))),l==="conditional"&&!!i.commonResourceType&&e.createElement(z,{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:$,disabled:!P||!S},"Save"))))}export{ae as DecisionDialog};
|
|
2
2
|
//# sourceMappingURL=DecisionDialog.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{TextField as
|
|
1
|
+
import{TextField as c}from"@material-ui/core";import{Autocomplete as d}from"@material-ui/lab";import t from"react";const m="Action";function p({actions:o,readonly:r,resourceSelected:n,onActionsChange:a}){const l=[...n?[]:["create"],"read","update","delete"];return t.createElement(d,{multiple:!0,id:"match-by-attribute-dropdown",options:l,getOptionLabel:e=>e,value:o??[],onChange:(e,i)=>a?.(i),filterSelectedOptions:!0,renderInput:e=>t.createElement(c,{...e,variant:"outlined",label:m,placeholder:"Choose attributes",margin:"normal"}),disabled:r})}export{p as default};
|
|
2
2
|
//# sourceMappingURL=MatchByActions.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{makeStyles as m,FormControl as s,InputLabel as
|
|
1
|
+
import{makeStyles as m,FormControl as s,InputLabel as d,Select as i,MenuItem as a}from"@material-ui/core";import t from"react";import{useResourceTypeOptions as p}from"../Permissions/PermissionsMetadataContext.esm.js";const y=m(()=>({fullWidth:{width:"100%","& > *":{flexGrow:1}}})),l="Resource type";function b({resourceType:o="",readonly:n,onResourceTypeChange:c}){const u=y(),r=p();return t.createElement(s,{className:u.fullWidth,variant:"outlined",disabled:n,"data-testid":"match-by-resource-select"},t.createElement(d,{id:"match-by-resource-dropdown"},l),t.createElement(i,{labelId:"match-by-resource-dropdown",label:l,value:r?o:"",onChange:e=>c?.(e.target.value),displayEmpty:!0},t.createElement(a,{key:"all",value:void 0},"(all)"),r?.map(e=>t.createElement(a,{key:e,value:e},e))))}export{b as default};
|
|
2
2
|
//# sourceMappingURL=MatchByResourceType.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{IconButton as h,Box as s,FormControlLabel as I,Checkbox as
|
|
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 O}from"./ParamsFormInputRouter.esm.js";const S=[];function T(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:S,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(O,{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{T as ParamsFormArrayInput};
|
|
2
2
|
//# sourceMappingURL=ParamsFormArrayInput.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{makeStyles as
|
|
1
|
+
import{makeStyles as M,Box as f,Typography as N}from"@material-ui/core";import e,{Fragment as s}from"react";import{getMatchBy as d}from"../Permissions/utils.esm.js";import{usePolicyDiff as R}from"./usePolicyDiff.esm.js";import{getColorFromDiffOperation as V}from"./utils.esm.js";const C=M(m=>({root:({operation:r})=>({color:V(m,r)})})),o=m=>e.createElement(N,{...m,variant:"body2"}),t=m=>{const r=C(m);return e.createElement(f,{...m,className:r.root,component:"span",fontWeight:"fontWeightBold"})},P=({policy:m})=>{const r=R(m),D=r?.policy.operation==="CHANGED"||Object.values(r?.roles??{}).some(a=>a.role.operation!=="UNCHANGED")||r?.options?.resolutionStrategy.operation==="CHANGED";if(!r||!D)return e.createElement(f,null,"No changes");const b=!!r.policy.before&&!!r.policy.after&&r.policy.before.name!==r.policy.after.name,y=r.options.resolutionStrategy.operation==="CHANGED",A=({before:a,after:n})=>a&&n&&a.name!==n.name,h=({before:a,after:n})=>a&&n&&a.description!==n.description,g=({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,'"',r.policy.before?.name,'"')," to"," ",e.createElement(t,null,'"',r.policy.after?.name,'"')),y&&e.createElement(o,null,"Resolution Strategy ",e.createElement(t,{operation:"CHANGED"},"changed")," ","from ",e.createElement(t,null,'"',r.options.resolutionStrategy.before,'"')," to"," ",e.createElement(t,null,'"',r.options.resolutionStrategy.after,'"')),Object.entries(r.roles).map(([a,{role:n,permissions:O,members:x}])=>e.createElement(s,{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,'"')),h(n)&&e.createElement(o,null,"Role description changed from"," ",e.createElement(t,null,'"',n.before?.description,'"')," to"," ",e.createElement(t,null,'"',n.after?.description,'"')),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"),g(n)&&e.createElement(e.Fragment,null,Object.entries(O).map(([E,l])=>{const{before:p,after:u}=l,c=p&&d(p),i=u&&d(u);return e.createElement(s,{key:E},l.operation==="ADDED"&&l.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,'"')),l.operation==="REMOVED"&&l.before&&e.createElement(o,null,"Permission decision"," ",e.createElement(t,null,'"',c,'"')," has been"," ",e.createElement(t,{operation:"REMOVED"},"removed")," ","from ",e.createElement(t,null,'"',n.after?.name,'"')),l.operation==="CHANGED"&&e.createElement(o,null,c!==i?e.createElement(e.Fragment,null,"Permission decision"," ",e.createElement(t,null,'"',c,'"')," 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,'"',c,'"')," has been"," ",e.createElement(t,{operation:"CHANGED"},"updated"))," ","in ",e.createElement(t,null,'"',n.after?.name,'"')),l.indexAfter>l.indexBefore&&l.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,'"')),l.indexAfter<l.indexBefore&&l.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(x).map(([E,l])=>e.createElement(s,{key:E},l.operation==="ADDED"&&l.after&&e.createElement(o,null,"Member ",e.createElement(t,null,'"',l.after,'"')," has been"," ",e.createElement(t,{operation:"ADDED"},"added")," to"," ",e.createElement(t,null,'"',n.after?.name,'"')),l.operation==="REMOVED"&&l.before&&e.createElement(o,null,"Member ",e.createElement(t,null,'"',l.before,'"')," has been"," ",e.createElement(t,{operation:"REMOVED"},"removed")," from"," ",e.createElement(t,null,'"',n.after?.name,'"'))))))))};export{P as DiffSummary};
|
|
2
2
|
//# sourceMappingURL=DiffSummary.esm.js.map
|
|
@@ -1,2 +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
|
|
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 x=(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=e.description!==o.description,a=Object.values(l).some(({operation:s})=>s!=="UNCHANGED"),D=Object.values(d).some(({operation:s})=>s!=="UNCHANGED"),c=e.name!==o.name||b||a||D;i[e.id].role.before=e,i[e.id].role.indexBefore=r,i[e.id].role.operation=c?"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{x as getRolesDiff};
|
|
2
2
|
//# sourceMappingURL=getRolesDiff.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useApi as
|
|
1
|
+
import{useApi as l}from"@backstage/core-plugin-api";import{useMemo as s}from"react";import p from"react-use/lib/useAsync";import{rbacApiRef as a}from"../../api.esm.js";import{usePoliciesContext as n}from"../Policies/PoliciesProvider.esm.js";import{getPolicyDiff as u}from"./getPolicyDiff/getPolicyDiff.esm.js";const y=i=>{const{fallbackPolicy:o,policies:r}=n(),t=l(a),{value:e,loading:c,error:f}=p(async()=>o&&!r?.find(m=>m.status==="active")?o:t.getActivePolicy(),[t,o,r]);return s(()=>i&&!c&&!f?u(e,i):null,[e,i,c,f])};export{y as usePolicyDiff};
|
|
2
2
|
//# sourceMappingURL=usePolicyDiff.esm.js.map
|
|
@@ -1,2 +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.
|
|
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.info.main;case"MOVED_UP":case"MOVED_DOWN":return e.palette.info.main;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"}},n=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,n as getTextFromDiffOperation};
|
|
2
2
|
//# sourceMappingURL=utils.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Progress as
|
|
1
|
+
import{Progress as c,ErrorPanel as a,ContentHeader as p}from"@backstage/core-components";import{Grid as s,Typography as f}from"@material-ui/core";import e from"react";import E from"react-use/lib/useMount";import{PageWrapper as g}from"../Layout/PageWrapper.esm.js";import{usePoliciesContext as P}from"../Policies/PoliciesProvider.esm.js";import{useFetchPolicies as u}from"../Policies/useFetchPolicies.esm.js";import{PolicyImportButton as h}from"../Policy/PolicyImportButton.esm.js";import m from"./HomePageContent.esm.js";import d from"./HomePageEmptyState.esm.js";function y(){const{fallbackPolicy:o,policies:r}=P(),{loading:l,error:i,fetchPolicies:n}=u();E(()=>{r||n()});let t;return l?t=e.createElement(s,{item:!0,xs:12},e.createElement(c,null)):i?t=e.createElement(a,{error:i}):o&&(!r||r.length===0)?t=e.createElement(m,{policies:[o]}):!r||r.length===0?t=e.createElement(d,null):t=e.createElement(m,{policies:r}),e.createElement(g,{pages:void 0,header:e.createElement(p,{titleComponent:e.createElement(f,{variant:"h2"},"RBAC Policies")},e.createElement(h,null))},t)}export{y as HomePage};
|
|
2
2
|
//# sourceMappingURL=HomePage.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{EmptyState as l}from"@backstage/core-components";import{useApi as c}from"@backstage/core-plugin-api";import{makeStyles as
|
|
1
|
+
import{EmptyState as l}from"@backstage/core-components";import{useApi as c}from"@backstage/core-plugin-api";import{makeStyles as s,Card as m,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=s(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(m,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
2
|
//# sourceMappingURL=HomePageEmptyState.esm.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{parseEntityRef as i,DEFAULT_NAMESPACE as m}from"@backstage/catalog-model";import{EntityDisplayName as a}from"@backstage/plugin-catalog-react";import{Tooltip as r}from"@material-ui/core";import n from"react";function o({member:e}){const t=typeof e=="string"?i(e):i(e.entityRef);return t.name==="*"?n.createElement(r,{title:`All ${t.kind}s in the ${t.namespace} namespace`},n.createElement("label",null,`${t.kind}:${t.namespace}`)):typeof e=="string"?n.createElement(a,{hideIcon:!0,entityRef:t}):n.createElement(a,{hideIcon:!0,entityRef:{apiVersion:"",kind:e.type,metadata:{name:e.name,namespace:e.namespace||m,description:e.description},spec:e.spec}})}export{o as MemberLabel};
|
|
2
|
+
//# sourceMappingURL=MemberLabel.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{parseEntityRef as
|
|
1
|
+
import{parseEntityRef as E}from"@backstage/catalog-model";import{makeStyles as x,Box as R,Checkbox as C,TextField as k,CircularProgress as A}from"@material-ui/core";import{Autocomplete as S}from"@material-ui/lab";import t,{useState as O,useReducer as P,useEffect as F}from"react";import{MemberLabel as L}from"./MemberLabel.esm.js";import{MembersAutocompleteListBox as M}from"./MembersAutocompleteListBox.esm.js";const I=x({autocomplete:{display:"flex",flex:1}});function w({members:n,allOptions:r,memberDisplayNames:m,loading:o=!1,disabled:s=!1,placeholder:u,onTextChange:a,onToggleMember:d,onChange:f}){const b=I(),[l,i]=O(!1),[y,g]=P(e=>e+1,0),h=(e,c)=>{c&&(d(c),g())};return F(()=>{l&&a("")},[l,a]),t.createElement(R,{width:250},t.createElement(S,{key:`${y}`,open:l,onOpen:()=>{i(!0)},onClose:()=>{i(!1)},onChange:h,getOptionLabel:e=>m.get(e.entityRef)||e.entityRef,groupBy:B,ListboxComponent:M,renderOption:e=>t.createElement("div",{key:e.entityRef},t.createElement(C,{id:`checkbox-${e.entityRef}`,checked:n.includes(e.entityRef),color:"primary"}),t.createElement("label",{htmlFor:`checkbox-${e.entityRef}`},t.createElement(L,{member:e}))),options:r,openOnFocus:!0,disabled:s,loading:o,className:b.autocomplete,renderInput:e=>t.createElement(k,{...e,placeholder:u,variant:"standard",onChange:f,InputProps:{...e.InputProps,endAdornment:t.createElement(t.Fragment,null,o?t.createElement(A,{color:"inherit",size:20}):null,e.InputProps.endAdornment)}})}))}const p={user:"USERS",group:"GROUPS",namespace:"NAMESPACES"};function B(n){const{name:r,kind:m}=E(n.entityRef),o=r==="*"?"namespace":m;if(!p[o])throw new Error(`Group '${o}' is not supported for members in a policy`);return p[o]}export{w as MembersAutocomplete};
|
|
2
2
|
//# sourceMappingURL=MembersAutocomplete.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{parseEntityRef as
|
|
1
|
+
import{parseEntityRef as L}from"@backstage/catalog-model";import{useApi as k,useApiHolder as P}from"@backstage/core-plugin-api";import{catalogApiRef as j,entityPresentationApiRef as F}from"@backstage/plugin-catalog-react";import{makeStyles as V,debounce as q,Card as z,CardHeader as G,Box as J,CardContent as K,Table as Q,TableHead as U,TableRow as W,TableCell as c,TableBody as X}from"@material-ui/core";import a,{useState as Y,useRef as Z,useMemo as u}from"react";import v from"react-use/lib/useAsync";import{rbacApiRef as _}from"../../api.esm.js";import{useMemberOptions as ee}from"./MemberOptionsProvider.esm.js";import{MembersAutocomplete as te}from"./MembersAutocomplete.esm.js";import ae from"./MembersTableBody.esm.js";const re=V(()=>({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 ne({diff:o,policyId:r,role:e,onToggleMember:n,readonly:i=!1,debounceTime:E=1e3}){const y=re(),D=k(_),R=k(j),C=P().get(F),[T,b]=Y(""),{current:p}=Z({}),$=u(()=>q(t=>{b(t.target.value.toLowerCase())},E),[b,E]),{value:g,loading:H}=ee(),{loading:h,value:s}=v(async()=>{const t=await R.getEntityFacets({facets:["metadata.namespace"],filter:{kind:["group","user"]}}).then(m=>m.facets["metadata.namespace"].map(l=>l.value));return me(t)},[R]),w=t=>{p[t.entityRef]=t,n(t.entityRef)},d=s?s?.length>2:!1,M=u(()=>s?s.filter(t=>t.entityRef.toLowerCase().includes(T)):[],[s,T]),f=u(()=>d?M.concat(g?.members||[]):g?.members||[],[g,M,d]),A=u(()=>x(f,C),[f,C]),N=t=>{if(p[t])return p[t];const m=f.find(O=>O.entityRef===t),l=L(t);return{entityRef:t,type:l.kind.toLowerCase(),name:l.name??t,namespace:l.namespace,description:m?.description,spec:m?.spec}},S=e.members==="*",{loading:B,error:I}=v(async()=>{e.members==="*"||e.members.length===0||(await D.getPolicy(r)).roles.find(t=>t.id===e.id)===void 0||e.members.forEach(t=>{const m=N(t);p[m.entityRef]=m})},[r,S]);return a.createElement(z,null,a.createElement(G,{title:"Members",action:a.createElement(J,{m:1,mt:1.25},a.createElement(te,{onToggleMember:w,members:e.members,disabled:i,allOptions:f,memberDisplayNames:A,loading:H||h,onTextChange:b,onChange:$,placeholder:d?"Select members":"Select specific users/groups"}))}),a.createElement(K,null,a.createElement(Q,{"data-testid":"membersTable"},a.createElement(U,null,a.createElement(W,null,a.createElement(c,{className:y.typeIconCol}),a.createElement(c,{className:y.nameCol},"Name"),a.createElement(c,null,"Type"),a.createElement(c,null),!i&&a.createElement(c,{className:y.actionCol}))),a.createElement(X,null,a.createElement(ae,{diff:o,loading:B||h,isMultiNamespaces:d,error:I,members:Array.isArray(e.members)?e.members.map(N):e.members,memberDisplayNames:A,onToggleMember:w,readonly:i})))))}function x(o,r){return new Map(o.map(e=>{const n=L(e.entityRef),i=n.name==="*"?`${n.kind}:${e.namespace||n.namespace}`:r?.forEntity({apiVersion:"",kind:e.type,metadata:{name:e.name||n.name,namespace:e.namespace||n.namespace,description:e.description},spec:e.spec})?.snapshot.primaryTitle||n.name;return[e.entityRef,i]}))}function me(o){return o.map(r=>[{name:"*",type:"user",entityRef:`user:${r}/*`},{name:"*",type:"group",entityRef:`group:${r}/*`}]).flat().sort((r,e)=>r.entityRef.toLowerCase().localeCompare(e.entityRef.toLowerCase()))}export{ne as MembersTable,x as getMemberDisplayNames};
|
|
2
2
|
//# sourceMappingURL=MembersTable.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{parseEntityRef as
|
|
1
|
+
import{parseEntityRef as p}from"@backstage/catalog-model";import{Progress as I}from"@backstage/core-components";import{makeStyles as S,TableRow as i,TableCell as r,IconButton as h}from"@material-ui/core";import k from"@material-ui/icons/Delete";import B from"@material-ui/icons/Group";import M from"@material-ui/icons/GroupWork";import T from"@material-ui/icons/Person";import e from"react";import{DiffBadge as g}from"../Diffing/DiffBadge.esm.js";import{MemberLabel as v}from"./MemberLabel.esm.js";const A=S(m=>({actionCol:{width:48},typeIconCol:{paddingRight:"0.4rem"},nameCol:{paddingLeft:0},typeIcon:{color:m.palette.grey[500]}}));function D({diff:m,loading:d,isMultiNamespaces:o,members:f,memberDisplayNames:u,error:y,onToggleMember:b,readonly:l=!1}){const a=A();if(d)return e.createElement(i,null,e.createElement(r,{scope:"row",colSpan:l?4:5},e.createElement(I,null)));if(y&&y.message,f==="*")return e.createElement(i,null,e.createElement(r,{colSpan:2,height:80},"All"),e.createElement(r,{colSpan:l?2:3},e.createElement(g,{operation:m?.members["*"].operation})));if(f.length===0)return e.createElement(i,null,e.createElement(r,{scope:"row",colSpan:l?4:5},"Select users or groups using the drop-down menu above."));const C=f.sort((t,n)=>{const c=u.get(t.entityRef)||p(t.entityRef).name,s=u.get(n.entityRef)||p(n.entityRef).name;let E=0;o&&n.name==="*"&&t.name!=="*"?E=1:o&&t.name==="*"&&n.name!=="*"&&(E=-1);const R=t.type.localeCompare(n.type),w=p(t.entityRef).namespace.localeCompare(p(n.entityRef).namespace),N=c.localeCompare(s);return E||R||w||N});return e.createElement(e.Fragment,null,C.map(t=>{const{name:n,type:c,entityRef:s}=t;return e.createElement(i,{key:s},e.createElement(r,{className:a.typeIconCol},o&&n==="*"&&e.createElement(M,{className:a.typeIcon})||c==="group"&&e.createElement(B,{className:a.typeIcon})||e.createElement(T,{className:a.typeIcon})),e.createElement(r,{scope:"row",className:a.nameCol},e.createElement(v,{member:t})),e.createElement(r,{scope:"row"},n==="*"&&o?"namespace":c),e.createElement(r,null,n&&e.createElement(g,{operation:m?.members[s].operation})),!l&&e.createElement(r,{scope:"row",className:a.actionCol},e.createElement(h,{"aria-label":"Remove member",onClick:()=>b(t),size:"small"},e.createElement(k,null))))}))}export{D as default};
|
|
2
2
|
//# sourceMappingURL=MembersTableBody.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{EmptyState as f}from"@backstage/core-components";import{Card as y,CardHeader as h,Box as g,Button as c,CardContent as C,Table as b,TableHead as w,TableRow as i,TableCell as t,TableBody as
|
|
1
|
+
import{EmptyState as f}from"@backstage/core-components";import{Card as y,CardHeader as h,Box as g,Button as c,CardContent as C,Table as b,TableHead as w,TableRow as i,TableCell as t,TableBody as k,Link as v,IconButton as R}from"@material-ui/core";import T from"@material-ui/icons/Add";import B from"@material-ui/icons/Delete";import e from"react";import D from"../../images/no-permissions.svg";import{ConfirmationDialog as N}from"../ConfirmationDialog/ConfirmationDialog.esm.js";import{DiffBadge as I}from"../Diffing/DiffBadge.esm.js";import{EmptyStateImageWrapper as P}from"../Layout/EmptyStateImageWrapper.esm.js";import{ReorderControls as x}from"../ReorderControls/ReorderControls.esm.js";import{ReorderInfo as A}from"../ReorderControls/ReorderInfo.esm.js";import{getMatchBy as S,getDecisionDescription as H}from"./utils.esm.js";const M="Use the arrows to change the order in which permission decisions are evaluated.";function O({diff:s,permissions:n,onReorderPermissions:p,onNewPermissionClick:a,onOpenPermission:E,onRemovePermissionClick:d,anyAllow:m,readonly:r=!1}){return e.createElement(y,null,e.createElement(h,{title:"Permission Decisions",action:!r&&n.length!==0&&e.createElement(g,{m:1,mt:1.25},e.createElement(c,{color:"primary",variant:"outlined",startIcon:e.createElement(T,null),onClick:a},"New"))}),e.createElement(C,null,e.createElement(b,{"data-testid":"permissionsTable"},e.createElement(w,null,e.createElement(i,null,!r&&!m&&e.createElement(t,{style:{width:0}},e.createElement(A,{helpText:M})),e.createElement(t,null,"Match by"),e.createElement(t,null,"Decision"),e.createElement(t,null),!r&&e.createElement(t,null))),e.createElement(k,null,n.length===0&&e.createElement(i,null,e.createElement(t,{colSpan:5},e.createElement(f,{title:"No permission decisions set",description:"Click the button below to create your first permission.",missing:{customImage:e.createElement(P,{src:D,alt:"No permission placeholder"})},action:e.createElement(c,{variant:"contained",color:"primary",onClick:a},"New decision")}))),n.map((l,o)=>e.createElement(i,{key:o},!r&&!m&&e.createElement(t,null,e.createElement(x,{array:n,index:o,onReorder:p})),e.createElement(t,null,e.createElement(v,{component:"button",color:"primary",variant:"body2",align:"left",onClick:()=>E(o)},S(l))),e.createElement(t,null,H(l)),e.createElement(t,null,e.createElement(I,{operation:s?.permissions[l.id].operation})),!r&&e.createElement(t,{align:"right"},e.createElement(N,{message:"Are you sure you want to remove this permission decision?",onConfirm:()=>d(o),title:"Remove?"},u=>e.createElement(R,{...u,"aria-label":"Remove permission decision",size:"small"},e.createElement(B,null))))))))))}export{O as default};
|
|
2
2
|
//# sourceMappingURL=PermissionsTable.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
1
|
+
import h,{createContext as u,useState as v,useCallback as l,useMemo as p,useContext as b}from"react";const s=u({hasDraftPolicy:!1,policies:void 0,fallbackPolicy:void 0,setPolicies:()=>{},setFallbackPolicy:()=>{},setPolicy:()=>{},getPolicy:()=>{},removePolicy:()=>{}}),k=()=>b(s);function m({children:a,initialState:t={policies:void 0,fallbackPolicy:void 0,cache:{}}}){const[c,o]=v(t),P=l(i=>{o(e=>({...e,policies:i,cache:d(e.cache,i)}))},[]),r=l(i=>c.cache[i],[c.cache]),y=l(i=>o(e=>({...e,cache:{...e.cache,[i]:void 0},policies:void 0})),[]),n=l(i=>o(e=>({...e,policies:void 0,cache:d(e.cache,[i])})),[]),f=l(i=>o(e=>({...e,fallbackPolicy:i})),[]);return h.createElement(s.Provider,{value:p(()=>({hasDraftPolicy:c.policies?.some(({status:i})=>i==="draft")||!1,policies:c.policies,fallbackPolicy:c.fallbackPolicy,setPolicies:P,setFallbackPolicy:f,setPolicy:n,getPolicy:r,removePolicy:y}),[c.policies,P,c.fallbackPolicy,f,n,r,y])},a)}function d(a,t){if(!t)return a;const c={...a};return t.forEach(o=>{c[o.id]=o}),c}export{s as PoliciesContext,m as PoliciesProvider,k as usePoliciesContext};
|
|
2
2
|
//# sourceMappingURL=PoliciesProvider.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useApi as
|
|
1
|
+
import{useApi as f}from"@backstage/core-plugin-api";import{useCallback as P}from"react";import p from"react-use/lib/useAsyncFn";import{rbacApiRef as b}from"../../api.esm.js";import{usePoliciesContext as y}from"./PoliciesProvider.esm.js";const k=()=>{const o=f(b),{setFallbackPolicy:c,fallbackPolicy:t,setPolicies:a,policies:l}=y(),[{loading:s,error:r},e]=p(async()=>{const i=await o.getPolicies();return{policies:i,fallbackPolicy:i.items.find(m=>m.status==="active")?void 0:await o.getFallbackPolicy()}},[o],l?{loading:!1,value:{policies:{items:l,totalItems:l.length},fallbackPolicy:t}}:{loading:!0}),n=P(async()=>{const i=await e();i.fallbackPolicy&&c(i.fallbackPolicy),a(i.policies?.items)},[e,a,c]);return{loading:s,error:r,fetchPolicies:n}};export{k as useFetchPolicies};
|
|
2
2
|
//# sourceMappingURL=useFetchPolicies.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Link as
|
|
1
|
+
import{Link as g}from"@backstage/core-components";import{EntityDisplayName as b}from"@backstage/plugin-catalog-react";import{makeStyles as h,Card as v,CardContent as C,Typography as n,List as x,ListItem as o,ListItemIcon as c,ListItemText as m,Box as s,CardActions as I}from"@material-ui/core";import L from"@material-ui/icons/CalendarToday";import N from"@material-ui/icons/Person";import e from"react";import{DiffSummary as S}from"../Diffing/DiffSummary.esm.js";import{RelativeTime as $}from"../RelativeTime/RelativeTime.esm.js";import{getActivityDetails as k}from"./getActivityDetails.esm.js";import{PolicyStatusChip as P}from"./PolicyStatusChip.esm.js";const T=h(t=>({card:a=>({backgroundImage:a.policy.status==="active"?`linear-gradient(${t.palette.success.main}, ${t.palette.success.main})`:`linear-gradient(${t.palette.text.secondary}, ${t.palette.text.secondary})`,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 D(t){const a=T(t),{policy:r,to:d,withChangeSummary:p}=t,i=`${r.name} ${r.status==="draft"?"- Draft":""}`,u={created:"Created: ",published:"Published: ",updated:"Updated: "},y={created:"Created by",published:"Published by",updated:"Updated by"},{type:l,user:E,timestamp:f}=k(r);return e.createElement(v,{className:a.card},e.createElement(C,null,e.createElement("div",{className:a.header},d?e.createElement(g,{to:`versions/${r.id}`},e.createElement(n,{variant:"h2"},i)):e.createElement(n,{variant:"h2"},i),r.status==="active"?e.createElement(P,{status:"active",size:"small"}):null),r.description?e.createElement(n,{variant:"body1",color:"textSecondary"},'"',r.description,'"'):null,e.createElement(n,{component:"h2",className:a.detailsHeader},"Details"),e.createElement(x,{className:a.activityList},e.createElement(o,{className:a.activityListItem},e.createElement(c,null,e.createElement(L,null)),e.createElement(m,{primary:e.createElement($,{timestamp:f,description:u[l]})})),e.createElement(o,{className:a.activityListItem},e.createElement(c,null,e.createElement(N,null)),e.createElement(m,{primary:e.createElement(e.Fragment,null,y[l]," ",e.createElement(b,{hideIcon:!0,entityRef:E}))}))),p&&e.createElement(s,{paddingTop:2},e.createElement(n,{gutterBottom:!0,variant:"subtitle2"},"What's changed"),e.createElement(s,{className:a.diffSummaryContainer},e.createElement(S,{policy:r})))),t.actions?e.createElement(I,{className:a.actions},t.actions):null)}export{D as PolicyCard};
|
|
2
2
|
//# sourceMappingURL=PolicyCard.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ContentHeader as P}from"@backstage/core-components";import{useApi as g,alertApiRef as
|
|
1
|
+
import{ContentHeader as P}from"@backstage/core-components";import{useApi as g,alertApiRef as h}from"@backstage/core-plugin-api";import{EntityDisplayName as v}from"@backstage/plugin-catalog-react";import{Grid as s,Typography as f}from"@material-ui/core";import{invariant as T}from"@spotify/backstage-plugin-core";import{UpdateDraftRequestParser as b}from"@spotify/backstage-plugin-rbac-common";import e,{useState as x}from"react";import{useParams as C}from"react-router-dom";import{getZodValidationToKeyMap as R}from"../../utils/getZodValidationToKeyMap.esm.js";import D from"../EditableInput/EditableInput.esm.js";import{PageWrapper as A}from"../Layout/PageWrapper.esm.js";import{Title as I}from"../Layout/Title.esm.js";import{PolicyTester as L}from"../PolicyTester/PolicyTester.esm.js";import{RelativeTime as q}from"../RelativeTime/RelativeTime.esm.js";import{RolesTable as M}from"../Roles/RolesTable.esm.js";import N from"./EmptyRolesCard.esm.js";import{getActivityDetails as S}from"./getActivityDetails.esm.js";import{PolicyMenu as F}from"./PolicyMenu.esm.js";import{PolicyProvider as G,usePolicyContext as H}from"./PolicyProvider.esm.js";import{PolicyStatusChip as K}from"./PolicyStatusChip.esm.js";function U(){const{versionId:t}=C();return T(t),e.createElement(G,{policyId:t},e.createElement(d,null))}function d(){const{policy:t,updateLocalDraft:o}=H(),m=g(h),[i,l]=x(!1),y=r=>{let a;const n=b.safeParse({...t,name:r}),p=R(n).name;return p&&(a=n.error?.issues.find(u=>u.path.length===1&&u.path[0]==="name")?.message),l(p),{result:!p,helperText:a}},E=r=>{const{result:a,helperText:n}=y(r);a?o({...t,name:r}):m.post({display:"transient",severity:"error",message:n||"Please specify a valid policy name."})},c=t.status!=="draft";return e.createElement(A,{pages:[{title:t.name}],header:e.createElement(P,{title:t.name,titleComponent:e.createElement(e.Fragment,null,e.createElement(I,null,c?t.name:e.createElement(D,{invalid:i,name:"Policy name",value:t.name,onTextChange:E}),e.createElement(K,{status:t.status})),V(t))},e.createElement(F,null))},e.createElement(s,{container:!0,spacing:4},e.createElement(s,{item:!0,xs:12},t.roles.length>0?e.createElement(M,null):e.createElement(N,{readonly:c})),e.createElement(s,{item:!0,xs:12},e.createElement(L,null))))}function V(t){const o={created:"Created by ",published:"Last published by ",updated:"Last updated by "},{type:m,user:i,timestamp:l}=S(t);return e.createElement(f,{variant:"body2"},e.createElement(f,{component:"span",display:"inline",variant:"body2"},o[m],e.createElement(v,{hideIcon:!0,entityRef:i})," "),e.createElement(q,{timestamp:l}))}export{U as PolicyPage,d as PolicyPageContent};
|
|
2
2
|
//# sourceMappingURL=PolicyPage.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Progress as Z,ErrorPanel as _}from"@backstage/core-components";import{useApi as D,alertApiRef as ee,useApp as oe}from"@backstage/core-plugin-api";import{PolicyConfigParser as x}from"@spotify/backstage-plugin-rbac-common";import t,{createContext as re,useContext as te,useState as A,useCallback as f,useEffect as L}from"react";import{useNavigate as ie}from"react-router-dom";import le from"react-use/lib/useAsyncFn";import{v4 as ae}from"uuid";import{rbacApiRef as ce}from"../../api.esm.js";import{isNotFoundError as se}from"../../utils/errors.esm.js";import{usePolicyDiff as ne}from"../Diffing/usePolicyDiff.esm.js";import{usePoliciesContext as
|
|
1
|
+
import{Progress as Z,ErrorPanel as _}from"@backstage/core-components";import{useApi as D,alertApiRef as ee,useApp as oe}from"@backstage/core-plugin-api";import{PolicyConfigParser as x}from"@spotify/backstage-plugin-rbac-common";import t,{createContext as re,useContext as te,useState as A,useCallback as f,useEffect as L}from"react";import{useNavigate as ie}from"react-router-dom";import le from"react-use/lib/useAsyncFn";import{v4 as ae}from"uuid";import{rbacApiRef as ce}from"../../api.esm.js";import{isNotFoundError as se}from"../../utils/errors.esm.js";import{usePolicyDiff as ne}from"../Diffing/usePolicyDiff.esm.js";import{usePoliciesContext as pe}from"../Policies/PoliciesProvider.esm.js";import{exportPolicy as me}from"./exportPolicy.esm.js";import{getLatestPolicy as ue}from"./getLatestPolicy.esm.js";import{PolicyConflictDialog as fe}from"./PolicyConflictDialog.esm.js";import{PolicyInvalidDialog as Pe}from"./PolicyInvalidDialog.esm.js";import{PolicyPublishConfirmationDialog as ye}from"./PolicyPublishConfirmationDialog.esm.js";import{PolicyPublishSuccessDialog as de}from"./PolicyPublishSuccessDialog.esm.js";import{useLocalDraftPolicy as ve}from"./useLocalDraftPolicy.esm.js";import{usePublishPolicy as he}from"./usePublishPolicy.esm.js";const S={canPublish:!1,diff:null,hasChanges:!1,isValid:!1,policy:void 0,createNewRole:()=>"",discardLocalDraft:()=>{},exportPolicy:()=>{},publish:()=>{},saveLocalDraftToServer:()=>Promise.reject(),saveAndPublish:()=>Promise.reject(),refetchPolicy:()=>Promise.reject(),updateLocalDraft:()=>{}},N=re(S),ge=()=>te(N);function Ce({children:R,policyId:P}){const j=ie(),y=D(ee),n=D(ce),{getPolicy:$,setPolicy:h}=pe(),k=oe(),{NotFoundErrorPage:F}=k.getComponents(),[d,l]=A({active:!1,update:!1}),[I,g]=A(!1),[{loading:T,value:p},C]=he(),r=$(P),[m,u,a]=ve(),E=!m||x.safeParse(m).success,c=E?m:void 0,{policy:e,policyConflict:V}=ue({serverPolicy:r,localPolicy:c}),O=ne(e),b=x.safeParse(e).success,U=b&&!c&&!T,[{loading:q,error:v},w]=le(()=>n.getPolicy(P),[n,P],r?{loading:!1,value:r}:{loading:!0}),z=()=>{l({active:!0,update:!1})},B=()=>{l({active:!0,update:!0})},i=f(async()=>{const o=await w();h(o)},[w,h]),G=f(async o=>{await C(e,o,d.update?e:void 0),l({active:!1,update:!1}),i?.()},[e,d,C,l,i]),H=async()=>{g(!1)},J=()=>{u(o=>o&&r&&{...o,updatedAt:r.updatedAt})},K=f(async()=>{if(!e)throw new Error("No policy to save");try{await n.updateDraft(e.id,{name:e.name,roles:e.roles,options:e.options}),y.post({message:"Policy saved",severity:"success"}),a(),i?.()}catch(o){y.post({message:o?.message||"An error occurred while updating the policy",severity:"error"})}},[y,n,e,i,a]),M=f(()=>{if(!e)throw new Error("No policy to create a new role");const o=new Set(e.roles.map(Y=>Y.id));let s;do s=ae().split("-")[0];while(o.has(s));const X={name:`Role ${s}`,permissions:[],members:"*",id:s};return u({...e,roles:[...e.roles,X]}),s},[e,u]),Q=()=>{a(),j("/rbac")},W=()=>{e&&me(e)};return L(()=>{r||i()},[i,r]),L(()=>{p&&g(!0)},[p]),E?e?t.createElement(N.Provider,{value:{canPublish:U,diff:O,hasChanges:!!c,isValid:b,policy:e,createNewRole:M,discardLocalDraft:a,exportPolicy:W,publish:z,saveLocalDraftToServer:K,refetchPolicy:i,updateLocalDraft:u,saveAndPublish:B}},V&&c&&r&&t.createElement(fe,{localPolicy:c,onSelectLocalPolicy:J,onSelectServerPolicy:a,serverPolicy:r}),t.createElement(ye,{open:d.active,onClose:()=>l({active:!1,update:!1}),onPublish:G,policy:e}),p&&t.createElement(de,{isOpen:I,onClose:H,policy:p}),R):q?t.createElement(Z,null):v?se(v)?t.createElement(F,null):t.createElement(_,{error:v??new Error("Unknown")}):null:t.createElement(Pe,{onConfirm:Q,policy:m})}export{Ce as PolicyProvider,S as defaultContext,ge as usePolicyContext};
|
|
2
2
|
//# sourceMappingURL=PolicyProvider.esm.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var s=(t=>(t.Created="created",t.Updated="updated",t.Published="published",t))(s||{});function u(t){const e={type:"created",user:t.createdBy,timestamp:t.createdAt},a=t.status==="active",d=t.createdAt!==t.updatedAt;return a?(e.type="published",e.user=t.lastPublishedBy??"",e.timestamp=t.lastPublishedAt??""):d&&(e.type="updated",e.user=t.updatedBy,e.timestamp=t.updatedAt),e.user.toLocaleLowerCase("en-US").startsWith("user:")||(e.user=`user:${e.user}`),e}export{s as ActivityType,u as getActivityDetails};
|
|
2
|
+
//# sourceMappingURL=getActivityDetails.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useApi as t,alertApiRef as c}from"@backstage/core-plugin-api";import
|
|
1
|
+
import{useApi as t,alertApiRef as c}from"@backstage/core-plugin-api";import f from"react-use/lib/useAsyncFn";import{rbacApiRef as m}from"../../api.esm.js";import{useFetchPolicies as p}from"../Policies/useFetchPolicies.esm.js";function a(e){const i=t(m),o=t(c),{fetchPolicies:s}=p();return f(async()=>{if(e)return i.deleteDraft(e.id).then(s).catch(r=>(o.post({message:r.message,severity:"error"}),Promise.reject(r)))},[e])}export{a as useDeleteDraftPolicy};
|
|
2
2
|
//# sourceMappingURL=useDeleteDraftPolicy.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{useApi as s,alertApiRef as
|
|
1
|
+
import{useApi as s,alertApiRef as m}from"@backstage/core-plugin-api";import{useEffect as c}from"react";import u from"react-use/lib/useAsyncFn";import{rbacApiRef as a}from"../../api.esm.js";function n(){const e=s(a),o=s(m),t=u(async(i,p,f)=>{if(i)return await e.publishPolicy(i.id,{description:p,update:f}),e.getPolicy(i.id)},[]),[{error:r}]=t;return c(()=>{r&&o.post({message:r.message,severity:"error"})},[r,o]),t}export{n as usePublishPolicy};
|
|
2
2
|
//# sourceMappingURL=usePublishPolicy.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{ContentHeader as
|
|
1
|
+
import{ContentHeader as K}from"@backstage/core-components";import{useApi as L,alertApiRef as V,useApp as Z}from"@backstage/core-plugin-api";import{makeStyles as j,Button as q,Grid as y,Card as J,CardHeader as Q,CardContent as U,TextField as X,Box as x}from"@material-ui/core";import{invariant as h}from"@spotify/backstage-plugin-core";import{RoleParser as Y,RolesParser as _}from"@spotify/backstage-plugin-rbac-common";import o,{useState as P}from"react";import{useParams as ee,useNavigate as re}from"react-router-dom";import{getZodValidationToKeyMap as oe}from"../../utils/getZodValidationToKeyMap.esm.js";import{DecisionDialog as te}from"../DecisionDialog/DecisionDialog.esm.js";import{DiffBadge as ne}from"../Diffing/DiffBadge.esm.js";import ie from"../EditableInput/EditableInput.esm.js";import{PageWrapper as le}from"../Layout/PageWrapper.esm.js";import{Title as se}from"../Layout/Title.esm.js";import{MembersTable as me}from"../Members/MembersTable.esm.js";import ae from"../Permissions/PermissionsTable.esm.js";import{PolicyProvider as ce,usePolicyContext as pe}from"../Policy/PolicyProvider.esm.js";function de({roleId:s}){const{versionId:a,roleId:d}=ee(),t=s??d;return h(t),h(a),o.createElement(ce,{policyId:a},o.createElement(R,{roleId:t}))}const fe=j(s=>({cardContainer:{margin:s.spacing(0)}}));function R({roleId:s}){const{diff:a,updateLocalDraft:d,policy:t}=pe(),[T,I]=P(!1),A=L(V),r=t.roles.find(e=>e.id===s),f=a?.roles[s],[c,v]=P(null),[k,p]=P(!1),w=Z(),{NotFoundErrorPage:D}=w.getComponents(),N=re(),B=fe();if(!r)return o.createElement(D,null);const u=r.name,l=e=>{const n=t.roles.findIndex(g=>g.id===e.id),i=[...t.roles];i.splice(n,1,e),d({...t,roles:i})},F=e=>{let n;const i=oe(Y.safeParse({...r,name:e})).name,g=t.roles.findIndex(z=>z.id===r.id),C=[...t.roles];C.splice(g,1,{...r,name:e});const b=_.safeParse(C),E=!b.success;return E&&(n=b.error.issues[0].message),I(i||E),{result:!(i||E),helperText:n}},S=e=>{const{result:n,helperText:i}=F(e);n?l({...r,name:e}):A.post({display:"transient",severity:"error",message:i||"Please specify a valid role name."})},M=e=>{l({...r,description:e})},$=e=>{if(c===null)l({...r,permissions:[e,...r.permissions]});else{const n=[...r.permissions];n.splice(c,1,e),l({...r,permissions:n})}p(!1)},H=e=>{if(e==="*")l({...r,members:r.members==="*"?[]:"*"});else if(r.members==="*")l({...r,members:[e]});else{const n=r.members.includes(e)?r.members.filter(i=>i!==e):[...r.members,e];l({...r,members:n.length===0?"*":n})}},O=e=>{l({...r,permissions:r.permissions.filter((n,i)=>e!==i)})},W=e=>{l({...r,permissions:e})},m=t.status!=="draft",G=t.options.resolutionStrategy==="any-allow";return o.createElement(o.Fragment,null,o.createElement(le,{pages:[{title:t.name,path:`../../../${t.id}`},{title:u}],header:o.createElement(K,{titleComponent:o.createElement(se,null,t.name," \xA0\u01C0",m?o.createElement(o.Fragment,null,"\xA0",u):o.createElement(ie,{invalid:T,value:u,name:"Role name",onTextChange:S}),o.createElement(ne,{operation:f?.role.operation,size:"medium"})),description:t.description||void 0},o.createElement(q,{variant:"outlined",color:"primary",onClick:()=>N("../..",{relative:"path"})},"Back to policy"))},o.createElement(y,{container:!0,className:B.cardContainer,spacing:4,direction:"row"},o.createElement(y,{item:!0,xs:6},o.createElement(J,null,o.createElement(Q,{title:"Description"}),o.createElement(U,null,o.createElement(X,{fullWidth:!0,minRows:3,multiline:!0,variant:"outlined",value:r.description,disabled:m,placeholder:"No description",onChange:e=>M(e.target.value)})))),o.createElement(y,{item:!0,xs:12},o.createElement(x,{mb:4},o.createElement(me,{diff:f||null,role:r,policyId:t.id,onToggleMember:H,readonly:m})),o.createElement(x,{mb:4},o.createElement(ae,{diff:f||null,permissions:r.permissions,onNewPermissionClick:()=>{v(null),p(!0)},onOpenPermission:e=>{v(e),p(!0)},onReorderPermissions:W,onRemovePermissionClick:O,anyAllow:G,readonly:m}))))),k&&o.createElement(te,{rolePermission:c!==null?r.permissions[c]:void 0,onClose:()=>p(!1),onSave:$,readonly:m}))}export{de as RolePage,R as RolePageContent};
|
|
2
2
|
//# sourceMappingURL=RolePage.esm.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{Link as C}from"@backstage/core-components";import{Card as
|
|
1
|
+
import{Link as C}from"@backstage/core-components";import{Card as T,CardHeader as w,Box as i,Button as R,CardContent as x,Table as v,TableHead as A,TableRow as u,TableCell as l,TableBody as B,Typography as d,IconButton as N}from"@material-ui/core";import k from"@material-ui/icons/Add";import I from"@material-ui/icons/Delete";import e from"react";import{useNavigate as D}from"react-router-dom";import{ConfirmationDialog as U}from"../ConfirmationDialog/ConfirmationDialog.esm.js";import{DiffBadge as W}from"../Diffing/DiffBadge.esm.js";import{usePolicyContext as G}from"../Policy/PolicyProvider.esm.js";import{ReorderControls as H}from"../ReorderControls/ReorderControls.esm.js";import{ReorderInfo as L}from"../ReorderControls/ReorderInfo.esm.js";const P="Use the arrows to change the order in which roles are evaluated.";function S({}){const{diff:o,policy:t,createNewRole:n,updateLocalDraft:s}=G(),E=D(),f=$(t),a=t.status!=="draft",c=t.options.resolutionStrategy==="any-allow",y=r=>{s({...t,roles:r})},g=r=>{s({...t,roles:t.roles.filter(({id:m})=>m!==r)})},b=()=>{E(`./roles/${n()}`)};return e.createElement(T,null,e.createElement(w,{title:"Roles",action:!a&&e.createElement(i,{m:1,mt:1.25},e.createElement(R,{color:"primary",variant:"outlined",startIcon:e.createElement(k,null),onClick:()=>b()},"New role"))}),e.createElement(x,null,e.createElement(v,{"data-testid":"rolesTable"},e.createElement(A,null,e.createElement(u,null,!a&&!c&&e.createElement(l,{style:{width:0}},e.createElement(L,{helpText:P})),e.createElement(l,null,"Name"),e.createElement(l,null,"Users"),e.createElement(l,null,"Groups"),!a&&e.createElement(l,{style:{width:0}}))),e.createElement(B,null,f.map((r,m)=>e.createElement(u,{key:m},!a&&!c&&e.createElement(l,null,e.createElement(H,{array:t.roles,index:m,onReorder:y})),e.createElement(l,null,e.createElement(i,{alignItems:"center",display:"flex",gridGap:8},e.createElement(i,null,e.createElement(C,{to:`roles/${r.id}`},e.createElement(d,{color:"textPrimary"},r.name)),r.description&&e.createElement(d,{variant:"body2",color:"textSecondary"},r.description)),e.createElement(W,{operation:o?.roles[r.id].role.operation}))),e.createElement(l,null,r.userCount),e.createElement(l,null,r.groupCount),!a&&e.createElement(l,{align:"right"},e.createElement(U,{message:"Are you sure you want to remove this role?",title:"Remove role?",onConfirm:()=>g(r.id)},h=>e.createElement(N,{...h,"aria-label":"Remove role",size:"small"},e.createElement(I,null))))))))))}function p(o){return o==="*"?"All":o}function $(o){return o.roles.map(t=>({id:t.id,name:t.name,description:t.description,userCount:Array.isArray(t.members)?t.members.filter(n=>n.startsWith("user:")).length:p(t.members),groupCount:Array.isArray(t.members)?t.members.filter(n=>n.startsWith("group:")).length:p(t.members)}))}export{S as RolesTable};
|
|
2
2
|
//# sourceMappingURL=RolesTable.esm.js.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spotify/backstage-plugin-rbac",
|
|
3
3
|
"description": "Control access to actions and data in Backstage with ease.",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.6",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"homepage": "https://backstage.spotify.com",
|
|
7
7
|
"main": "./dist/index.esm.js",
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
"@spotify/backstage-plugin-rbac-backend",
|
|
16
16
|
"@spotify/backstage-plugin-rbac-common",
|
|
17
17
|
"@spotify/backstage-plugin-rbac-node"
|
|
18
|
-
]
|
|
18
|
+
],
|
|
19
|
+
"features": {
|
|
20
|
+
"./alpha": "@backstage/FrontendPlugin"
|
|
21
|
+
}
|
|
19
22
|
},
|
|
20
23
|
"sideEffects": false,
|
|
21
24
|
"exports": {
|
|
@@ -53,22 +56,22 @@
|
|
|
53
56
|
"a11y": "yarn dlx @lhci/cli@0.13.x --config ./.lighthouserc.js autorun"
|
|
54
57
|
},
|
|
55
58
|
"dependencies": {
|
|
56
|
-
"@backstage/catalog-model": "^1.7.
|
|
57
|
-
"@backstage/core-compat-api": "^0.3.
|
|
58
|
-
"@backstage/core-components": "^0.16.
|
|
59
|
-
"@backstage/core-plugin-api": "^1.10.
|
|
60
|
-
"@backstage/errors": "^1.2.
|
|
61
|
-
"@backstage/frontend-plugin-api": "^0.9.
|
|
62
|
-
"@backstage/plugin-catalog-react": "^1.15.
|
|
63
|
-
"@backstage/plugin-permission-common": "^0.8.
|
|
64
|
-
"@backstage/plugin-permission-react": "^0.4.
|
|
65
|
-
"@backstage/theme": "^0.6.
|
|
66
|
-
"@backstage/types": "^1.2.
|
|
59
|
+
"@backstage/catalog-model": "^1.7.3",
|
|
60
|
+
"@backstage/core-compat-api": "^0.3.6",
|
|
61
|
+
"@backstage/core-components": "^0.16.4",
|
|
62
|
+
"@backstage/core-plugin-api": "^1.10.4",
|
|
63
|
+
"@backstage/errors": "^1.2.7",
|
|
64
|
+
"@backstage/frontend-plugin-api": "^0.9.5",
|
|
65
|
+
"@backstage/plugin-catalog-react": "^1.15.2",
|
|
66
|
+
"@backstage/plugin-permission-common": "^0.8.4",
|
|
67
|
+
"@backstage/plugin-permission-react": "^0.4.31",
|
|
68
|
+
"@backstage/theme": "^0.6.4",
|
|
69
|
+
"@backstage/types": "^1.2.1",
|
|
67
70
|
"@material-ui/core": "^4.12.2",
|
|
68
71
|
"@material-ui/icons": "^4.9.1",
|
|
69
72
|
"@material-ui/lab": "4.0.0-alpha.61",
|
|
70
|
-
"@spotify/backstage-plugin-core": "^0.8.
|
|
71
|
-
"@spotify/backstage-plugin-rbac-common": "^0.6.
|
|
73
|
+
"@spotify/backstage-plugin-core": "^0.8.6",
|
|
74
|
+
"@spotify/backstage-plugin-rbac-common": "^0.6.6",
|
|
72
75
|
"ajv": "^8.11.2",
|
|
73
76
|
"file-saver": "^2.0.5",
|
|
74
77
|
"js-yaml": "^4.1.0",
|
|
@@ -82,19 +85,19 @@
|
|
|
82
85
|
"zod-to-json-schema": "^3.20.2"
|
|
83
86
|
},
|
|
84
87
|
"peerDependencies": {
|
|
85
|
-
"react": "^
|
|
86
|
-
"react-dom": "^
|
|
88
|
+
"react": "^17.0.0 || ^18.0.0",
|
|
89
|
+
"react-dom": "^17.0.0 || ^18.0.0",
|
|
87
90
|
"react-router-dom": "6.0.0-beta.0 || ^6.3.0"
|
|
88
91
|
},
|
|
89
92
|
"devDependencies": {
|
|
90
|
-
"@backstage/cli": "^0.
|
|
91
|
-
"@backstage/core-app-api": "^1.15.
|
|
92
|
-
"@backstage/dev-utils": "^1.1.
|
|
93
|
+
"@backstage/cli": "^0.30.0",
|
|
94
|
+
"@backstage/core-app-api": "^1.15.5",
|
|
95
|
+
"@backstage/dev-utils": "^1.1.7",
|
|
93
96
|
"@backstage/e2e-test-utils": "^0.1.1",
|
|
94
|
-
"@backstage/frontend-test-utils": "^0.2.
|
|
95
|
-
"@backstage/test-utils": "^1.7.
|
|
97
|
+
"@backstage/frontend-test-utils": "^0.2.6",
|
|
98
|
+
"@backstage/test-utils": "^1.7.5",
|
|
96
99
|
"@playwright/test": "^1.32.3",
|
|
97
|
-
"@sp4b-dev/test-utils": "^0.0.
|
|
100
|
+
"@sp4b-dev/test-utils": "^0.0.12",
|
|
98
101
|
"@testing-library/jest-dom": "^6.0.0",
|
|
99
102
|
"@testing-library/react": "^14.0.0",
|
|
100
103
|
"@testing-library/user-event": "^14.0.0",
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
function c(e,d,a){let i=d.created,t=e.createdBy;a?.created&&(t=a.created+t);let u=e.createdAt;return e.status==="active"?(i=d.published,t=e.lastPublishedBy??"",a?.published&&(t=a.published+t),u=e.lastPublishedAt??""):e.createdAt!==e.updatedAt&&(i=d.updated,t=e.updatedBy,a?.updated&&(t=a.updated+t),u=e.updatedAt),{activityDateText:i,activityUser:t,timestamp:u}}export{c as getActivityDescription};
|
|
2
|
-
//# sourceMappingURL=getActivityDescriptions.esm.js.map
|