@spotify/backstage-plugin-rbac 0.2.1

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/LICENSE.md ADDED
@@ -0,0 +1,9 @@
1
+ # Commercial License
2
+
3
+ Copyright (c) 2022 Spotify. All rights reserved.
4
+
5
+ This software is part of the "Spotify Plugins for Backstage" bundle. "Spotify
6
+ Plugins for Backstage" is commercial software. To use it, you must obtain a
7
+ license and agree to the [License
8
+ Terms](https://backstage.spotify.com/spotify-plugins-for-backstage-terms).
9
+ Commercial licenses can be obtained at https://backstage.spotify.com/.
package/README.md ADDED
@@ -0,0 +1,199 @@
1
+ # Spotify Plugins for Backstage: Role-Based Access Control (RBAC) - Frontend
2
+
3
+ ![](https://spotify-plugins-for-backstage-readme-images.spotifycdn.com/rbac.png)
4
+
5
+ The RBAC plugin works with the [Backstage permission framework](https://backstage.io/docs/permissions/overview) to provide support for role-based access control in Backstage. The Backstage permission framework is a system in the open-source Backstage project, which allows granular control of access to specific resources or actions. The permission framework is currently supported in the Catalog and TechDocs, with other core features soon to come. In the future, we’ll encourage third-party plugin authors to add permission support too — which can be done without changes to the Backstage core.
6
+
7
+ Permissions are controlled in a Backstage instance through a **policy**. A policy is simply an async function which receives a request to authorize a specific action for a user and (optional) resource, and returns a decision on whether to authorize that permission. Without the RBAC plugin, integrators must implement their own policies from scratch, or adapt reusable policies written by others.
8
+
9
+ The RBAC plugin allows you to control permissions in Backstage without writing code. Instead, you can manage your policy using the RBAC interface integrated with Backstage. Once you publish the changes to your policy, they will be reflected immediately.
10
+
11
+ With the RBAC plugin, you manage the permissions in your Backstage instance by assigning users and groups to roles, and configuring the rules that should apply for each role. You can use powerful matching features to keep your policy short, or supply granular decisions for each available permission and role.
12
+
13
+ ## Prerequisites
14
+
15
+ ### 1. Install the RBAC Backend plugin
16
+
17
+ You must install the [RBAC Backend](https://npmjs.com/@spotify/backstage-plugin-rbac-backend) and all of its prerequisites before installing the RBAC frontend.
18
+
19
+ ## Installation
20
+
21
+ ### 1. Getting the plugin
22
+
23
+ Add the RBAC packages as dependencies to your Backstage instance:
24
+
25
+ ```bash
26
+ yarn workspace app add @spotify/backstage-plugin-rbac
27
+ ```
28
+
29
+ ### 2. Install RBAC frontend
30
+
31
+ First install the RBAC routes in the app within the `packages/app/src/App.tsx`. This will provide the UI for authoring your RBAC policy under the `/rbac` route. Note that this route can only be accessed by the `authorizedUsers` configured above.
32
+
33
+ ```diff
34
+ // packages/app/src/App.tsx
35
+
36
+ + import { RBACRoot } from '@spotify/backstage-plugin-rbac';
37
+
38
+ /* ... */
39
+
40
+ const routes = (
41
+ <FlatRoutes>
42
+ /* ... */
43
+ + <Route path="/rbac" element={<RBACRoot />} />
44
+ </FlatRoutes>
45
+ );
46
+ ```
47
+
48
+ RBAC also provides a sidebar item that will only be visible to RBAC `authorizedUsers`. This is an optional step, but it provides an easy way for RBAC authorized users to access the plugin.
49
+
50
+ ```diff
51
+ // packages/app/src/components/Root.tsx
52
+
53
+ + import { RBACSidebarItem } from '@spotify/backstage-plugin-rbac';
54
+
55
+ export const Root = ({ children }: PropsWithChildren<{}>) => (
56
+ <SidebarPage>
57
+ <Sidebar>
58
+ <SidebarLogo />
59
+
60
+ /* ... */
61
+
62
+ <SidebarScrollWrapper>
63
+ <SidebarItem icon={MapIcon} to="tech-radar" text="Tech Radar" />
64
+ <SidebarItem
65
+ icon={SkillExchangeIcon}
66
+ to="skill-exchange"
67
+ text="Skill Exchange"
68
+ />
69
+ <SidebarItem icon={PulseIcon} to="pulse" text="Pulse" />
70
+ <SidebarItem icon={SoundcheckIcon} to="soundcheck" text="Soundcheck" />
71
+ + <RBACSidebarItem />
72
+ </SidebarScrollWrapper>
73
+ </Sidebar>
74
+ </SidebarPage>
75
+ );
76
+ ```
77
+
78
+ ### 3. Configure an initial policy
79
+
80
+ When there is no published RBAC policy, the default behaviour of RBAC is to deny all authorization requests sent to the permission framework. With this in mind, it's preferable to publish a simple RBAC policy before proceeding to install RBAC in the permission framework.
81
+
82
+ The following instructions configure RBAC with a policy that allows all authorization requests. If you want to start with something more complex, refer to later sections of this documentation.
83
+
84
+ 1. Open the RBAC UI by visiting the `/rbac` path in your Backstage instance, or clicking the RBAC item in the sidebar (if you've installed the `RBACSidebarItem`).
85
+ 1. Click "New Version" to start working on a new draft policy, and choose a name for it.
86
+ 1. Click "New Role" to create a role within the policy, and give that a name too.
87
+ 1. Click the "New Permission Decision" button in the Permission Decisions table on the right hand side.
88
+ 1. In the dialog, select "Match All Permissions".
89
+ 1. Confirm that "Allow" is already selected at the bottom of the dialog.
90
+ 1. Click "Save".
91
+ 1. Confirm that the Members table on the left hand side contains a row for "All" users.
92
+ 1. Click "Back to Policy"
93
+ 1. Click "Save Draft"
94
+ 1. Click "Publish", and confirm publishing in the confirmation dialog.
95
+
96
+ ### 4. Install the RBAC policy in the permission framework
97
+
98
+ To use the RBAC policy in the Backstage instance, we replace the `TestPermissionPolicy` we created when setting up the permission framework with an `RBACPolicy` instance which uses the roles we define in the UI.
99
+
100
+ Adjust `packages/backend/src/plugins/permission.ts` as follows:
101
+
102
+ ```diff
103
+ import { createRouter } from '@backstage/plugin-permission-backend';
104
+ - import {
105
+ - AuthorizeResult,
106
+ - PolicyDecision,
107
+ - } from '@backstage/plugin-permission-common';
108
+ - import { PermissionPolicy } from '@backstage/plugin-permission-node';
109
+ + import { RBACPolicyBuilder } from '@spotify/backstage-plugin-rbac-backend';
110
+ import { Router } from 'express';
111
+ import { PluginEnvironment } from '../types';
112
+
113
+ - class TestPermissionPolicy implements PermissionPolicy {
114
+ - async handle(): Promise<PolicyDecision> {
115
+ - return { result: AuthorizeResult.ALLOW };
116
+ - }
117
+ - }
118
+ -
119
+ export default async function createPlugin(
120
+ env: PluginEnvironment,
121
+ ): Promise<Router> {
122
+ return await createRouter({
123
+ config: env.config,
124
+ logger: env.logger,
125
+ discovery: env.discovery,
126
+ - policy: new TestPermissionPolicy(),
127
+ + policy: await RBACPolicyBuilder.create(env).build(),
128
+ identity: env.identity,
129
+ });
130
+ }
131
+ ```
132
+
133
+ ### 5. Check everything is working
134
+
135
+ If you've followed all the steps up to this point, the RBAC policy is now in place! You should find that Backstage adheres to the policy you configured in step 3. If you have any problems, please reach out to us and we'll be happy to provide support.
136
+
137
+ ## Working with the RBAC UI
138
+
139
+ ### Publishing Lifecycle
140
+
141
+ The RBAC UI provides the ability to build **RBAC policies**. When a policy is first created, it is in **draft** state, and doesn't have any effect on the behavior of Backstage. You can save draft policies while you're working on them, and come back to them later. Once a draft policy is ready, it can be **published**. There is only one published policy in Backstage at any given time. A newly-published policy replaces the existing one, which moves to **inactive** state. Inactive policies can be republished at any time.
142
+
143
+ ### Policy Overview
144
+
145
+ The RBAC policy is configured by defining one or more **roles**, to which you can add users/groups as members. Each role can have multiple **permission decisions** configured, which match one or more **permissions**, and specify the authorization **decision** that should be made for those permissions.
146
+
147
+ Users can be a member of multiple roles, and roles can overlap in the permissions they match. When a given permission matches multiple times, the **first match** will be the one used to determine the decision returned.
148
+
149
+ ### Matching permissions
150
+
151
+ Permissions are a core concept in the Backstage permission framework. Each plugin can define a set of permissions that control what users can see and do within that plugin. Each [permission](https://github.com/backstage/backstage/blob/master/plugins/permission-common/src/types/permission.ts#L39) is an object with the following fields:
152
+
153
+ - **name**: a string which uniquely identifies the permission, such as `catalog.entity.read`
154
+ - **attributes**: an object containing attributes which describe the characteristics of the permission, to allow matching multiple permissions when making a policy decision. We expect the number of supported attributes to increase over time, but for now, the only attribute is `action`, which can be set to `"create"`, `"read"`, `"update"`, or `"delete"`.
155
+ - **resourceType**: the type of resource expected to be supplied when authorizing this permission, if applicable (for example `catalog-entity`).
156
+
157
+ In the RBAC UI, it's possible to match a single specific permission by name, or to match using a combination of resourceType and actions in order to match multiple permissions with a single entry in the list. It's also possible to match all permissions with a single entry - this is mostly useful for defining a fallback at the end of your policy, in case no other permission decision in the policy matched a request.
158
+
159
+ ### Specifying decisions
160
+
161
+ The RBAC UI supports definitive `allow` or `deny` decisions, as well as [conditional decisions](https://backstage.io/docs/permissions/writing-a-policy#conditional-decisions) whose result can vary based on characteristics of the resource being authorized. Conditional decisions can only be returned for permissions with a resourceType - the RBAC UI handles enabling and disabling the "conditional" option as needed.
162
+
163
+ Conditional decisions contain one or more **conditions**, which are exported by permissioned plugins and tied to a resourceType. The condition `HAS_ANNOTATION`, for example, is tied to the `catalog-entity` resourceType, and checks whether a catalog entity has a certain annotation. Multiple conditions can be combined using "any of" (return `allow` when any one of these conditions is true), or "all of" (only return `allow` when all of these conditions is true). It's also possible to negate conditions using "not", and combinations of conditions and logical operators can be deeply nested if needed.
164
+
165
+ ## Other features
166
+
167
+ ### Import / Export
168
+
169
+ The RBAC plugin allows users to export existing policies, a feature which can be found within the policy page. You can import the resulting yaml file back into RBAC, which will result in a draft policy identical to the exported policy. This can be useful when working with multiple Backstage instances with similar configurations.
170
+
171
+ ### Default policy
172
+
173
+ The RBAC plugin allows Backstage administrators to configure a default policy for deployment. Setting a default policy allows RBAC to enforce an active policy from the start, before any administrator has interacted with the RBAC UI. You can set a default policy by:
174
+
175
+ 1. Create a draft policy in the RBAC UI that represents the policy that you would like to become the default policy.
176
+ 1. Go to the draft policy page, and download the policy by clicking "Export." Alternatively, you can export any previous version or the active policy from the respective policy pages.
177
+ 1. Add a `defaultPolicy` field under the `rbac` field in your `app-config.yaml`, and point it to the file you saved from the previous step:
178
+
179
+ ```yaml
180
+ permission:
181
+ rbac:
182
+ defaultPolicy:
183
+ $include: ./default-rbac-policy.yaml
184
+ ```
185
+
186
+ 1. You should now see that your Backstage instance behaves as configured in your default policy, even though you have not yet authored any other policies using the RBAC UI.
187
+
188
+ **NOTE:** The default policy will be active if and only if no other active policies already exist.
189
+
190
+ ### Fallback policy
191
+
192
+ By default, when a request to the RBAC backend fails, RBAC will automatically switch to denying all permissions. You can configure this behavior by specifying a fallback policy in your `app-config.yaml` in the exact same way as the default policy:
193
+
194
+ ```yaml
195
+ permission:
196
+ rbac:
197
+ fallbackPolicy:
198
+ $include: ./fallback-rbac-policy.yaml
199
+ ```
package/config.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ import type {
2
+ LiteralDecision,
3
+ Policy,
4
+ } from '@spotify/backstage-plugin-rbac-common';
5
+
6
+ export interface Config {
7
+ permission?: {
8
+ /**
9
+ * A list of plugins which export permissions and permission rules. If
10
+ * listed here, the plugin's permissions and permission rules will be
11
+ * aggregated and displayed in the RBAC UI.
12
+ * @visibility frontend
13
+ */
14
+ permissionedPlugins?: string[];
15
+
16
+ rbac?: {
17
+ /**
18
+ * A list of features that are enabled in the RBAC UI.
19
+ * @visibility frontend
20
+ */
21
+ flags?: string[];
22
+ /**
23
+ * A default policy that is seeded into the RBAC database
24
+ * on startup, when no policies already exist.
25
+ * @visibility backend
26
+ */
27
+ defaultPolicy?: Policy;
28
+ /**
29
+ * A fallback policy that is used when there is an error
30
+ * in Backstage or the RBAC backend and no active policy
31
+ * is being used. If no fallback policy is specified, RBAC
32
+ * will continue to DENY ALL as it did previously by default.
33
+ * @visibility backend
34
+ */
35
+ fallbackPolicy?: Policy;
36
+ };
37
+ };
38
+ }
@@ -0,0 +1,2 @@
1
+ import{useApi as u}from"@backstage/core-plugin-api";import e from"react";import i from"react-use/lib/useAsync";import{r as m}from"./index-bb1908ac.esm.js";function c({children:n,loading:o=null,unauthorized:a=null}){var r;const l=u(m),t=i(()=>l.authorize(),[]);return t.loading?e.createElement(e.Fragment,null,o):(r=t.value)!=null&&r.authorized?e.createElement(e.Fragment,null,n):e.createElement(e.Fragment,null,a)}export{c as A};
2
+ //# sourceMappingURL=Authorized-296ab754.esm.js.map
@@ -0,0 +1,2 @@
1
+ import r from"react";import e from"@material-ui/icons/Lock";import{SidebarItem as m}from"@backstage/core-components";import{A as i}from"./Authorized-296ab754.esm.js";import"@backstage/core-plugin-api";import"react-use/lib/useAsync";import"./index-bb1908ac.esm.js";import"@backstage/errors";function p({text:t="RBAC",...o}){return r.createElement(i,null,r.createElement(m,{icon:e,to:"rbac",text:t,...o}))}export{p as RBACSidebarItem};
2
+ //# sourceMappingURL=RBACSidebarItem-ca7b78f0.esm.js.map
@@ -0,0 +1,3 @@
1
+ import e,{createContext as Te,useState as B,useCallback as w,useMemo as $,useContext as Se,useEffect as G,Fragment as pe,useRef as Z,useReducer as sn,useLayoutEffect as mn}from"react";import{Link as un,useNavigate as Y,useParams as rt,Routes as dn,Route as Re}from"react-router-dom";import{useApi as k,configApiRef as pn,alertApiRef as Q,useApp as we,useRouteRef as fn}from"@backstage/core-plugin-api";import Ie from"react-use/lib/useAsync";import{isResourcePermission as at}from"@backstage/plugin-permission-common";import{r as j,a as En}from"./index-bb1908ac.esm.js";import{forEach as yn,mapValues as gn,groupBy as hn,uniq as bn}from"lodash";import{Link as ee,Progress as fe,ErrorPanel as lt,Table as vn,Breadcrumbs as Cn,Page as Dn,Header as Pn,Content as xn,ContentHeader as ke,EmptyState as Ee}from"@backstage/core-components";import J from"react-use/lib/useAsyncFn";import ot from"react-use/lib/useMount";import{makeStyles as N,Chip as it,Box as p,Typography as D,Card as K,CardContent as ye,List as An,ListItem as ct,ListItemIcon as st,ListItemText as mt,CardActions as Nn,Dialog as te,DialogTitle as ge,IconButton as H,DialogContent as q,DialogActions as Be,Button as x,TextField as le,Container as Tn,Grid as V,debounce as Sn,Checkbox as Oe,CircularProgress as Rn,Table as Me,TableHead as _e,TableRow as W,TableCell as v,TableBody as $e,FormControlLabel as ut,Tooltip as he,FormHelperText as dt,InputLabel as be,Paper as wn,Popper as In,Menu as kn,MenuItem as ne,FormControl as Le,Select as Fe,Tabs as Bn,Tab as On,Divider as Mn,DialogContentText as _n,CardHeader as $n}from"@material-ui/core";import Ln from"@material-ui/icons/Publish";import Fn from"@material-ui/icons/FilterNone";import{DateTime as L}from"luxon";import pt from"lodash/omit";import{saveAs as jn}from"file-saver";import Hn,{dump as Vn}from"js-yaml";import Wn from"lodash/pickBy";import ve from"@material-ui/icons/Close";import zn from"@material-ui/icons/CalendarToday";import Gn from"@material-ui/icons/Person";import Un from"@material-ui/icons/FiberManualRecord";import ft from"lodash/keyBy";import Yn from"lodash/isEqual";import{isConditionalDecision as je,PolicyConfigParser as Ce,BackstageUserPlaceholder as oe,isAllOfPermissionCriteria as Jn,isAnyOfPermissionCriteria as Kn,isNotPermissionCriteria as qn,isMatchingPermission as Xn,RoleParser as Zn,UpdateDraftRequestParser as Qn}from"@spotify/backstage-plugin-rbac-common";import{v4 as re}from"uuid";import Et from"@material-ui/icons/ReportProblemOutlined";import er from"react-use/lib/useLocalStorage";import{SpotifyLicenseBanner as tr,invariant as He}from"@spotify/backstage-plugin-core";import Ve from"@material-ui/icons/Add";import ie from"@material-ui/icons/Delete";import{parseEntityRef as We,DEFAULT_NAMESPACE as nr}from"@backstage/catalog-model";import{humanizeEntityRef as rr}from"@backstage/plugin-catalog-react";import{Autocomplete as ze,ToggleButton as ar,ToggleButtonGroup as lr}from"@material-ui/lab";import or from"lodash/uniqBy";import yt from"@material-ui/icons/Info";import ir from"@material-ui/icons/Edit";import cr from"@material-ui/icons/Check";import{JSONEditor as sr,isTextContent as mr,createAjvValidator as ur,Mode as dr}from"vanilla-jsoneditor";import gt from"ajv";import pr from"@material-ui/icons/Remove";import fr from"@material-ui/icons/KeyboardArrowDown";import Er from"@material-ui/icons/KeyboardArrowUp";import yr from"../images/no-permissions.svg";import gr from"../images/no-roles.svg";import{A as hr}from"./Authorized-296ab754.esm.js";import"@backstage/errors";const ht=Te(null),br=({children:t})=>{const n=k(pn),a=k(j),l=k(Q),[r,o]=B(null),c=w(async()=>{var m;if(!r){const u=await a.fetchAllPermissionMetadata((m=n.getOptionalStringArray("permission.permissionedPlugins"))!=null?m:[]),i=Cr(u.rules);yn(i,f=>{f.length!==1&&l.post({message:`The plugin(s) ${f.slice(1).join(", ")} expose rules which are conflicting with rules exposed by the ${f[0]} plugin. These rules will not be available for use. Please contact RBAC support if you need assistance resolving this issue.`,severity:"error"})});const s=Dr(u,i);return o(s),s}return r},[l,r,a,n]);return e.createElement(ht.Provider,{value:$(()=>({getMetadata:c}),[c])},t)};function De(){const t=Se(ht),{value:n}=Ie(async()=>t?.getMetadata(),[t]);return n}function bt(){var t;const n=De();return(t=n?.rules)!=null?t:null}function vt(){var t;const n=De();return(t=n?.permissions)!=null?t:null}function Ct(){const t=De();return t?[...new Set(t.permissions.filter(n=>at(n)).map(({resourceType:n})=>n))]:null}function vr(){const t=De(),n=Ct();return!t||!n?null:n.reduce((a,l)=>{const r=t.rules.find(o=>o.resourceType===l);return r&&(a[l]={pluginId:r.pluginId}),a},{})}function Cr(t){return gn(hn(t,"resourceType"),n=>bn(n.map(({pluginId:a})=>a)))}function Dr(t,n){return{...t,rules:t.rules.filter(({resourceType:a,pluginId:l})=>{const r=n[a];return l===r[0]})}}function Pr(t){throw new Error("Invalid state")}function xr(t){var n,a;return((a=(n=t?.body)==null?void 0:n.response)==null?void 0:a.statusCode)===404}function Dt(t){const n=new Blob([Ar(t)],{type:"text/yaml"});jn(n,`${(t.name||"policy").toLocaleLowerCase().replace(/\W/g,"-")}.yaml`)}function Ar(t){const{name:n,roles:a,description:l}=t;return`# this is an autogenerated file, do not edit
2
+ ${Vn(Wn({name:n,description:l,roles:a.map(({permissions:o,...c})=>({...pt(c,["id"]),permissions:o.map(m=>pt(m,["id"]))}))},o=>o!==null||o!==void 0))}`}const Pt=Te({policies:void 0,setPolicies:()=>{},setPolicy:()=>{},getPolicy:()=>{},removePolicy:()=>{}}),Ge=()=>Se(Pt);function Nr({children:t,initialState:n={policies:void 0,cache:{}}}){const[a,l]=B(n),r=w(u=>{l(i=>({...i,policies:u,cache:xt(i.cache,u)}))},[]),o=w(u=>a.cache[u],[a.cache]),c=w(u=>l(i=>({...i,cache:{...i.cache,[u]:void 0},policies:void 0})),[]),m=w(u=>l(i=>({...i,policies:void 0,cache:xt(i.cache,[u])})),[]);return e.createElement(Pt.Provider,{value:$(()=>({policies:a.policies,setPolicies:r,setPolicy:m,getPolicy:o,removePolicy:c}),[a.policies,r,m,o,c])},t)}function xt(t,n){if(!n)return t;const a={...t};return n.forEach(l=>{a[l.id]=l}),a}const ce=()=>{const t=k(j),{setPolicies:n,policies:a}=Ge(),[{loading:l,error:r},o]=J(()=>t.getPolicies(),[t],a?{loading:!1,value:{items:a,totalItems:a.length}}:{loading:!0}),c=w(async()=>{const m=await o();n(m.items)},[o,n]);return{loading:l,error:r,fetchPolicies:c}};function At(){const t=k(j),n=k(Q),{fetchPolicies:a}=ce();return J(async l=>{if(!l)return;const{roles:r,name:o}=l;return t.createDraft({roles:r,name:o}).then(a).catch(c=>(n.post({message:c.message,severity:"error"}),Promise.reject(c)))},[])}function Nt(){const t=k(j),n=k(Q),a=J(async(r,o)=>{if(r)return await t.publishPolicy(r.id,{description:o}),t.getPolicy(r.id)},[]),[{error:l}]=a;return G(()=>{l&&n.post({message:l.message,severity:"error"})},[l,n]),a}const Tr=N(t=>({chip:{margin:0},icon:{color:t.palette.success.main}}));function Tt(t){const n=Tr();return t.status==="inactive"?null:t.status==="draft"?e.createElement(it,{className:n.chip,label:"Draft",size:t.size}):e.createElement(it,{className:n.chip,classes:{icon:n.icon},label:"Active",icon:e.createElement(Un,null),size:t.size})}const Ue=(t,n)=>{const a=Object.entries(t);for(const[,l]of a){const r=n(l);for(const[,o]of a){const c=n(o);c.operation!=="ADDED"&&c.operation!=="REMOVED"&&(r.operation==="ADDED"&&r.indexAfter<c.indexAfter?c.indexBefore+=1:r.operation==="REMOVED"&&r.indexBefore<c.indexBefore&&(c.indexBefore-=1))}}for(const[,l]of a){const r=n(l);r.operation==="UNCHANGED"&&r.indexAfter!==r.indexBefore&&(r.operation=r.indexAfter>r.indexBefore?"MOVED_DOWN":"MOVED_UP")}return t},Ye=(t,n)=>{const a=ft(n,"id"),l=Object.fromEntries(n.map((r,o)=>[r.id,{operation:"ADDED",indexAfter:o,indexBefore:-1,after:r,before:null}]));for(let r=0;r<t.length;r++){const o=t[r];if(l[o.id]){const c=!Yn(o,a[o.id]);l[o.id].before=o,l[o.id].indexBefore=r,l[o.id].operation=c?"CHANGED":"UNCHANGED"}else l[o.id]={operation:"REMOVED",after:null,before:o,indexAfter:-1,indexBefore:r}}return Ue(l,r=>r)},Je=(t,n)=>{if(t==="*")return n==="*"?{"*":{operation:"UNCHANGED",after:"*",before:"*",indexAfter:0,indexBefore:0}}:{"*":{operation:"REMOVED",after:null,before:"*",indexAfter:-1,indexBefore:0},...Object.fromEntries(n.map((l,r)=>[l,{operation:"ADDED",after:l,before:null,indexAfter:r,indexBefore:-1}]))};if(n==="*")return{"*":{operation:"ADDED",after:"*",before:null,indexAfter:0,indexBefore:-1},...Object.fromEntries(t.map((l,r)=>[l,{operation:"REMOVED",after:null,before:l,indexAfter:-1,indexBefore:r}]))};const a=Object.fromEntries(n.map((l,r)=>[l,{operation:"ADDED",after:l,before:null,indexAfter:r,indexBefore:-1}]));for(let l=0;l<t.length;l++){const r=t[l];a[r]?(a[r].before=r,a[r].indexBefore=l,a[r].operation="UNCHANGED"):a[r]={operation:"REMOVED",after:null,before:r,indexAfter:-1,indexBefore:l}}return Ue(a,l=>l)},Sr=(t=[],n=[])=>{const a=ft(n,"id"),l=Object.fromEntries(n.map((r,o)=>[r.id,{role:{operation:"ADDED",indexAfter:o,indexBefore:-1,after:r,before:null},members:Je([],r.members),permissions:Ye([],r.permissions)}]));for(let r=0;r<t.length;r++){const o=t[r];if(a[o.id]){const c=a[o.id],m=Je(o.members,c.members),u=Ye(o.permissions,c.permissions),i=Object.values(u).some(({operation:h})=>h!=="UNCHANGED"),s=Object.values(m).some(({operation:h})=>h!=="UNCHANGED"),E=o.name!==c.name||i||s;l[o.id].role.before=o,l[o.id].role.indexBefore=r,l[o.id].role.operation=E?"CHANGED":"UNCHANGED",l[o.id].members=m,l[o.id].permissions=u}else l[o.id]={role:{operation:"REMOVED",after:null,before:o,indexAfter:-1,indexBefore:r},members:Je(o.members,[]),permissions:Ye(o.permissions,[])}}return Ue(l,({role:r})=>r)},Rr=(t,n)=>{const a=t.name!==n.name,l=Sr(t.roles||[],n.roles||[]);return{policy:{operation:a?"CHANGED":"UNCHANGED",before:t,after:n},roles:l}},St=t=>{const n=k(j),{value:a}=Ie(()=>n.getActivePolicy(),[n]);return $(()=>a&&t?Rr(a,t):null,[a,t])};function Ke(t){var n;if(t.match==="*")return"All";if(t.match.name)return t.match.name;const a=[];return t.match.resourceType&&a.push(t.match.resourceType),(n=t.match.actions)!=null&&n.length&&a.push(t.match.actions.join(", ")),a.join(" | ")}function wr(t){var n;return je(t.decision)?"Conditional":(n={allow:"Allow",deny:"Deny"}[t.decision])!=null?n:"Unknown"}const qe=(t,n)=>{switch(n){case"ADDED":return t.palette.success.main;case"REMOVED":return t.palette.error.main;case"CHANGED":return t.palette.info.main;case"MOVED_UP":case"MOVED_DOWN":return t.palette.info.main;case"UNCHANGED":default:return t.palette.text.primary}},Ir=t=>{switch(t){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"}},kr=N(t=>({root:({operation:n})=>({color:qe(t,n)})})),_=t=>e.createElement(D,{...t,variant:"body2"}),b=t=>{const n=kr(t);return e.createElement(p,{...t,className:n.root,component:"span",fontWeight:"fontWeightBold"})},Rt=({policy:t})=>{var n,a,l;const r=St(t),o=r?.policy.operation==="CHANGED"||Object.values((n=r?.roles)!=null?n:{}).some(i=>i.role.operation!=="UNCHANGED");if(!r||!o)return e.createElement(p,null,"No changes");const c=!!r.policy.before&&!!r.policy.after&&r.policy.before.name!==r.policy.after.name,m=({before:i,after:s})=>i&&s&&i.name!==s.name,u=({operation:i})=>i!=="ADDED"&&i!=="REMOVED";return e.createElement(p,null,c&&e.createElement(_,null,"Policy name ",e.createElement(b,{operation:"CHANGED"},"changed")," from"," ",e.createElement(b,null,'"',(a=r.policy.before)==null?void 0:a.name,'"')," to"," ",e.createElement(b,null,'"',(l=r.policy.after)==null?void 0:l.name,'"')),Object.entries(r.roles).map(([i,{role:s,permissions:f,members:E}])=>{var h,y,d,g,P,S;return e.createElement(pe,{key:i},s.operation==="ADDED"&&e.createElement(_,null,"Role ",e.createElement(b,null,'"',(h=s.after)==null?void 0:h.name,'"')," has been"," ",e.createElement(b,{operation:"ADDED"},"added")),s.operation==="REMOVED"&&e.createElement(_,null,"Role ",e.createElement(b,null,'"',(y=s.before)==null?void 0:y.name,'"')," has been"," ",e.createElement(b,{operation:"REMOVED"},"removed")),m(s)&&e.createElement(_,null,"Role name changed from ",e.createElement(b,null,'"',(d=s.before)==null?void 0:d.name,'"')," ","to ",e.createElement(b,null,'"',(g=s.after)==null?void 0:g.name,'"')),s.indexAfter>s.indexBefore&&s.indexBefore!==-1&&e.createElement(_,null,"Role ",e.createElement(b,null,'"',(P=s.after)==null?void 0:P.name,'"')," has been"," ",e.createElement(b,{operation:"MOVED_DOWN"},"moved down")," in priority"),s.indexAfter<s.indexBefore&&s.indexAfter!==-1&&e.createElement(_,null,"Role ",e.createElement(b,null,'"',(S=s.after)==null?void 0:S.name,'"')," has been"," ",e.createElement(b,{operation:"MOVED_UP"},"moved up")," in priority"),u(s)&&e.createElement(e.Fragment,null,Object.entries(f).map(([I,A])=>{var F,O,T,C,M;const{before:R,after:z}=A,X=R&&Ke(R),U=z&&Ke(z);return e.createElement(pe,{key:I},A.operation==="ADDED"&&A.after&&e.createElement(_,null,"Permission decision"," ",e.createElement(b,null,'"',U,'"')," has been"," ",e.createElement(b,{operation:"ADDED"},"added")," to"," ",e.createElement(b,null,'"',(F=s.after)==null?void 0:F.name,'"')),A.operation==="REMOVED"&&A.before&&e.createElement(_,null,"Permission decision"," ",e.createElement(b,null,'"',X,'"')," has been"," ",e.createElement(b,{operation:"REMOVED"},"removed")," ","from ",e.createElement(b,null,'"',(O=s.after)==null?void 0:O.name,'"')),A.operation==="CHANGED"&&e.createElement(_,null,X!==U?e.createElement(e.Fragment,null,"Permission decision"," ",e.createElement(b,null,'"',X,'"')," has been"," ",e.createElement(b,{operation:"CHANGED"},"updated")," ","to ",e.createElement(b,null,'"',U,'"')):e.createElement(e.Fragment,null,"Permission decision"," ",e.createElement(b,null,'"',X,'"')," has been"," ",e.createElement(b,{operation:"CHANGED"},"updated"))," ","in ",e.createElement(b,null,'"',(T=s.after)==null?void 0:T.name,'"')),A.indexAfter>A.indexBefore&&A.indexBefore!==-1&&e.createElement(_,null,"Permission decision"," ",e.createElement(b,null,'"',U,'"')," has been"," ",e.createElement(b,{operation:"MOVED_DOWN"},"moved down")," ","in priority in"," ",e.createElement(b,null,'"',(C=s.after)==null?void 0:C.name,'"')),A.indexAfter<A.indexBefore&&A.indexAfter!==-1&&e.createElement(_,null,"Permission decision"," ",e.createElement(b,null,'"',U,'"')," has been"," ",e.createElement(b,{operation:"MOVED_UP"},"moved up")," ","in priority in"," ",e.createElement(b,null,'"',(M=s.after)==null?void 0:M.name,'"')))}),Object.entries(E).map(([I,A])=>{var F,O;return e.createElement(pe,{key:I},A.operation==="ADDED"&&A.after&&e.createElement(_,null,"Member ",e.createElement(b,null,'"',A.after,'"')," has been"," ",e.createElement(b,{operation:"ADDED"},"added")," to"," ",e.createElement(b,null,'"',(F=s.after)==null?void 0:F.name,'"')),A.operation==="REMOVED"&&A.before&&e.createElement(_,null,"Member ",e.createElement(b,null,'"',A.before,'"')," has been"," ",e.createElement(b,{operation:"REMOVED"},"removed")," from"," ",e.createElement(b,null,'"',(O=s.after)==null?void 0:O.name,'"')))})))}))},Br=N(t=>({card:n=>({backgroundImage:n.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.caption,paddingTop:t.spacing(3),color:t.palette.text.secondary},activityList:{color:t.palette.text.secondary},activityListItem:{padding:0},actions:{justifyContent:"flex-start"}}));function se(t){var n,a;const l=Br(t),{policy:r,to:o,withChangeSummary:c}=t,m=`${r.name} ${r.status==="draft"?"- Draft":""}`;let u="Created on ",i=L.fromISO(r.createdAt),s=`Created by ${r.createdBy}`;return r.status==="active"?(u="Published on ",i=L.fromISO((n=r.lastPublishedAt)!=null?n:""),s=`Published by ${r.lastPublishedBy}`):r.createdAt!==r.updatedAt&&(u="Updated on ",i=L.fromISO((a=r.updatedAt)!=null?a:""),s=`Updated by ${r.updatedBy}`),u+=i.toLocaleString(L.DATETIME_MED_WITH_SECONDS),e.createElement(K,{className:l.card},e.createElement(ye,null,e.createElement("div",{className:l.header},o?e.createElement(ee,{to:`versions/${r.id}`},e.createElement(D,{variant:"h5",component:"h1"},m)):e.createElement(D,{variant:"h5",component:"h1"},m),r.status==="active"?e.createElement(Tt,{status:"active",size:"small"}):null),r.description?e.createElement(D,{variant:"body1",color:"textSecondary"},'"',r.description,'"'):null,e.createElement(D,{component:"h4",className:l.detailsHeader},"Details"),e.createElement(An,{className:l.activityList},e.createElement(ct,{className:l.activityListItem},e.createElement(st,null,e.createElement(zn,null)),e.createElement(mt,{primary:u})),e.createElement(ct,{className:l.activityListItem},e.createElement(st,null,e.createElement(Gn,null)),e.createElement(mt,{primary:s}))),c&&e.createElement(p,{paddingTop:2},e.createElement(D,{gutterBottom:!0,variant:"subtitle2"},"What's changed"),e.createElement(p,{className:l.diffSummaryContainer},e.createElement(Rt,{policy:r})))),t.actions?e.createElement(Nn,{className:l.actions},t.actions):null)}const Or=N(t=>({paper:{padding:t.spacing(2,2,0,2)}})),wt=({isOpen:t,onClose:n,policy:a})=>{const l=Or();return e.createElement(te,{classes:{...l},open:t,onClose:n},e.createElement(ge,{disableTypography:!0},e.createElement(p,{display:"flex",flexDirection:"row"},e.createElement(p,null,e.createElement(D,{variant:"h4",component:"h2"},"Success!"),e.createElement(D,null,a.name," has been published and is now your active policy.")),e.createElement(p,null,e.createElement(H,{onClick:n,title:"Close dialog"},e.createElement(ve,null))))),e.createElement(q,null,e.createElement(se,{policy:a})),e.createElement(Be,null,e.createElement(p,{display:"flex",flexDirection:"row",flexGrow:1,justifyContent:"flex-start"},e.createElement(x,{component:un,color:"primary",onClick:n,role:"link",to:"/rbac"},"View all versions"))))},Mr=N(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)}})),_r=({localPolicy:t,onSelectLocalPolicy:n,onSelectServerPolicy:a,serverPolicy:l})=>{const r=Mr();return e.createElement(te,{open:!0,maxWidth:"md"},e.createElement(q,null,e.createElement(p,{display:"flex",flexDirection:"column",gridGap:8},e.createElement(p,{display:"flex",justifyContent:"center"},e.createElement(Et,{className:r.icon})),e.createElement(D,{align:"center",variant:"h6"},"There is a conflict with your drafts"),e.createElement(p,null,e.createElement(D,{align:"center"},"A newer version of the draft you are trying to edit has been recently saved."),e.createElement(D,{align:"center"},"Please review the changes and decide on a version to keep."))),e.createElement(p,{className:r.policiesContainer},e.createElement(p,{alignItems:"center",display:"flex",flexDirection:"column",flex:"1 1 0%"},e.createElement(D,{className:r.label,variant:"button"},"Your local draft"),e.createElement(se,{policy:t,withChangeSummary:!0}),e.createElement(x,{className:r.button,color:"primary",onClick:n,variant:"outlined"},"Keep local draft")),e.createElement(p,{alignItems:"center",display:"flex",flexDirection:"column",flex:"1 1 0%"},e.createElement(D,{className:r.label,variant:"button"},"Recently saved draft"),e.createElement(se,{policy:l,withChangeSummary:!0}),e.createElement(x,{className:r.button,color:"primary",onClick:a,variant:"outlined"},"Keep recently saved draft")))))},$r=({serverPolicy:t,localPolicy:n})=>!n||!t?{policy:t,policyConflict:!1}:t.status!=="draft"?{policy:t,policyConflict:!1}:n.id!==t.id?{policy:t,policyConflict:!1}:n.updatedAt===t.updatedAt?{policy:n,policyConflict:!1}:{policy:n,policyConflict:!0},Lr=()=>er("@spotify/backstage-plugin-rbac:draftPolicy"),Fr=N(t=>({icon:{color:t.palette.warning.main,width:"2rem",height:"2rem"}})),jr=({onConfirm:t,policy:n})=>{const a=Fr(),l=()=>{Dt(n)};return e.createElement(te,{open:!0},e.createElement(q,null,e.createElement(p,{display:"flex",flexDirection:"column",gridGap:16},e.createElement(p,{display:"flex",flexDirection:"column",gridGap:4},e.createElement(p,{display:"flex",justifyContent:"center"},e.createElement(Et,{className:a.icon})),e.createElement(D,{align:"center",variant:"h6"},"Invalid local draft")),e.createElement(p,{display:"flex",flexDirection:"column",gridGap:8},e.createElement(D,{align:"center"},"You have a local draft that is no longer compatible or has become corrupted."),e.createElement(D,{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(D,{align:"center"},"Clicking continue will discard your draft."," ",e.createElement(p,{component:"span",fontWeight:"fontWeightBold"},"This action cannot be undone."))),e.createElement(p,{display:"flex",justifyContent:"center",gridGap:8,marginY:3},e.createElement(x,{color:"primary",onClick:l,variant:"outlined"},"Export"),e.createElement(x,{color:"primary",onClick:t,variant:"contained"},"Discard and continue")))))},It=Te({diff:null,hasChanges:!1,policy:void 0,createNewRole:()=>"",discardLocalDraft:()=>{},saveLocalDraftToServer:()=>Promise.reject(),refetchPolicy:()=>Promise.reject(),updateLocalDraft:()=>{}}),ae=()=>Se(It);function Pe({children:t,policyId:n}){const a=Y(),l=k(Q),r=k(j),{getPolicy:o,setPolicy:c}=Ge(),m=we(),{NotFoundErrorPage:u}=m.getComponents(),i=o(n),[s,f,E]=Lr(),h=!s||Ce.safeParse(s).success,y=h?s:void 0,{policy:d,policyConflict:g}=$r({serverPolicy:i,localPolicy:y}),P=St(d),[{loading:S,error:I},A]=J(()=>r.getPolicy(n),[r,n],i?{loading:!1,value:i}:{loading:!0}),F=()=>{f(R=>R&&i&&{...R,updatedAt:i.updatedAt})},O=w(async()=>{const R=await A();c(R)},[A,c]),T=w(async()=>{if(!d)throw new Error("No policy to save");try{await r.updateDraft(d.id,{name:d.name,roles:d.roles}),l.post({message:"Policy saved",severity:"success"}),E(),O?.()}catch(R){l.post({message:R?.message||"An error occurred while updating the policy",severity:"error"})}},[l,r,d,O,E]),C=w(()=>{if(!d)throw new Error("No policy to create a new role");const R=new Set(d.roles.map(U=>U.id));let z;do z=re().split("-")[0];while(R.has(z));const X={name:`Role ${z}`,permissions:[],members:"*",id:z};return f({...d,roles:[...d.roles,X]}),z},[d,f]),M=()=>{E(),a("/rbac")};return G(()=>{i||O()},[O,i]),h?d?e.createElement(It.Provider,{value:{diff:P,hasChanges:!!y,policy:d,createNewRole:C,discardLocalDraft:E,saveLocalDraftToServer:T,refetchPolicy:O,updateLocalDraft:f}},g&&y&&i&&e.createElement(_r,{localPolicy:y,onSelectLocalPolicy:F,onSelectServerPolicy:E,serverPolicy:i}),t):S?e.createElement(fe,null):I?xr(I)?e.createElement(u,null):e.createElement(lt,{error:I??new Error("Unknown")}):null:e.createElement(jr,{onConfirm:M,policy:s})}const Hr=N(t=>({closeButton:{color:t.palette.text.secondary},diffSummaryContainer:{backgroundColor:t.palette.background.default,marginBottom:t.spacing(2)}}));function kt({open:t,onPublish:n,onClose:a}){const{policy:l}=ae(),r=Hr(),o=Z(null);return e.createElement(te,{open:t,onClose:a,fullWidth:!0},e.createElement(ge,null,e.createElement(p,{display:"flex",justifyContent:"space-between",alignItems:"center"},"Ready to publish?",e.createElement(x,{startIcon:e.createElement(ve,null),onClick:a,className:r.closeButton},"Close")),e.createElement(D,null,"Double check your changes, then click Publish to activate this version of your policy. This will immediately apply the permissions defined in this version across Backstage.")),e.createElement(q,{className:r.diffSummaryContainer,dividers:!0},e.createElement(Rt,{policy:l})),e.createElement(q,null,e.createElement(le,{variant:"outlined",fullWidth:!0,label:"Summary (optional)",placeholder:"Briefly describe this version (or changes from a previous version)",inputRef:o})),e.createElement(Be,null,e.createElement(x,{color:"primary",onClick:()=>{var c,m;return n((m=(c=o.current)==null?void 0:c.value)!=null?m:"")}},"Publish")))}const Vr=[{title:"Name",field:"name",render:t=>e.createElement(ee,{to:`versions/${t.id}`},t.name)},{title:"Status",field:"status",render:t=>{switch(t.status){case"active":return"Active";case"draft":return"Draft";case"inactive":return"Inactive";default:return Pr(t.status)}}},{title:"Publish date",field:"lastPublishedAt",render:t=>t.lastPublishedAt?L.fromISO(t.lastPublishedAt).toLocaleString(L.DATETIME_MED_WITH_SECONDS):"",type:"datetime",defaultSort:"desc"},{title:"Published by",field:"lastPublishedBy"}];function Wr(t){const a=t.data.length>3,{fetchPolicies:l}=ce(),[{loading:r},o]=At(),[{loading:c,value:m},u]=Nt(),[i,s]=B(void 0),[f,E]=B(!1),h=()=>{s(void 0),l()},y=i?.id===m?.id?m:void 0,d=[g=>{const{tableData:P,...S}=g;return{icon:Ln,tooltip:"Publish",onClick:()=>{s(S),E(!0)},disabled:c}},g=>{const{tableData:P,...S}=g;return{icon:Fn,tooltip:"Duplicate",disabled:r||!t.canDuplicate,onClick:()=>o(S)}}];return e.createElement(e.Fragment,null,e.createElement(vn,{title:"Previous Versions",columns:Vr,data:t.data,options:{paging:a,pageSize:3,pageSizeOptions:[3,5,10,20],actionsColumnIndex:-1,loadingType:"linear"},actions:d}),i&&e.createElement(Pe,{policyId:i.id},e.createElement(kt,{open:f,onPublish:g=>{u(i,g),E(!1)},onClose:()=>{s(void 0),E(!1)}})),y&&e.createElement(wt,{isOpen:!0,policy:y,onClose:h}))}const zr=N(t=>({breadcrumbs:{marginBottom:t.spacing(4)}}));function Gr({pages:t}){const n=fn(En),a=zr();return e.createElement(Cn,{className:a.breadcrumbs},e.createElement(ee,{to:n()},"Home"),t.map(({title:l,path:r},o)=>r?e.createElement(ee,{to:r,key:r,relative:"path"},l):e.createElement(D,{key:`${o}`},l)))}function Xe({children:t,header:n,pages:a}){return e.createElement(Dn,{themeId:"tool"},e.createElement(tr,{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(Pn,{title:"Role Based Access Control"}),e.createElement(xn,null,e.createElement(Tn,{maxWidth:"lg"},e.createElement(V,{container:!0,spacing:4},e.createElement(V,{item:!0,xs:12},a&&e.createElement(Gr,{pages:a}),n),t))))}const Bt=t=>{const[n,a]=B(!1),{fetchPolicies:l}=ce(),[{loading:r,value:o},c]=Nt(),{policy:m,hasChanges:u}=ae(),i=Ce.safeParse(m).success,s=!u&&i,f=h=>{c(m,h),a(!1)},E=()=>{l()};return e.createElement(e.Fragment,null,e.createElement(x,{...t,onClick:()=>a(!0),disabled:!s||r},"Publish"),e.createElement(kt,{open:n,onClose:()=>a(!1),onPublish:f}),o&&e.createElement(wt,{isOpen:!0,onClose:E,policy:o}))};function Ur(t){const n=k(j),a=k(Q),{fetchPolicies:l}=ce();return J(async()=>{if(t)return n.deleteDraft(t.id).then(l).catch(r=>(a.post({message:r.message,severity:"error"}),Promise.reject(r)))},[t])}function Yr(){const t=k(j),n=Y(),a=k(Q);function l(r){var o,c;const m=(c=(o=r.target)==null?void 0:o.files)==null?void 0:c[0],u=new FileReader;m&&(u.readAsText(m,"utf-8"),u.onload=async i=>{var s,f;const E=(f=(s=i.target)==null?void 0:s.result)==null?void 0:f.toString();if(E){let h=null;try{h=Hn.load(E)}catch{a.post({message:"YAML file is invalid",severity:"error"});return}if(!Ce.safeParse(h).success){a.post({message:"Imported policy is invalid",severity:"error"});return}if((await t.getPolicies()).items.some(I=>I.status==="draft")){a.post({message:"Unable to import new policy due to existing draft policy",severity:"error"});return}const P=h,S=await t.createDraft({name:P.name,roles:P.roles});n(`./versions/${S.id}`),a.post({message:"Policy imported successfully",severity:"success"})}})}return e.createElement(x,{variant:"outlined",color:"primary",component:"label"},"Import",e.createElement("input",{role:"input",type:"file",hidden:!0,onChange:l,accept:".yaml"}))}function Jr(){const{policies:t}=Ge(),{loading:n,error:a,fetchPolicies:l}=ce();ot(()=>{t||l()});let r;return n?r=e.createElement(V,{item:!0,xs:12},e.createElement(fe,null)):a?r=e.createElement(lt,{error:a}):!t||t.length===0?r=e.createElement(qr,null):r=e.createElement(Xr,{policies:t}),e.createElement(Xe,{pages:void 0,header:e.createElement(ke,{title:"RBAC Policies"},e.createElement(Yr,null))},r)}const Kr=N(t=>({cardContent:{padding:t.spacing(6,3),"& > *":{background:"transparent"}}}));function qr(){const t=Kr(),n=k(j),a=Y(),[l,r]=J(async()=>n.createDraft({roles:[]}),[n]);return G(()=>{l.value&&a(`./versions/${l.value.id}`)},[a,l.value]),e.createElement(K,null,e.createElement(ye,{className:t.cardContent},e.createElement(Ee,{missing:"content",title:"No policy configured",description:e.createElement(e.Fragment,null,e.createElement(p,{component:"span",display:"block",pb:2},"Until you've configured your policy, authorization will be denied for all permissions."),e.createElement(p,{component:"span",display:"block"},"Click the button below to create the first version of your policy.")),action:e.createElement(x,{variant:"contained",color:"primary",disabled:l.loading,onClick:r},"New version")})))}function Xr({policies:t}){const n=t.find(i=>i.status==="draft"),a=t.find(i=>i.status==="active"),[l,r]=At(),[o,c]=Ur(n),m=Y(),u=Zr(t);return e.createElement(V,{container:!0,spacing:4},a?e.createElement(V,{item:!0,xs:12,md:6},e.createElement(se,{policy:a,to:`./versions/${a.id}`,actions:e.createElement(x,{color:"primary",disabled:l.loading||!!n,onClick:()=>r(a)},"Duplicate")})):null,n?e.createElement(V,{item:!0,xs:12,md:6},e.createElement(se,{policy:n,to:`./versions/${n.id}`,actions:e.createElement(e.Fragment,null,e.createElement(x,{onClick:()=>m(`versions/${n.id}`),color:"primary"},"Edit"),e.createElement(x,{color:"primary",disabled:o.loading,onClick:c},"Delete Draft"),e.createElement(Pe,{policyId:n.id},e.createElement(Bt,{color:"primary"})))})):null,e.createElement(V,{item:!0,xs:12},e.createElement(Wr,{data:u,canDuplicate:!n})))}function Zr(t){return t.filter(({status:n})=>n==="inactive")}const Qr=N(t=>({titleWrapper:{display:"flex",alignItems:"center",gap:t.spacing(2)}}));function Ot({children:t}){const n=Qr();return e.createElement(D,{noWrap:!0,variant:"h4",component:"h2",color:"textSecondary",className:n.titleWrapper},t)}const ea=N({autocomplete:{display:"flex",flex:1}});function ta({members:t,disabled:n=!1,onToggleMember:a}){var l;const r=k(j),[o,c]=B(!1),m=ea(),[u,i]=sn(d=>d+1,0),[{value:s,loading:f},E]=J((d="")=>r.searchMembers({query:d}),[r]),h=$(()=>Sn(d=>{const g=d.target.value;E(g)},1e3),[E]),y=(d,g)=>{g&&(a(g),i())};return G(()=>{o&&E("")},[o,E]),e.createElement(p,{width:250},e.createElement(ze,{key:`${u}`,open:o,onOpen:()=>{c(!0)},onClose:()=>{c(!1)},onChange:y,getOptionLabel:Mt,groupBy:na,renderOption:d=>e.createElement(e.Fragment,null,e.createElement(Oe,{id:`checkbox-${d.entityRef}`,checked:t.includes(d.entityRef),color:"primary"}),e.createElement("label",{htmlFor:`checkbox-${d.entityRef}`},Mt(d))),options:(l=s?.members)!=null?l:[],openOnFocus:!0,disabled:n,loading:f,className:m.autocomplete,renderInput:d=>e.createElement(le,{...d,label:"Select specific users/groups",variant:"standard",onChange:h,InputProps:{...d.InputProps,endAdornment:e.createElement(e.Fragment,null,f?e.createElement(Rn,{color:"inherit",size:20}):null,d.InputProps.endAdornment)}})}))}function Mt(t){var n;const a=We(t.entityRef);return rr({...a,name:(n=t.name)!=null?n:a.name},{defaultKind:a.kind,defaultNamespace:nr})}const _t={user:"USERS",group:"GROUPS"};function na(t){const{kind:n}=We(t.entityRef);if(!_t[n])throw new Error(`Kind '${n}' is not supported for members in a policy`);return _t[n]}const ra=N(t=>({root:({operation:n})=>({borderRadius:100,borderColor:qe(t,n),borderSize:1,borderStyle:"solid",color:qe(t,n),lineHeight:1,padding:t.spacing(.5,1),whiteSpace:"nowrap"})})),me=({operation:t,size:n="small"})=>{const a=ra({operation:t}),l=Ir(t),r=n==="small"&&"caption"||n==="medium"&&"body1"||n==="large"&&"subtitle1"||"inherit";return!t||t==="UNCHANGED"?null:e.createElement(D,{className:a.root,variant:r},l)},$t=N({header:{display:"flex",flexDirection:"row",justifyContent:"space-between",paddingLeft:"1rem",paddingRight:"1rem",gap:"1rem"},actionCol:{width:48}});function aa({diff:t,policyId:n,role:a,onToggleMember:l,readonly:r=!1}){const o=k(j),c=$t(),m=a.members==="*",{current:u}=Z({}),i=h=>{u[h.entityRef]=h,l(h.entityRef)},{loading:s,error:f}=Ie(async()=>{if(a.members==="*"||a.members.length===0||(await o.getPolicy(n)).roles.find(d=>d.id===a.id)===void 0)return;(await o.getRoleMembers({policyId:n,roleId:a.id})).forEach(d=>u[d.entityRef]=d)},[n,m]),E=h=>{var y;if(u[h])return u[h];const d=We(h);return{entityRef:h,type:d.kind.toLowerCase(),name:(y=d.name)!=null?y:h}};return e.createElement(e.Fragment,null,e.createElement("div",{className:c.header},e.createElement("h2",null,"Members"),e.createElement(ta,{onToggleMember:i,members:a.members,disabled:r})),e.createElement(Me,null,e.createElement(_e,null,e.createElement(W,null,e.createElement(v,null,"Name"),e.createElement(v,null,"Type"),e.createElement(v,null),!r&&e.createElement(v,{className:c.actionCol}))),e.createElement($e,null,e.createElement(la,{diff:t,loading:s,error:f,members:Array.isArray(a.members)?a.members.map(E):a.members,onToggleMember:i,readonly:r}))))}function la({diff:t,loading:n,members:a,error:l,onToggleMember:r,readonly:o=!1}){var c;const m=$t();return n?e.createElement(W,null,e.createElement(v,{scope:"row",colSpan:4},e.createElement(fe,null))):(l&&(W,v,(c=l.message)!=null),a==="*"?e.createElement(W,null,e.createElement(v,null,"All"),e.createElement(v,{height:80},"any"),e.createElement(v,{colSpan:2},e.createElement(me,{operation:t?.members["*"].operation}))):a.length===0?e.createElement(W,null,e.createElement(v,{scope:"row",colSpan:4},"Select users or groups using the drop-down menu above.")):e.createElement(e.Fragment,null,a.map(u=>{const{name:i,type:s,entityRef:f}=u;return e.createElement(W,{key:f},e.createElement(v,{scope:"row"},i??"Unknown"),e.createElement(v,{scope:"row"},s),e.createElement(v,null,i&&e.createElement(me,{operation:t?.members[f].operation})),!o&&e.createElement(v,{scope:"row",className:m.actionCol},e.createElement(H,{"aria-label":"delete",onClick:()=>r(u),size:"small"},e.createElement(ie,null))))})))}function Lt(t){return`${t.palette.primary.main}50`}const oa=N(t=>({toggleButton:{"&.Mui-selected":{backgroundColor:Lt(t),color:t.palette.primary.main},"&.Mui-selected:hover":{backgroundColor:"#97BBE8"},color:t.palette.primary.main,border:`1px solid ${t.palette.primary.main}`}}));function Ze({className:t,...n}){const a=oa();return e.createElement(ar,{className:`${a.toggleButton} ${t}`,...n})}const ia=N({fullWidth:{width:"100%","& > *":{flexGrow:1}}});function ca({className:t,fullWidth:n,...a}){const l=ia();return e.createElement(lr,{className:`${n?l.fullWidth:""} ${t}`,...a})}const sa=N(t=>({container:{display:"flex",position:"relative",alignItems:"center",gap:t.spacing(1),flexShrink:1,maxWidth:"100%",minWidth:0},input:({invalid:n})=>({boxSizing:"content-box",display:"block",maxWidth:"100%",padding:0,borderWidth:2,borderStyle:"solid",borderColor:n?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 Ft({invalid:t,name:n,value:a,onTextChange:l}){const r=sa({invalid:t}),[o,c]=B(!1),[m,u]=B(null),i=Z(null),[s,f]=B(a);G(()=>{f(a)},[a]),mn(()=>{i.current&&m&&i.current.style.setProperty("width",`max(${m.getBoundingClientRect().width}px, 3ch)`)},[m,s]);const E=()=>{c(!1),f(a)},h=()=>{c(!1),l?.(s)},y=()=>{var g;o?h():(c(!0),(g=i.current)==null||g.focus())},d=g=>{var P;g.key==="Enter"&&((P=i.current)==null||P.blur()),g.key==="Escape"&&E()};return e.createElement(e.Fragment,null,e.createElement("div",{className:r.container},e.createElement("input",{"aria-label":n,className:r.input,name:n,ref:i,onChange:g=>f(g.target.value),onFocus:y,onBlur:h,onKeyDown:d,value:s}),e.createElement("span",{"aria-hidden":"true",className:r.hiddenSpan,ref:u},s),e.createElement(H,{onClick:y,size:"small"},o?e.createElement(cr,{"aria-label":"Save title"}):e.createElement(ir,{"aria-label":"Edit title"}))))}const ma=["condition","anyOf","allOf","not"],jt={condition:"Condition",anyOf:"Any of",allOf:"All of",not:"Not"};function Qe(t){return t===null?!1:t.hasOwnProperty("id")&&t.hasOwnProperty("ruleName")&&t.hasOwnProperty("parameters")}function ue(t){return t.hasOwnProperty("levelType")}function ua(t){return t==="anyOf"||t==="allOf"||t==="not"}const da=N(t=>({descriptiveText:{fontWeight:500,marginBottom:t.spacing(1)}})),xe=({children:t})=>{const n=da();return e.createElement(D,{variant:"body2",className:n.descriptiveText},t)},Ht=({children:t})=>e.createElement(p,{pl:3},t),pa="#4CAF50";function fa({permissionCriteria:t}){return e.createElement("div",null,e.createElement(xe,null,"If the below conditions are met"),e.createElement(Ht,null,Qe(t)&&e.createElement(zt,{condition:t}),ue(t)&&e.createElement(Vt,{level:t})),e.createElement(xe,null,"Then the action is"," ",e.createElement(p,{component:"span",color:pa},"allowed")))}function Vt({level:t}){return e.createElement(e.Fragment,null,e.createElement(xe,null,jt[t.levelType]),e.createElement(Ht,null,t.children.map((n,a)=>ue(n)?e.createElement(Vt,{key:a,level:n}):e.createElement(zt,{key:a,condition:n}))))}const Wt="#FF737F",Ea="#E22134";function zt({condition:t}){return e.createElement(xe,null,e.createElement(p,{component:"span",color:Wt},t.ruleName,"("),e.createElement(p,{component:"span",color:Ea},JSON.stringify(t.parameters)),e.createElement(p,{component:"span",color:Wt},")"))}const ya=N(t=>({editor:{"--jse-main-border":`1px solid ${t.palette.divider}`,"--jse-panel-border":`1px solid ${t.palette.divider}`,"--jse-message-error-background":t.palette.error.main,"--jse-message-warning-background":t.palette.warning.main,"--jse-background-color":t.palette.background.default,"--jse-panel-background":t.palette.background.default,"--jse-delimiter-color":t.palette.type==="light"?"rgba(0, 0, 0, 0.38)":"rgba(255, 255, 255, 0.38)","--jse-error-color":t.palette.text.primary,"--jse-key-color":t.palette.text.primary,"--jse-value-color":t.palette.text.primary,"--jse-text-color":t.palette.text.primary,"--jse-panel-color-readonly":t.palette.text.hint,"--jse-value-color-string":t.palette.status.ok,"--jse-value-color-null":t.palette.status.warning,"--jse-value-color-number":t.palette.status.error,"--jse-value-color-boolean":t.palette.status.running,"--jse-font-family":"inherit"}})),ga=t=>"parseError"in t,ha=t=>{var n;return ga(t)?!!t.parseError:((n=t?.validationErrors)==null?void 0:n.length)>0};function ba({onChange:t,schema:n,value:a}){const l=Z(null),r=Z(),o=ya();return G(()=>(l.current&&!r.current&&(r.current=new sr({target:l.current,props:{onChange:(c,m,{contentErrors:u})=>{!ha(u)&&mr(c)&&t(JSON.parse(c.text))},validator:ur({schema:n}),content:{json:{}},mainMenuBar:!1,mode:dr.text}})),()=>{var c;(c=r.current)==null||c.destroy(),r.current=void 0}),[t,n]),ot(()=>{var c;(c=r.current)==null||c.updateProps({content:{json:a}})}),e.createElement("div",{ref:l,className:o.editor,style:{height:300}})}const va=[];function Ca(t){const{onChange:n,schema:a,name:l}=t,{description:r,items:o}=a,[c,m]=e.useState(!1),u=Array.isArray(t.value)?t.value:va,i=u.includes(oe),s=(g,P)=>{if(!Array.isArray(P)){const S=[...u];S[g]=P||"",n(S)}},f=w(()=>{n([...u,""])},[n,u]),E=g=>{n(u.filter((P,S)=>S!==g))},h=()=>{n(i?[]:[oe])},y=()=>{i&&m(!0)},d=()=>{m(!1)};return G(()=>{u.length?i&&u.length>1&&n([oe]):f()},[f,n,u,i]),!o||!("type"in o)?null:e.createElement(e.Fragment,null,(u??[]).map((g,P,{length:S})=>e.createElement(Ut,{allowEmptyStrings:!0,key:P,onChange:I=>s(P,I),name:P===0?l:"",schema:{description:P===S-1?r:"",type:o.type},value:g,controls:e.createElement(H,{size:"small",onClick:()=>E(P)},e.createElement(pr,null))})),!!u?.length&&e.createElement(p,{alignItems:"center",display:"flex",flexDirection:"row",justifyContent:"space-between"},e.createElement(p,null,e.createElement(ut,{control:e.createElement(Oe,{checked:i,onChange:h,name:"checkedB",color:"primary"}),label:"Use the claims from the logged in users token"})),e.createElement(p,null,e.createElement(he,{onClose:d,onOpen:y,open:c,title:"To add additional entries you must uncheck using the claims from the logged in user."},e.createElement("span",null,e.createElement(H,{disabled:i,size:"small",onClick:f},e.createElement(Ve,null)))))))}function Da(t){const{onChange:n,schema:a,name:l,value:r}=t,{description:o}=a,c=m=>{n(m.target.checked)};return e.createElement(p,{mb:1},e.createElement(ut,{control:e.createElement(Oe,{checked:r===!0,onChange:c,name:l,color:"primary"}),label:l}),o&&e.createElement(D,{display:"block",variant:"caption",color:"textSecondary"},o))}function Pa({allowEmptyStrings:t,controls:n,name:a,onChange:l,schema:r,value:o}){const c=m=>{l(Aa({value:m.currentTarget.value,type:r.type}))};return e.createElement(p,{mb:1},e.createElement(p,{display:"flex",gridGap:6},e.createElement(le,{fullWidth:!0,id:a,label:a,placeholder:"Enter",variant:"outlined",size:"small",value:xa(o,t),onChange:et(o,t)?void 0:c,disabled:et(o,t)}),n&&e.createElement(p,{alignSelf:"center"},n)),r.description&&e.createElement(D,{variant:"caption",color:"textSecondary"},r.description,et(o)&&!t&&e.createElement(e.Fragment,null," (switch to JSON editor to edit)")))}function et(t,n=!1){return!n&&t===""||t===null||t===oe}function xa(t,n=!1){return!n&&t===""?"[empty string]":t===null?"[null]":t===oe?"[BackstageUserClaims]":t||""}function Aa({value:t,type:n}){switch(n){case"string":return t===""?void 0:t;case"number":case"integer":return Number.isNaN(Number(t))?void 0:Number(t);case"null":return t==="null"?null:void 0;default:return}}function Gt(t){return!!t&&"type"in t&&(t.type==="array"||t.type==="boolean"||t.type==="null"||t.type==="number"||t.type==="integer"||t.type==="string")}function Na(t){return"type"in t&&t.type==="array"}function Ta(t){return"type"in t&&t.type==="boolean"}function Ut({schema:t,...n}){return Gt(t)?Na(t)?e.createElement(Ca,{...n,schema:t}):Ta(t)?e.createElement(Da,{...n,schema:t}):e.createElement(Pa,{...n,schema:t}):null}const Sa=new gt({allErrors:!0});function Ra({onChange:t,schema:n,value:a}){var l;const r=$(()=>Sa.compile(n),[n]),o=$(()=>r(a),[r,a]),c=Object.entries(n.properties),m=u=>i=>{t({...a,[u]:i})};return e.createElement(e.Fragment,null,c.map(([u,i])=>{var s;return e.createElement(Ut,{isRequired:((s=n.required)==null?void 0:s.includes(u))||!1,key:u,name:u,onChange:m(u),schema:i,value:a?.[u]})}),e.createElement(dt,{error:!o},(l=r.errors)==null?void 0:l[0].message))}const wa=t=>!!t&&"properties"in t;function Ia({onChange:t,rule:n,value:a}){const[l,r]=B(!1),{paramsSchema:o}=n??{},c=()=>r(s=>!s);if(!wa(o))return null;const m=!ka(o),u=m||l,i=e.createElement(x,{size:"small",onClick:c,disabled:m},u?"Close editor":"Edit as JSON");return e.createElement(p,{marginTop:2},e.createElement("form",null,u?e.createElement(ba,{onChange:t,schema:o,value:a}):e.createElement(e.Fragment,null,e.createElement(p,{marginBottom:2},e.createElement(be,null,"Parameters")),e.createElement(Ra,{onChange:t,schema:o,value:a}))),e.createElement(p,{display:"flex",flexDirection:"column",alignItems:"flex-end",marginTop:1},m?e.createElement(he,{title:"Only JSON editing is supported for this parameter",arrow:!0},e.createElement("span",null,i)):i))}function ka(t){return Object.values(t.properties).every(Gt)}const de=N(t=>({paper:{backgroundColor:t.palette.background.default,padding:t.spacing(3),marginBottom:t.spacing(3),minHeight:t.spacing(48)},conditionCard:{minWidth:t.spacing(63)},conditionCardBar:{height:t.spacing(1),backgroundImage:"linear-gradient(90deg, #007DFF 0%, #0057B2 100%)"},conditionTypeFormControl:{minWidth:80,marginLeft:t.spacing(1)},autocomplete:{flex:1},conditionContent:{gap:t.spacing(2)},treeVerticalSpacer:{width:t.spacing(2),borderLeft:`1px solid ${t.palette.status.aborted}`},treeHorizontalSpacer:{height:t.spacing(3),borderLeft:`1px solid ${t.palette.status.aborted}`},treeVerticalBranchHalf:{position:"absolute",height:"50%",borderLeft:`1px solid ${t.palette.status.aborted}`,alignSelf:"flex-start"},treeVerticalBranchFull:{borderLeft:`1px solid ${t.palette.status.aborted}`,alignSelf:"stretch"},treeHorizontalBranch:{width:t.spacing(2),borderTop:`1px solid ${t.palette.status.aborted}`},addButton:{paddingLeft:40,paddingRight:40}}));function Ba({permissionCriteria:t,resourceType:n,onUpdate:a,readonly:l=!1}){const r=de(),o=w(s=>{a(f=>({...f,...s}))},[a]),c=w(s=>{const f=re();o(s==="condition"?Ae():s==="not"?{id:f,levelType:s,children:[]}:{id:f,levelType:s,children:[Ae()]})},[o]),m=w((s,f)=>{a(E=>({...E,ruleName:s,parameters:f}))},[a]),u=w(()=>{a(null)},[a]);let i;return l?i=e.createElement(fa,{permissionCriteria:t}):t===null?i=e.createElement(Yt,{onSelect:c}):Qe(t)?i=e.createElement(Jt,{ruleName:t.ruleName,parameters:t.parameters,resourceType:n,onChange:m,onDelete:u}):ue(t)&&(i=e.createElement(Kt,{level:t,resourceType:n,onChange:a,isRoot:!0})),e.createElement(wn,{variant:"outlined",className:r.paper},i)}function Ae(){return{id:re(),ruleName:null,parameters:{}}}function Yt({onSelect:t}){const n=de(),a=Z(null),[l,r]=B(!1),o=()=>{r(c=>!c)};return e.createElement("div",null,e.createElement(x,{className:n.addButton,variant:"outlined",color:"primary",onClick:o,ref:a},"Add"),e.createElement(kn,{anchorEl:a.current,open:l,onClose:o,BackdropProps:{}},ma.map(c=>e.createElement(ne,{key:c,onClick:()=>{t?.(c),r(!1)}},jt[c]))))}function Jt({ruleName:t,parameters:n,resourceType:a,onChange:l,onDelete:r}){var o;const c=de(),m=bt(),u=(o=m?.filter(E=>E.resourceType===a))!=null?o:[],i=u.find(E=>E.name===t),s=E=>{l(E,{})},f=w(E=>{l(t,E)},[l,t]);return e.createElement(p,{display:"flex",alignItems:"center"},e.createElement(K,{className:c.conditionCard},e.createElement("div",{className:c.conditionCardBar}),e.createElement(ye,null,e.createElement(p,null,e.createElement(p,null,e.createElement(ze,{className:c.autocomplete,"data-testid":"rule-select",getOptionLabel:E=>E.name,getOptionSelected:(E,h)=>E.name===h.name,options:u,onChange:(E,h)=>s(h?h.name:null),renderInput:E=>e.createElement(e.Fragment,null,e.createElement(p,{marginBottom:2},e.createElement(be,null,"Rule")),e.createElement(le,{...E,placeholder:"Select",variant:"outlined",size:"small",name:"rule"})),renderOption:E=>e.createElement(p,null,e.createElement(D,{variant:"body2"},E.name),e.createElement(D,{noWrap:!0,variant:"caption"},E.description)),value:i||null,PopperComponent:E=>e.createElement(In,{...E,style:{width:"auto"},placement:"bottom-start"})})),e.createElement(p,{flex:"1"},e.createElement(p,{display:"flex",flexDirection:"column"},e.createElement(Ia,{rule:i,onChange:f,value:n})))))),e.createElement(p,{ml:1},e.createElement(H,{"aria-label":"delete",onClick:r,size:"small"},e.createElement(ie,null))))}function Kt({level:t,resourceType:n,onChange:a,parentConditionType:l,isRoot:r=!1}){const o=de(),c=w((y,d)=>{const g=[...t.children];return g.splice(y,1,d),g},[t]),m=w(y=>{a({...t,children:y})},[a,t]),u=w(y=>{y===null?a(null):y==="not"&&t.children.length>1?a({...t,levelType:y,children:t.children.slice(0,1)}):a({...t,levelType:y})},[a,t]),i=w((y,d)=>{m(y===null?qt(t.children,d):c(d,y))},[t,m,c]),s=y=>{const d=re();y==="condition"?m([...t.children,Ae()]):y==="not"?m([...t.children,{id:d,levelType:y,children:[]}]):ua(y)&&m([...t.children,{id:d,levelType:y,children:[Ae()]}])},f=y=>{m(qt(t.children,y))},E=$(()=>t.children.map((y,d)=>(g,P)=>{m(c(d,{...y,ruleName:g,parameters:P}))}),[t.children,m,c]),h=$(()=>t.children.map((y,d)=>g=>i(g,d)),[t.children,i]);return e.createElement("div",null,!r&&e.createElement("div",{className:o.treeHorizontalSpacer}),e.createElement(p,{display:"flex",alignItems:"center",position:"relative"},!r&&e.createElement(e.Fragment,null,e.createElement("div",{className:l==="not"?o.treeVerticalBranchHalf:o.treeVerticalBranchFull}),e.createElement("div",{className:o.treeHorizontalBranch})),e.createElement(Oa,{level:t,onSelect:u})),e.createElement(p,{display:"flex"},r||l==="not"?e.createElement(p,{pl:2}):e.createElement("div",{className:o.treeVerticalSpacer}),!r&&e.createElement(p,{pl:2}),e.createElement("div",null,t.children.map((y,d)=>ue(y)?e.createElement(p,{key:y.id},e.createElement(Kt,{level:y,resourceType:n,parentConditionType:t.levelType,onChange:h[d]})):e.createElement(pe,{key:y.id},e.createElement("div",{className:o.treeHorizontalSpacer}),e.createElement(p,{display:"flex",alignItems:"center",position:"relative"},e.createElement("div",{className:t.levelType==="not"?o.treeVerticalBranchHalf:o.treeVerticalBranchFull}),e.createElement("div",{className:o.treeHorizontalBranch}),e.createElement(Jt,{ruleName:y.ruleName,parameters:y.parameters,resourceType:n,onChange:E[d],onDelete:()=>f(d)})))),!(t.levelType==="not"&&t.children.length>=1)&&e.createElement(e.Fragment,null,e.createElement("div",{className:o.treeHorizontalSpacer}),e.createElement(p,{display:"flex",alignItems:"center",position:"relative"},e.createElement("div",{className:o.treeVerticalBranchHalf}),e.createElement("div",{className:o.treeHorizontalBranch}),e.createElement(Yt,{onSelect:s}))))))}function qt(t,n){const a=[...t];return a.splice(n,1),a}function Oa({level:t,onSelect:n}){const a=de(),l=t.children.length>1;return e.createElement(p,{display:"flex",alignItems:"center"},e.createElement(Le,{className:a.conditionTypeFormControl},e.createElement(Fe,{value:t.levelType,onChange:r=>n?.(r.target.value)},e.createElement(ne,{key:"anyOf",value:"anyOf"},"Any of"),e.createElement(ne,{key:"allOf",value:"allOf"},"All of"),e.createElement(ne,{key:"not",value:"not",disabled:l},"Not"))),e.createElement(p,{ml:1},e.createElement(H,{"aria-label":"delete",onClick:()=>n?.(null),size:"small"},e.createElement(ie,null))))}const Ma=N(t=>({indicator:{right:"unset"},tab:{maxWidth:"none","&.Mui-selected":{backgroundColor:Lt(t),color:t.palette.primary.main}}}));function _a({options:t,selected:n,onChange:a,readonly:l=!1}){const r=Ma();return e.createElement(Bn,{orientation:"vertical",value:t.map(({id:o})=>o).indexOf(n),onChange:(o,c)=>a(t[c].id),indicatorColor:"primary",TabIndicatorProps:{className:r.indicator}},t.map(o=>e.createElement(On,{key:o.id,label:o.displayText.toUpperCase(),className:r.tab,disabled:l})))}function $a(t){return t?{id:t.id,match:La(t),decisionType:Fa(t),criteria:je(t.decision)?Ne(t.decision.conditions):null}:{id:re(),match:{method:"specificPermission"},decisionType:"allow",criteria:null}}function La(t){var n;return t.match==="*"?{method:"all"}:t.match.name?{method:"specificPermission",name:t.match.name}:t.match.resourceType||(n=t.match.actions)!=null&&n.length?{method:"filter",resourceType:t.match.resourceType,actions:t.match.actions}:{method:"specificPermission"}}function Fa(t){return typeof t.decision=="string"?t.decision:"conditional"}function Ne(t){const n=re();return Jn(t)?{id:n,levelType:"allOf",children:t.allOf.map(a=>Ne(a))}:Kn(t)?{id:n,levelType:"anyOf",children:t.anyOf.map(a=>Ne(a))}:qn(t)?{id:n,levelType:"not",children:[Ne(t.not)]}:{id:n,ruleName:t.rule,parameters:t.params}}function Xt(t,n){if(!t)return!1;if(ue(t))return t.children.length>0&&t.children.every(l=>Xt(l,n));if(!t.ruleName)return!1;const a=n?.find(({name:l})=>l===t.ruleName);return a?a.paramsSchema?new gt({allErrors:!0}).compile(a.paramsSchema)(t.parameters):!0:!1}function ja(t,n,a){return{id:t,match:Zt(n,a),decision:a}}function Zt({method:t,...n},a){return t==="all"?"*":a&&je(a)?{resourceType:a.resourceType,...n}:n}function tt(t){return Qe(t)?{rule:t.ruleName,params:t.parameters}:t.levelType==="not"?{not:tt(t.children[0])}:{[t.levelType]:t.children.map(n=>tt(n))}}const nt=N(t=>({dialogTitle:{display:"flex",alignItems:"center",justifyContent:"space-between"},fullWidth:{width:"100%","& > *":{flexGrow:1}},infoIcon:{position:"absolute",right:t.spacing(3)},content:{padding:t.spacing(7)},saveButton:{paddingLeft:t.spacing(5),paddingRight:t.spacing(5)},contentContainerConditional:{display:"flex",gap:t.spacing(5),maxWidth:1480}})),Ha={specificPermission:"Choose a specific permission",filter:"Filter by permission properties",all:"Match all permissions"},Qt="Choose the name of a resource permission or filter by resource type to set a conditional decision.";function Va({rolePermission:t,readonly:n=!1,onClose:a,onSave:l}){const r=nt(),o=vt(),c=bt(),m=vr(),u=$a(t),[i,s]=B(u.match),[f,E]=B(u.decisionType),[h,y]=B(u.criteria),d=$(()=>Wa(o,i),[o,i]),g=f==="conditional",P=g?"xl":"sm";G(()=>{g&&o&&!d.commonResourceType&&E("allow")},[g,o,d.commonResourceType,E]);const S=T=>{T!==null&&E(T)},I=$(()=>i.method==="specificPermission"&&!i.name||i.method==="filter"&&!i.resourceType&&!i.actions,[i]),A=$(()=>d.permissions.length===0?!1:!I,[d,I]),F=$(()=>f!=="conditional"?!0:!(!d.commonResourceType||!m?.[d.commonResourceType].pluginId||!Xt(h,c)),[f,d,m,h,c]),O=()=>{l?.(ja(u.id,i,f==="conditional"?{resourceType:d.commonResourceType,pluginId:m[d.commonResourceType].pluginId,conditions:tt(h)}:f))};return e.createElement(te,{open:!0,maxWidth:P,onClose:a,fullWidth:!0},e.createElement(ge,{disableTypography:!0,className:r.dialogTitle},e.createElement(D,{variant:"h4",component:"h2"},"New Permission Decision"),e.createElement(x,{startIcon:e.createElement(ve,null),onClick:a},"Close")),e.createElement(q,{dividers:!0,className:r.content},e.createElement(p,{className:g?r.contentContainerConditional:void 0},e.createElement(p,{mb:5,flex:1},e.createElement(_a,{options:Object.entries(Ha).map(([T,C])=>({id:T,displayText:C})),selected:i.method,onChange:T=>s({method:T}),readonly:n})),e.createElement(p,{mb:5,height:189,flex:1},i.method==="specificPermission"&&e.createElement(za,{name:i.name,readonly:n,onNameChange:T=>s({...i,name:T})}),i.method==="filter"&&e.createElement(e.Fragment,null,e.createElement(Ga,{resourceType:i.resourceType,readonly:n,onResourceTypeChange:T=>s({...i,resourceType:T})}),e.createElement(Ya,{actions:i.actions,readonly:n,onActionsChange:T=>s({...i,actions:T.length?T:void 0})}),I?null:e.createElement(e.Fragment,null,e.createElement(p,{marginY:2},e.createElement(Mn,{variant:"middle"})),e.createElement(dt,null,`Matched ${d.permissions.length} ${d.permissions.length===1?"permission":"permissions"}`)))),e.createElement(p,{mb:5,flex:1},e.createElement(p,{display:"flex",alignItems:"center"},e.createElement(ca,{value:f,exclusive:!0,fullWidth:!0,"aria-label":"Decision result",onChange:(T,C)=>S(C)},e.createElement(Ze,{value:"allow","aria-label":"Decision allowed",disabled:n},"Allow"),e.createElement(Ze,{value:"deny","aria-label":"Decision denied",disabled:n},"Deny"),e.createElement(Ze,{value:"conditional","aria-label":"Decision conditionally allowed",disabled:!d.commonResourceType||n},"Conditional")),!g&&!n&&e.createElement(he,{title:Qt},e.createElement(yt,{className:r.infoIcon,color:"primary","aria-label":Qt}))))),f==="conditional"&&!!d.commonResourceType&&e.createElement(Ba,{permissionCriteria:h,resourceType:d.commonResourceType,onUpdate:y,readonly:n}),!n&&e.createElement(p,{display:"flex",justifyContent:"flex-end"},e.createElement(x,{variant:"contained",color:"primary",className:r.saveButton,onClick:O,disabled:!A||!F},"Save"))))}function Wa(t,n){const a=(t??[]).filter(o=>Xn(o,Zt(n))),l=or(a,"resourceType"),r=l.length===1&&at(l[0])?l[0].resourceType:void 0;return{permissions:a,commonResourceType:r}}const en="Permission name";function za({name:t="",readonly:n,onNameChange:a}){const l=nt(),r=vt();return e.createElement(Le,{className:l.fullWidth,variant:"outlined",disabled:n},e.createElement(be,{id:"match-by-name-dropdown"},en),e.createElement(Fe,{labelId:"match-by-name-dropdown",label:en,value:r?t:"",onChange:o=>a?.(o.target.value)},r?.map(o=>e.createElement(ne,{key:o.name,value:o.name},o.name))))}const tn="Resource type";function Ga({resourceType:t="",readonly:n,onResourceTypeChange:a}){const l=nt(),r=Ct();return e.createElement(Le,{className:l.fullWidth,variant:"outlined",disabled:n},e.createElement(be,{id:"match-by-resource-dropdown"},tn),e.createElement(Fe,{labelId:"match-by-resource-dropdown",label:tn,value:r?t:"",onChange:o=>a?.(o.target.value),displayEmpty:!0},r?.map(o=>e.createElement(ne,{key:o,value:o},o))))}const Ua="Action";function Ya({actions:t,readonly:n,onActionsChange:a}){const l=["create","read","update","delete"];return e.createElement(ze,{multiple:!0,id:"match-by-attribute-dropdown",options:l,getOptionLabel:r=>r,value:t??[],onChange:(r,o)=>a?.(o),filterSelectedOptions:!0,renderInput:r=>e.createElement(le,{...r,variant:"outlined",label:Ua,placeholder:"Choose attributes",margin:"normal"}),disabled:n})}const Ja=N(t=>({closeButton:{color:t.palette.text.secondary}})),nn=({children:t,onConfirm:n,message:a,title:l})=>{const r=Ja(),[o,c]=B(!1),m=()=>c(!1),u=()=>c(!0),i=()=>{n(),m()};return e.createElement(e.Fragment,null,t({onClick:u}),e.createElement(te,{open:o,onClose:m},e.createElement(ge,null,e.createElement(p,{display:"flex",justifyContent:"space-between",alignItems:"center"},l,e.createElement(x,{startIcon:e.createElement(ve,null),onClick:m,className:r.closeButton},"Close"))),e.createElement(q,null,e.createElement(_n,null,a)),e.createElement(Be,null,e.createElement(x,{"aria-label":"Cancel action",color:"primary",onClick:m},"Cancel"),e.createElement(x,{"aria-label":"Confirm action",color:"secondary",onClick:i,variant:"contained"},"Confirm"))))},rn=({helpText:t})=>e.createElement(p,{display:"flex",alignItems:"center"},e.createElement(p,{component:"span",mr:1},e.createElement(D,{variant:"body2",noWrap:!0},"Reorder")),e.createElement(he,{title:t},e.createElement(yt,{color:"primary","aria-label":t}))),an=(t,n,a)=>{const l=n+a;if(l<0||l>=t.length)return t;const r=[...t];return[r[l],r[n]]=[r[n],r[l]],r},ln=({array:t,index:n,onReorder:a})=>{const l=n===0,r=n===t.length-1;return e.createElement(p,{display:"flex"},e.createElement(H,{disabled:l,onClick:()=>a(an(t,n,-1)),"aria-label":"Move up",size:"small"},e.createElement(Er,null)),e.createElement(H,{disabled:r,onClick:()=>a(an(t,n,1)),"aria-label":"Move down",size:"small"},e.createElement(fr,null)))},on=t=>{if(t.success)return{};const n={};for(const a of t.error.issues)n[a.path.join(".")]=!0;return n},Ka=N(()=>({emptyStateImage:{width:"95%",zIndex:2,position:"relative",left:"50%",top:"50%",transform:"translate(-50%, 15%)"}}));function cn({src:t,alt:n}){const a=Ka();return e.createElement("img",{src:t,className:`${a.emptyStateImage} `,alt:n})}const qa="Use the arrows to change the order in which permission decisions are evaluated.";function Xa(){const{roleId:t,versionId:n}=rt();return He(t),He(n),e.createElement(Pe,{policyId:n},e.createElement(Za,{roleId:t}))}function Za({roleId:t}){const{diff:n,updateLocalDraft:a,policy:l}=ae(),r=l.roles.find(C=>C.id===t),o=n?.roles[t],[c,m]=B(null),[u,i]=B(!1),s=we(),{NotFoundErrorPage:f}=s.getComponents(),E=Y(),y=N(C=>({cardContainer:{margin:C.spacing(0)}}))();if(!r)return e.createElement(f,null);const d=r.name,g=C=>{const M=l.roles.findIndex(z=>z.id===C.id),R=[...l.roles];R.splice(M,1,C),a({...l,roles:R})},P=C=>{g({...r,name:C})},S=C=>{if(c===null)g({...r,permissions:[C,...r.permissions]});else{const M=[...r.permissions];M.splice(c,1,C),g({...r,permissions:M})}i(!1)},I=C=>{if(C==="*")g({...r,members:r.members==="*"?[]:"*"});else if(r.members==="*")g({...r,members:[C]});else{const M=r.members.includes(C)?r.members.filter(R=>R!==C):[...r.members,C];g({...r,members:M.length===0?"*":M})}},A=C=>{g({...r,permissions:r.permissions.filter((M,R)=>C!==R)})},F=C=>{g({...r,permissions:C})},O=on(Zn.safeParse(r)).name,T=l.status!=="draft";return e.createElement(e.Fragment,null,e.createElement(Xe,{pages:[{title:l.name,path:`../../../${l.id}`},{title:d}],header:e.createElement(ke,{titleComponent:e.createElement(Ot,null,l.name," \xA0\u01C0",T?e.createElement(e.Fragment,null,"\xA0",d):e.createElement(Ft,{invalid:O,value:d,onTextChange:P}),e.createElement(me,{operation:o?.role.operation,size:"large"})),description:l.description},e.createElement(x,{variant:"outlined",color:"primary",onClick:()=>E("../..",{relative:"path"})},"Back to policy"))},e.createElement(V,{container:!0,className:y.cardContainer,spacing:4,direction:"row"},e.createElement(V,{item:!0,xs:6},e.createElement(K,null,e.createElement(aa,{diff:o||null,role:r,policyId:l.id,onToggleMember:I,readonly:T}))),e.createElement(V,{item:!0,xs:6},e.createElement(K,null,e.createElement(Qa,{diff:o||null,permissions:r.permissions,onNewPermissionClick:()=>{m(null),i(!0)},onOpenPermission:C=>{m(C),i(!0)},onReorderPermissions:F,onRemovePermissionClick:A,readonly:T}))))),u&&e.createElement(Va,{rolePermission:c!==null?r.permissions[c]:void 0,onClose:()=>i(!1),onSave:S,readonly:T}))}function Qa({diff:t,permissions:n,onReorderPermissions:a,onNewPermissionClick:l,onOpenPermission:r,onRemovePermissionClick:o,readonly:c=!1}){return e.createElement(e.Fragment,null,e.createElement(p,{display:"flex",justifyContent:"space-between",padding:2},e.createElement(D,{variant:"h5"},"Permission Decisions"),!c&&n.length!==0&&e.createElement(x,{color:"primary",variant:"outlined",startIcon:e.createElement(Ve,null),onClick:l},"New")),e.createElement(Me,null,e.createElement(_e,null,e.createElement(W,null,!c&&e.createElement(v,{style:{width:0}},e.createElement(rn,{helpText:qa})),e.createElement(v,null,"Match by"),e.createElement(v,null,"Decision"),e.createElement(v,null),!c&&e.createElement(v,null))),e.createElement($e,null,n.length===0&&e.createElement(W,null,e.createElement(v,{colSpan:5},e.createElement(Ee,{title:"No permission decisions set",description:"Click the button below to create your first permission.",missing:{customImage:e.createElement(cn,{src:yr,alt:"No permission placeholder"})},action:e.createElement(x,{variant:"contained",color:"primary",onClick:l},"New permission decision")}))),n.map((m,u)=>e.createElement(W,{key:u},!c&&e.createElement(v,null,e.createElement(ln,{array:n,index:u,onReorder:a})),e.createElement(v,null,e.createElement(ee,{to:"#",component:"button",onClick:()=>r(u)},Ke(m))),e.createElement(v,null,wr(m)),e.createElement(v,null,e.createElement(me,{operation:t?.permissions[m.id].operation})),!c&&e.createElement(v,{align:"right"},e.createElement(nn,{message:"Are you sure you want to remove this permission decision?",onConfirm:()=>o(u),title:"Remove?"},i=>e.createElement(H,{...i,"aria-label":"Remove permission decision",size:"small"},e.createElement(ie,null)))))))))}const el="Use the arrows to change the order in which roles are evaluated.";function tl({}){const{diff:t,policy:n,createNewRole:a,updateLocalDraft:l}=ae(),r=Y(),o=nl(n),c=n.status!=="draft",m=s=>{l({...n,roles:s})},u=s=>{l({...n,roles:n.roles.filter(({id:f})=>f!==s)})},i=()=>{r(`./roles/${a()}`)};return e.createElement(K,null,e.createElement(p,{display:"flex",justifyContent:"space-between",padding:2},e.createElement(D,{variant:"h5"},"Roles"),!c&&e.createElement(x,{color:"primary",variant:"outlined",startIcon:e.createElement(Ve,null),onClick:()=>i()},"New role")),e.createElement(Me,null,e.createElement(_e,null,e.createElement(W,null,!c&&e.createElement(v,{style:{width:0}},e.createElement(rn,{helpText:el})),e.createElement(v,null,"Name"),e.createElement(v,null,"Users"),e.createElement(v,null,"Groups"),!c&&e.createElement(v,{style:{width:0}}))),e.createElement($e,null,o.map((s,f)=>e.createElement(W,{key:f},!c&&e.createElement(v,null,e.createElement(ln,{array:n.roles,index:f,onReorder:m})),e.createElement(v,null,e.createElement(p,{alignItems:"center",display:"flex",gridGap:8},e.createElement(ee,{to:`roles/${s.id}`},s.name),e.createElement(me,{operation:t?.roles[s.id].role.operation}))),e.createElement(v,null,s.userCount),e.createElement(v,null,s.groupCount),!c&&e.createElement(v,{align:"right"},e.createElement(nn,{message:"Are you sure you want to remove this role?",title:"Remove role?",onConfirm:()=>u(s.id)},E=>e.createElement(H,{...E,"aria-label":"Remove role",size:"small"},e.createElement(ie,null)))))))))}function nl(t){return t.roles.map(n=>({id:n.id,name:n.name,userCount:Array.isArray(n.members)?n.members.filter(a=>a.startsWith("user:")).length:n.members,groupCount:Array.isArray(n.members)?n.members.filter(a=>a.startsWith("group:")).length:n.members}))}function rl(){const{versionId:t}=rt();return He(t),e.createElement(Pe,{policyId:t},e.createElement(al,null))}function al(){const{policy:t,hasChanges:n,discardLocalDraft:a,saveLocalDraftToServer:l,updateLocalDraft:r}=ae(),o=s=>{r({...t,name:s})},c=on(Qn.safeParse(t)).name,m=t.status!=="draft",u=Ce.safeParse(t).success,i=n&&u;return e.createElement(Xe,{pages:[{title:t.name}],header:e.createElement(ke,{title:t.name,titleComponent:e.createElement(Ot,null,m?t.name:e.createElement(Ft,{invalid:c,name:"Policy name",value:t.name,onTextChange:o}),e.createElement(Tt,{status:t.status})),description:il(t)},e.createElement(p,{display:"flex",gridGap:8},e.createElement(x,{variant:"outlined",color:"primary",onClick:()=>Dt(t)},"Export"),t.status==="draft"&&e.createElement(e.Fragment,null,n&&e.createElement(x,{variant:"outlined",color:"secondary",onClick:a},"Discard changes"),e.createElement(x,{variant:"outlined",color:"primary",onClick:l,disabled:!i},"Save draft")),t.status!=="active"&&e.createElement(Bt,{color:"primary",variant:"contained"})))},e.createElement(V,{item:!0,xs:12},t.roles.length>0?e.createElement(tl,null):e.createElement(ol,{readonly:m})))}const ll=N(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 ol({readonly:t}){const n=ll(),a=Y(),{createNewRole:l}=ae(),r=()=>{const o=l();a(`./roles/${o}`)};return e.createElement(K,null,e.createElement($n,{title:"Roles",className:n.cardHeader}),e.createElement(ye,{className:n.cardContent},t?e.createElement(Ee,{title:"No roles configured",missing:"content"}):e.createElement(Ee,{title:"No roles yet",description:"Click the button below to create your first role.",missing:{customImage:e.createElement(cn,{src:gr,alt:"No roles placeholder"})},action:e.createElement(x,{variant:"contained",color:"primary",onClick:()=>r()},"New role")})))}function il(t){if(t.lastPublishedAt){const a=L.fromISO(t.lastPublishedAt);return`Last published by ${t.lastPublishedBy} on ${a.toLocaleString(L.DATETIME_MED_WITH_SECONDS)}`}if(t.createdAt!==t.updatedAt){const a=L.fromISO(t.updatedAt);return`Last updated by ${t.updatedBy} on ${a.toLocaleString(L.DATETIME_MED_WITH_SECONDS)}`}const n=L.fromISO(t.createdAt);return`Created by ${t.createdBy} on ${n.toLocaleString(L.DATETIME_MED_WITH_SECONDS)}`}function cl(){const t=we(),{NotFoundErrorPage:n}=t.getComponents();return e.createElement(hr,{loading:e.createElement(fe,null),unauthorized:e.createElement(n,null)},e.createElement(Nr,null,e.createElement(br,null,e.createElement(dn,null,e.createElement(Re,{element:e.createElement(Jr,null),path:"/"}),e.createElement(Re,{element:e.createElement(rl,null),path:"/versions/:versionId"}),e.createElement(Re,{element:e.createElement(Xa,null),path:"/versions/:versionId/roles/:roleId"})))))}export{cl as RBACRoot};
3
+ //# sourceMappingURL=Root-e3ab1bbe.esm.js.map
@@ -0,0 +1,2 @@
1
+ import{createApiRef as y,createRouteRef as A,createPlugin as m,createApiFactory as u,fetchApiRef as R,discoveryApiRef as b,createRoutableExtension as w,createComponentExtension as g}from"@backstage/core-plugin-api";import{ResponseError as v}from"@backstage/errors";const p=y({id:"plugin.rbac"});class B{constructor(e){this.fetchApi=e.fetchApi,this.discoveryApi=e.discoveryApi}async getPolicies(){const{fetch:e}=this.fetchApi,s=await e(`${await this.discoveryApi.getBaseUrl("rbac")}/policies`);return this.parseResponse(s)}async getPolicy(e){const{fetch:s}=this.fetchApi,t=await s(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${e}`);return this.parseResponse(t)}async getActivePolicy(){const{fetch:e}=this.fetchApi,s=await e(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/active`);return this.parseResponse(s)}async searchMembers(e){const{fetch:s}=this.fetchApi,t=await s(`${await this.discoveryApi.getBaseUrl("rbac")}/members?query=${encodeURIComponent(e.query)}`);return this.parseResponse(t)}async getRoleMembers({policyId:e,roleId:s}){const{fetch:t}=this.fetchApi,i=await t(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${e}/roles/${s}/members`);return this.parseResponse(i)}async authorize(){const{fetch:e}=this.fetchApi,s=await e(`${await this.discoveryApi.getBaseUrl("rbac")}/authorize`);return this.parseResponse(s)}async createDraft(e){const{fetch:s}=this.fetchApi,t=await s(`${await this.discoveryApi.getBaseUrl("rbac")}/policies`,{method:"POST",body:JSON.stringify(e),headers:{"Content-Type":"application/json"}});return this.parseResponse(t)}async updateDraft(e,s){const{fetch:t}=this.fetchApi,i=await t(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${e}`,{method:"PATCH",body:JSON.stringify(s),headers:{"Content-Type":"application/json"}});return this.parseResponse(i)}async deleteDraft(e){const{fetch:s}=this.fetchApi,t=await s(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${e}`,{method:"DELETE"});return this.parseResponse(t)}async publishPolicy(e,s){const{fetch:t}=this.fetchApi,i=await t(`${await this.discoveryApi.getBaseUrl("rbac")}/policies/${e}/publish`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({description:s.description})});return this.parseResponse(i)}async fetchAllPermissionMetadata(e){const s=await Promise.all(e.map(t=>this.fetchPermissionMetadata(t)));return{permissions:s.flatMap(({permissions:t})=>t),rules:s.flatMap(({rules:t})=>t)}}async fetchPermissionMetadata(e){var s,t,i,n;const h=await this.discoveryApi.getBaseUrl(e),c=await(await this.fetchApi.fetch(`${h}/.well-known/backstage/permissions/metadata`)).json(),l=(t=(s=c.permissions)==null?void 0:s.filter(Boolean))!=null?t:[],f=(n=(i=c.rules)==null?void 0:i.filter(Boolean))!=null?n:[];return{permissions:l,rules:f.map(d=>({...d,pluginId:e}))}}async parseResponse(e){var s,t;if(e.ok)return e.status===204?void 0:e.json();const i=await v.fromResponse(e);throw i.message=(t=(s=i.body.error.message)!=null?s:i.message)!=null?t:"Unknown error",i}}const o=A({id:"rbac"}),r=m({id:"rbac",routes:{root:o},apis:[u({api:p,deps:{fetchApi:R,discoveryApi:b},factory(a){return new B(a)}})]}),$=r.provide(w({name:"RBACRoot",component:()=>import("./Root-e3ab1bbe.esm.js").then(a=>a.RBACRoot),mountPoint:o})),P=r.provide(g({name:"RBACSidebarItem",component:{lazy:()=>import("./RBACSidebarItem-ca7b78f0.esm.js").then(a=>a.RBACSidebarItem)}}));export{$ as R,o as a,r as b,P as c,p as r};
2
+ //# sourceMappingURL=index-bb1908ac.esm.js.map
@@ -0,0 +1,53 @@
1
+ <svg width="337" height="207" viewBox="0 0 337 207" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M19.6449 53.9135C13.1919 55.116 8.93546 61.322 10.1379 67.775C11.3404 74.228 17.5464 78.4845 23.9994 77.282L32.8883 75.6256C30.414 78.2894 29.1893 82.0503 29.9065 85.899C31.109 92.3521 37.315 96.6085 43.768 95.406L107.066 83.6108C107.079 83.6873 107.092 83.7639 107.107 83.8405C107.824 87.6904 110.322 90.7584 113.592 92.3518L109.707 93.0756C103.254 94.2781 98.998 100.484 100.2 106.937C101.403 113.39 107.609 117.647 114.062 116.444L298.549 82.0661C305.002 80.8636 309.259 74.6576 308.056 68.2046C307.339 64.3547 304.84 61.2867 301.571 59.6932L307.785 58.5353C314.238 57.3328 318.495 51.1268 317.292 44.6738C316.09 38.2208 309.884 33.9644 303.431 35.1669L192.777 55.7864C192.764 55.7099 192.751 55.6333 192.737 55.5567C192.02 51.708 189.522 48.6406 186.255 47.0468L196.995 45.0453C203.448 43.8428 207.705 37.6368 206.502 31.1838C205.3 24.7308 199.094 20.4744 192.641 21.6769L19.6449 53.9135ZM29.011 146.279C27.8085 139.826 32.0649 133.62 38.5179 132.417L227.831 97.1402C234.284 95.9378 240.49 100.194 241.692 106.647C242.895 113.1 238.638 119.306 232.185 120.509L226.763 121.519C227.396 121.828 228.001 122.192 228.569 122.606L294.17 110.382C300.623 109.179 306.829 113.435 308.032 119.888C308.749 123.738 307.524 127.499 305.049 130.163L306.369 129.917C312.822 128.715 319.028 132.971 320.231 139.424C321.433 145.877 317.177 152.083 310.724 153.286L114.072 189.93C107.619 191.133 101.413 186.876 100.21 180.423C99.0077 173.97 103.264 167.764 109.717 166.562L124.076 163.886C123.443 163.578 122.84 163.214 122.272 162.801L34.7377 179.112C28.2847 180.315 22.0787 176.058 20.8762 169.605C19.6737 163.152 23.9301 156.946 30.3832 155.744L35.4968 154.791C32.2272 153.197 29.7284 150.129 29.011 146.279Z" fill="black" fill-opacity="0.05"/>
3
+ <g filter="url(#filter0_ddd_1738_75753)">
4
+ <rect x="80" y="60" width="97" height="117" rx="6" fill="#EEEEEE"/>
5
+ </g>
6
+ <path d="M151.187 101.333H147.43V93.8095C147.43 83.4267 139.016 75 128.649 75C118.282 75 109.868 83.4267 109.868 93.8095V101.333H106.112C101.98 101.333 98.5996 104.719 98.5996 108.857V146.476C98.5996 150.614 101.98 154 106.112 154H151.187C155.318 154 158.699 150.614 158.699 146.476V108.857C158.699 104.719 155.318 101.333 151.187 101.333ZM128.649 135.19C124.517 135.19 121.137 131.805 121.137 127.667C121.137 123.529 124.517 120.143 128.649 120.143C132.781 120.143 136.162 123.529 136.162 127.667C136.162 131.805 132.781 135.19 128.649 135.19ZM140.294 101.333H117.005V93.8095C117.005 87.3767 122.226 82.1476 128.649 82.1476C135.072 82.1476 140.294 87.3767 140.294 93.8095V101.333Z" fill="#C4C4C4"/>
7
+ <g filter="url(#filter1_ddd_1738_75753)">
8
+ <rect x="168" y="37" width="97" height="117" rx="6" fill="#EEEEEE"/>
9
+ </g>
10
+ <path d="M239.332 78.3333H235.576V70.8095C235.576 60.4267 227.162 52 216.795 52C206.428 52 198.014 60.4267 198.014 70.8095V78.3333H194.258C190.126 78.3333 186.745 81.719 186.745 85.8571V123.476C186.745 127.614 190.126 131 194.258 131H239.332C243.464 131 246.844 127.614 246.844 123.476V85.8571C246.844 81.719 243.464 78.3333 239.332 78.3333ZM216.795 112.19C212.663 112.19 209.282 108.805 209.282 104.667C209.282 100.529 212.663 97.1429 216.795 97.1429C220.927 97.1429 224.307 100.529 224.307 104.667C224.307 108.805 220.927 112.19 216.795 112.19ZM228.439 78.3333H205.151V70.8095C205.151 64.3767 210.372 59.1476 216.795 59.1476C223.218 59.1476 228.439 64.3767 228.439 70.8095V78.3333Z" fill="#C4C4C4"/>
11
+ <defs>
12
+ <filter id="filter0_ddd_1738_75753" x="66" y="50" width="125" height="145" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
13
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
14
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
15
+ <feOffset dy="2"/>
16
+ <feGaussianBlur stdDeviation="0.5"/>
17
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
18
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1738_75753"/>
19
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
20
+ <feOffset dy="1"/>
21
+ <feGaussianBlur stdDeviation="0.5"/>
22
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
23
+ <feBlend mode="normal" in2="effect1_dropShadow_1738_75753" result="effect2_dropShadow_1738_75753"/>
24
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
25
+ <feOffset dy="4"/>
26
+ <feGaussianBlur stdDeviation="7"/>
27
+ <feComposite in2="hardAlpha" operator="out"/>
28
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"/>
29
+ <feBlend mode="normal" in2="effect2_dropShadow_1738_75753" result="effect3_dropShadow_1738_75753"/>
30
+ <feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_1738_75753" result="shape"/>
31
+ </filter>
32
+ <filter id="filter1_ddd_1738_75753" x="154" y="27" width="125" height="145" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
33
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
34
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
35
+ <feOffset dy="2"/>
36
+ <feGaussianBlur stdDeviation="0.5"/>
37
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
38
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1738_75753"/>
39
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
40
+ <feOffset dy="1"/>
41
+ <feGaussianBlur stdDeviation="0.5"/>
42
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
43
+ <feBlend mode="normal" in2="effect1_dropShadow_1738_75753" result="effect2_dropShadow_1738_75753"/>
44
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
45
+ <feOffset dy="4"/>
46
+ <feGaussianBlur stdDeviation="7"/>
47
+ <feComposite in2="hardAlpha" operator="out"/>
48
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"/>
49
+ <feBlend mode="normal" in2="effect2_dropShadow_1738_75753" result="effect3_dropShadow_1738_75753"/>
50
+ <feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_1738_75753" result="shape"/>
51
+ </filter>
52
+ </defs>
53
+ </svg>
@@ -0,0 +1,60 @@
1
+ <svg width="543" height="333" viewBox="0 0 543 333" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M31.6665 86.9058C21.2646 88.8441 14.4035 98.8479 16.3418 109.25C18.2801 119.652 28.2839 126.513 38.6858 124.574L53.0156 121.904C49.0264 126.198 47.0519 132.261 48.208 138.465C50.1464 148.867 60.1501 155.728 70.552 153.79L172.585 134.777C172.606 134.9 172.628 135.024 172.651 135.147C173.807 141.353 177.834 146.298 183.104 148.867L176.843 150.034C166.441 151.972 159.58 161.976 161.518 172.378C163.456 182.78 173.46 189.641 183.862 187.702L481.245 132.287C491.647 130.349 498.508 120.345 496.57 109.943C495.413 103.737 491.386 98.7919 486.117 96.2233L496.133 94.3568C506.535 92.4185 513.396 82.4148 511.458 72.0129C509.52 61.611 499.516 54.7499 489.114 56.6882L310.747 89.9258C310.726 89.8024 310.704 89.6789 310.681 89.5553C309.525 83.3509 305.499 78.4062 300.231 75.8372L317.546 72.6107C327.948 70.6724 334.809 60.6687 332.87 50.2668C330.932 39.8649 320.928 33.0038 310.526 34.9421L31.6665 86.9058ZM46.7645 235.794C44.8262 225.392 51.6873 215.389 62.0892 213.45L367.251 156.585C377.653 154.647 387.657 161.508 389.595 171.91C391.533 182.312 384.672 192.316 374.27 194.254L365.53 195.883C366.55 196.38 367.524 196.967 368.44 197.634L474.186 177.929C484.588 175.991 494.591 182.852 496.53 193.254C497.686 199.459 495.711 205.522 491.721 209.816L493.851 209.419C504.252 207.481 514.256 214.342 516.194 224.744C518.133 235.146 511.272 245.149 500.87 247.088L183.877 306.157C173.475 308.096 163.472 301.234 161.533 290.833C159.595 280.431 166.456 270.427 176.858 268.489L200.003 264.176C198.983 263.679 198.011 263.093 197.096 262.426L55.9953 288.719C45.5934 290.657 35.5897 283.796 33.6513 273.394C31.713 262.992 38.5741 252.989 48.976 251.05L57.2186 249.514C51.9485 246.946 47.921 242 46.7645 235.794Z" fill="black" fill-opacity="0.05"/>
3
+ <g filter="url(#filter0_ddd_1223_62287)">
4
+ <rect x="72.5371" y="88.6572" width="224.06" height="169.254" rx="6" fill="#EEEEEE"/>
5
+ </g>
6
+ <path d="M146.744 181.689V198.5C150.089 198.5 153.295 199.828 155.66 202.192C158.024 204.557 159.352 207.763 159.352 211.107L159.352 219.512C159.352 222.857 158.024 226.063 155.66 228.428C153.295 230.792 150.089 232.12 146.744 232.12H138.339C134.995 232.12 131.789 230.792 129.424 228.428C127.06 226.063 125.731 222.857 125.731 219.512V211.107C125.731 207.763 127.06 204.557 129.424 202.192C131.789 199.828 134.995 198.5 138.339 198.5V181.689C138.339 178.345 139.667 175.139 142.031 172.774C144.396 170.41 147.603 169.082 150.947 169.082H180.365V148.069C177.021 148.069 173.814 146.74 171.449 144.377C169.085 142.012 167.757 138.805 167.757 135.461V127.056C167.757 123.712 169.085 120.505 171.449 118.14C173.814 115.777 177.021 114.448 180.365 114.448H188.77C192.114 114.448 195.32 115.777 197.685 118.14C200.049 120.505 201.378 123.712 201.378 127.056V135.461C201.378 138.805 200.049 142.012 197.685 144.377C195.321 146.74 192.114 148.069 188.77 148.069V169.082H218.188C221.532 169.082 224.738 170.41 227.103 172.774C229.467 175.139 230.796 178.345 230.796 181.689V198.5C234.14 198.5 237.346 199.828 239.711 202.192C242.075 204.557 243.403 207.763 243.403 211.107V219.512C243.403 222.857 242.075 226.063 239.711 228.428C237.346 230.792 234.14 232.12 230.796 232.12H222.391C219.046 232.12 215.84 230.792 213.475 228.428C211.111 226.063 209.783 222.857 209.783 219.512V211.107C209.783 207.763 211.111 204.557 213.475 202.192C215.84 199.828 219.046 198.5 222.391 198.5V181.689C222.391 180.575 221.948 179.506 221.16 178.718C220.372 177.93 219.302 177.487 218.188 177.487H188.77V198.5C192.114 198.5 195.32 199.828 197.685 202.192C200.049 204.557 201.378 207.763 201.378 211.107V219.512C201.378 222.857 200.049 226.063 197.685 228.428C195.321 230.792 192.114 232.12 188.77 232.12H180.365C177.021 232.12 173.814 230.792 171.449 228.428C169.085 226.063 167.757 222.857 167.757 219.512L167.757 211.107C167.757 207.763 169.085 204.557 171.449 202.192C173.814 199.828 177.021 198.5 180.365 198.5V177.487H150.947C149.832 177.487 148.763 177.93 147.975 178.718C147.187 179.506 146.744 180.575 146.744 181.689ZM138.339 206.905C137.225 206.905 136.155 207.348 135.367 208.136C134.579 208.923 134.137 209.993 134.137 211.107V219.512C134.137 220.627 134.579 221.696 135.367 222.484C136.155 223.272 137.225 223.715 138.339 223.715H146.744C147.859 223.715 148.928 223.272 149.716 222.484C150.504 221.696 150.947 220.627 150.947 219.512V211.107C150.947 209.993 150.504 208.923 149.716 208.136C148.928 207.348 147.859 206.905 146.744 206.905H138.339ZM188.77 139.664C189.884 139.664 190.954 139.221 191.742 138.433C192.53 137.645 192.973 136.576 192.973 135.461V127.056C192.973 125.942 192.53 124.872 191.742 124.084C190.954 123.296 189.884 122.853 188.77 122.853H180.365C179.25 122.853 178.181 123.296 177.393 124.084C176.605 124.872 176.162 125.942 176.162 127.056V135.461C176.162 136.576 176.605 137.645 177.393 138.433C178.181 139.221 179.25 139.664 180.365 139.664H188.77ZM222.391 206.905C221.276 206.905 220.207 207.348 219.419 208.136C218.631 208.923 218.188 209.993 218.188 211.107V219.512C218.188 220.627 218.631 221.696 219.419 222.484C220.207 223.272 221.276 223.715 222.391 223.715H230.796C231.91 223.715 232.98 223.272 233.767 222.484C234.555 221.696 234.998 220.627 234.998 219.512V211.107C234.998 209.993 234.555 208.923 233.767 208.136C232.98 207.348 231.91 206.905 230.796 206.905H222.391ZM180.365 206.905C179.25 206.905 178.181 207.348 177.393 208.136C176.605 208.923 176.162 209.993 176.162 211.107L176.162 219.512C176.162 220.627 176.605 221.696 177.393 222.484C178.181 223.272 179.25 223.715 180.365 223.715H188.77C189.884 223.715 190.954 223.272 191.742 222.484C192.53 221.696 192.973 220.627 192.973 219.512V211.107C192.973 209.993 192.53 208.923 191.742 208.136C190.954 207.348 189.884 206.905 188.77 206.905H180.365Z" fill="#C4C4C4"/>
7
+ <g filter="url(#filter1_ddd_1223_62287)">
8
+ <rect x="234" y="37" width="224.06" height="169.254" rx="6" fill="#EEEEEE"/>
9
+ </g>
10
+ <rect x="289.4" y="99.0908" width="137.584" height="17.198" rx="2" fill="#F8F8F8"/>
11
+ <rect x="289.4" y="153.91" width="137.584" height="17.198" rx="2" fill="#F8F8F8"/>
12
+ <rect x="289.4" y="125.963" width="137.584" height="18.2728" rx="2" fill="#D9D9D9"/>
13
+ <rect x="289.4" y="71.1445" width="137.584" height="17.198" rx="2" fill="#D9D9D9"/>
14
+ <rect x="265" y="98.7227" width="17.3263" height="17.3263" rx="2" fill="#F8F8F8"/>
15
+ <rect x="265" y="154.167" width="17.3263" height="17.3263" rx="2" fill="#F8F8F8"/>
16
+ <rect x="265" y="126.444" width="17.3263" height="17.3263" rx="2" fill="#D9D9D9"/>
17
+ <rect x="265" y="71" width="17.3263" height="17.3263" rx="2" fill="#D9D9D9"/>
18
+ <defs>
19
+ <filter id="filter0_ddd_1223_62287" x="58.5371" y="78.6572" width="252.061" height="197.254" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
20
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
21
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
22
+ <feOffset dy="2"/>
23
+ <feGaussianBlur stdDeviation="0.5"/>
24
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
25
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1223_62287"/>
26
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
27
+ <feOffset dy="1"/>
28
+ <feGaussianBlur stdDeviation="0.5"/>
29
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
30
+ <feBlend mode="normal" in2="effect1_dropShadow_1223_62287" result="effect2_dropShadow_1223_62287"/>
31
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
32
+ <feOffset dy="4"/>
33
+ <feGaussianBlur stdDeviation="7"/>
34
+ <feComposite in2="hardAlpha" operator="out"/>
35
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"/>
36
+ <feBlend mode="normal" in2="effect2_dropShadow_1223_62287" result="effect3_dropShadow_1223_62287"/>
37
+ <feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_1223_62287" result="shape"/>
38
+ </filter>
39
+ <filter id="filter1_ddd_1223_62287" x="220" y="27" width="252.061" height="197.254" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
40
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
41
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
42
+ <feOffset dy="2"/>
43
+ <feGaussianBlur stdDeviation="0.5"/>
44
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
45
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1223_62287"/>
46
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
47
+ <feOffset dy="1"/>
48
+ <feGaussianBlur stdDeviation="0.5"/>
49
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
50
+ <feBlend mode="normal" in2="effect1_dropShadow_1223_62287" result="effect2_dropShadow_1223_62287"/>
51
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
52
+ <feOffset dy="4"/>
53
+ <feGaussianBlur stdDeviation="7"/>
54
+ <feComposite in2="hardAlpha" operator="out"/>
55
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"/>
56
+ <feBlend mode="normal" in2="effect2_dropShadow_1223_62287" result="effect3_dropShadow_1223_62287"/>
57
+ <feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_1223_62287" result="shape"/>
58
+ </filter>
59
+ </defs>
60
+ </svg>
@@ -0,0 +1,17 @@
1
+ /// <reference types="react" />
2
+ import React from 'react';
3
+ import { SidebarItem } from '@backstage/core-components';
4
+ import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
5
+
6
+ declare function RBACSidebarItem$1({ text, ...props }: Partial<PropsFor<typeof SidebarItem>>): JSX.Element;
7
+ declare type PropsFor<T> = T extends React.ComponentType<infer P> ? P : never;
8
+
9
+ declare function RBACRoot$1(): JSX.Element;
10
+
11
+ declare const rbacPlugin: _backstage_core_plugin_api.BackstagePlugin<{
12
+ root: _backstage_core_plugin_api.RouteRef<undefined>;
13
+ }, {}, {}>;
14
+ declare const RBACRoot: typeof RBACRoot$1;
15
+ declare const RBACSidebarItem: typeof RBACSidebarItem$1;
16
+
17
+ export { RBACRoot, RBACSidebarItem, rbacPlugin };
@@ -0,0 +1,2 @@
1
+ import{R as i,c as m,b as R}from"./esm/index-bb1908ac.esm.js";import"@backstage/core-plugin-api";import"@backstage/errors";export{i as RBACRoot,m as RBACSidebarItem,R as rbacPlugin};
2
+ //# sourceMappingURL=index.esm.js.map
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "@spotify/backstage-plugin-rbac",
3
+ "description": "Control access to actions and data in Backstage with ease.",
4
+ "version": "0.2.1",
5
+ "license": "SEE LICENSE IN LICENSE.md",
6
+ "homepage": "https://backstage.spotify.com/",
7
+ "main": "dist/index.esm.js",
8
+ "types": "dist/index.d.ts",
9
+ "publishConfig": {
10
+ "main": "dist/index.esm.js",
11
+ "types": "dist/index.d.ts"
12
+ },
13
+ "backstage": {
14
+ "role": "frontend-plugin"
15
+ },
16
+ "scripts": {
17
+ "start": "backstage-cli package start",
18
+ "build": "backstage-cli package build --minify",
19
+ "lint": "backstage-cli package lint",
20
+ "test": "backstage-cli package test",
21
+ "clean": "backstage-cli package clean",
22
+ "prepack": "backstage-cli package prepack",
23
+ "postpack": "backstage-cli package postpack"
24
+ },
25
+ "dependencies": {
26
+ "@backstage/catalog-model": "^1.1.4",
27
+ "@backstage/core-components": "^0.12.1",
28
+ "@backstage/core-plugin-api": "^1.2.0",
29
+ "@backstage/errors": "^1.1.4",
30
+ "@backstage/plugin-catalog-react": "^1.2.2",
31
+ "@backstage/plugin-permission-common": "^0.7.2",
32
+ "@backstage/plugin-permission-node": "^0.7.2",
33
+ "@backstage/plugin-permission-react": "^0.4.8",
34
+ "@backstage/theme": "^0.2.16",
35
+ "@backstage/types": "^1.0.2",
36
+ "@material-ui/core": "^4.12.2",
37
+ "@material-ui/icons": "^4.9.1",
38
+ "@material-ui/lab": "4.0.0-alpha.61",
39
+ "@spotify/backstage-plugin-core": "^0.2.2",
40
+ "@spotify/backstage-plugin-rbac-common": "^0.2.1",
41
+ "ajv": "^8.11.2",
42
+ "file-saver": "^2.0.5",
43
+ "js-yaml": "^4.1.0",
44
+ "json-schema": "^0.4.0",
45
+ "lodash": "^4.17.21",
46
+ "luxon": "^3.1.1",
47
+ "react-use": "^17.2.4",
48
+ "uuid": "^8.3.2",
49
+ "vanilla-jsoneditor": "0.11.2",
50
+ "zod": "^3.18.0",
51
+ "zod-to-json-schema": "^3.18.1"
52
+ },
53
+ "peerDependencies": {
54
+ "@backstage/plugin-permission-node": "^0.7.2",
55
+ "react": "^16.13.1 || ^17.0.0",
56
+ "react-router-dom": "6.0.0-beta.0 || ^6.3.0"
57
+ },
58
+ "devDependencies": {
59
+ "@backstage/cli": "^0.22.0",
60
+ "@backstage/core-app-api": "^1.3.0",
61
+ "@backstage/dev-utils": "^1.0.9",
62
+ "@backstage/test-utils": "^1.2.3",
63
+ "@testing-library/jest-dom": "^5.10.1",
64
+ "@testing-library/react": "^12.1.3",
65
+ "@testing-library/react-hooks": "^8.0.0",
66
+ "@testing-library/user-event": "^14.0.0",
67
+ "@types/file-saver": "^2.0.5",
68
+ "@types/jest": "*",
69
+ "@types/node": "*",
70
+ "cross-fetch": "^3.1.5",
71
+ "msw": "^0.49.0"
72
+ },
73
+ "files": [
74
+ "dist",
75
+ "!dist/**/*.map",
76
+ "config.d.ts"
77
+ ],
78
+ "configSchema": "config.d.ts"
79
+ }