adminizer 5.1.0-build.28 → 5.2.0-build.30
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/assets/{abnfDiagram-VCTEODGH-uWOVpoSR.js → abnfDiagram-VCTEODGH-BhZn7BLv.js} +1 -1
- package/assets/{add-A_fIlNKI.js → add-DDfJt70P.js} +1 -1
- package/assets/{add-group-C2x6K3tV.js → add-group-Cs3S9VVn.js} +1 -1
- package/assets/{add-user-u61kYlEm.js → add-user-DxI_sJLw.js} +1 -1
- package/assets/ai-assistant/agent.es.js +14736 -11737
- package/assets/app-DM8KzeFz.css +1 -0
- package/assets/app-DOMFUTFw.js +138 -0
- package/assets/{arc--ZX64bmY.js → arc-BRY7wCfa.js} +1 -1
- package/assets/{architectureDiagram-5GKGNRK7-W9AzLZvl.js → architectureDiagram-5GKGNRK7-DfBT7jAW.js} +1 -1
- package/assets/{blockDiagram-I7D4REHJ-BpK_yEa7.js → blockDiagram-I7D4REHJ-CW2mcR7Z.js} +1 -1
- package/assets/{c4Diagram-7LVT6UL2-DiQzU1s0.js → c4Diagram-7LVT6UL2-BGsyO-4Y.js} +1 -1
- package/assets/{catalog-dSCv3Szm.js → catalog-cyCZOCXs.js} +3 -3
- package/assets/channel-Bd-bsjgh.js +1 -0
- package/assets/{chunk-2Q5K7J3B-GPHETbCq.js → chunk-2Q5K7J3B-4EnjsYhG.js} +1 -1
- package/assets/{chunk-5VM5RSS4-bLovkogd.js → chunk-5VM5RSS4-BVzmz0IS.js} +1 -1
- package/assets/{chunk-F27PBJKO-DbkTY41z.js → chunk-F27PBJKO-Bkf9Z4lt.js} +1 -1
- package/assets/{chunk-IMKFNOWR-CL0VAxX7.js → chunk-IMKFNOWR-Dg6Y3xGC.js} +1 -1
- package/assets/{chunk-JWPE2WC7-d1Grk14b.js → chunk-JWPE2WC7-BdVNpqE2.js} +1 -1
- package/assets/{chunk-POPQ4Y6H-CAUhiiNt.js → chunk-POPQ4Y6H-0R-etdBM.js} +1 -1
- package/assets/{chunk-SVP7TREG-C8ADZUEr.js → chunk-SVP7TREG-CdABJwLU.js} +1 -1
- package/assets/{chunk-TICWLB2K-oRqFZabo.js → chunk-TICWLB2K-Da-oSw37.js} +1 -1
- package/assets/{chunk-XXDRQBXY-C3zo4c2P.js → chunk-XXDRQBXY-Ba8BsH2Z.js} +1 -1
- package/assets/classDiagram-ZZMXUADV-BftNBmvr.js +1 -0
- package/assets/classDiagram-v2-VYDZK3BY-BftNBmvr.js +1 -0
- package/assets/controls/ckeditor.es.js +10659 -10551
- package/assets/controls/handsontable.es.js +9053 -8479
- package/assets/controls/jsoneditor.es.js +641 -614
- package/assets/controls/leaflet.es.js +672 -663
- package/assets/controls/toast-ui.es.js +13696 -13676
- package/assets/{cose-bilkent-JH36ORCC-ZPvVaI6n.js → cose-bilkent-JH36ORCC-BYrWDdVx.js} +1 -1
- package/assets/{cynefin-OW5HDTMX-EEL4eqU7.js → cynefin-OW5HDTMX-CwHzXvDB.js} +1 -1
- package/assets/{cynefinDiagram-5FMLGOSQ-DpDFbbrn.js → cynefinDiagram-5FMLGOSQ-V6tH6arn.js} +1 -1
- package/assets/{dagre-GXQ25YYZ-Dtjy1xN1.js → dagre-GXQ25YYZ-CaBvafdG.js} +1 -1
- package/assets/{dashboard-DXs-vdJG.js → dashboard-C27hB1GI.js} +1 -1
- package/assets/{diagram-S7CK7UJ4-BhWisCOy.js → diagram-S7CK7UJ4-85jkE9hd.js} +1 -1
- package/assets/{diagram-UQ7AKVKN-BBH2Mm33.js → diagram-UQ7AKVKN-DHJRq1TM.js} +1 -1
- package/assets/{diagram-VSXAHHWV-B1Xc2cPz.js → diagram-VSXAHHWV-C74VLfSc.js} +1 -1
- package/assets/{diagram-VX7I27RA-CTTYzy1s.js → diagram-VX7I27RA-CVJcG5hn.js} +1 -1
- package/assets/{diagram-Z3DM3KII-DdH0yWH0.js → diagram-Z3DM3KII-B8ybg5RA.js} +1 -1
- package/assets/{docs-BZYlfOON.js → docs-CK6W0Jko.js} +1 -1
- package/assets/{ebnfDiagram-PWID7BFC-R9cSqf0y.js → ebnfDiagram-PWID7BFC-D_gz_iz6.js} +1 -1
- package/assets/{erDiagram-RLTQ6QDP-Bpu-Pm95.js → erDiagram-RLTQ6QDP-D3W95aGH.js} +1 -1
- package/assets/{flowDiagram-HODETNUW-NdXf-fRN.js → flowDiagram-HODETNUW-D2PTWIEg.js} +1 -1
- package/assets/{ganttDiagram-EL5Y4UJY-itQHv_dH.js → ganttDiagram-EL5Y4UJY-TFBUh0C6.js} +1 -1
- package/assets/{gitGraphDiagram-WWUBYQGX-DorHK4Wx.js → gitGraphDiagram-WWUBYQGX-BfFJzeqx.js} +1 -1
- package/assets/{history-DB48MCa8.js → history-DX6CEQqv.js} +1 -1
- package/assets/{infoDiagram-27XIBGKW-FgFATKk4.js → infoDiagram-27XIBGKW-esGmrWiw.js} +1 -1
- package/assets/{init-user-DAXb55S_.js → init-user-D1G_dbcZ.js} +1 -1
- package/assets/{ishikawaDiagram-5VMMS53U-Bjl1a496.js → ishikawaDiagram-5VMMS53U--aGHPnva.js} +1 -1
- package/assets/{journeyDiagram-3NMN7TZE-DU1TmnbI.js → journeyDiagram-3NMN7TZE-03BXeE8O.js} +1 -1
- package/assets/{kanban-definition-UXKFOSKX-BsrlKdcU.js → kanban-definition-UXKFOSKX-JdDv2WHg.js} +1 -1
- package/assets/{layout-C68duuC7.js → layout-Bz6WKClu.js} +1 -1
- package/assets/{linear-DdadsTLS.js → linear-Chzx_9mb.js} +1 -1
- package/assets/{list-D3R3q3Ti.js → list-BuSdZ2Ic.js} +1 -1
- package/assets/{login-DwxC2WD6.js → login-DFWfnrmE.js} +1 -1
- package/assets/manifest.json +277 -277
- package/assets/media-manager-CT4LZgo_.js +7 -0
- package/assets/mermaid.core-Dp-0i8FJ.js +310 -0
- package/assets/{mindmap-definition-YA3MSWOX-BfdP8hOy.js → mindmap-definition-YA3MSWOX-BJSEYobY.js} +1 -1
- package/assets/{module-DKdDlng0.js → module-Cgn-q5gZ.js} +1 -1
- package/assets/{notification-DDWbaooT.js → notification-BrfoqVVT.js} +1 -1
- package/assets/{pegDiagram-XKGWAZYB-BO9cFGCI.js → pegDiagram-XKGWAZYB-ccVsKwl1.js} +1 -1
- package/assets/{pieDiagram-E7YTZNPT-B4KrTpto.js → pieDiagram-E7YTZNPT-B1XZVgNq.js} +1 -1
- package/assets/{quadrantDiagram-AXDQQJYC-BumScZvv.js → quadrantDiagram-AXDQQJYC-CdABEYmF.js} +1 -1
- package/assets/{railroadDiagram-O6MQD6OU-DUDQQC-p.js → railroadDiagram-O6MQD6OU-OX83MXuO.js} +1 -1
- package/assets/{register-5rs1OSaq.js → register-Cxf3Pow-.js} +1 -1
- package/assets/{requirementDiagram-BXWQKSXE-BtNsxNt1.js → requirementDiagram-BXWQKSXE-CD7swf9u.js} +1 -1
- package/assets/{ru-Cf1WWSt0.js → ru-DxiFV21N.js} +1 -1
- package/assets/{sankeyDiagram-P5KCCOFB-xjPcSTcN.js → sankeyDiagram-P5KCCOFB-Cgwq2DVJ.js} +1 -1
- package/assets/{sequenceDiagram-WJ2MYXX4-BVOgA3-B.js → sequenceDiagram-WJ2MYXX4-BgjP07Zh.js} +1 -1
- package/assets/{sizeCapture-INFHLROL-BDI5FsKO.js → sizeCapture-INFHLROL-B-jQ1aKT.js} +1 -1
- package/assets/{stateDiagram-D77RDMKH-DreIJby8.js → stateDiagram-D77RDMKH-Drot14NK.js} +1 -1
- package/assets/stateDiagram-v2-MP3YSRHH-C5VLF0H1.js +1 -0
- package/assets/{swimlanes-42K2YHIH-J_CNnPZv.js → swimlanes-42K2YHIH-lCqHhK1l.js} +1 -1
- package/assets/swimlanesDiagram-VR7AAH4N-4yyX1ZbA.js +8 -0
- package/assets/{timeline-definition-24CTP7MA-BXGN0YmT.js → timeline-definition-24CTP7MA-B-QLcvwc.js} +1 -1
- package/assets/{use-appearance-B2YFalXG.js → use-appearance-B0ck1CR_.js} +1 -1
- package/assets/{user-filters-list-D8WohjvX.js → user-filters-list-ce2cmS5Z.js} +1 -1
- package/assets/{vennDiagram-4TSXK5OY-Mu0lMKUo.js → vennDiagram-4TSXK5OY-2DN2uspP.js} +1 -1
- package/assets/{wardleyDiagram-VM6X3IG4-CXFMI74r.js → wardleyDiagram-VM6X3IG4-C_GODc0p.js} +1 -1
- package/assets/{welcome-DHQx7R11.js → welcome-DaAj6jOI.js} +1 -1
- package/assets/with-app-layout-CwAECGwY.js +34 -0
- package/assets/{xychartDiagram-S5SC5T6Z-DCr7j1YG.js → xychartDiagram-S5SC5T6Z-Cq8htGoW.js} +1 -1
- package/controllers/catalog/FrontendCatalogAdapter.d.ts +5 -5
- package/controllers/catalog/FrontentCatalogAdapter.d.ts +5 -5
- package/controllers/initUser.js +1 -1
- package/helpers/inertiaAddHelper.js +10 -1
- package/helpers/inertiaMenuHelper.d.ts +3 -2
- package/helpers/inertiaMenuHelper.js +9 -4
- package/helpers/navigationAccessHelper.d.ts +5 -0
- package/helpers/navigationAccessHelper.js +13 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/interfaces/adminpanelConfig.d.ts +7 -0
- package/lib/Adminizer.d.ts +2 -0
- package/lib/Adminizer.js +3 -0
- package/lib/admin-links/AdminLinkHandler.js +5 -1
- package/lib/app-manager/AdminizerApp.d.ts +34 -0
- package/lib/app-manager/AppManager.js +35 -0
- package/lib/app-manager/ContextHandler.d.ts +240 -0
- package/lib/app-manager/ContextHandler.js +446 -0
- package/lib/app-manager/ControllerHandler.d.ts +2 -0
- package/lib/app-manager/ControllerHandler.js +7 -0
- package/lib/media-manager/helpers/MediaManagerHelper.d.ts +1 -1
- package/lib/notifications/AbstractNotificationService.d.ts +3 -3
- package/package.json +3 -2
- package/system/bindDocs.js +1 -1
- package/system/bindInertia.js +34 -9
- package/assets/app-CRa5Kokq.js +0 -138
- package/assets/app-TCCHARSx.css +0 -1
- package/assets/channel-DRO88SVn.js +0 -1
- package/assets/classDiagram-ZZMXUADV-Cb-leHEm.js +0 -1
- package/assets/classDiagram-v2-VYDZK3BY-Cb-leHEm.js +0 -1
- package/assets/media-manager-mt4Ykki7.js +0 -6
- package/assets/mermaid.core-DxLHD4PF.js +0 -310
- package/assets/stateDiagram-v2-MP3YSRHH-BNzSJJYe.js +0 -1
- package/assets/swimlanesDiagram-VR7AAH4N-DN5N1rG7.js +0 -8
- package/assets/with-app-layout-Cvg36gxr.js +0 -31
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{s as pi,g as mi,o as $t,n as yi,a as bi,b as wi,_ as a,l as Ut,D as Ai,d as Ci,p as Si,y as Dt,i as Ri,A as Gt,B as _i,E as ki,aC as Ti,a9 as Xt}from"./mermaid.core-
|
|
1
|
+
import{s as pi,g as mi,o as $t,n as yi,a as bi,b as wi,_ as a,l as Ut,D as Ai,d as Ci,p as Si,y as Dt,i as Ri,A as Gt,B as _i,E as ki,aC as Ti,a9 as Xt}from"./mermaid.core-Dp-0i8FJ.js";import{i as Di}from"./init-Gi6I4Gst.js";import{o as Pi}from"./ordinal-Cboi1Yqb.js";import{l as Nt}from"./linear-Chzx_9mb.js";import"./app-DOMFUTFw.js";import"./isObject-DL-BuaBl.js";import"./defaultLocale-DX6XiGOO.js";function vi(e,t,i){e=+e,t=+t,i=(n=arguments.length)<2?(t=e,e=0,1):n<3?1:+i;for(var s=-1,n=Math.max(0,Math.ceil((t-e)/i))|0,o=new Array(n);++s<n;)o[s]=e+s*i;return o}function St(){var e=Pi().unknown(void 0),t=e.domain,i=e.range,s=0,n=1,o,h,p=!1,u=0,f=0,R=.5;delete e.unknown;function C(){var y=t().length,E=n<s,v=E?n:s,L=E?s:n;o=(L-v)/Math.max(1,y-u+f*2),p&&(o=Math.floor(o)),v+=(L-v-o*(y-u))*R,h=o*(1-u),p&&(v=Math.round(v),h=Math.round(h));var M=vi(y).map(function(b){return v+o*b});return i(E?M.reverse():M)}return e.domain=function(y){return arguments.length?(t(y),C()):t()},e.range=function(y){return arguments.length?([s,n]=y,s=+s,n=+n,C()):[s,n]},e.rangeRound=function(y){return[s,n]=y,s=+s,n=+n,p=!0,C()},e.bandwidth=function(){return h},e.step=function(){return o},e.round=function(y){return arguments.length?(p=!!y,C()):p},e.padding=function(y){return arguments.length?(u=Math.min(1,f=+y),C()):u},e.paddingInner=function(y){return arguments.length?(u=Math.min(1,y),C()):u},e.paddingOuter=function(y){return arguments.length?(f=+y,C()):f},e.align=function(y){return arguments.length?(R=Math.max(0,Math.min(1,y)),C()):R},e.copy=function(){return St(t(),[s,n]).round(p).paddingInner(u).paddingOuter(f).align(R)},Di.apply(C(),arguments)}var Rt=(function(){var e=a(function(W,l,g,d){for(g=g||{},d=W.length;d--;g[W[d]]=l);return g},"o"),t=[1,10,12,14,16,18,19,21,23],i=[2,6],s=[1,3],n=[1,5],o=[1,6],h=[1,7],p=[1,5,10,12,14,16,18,19,21,23,36,37,38],u=[1,25],f=[1,26],R=[1,28],C=[1,29],y=[1,30],E=[1,31],v=[1,32],L=[1,33],M=[1,34],b=[1,35],D=[1,36],c=[1,37],z=[1,43],F=[1,42],X=[1,47],N=[1,50],k=[1,10,12,14,16,18,19,21,23,36,37,38],H=[1,10,12,14,16,18,19,21,23,24,26,28,29,36,37,38],A=[1,10,12,14,16,18,19,21,23,24,26,28,29,36,37,38,42,43,44,45,46,47,48,49,50,51],S=[1,65],O=[26,28],T={trace:a(function(){},"trace"),yy:{},symbols_:{error:2,start:3,eol:4,XYCHART:5,chartConfig:6,document:7,CHART_ORIENTATION:8,statement:9,title:10,text:11,X_AXIS:12,parseXAxis:13,Y_AXIS:14,parseYAxis:15,LINE:16,plotData:17,BAR:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,SQUARE_BRACES_START:24,dataPoints:25,SQUARE_BRACES_END:26,dataPoint:27,COMMA:28,NUMBER_WITH_DECIMAL:29,STR:30,xAxisData:31,bandData:32,ARROW_DELIMITER:33,commaSeparatedTexts:34,yAxisData:35,NEWLINE:36,SEMI:37,EOF:38,alphaNum:39,MD_STR:40,alphaNumToken:41,AMP:42,NUM:43,ALPHA:44,PLUS:45,EQUALS:46,MULT:47,DOT:48,BRKT:49,MINUS:50,UNDERSCORE:51,$accept:0,$end:1},terminals_:{2:"error",5:"XYCHART",8:"CHART_ORIENTATION",10:"title",12:"X_AXIS",14:"Y_AXIS",16:"LINE",18:"BAR",19:"acc_title",20:"acc_title_value",21:"acc_descr",22:"acc_descr_value",23:"acc_descr_multiline_value",24:"SQUARE_BRACES_START",26:"SQUARE_BRACES_END",28:"COMMA",29:"NUMBER_WITH_DECIMAL",30:"STR",33:"ARROW_DELIMITER",36:"NEWLINE",37:"SEMI",38:"EOF",40:"MD_STR",42:"AMP",43:"NUM",44:"ALPHA",45:"PLUS",46:"EQUALS",47:"MULT",48:"DOT",49:"BRKT",50:"MINUS",51:"UNDERSCORE"},productions_:[0,[3,2],[3,3],[3,2],[3,1],[6,1],[7,0],[7,2],[9,2],[9,2],[9,2],[9,2],[9,2],[9,3],[9,2],[9,3],[9,2],[9,2],[9,1],[17,3],[25,3],[25,1],[27,2],[27,1],[13,1],[13,2],[13,1],[31,1],[31,3],[32,3],[34,3],[34,1],[15,1],[15,2],[15,1],[35,3],[4,1],[4,1],[4,1],[11,1],[11,1],[11,1],[39,1],[39,2],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1],[41,1]],performAction:a(function(l,g,d,x,_,r,lt){var m=r.length-1;switch(_){case 5:x.setOrientation(r[m]);break;case 9:x.setDiagramTitle(r[m].text.trim());break;case 12:x.setLineData({text:"",type:"text"},r[m]);break;case 13:x.setLineData(r[m-1],r[m]);break;case 14:x.setBarData({text:"",type:"text"},r[m]);break;case 15:x.setBarData(r[m-1],r[m]);break;case 16:this.$=r[m].trim(),x.setAccTitle(this.$);break;case 17:case 18:this.$=r[m].trim(),x.setAccDescription(this.$);break;case 19:this.$=r[m-1];break;case 20:case 30:this.$=[r[m-2],...r[m]];break;case 21:case 31:this.$=[r[m]];break;case 22:this.$={value:Number(r[m-1]),label:r[m]};break;case 23:this.$={value:Number(r[m]),label:""};break;case 24:x.setXAxisTitle(r[m]);break;case 25:x.setXAxisTitle(r[m-1]);break;case 26:x.setXAxisTitle({type:"text",text:""});break;case 27:x.setXAxisBand(r[m]);break;case 28:x.setXAxisRangeData(Number(r[m-2]),Number(r[m]));break;case 29:this.$=r[m-1];break;case 32:x.setYAxisTitle(r[m]);break;case 33:x.setYAxisTitle(r[m-1]);break;case 34:x.setYAxisTitle({type:"text",text:""});break;case 35:x.setYAxisRangeData(Number(r[m-2]),Number(r[m]));break;case 39:this.$={text:r[m],type:"text"};break;case 40:this.$={text:r[m],type:"text"};break;case 41:this.$={text:r[m],type:"markdown"};break;case 42:this.$=r[m];break;case 43:this.$=r[m-1]+""+r[m];break}},"anonymous"),table:[e(t,i,{3:1,4:2,7:4,5:s,36:n,37:o,38:h}),{1:[3]},e(t,i,{4:2,7:4,3:8,5:s,36:n,37:o,38:h}),e(t,i,{4:2,7:4,6:9,3:10,5:s,8:[1,11],36:n,37:o,38:h}),{1:[2,4],9:12,10:[1,13],12:[1,14],14:[1,15],16:[1,16],18:[1,17],19:[1,18],21:[1,19],23:[1,20]},e(p,[2,36]),e(p,[2,37]),e(p,[2,38]),{1:[2,1]},e(t,i,{4:2,7:4,3:21,5:s,36:n,37:o,38:h}),{1:[2,3]},e(p,[2,5]),e(t,[2,7],{4:22,36:n,37:o,38:h}),{11:23,30:u,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},{11:39,13:38,24:z,29:F,30:u,31:40,32:41,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},{11:45,15:44,29:X,30:u,35:46,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},{11:49,17:48,24:N,30:u,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},{11:52,17:51,24:N,30:u,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},{20:[1,53]},{22:[1,54]},e(k,[2,18]),{1:[2,2]},e(k,[2,8]),e(k,[2,9]),e(H,[2,39],{41:55,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c}),e(H,[2,40]),e(H,[2,41]),e(A,[2,42]),e(A,[2,44]),e(A,[2,45]),e(A,[2,46]),e(A,[2,47]),e(A,[2,48]),e(A,[2,49]),e(A,[2,50]),e(A,[2,51]),e(A,[2,52]),e(A,[2,53]),e(k,[2,10]),e(k,[2,24],{32:41,31:56,24:z,29:F}),e(k,[2,26]),e(k,[2,27]),{33:[1,57]},{11:59,30:u,34:58,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},e(k,[2,11]),e(k,[2,32],{35:60,29:X}),e(k,[2,34]),{33:[1,61]},e(k,[2,12]),{17:62,24:N},{25:63,27:64,29:S},e(k,[2,14]),{17:66,24:N},e(k,[2,16]),e(k,[2,17]),e(A,[2,43]),e(k,[2,25]),{29:[1,67]},{26:[1,68]},{26:[2,31],28:[1,69]},e(k,[2,33]),{29:[1,70]},e(k,[2,13]),{26:[1,71]},{26:[2,21],28:[1,72]},e(O,[2,23],{30:[1,73]}),e(k,[2,15]),e(k,[2,28]),e(k,[2,29]),{11:59,30:u,34:74,39:24,40:f,41:27,42:R,43:C,44:y,45:E,46:v,47:L,48:M,49:b,50:D,51:c},e(k,[2,35]),e(k,[2,19]),{25:75,27:64,29:S},e(O,[2,22]),{26:[2,30]},{26:[2,20]}],defaultActions:{8:[2,1],10:[2,3],21:[2,2],74:[2,30],75:[2,20]},parseError:a(function(l,g){if(g.recoverable)this.trace(l);else{var d=new Error(l);throw d.hash=g,d}},"parseError"),parse:a(function(l){var g=this,d=[0],x=[],_=[null],r=[],lt=this.table,m="",dt=0,Ot=0,ui=2,Vt=1,di=r.slice.call(arguments,1),P=Object.create(this.lexer),$={yy:{}};for(var bt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,bt)&&($.yy[bt]=this.yy[bt]);P.setInput(l,$.yy),$.yy.lexer=P,$.yy.parser=this,typeof P.yylloc>"u"&&(P.yylloc={});var wt=P.yylloc;r.push(wt);var xi=P.options&&P.options.ranges;typeof $.yy.parseError=="function"?this.parseError=$.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function fi(B){d.length=d.length-2*B,_.length=_.length-B,r.length=r.length-B}a(fi,"popStack");function Ft(){var B;return B=x.pop()||P.lex()||Vt,typeof B!="number"&&(B instanceof Array&&(x=B,B=x.pop()),B=g.symbols_[B]||B),B}a(Ft,"lex");for(var I,U,V,At,j={},xt,Y,Wt,ft;;){if(U=d[d.length-1],this.defaultActions[U]?V=this.defaultActions[U]:((I===null||typeof I>"u")&&(I=Ft()),V=lt[U]&<[U][I]),typeof V>"u"||!V.length||!V[0]){var Ct="";ft=[];for(xt in lt[U])this.terminals_[xt]&&xt>ui&&ft.push("'"+this.terminals_[xt]+"'");P.showPosition?Ct="Parse error on line "+(dt+1)+`:
|
|
2
2
|
`+P.showPosition()+`
|
|
3
3
|
Expecting `+ft.join(", ")+", got '"+(this.terminals_[I]||I)+"'":Ct="Parse error on line "+(dt+1)+": Unexpected "+(I==Vt?"end of input":"'"+(this.terminals_[I]||I)+"'"),this.parseError(Ct,{text:P.match,token:this.terminals_[I]||I,line:P.yylineno,loc:wt,expected:ft})}if(V[0]instanceof Array&&V.length>1)throw new Error("Parse Error: multiple actions possible at state: "+U+", token: "+I);switch(V[0]){case 1:d.push(I),_.push(P.yytext),r.push(P.yylloc),d.push(V[1]),I=null,Ot=P.yyleng,m=P.yytext,dt=P.yylineno,wt=P.yylloc;break;case 2:if(Y=this.productions_[V[1]][1],j.$=_[_.length-Y],j._$={first_line:r[r.length-(Y||1)].first_line,last_line:r[r.length-1].last_line,first_column:r[r.length-(Y||1)].first_column,last_column:r[r.length-1].last_column},xi&&(j._$.range=[r[r.length-(Y||1)].range[0],r[r.length-1].range[1]]),At=this.performAction.apply(j,[m,Ot,dt,$.yy,V[1],_,r].concat(di)),typeof At<"u")return At;Y&&(d=d.slice(0,-1*Y*2),_=_.slice(0,-1*Y),r=r.slice(0,-1*Y)),d.push(this.productions_[V[1]][0]),_.push(j.$),r.push(j._$),Wt=lt[d[d.length-2]][d[d.length-1]],d.push(Wt);break;case 3:return!0}}return!0},"parse")},ht=(function(){var W={EOF:1,parseError:a(function(g,d){if(this.yy.parser)this.yy.parser.parseError(g,d);else throw new Error(g)},"parseError"),setInput:a(function(l,g){return this.yy=g||this.yy||{},this._input=l,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:a(function(){var l=this._input[0];this.yytext+=l,this.yyleng++,this.offset++,this.match+=l,this.matched+=l;var g=l.match(/(?:\r\n?|\n).*/g);return g?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),l},"input"),unput:a(function(l){var g=l.length,d=l.split(/(?:\r\n?|\n)/g);this._input=l+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-g),this.offset-=g;var x=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),d.length-1&&(this.yylineno-=d.length-1);var _=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:d?(d.length===x.length?this.yylloc.first_column:0)+x[x.length-d.length].length-d[0].length:this.yylloc.first_column-g},this.options.ranges&&(this.yylloc.range=[_[0],_[0]+this.yyleng-g]),this.yyleng=this.yytext.length,this},"unput"),more:a(function(){return this._more=!0,this},"more"),reject:a(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
|
|
4
4
|
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:a(function(l){this.unput(this.match.slice(l))},"less"),pastInput:a(function(){var l=this.matched.substr(0,this.matched.length-this.match.length);return(l.length>20?"...":"")+l.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:a(function(){var l=this.match;return l.length<20&&(l+=this._input.substr(0,20-l.length)),(l.substr(0,20)+(l.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:a(function(){var l=this.pastInput(),g=new Array(l.length+1).join("-");return l+this.upcomingInput()+`
|
|
@@ -27,21 +27,21 @@ export declare class FrontendCatalog {
|
|
|
27
27
|
catalog: AbstractCatalog;
|
|
28
28
|
constructor(_catalog: AbstractCatalog);
|
|
29
29
|
setId(id: string): void;
|
|
30
|
-
getItemType(type: string): import("
|
|
31
|
-
getAddTemplate(item: any, req: ReqType): Promise<import("
|
|
32
|
-
getEditTemplate(item: any, id: string | number, req: ReqType, modelId: string | number): Promise<import("
|
|
30
|
+
getItemType(type: string): import("../../index.js").BaseItem<Item>;
|
|
31
|
+
getAddTemplate(item: any, req: ReqType): Promise<import("../../index.js").CatalogTemplate<any>>;
|
|
32
|
+
getEditTemplate(item: any, id: string | number, req: ReqType, modelId: string | number): Promise<import("../../index.js").CatalogTemplate<any>>;
|
|
33
33
|
getitemTypes(): {
|
|
34
34
|
type: string;
|
|
35
35
|
name: string;
|
|
36
36
|
isGroup: boolean;
|
|
37
37
|
allowedRoot: boolean;
|
|
38
38
|
icon: string;
|
|
39
|
-
actionHandlers: import("
|
|
39
|
+
actionHandlers: import("../../index.js").ActionHandler[];
|
|
40
40
|
}[];
|
|
41
41
|
getLocales(req: ReqType): {
|
|
42
42
|
[key: string]: string;
|
|
43
43
|
};
|
|
44
|
-
getActions(items: NodeModel<any>[], type: string): Promise<import("
|
|
44
|
+
getActions(items: NodeModel<any>[], type: string): Promise<import("../../index.js").ActionHandler[]>;
|
|
45
45
|
handleAction(actionId: string, items: any[], data: any, req: ReqType): Promise<string | void>;
|
|
46
46
|
getPopUpTemplate(actionId: string, req: ReqType): Promise<string>;
|
|
47
47
|
getLink(actionId: string): Promise<string>;
|
|
@@ -27,21 +27,21 @@ export declare class FrontendCatalog {
|
|
|
27
27
|
catalog: AbstractCatalog;
|
|
28
28
|
constructor(_catalog: AbstractCatalog);
|
|
29
29
|
setId(id: string): void;
|
|
30
|
-
getItemType(type: string): import("
|
|
31
|
-
getAddTemplate(item: any, req: ReqType): Promise<import("
|
|
32
|
-
getEditTemplate(item: any, id: string | number, req: ReqType, modelId: string | number): Promise<import("
|
|
30
|
+
getItemType(type: string): import("../../index.js").BaseItem<Item>;
|
|
31
|
+
getAddTemplate(item: any, req: ReqType): Promise<import("../../index.js").CatalogTemplate<any>>;
|
|
32
|
+
getEditTemplate(item: any, id: string | number, req: ReqType, modelId: string | number): Promise<import("../../index.js").CatalogTemplate<any>>;
|
|
33
33
|
getitemTypes(): {
|
|
34
34
|
type: string;
|
|
35
35
|
name: string;
|
|
36
36
|
isGroup: boolean;
|
|
37
37
|
allowedRoot: boolean;
|
|
38
38
|
icon: string;
|
|
39
|
-
actionHandlers: import("
|
|
39
|
+
actionHandlers: import("../../index.js").ActionHandler[];
|
|
40
40
|
}[];
|
|
41
41
|
getLocales(req: ReqType): {
|
|
42
42
|
[key: string]: string;
|
|
43
43
|
};
|
|
44
|
-
getActions(items: NodeModel<any>[], type: string): Promise<import("
|
|
44
|
+
getActions(items: NodeModel<any>[], type: string): Promise<import("../../index.js").ActionHandler[]>;
|
|
45
45
|
handleAction(actionId: string, items: any[], data: any, req: ReqType): Promise<string | void>;
|
|
46
46
|
getPopUpTemplate(actionId: string, req: ReqType): Promise<string>;
|
|
47
47
|
getLink(actionId: string): Promise<string>;
|
package/controllers/initUser.js
CHANGED
|
@@ -9,7 +9,7 @@ export default async function initUser(req, res) {
|
|
|
9
9
|
const userModel = req.adminizer.modelHandler.internal("auth").get("User");
|
|
10
10
|
let admins = await userModel.find({ where: { isAdministrator: true } });
|
|
11
11
|
if (admins.length) {
|
|
12
|
-
res.redirect(`${req.adminizer.config.routePrefix}/model/User/login`);
|
|
12
|
+
return res.redirect(`${req.adminizer.config.routePrefix}/model/User/login`);
|
|
13
13
|
}
|
|
14
14
|
if (req.method.toUpperCase() === "POST") {
|
|
15
15
|
let login = req.body.login;
|
|
@@ -2,6 +2,7 @@ import inertiaActionsHelper from "./inertiaActionsHelper.js";
|
|
|
2
2
|
import { isObject } from "./JsUtils.js";
|
|
3
3
|
import { withAssetVersion } from "./assetVersionHelper.js";
|
|
4
4
|
import { Adminizer } from "../lib/Adminizer.js";
|
|
5
|
+
import { isBlockedLink } from "./navigationAccessHelper.js";
|
|
5
6
|
const missingControlWarnings = new Set();
|
|
6
7
|
/**
|
|
7
8
|
* Get ISO week number from date
|
|
@@ -123,8 +124,11 @@ export default async function inertiaAddHelper(req, modelResource, fields, recor
|
|
|
123
124
|
options = initOptions;
|
|
124
125
|
value = initValue;
|
|
125
126
|
const rawRelatedModel = (field.model?.model || field.model?.collection);
|
|
127
|
+
// `model`/`collection` is the host ORM model name, not an Adminizer resource name:
|
|
128
|
+
// resolve it the same way FieldsHelper.loadAssoc does, otherwise a host model that
|
|
129
|
+
// shares its name with a system resource (group -> Group, user -> User) opens the wrong form
|
|
126
130
|
relatedModel = rawRelatedModel
|
|
127
|
-
? req.adminizer.modelHandler.
|
|
131
|
+
? req.adminizer.modelHandler.resolveAssociationResource(rawRelatedModel, field.model?.resourceName)
|
|
128
132
|
: undefined;
|
|
129
133
|
if (relatedModel && req.user) {
|
|
130
134
|
canCreateRelated = await req.adminizer.accessRightsHelper.checkPermission(`create-${relatedModel}-model`, req.user);
|
|
@@ -132,6 +136,11 @@ export default async function inertiaAddHelper(req, modelResource, fields, recor
|
|
|
132
136
|
else if (relatedModel && !req.adminizer.config.auth?.enable) {
|
|
133
137
|
canCreateRelated = true;
|
|
134
138
|
}
|
|
139
|
+
// The create form of a model declared to belong to a layout context
|
|
140
|
+
// the user may not enter answers 403
|
|
141
|
+
if (canCreateRelated && relatedModel && await isBlockedLink(req.adminizer, req.user, `${req.adminizer.config.routePrefix}/model/${relatedModel}/add`)) {
|
|
142
|
+
canCreateRelated = false;
|
|
143
|
+
}
|
|
135
144
|
}
|
|
136
145
|
if (type === 'select-many') {
|
|
137
146
|
fieldType = 'select-many';
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { Adminizer } from "../lib/Adminizer.js";
|
|
2
2
|
import { NavbarSectionConfig } from "../interfaces/adminpanelConfig.js";
|
|
3
3
|
import { MenuItem } from "./menuHelper.js";
|
|
4
|
+
import type { AdminContext } from "../lib/app-manager/ContextHandler.js";
|
|
4
5
|
export declare class InertiaMenuHelper {
|
|
5
6
|
private adminizer;
|
|
6
7
|
constructor(adminizer: Adminizer);
|
|
7
|
-
getMenuItems(req: ReqType): Promise<MenuItem[]>;
|
|
8
|
+
getMenuItems(req: ReqType, context?: AdminContext): Promise<MenuItem[]>;
|
|
8
9
|
private translateMenuItem;
|
|
9
10
|
private translateHrefItem;
|
|
10
11
|
/**
|
|
11
12
|
* Navbar section metadata keyed by the *translated* section name, so the UI
|
|
12
13
|
* can look it up with the already-translated `section` of a menu item.
|
|
13
14
|
*/
|
|
14
|
-
getSections(req: ReqType): Record<string, NavbarSectionConfig>;
|
|
15
|
+
getSections(req: ReqType, context?: AdminContext): Record<string, NavbarSectionConfig>;
|
|
15
16
|
getBrandTitle(): string;
|
|
16
17
|
getLogoutUrl(): string;
|
|
17
18
|
}
|
|
@@ -4,8 +4,11 @@ export class InertiaMenuHelper {
|
|
|
4
4
|
constructor(adminizer) {
|
|
5
5
|
this.adminizer = adminizer;
|
|
6
6
|
}
|
|
7
|
-
async getMenuItems(req) {
|
|
8
|
-
|
|
7
|
+
async getMenuItems(req, context) {
|
|
8
|
+
const items = context
|
|
9
|
+
? await this.adminizer.contextHandler.listMenuItems(context, req.user)
|
|
10
|
+
: await listAccessibleMenuItems(this.adminizer, req.user);
|
|
11
|
+
return items
|
|
9
12
|
.map((menuItem) => this.translateMenuItem(req, menuItem));
|
|
10
13
|
}
|
|
11
14
|
translateMenuItem(req, menuItem) {
|
|
@@ -28,8 +31,10 @@ export class InertiaMenuHelper {
|
|
|
28
31
|
* Navbar section metadata keyed by the *translated* section name, so the UI
|
|
29
32
|
* can look it up with the already-translated `section` of a menu item.
|
|
30
33
|
*/
|
|
31
|
-
getSections(req) {
|
|
32
|
-
const sections =
|
|
34
|
+
getSections(req, context) {
|
|
35
|
+
const sections = context
|
|
36
|
+
? this.adminizer.contextHandler.getSections(context)
|
|
37
|
+
: this.adminizer.menuHelper.getSections();
|
|
33
38
|
return Object.fromEntries(Object.entries(sections).map(([name, section]) => [req.i18n.__(name), section]));
|
|
34
39
|
}
|
|
35
40
|
getBrandTitle() {
|
|
@@ -2,6 +2,11 @@ import type { HrefConfig, MenuBadge } from '../interfaces/adminpanelConfig.js';
|
|
|
2
2
|
import { Adminizer } from '../lib/Adminizer.js';
|
|
3
3
|
import type { User } from '../models/User.js';
|
|
4
4
|
import type { MenuItem } from './menuHelper.js';
|
|
5
|
+
/**
|
|
6
|
+
* True for a link to a page of a layout context this user may not enter
|
|
7
|
+
* (`context` of a model or a route): the page would answer 403.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isBlockedLink(adminizer: Adminizer, user: User | undefined, link: unknown): Promise<boolean>;
|
|
5
10
|
/** Drops the sub-items this user may not open, recursively. */
|
|
6
11
|
export declare function filterAccessibleHrefItems(adminizer: Adminizer, user: User, items: HrefConfig[]): Promise<HrefConfig[]>;
|
|
7
12
|
/**
|
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { Adminizer } from '../lib/Adminizer.js';
|
|
2
|
+
/**
|
|
3
|
+
* True for a link to a page of a layout context this user may not enter
|
|
4
|
+
* (`context` of a model or a route): the page would answer 403.
|
|
5
|
+
*/
|
|
6
|
+
export async function isBlockedLink(adminizer, user, link) {
|
|
7
|
+
// Partial Adminizer stand-ins (tests) may come without contexts.
|
|
8
|
+
return typeof link === 'string' && !!adminizer.contextHandler && await adminizer.contextHandler.isBlocked(link, user);
|
|
9
|
+
}
|
|
2
10
|
/** Drops the sub-items this user may not open, recursively. */
|
|
3
11
|
export async function filterAccessibleHrefItems(adminizer, user, items) {
|
|
4
12
|
const accessible = [];
|
|
@@ -6,6 +14,9 @@ export async function filterAccessibleHrefItems(adminizer, user, items) {
|
|
|
6
14
|
if (item.accessRightsToken && !await adminizer.accessRightsHelper.checkPermission(item.accessRightsToken, user)) {
|
|
7
15
|
continue;
|
|
8
16
|
}
|
|
17
|
+
if (await isBlockedLink(adminizer, user, item.link)) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
9
20
|
accessible.push({
|
|
10
21
|
...item,
|
|
11
22
|
subItems: item.subItems ? await filterAccessibleHrefItems(adminizer, user, item.subItems) : item.subItems,
|
|
@@ -39,6 +50,8 @@ export async function resolveMenuBadge(user, badge, itemId) {
|
|
|
39
50
|
export async function listAccessibleMenuItems(adminizer, user) {
|
|
40
51
|
const menu = [];
|
|
41
52
|
for (const menuItem of adminizer.menuHelper.getMenuItems(user)) {
|
|
53
|
+
if (await isBlockedLink(adminizer, user, menuItem.link))
|
|
54
|
+
continue;
|
|
42
55
|
const actions = await filterAccessibleHrefItems(adminizer, user, menuItem.actions ?? []);
|
|
43
56
|
const tokens = actions.map((item) => item.accessRightsToken).filter(Boolean);
|
|
44
57
|
if (menuItem.accessRightsToken)
|
package/index.d.ts
CHANGED
|
@@ -64,6 +64,7 @@ export * from "./lib/app-manager/AdminizerApp.js";
|
|
|
64
64
|
export * from "./lib/app-manager/AppManager.js";
|
|
65
65
|
export * from "./lib/app-manager/ControllerHandler.js";
|
|
66
66
|
export * from "./lib/app-manager/AssetHandler.js";
|
|
67
|
+
export * from "./lib/app-manager/ContextHandler.js";
|
|
67
68
|
export * from "./lib/app-manager/ConfigLayerHandler.js";
|
|
68
69
|
export * from "./lib/access-rights/AccessRightsHandler.js";
|
|
69
70
|
export * from "./lib/media-manager/helpers/MediaManagerHelper.js";
|
package/index.js
CHANGED
|
@@ -64,6 +64,7 @@ export * from "./lib/app-manager/AdminizerApp.js";
|
|
|
64
64
|
export * from "./lib/app-manager/AppManager.js";
|
|
65
65
|
export * from "./lib/app-manager/ControllerHandler.js";
|
|
66
66
|
export * from "./lib/app-manager/AssetHandler.js";
|
|
67
|
+
export * from "./lib/app-manager/ContextHandler.js";
|
|
67
68
|
export * from "./lib/app-manager/ConfigLayerHandler.js";
|
|
68
69
|
export * from "./lib/access-rights/AccessRightsHandler.js";
|
|
69
70
|
export * from "./lib/media-manager/helpers/MediaManagerHelper.js";
|
|
@@ -372,6 +372,13 @@ export interface ModelConfig {
|
|
|
372
372
|
*/
|
|
373
373
|
section?: string;
|
|
374
374
|
};
|
|
375
|
+
/**
|
|
376
|
+
* Id of the layout context the model's pages (`/model/<name>/...`) belong
|
|
377
|
+
* to: they render in that context, and users who may not enter it get 403
|
|
378
|
+
* on every one of them, related-record dialogs included (404 when no such
|
|
379
|
+
* context is registered). Left out, the pages behave as before.
|
|
380
|
+
*/
|
|
381
|
+
context?: string;
|
|
375
382
|
/**
|
|
376
383
|
* Model resource fields configuration
|
|
377
384
|
* */
|
package/lib/Adminizer.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ import { FeedbackHandler } from "./feedback/FeedbackHandler.js";
|
|
|
25
25
|
import { AppManager } from "./app-manager/AppManager.js";
|
|
26
26
|
import { ControllerHandler } from "./app-manager/ControllerHandler.js";
|
|
27
27
|
import { AssetHandler } from "./app-manager/AssetHandler.js";
|
|
28
|
+
import { ContextHandler } from "./app-manager/ContextHandler.js";
|
|
28
29
|
import { ConfigLayerHandler } from "./app-manager/ConfigLayerHandler.js";
|
|
29
30
|
import { AccessRightsHandler } from "./access-rights/AccessRightsHandler.js";
|
|
30
31
|
import { AiAssistantUiMethodHandler } from './ai-assistant/AiAssistantUiMethodHandler.js';
|
|
@@ -74,6 +75,7 @@ export declare class Adminizer {
|
|
|
74
75
|
appManager: AppManager;
|
|
75
76
|
controllerHandler: ControllerHandler;
|
|
76
77
|
assetHandler: AssetHandler;
|
|
78
|
+
contextHandler: ContextHandler;
|
|
77
79
|
configLayerHandler: ConfigLayerHandler;
|
|
78
80
|
accessRightsHandler: AccessRightsHandler;
|
|
79
81
|
jwtSecret: string;
|
package/lib/Adminizer.js
CHANGED
|
@@ -42,6 +42,7 @@ import { validateAccessGraph } from "./access-graph/AccessGraphResolver.js";
|
|
|
42
42
|
import { AppManager } from "./app-manager/AppManager.js";
|
|
43
43
|
import { ControllerHandler } from "./app-manager/ControllerHandler.js";
|
|
44
44
|
import { AssetHandler } from "./app-manager/AssetHandler.js";
|
|
45
|
+
import { ContextHandler } from "./app-manager/ContextHandler.js";
|
|
45
46
|
import { ConfigLayerHandler } from "./app-manager/ConfigLayerHandler.js";
|
|
46
47
|
import { AccessRightsHandler } from "./access-rights/AccessRightsHandler.js";
|
|
47
48
|
import { AiAssistantUiMethodHandler } from './ai-assistant/AiAssistantUiMethodHandler.js';
|
|
@@ -131,6 +132,7 @@ export class Adminizer {
|
|
|
131
132
|
appManager;
|
|
132
133
|
controllerHandler;
|
|
133
134
|
assetHandler;
|
|
135
|
+
contextHandler;
|
|
134
136
|
configLayerHandler;
|
|
135
137
|
accessRightsHandler;
|
|
136
138
|
// Constants
|
|
@@ -157,6 +159,7 @@ export class Adminizer {
|
|
|
157
159
|
this.documentationHandler = new DocumentationHandler(this, () => bindDocs(this));
|
|
158
160
|
this.controllerHandler = new ControllerHandler(this);
|
|
159
161
|
this.assetHandler = new AssetHandler(this);
|
|
162
|
+
this.contextHandler = new ContextHandler(this);
|
|
160
163
|
this.configLayerHandler = new ConfigLayerHandler(this);
|
|
161
164
|
this.appManager = new AppManager(this);
|
|
162
165
|
// Registering or unregistering a model changes what the record-access resolvers may
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { listAccessibleMenuItems } from '../../helpers/navigationAccessHelper.js';
|
|
1
|
+
import { isBlockedLink, listAccessibleMenuItems } from '../../helpers/navigationAccessHelper.js';
|
|
2
2
|
import { matchesPathPattern } from '../../helpers/pathPattern.js';
|
|
3
3
|
import { isModelHiddenInNavbar } from '../../helpers/menuHelper.js';
|
|
4
4
|
/** Segments no template may point at: opening one mutates data. */
|
|
@@ -43,6 +43,8 @@ export class AdminLinkHandler {
|
|
|
43
43
|
continue;
|
|
44
44
|
if (link.accessRightsToken && !await this.adminizer.accessRightsHelper.checkPermission(link.accessRightsToken, user))
|
|
45
45
|
continue;
|
|
46
|
+
if (await isBlockedLink(this.adminizer, user, link.link))
|
|
47
|
+
continue;
|
|
46
48
|
accessible.push(link);
|
|
47
49
|
}
|
|
48
50
|
return accessible;
|
|
@@ -88,6 +90,8 @@ export class AdminLinkHandler {
|
|
|
88
90
|
return;
|
|
89
91
|
if (template.accessRightsToken && !await this.adminizer.accessRightsHelper.checkPermission(template.accessRightsToken, user))
|
|
90
92
|
return;
|
|
93
|
+
if (await isBlockedLink(this.adminizer, user, template.template))
|
|
94
|
+
return;
|
|
91
95
|
if (templates.some((existing) => existing.template === template.template || existing.id === template.id))
|
|
92
96
|
return;
|
|
93
97
|
templates.push(template);
|
|
@@ -11,6 +11,7 @@ import type { AbstractAiModelService } from "../ai-assistant/AbstractAiModelServ
|
|
|
11
11
|
import type { AiAssistantUiMethod } from '../ai-assistant/AiAssistantUiMethodHandler.js';
|
|
12
12
|
import type { AdminLink, AdminLinkTemplate } from '../admin-links/AdminLinkHandler.js';
|
|
13
13
|
import type { AiAssistantAgentSkill } from '../ai-assistant/AiAssistantAgentSkillHandler.js';
|
|
14
|
+
import type { AdminContext, AdminContextScope } from './ContextHandler.js';
|
|
14
15
|
export type AppDisposer = () => void | Promise<void>;
|
|
15
16
|
export type AppEventName = string | symbol;
|
|
16
17
|
export type AppEventHandler<TPayload = any> = (payload: TPayload, runtime: AppRuntime) => void | Promise<void>;
|
|
@@ -49,6 +50,12 @@ export interface AppController {
|
|
|
49
50
|
method: AppControllerMethod;
|
|
50
51
|
middleware: MiddlewareType;
|
|
51
52
|
policies?: AppControllerPolicy[];
|
|
53
|
+
/**
|
|
54
|
+
* Id of the layout context the route belongs to: it renders in that
|
|
55
|
+
* context, and users who may not enter it get 403 (404 when no such
|
|
56
|
+
* context is registered). Left out, the route behaves as before.
|
|
57
|
+
*/
|
|
58
|
+
context?: string;
|
|
52
59
|
}
|
|
53
60
|
export interface AppAsset {
|
|
54
61
|
id: string;
|
|
@@ -209,6 +216,28 @@ export interface AppSkills {
|
|
|
209
216
|
}
|
|
210
217
|
export interface AppAdminLinkResource extends AdminLink {
|
|
211
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* A layout context owned by an app. Unlike {@link AdminContext}, layout
|
|
221
|
+
* modules are given as app assets; they are served and disposed with the app.
|
|
222
|
+
*/
|
|
223
|
+
export interface AppContextResource extends Omit<AdminContext, "layout"> {
|
|
224
|
+
layout?: "inherit" | "stock" | "none" | "default" | "bare" | {
|
|
225
|
+
module: AppAsset;
|
|
226
|
+
stylesheet?: AppAsset;
|
|
227
|
+
base?: "inherit" | "stock";
|
|
228
|
+
} | {
|
|
229
|
+
overrides: AppAsset;
|
|
230
|
+
stylesheet?: AppAsset;
|
|
231
|
+
} | {
|
|
232
|
+
component: AppAsset;
|
|
233
|
+
stylesheet?: AppAsset;
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* A context registered by an app. Pages may give their component as an app
|
|
238
|
+
* asset; pages and routes are removed together with the app.
|
|
239
|
+
*/
|
|
240
|
+
export type AppContextScope = AdminContextScope<AppAsset | string>;
|
|
212
241
|
export interface AppAdminLinkTemplateResource extends AdminLinkTemplate {
|
|
213
242
|
}
|
|
214
243
|
/**
|
|
@@ -236,6 +265,11 @@ export interface AppSetupContext {
|
|
|
236
265
|
adminLink(link: AppAdminLinkResource): void;
|
|
237
266
|
/** Register a parametrized page (e.g. `/admin/orders/:id/invoice`) the assistant may open. */
|
|
238
267
|
adminLinkTemplate(template: AppAdminLinkTemplateResource): void;
|
|
268
|
+
/**
|
|
269
|
+
* Register a layout context: own URL prefix, navbar and, optionally,
|
|
270
|
+
* layout. The returned scope adds pages to it.
|
|
271
|
+
*/
|
|
272
|
+
context(context: AppContextResource): AppContextScope;
|
|
239
273
|
listener(event: AppEventName, handler: AppEventHandler): void;
|
|
240
274
|
}
|
|
241
275
|
/**
|
|
@@ -14,6 +14,8 @@ class RuntimeAppSetupContext {
|
|
|
14
14
|
pendingCatalogRegistrations = [];
|
|
15
15
|
configLayerIndex = 0;
|
|
16
16
|
modelAccessIndex = 0;
|
|
17
|
+
/** Asset URLs of context page components, by asset id. */
|
|
18
|
+
pageComponents = new Map();
|
|
17
19
|
constructor(adminizer, appName) {
|
|
18
20
|
this.adminizer = adminizer;
|
|
19
21
|
this.appName = appName;
|
|
@@ -148,6 +150,39 @@ class RuntimeAppSetupContext {
|
|
|
148
150
|
this.adminizer.adminLinkHandler.removeTemplate(resourceId, this.appName);
|
|
149
151
|
});
|
|
150
152
|
}
|
|
153
|
+
context(resource) {
|
|
154
|
+
const source = resource.layout;
|
|
155
|
+
let layout;
|
|
156
|
+
if (typeof source !== "object") {
|
|
157
|
+
layout = source;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
const stylesheet = source.stylesheet ? this.asset(source.stylesheet) : undefined;
|
|
161
|
+
if ("component" in source)
|
|
162
|
+
layout = { component: this.asset(source.component), stylesheet };
|
|
163
|
+
else if ("overrides" in source)
|
|
164
|
+
layout = { overrides: this.asset(source.overrides), stylesheet };
|
|
165
|
+
else
|
|
166
|
+
layout = { module: this.asset(source.module), stylesheet, base: source.base };
|
|
167
|
+
}
|
|
168
|
+
const { id } = this.adminizer.contextHandler.register({ ...resource, layout }, this.appName);
|
|
169
|
+
this.disposers.push(() => this.adminizer.contextHandler.unregister(id, this.appName));
|
|
170
|
+
// Pages go through this context: their routes and assets are the app's.
|
|
171
|
+
return this.adminizer.contextHandler.scope(id, {
|
|
172
|
+
controller: (controller) => this.controller(controller),
|
|
173
|
+
component: (component) => {
|
|
174
|
+
if (typeof component === "string")
|
|
175
|
+
return component;
|
|
176
|
+
// One asset however many pages, of however many contexts, render it.
|
|
177
|
+
let url = this.pageComponents.get(component.id);
|
|
178
|
+
if (!url) {
|
|
179
|
+
url = this.asset(component);
|
|
180
|
+
this.pageComponents.set(component.id, url);
|
|
181
|
+
}
|
|
182
|
+
return url;
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
}
|
|
151
186
|
listener(event, handler) {
|
|
152
187
|
const resourceId = `${this.appName}:${event.toString()}:${this.disposers.length + 1}`;
|
|
153
188
|
const listener = (payload) => handler(payload, this.adminizer.appManager.createRuntime(this.appName));
|