@zhama/tego-plugin-access-ui 0.0.0-stage → 1.36.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 +172 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +159 -0
- package/dist/index.d.ts +159 -0
- package/dist/index.js +1 -0
- package/locales/de.json +179 -0
- package/locales/en.json +179 -0
- package/locales/es.json +179 -0
- package/locales/fr.json +179 -0
- package/locales/it.json +179 -0
- package/locales/ja.json +179 -0
- package/locales/ko.json +179 -0
- package/locales/pt.json +179 -0
- package/locales/zh-CN.json +179 -0
- package/locales/zh-TW.json +179 -0
- package/package.json +41 -4
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
Tego 插件开发套件许可协议 / Tego Plugin SDK License
|
|
2
|
+
版本 1.0
|
|
3
|
+
|
|
4
|
+
Copyright (c) 2026 zhama. 保留所有权利。All rights reserved.
|
|
5
|
+
|
|
6
|
+
本协议以中文和英文书就,两种文本如有不一致,以中文文本为准。
|
|
7
|
+
This license is written in Chinese and English. If the two versions differ,
|
|
8
|
+
the Chinese version prevails.
|
|
9
|
+
|
|
10
|
+
============================================================================
|
|
11
|
+
中文文本
|
|
12
|
+
============================================================================
|
|
13
|
+
|
|
14
|
+
一、定义
|
|
15
|
+
|
|
16
|
+
1.1 “许可方”指 zhama。
|
|
17
|
+
1.2 “本软件”指许可方以 @zhama/tego-* 名称发布的软件包,包括其中的源代码、
|
|
18
|
+
编译产物、类型声明、配置文件与文档,以及许可方提供的更新版本。
|
|
19
|
+
1.3 “Tego 平台”指许可方或其授权方提供、部署或运营的 Tego OS 及相关产品与服务。
|
|
20
|
+
1.4 “插件”指为在 Tego 平台中加载与运行而开发的软件扩展,包括其前端、后端与
|
|
21
|
+
智能体组件。
|
|
22
|
+
1.5 “您”指使用本软件的个人或组织。
|
|
23
|
+
|
|
24
|
+
二、许可授予
|
|
25
|
+
|
|
26
|
+
在您遵守本协议的前提下,许可方授予您一项全球范围、非独占、免许可费、不可转让、
|
|
27
|
+
不可再许可的许可,仅为开发、测试、构建、打包和分发插件之目的:
|
|
28
|
+
(a) 安装、使用和复制本软件;
|
|
29
|
+
(b) 为上述目的修改本软件;
|
|
30
|
+
(c) 将本软件中由构建工具打包进插件产物的部分,作为插件的组成部分随插件分发。
|
|
31
|
+
|
|
32
|
+
三、限制
|
|
33
|
+
|
|
34
|
+
除本协议明确允许的以外,您不得:
|
|
35
|
+
(a) 将本软件或其任何部分用于开发、运行或支持不在 Tego 平台中运行的产品或服务;
|
|
36
|
+
(b) 单独分发、出售、出租、再许可、发布或以其他方式提供本软件或其修改版本,
|
|
37
|
+
包括以独立软件包形式发布到任何软件仓库;
|
|
38
|
+
(c) 使用本软件开发与 Tego 平台竞争或用以替代 Tego 平台的产品或服务;
|
|
39
|
+
(d) 删除、遮盖或修改本软件中的版权声明、本协议文本或其他权利声明;
|
|
40
|
+
(e) 规避、绕过或篡改 Tego 平台对插件实施的版本兼容、权限或安全校验。
|
|
41
|
+
|
|
42
|
+
四、您的插件
|
|
43
|
+
|
|
44
|
+
您开发的插件中由您编写的部分归您或相应权利人所有。本协议不授予许可方对您插件
|
|
45
|
+
代码的任何权利,也不限制您按自行选择的条款许可您自己的代码;但插件中包含的本
|
|
46
|
+
软件部分仍受本协议约束。
|
|
47
|
+
|
|
48
|
+
五、权利保留
|
|
49
|
+
|
|
50
|
+
本软件的所有权、著作权及其他知识产权归许可方所有。本协议未明确授予的权利均由
|
|
51
|
+
许可方保留。本协议不授予您使用许可方商号、商标或标识的权利,但为如实说明插件
|
|
52
|
+
适用于 Tego 平台而作的合理提及除外。
|
|
53
|
+
|
|
54
|
+
六、第三方组件
|
|
55
|
+
|
|
56
|
+
本软件依赖的第三方开源组件不属于本软件,受其各自许可证约束。
|
|
57
|
+
|
|
58
|
+
七、免责声明
|
|
59
|
+
|
|
60
|
+
本软件按“现状”提供,不附带任何明示或默示的保证,包括但不限于适销性、特定用途
|
|
61
|
+
适用性和不侵权的保证。
|
|
62
|
+
|
|
63
|
+
八、责任限制
|
|
64
|
+
|
|
65
|
+
在适用法律允许的最大范围内,许可方对因本软件或本协议产生或与之相关的任何间接、
|
|
66
|
+
附带、特殊、惩罚性或后果性损害,或利润、数据、业务的损失,不承担责任;许可方
|
|
67
|
+
就本协议承担的全部责任以人民币一百元为限。
|
|
68
|
+
|
|
69
|
+
九、终止
|
|
70
|
+
|
|
71
|
+
您违反本协议任何条款的,本协议授予的许可自动终止。许可终止后,您应停止使用并
|
|
72
|
+
删除本软件的全部副本。终止前已合法分发给最终用户的插件,最终用户可继续在 Tego
|
|
73
|
+
平台中使用。第四条至第八条及第十条在本协议终止后继续有效。
|
|
74
|
+
|
|
75
|
+
十、适用法律与争议解决
|
|
76
|
+
|
|
77
|
+
本协议适用中华人民共和国法律(为本协议之目的,不包括香港、澳门特别行政区和
|
|
78
|
+
台湾地区法律)。因本协议产生的争议,双方应友好协商;协商不成的,提交许可方
|
|
79
|
+
住所地有管辖权的人民法院诉讼解决。
|
|
80
|
+
|
|
81
|
+
============================================================================
|
|
82
|
+
English text
|
|
83
|
+
============================================================================
|
|
84
|
+
|
|
85
|
+
1. Definitions
|
|
86
|
+
|
|
87
|
+
1.1 "Licensor" means zhama.
|
|
88
|
+
1.2 "Software" means the packages the Licensor publishes under the names
|
|
89
|
+
@zhama/tego-*, including their source code, compiled output, type
|
|
90
|
+
declarations, configuration files and documentation, and any updates the
|
|
91
|
+
Licensor provides.
|
|
92
|
+
1.3 "Tego Platform" means Tego OS and the related products and services
|
|
93
|
+
provided, deployed or operated by the Licensor or its authorized parties.
|
|
94
|
+
1.4 "Plugin" means a software extension developed to be loaded and run in the
|
|
95
|
+
Tego Platform, including its frontend, backend and agent parts.
|
|
96
|
+
1.5 "You" means the individual or organization using the Software.
|
|
97
|
+
|
|
98
|
+
2. License grant
|
|
99
|
+
|
|
100
|
+
Subject to your compliance with this license, the Licensor grants you a
|
|
101
|
+
worldwide, non-exclusive, royalty-free, non-transferable, non-sublicensable
|
|
102
|
+
license, solely to develop, test, build, package and distribute Plugins, to:
|
|
103
|
+
(a) install, use and copy the Software;
|
|
104
|
+
(b) modify the Software for that purpose; and
|
|
105
|
+
(c) distribute those portions of the Software that the build tools include
|
|
106
|
+
in a Plugin's build output, as part of that Plugin.
|
|
107
|
+
|
|
108
|
+
3. Restrictions
|
|
109
|
+
|
|
110
|
+
Except as expressly permitted by this license, you may not:
|
|
111
|
+
(a) use the Software, or any part of it, to develop, run or support any
|
|
112
|
+
product or service that does not run in the Tego Platform;
|
|
113
|
+
(b) distribute, sell, rent, sublicense, publish or otherwise make available
|
|
114
|
+
the Software or a modified version of it on its own, including as a
|
|
115
|
+
standalone package in any package registry;
|
|
116
|
+
(c) use the Software to develop a product or service that competes with or
|
|
117
|
+
substitutes for the Tego Platform;
|
|
118
|
+
(d) remove, obscure or alter any copyright notice, this license text or any
|
|
119
|
+
other proprietary notice in the Software; or
|
|
120
|
+
(e) circumvent, bypass or tamper with the version-compatibility, permission
|
|
121
|
+
or security checks the Tego Platform applies to Plugins.
|
|
122
|
+
|
|
123
|
+
4. Your Plugins
|
|
124
|
+
|
|
125
|
+
The parts of your Plugins that you write belong to you or the respective
|
|
126
|
+
rights holders. This license gives the Licensor no rights in your Plugin code
|
|
127
|
+
and does not restrict you from licensing your own code on terms of your
|
|
128
|
+
choosing; portions of the Software included in a Plugin remain subject to this
|
|
129
|
+
license.
|
|
130
|
+
|
|
131
|
+
5. Reservation of rights
|
|
132
|
+
|
|
133
|
+
The Software and all copyright and other intellectual property rights in it
|
|
134
|
+
belong to the Licensor. All rights not expressly granted are reserved. This
|
|
135
|
+
license grants no right to use the Licensor's trade names, trademarks or
|
|
136
|
+
logos, except for reasonable reference to state accurately that a Plugin is
|
|
137
|
+
built for the Tego Platform.
|
|
138
|
+
|
|
139
|
+
6. Third-party components
|
|
140
|
+
|
|
141
|
+
Third-party open-source components the Software depends on are not part of
|
|
142
|
+
the Software and are governed by their own licenses.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of warranty
|
|
145
|
+
|
|
146
|
+
The Software is provided "as is", without warranty of any kind, express or
|
|
147
|
+
implied, including without limitation the warranties of merchantability,
|
|
148
|
+
fitness for a particular purpose and non-infringement.
|
|
149
|
+
|
|
150
|
+
8. Limitation of liability
|
|
151
|
+
|
|
152
|
+
To the maximum extent permitted by applicable law, the Licensor is not liable
|
|
153
|
+
for any indirect, incidental, special, punitive or consequential damages, or
|
|
154
|
+
for any loss of profits, data or business, arising out of or relating to the
|
|
155
|
+
Software or this license; the Licensor's total liability under this license
|
|
156
|
+
is limited to RMB 100.
|
|
157
|
+
|
|
158
|
+
9. Termination
|
|
159
|
+
|
|
160
|
+
This license terminates automatically if you breach any of its terms. On
|
|
161
|
+
termination you must stop using and delete all copies of the Software. End
|
|
162
|
+
users may continue to use, in the Tego Platform, Plugins lawfully distributed
|
|
163
|
+
to them before termination. Sections 4 to 8 and 10 survive termination.
|
|
164
|
+
|
|
165
|
+
10. Governing law and disputes
|
|
166
|
+
|
|
167
|
+
This license is governed by the laws of the People's Republic of China
|
|
168
|
+
(excluding, for this purpose, the laws of the Hong Kong and Macao Special
|
|
169
|
+
Administrative Regions and Taiwan). The parties shall first seek to resolve
|
|
170
|
+
any dispute arising from this license through friendly negotiation; failing
|
|
171
|
+
that, the dispute shall be submitted to the competent people's court at the
|
|
172
|
+
Licensor's domicile.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var q=Object.defineProperty;var n=(t,s)=>q(t,"name",{value:s,configurable:!0});var ui=require("@tego/ui"),lucideReact=require("lucide-react"),reactI18next=require("react-i18next"),reactQuery=require("@tanstack/react-query"),react=require("react"),jsxRuntime=require("react/jsx-runtime"),implications=require("@tego/plugin-sdk/access/implications"),__defProp=Object.defineProperty,__defNormalProp=n((t,s,e)=>s in t?__defProp(t,s,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[s]=e,"__defNormalProp"),__publicField=n((t,s,e)=>__defNormalProp(t,typeof s!="symbol"?s+"":s,e),"__publicField");function auditEntries(t){const s=new Set,e=[];for(const c of t)for(const d of c.items)s.has(d.id)||(s.add(d.id),e.push(d));return e}n(auditEntries,"auditEntries");var AccessApiError=class extends Error{static{n(this,"AccessApiError")}constructor(t,s,e){super(t),__publicField(this,"status",s),__publicField(this,"code",e),this.name="AccessApiError"}};function query(t,s={}){const e=new URLSearchParams;t&&(e.set("domainType",t.type),e.set("domainId",t.id));for(const[d,i]of Object.entries(s))i!==void 0&&i!==""&&e.set(d,String(i));const c=e.toString();return c?`?${c}`:""}n(query,"query");async function readError(t){const s=await t.json().catch(()=>null),e=s&&typeof s=="object"?s.error:void 0;return new AccessApiError(typeof e?.message=="string"?e.message:`HTTP ${t.status}`,t.status,typeof e?.code=="string"?e.code:null)}n(readError,"readError");function createAccessClient(t){const s=n(async(e,c,d)=>{const i=await t.request(c,{method:e,...d===void 0?{}:{body:JSON.stringify(d),headers:{"content-type":"application/json"}}});if(!i.ok)throw await readError(i);return i.status===204?void 0:await i.json()},"send");return{me:n(e=>s("GET",`/access/me${query(e)}`),"me"),catalog:n(e=>s("GET",`/access/catalog${query(e)}`),"catalog"),roles:n(async e=>(await s("GET",`/access/roles${query(e)}`)).roles,"roles"),createRole:n(async e=>(await s("POST","/access/roles",e)).role,"createRole"),updateRole:n(async(e,c)=>(await s("PUT",`/access/roles/${encodeURIComponent(e)}`,c)).role,"updateRole"),deleteRole:n(e=>s("DELETE",`/access/roles/${encodeURIComponent(e)}`),"deleteRole"),cloneRole:n(async(e,c)=>(await s("POST",`/access/roles/${encodeURIComponent(e)}/clone`,c)).role,"cloneRole"),assignments:n(async(e,c={})=>(await s("GET",`/access/assignments${query(e,c)}`)).assignments,"assignments"),createAssignment:n(async e=>(await s("POST","/access/assignments",e)).assignment,"createAssignment"),deleteAssignment:n(e=>s("DELETE",`/access/assignments/${encodeURIComponent(e)}`),"deleteAssignment"),principals:n((e,c)=>s("GET",`/access/principals${query(e,{kind:c.kind,search:c.search,ids:c.ids?.join(","),offset:c.offset,limit:c.limit})}`),"principals"),explain:n((e,c)=>s("GET",`/access/explain/${encodeURIComponent(e)}${query(c)}`),"explain"),settings:n(()=>s("GET","/access/settings"),"settings"),updateSettings:n(e=>s("PUT","/access/settings",e),"updateSettings"),audit:n((e={})=>s("GET",`/access/audit${query(null,e)}`),"audit")}}n(createAccessClient,"createAccessClient");var AccessClientContext=react.createContext(null);function useAccessClient(){const t=react.useContext(AccessClientContext);if(!t)throw new Error("@tego/plugin-access-ui: no <AccessProvider> above this.");return t}n(useAccessClient,"useAccessClient");var ACCESS_QUERY_KEY=["plugin-access"],domainKey=n(t=>t?`${t.type}:${t.id}`:"global","domainKey");function useCatalog(t,s){const e=useAccessClient();return reactQuery.useQuery({queryKey:[...ACCESS_QUERY_KEY,"catalog",domainKey(t)],queryFn:n(()=>e.catalog(t),"queryFn"),enabled:s,staleTime:1/0,retry:!1})}n(useCatalog,"useCatalog");function useRoles(t){const s=useAccessClient();return reactQuery.useQuery({queryKey:[...ACCESS_QUERY_KEY,"roles",domainKey(t)],queryFn:n(()=>s.roles(t),"queryFn")})}n(useRoles,"useRoles");function useAssignments(t){const s=useAccessClient();return reactQuery.useQuery({queryKey:[...ACCESS_QUERY_KEY,"assignments",domainKey(t)],queryFn:n(()=>s.assignments(t),"queryFn")})}n(useAssignments,"useAssignments");function usePrincipals(t,s,e){const c=useAccessClient();return reactQuery.useQuery({queryKey:[...ACCESS_QUERY_KEY,"principals",domainKey(t),s,e],queryFn:n(()=>c.principals(t,{kind:s,search:e||void 0,limit:50}),"queryFn"),placeholderData:n(d=>d,"placeholderData")})}n(usePrincipals,"usePrincipals");function useExplain(t,s){const e=useAccessClient();return reactQuery.useQuery({queryKey:[...ACCESS_QUERY_KEY,"explain",domainKey(t),s],queryFn:n(()=>e.explain(s,t),"queryFn"),enabled:s!==null})}n(useExplain,"useExplain");function useSettings(){const t=useAccessClient();return reactQuery.useQuery({queryKey:[...ACCESS_QUERY_KEY,"settings"],queryFn:n(()=>t.settings(),"queryFn")})}n(useSettings,"useSettings");var AUDIT_PAGE_SIZE=50;function useAudit(){const t=useAccessClient();return reactQuery.useInfiniteQuery({queryKey:[...ACCESS_QUERY_KEY,"audit"],queryFn:n(({pageParam:s})=>t.audit({offset:s,limit:AUDIT_PAGE_SIZE}),"queryFn"),initialPageParam:0,getNextPageParam:n((s,e)=>s.hasMore?e.length*AUDIT_PAGE_SIZE:void 0,"getNextPageParam")})}n(useAudit,"useAudit");function useDescribeError(){const{t}=reactI18next.useTranslation();return s=>s instanceof AccessApiError&&s.code?t(`tegoAccess.errors.${s.code}`,{defaultValue:s.message}):s instanceof Error?s.message:String(s)}n(useDescribeError,"useDescribeError");function useAccessMutation(t,s){const e=useAccessClient(),c=reactQuery.useQueryClient(),{t:d}=reactI18next.useTranslation(),i=useDescribeError();return reactQuery.useMutation({mutationFn:n(r=>t(e,r),"mutationFn"),onSuccess:n(async()=>{ui.toasts.success(d(s)),await c.invalidateQueries({queryKey:ACCESS_QUERY_KEY})},"onSuccess"),onError:n(r=>ui.toasts.error(d("tegoAccess.common.failed"),i(r)),"onError")})}n(useAccessMutation,"useAccessMutation");function LoadFailed({error:t,onRetry:s}){const{t:e}=reactI18next.useTranslation(),c=useDescribeError();return jsxRuntime.jsx(ui.EmptyState,{size:"sm",icon:jsxRuntime.jsx(lucideReact.CircleAlert,{}),title:e("tegoAccess.common.loadFailed"),description:c(t),action:{label:e("tegoAccess.common.retry"),onClick:s}})}n(LoadFailed,"LoadFailed");function recordName(t){for(const s of[t.after,t.before])if(s&&typeof s=="object"&&"name"in s){const{name:e}=s;if(typeof e=="string")return e}return null}n(recordName,"recordName");function AuditTab(){const{t,i18n:s}=reactI18next.useTranslation(),e=useAudit(),c=auditEntries(e.data?.pages??[]),d=new Intl.DateTimeFormat(s.language,{dateStyle:"medium",timeStyle:"short"});return e.isLoading?jsxRuntime.jsx(ui.Loading,{className:"py-10"}):!e.data&&e.error?jsxRuntime.jsx(LoadFailed,{error:e.error,onRetry:n(()=>void e.refetch(),"onRetry")}):c.length===0?jsxRuntime.jsx(ui.EmptyState,{size:"sm",icon:jsxRuntime.jsx(lucideReact.History,{}),title:t("tegoAccess.audit.emptyTitle"),description:t("tegoAccess.audit.emptyDescription")}):jsxRuntime.jsxs("div",{className:"space-y-3",children:[jsxRuntime.jsxs(ui.Table,{children:[jsxRuntime.jsx(ui.TableHeader,{children:jsxRuntime.jsxs(ui.TableRow,{children:[jsxRuntime.jsx(ui.TableHead,{children:t("tegoAccess.audit.at")}),jsxRuntime.jsx(ui.TableHead,{children:t("tegoAccess.audit.actor")}),jsxRuntime.jsx(ui.TableHead,{children:t("tegoAccess.audit.action")}),jsxRuntime.jsx(ui.TableHead,{children:t("tegoAccess.audit.target")})]})}),jsxRuntime.jsx(ui.TableBody,{children:c.map(i=>jsxRuntime.jsxs(ui.TableRow,{children:[jsxRuntime.jsx(ui.TableCell,{className:"whitespace-nowrap text-sm tabular-nums",children:d.format(new Date(i.at))}),jsxRuntime.jsx(ui.TableCell,{children:i.actorId?i.actorName??i.actorId:t("tegoAccess.audit.system")}),jsxRuntime.jsx(ui.TableCell,{children:t(`tegoAccess.audit.actions.${i.action}`)}),jsxRuntime.jsx(ui.TableCell,{className:"text-sm text-muted-foreground",children:recordName(i)??i.targetId})]},i.id))})]}),e.hasNextPage&&jsxRuntime.jsx("div",{className:"flex justify-center",children:jsxRuntime.jsx(ui.Button,{variant:"outline",size:"sm",disabled:e.isFetchingNextPage,onClick:n(()=>void e.fetchNextPage(),"onClick"),children:t("tegoAccess.audit.more")})})]})}n(AuditTab,"AuditTab");function roleName(t,s){return s.nameKey?t(s.nameKey):s.name}n(roleName,"roleName");function scopeName(t,s,e){if(e===null)return t("tegoAccess.roles.notGranted");if(e===!0)return t("tegoAccess.roles.granted");const c=s.scopes[e];return c?t(c.labelKey):e}n(scopeName,"scopeName");function permissionName(t,s,e){const c=s.permissions[e];return c?t(c.labelKey):e}n(permissionName,"permissionName");var BUILTIN_KIND_LABELS={user:"tegoAccess.principalKind.user",unit:"tegoAccess.principalKind.unit"};function principalKindName(t,s,e){const c=s[e]??BUILTIN_KIND_LABELS[e];return c?t(c):e}n(principalKindName,"principalKindName");var UNIT_ROLES=["owner","admin","member","viewer"],NO_ROLE="__none__";function DefaultsTab(){const{t}=reactI18next.useTranslation(),s=useSettings(),e=useRoles(null),[c,d]=react.useState(null),i=useAccessMutation((l,f)=>l.updateSettings({unassignedRoleId:f}),"tegoAccess.defaults.saved");if(s.isLoading||e.isLoading)return jsxRuntime.jsx(ui.Loading,{className:"py-10"});for(const l of[s,e])if(!l.data&&l.error)return jsxRuntime.jsx(LoadFailed,{error:l.error,onRetry:n(()=>void l.refetch(),"onRetry")});const r=s.data?.unassignedRoleId??NO_ROLE,x=c??r;return jsxRuntime.jsxs("div",{className:"max-w-md space-y-4",children:[jsxRuntime.jsxs("div",{className:"space-y-2",children:[jsxRuntime.jsx(ui.Label,{children:t("tegoAccess.defaults.label")}),jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:t("tegoAccess.defaults.description")}),jsxRuntime.jsxs(ui.Select,{value:x,onValueChange:d,children:[jsxRuntime.jsx(ui.SelectTrigger,{"aria-label":t("tegoAccess.defaults.label"),children:jsxRuntime.jsx(ui.SelectValue,{})}),jsxRuntime.jsxs(ui.SelectContent,{children:[jsxRuntime.jsx(ui.SelectItem,{value:NO_ROLE,children:t("tegoAccess.defaults.none")}),(e.data??[]).filter(l=>l.domain===null).map(l=>jsxRuntime.jsx(ui.SelectItem,{value:l.id,children:roleName(t,l)},l.id))]})]}),x===NO_ROLE&&jsxRuntime.jsx("p",{className:"text-sm text-warning",children:t("tegoAccess.defaults.noneHint")})]}),jsxRuntime.jsx(ui.Button,{disabled:i.isPending||x===r,onClick:n(()=>i.mutate(x===NO_ROLE?null:x,{onSuccess:n(()=>d(null),"onSuccess")}),"onClick"),children:t("tegoAccess.common.save")})]})}n(DefaultsTab,"DefaultsTab");function ExplainTab({catalog:t,domain:s,kindLabels:e}){const{t:c}=reactI18next.useTranslation(),[d,i]=react.useState(""),[r,x]=react.useState(null),l=r?.id??null,f=usePrincipals(s,"user",d),g=useExplain(s,l),A=(f.data?.items??[]).map(m=>({value:m.id,label:m.displayName})),p=n(m=>m.source==="hostRole"?c("tegoAccess.explain.viaHostRole",{role:m.hostRole}):m.source==="unassigned"?c("tegoAccess.explain.viaDefault"):m.inherited?c("tegoAccess.explain.viaParent"):m.principal&&m.principal.kind!=="user"?c("tegoAccess.explain.viaGroup",{kind:principalKindName(c,e,m.principal.kind)}):c("tegoAccess.explain.viaDirect"),"source");return jsxRuntime.jsxs("div",{className:"space-y-4",children:[jsxRuntime.jsxs("div",{className:"max-w-sm space-y-2",children:[jsxRuntime.jsx(ui.Label,{children:c("tegoAccess.explain.user")}),jsxRuntime.jsx(ui.Combobox,{options:A,value:l,selectedLabel:r?.label,onChange:n(m=>x(m===null?null:{id:m,label:A.find(b=>b.value===m)?.label??m}),"onChange"),onSearch:i,searching:f.isFetching,placeholder:c("tegoAccess.explain.pickUser"),searchPlaceholder:c("tegoAccess.common.search"),emptyText:c("tegoAccess.common.noMatches"),"aria-label":c("tegoAccess.explain.user")})]}),g.isLoading&&jsxRuntime.jsx(ui.Loading,{className:"py-10"}),!g.data&&g.error&&jsxRuntime.jsx(LoadFailed,{error:g.error,onRetry:n(()=>void g.refetch(),"onRetry")}),g.data&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsxs("section",{className:"space-y-2",children:[jsxRuntime.jsx("h4",{className:"text-sm font-medium",children:c("tegoAccess.explain.roles")}),g.data.roles.length===0?jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:c("tegoAccess.explain.noRoles")}):jsxRuntime.jsx("ul",{className:"flex flex-wrap gap-2",children:g.data.roles.map((m,b)=>jsxRuntime.jsx("li",{children:jsxRuntime.jsxs(ui.Badge,{variant:"outline",children:[roleName(c,m)," \xB7 ",p(m)]})},`${m.roleId}-${b}`))})]}),jsxRuntime.jsxs(ui.Table,{children:[jsxRuntime.jsx(ui.TableHeader,{children:jsxRuntime.jsxs(ui.TableRow,{children:[jsxRuntime.jsx(ui.TableHead,{children:c("tegoAccess.explain.permission")}),jsxRuntime.jsx(ui.TableHead,{children:c("tegoAccess.explain.result")}),jsxRuntime.jsx(ui.TableHead,{children:c("tegoAccess.explain.scope")})]})}),jsxRuntime.jsx(ui.TableBody,{children:g.data.permissions.map(m=>jsxRuntime.jsxs(ui.TableRow,{children:[jsxRuntime.jsx(ui.TableCell,{children:permissionName(c,t,m.permission)}),jsxRuntime.jsx(ui.TableCell,{children:jsxRuntime.jsx(ui.Badge,{variant:m.allowed?"success":"secondary",children:c(`tegoAccess.explain.reason.${m.reason}`)})}),jsxRuntime.jsx(ui.TableCell,{className:"text-sm text-muted-foreground",children:m.allowed?scopeName(c,t,m.scope??!0):"\u2014"})]},m.permission))})]})]})]})}n(ExplainTab,"ExplainTab");function AssignDialog({catalog:t,domain:s,roles:e,assignments:c,kindLabels:d,saving:i,onAssign:r,onClose:x}){const{t:l}=reactI18next.useTranslation(),f=t.assignment.principals,[g,A]=react.useState(f[0]),[p,m]=react.useState(""),[b,N]=react.useState(null),y=b?.id??null,[a,o]=react.useState([]),[h,T]=react.useState(!1),[j,k]=react.useState([]),R=usePrincipals(s,g,p),E=(R.data?.items??[]).map(u=>({value:u.id,label:u.displayName})),L=n(u=>{A(u),m(""),N(null),T(!1),k([])},"changeKind"),I=n((u,v)=>k(C=>v?[...C,u]:C.filter(S=>S!==u)),"toggleUnitRole"),D=new Set(c.filter(u=>u.principal.kind===g&&u.principal.id===y).map(u=>u.roleId)),w=a.filter(u=>!D.has(u)),P=n((u,v)=>o(C=>v?[...C,u]:C.filter(S=>S!==u)),"toggleRole"),K=n(()=>{!y||w.length===0||r(w.map(u=>({roleId:u,principal:{kind:g,id:y,includeDescendants:h,unitRoles:g==="unit"&&j.length>0?j:null},domain:s})))},"submit");return jsxRuntime.jsx(ui.Dialog,{open:!0,onOpenChange:n(u=>!u&&x(),"onOpenChange"),children:jsxRuntime.jsxs(ui.DialogContent,{className:"max-w-lg",children:[jsxRuntime.jsx(ui.DialogHeader,{children:jsxRuntime.jsx(ui.DialogTitle,{children:l("tegoAccess.members.assignTitle")})}),jsxRuntime.jsxs("div",{className:"space-y-4",children:[f.length>1&&jsxRuntime.jsxs("div",{className:"space-y-2",children:[jsxRuntime.jsx(ui.Label,{children:l("tegoAccess.members.principalKind")}),jsxRuntime.jsxs(ui.Select,{value:g,onValueChange:L,children:[jsxRuntime.jsx(ui.SelectTrigger,{children:jsxRuntime.jsx(ui.SelectValue,{})}),jsxRuntime.jsx(ui.SelectContent,{children:f.map(u=>jsxRuntime.jsx(ui.SelectItem,{value:u,children:principalKindName(l,d,u)},u))})]})]}),jsxRuntime.jsxs("div",{className:"space-y-2",children:[jsxRuntime.jsx(ui.Label,{children:principalKindName(l,d,g)}),jsxRuntime.jsx(ui.Combobox,{options:E,value:y,selectedLabel:b?.label,onChange:n(u=>N(u===null?null:{id:u,label:E.find(v=>v.value===u)?.label??u}),"onChange"),onSearch:m,searching:R.isFetching,placeholder:l("tegoAccess.members.pickPrincipal"),searchPlaceholder:l("tegoAccess.common.search"),emptyText:l("tegoAccess.common.noMatches"),"aria-label":principalKindName(l,d,g)})]}),g!=="user"&&jsxRuntime.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[jsxRuntime.jsx(ui.Checkbox,{checked:h,onCheckedChange:n(u=>T(u===!0),"onCheckedChange")}),l("tegoAccess.members.includeDescendants")]}),g==="unit"&&jsxRuntime.jsxs("div",{className:"space-y-2",children:[jsxRuntime.jsx(ui.Label,{children:l("tegoAccess.members.unitRoles")}),jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:l("tegoAccess.members.unitRolesHint")}),jsxRuntime.jsx("div",{className:"flex flex-wrap gap-4",children:UNIT_ROLES.map(u=>jsxRuntime.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[jsxRuntime.jsx(ui.Checkbox,{checked:j.includes(u),onCheckedChange:n(v=>I(u,v===!0),"onCheckedChange")}),l(`tegoAccess.unitRole.${u}`)]},u))})]}),jsxRuntime.jsxs("div",{className:"space-y-2",children:[jsxRuntime.jsx(ui.Label,{children:l("tegoAccess.members.role")}),jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:l("tegoAccess.members.rolesHint")}),jsxRuntime.jsx("div",{role:"group","aria-label":l("tegoAccess.members.role"),className:"max-h-60 space-y-2 overflow-y-auto rounded-md border p-3",children:e.map(u=>{const v=D.has(u.id);return jsxRuntime.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[jsxRuntime.jsx(ui.Checkbox,{checked:v||a.includes(u.id),disabled:v,onCheckedChange:n(C=>P(u.id,C===!0),"onCheckedChange")}),jsxRuntime.jsx("span",{className:v?"text-muted-foreground":void 0,children:roleName(l,u)}),v&&jsxRuntime.jsx(ui.Badge,{variant:"secondary",children:l("tegoAccess.members.alreadyAssigned")})]},u.id)})})]})]}),jsxRuntime.jsxs(ui.DialogFooter,{children:[jsxRuntime.jsx(ui.Button,{variant:"outline",onClick:x,children:l("tegoAccess.common.cancel")}),jsxRuntime.jsx(ui.Button,{disabled:i||!y||w.length===0,onClick:K,children:l("tegoAccess.members.assign")})]})]})})}n(AssignDialog,"AssignDialog");function MembersTab({catalog:t,domain:s,kindLabels:e}){const{t:c}=reactI18next.useTranslation(),d=reactQuery.useQueryClient(),i=useAssignments(s),r=useRoles(s),[x,l]=react.useState(null),{confirm:f,ConfirmDialog:g}=ui.useConfirm(),A=new Map((r.data??[]).map(a=>[a.id,a])),p=useAccessMutation(async(a,o)=>{for(const h of o)await a.createAssignment(h)},"tegoAccess.members.assigned"),m=useAccessMutation((a,o)=>a.deleteAssignment(o),"tegoAccess.members.removed"),b=n(a=>a.principalName??a.principal.id,"principalLabel"),N=n(async a=>{const o=A.get(a.roleId);await f({title:c("tegoAccess.members.removeTitle"),description:c("tegoAccess.members.removeDescription",{principal:b(a),role:o?roleName(c,o):a.roleId}),confirmText:c("tegoAccess.members.remove"),cancelText:c("tegoAccess.common.cancel"),variant:"destructive"})&&m.mutate(a.id)},"askRemove");if(i.isLoading||r.isLoading)return jsxRuntime.jsx(ui.Loading,{className:"py-10"});for(const a of[i,r])if(!a.data&&a.error)return jsxRuntime.jsx(LoadFailed,{error:a.error,onRetry:n(()=>void a.refetch(),"onRetry")});const y=i.data??[];return jsxRuntime.jsxs("div",{className:"space-y-3",children:[jsxRuntime.jsx("div",{className:"flex justify-end",children:jsxRuntime.jsxs(ui.Button,{size:"sm",onClick:n(()=>l({}),"onClick"),children:[jsxRuntime.jsx(lucideReact.Plus,{className:"mr-1 h-4 w-4"}),c("tegoAccess.members.assign")]})}),y.length===0?jsxRuntime.jsx(ui.EmptyState,{size:"sm",icon:jsxRuntime.jsx(lucideReact.Users,{}),title:c("tegoAccess.members.emptyTitle"),description:c("tegoAccess.members.emptyDescription")}):jsxRuntime.jsxs(ui.Table,{children:[jsxRuntime.jsx(ui.TableHeader,{children:jsxRuntime.jsxs(ui.TableRow,{children:[jsxRuntime.jsx(ui.TableHead,{children:c("tegoAccess.members.principal")}),jsxRuntime.jsx(ui.TableHead,{children:c("tegoAccess.members.role")}),jsxRuntime.jsx(ui.TableHead,{children:c("tegoAccess.members.coverage")}),jsxRuntime.jsx(ui.TableHead,{className:"w-12"})]})}),jsxRuntime.jsx(ui.TableBody,{children:y.map(a=>{const o=A.get(a.roleId),{principal:h}=a;return jsxRuntime.jsxs(ui.TableRow,{children:[jsxRuntime.jsx(ui.TableCell,{children:jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsx("span",{className:"font-medium",children:b(a)}),jsxRuntime.jsx(ui.Badge,{variant:"outline",children:principalKindName(c,e,h.kind)})]})}),jsxRuntime.jsx(ui.TableCell,{children:o?roleName(c,o):a.roleId}),jsxRuntime.jsx(ui.TableCell,{className:"text-sm text-muted-foreground",children:h.kind==="user"?"\u2014":[h.includeDescendants?c("tegoAccess.members.withDescendants"):c("tegoAccess.members.directOnly"),h.unitRoles?h.unitRoles.map(T=>c(`tegoAccess.unitRole.${T}`)).join(c("tegoAccess.common.listSeparator")):null].filter(Boolean).join(" \xB7 ")}),jsxRuntime.jsx(ui.TableCell,{children:jsxRuntime.jsx(ui.Button,{size:"icon",variant:"ghost","aria-label":c("tegoAccess.members.remove"),onClick:n(()=>void N(a),"onClick"),children:jsxRuntime.jsx(lucideReact.Trash2,{className:"h-4 w-4"})})})]},a.id)})})]}),x&&jsxRuntime.jsx(AssignDialog,{catalog:t,domain:s,roles:r.data??[],assignments:y,kindLabels:e,saving:p.isPending,onAssign:n(a=>p.mutate(a,{onSuccess:n(()=>l(o=>o===x?null:o),"onSuccess"),onError:n(()=>void d.invalidateQueries({queryKey:ACCESS_QUERY_KEY}),"onError")}),"onAssign"),onClose:n(()=>l(null),"onClose")}),jsxRuntime.jsx(g,{})]})}n(MembersTab,"MembersTab");function permissionGroups(t,s){return t.groups.map(e=>({...e,permissions:Object.values(t.permissions).filter(c=>c.group===e.key&&(!c.deprecated||c.key in s))})).filter(e=>e.permissions.length>0)}n(permissionGroups,"permissionGroups");function impliedGrants(t,s){const e={};for(const[c,d]of Object.entries(implications.expandImplications(t.permissions,s)))s[c]!==d&&(e[c]=d);return e}n(impliedGrants,"impliedGrants");function setGrant(t,s,e){const c={...t};return e===null?delete c[s]:c[s]=e,c}n(setGrant,"setGrant");var NOT_GRANTED="__not_granted__";function RoleEditorDialog({catalog:t,role:s,lock:e,saving:c,onSave:d,onClose:i}){const{t:r}=reactI18next.useTranslation(),x=e!==null,[l,f]=react.useState(s?roleName(r,s):""),[g,A]=react.useState(s?.descriptionKey?r(s.descriptionKey):s?.description??""),[p,m]=react.useState(s?.grants??{}),b=permissionGroups(t,p),N=impliedGrants(t,p),y=r(s?x?"tegoAccess.roles.viewTitle":"tegoAccess.roles.editTitle":"tegoAccess.roles.createTitle");return jsxRuntime.jsx(ui.Dialog,{open:!0,onOpenChange:n(a=>!a&&i(),"onOpenChange"),children:jsxRuntime.jsxs(ui.DialogContent,{className:"flex max-h-[85vh] max-w-2xl flex-col",children:[jsxRuntime.jsxs(ui.DialogHeader,{children:[jsxRuntime.jsx(ui.DialogTitle,{children:y}),e&&jsxRuntime.jsx(ui.DialogDescription,{children:r(e==="builtin"?"tegoAccess.roles.builtinHint":"tegoAccess.roles.globalHint")})]}),jsxRuntime.jsxs("div",{className:"-mx-6 flex-1 space-y-4 overflow-y-auto px-6",children:[jsxRuntime.jsxs("div",{className:"space-y-2",children:[jsxRuntime.jsx(ui.Label,{htmlFor:"tego-access-role-name",children:r("tegoAccess.roles.name")}),jsxRuntime.jsx(ui.Input,{id:"tego-access-role-name",value:l,maxLength:80,disabled:x,onChange:n(a=>f(a.target.value),"onChange")})]}),jsxRuntime.jsxs("div",{className:"space-y-2",children:[jsxRuntime.jsx(ui.Label,{htmlFor:"tego-access-role-description",children:r("tegoAccess.roles.description")}),jsxRuntime.jsx(ui.Textarea,{id:"tego-access-role-description",value:g,maxLength:500,rows:2,disabled:x,onChange:n(a=>A(a.target.value),"onChange")})]}),s&&s.staleGrants.length>0&&jsxRuntime.jsx("p",{className:"text-sm text-warning",children:r("tegoAccess.roles.staleGrants",{permissions:s.staleGrants.join(", ")})}),jsxRuntime.jsxs("div",{className:"space-y-4",children:[jsxRuntime.jsx(ui.Label,{children:r("tegoAccess.roles.permissions")}),b.map(a=>jsxRuntime.jsxs("section",{className:"space-y-2",children:[jsxRuntime.jsx("h4",{className:"text-sm font-medium text-muted-foreground",children:r(a.labelKey)}),jsxRuntime.jsx("ul",{className:"divide-y divide-border rounded-md border border-border",children:a.permissions.map(o=>{const h=p[o.key]??null,T=N[o.key];return jsxRuntime.jsxs("li",{className:"flex items-center justify-between gap-4 px-3 py-2",children:[jsxRuntime.jsxs("div",{className:"min-w-0",children:[jsxRuntime.jsx("p",{className:"text-sm",children:r(o.labelKey)}),o.descriptionKey&&jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:r(o.descriptionKey)}),T!==void 0&&jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:T===!0?r("tegoAccess.roles.implied"):r("tegoAccess.roles.impliedScope",{scope:scopeName(r,t,T)})})]}),o.scopes?jsxRuntime.jsxs(ui.Select,{value:typeof h=="string"?h:NOT_GRANTED,disabled:x,onValueChange:n(j=>m(setGrant(p,o.key,j===NOT_GRANTED?null:j)),"onValueChange"),children:[jsxRuntime.jsx(ui.SelectTrigger,{className:"w-40 shrink-0","aria-label":r(o.labelKey),children:jsxRuntime.jsx(ui.SelectValue,{})}),jsxRuntime.jsxs(ui.SelectContent,{children:[jsxRuntime.jsx(ui.SelectItem,{value:NOT_GRANTED,children:r("tegoAccess.roles.notGranted")}),o.scopes.map(j=>jsxRuntime.jsx(ui.SelectItem,{value:j,children:scopeName(r,t,j)},j))]})]}):jsxRuntime.jsx(ui.Checkbox,{checked:h===!0,disabled:x,"aria-label":r(o.labelKey),onCheckedChange:n(j=>m(setGrant(p,o.key,j===!0?!0:null)),"onCheckedChange")})]},o.key)})})]},a.key))]})]}),jsxRuntime.jsxs(ui.DialogFooter,{children:[jsxRuntime.jsx(ui.Button,{variant:"outline",onClick:i,children:r(x?"tegoAccess.common.close":"tegoAccess.common.cancel")}),!x&&jsxRuntime.jsx(ui.Button,{disabled:c||l.trim()==="",onClick:n(()=>d({name:l.trim(),description:g.trim(),grants:p}),"onClick"),children:r("tegoAccess.common.save")})]})]})})}n(RoleEditorDialog,"RoleEditorDialog");function roleLock(t,s){return t.builtin?"builtin":s&&t.domain===null?"global":null}n(roleLock,"roleLock");function RolesTab({catalog:t,domain:s}){const{t:e}=reactI18next.useTranslation(),c=useRoles(s),[d,i]=react.useState(null),{confirm:r,ConfirmDialog:x}=ui.useConfirm(),{prompt:l,PromptDialog:f}=ui.usePrompt(),g=useAccessMutation((a,o)=>a.createRole({...o,domain:s}),"tegoAccess.roles.created"),A=useAccessMutation((a,o)=>a.updateRole(o.id,o.draft),"tegoAccess.roles.updated"),p=useAccessMutation((a,o)=>a.deleteRole(o),"tegoAccess.roles.deleted"),m=useAccessMutation((a,o)=>a.cloneRole(o.id,{name:o.name,domain:s}),"tegoAccess.roles.cloned"),b=n(a=>{const o=d,h=o?.role,T={onSuccess:n(()=>i(j=>j===o?null:j),"onSuccess")};h?A.mutate({id:h.id,draft:a},T):g.mutate(a,T)},"save"),N=n(async a=>{const o=await l({title:e("tegoAccess.roles.cloneTitle"),label:e("tegoAccess.roles.name"),defaultValue:e("tegoAccess.roles.cloneName",{name:roleName(e,a)}),confirmText:e("tegoAccess.roles.clone"),cancelText:e("tegoAccess.common.cancel")});o&&m.mutate({id:a.id,name:o})},"askClone"),y=n(async a=>{await r({title:e("tegoAccess.roles.deleteTitle",{name:roleName(e,a)}),description:e("tegoAccess.roles.deleteDescription"),confirmText:e("tegoAccess.common.delete"),cancelText:e("tegoAccess.common.cancel"),variant:"destructive"})&&p.mutate(a.id)},"askDelete");return c.isLoading?jsxRuntime.jsx(ui.Loading,{className:"py-10"}):!c.data&&c.error?jsxRuntime.jsx(LoadFailed,{error:c.error,onRetry:n(()=>void c.refetch(),"onRetry")}):jsxRuntime.jsxs("div",{className:"space-y-3",children:[jsxRuntime.jsx("div",{className:"flex justify-end",children:jsxRuntime.jsxs(ui.Button,{size:"sm",onClick:n(()=>i({role:null}),"onClick"),children:[jsxRuntime.jsx(lucideReact.Plus,{className:"mr-1 h-4 w-4"}),e("tegoAccess.roles.create")]})}),jsxRuntime.jsxs(ui.Table,{children:[jsxRuntime.jsx(ui.TableHeader,{children:jsxRuntime.jsxs(ui.TableRow,{children:[jsxRuntime.jsx(ui.TableHead,{children:e("tegoAccess.roles.name")}),jsxRuntime.jsx(ui.TableHead,{children:e("tegoAccess.roles.type")}),jsxRuntime.jsx(ui.TableHead,{className:"text-right",children:e("tegoAccess.roles.assignments")}),jsxRuntime.jsx(ui.TableHead,{className:"w-32"})]})}),jsxRuntime.jsx(ui.TableBody,{children:(c.data??[]).map(a=>{const o=roleLock(a,s)!==null;return jsxRuntime.jsxs(ui.TableRow,{children:[jsxRuntime.jsxs(ui.TableCell,{children:[jsxRuntime.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[jsxRuntime.jsx("span",{className:"font-medium",children:roleName(e,a)}),a.isDefault&&jsxRuntime.jsx(ui.Badge,{variant:"secondary",children:e("tegoAccess.roles.default")}),a.staleGrants.length>0&&jsxRuntime.jsx(ui.Badge,{variant:"warning",children:e("tegoAccess.roles.stale")})]}),a.descriptionKey?jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:e(a.descriptionKey)}):a.description&&jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:a.description})]}),jsxRuntime.jsx(ui.TableCell,{children:jsxRuntime.jsx(ui.Badge,{variant:"outline",children:a.builtin?e("tegoAccess.roles.builtin"):a.domain?e("tegoAccess.roles.domainRole"):e("tegoAccess.roles.custom")})}),jsxRuntime.jsx(ui.TableCell,{className:"text-right tabular-nums",children:a.assignmentCount}),jsxRuntime.jsx(ui.TableCell,{children:jsxRuntime.jsxs("div",{className:"flex justify-end gap-1",children:[jsxRuntime.jsx(ui.Button,{size:"icon",variant:"ghost","aria-label":e(o?"tegoAccess.roles.view":"tegoAccess.roles.edit"),onClick:n(()=>i({role:a}),"onClick"),children:o?jsxRuntime.jsx(lucideReact.Eye,{className:"h-4 w-4"}):jsxRuntime.jsx(lucideReact.Pencil,{className:"h-4 w-4"})}),jsxRuntime.jsx(ui.Button,{size:"icon",variant:"ghost","aria-label":e("tegoAccess.roles.clone"),onClick:n(()=>void N(a),"onClick"),children:jsxRuntime.jsx(lucideReact.Copy,{className:"h-4 w-4"})}),!o&&jsxRuntime.jsx(ui.Button,{size:"icon",variant:"ghost","aria-label":e("tegoAccess.common.delete"),onClick:n(()=>void y(a),"onClick"),children:jsxRuntime.jsx(lucideReact.Trash2,{className:"h-4 w-4"})})]})})]},a.id)})})]}),d&&jsxRuntime.jsx(RoleEditorDialog,{catalog:t,role:d.role,lock:d.role?roleLock(d.role,s):null,saving:g.isPending||A.isPending,onSave:b,onClose:n(()=>i(null),"onClose")}),jsxRuntime.jsx(x,{}),jsxRuntime.jsx(f,{})]})}n(RolesTab,"RolesTab");function accessView(t){return{can:n(s=>t?.permissions[s]!==void 0,"can"),scope:n(s=>t?.permissions[s]??null,"scope"),sees:n(s=>t?t.menus[s]??!0:!1,"sees")}}n(accessView,"accessView");function filterNav(t,s){return t.filter(e=>s.sees(e.key))}n(filterNav,"filterNav");function accessMeKey(t){return t?[...ACCESS_QUERY_KEY,"me",t.type,t.id]:[...ACCESS_QUERY_KEY,"me"]}n(accessMeKey,"accessMeKey");function useAccess(t){const s=useAccessClient(),e=reactQuery.useQuery({queryKey:accessMeKey(t),queryFn:n(()=>s.me(t),"queryFn"),staleTime:6e4}),{data:c,isLoading:d,error:i,refetch:r}=e;return react.useMemo(()=>({...accessView(c),snapshot:c,loading:d,error:i,refetch:n(()=>void r(),"refetch")}),[c,d,i,r])}n(useAccess,"useAccess");var NO_LABELS={};function AccessSettings({domain:t=null,principalKindLabels:s=NO_LABELS}){const{t:e}=reactI18next.useTranslation(),c=useAccess(t),d=useAccess(null),i=c.can("access.manage"),r=!t&&d.can("access.audit"),x=useCatalog(t,i);if(c.loading||d.loading||i&&x.isLoading)return jsxRuntime.jsx(ui.Loading,{className:"py-10"});for(const l of[c,d])if(!l.snapshot&&l.error)return jsxRuntime.jsx(LoadFailed,{error:l.error,onRetry:l.refetch});return!i&&!r?jsxRuntime.jsx(ui.EmptyState,{size:"sm",icon:jsxRuntime.jsx(lucideReact.ShieldOff,{}),title:e("tegoAccess.denied.title"),description:e("tegoAccess.denied.description")}):i&&!x.data&&x.error?jsxRuntime.jsx(LoadFailed,{error:x.error,onRetry:n(()=>void x.refetch(),"onRetry")}):jsxRuntime.jsxs(ui.Tabs,{defaultValue:i?"roles":"audit",children:[jsxRuntime.jsxs(ui.TabsList,{children:[i&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(ui.TabsTrigger,{value:"roles",children:e("tegoAccess.tabs.roles")}),jsxRuntime.jsx(ui.TabsTrigger,{value:"members",children:e("tegoAccess.tabs.members")}),jsxRuntime.jsx(ui.TabsTrigger,{value:"explain",children:e("tegoAccess.tabs.explain")}),!t&&jsxRuntime.jsx(ui.TabsTrigger,{value:"defaults",children:e("tegoAccess.tabs.defaults")})]}),r&&jsxRuntime.jsx(ui.TabsTrigger,{value:"audit",children:e("tegoAccess.tabs.audit")})]}),i&&x.data&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(ui.TabsContent,{value:"roles",children:jsxRuntime.jsx(RolesTab,{catalog:x.data,domain:t})}),jsxRuntime.jsx(ui.TabsContent,{value:"members",children:jsxRuntime.jsx(MembersTab,{catalog:x.data,domain:t,kindLabels:s})}),jsxRuntime.jsx(ui.TabsContent,{value:"explain",children:jsxRuntime.jsx(ExplainTab,{catalog:x.data,domain:t,kindLabels:s})}),!t&&jsxRuntime.jsx(ui.TabsContent,{value:"defaults",children:jsxRuntime.jsx(DefaultsTab,{})})]}),r&&jsxRuntime.jsx(ui.TabsContent,{value:"audit",children:jsxRuntime.jsx(AuditTab,{})})]})}n(AccessSettings,"AccessSettings");function Can({permission:t,domain:s,fallback:e=null,children:c}){return useAccess(s).can(t)?c:e}n(Can,"Can");function AccessProvider({api:t,children:s}){const e=react.useMemo(()=>createAccessClient(t),[t]);return jsxRuntime.jsx(AccessClientContext,{value:e,children:s})}n(AccessProvider,"AccessProvider"),exports.AccessApiError=AccessApiError,exports.AccessProvider=AccessProvider,exports.AccessSettings=AccessSettings,exports.Can=Can,exports.accessMeKey=accessMeKey,exports.accessView=accessView,exports.createAccessClient=createAccessClient,exports.filterNav=filterNav,exports.useAccess=useAccess,exports.useAccessClient=useAccessClient;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { AccessDomain, AccessSnapshot, AccessCatalog, RoleView, Grants, AssignmentView, PrincipalEntry, ExplainView, SettingsView, AuditEntryView } from '@tego/plugin-sdk/access';
|
|
4
|
+
export { AccessDomain, AccessSnapshot } from '@tego/plugin-sdk/access';
|
|
5
|
+
import { PluginApiClient } from '@tego/plugin-sdk/frontend';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The `/access` API of the plugin's own backend.
|
|
9
|
+
*
|
|
10
|
+
* The routes and their `{ error: { code, message } }` refusals are defined by
|
|
11
|
+
* `@tego/plugin-sdk/access` (Hono) and `tego_plugin_sdk.access` (FastAPI)
|
|
12
|
+
* alike, so one client serves every plugin. Everything goes through
|
|
13
|
+
* `ctx.api`, which adds the plugin's namespace and the session.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** A refusal from the access API, with its code kept for translation. */
|
|
17
|
+
declare class AccessApiError extends Error {
|
|
18
|
+
readonly status: number;
|
|
19
|
+
readonly code: string | null;
|
|
20
|
+
constructor(message: string, status: number, code: string | null);
|
|
21
|
+
}
|
|
22
|
+
interface Page<T> {
|
|
23
|
+
items: T[];
|
|
24
|
+
hasMore: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface NewRole {
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
grants: Grants;
|
|
30
|
+
domain: AccessDomain | null;
|
|
31
|
+
}
|
|
32
|
+
interface RoleChanges {
|
|
33
|
+
name?: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
grants?: Grants;
|
|
36
|
+
}
|
|
37
|
+
interface NewAssignment {
|
|
38
|
+
roleId: string;
|
|
39
|
+
principal: {
|
|
40
|
+
kind: string;
|
|
41
|
+
id: string;
|
|
42
|
+
includeDescendants?: boolean;
|
|
43
|
+
unitRoles?: string[] | null;
|
|
44
|
+
};
|
|
45
|
+
domain: AccessDomain | null;
|
|
46
|
+
}
|
|
47
|
+
interface PrincipalSearch {
|
|
48
|
+
kind: string;
|
|
49
|
+
search?: string | undefined;
|
|
50
|
+
ids?: string[] | undefined;
|
|
51
|
+
offset?: number | undefined;
|
|
52
|
+
limit?: number | undefined;
|
|
53
|
+
}
|
|
54
|
+
declare function createAccessClient(api: PluginApiClient): {
|
|
55
|
+
me: (domain?: AccessDomain | null) => Promise<AccessSnapshot>;
|
|
56
|
+
catalog: (domain?: AccessDomain | null) => Promise<AccessCatalog>;
|
|
57
|
+
roles: (domain?: AccessDomain | null) => Promise<RoleView[]>;
|
|
58
|
+
createRole: (input: NewRole) => Promise<RoleView>;
|
|
59
|
+
updateRole: (id: string, changes: RoleChanges) => Promise<RoleView>;
|
|
60
|
+
deleteRole: (id: string) => Promise<void>;
|
|
61
|
+
cloneRole: (id: string, input: {
|
|
62
|
+
name: string;
|
|
63
|
+
domain?: AccessDomain | null;
|
|
64
|
+
}) => Promise<RoleView>;
|
|
65
|
+
assignments: (domain: AccessDomain | null, filter?: {
|
|
66
|
+
roleId?: string;
|
|
67
|
+
principalKind?: string;
|
|
68
|
+
principalId?: string;
|
|
69
|
+
}) => Promise<AssignmentView[]>;
|
|
70
|
+
createAssignment: (input: NewAssignment) => Promise<AssignmentView>;
|
|
71
|
+
deleteAssignment: (id: string) => Promise<void>;
|
|
72
|
+
principals: (domain: AccessDomain | null, search: PrincipalSearch) => Promise<Page<PrincipalEntry>>;
|
|
73
|
+
explain: (userId: string, domain: AccessDomain | null) => Promise<ExplainView>;
|
|
74
|
+
settings: () => Promise<SettingsView>;
|
|
75
|
+
updateSettings: (input: {
|
|
76
|
+
unassignedRoleId: string | null;
|
|
77
|
+
}) => Promise<SettingsView>;
|
|
78
|
+
audit: (page?: {
|
|
79
|
+
offset?: number;
|
|
80
|
+
limit?: number;
|
|
81
|
+
}) => Promise<Page<AuditEntryView>>;
|
|
82
|
+
};
|
|
83
|
+
type AccessClient = ReturnType<typeof createAccessClient>;
|
|
84
|
+
|
|
85
|
+
/** Labels for principal kinds, by translation key. */
|
|
86
|
+
type PrincipalKindLabels = Record<string, string>;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Roles, assignments, explanations, the default role and the audit log of
|
|
90
|
+
* this plugin.
|
|
91
|
+
*
|
|
92
|
+
* With `domain`, it manages that domain: its own roles and its assignments.
|
|
93
|
+
* The default role and the audit log are tenant-wide, so they appear only
|
|
94
|
+
* without one.
|
|
95
|
+
*/
|
|
96
|
+
declare function AccessSettings({ domain, principalKindLabels, }: {
|
|
97
|
+
domain?: AccessDomain | null;
|
|
98
|
+
/** Translation keys for principal kinds the plugin adds (`department`). */
|
|
99
|
+
principalKindLabels?: PrincipalKindLabels;
|
|
100
|
+
}): react.JSX.Element;
|
|
101
|
+
|
|
102
|
+
/** Renders `children` when the permission is held, `fallback` otherwise. */
|
|
103
|
+
declare function Can({ permission, domain, fallback, children, }: {
|
|
104
|
+
permission: string;
|
|
105
|
+
domain?: AccessDomain | null;
|
|
106
|
+
fallback?: ReactNode;
|
|
107
|
+
children: ReactNode;
|
|
108
|
+
}): ReactNode;
|
|
109
|
+
|
|
110
|
+
declare function useAccessClient(): AccessClient;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Put once under the plugin's own `QueryClientProvider`. Every hook and screen
|
|
114
|
+
* in this package reads the client from here.
|
|
115
|
+
*/
|
|
116
|
+
declare function AccessProvider({ api, children, }: {
|
|
117
|
+
api: PluginApiClient;
|
|
118
|
+
children: ReactNode;
|
|
119
|
+
}): react.JSX.Element;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Reading a `/access/me` snapshot.
|
|
123
|
+
*
|
|
124
|
+
* Pure, so the rules a screen gates on are tested apart from React. Missing
|
|
125
|
+
* data never opens anything: until the snapshot arrives every check is false.
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
interface AccessView {
|
|
129
|
+
/** The permission is held, at any scope. */
|
|
130
|
+
can(permission: string): boolean;
|
|
131
|
+
/** The scope held, `null` when not held, `true` for an unscoped grant. */
|
|
132
|
+
scope(permission: string): string | true | null;
|
|
133
|
+
/**
|
|
134
|
+
* Whether a page is offered. Pages the catalog does not gate are offered to
|
|
135
|
+
* everyone who can open the plugin at all.
|
|
136
|
+
*/
|
|
137
|
+
sees(navKey: string): boolean;
|
|
138
|
+
}
|
|
139
|
+
declare function accessView(snapshot: AccessSnapshot | undefined): AccessView;
|
|
140
|
+
/** The entries a person is offered, in their declared order. */
|
|
141
|
+
declare function filterNav<T extends {
|
|
142
|
+
key: string;
|
|
143
|
+
}>(entries: readonly T[], view: Pick<AccessView, 'sees'>): T[];
|
|
144
|
+
|
|
145
|
+
interface Access extends AccessView {
|
|
146
|
+
snapshot: AccessSnapshot | undefined;
|
|
147
|
+
loading: boolean;
|
|
148
|
+
/** Why the snapshot could not be read; every check is false meanwhile. */
|
|
149
|
+
error: unknown;
|
|
150
|
+
refetch: () => void;
|
|
151
|
+
}
|
|
152
|
+
declare function accessMeKey(domain?: AccessDomain | null): readonly ["plugin-access", "me", string, string] | readonly ["plugin-access", "me"];
|
|
153
|
+
/**
|
|
154
|
+
* What the signed-in person may do in this plugin, asked once per domain and
|
|
155
|
+
* shared by key. For drawing the UI only — the backend decides.
|
|
156
|
+
*/
|
|
157
|
+
declare function useAccess(domain?: AccessDomain | null): Access;
|
|
158
|
+
|
|
159
|
+
export { type Access, AccessApiError, type AccessClient, AccessProvider, AccessSettings, type AccessView, Can, type PrincipalKindLabels, accessMeKey, accessView, createAccessClient, filterNav, useAccess, useAccessClient };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { AccessDomain, AccessSnapshot, AccessCatalog, RoleView, Grants, AssignmentView, PrincipalEntry, ExplainView, SettingsView, AuditEntryView } from '@tego/plugin-sdk/access';
|
|
4
|
+
export { AccessDomain, AccessSnapshot } from '@tego/plugin-sdk/access';
|
|
5
|
+
import { PluginApiClient } from '@tego/plugin-sdk/frontend';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The `/access` API of the plugin's own backend.
|
|
9
|
+
*
|
|
10
|
+
* The routes and their `{ error: { code, message } }` refusals are defined by
|
|
11
|
+
* `@tego/plugin-sdk/access` (Hono) and `tego_plugin_sdk.access` (FastAPI)
|
|
12
|
+
* alike, so one client serves every plugin. Everything goes through
|
|
13
|
+
* `ctx.api`, which adds the plugin's namespace and the session.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/** A refusal from the access API, with its code kept for translation. */
|
|
17
|
+
declare class AccessApiError extends Error {
|
|
18
|
+
readonly status: number;
|
|
19
|
+
readonly code: string | null;
|
|
20
|
+
constructor(message: string, status: number, code: string | null);
|
|
21
|
+
}
|
|
22
|
+
interface Page<T> {
|
|
23
|
+
items: T[];
|
|
24
|
+
hasMore: boolean;
|
|
25
|
+
}
|
|
26
|
+
interface NewRole {
|
|
27
|
+
name: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
grants: Grants;
|
|
30
|
+
domain: AccessDomain | null;
|
|
31
|
+
}
|
|
32
|
+
interface RoleChanges {
|
|
33
|
+
name?: string;
|
|
34
|
+
description?: string;
|
|
35
|
+
grants?: Grants;
|
|
36
|
+
}
|
|
37
|
+
interface NewAssignment {
|
|
38
|
+
roleId: string;
|
|
39
|
+
principal: {
|
|
40
|
+
kind: string;
|
|
41
|
+
id: string;
|
|
42
|
+
includeDescendants?: boolean;
|
|
43
|
+
unitRoles?: string[] | null;
|
|
44
|
+
};
|
|
45
|
+
domain: AccessDomain | null;
|
|
46
|
+
}
|
|
47
|
+
interface PrincipalSearch {
|
|
48
|
+
kind: string;
|
|
49
|
+
search?: string | undefined;
|
|
50
|
+
ids?: string[] | undefined;
|
|
51
|
+
offset?: number | undefined;
|
|
52
|
+
limit?: number | undefined;
|
|
53
|
+
}
|
|
54
|
+
declare function createAccessClient(api: PluginApiClient): {
|
|
55
|
+
me: (domain?: AccessDomain | null) => Promise<AccessSnapshot>;
|
|
56
|
+
catalog: (domain?: AccessDomain | null) => Promise<AccessCatalog>;
|
|
57
|
+
roles: (domain?: AccessDomain | null) => Promise<RoleView[]>;
|
|
58
|
+
createRole: (input: NewRole) => Promise<RoleView>;
|
|
59
|
+
updateRole: (id: string, changes: RoleChanges) => Promise<RoleView>;
|
|
60
|
+
deleteRole: (id: string) => Promise<void>;
|
|
61
|
+
cloneRole: (id: string, input: {
|
|
62
|
+
name: string;
|
|
63
|
+
domain?: AccessDomain | null;
|
|
64
|
+
}) => Promise<RoleView>;
|
|
65
|
+
assignments: (domain: AccessDomain | null, filter?: {
|
|
66
|
+
roleId?: string;
|
|
67
|
+
principalKind?: string;
|
|
68
|
+
principalId?: string;
|
|
69
|
+
}) => Promise<AssignmentView[]>;
|
|
70
|
+
createAssignment: (input: NewAssignment) => Promise<AssignmentView>;
|
|
71
|
+
deleteAssignment: (id: string) => Promise<void>;
|
|
72
|
+
principals: (domain: AccessDomain | null, search: PrincipalSearch) => Promise<Page<PrincipalEntry>>;
|
|
73
|
+
explain: (userId: string, domain: AccessDomain | null) => Promise<ExplainView>;
|
|
74
|
+
settings: () => Promise<SettingsView>;
|
|
75
|
+
updateSettings: (input: {
|
|
76
|
+
unassignedRoleId: string | null;
|
|
77
|
+
}) => Promise<SettingsView>;
|
|
78
|
+
audit: (page?: {
|
|
79
|
+
offset?: number;
|
|
80
|
+
limit?: number;
|
|
81
|
+
}) => Promise<Page<AuditEntryView>>;
|
|
82
|
+
};
|
|
83
|
+
type AccessClient = ReturnType<typeof createAccessClient>;
|
|
84
|
+
|
|
85
|
+
/** Labels for principal kinds, by translation key. */
|
|
86
|
+
type PrincipalKindLabels = Record<string, string>;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Roles, assignments, explanations, the default role and the audit log of
|
|
90
|
+
* this plugin.
|
|
91
|
+
*
|
|
92
|
+
* With `domain`, it manages that domain: its own roles and its assignments.
|
|
93
|
+
* The default role and the audit log are tenant-wide, so they appear only
|
|
94
|
+
* without one.
|
|
95
|
+
*/
|
|
96
|
+
declare function AccessSettings({ domain, principalKindLabels, }: {
|
|
97
|
+
domain?: AccessDomain | null;
|
|
98
|
+
/** Translation keys for principal kinds the plugin adds (`department`). */
|
|
99
|
+
principalKindLabels?: PrincipalKindLabels;
|
|
100
|
+
}): react.JSX.Element;
|
|
101
|
+
|
|
102
|
+
/** Renders `children` when the permission is held, `fallback` otherwise. */
|
|
103
|
+
declare function Can({ permission, domain, fallback, children, }: {
|
|
104
|
+
permission: string;
|
|
105
|
+
domain?: AccessDomain | null;
|
|
106
|
+
fallback?: ReactNode;
|
|
107
|
+
children: ReactNode;
|
|
108
|
+
}): ReactNode;
|
|
109
|
+
|
|
110
|
+
declare function useAccessClient(): AccessClient;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Put once under the plugin's own `QueryClientProvider`. Every hook and screen
|
|
114
|
+
* in this package reads the client from here.
|
|
115
|
+
*/
|
|
116
|
+
declare function AccessProvider({ api, children, }: {
|
|
117
|
+
api: PluginApiClient;
|
|
118
|
+
children: ReactNode;
|
|
119
|
+
}): react.JSX.Element;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Reading a `/access/me` snapshot.
|
|
123
|
+
*
|
|
124
|
+
* Pure, so the rules a screen gates on are tested apart from React. Missing
|
|
125
|
+
* data never opens anything: until the snapshot arrives every check is false.
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
interface AccessView {
|
|
129
|
+
/** The permission is held, at any scope. */
|
|
130
|
+
can(permission: string): boolean;
|
|
131
|
+
/** The scope held, `null` when not held, `true` for an unscoped grant. */
|
|
132
|
+
scope(permission: string): string | true | null;
|
|
133
|
+
/**
|
|
134
|
+
* Whether a page is offered. Pages the catalog does not gate are offered to
|
|
135
|
+
* everyone who can open the plugin at all.
|
|
136
|
+
*/
|
|
137
|
+
sees(navKey: string): boolean;
|
|
138
|
+
}
|
|
139
|
+
declare function accessView(snapshot: AccessSnapshot | undefined): AccessView;
|
|
140
|
+
/** The entries a person is offered, in their declared order. */
|
|
141
|
+
declare function filterNav<T extends {
|
|
142
|
+
key: string;
|
|
143
|
+
}>(entries: readonly T[], view: Pick<AccessView, 'sees'>): T[];
|
|
144
|
+
|
|
145
|
+
interface Access extends AccessView {
|
|
146
|
+
snapshot: AccessSnapshot | undefined;
|
|
147
|
+
loading: boolean;
|
|
148
|
+
/** Why the snapshot could not be read; every check is false meanwhile. */
|
|
149
|
+
error: unknown;
|
|
150
|
+
refetch: () => void;
|
|
151
|
+
}
|
|
152
|
+
declare function accessMeKey(domain?: AccessDomain | null): readonly ["plugin-access", "me", string, string] | readonly ["plugin-access", "me"];
|
|
153
|
+
/**
|
|
154
|
+
* What the signed-in person may do in this plugin, asked once per domain and
|
|
155
|
+
* shared by key. For drawing the UI only — the backend decides.
|
|
156
|
+
*/
|
|
157
|
+
declare function useAccess(domain?: AccessDomain | null): Access;
|
|
158
|
+
|
|
159
|
+
export { type Access, AccessApiError, type AccessClient, AccessProvider, AccessSettings, type AccessView, Can, type PrincipalKindLabels, accessMeKey, accessView, createAccessClient, filterNav, useAccess, useAccessClient };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var ze=Object.defineProperty;var n=(c,t)=>ze(c,"name",{value:t,configurable:!0});import{Loading as z,EmptyState as Y,Tabs as He,TabsList as Be,TabsTrigger as H,TabsContent as B,useConfirm as Ae,usePrompt as Me,Button as S,Table as J,TableHeader as Z,TableRow as _,TableHead as b,TableBody as W,TableCell as x,Badge as G,Label as I,Combobox as ye,Select as ne,SelectTrigger as ie,SelectValue as re,SelectContent as ae,SelectItem as M,toasts as ve,Dialog as be,DialogContent as xe,DialogHeader as Ne,DialogTitle as Te,DialogDescription as Ve,Input as Qe,Textarea as Ye,Checkbox as X,DialogFooter as we}from"@tego/ui";import{ShieldOff as Je,CircleAlert as Ze,Plus as Ce,Eye as We,Pencil as Xe,Copy as es,Trash2 as ke,Users as ss,History as ts}from"lucide-react";import{useTranslation as D}from"react-i18next";import{useQuery as F,useQueryClient as Re,useMutation as cs,useInfiniteQuery as ns}from"@tanstack/react-query";import{createContext as is,useContext as rs,useMemo as Se,useState as T}from"react";import{jsx as e,jsxs as a,Fragment as le}from"react/jsx-runtime";import{expandImplications as as}from"@tego/plugin-sdk/access/implications";var ls=Object.defineProperty,os=n((c,t,s)=>t in c?ls(c,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):c[t]=s,"__defNormalProp"),Ee=n((c,t,s)=>os(c,typeof t!="symbol"?t+"":t,s),"__publicField");function ds(c){const t=new Set,s=[];for(const i of c)for(const m of i.items)t.has(m.id)||(t.add(m.id),s.push(m));return s}n(ds,"auditEntries");var oe=class extends Error{static{n(this,"AccessApiError")}constructor(c,t,s){super(c),Ee(this,"status",t),Ee(this,"code",s),this.name="AccessApiError"}};function j(c,t={}){const s=new URLSearchParams;c&&(s.set("domainType",c.type),s.set("domainId",c.id));for(const[m,d]of Object.entries(t))d!==void 0&&d!==""&&s.set(m,String(d));const i=s.toString();return i?`?${i}`:""}n(j,"query");async function us(c){const t=await c.json().catch(()=>null),s=t&&typeof t=="object"?t.error:void 0;return new oe(typeof s?.message=="string"?s.message:`HTTP ${c.status}`,c.status,typeof s?.code=="string"?s.code:null)}n(us,"readError");function De(c){const t=n(async(s,i,m)=>{const d=await c.request(i,{method:s,...m===void 0?{}:{body:JSON.stringify(m),headers:{"content-type":"application/json"}}});if(!d.ok)throw await us(d);return d.status===204?void 0:await d.json()},"send");return{me:n(s=>t("GET",`/access/me${j(s)}`),"me"),catalog:n(s=>t("GET",`/access/catalog${j(s)}`),"catalog"),roles:n(async s=>(await t("GET",`/access/roles${j(s)}`)).roles,"roles"),createRole:n(async s=>(await t("POST","/access/roles",s)).role,"createRole"),updateRole:n(async(s,i)=>(await t("PUT",`/access/roles/${encodeURIComponent(s)}`,i)).role,"updateRole"),deleteRole:n(s=>t("DELETE",`/access/roles/${encodeURIComponent(s)}`),"deleteRole"),cloneRole:n(async(s,i)=>(await t("POST",`/access/roles/${encodeURIComponent(s)}/clone`,i)).role,"cloneRole"),assignments:n(async(s,i={})=>(await t("GET",`/access/assignments${j(s,i)}`)).assignments,"assignments"),createAssignment:n(async s=>(await t("POST","/access/assignments",s)).assignment,"createAssignment"),deleteAssignment:n(s=>t("DELETE",`/access/assignments/${encodeURIComponent(s)}`),"deleteAssignment"),principals:n((s,i)=>t("GET",`/access/principals${j(s,{kind:i.kind,search:i.search,ids:i.ids?.join(","),offset:i.offset,limit:i.limit})}`),"principals"),explain:n((s,i)=>t("GET",`/access/explain/${encodeURIComponent(s)}${j(i)}`),"explain"),settings:n(()=>t("GET","/access/settings"),"settings"),updateSettings:n(s=>t("PUT","/access/settings",s),"updateSettings"),audit:n((s={})=>t("GET",`/access/audit${j(null,s)}`),"audit")}}n(De,"createAccessClient");var Pe=is(null);function K(){const c=rs(Pe);if(!c)throw new Error("@tego/plugin-access-ui: no <AccessProvider> above this.");return c}n(K,"useAccessClient");var P=["plugin-access"],V=n(c=>c?`${c.type}:${c.id}`:"global","domainKey");function ms(c,t){const s=K();return F({queryKey:[...P,"catalog",V(c)],queryFn:n(()=>s.catalog(c),"queryFn"),enabled:t,staleTime:1/0,retry:!1})}n(ms,"useCatalog");function de(c){const t=K();return F({queryKey:[...P,"roles",V(c)],queryFn:n(()=>t.roles(c),"queryFn")})}n(de,"useRoles");function gs(c){const t=K();return F({queryKey:[...P,"assignments",V(c)],queryFn:n(()=>t.assignments(c),"queryFn")})}n(gs,"useAssignments");function Ke(c,t,s){const i=K();return F({queryKey:[...P,"principals",V(c),t,s],queryFn:n(()=>i.principals(c,{kind:t,search:s||void 0,limit:50}),"queryFn"),placeholderData:n(m=>m,"placeholderData")})}n(Ke,"usePrincipals");function hs(c,t){const s=K();return F({queryKey:[...P,"explain",V(c),t],queryFn:n(()=>s.explain(t,c),"queryFn"),enabled:t!==null})}n(hs,"useExplain");function ps(){const c=K();return F({queryKey:[...P,"settings"],queryFn:n(()=>c.settings(),"queryFn")})}n(ps,"useSettings");var Ie=50;function fs(){const c=K();return ns({queryKey:[...P,"audit"],queryFn:n(({pageParam:t})=>c.audit({offset:t,limit:Ie}),"queryFn"),initialPageParam:0,getNextPageParam:n((t,s)=>t.hasMore?s.length*Ie:void 0,"getNextPageParam")})}n(fs,"useAudit");function Le(){const{t:c}=D();return t=>t instanceof oe&&t.code?c(`tegoAccess.errors.${t.code}`,{defaultValue:t.message}):t instanceof Error?t.message:String(t)}n(Le,"useDescribeError");function O(c,t){const s=K(),i=Re(),{t:m}=D(),d=Le();return cs({mutationFn:n(l=>c(s,l),"mutationFn"),onSuccess:n(async()=>{ve.success(m(t)),await i.invalidateQueries({queryKey:P})},"onSuccess"),onError:n(l=>ve.error(m("tegoAccess.common.failed"),d(l)),"onError")})}n(O,"useAccessMutation");function U({error:c,onRetry:t}){const{t:s}=D(),i=Le();return e(Y,{size:"sm",icon:e(Ze,{}),title:s("tegoAccess.common.loadFailed"),description:i(c),action:{label:s("tegoAccess.common.retry"),onClick:t}})}n(U,"LoadFailed");function As(c){for(const t of[c.after,c.before])if(t&&typeof t=="object"&&"name"in t){const{name:s}=t;if(typeof s=="string")return s}return null}n(As,"recordName");function ys(){const{t:c,i18n:t}=D(),s=fs(),i=ds(s.data?.pages??[]),m=new Intl.DateTimeFormat(t.language,{dateStyle:"medium",timeStyle:"short"});return s.isLoading?e(z,{className:"py-10"}):!s.data&&s.error?e(U,{error:s.error,onRetry:n(()=>void s.refetch(),"onRetry")}):i.length===0?e(Y,{size:"sm",icon:e(ts,{}),title:c("tegoAccess.audit.emptyTitle"),description:c("tegoAccess.audit.emptyDescription")}):a("div",{className:"space-y-3",children:[a(J,{children:[e(Z,{children:a(_,{children:[e(b,{children:c("tegoAccess.audit.at")}),e(b,{children:c("tegoAccess.audit.actor")}),e(b,{children:c("tegoAccess.audit.action")}),e(b,{children:c("tegoAccess.audit.target")})]})}),e(W,{children:i.map(d=>a(_,{children:[e(x,{className:"whitespace-nowrap text-sm tabular-nums",children:m.format(new Date(d.at))}),e(x,{children:d.actorId?d.actorName??d.actorId:c("tegoAccess.audit.system")}),e(x,{children:c(`tegoAccess.audit.actions.${d.action}`)}),e(x,{className:"text-sm text-muted-foreground",children:As(d)??d.targetId})]},d.id))})]}),s.hasNextPage&&e("div",{className:"flex justify-center",children:e(S,{variant:"outline",size:"sm",disabled:s.isFetchingNextPage,onClick:n(()=>void s.fetchNextPage(),"onClick"),children:c("tegoAccess.audit.more")})})]})}n(ys,"AuditTab");function L(c,t){return t.nameKey?c(t.nameKey):t.name}n(L,"roleName");function ue(c,t,s){if(s===null)return c("tegoAccess.roles.notGranted");if(s===!0)return c("tegoAccess.roles.granted");const i=t.scopes[s];return i?c(i.labelKey):s}n(ue,"scopeName");function vs(c,t,s){const i=t.permissions[s];return i?c(i.labelKey):s}n(vs,"permissionName");var bs={user:"tegoAccess.principalKind.user",unit:"tegoAccess.principalKind.unit"};function Q(c,t,s){const i=t[s]??bs[s];return i?c(i):s}n(Q,"principalKindName");var xs=["owner","admin","member","viewer"],ee="__none__";function Ns(){const{t:c}=D(),t=ps(),s=de(null),[i,m]=T(null),d=O((o,N)=>o.updateSettings({unassignedRoleId:N}),"tegoAccess.defaults.saved");if(t.isLoading||s.isLoading)return e(z,{className:"py-10"});for(const o of[t,s])if(!o.data&&o.error)return e(U,{error:o.error,onRetry:n(()=>void o.refetch(),"onRetry")});const l=t.data?.unassignedRoleId??ee,p=i??l;return a("div",{className:"max-w-md space-y-4",children:[a("div",{className:"space-y-2",children:[e(I,{children:c("tegoAccess.defaults.label")}),e("p",{className:"text-sm text-muted-foreground",children:c("tegoAccess.defaults.description")}),a(ne,{value:p,onValueChange:m,children:[e(ie,{"aria-label":c("tegoAccess.defaults.label"),children:e(re,{})}),a(ae,{children:[e(M,{value:ee,children:c("tegoAccess.defaults.none")}),(s.data??[]).filter(o=>o.domain===null).map(o=>e(M,{value:o.id,children:L(c,o)},o.id))]})]}),p===ee&&e("p",{className:"text-sm text-warning",children:c("tegoAccess.defaults.noneHint")})]}),e(S,{disabled:d.isPending||p===l,onClick:n(()=>d.mutate(p===ee?null:p,{onSuccess:n(()=>m(null),"onSuccess")}),"onClick"),children:c("tegoAccess.common.save")})]})}n(Ns,"DefaultsTab");function Ts({catalog:c,domain:t,kindLabels:s}){const{t:i}=D(),[m,d]=T(""),[l,p]=T(null),o=l?.id??null,N=Ke(t,"user",m),f=hs(t,o),k=(N.data?.items??[]).map(h=>({value:h.id,label:h.displayName})),y=n(h=>h.source==="hostRole"?i("tegoAccess.explain.viaHostRole",{role:h.hostRole}):h.source==="unassigned"?i("tegoAccess.explain.viaDefault"):h.inherited?i("tegoAccess.explain.viaParent"):h.principal&&h.principal.kind!=="user"?i("tegoAccess.explain.viaGroup",{kind:Q(i,s,h.principal.kind)}):i("tegoAccess.explain.viaDirect"),"source");return a("div",{className:"space-y-4",children:[a("div",{className:"max-w-sm space-y-2",children:[e(I,{children:i("tegoAccess.explain.user")}),e(ye,{options:k,value:o,selectedLabel:l?.label,onChange:n(h=>p(h===null?null:{id:h,label:k.find(w=>w.value===h)?.label??h}),"onChange"),onSearch:d,searching:N.isFetching,placeholder:i("tegoAccess.explain.pickUser"),searchPlaceholder:i("tegoAccess.common.search"),emptyText:i("tegoAccess.common.noMatches"),"aria-label":i("tegoAccess.explain.user")})]}),f.isLoading&&e(z,{className:"py-10"}),!f.data&&f.error&&e(U,{error:f.error,onRetry:n(()=>void f.refetch(),"onRetry")}),f.data&&a(le,{children:[a("section",{className:"space-y-2",children:[e("h4",{className:"text-sm font-medium",children:i("tegoAccess.explain.roles")}),f.data.roles.length===0?e("p",{className:"text-sm text-muted-foreground",children:i("tegoAccess.explain.noRoles")}):e("ul",{className:"flex flex-wrap gap-2",children:f.data.roles.map((h,w)=>e("li",{children:a(G,{variant:"outline",children:[L(i,h)," \xB7 ",y(h)]})},`${h.roleId}-${w}`))})]}),a(J,{children:[e(Z,{children:a(_,{children:[e(b,{children:i("tegoAccess.explain.permission")}),e(b,{children:i("tegoAccess.explain.result")}),e(b,{children:i("tegoAccess.explain.scope")})]})}),e(W,{children:f.data.permissions.map(h=>a(_,{children:[e(x,{children:vs(i,c,h.permission)}),e(x,{children:e(G,{variant:h.allowed?"success":"secondary",children:i(`tegoAccess.explain.reason.${h.reason}`)})}),e(x,{className:"text-sm text-muted-foreground",children:h.allowed?ue(i,c,h.scope??!0):"\u2014"})]},h.permission))})]})]})]})}n(Ts,"ExplainTab");function ws({catalog:c,domain:t,roles:s,assignments:i,kindLabels:m,saving:d,onAssign:l,onClose:p}){const{t:o}=D(),N=c.assignment.principals,[f,k]=T(N[0]),[y,h]=T(""),[w,q]=T(null),C=w?.id??null,[r,u]=T([]),[A,E]=T(!1),[v,ge]=T([]),he=Ke(t,f,y),pe=(he.data?.items??[]).map(g=>({value:g.id,label:g.displayName})),Fe=n(g=>{k(g),h(""),q(null),E(!1),ge([])},"changeKind"),je=n((g,R)=>ge($=>R?[...$,g]:$.filter(ce=>ce!==g)),"toggleUnitRole"),fe=new Set(i.filter(g=>g.principal.kind===f&&g.principal.id===C).map(g=>g.roleId)),te=r.filter(g=>!fe.has(g)),Oe=n((g,R)=>u($=>R?[...$,g]:$.filter(ce=>ce!==g)),"toggleRole"),Ue=n(()=>{!C||te.length===0||l(te.map(g=>({roleId:g,principal:{kind:f,id:C,includeDescendants:A,unitRoles:f==="unit"&&v.length>0?v:null},domain:t})))},"submit");return e(be,{open:!0,onOpenChange:n(g=>!g&&p(),"onOpenChange"),children:a(xe,{className:"max-w-lg",children:[e(Ne,{children:e(Te,{children:o("tegoAccess.members.assignTitle")})}),a("div",{className:"space-y-4",children:[N.length>1&&a("div",{className:"space-y-2",children:[e(I,{children:o("tegoAccess.members.principalKind")}),a(ne,{value:f,onValueChange:Fe,children:[e(ie,{children:e(re,{})}),e(ae,{children:N.map(g=>e(M,{value:g,children:Q(o,m,g)},g))})]})]}),a("div",{className:"space-y-2",children:[e(I,{children:Q(o,m,f)}),e(ye,{options:pe,value:C,selectedLabel:w?.label,onChange:n(g=>q(g===null?null:{id:g,label:pe.find(R=>R.value===g)?.label??g}),"onChange"),onSearch:h,searching:he.isFetching,placeholder:o("tegoAccess.members.pickPrincipal"),searchPlaceholder:o("tegoAccess.common.search"),emptyText:o("tegoAccess.common.noMatches"),"aria-label":Q(o,m,f)})]}),f!=="user"&&a("label",{className:"flex items-center gap-2 text-sm",children:[e(X,{checked:A,onCheckedChange:n(g=>E(g===!0),"onCheckedChange")}),o("tegoAccess.members.includeDescendants")]}),f==="unit"&&a("div",{className:"space-y-2",children:[e(I,{children:o("tegoAccess.members.unitRoles")}),e("p",{className:"text-xs text-muted-foreground",children:o("tegoAccess.members.unitRolesHint")}),e("div",{className:"flex flex-wrap gap-4",children:xs.map(g=>a("label",{className:"flex items-center gap-2 text-sm",children:[e(X,{checked:v.includes(g),onCheckedChange:n(R=>je(g,R===!0),"onCheckedChange")}),o(`tegoAccess.unitRole.${g}`)]},g))})]}),a("div",{className:"space-y-2",children:[e(I,{children:o("tegoAccess.members.role")}),e("p",{className:"text-xs text-muted-foreground",children:o("tegoAccess.members.rolesHint")}),e("div",{role:"group","aria-label":o("tegoAccess.members.role"),className:"max-h-60 space-y-2 overflow-y-auto rounded-md border p-3",children:s.map(g=>{const R=fe.has(g.id);return a("label",{className:"flex items-center gap-2 text-sm",children:[e(X,{checked:R||r.includes(g.id),disabled:R,onCheckedChange:n($=>Oe(g.id,$===!0),"onCheckedChange")}),e("span",{className:R?"text-muted-foreground":void 0,children:L(o,g)}),R&&e(G,{variant:"secondary",children:o("tegoAccess.members.alreadyAssigned")})]},g.id)})})]})]}),a(we,{children:[e(S,{variant:"outline",onClick:p,children:o("tegoAccess.common.cancel")}),e(S,{disabled:d||!C||te.length===0,onClick:Ue,children:o("tegoAccess.members.assign")})]})]})})}n(ws,"AssignDialog");function Cs({catalog:c,domain:t,kindLabels:s}){const{t:i}=D(),m=Re(),d=gs(t),l=de(t),[p,o]=T(null),{confirm:N,ConfirmDialog:f}=Ae(),k=new Map((l.data??[]).map(r=>[r.id,r])),y=O(async(r,u)=>{for(const A of u)await r.createAssignment(A)},"tegoAccess.members.assigned"),h=O((r,u)=>r.deleteAssignment(u),"tegoAccess.members.removed"),w=n(r=>r.principalName??r.principal.id,"principalLabel"),q=n(async r=>{const u=k.get(r.roleId);await N({title:i("tegoAccess.members.removeTitle"),description:i("tegoAccess.members.removeDescription",{principal:w(r),role:u?L(i,u):r.roleId}),confirmText:i("tegoAccess.members.remove"),cancelText:i("tegoAccess.common.cancel"),variant:"destructive"})&&h.mutate(r.id)},"askRemove");if(d.isLoading||l.isLoading)return e(z,{className:"py-10"});for(const r of[d,l])if(!r.data&&r.error)return e(U,{error:r.error,onRetry:n(()=>void r.refetch(),"onRetry")});const C=d.data??[];return a("div",{className:"space-y-3",children:[e("div",{className:"flex justify-end",children:a(S,{size:"sm",onClick:n(()=>o({}),"onClick"),children:[e(Ce,{className:"mr-1 h-4 w-4"}),i("tegoAccess.members.assign")]})}),C.length===0?e(Y,{size:"sm",icon:e(ss,{}),title:i("tegoAccess.members.emptyTitle"),description:i("tegoAccess.members.emptyDescription")}):a(J,{children:[e(Z,{children:a(_,{children:[e(b,{children:i("tegoAccess.members.principal")}),e(b,{children:i("tegoAccess.members.role")}),e(b,{children:i("tegoAccess.members.coverage")}),e(b,{className:"w-12"})]})}),e(W,{children:C.map(r=>{const u=k.get(r.roleId),{principal:A}=r;return a(_,{children:[e(x,{children:a("div",{className:"flex items-center gap-2",children:[e("span",{className:"font-medium",children:w(r)}),e(G,{variant:"outline",children:Q(i,s,A.kind)})]})}),e(x,{children:u?L(i,u):r.roleId}),e(x,{className:"text-sm text-muted-foreground",children:A.kind==="user"?"\u2014":[A.includeDescendants?i("tegoAccess.members.withDescendants"):i("tegoAccess.members.directOnly"),A.unitRoles?A.unitRoles.map(E=>i(`tegoAccess.unitRole.${E}`)).join(i("tegoAccess.common.listSeparator")):null].filter(Boolean).join(" \xB7 ")}),e(x,{children:e(S,{size:"icon",variant:"ghost","aria-label":i("tegoAccess.members.remove"),onClick:n(()=>void q(r),"onClick"),children:e(ke,{className:"h-4 w-4"})})})]},r.id)})})]}),p&&e(ws,{catalog:c,domain:t,roles:l.data??[],assignments:C,kindLabels:s,saving:y.isPending,onAssign:n(r=>y.mutate(r,{onSuccess:n(()=>o(u=>u===p?null:u),"onSuccess"),onError:n(()=>void m.invalidateQueries({queryKey:P}),"onError")}),"onAssign"),onClose:n(()=>o(null),"onClose")}),e(f,{})]})}n(Cs,"MembersTab");function ks(c,t){return c.groups.map(s=>({...s,permissions:Object.values(c.permissions).filter(i=>i.group===s.key&&(!i.deprecated||i.key in t))})).filter(s=>s.permissions.length>0)}n(ks,"permissionGroups");function Rs(c,t){const s={};for(const[i,m]of Object.entries(as(c.permissions,t)))t[i]!==m&&(s[i]=m);return s}n(Rs,"impliedGrants");function qe(c,t,s){const i={...c};return s===null?delete i[t]:i[t]=s,i}n(qe,"setGrant");var me="__not_granted__";function Ss({catalog:c,role:t,lock:s,saving:i,onSave:m,onClose:d}){const{t:l}=D(),p=s!==null,[o,N]=T(t?L(l,t):""),[f,k]=T(t?.descriptionKey?l(t.descriptionKey):t?.description??""),[y,h]=T(t?.grants??{}),w=ks(c,y),q=Rs(c,y),C=l(t?p?"tegoAccess.roles.viewTitle":"tegoAccess.roles.editTitle":"tegoAccess.roles.createTitle");return e(be,{open:!0,onOpenChange:n(r=>!r&&d(),"onOpenChange"),children:a(xe,{className:"flex max-h-[85vh] max-w-2xl flex-col",children:[a(Ne,{children:[e(Te,{children:C}),s&&e(Ve,{children:l(s==="builtin"?"tegoAccess.roles.builtinHint":"tegoAccess.roles.globalHint")})]}),a("div",{className:"-mx-6 flex-1 space-y-4 overflow-y-auto px-6",children:[a("div",{className:"space-y-2",children:[e(I,{htmlFor:"tego-access-role-name",children:l("tegoAccess.roles.name")}),e(Qe,{id:"tego-access-role-name",value:o,maxLength:80,disabled:p,onChange:n(r=>N(r.target.value),"onChange")})]}),a("div",{className:"space-y-2",children:[e(I,{htmlFor:"tego-access-role-description",children:l("tegoAccess.roles.description")}),e(Ye,{id:"tego-access-role-description",value:f,maxLength:500,rows:2,disabled:p,onChange:n(r=>k(r.target.value),"onChange")})]}),t&&t.staleGrants.length>0&&e("p",{className:"text-sm text-warning",children:l("tegoAccess.roles.staleGrants",{permissions:t.staleGrants.join(", ")})}),a("div",{className:"space-y-4",children:[e(I,{children:l("tegoAccess.roles.permissions")}),w.map(r=>a("section",{className:"space-y-2",children:[e("h4",{className:"text-sm font-medium text-muted-foreground",children:l(r.labelKey)}),e("ul",{className:"divide-y divide-border rounded-md border border-border",children:r.permissions.map(u=>{const A=y[u.key]??null,E=q[u.key];return a("li",{className:"flex items-center justify-between gap-4 px-3 py-2",children:[a("div",{className:"min-w-0",children:[e("p",{className:"text-sm",children:l(u.labelKey)}),u.descriptionKey&&e("p",{className:"text-xs text-muted-foreground",children:l(u.descriptionKey)}),E!==void 0&&e("p",{className:"text-xs text-muted-foreground",children:E===!0?l("tegoAccess.roles.implied"):l("tegoAccess.roles.impliedScope",{scope:ue(l,c,E)})})]}),u.scopes?a(ne,{value:typeof A=="string"?A:me,disabled:p,onValueChange:n(v=>h(qe(y,u.key,v===me?null:v)),"onValueChange"),children:[e(ie,{className:"w-40 shrink-0","aria-label":l(u.labelKey),children:e(re,{})}),a(ae,{children:[e(M,{value:me,children:l("tegoAccess.roles.notGranted")}),u.scopes.map(v=>e(M,{value:v,children:ue(l,c,v)},v))]})]}):e(X,{checked:A===!0,disabled:p,"aria-label":l(u.labelKey),onCheckedChange:n(v=>h(qe(y,u.key,v===!0?!0:null)),"onCheckedChange")})]},u.key)})})]},r.key))]})]}),a(we,{children:[e(S,{variant:"outline",onClick:d,children:l(p?"tegoAccess.common.close":"tegoAccess.common.cancel")}),!p&&e(S,{disabled:i||o.trim()==="",onClick:n(()=>m({name:o.trim(),description:f.trim(),grants:y}),"onClick"),children:l("tegoAccess.common.save")})]})]})})}n(Ss,"RoleEditorDialog");function _e(c,t){return c.builtin?"builtin":t&&c.domain===null?"global":null}n(_e,"roleLock");function Es({catalog:c,domain:t}){const{t:s}=D(),i=de(t),[m,d]=T(null),{confirm:l,ConfirmDialog:p}=Ae(),{prompt:o,PromptDialog:N}=Me(),f=O((r,u)=>r.createRole({...u,domain:t}),"tegoAccess.roles.created"),k=O((r,u)=>r.updateRole(u.id,u.draft),"tegoAccess.roles.updated"),y=O((r,u)=>r.deleteRole(u),"tegoAccess.roles.deleted"),h=O((r,u)=>r.cloneRole(u.id,{name:u.name,domain:t}),"tegoAccess.roles.cloned"),w=n(r=>{const u=m,A=u?.role,E={onSuccess:n(()=>d(v=>v===u?null:v),"onSuccess")};A?k.mutate({id:A.id,draft:r},E):f.mutate(r,E)},"save"),q=n(async r=>{const u=await o({title:s("tegoAccess.roles.cloneTitle"),label:s("tegoAccess.roles.name"),defaultValue:s("tegoAccess.roles.cloneName",{name:L(s,r)}),confirmText:s("tegoAccess.roles.clone"),cancelText:s("tegoAccess.common.cancel")});u&&h.mutate({id:r.id,name:u})},"askClone"),C=n(async r=>{await l({title:s("tegoAccess.roles.deleteTitle",{name:L(s,r)}),description:s("tegoAccess.roles.deleteDescription"),confirmText:s("tegoAccess.common.delete"),cancelText:s("tegoAccess.common.cancel"),variant:"destructive"})&&y.mutate(r.id)},"askDelete");return i.isLoading?e(z,{className:"py-10"}):!i.data&&i.error?e(U,{error:i.error,onRetry:n(()=>void i.refetch(),"onRetry")}):a("div",{className:"space-y-3",children:[e("div",{className:"flex justify-end",children:a(S,{size:"sm",onClick:n(()=>d({role:null}),"onClick"),children:[e(Ce,{className:"mr-1 h-4 w-4"}),s("tegoAccess.roles.create")]})}),a(J,{children:[e(Z,{children:a(_,{children:[e(b,{children:s("tegoAccess.roles.name")}),e(b,{children:s("tegoAccess.roles.type")}),e(b,{className:"text-right",children:s("tegoAccess.roles.assignments")}),e(b,{className:"w-32"})]})}),e(W,{children:(i.data??[]).map(r=>{const u=_e(r,t)!==null;return a(_,{children:[a(x,{children:[a("div",{className:"flex flex-wrap items-center gap-2",children:[e("span",{className:"font-medium",children:L(s,r)}),r.isDefault&&e(G,{variant:"secondary",children:s("tegoAccess.roles.default")}),r.staleGrants.length>0&&e(G,{variant:"warning",children:s("tegoAccess.roles.stale")})]}),r.descriptionKey?e("p",{className:"text-xs text-muted-foreground",children:s(r.descriptionKey)}):r.description&&e("p",{className:"text-xs text-muted-foreground",children:r.description})]}),e(x,{children:e(G,{variant:"outline",children:r.builtin?s("tegoAccess.roles.builtin"):r.domain?s("tegoAccess.roles.domainRole"):s("tegoAccess.roles.custom")})}),e(x,{className:"text-right tabular-nums",children:r.assignmentCount}),e(x,{children:a("div",{className:"flex justify-end gap-1",children:[e(S,{size:"icon",variant:"ghost","aria-label":s(u?"tegoAccess.roles.view":"tegoAccess.roles.edit"),onClick:n(()=>d({role:r}),"onClick"),children:u?e(We,{className:"h-4 w-4"}):e(Xe,{className:"h-4 w-4"})}),e(S,{size:"icon",variant:"ghost","aria-label":s("tegoAccess.roles.clone"),onClick:n(()=>void q(r),"onClick"),children:e(es,{className:"h-4 w-4"})}),!u&&e(S,{size:"icon",variant:"ghost","aria-label":s("tegoAccess.common.delete"),onClick:n(()=>void C(r),"onClick"),children:e(ke,{className:"h-4 w-4"})})]})})]},r.id)})})]}),m&&e(Ss,{catalog:c,role:m.role,lock:m.role?_e(m.role,t):null,saving:f.isPending||k.isPending,onSave:w,onClose:n(()=>d(null),"onClose")}),e(p,{}),e(N,{})]})}n(Es,"RolesTab");function $e(c){return{can:n(t=>c?.permissions[t]!==void 0,"can"),scope:n(t=>c?.permissions[t]??null,"scope"),sees:n(t=>c?c.menus[t]??!0:!1,"sees")}}n($e,"accessView");function Ds(c,t){return c.filter(s=>t.sees(s.key))}n(Ds,"filterNav");function Ge(c){return c?[...P,"me",c.type,c.id]:[...P,"me"]}n(Ge,"accessMeKey");function se(c){const t=K(),s=F({queryKey:Ge(c),queryFn:n(()=>t.me(c),"queryFn"),staleTime:6e4}),{data:i,isLoading:m,error:d,refetch:l}=s;return Se(()=>({...$e(i),snapshot:i,loading:m,error:d,refetch:n(()=>void l(),"refetch")}),[i,m,d,l])}n(se,"useAccess");var Ps={};function Ks({domain:c=null,principalKindLabels:t=Ps}){const{t:s}=D(),i=se(c),m=se(null),d=i.can("access.manage"),l=!c&&m.can("access.audit"),p=ms(c,d);if(i.loading||m.loading||d&&p.isLoading)return e(z,{className:"py-10"});for(const o of[i,m])if(!o.snapshot&&o.error)return e(U,{error:o.error,onRetry:o.refetch});return!d&&!l?e(Y,{size:"sm",icon:e(Je,{}),title:s("tegoAccess.denied.title"),description:s("tegoAccess.denied.description")}):d&&!p.data&&p.error?e(U,{error:p.error,onRetry:n(()=>void p.refetch(),"onRetry")}):a(He,{defaultValue:d?"roles":"audit",children:[a(Be,{children:[d&&a(le,{children:[e(H,{value:"roles",children:s("tegoAccess.tabs.roles")}),e(H,{value:"members",children:s("tegoAccess.tabs.members")}),e(H,{value:"explain",children:s("tegoAccess.tabs.explain")}),!c&&e(H,{value:"defaults",children:s("tegoAccess.tabs.defaults")})]}),l&&e(H,{value:"audit",children:s("tegoAccess.tabs.audit")})]}),d&&p.data&&a(le,{children:[e(B,{value:"roles",children:e(Es,{catalog:p.data,domain:c})}),e(B,{value:"members",children:e(Cs,{catalog:p.data,domain:c,kindLabels:t})}),e(B,{value:"explain",children:e(Ts,{catalog:p.data,domain:c,kindLabels:t})}),!c&&e(B,{value:"defaults",children:e(Ns,{})})]}),l&&e(B,{value:"audit",children:e(ys,{})})]})}n(Ks,"AccessSettings");function Is({permission:c,domain:t,fallback:s=null,children:i}){return se(t).can(c)?i:s}n(Is,"Can");function Ls({api:c,children:t}){const s=Se(()=>De(c),[c]);return e(Pe,{value:s,children:t})}n(Ls,"AccessProvider");export{oe as AccessApiError,Ls as AccessProvider,Ks as AccessSettings,Is as Can,Ge as accessMeKey,$e as accessView,De as createAccessClient,Ds as filterNav,se as useAccess,K as useAccessClient};
|