@nocobase/plugin-acl 0.19.0-alpha.9 → 0.20.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/client/NewRole.d.ts +2 -0
  2. package/dist/client/RolesManagement.d.ts +2 -0
  3. package/dist/client/RolesManagerProvider.d.ts +5 -0
  4. package/dist/client/RolesMenu.d.ts +7 -0
  5. package/dist/client/index.d.ts +5 -2
  6. package/dist/client/index.js +9 -1
  7. package/dist/client/locale.d.ts +1 -0
  8. package/dist/client/permissions/ActionPermissions.d.ts +4 -0
  9. package/dist/client/permissions/AvailableActions.d.ts +3 -0
  10. package/dist/client/permissions/GeneralPermissions.d.ts +4 -0
  11. package/dist/client/permissions/MenuItemsProvider.d.ts +4 -0
  12. package/dist/client/permissions/MenuPermissions.d.ts +4 -0
  13. package/dist/client/permissions/Permissions.d.ts +4 -0
  14. package/dist/client/permissions/PluginPermissions.d.ts +4 -0
  15. package/dist/client/permissions/RolesResourcesActions.d.ts +3 -0
  16. package/dist/client/permissions/ScopeSelect.d.ts +3 -0
  17. package/dist/client/permissions/StrategyActions.d.ts +2 -0
  18. package/dist/client/permissions/style.d.ts +1 -0
  19. package/dist/client/roles-manager.d.ts +10 -0
  20. package/dist/client/schemas/roles.d.ts +54 -0
  21. package/dist/client/schemas/scopes.d.ts +67 -0
  22. package/dist/externalVersion.js +18 -7
  23. package/dist/locale/en-US.json +3 -1
  24. package/dist/locale/zh-CN.json +3 -1
  25. package/dist/server/collections/roles.js +2 -2
  26. package/dist/server/collections/rolesResources.js +3 -1
  27. package/dist/server/index.d.ts +4 -0
  28. package/dist/server/index.js +14 -0
  29. package/dist/server/middlewares/setCurrentRole.js +11 -6
  30. package/dist/server/middlewares/with-acl-meta.d.ts +2 -0
  31. package/dist/server/middlewares/with-acl-meta.js +236 -0
  32. package/dist/server/model/RoleModel.d.ts +1 -0
  33. package/dist/server/model/RoleModel.js +6 -4
  34. package/dist/server/server.d.ts +2 -2
  35. package/dist/server/server.js +55 -204
  36. package/package.json +2 -2
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const NewRole: React.FC;
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const RolesManagement: React.FC;
@@ -0,0 +1,5 @@
1
+ /// <reference types="react" />
2
+ export declare const RolesManagerContext: import("react").Context<{
3
+ role: any;
4
+ setRole: (role: any) => void;
5
+ }>;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export declare const RolesMenu: React.FC & {
3
+ Item: React.FC<{
4
+ item: any;
5
+ onEdit: () => void;
6
+ }>;
7
+ };
@@ -1,5 +1,8 @@
1
1
  import { Plugin } from '@nocobase/client';
2
- declare class AclPlugin extends Plugin {
2
+ import { RolesManager } from './roles-manager';
3
+ declare class ACLPlugin extends Plugin {
4
+ rolesManager: RolesManager;
3
5
  load(): Promise<void>;
4
6
  }
5
- export default AclPlugin;
7
+ export default ACLPlugin;
8
+ export { RolesManagerContext } from './RolesManagerProvider';
@@ -1 +1,9 @@
1
- (function(e,n){typeof exports=="object"&&typeof module!="undefined"?n(exports,require("@nocobase/client")):typeof define=="function"&&define.amd?define(["exports","@nocobase/client"],n):(e=typeof globalThis!="undefined"?globalThis:e||self,n(e["@nocobase/plugin-acl"]={},e["@nocobase/client"]))})(this,function(e,n){"use strict";var c=(e,n,o)=>new Promise((u,l)=>{var d=i=>{try{t(o.next(i))}catch(s){l(s)}},f=i=>{try{t(o.throw(i))}catch(s){l(s)}},t=i=>i.done?u(i.value):Promise.resolve(i.value).then(d,f);t((o=o.apply(e,n)).next())});class o extends n.Plugin{load(){return c(this,null,function*(){})}}e.default=o,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
1
+ (function(h,u){typeof exports=="object"&&typeof module!="undefined"?u(exports,require("@nocobase/client"),require("react/jsx-runtime"),require("react"),require("antd"),require("@formily/react"),require("@ant-design/icons"),require("react-i18next"),require("@formily/shared"),require("@nocobase/utils/client"),require("@formily/core"),require("ahooks"),require("lodash"),require("antd-style")):typeof define=="function"&&define.amd?define(["exports","@nocobase/client","react/jsx-runtime","react","antd","@formily/react","@ant-design/icons","react-i18next","@formily/shared","@nocobase/utils/client","@formily/core","ahooks","lodash","antd-style"],u):(h=typeof globalThis!="undefined"?globalThis:h||self,u(h["@nocobase/plugin-acl"]={},h["@nocobase/client"],h.jsxRuntime,h.react,h.antd,h["@formily/react"],h["@ant-design/icons"],h["react-i18next"],h["@formily/shared"],h["@nocobase/utils"],h["@formily/core"],h.ahooks,h.lodash,h["antd-style"]))})(this,function(h,u,s,g,p,A,G,C,_,k,ce,Ze,le,Qe){"use strict";var Si=Object.defineProperty,wi=Object.defineProperties;var Ai=Object.getOwnPropertyDescriptors;var Je=Object.getOwnPropertySymbols;var Pi=Object.prototype.hasOwnProperty,Ii=Object.prototype.propertyIsEnumerable;var oe=(h,u,s)=>u in h?Si(h,u,{enumerable:!0,configurable:!0,writable:!0,value:s}):h[u]=s,w=(h,u)=>{for(var s in u||(u={}))Pi.call(u,s)&&oe(h,s,u[s]);if(Je)for(var s of Je(u))Ii.call(u,s)&&oe(h,s,u[s]);return h},N=(h,u)=>wi(h,Ai(u));var ie=(h,u,s)=>(oe(h,typeof u!="symbol"?u+"":u,s),s);var S=(h,u,s)=>new Promise((g,p)=>{var A=_=>{try{C(s.next(_))}catch(k){p(k)}},G=_=>{try{C(s.throw(_))}catch(k){p(k)}},C=_=>_.done?g(_.value):Promise.resolve(_.value).then(A,G);C((s=s.apply(h,u)).next())});function O(){return C.useTranslation(["acl","client"],{nsMode:"fallback"})}const P=g.createContext({role:null});var U=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{};function ue(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Re=Array.isArray,q=Re,et=typeof U=="object"&&U&&U.Object===Object&&U,tt=et,rt=tt,nt=typeof self=="object"&&self&&self.Object===Object&&self,at=rt||nt||Function("return this")(),K=at,st=K,ot=st.Symbol,z=ot,pe=z,de=Object.prototype,it=de.hasOwnProperty,ct=de.toString,j=pe?pe.toStringTag:void 0;function lt(e){var t=it.call(e,j),r=e[j];try{e[j]=void 0;var n=!0}catch(o){}var a=ct.call(e);return n&&(t?e[j]=r:delete e[j]),a}var ut=lt,pt=Object.prototype,dt=pt.toString;function ht(e){return dt.call(e)}var ft=ht,he=z,vt=ut,gt=ft,mt="[object Null]",yt="[object Undefined]",fe=he?he.toStringTag:void 0;function _t(e){return e==null?e===void 0?yt:mt:fe&&fe in Object(e)?vt(e):gt(e)}var Z=_t;function bt(e){return e!=null&&typeof e=="object"}var Q=bt,$t=Z,Ct=Q,xt="[object Symbol]";function St(e){return typeof e=="symbol"||Ct(e)&&$t(e)==xt}var R=St,wt=q,At=R,Pt=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,It=/^\w*$/;function Tt(e,t){if(wt(e))return!1;var r=typeof e;return r=="number"||r=="symbol"||r=="boolean"||e==null||At(e)?!0:It.test(e)||!Pt.test(e)||t!=null&&e in Object(t)}var Ot=Tt;function Mt(e){var t=typeof e;return e!=null&&(t=="object"||t=="function")}var ee=Mt,Ft=Z,Dt=ee,Et="[object AsyncFunction]",Nt="[object Function]",kt="[object GeneratorFunction]",qt="[object Proxy]";function jt(e){if(!Dt(e))return!1;var t=Ft(e);return t==Nt||t==kt||t==Et||t==qt}var Ht=jt,Gt=K,Ut=Gt["__core-js_shared__"],Kt=Ut,te=Kt,ve=function(){var e=/[^.]+$/.exec(te&&te.keys&&te.keys.IE_PROTO||"");return e?"Symbol(src)_1."+e:""}();function zt(e){return!!ve&&ve in e}var Lt=zt,Vt=Function.prototype,Wt=Vt.toString;function Bt(e){if(e!=null){try{return Wt.call(e)}catch(t){}try{return e+""}catch(t){}}return""}var Yt=Bt,Xt=Ht,Jt=Lt,Zt=ee,Qt=Yt,Rt=/[\\^$.*+?()[\]{}|]/g,er=/^\[object .+?Constructor\]$/,tr=Function.prototype,rr=Object.prototype,nr=tr.toString,ar=rr.hasOwnProperty,sr=RegExp("^"+nr.call(ar).replace(Rt,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function or(e){if(!Zt(e)||Jt(e))return!1;var t=Xt(e)?sr:er;return t.test(Qt(e))}var ir=or;function cr(e,t){return e==null?void 0:e[t]}var lr=cr,ur=ir,pr=lr;function dr(e,t){var r=pr(e,t);return ur(r)?r:void 0}var L=dr,hr=L,fr=hr(Object,"create"),V=fr,ge=V;function vr(){this.__data__=ge?ge(null):{},this.size=0}var gr=vr;function mr(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t}var yr=mr,_r=V,br="__lodash_hash_undefined__",$r=Object.prototype,Cr=$r.hasOwnProperty;function xr(e){var t=this.__data__;if(_r){var r=t[e];return r===br?void 0:r}return Cr.call(t,e)?t[e]:void 0}var Sr=xr,wr=V,Ar=Object.prototype,Pr=Ar.hasOwnProperty;function Ir(e){var t=this.__data__;return wr?t[e]!==void 0:Pr.call(t,e)}var Tr=Ir,Or=V,Mr="__lodash_hash_undefined__";function Fr(e,t){var r=this.__data__;return this.size+=this.has(e)?0:1,r[e]=Or&&t===void 0?Mr:t,this}var Dr=Fr,Er=gr,Nr=yr,kr=Sr,qr=Tr,jr=Dr;function M(e){var t=-1,r=e==null?0:e.length;for(this.clear();++t<r;){var n=e[t];this.set(n[0],n[1])}}M.prototype.clear=Er,M.prototype.delete=Nr,M.prototype.get=kr,M.prototype.has=qr,M.prototype.set=jr;var Hr=M;function Gr(){this.__data__=[],this.size=0}var Ur=Gr;function Kr(e,t){return e===t||e!==e&&t!==t}var me=Kr,zr=me;function Lr(e,t){for(var r=e.length;r--;)if(zr(e[r][0],t))return r;return-1}var W=Lr,Vr=W,Wr=Array.prototype,Br=Wr.splice;function Yr(e){var t=this.__data__,r=Vr(t,e);if(r<0)return!1;var n=t.length-1;return r==n?t.pop():Br.call(t,r,1),--this.size,!0}var Xr=Yr,Jr=W;function Zr(e){var t=this.__data__,r=Jr(t,e);return r<0?void 0:t[r][1]}var Qr=Zr,Rr=W;function en(e){return Rr(this.__data__,e)>-1}var tn=en,rn=W;function nn(e,t){var r=this.__data__,n=rn(r,e);return n<0?(++this.size,r.push([e,t])):r[n][1]=t,this}var an=nn,sn=Ur,on=Xr,cn=Qr,ln=tn,un=an;function F(e){var t=-1,r=e==null?0:e.length;for(this.clear();++t<r;){var n=e[t];this.set(n[0],n[1])}}F.prototype.clear=sn,F.prototype.delete=on,F.prototype.get=cn,F.prototype.has=ln,F.prototype.set=un;var pn=F,dn=L,hn=K,fn=dn(hn,"Map"),vn=fn,ye=Hr,gn=pn,mn=vn;function yn(){this.size=0,this.__data__={hash:new ye,map:new(mn||gn),string:new ye}}var _n=yn;function bn(e){var t=typeof e;return t=="string"||t=="number"||t=="symbol"||t=="boolean"?e!=="__proto__":e===null}var $n=bn,Cn=$n;function xn(e,t){var r=e.__data__;return Cn(t)?r[typeof t=="string"?"string":"hash"]:r.map}var B=xn,Sn=B;function wn(e){var t=Sn(this,e).delete(e);return this.size-=t?1:0,t}var An=wn,Pn=B;function In(e){return Pn(this,e).get(e)}var Tn=In,On=B;function Mn(e){return On(this,e).has(e)}var Fn=Mn,Dn=B;function En(e,t){var r=Dn(this,e),n=r.size;return r.set(e,t),this.size+=r.size==n?0:1,this}var Nn=En,kn=_n,qn=An,jn=Tn,Hn=Fn,Gn=Nn;function D(e){var t=-1,r=e==null?0:e.length;for(this.clear();++t<r;){var n=e[t];this.set(n[0],n[1])}}D.prototype.clear=kn,D.prototype.delete=qn,D.prototype.get=jn,D.prototype.has=Hn,D.prototype.set=Gn;var _e=D,be=_e,Un="Expected a function";function re(e,t){if(typeof e!="function"||t!=null&&typeof t!="function")throw new TypeError(Un);var r=function(){var n=arguments,a=t?t.apply(this,n):n[0],o=r.cache;if(o.has(a))return o.get(a);var i=e.apply(this,n);return r.cache=o.set(a,i)||o,i};return r.cache=new(re.Cache||be),r}re.Cache=be;var Kn=re,zn=Kn,Ln=500;function Vn(e){var t=zn(e,function(n){return r.size===Ln&&r.clear(),n}),r=t.cache;return t}var Wn=Vn,Bn=Wn,Yn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Xn=/\\(\\)?/g,Jn=Bn(function(e){var t=[];return e.charCodeAt(0)===46&&t.push(""),e.replace(Yn,function(r,n,a,o){t.push(a?o.replace(Xn,"$1"):n||r)}),t}),Zn=Jn;function Qn(e,t){for(var r=-1,n=e==null?0:e.length,a=Array(n);++r<n;)a[r]=t(e[r],r,e);return a}var Rn=Qn,$e=z,ea=Rn,ta=q,ra=R,na=1/0,Ce=$e?$e.prototype:void 0,xe=Ce?Ce.toString:void 0;function Se(e){if(typeof e=="string")return e;if(ta(e))return ea(e,Se)+"";if(ra(e))return xe?xe.call(e):"";var t=e+"";return t=="0"&&1/e==-na?"-0":t}var aa=Se,sa=aa;function oa(e){return e==null?"":sa(e)}var ia=oa,ca=q,la=Ot,ua=Zn,pa=ia;function da(e,t){return ca(e)?e:la(e,t)?[e]:ua(pa(e))}var Y=da,ha=R,fa=1/0;function va(e){if(typeof e=="string"||ha(e))return e;var t=e+"";return t=="0"&&1/e==-fa?"-0":t}var ne=va,ga=Y,ma=ne;function ya(e,t){t=ga(t,e);for(var r=0,n=t.length;e!=null&&r<n;)e=e[ma(t[r++])];return r&&r==n?e:void 0}var _a=ya,ba=L,$a=function(){try{var e=ba(Object,"defineProperty");return e({},"",{}),e}catch(t){}}(),we=$a,Ae=we;function Ca(e,t,r){t=="__proto__"&&Ae?Ae(e,t,{configurable:!0,enumerable:!0,value:r,writable:!0}):e[t]=r}var xa=Ca,Sa=xa,wa=me,Aa=Object.prototype,Pa=Aa.hasOwnProperty;function Ia(e,t,r){var n=e[t];(!(Pa.call(e,t)&&wa(n,r))||r===void 0&&!(t in e))&&Sa(e,t,r)}var Ta=Ia,Oa=9007199254740991,Ma=/^(?:0|[1-9]\d*)$/;function Fa(e,t){var r=typeof e;return t=t==null?Oa:t,!!t&&(r=="number"||r!="symbol"&&Ma.test(e))&&e>-1&&e%1==0&&e<t}var Pe=Fa,Da=Ta,Ea=Y,Na=Pe,Ie=ee,ka=ne;function qa(e,t,r,n){if(!Ie(e))return e;t=Ea(t,e);for(var a=-1,o=t.length,i=o-1,c=e;c!=null&&++a<o;){var l=ka(t[a]),v=r;if(l==="__proto__"||l==="constructor"||l==="prototype")return e;if(a!=i){var f=c[l];v=n?n(f,l,c):void 0,v===void 0&&(v=Ie(f)?f:Na(t[a+1])?[]:{})}Da(c,l,v),c=c[l]}return e}var ja=qa,Ha=_a,Ga=ja,Ua=Y;function Ka(e,t,r){for(var n=-1,a=t.length,o={};++n<a;){var i=t[n],c=Ha(e,i);r(c,i)&&Ga(o,Ua(i,e),c)}return o}var za=Ka;function La(e,t){return e!=null&&t in Object(e)}var Va=La,Wa=Z,Ba=Q,Ya="[object Arguments]";function Xa(e){return Ba(e)&&Wa(e)==Ya}var Ja=Xa,Te=Ja,Za=Q,Oe=Object.prototype,Qa=Oe.hasOwnProperty,Ra=Oe.propertyIsEnumerable,es=Te(function(){return arguments}())?Te:function(e){return Za(e)&&Qa.call(e,"callee")&&!Ra.call(e,"callee")},Me=es,ts=9007199254740991;function rs(e){return typeof e=="number"&&e>-1&&e%1==0&&e<=ts}var ns=rs,as=Y,ss=Me,os=q,is=Pe,cs=ns,ls=ne;function us(e,t,r){t=as(t,e);for(var n=-1,a=t.length,o=!1;++n<a;){var i=ls(t[n]);if(!(o=e!=null&&r(e,i)))break;e=e[i]}return o||++n!=a?o:(a=e==null?0:e.length,!!a&&cs(a)&&is(i,a)&&(os(e)||ss(e)))}var ps=us,ds=Va,hs=ps;function fs(e,t){return e!=null&&hs(e,t,ds)}var vs=fs,gs=za,ms=vs;function ys(e,t){return gs(e,t,function(r,n){return ms(e,n)})}var _s=ys;function bs(e,t){for(var r=-1,n=t.length,a=e.length;++r<n;)e[a+r]=t[r];return e}var $s=bs,Fe=z,Cs=Me,xs=q,De=Fe?Fe.isConcatSpreadable:void 0;function Ss(e){return xs(e)||Cs(e)||!!(De&&e&&e[De])}var ws=Ss,As=$s,Ps=ws;function Ee(e,t,r,n,a){var o=-1,i=e.length;for(r||(r=Ps),a||(a=[]);++o<i;){var c=e[o];t>0&&r(c)?t>1?Ee(c,t-1,r,n,a):As(a,c):n||(a[a.length]=c)}return a}var Is=Ee,Ts=Is;function Os(e){var t=e==null?0:e.length;return t?Ts(e,1):[]}var Ms=Os;function Fs(e,t,r){switch(r.length){case 0:return e.call(t);case 1:return e.call(t,r[0]);case 2:return e.call(t,r[0],r[1]);case 3:return e.call(t,r[0],r[1],r[2])}return e.apply(t,r)}var Ds=Fs,Es=Ds,Ne=Math.max;function Ns(e,t,r){return t=Ne(t===void 0?e.length-1:t,0),function(){for(var n=arguments,a=-1,o=Ne(n.length-t,0),i=Array(o);++a<o;)i[a]=n[t+a];a=-1;for(var c=Array(t+1);++a<t;)c[a]=n[a];return c[t]=r(i),Es(e,this,c)}}var ks=Ns;function qs(e){return function(){return e}}var js=qs;function Hs(e){return e}var Gs=Hs,Us=js,ke=we,Ks=Gs,zs=ke?function(e,t){return ke(e,"toString",{configurable:!0,enumerable:!1,value:Us(t),writable:!0})}:Ks,Ls=zs,Vs=800,Ws=16,Bs=Date.now;function Ys(e){var t=0,r=0;return function(){var n=Bs(),a=Ws-(n-r);if(r=n,a>0){if(++t>=Vs)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}var Xs=Ys,Js=Ls,Zs=Xs,Qs=Zs(Js),Rs=Qs,eo=Ms,to=ks,ro=Rs;function no(e){return ro(to(e,void 0,eo),e+"")}var ao=no,so=_s,oo=ao,io=oo(function(e,t){return e==null?{}:so(e,t)}),co=io;const lo=ue(co),uo={type:"object",properties:{[_.uid()]:{type:"void","x-component":"Action.Drawer","x-decorator":"Form","x-decorator-props":{useValues:e=>{const t=u.useRecord(),r=u.useRequest(()=>Promise.resolve({data:lo(t,["title","name","default"])}),N(w({},e),{manual:!0})),n=u.useActionContext();return g.useEffect(()=>{n.visible&&r.run()},[n.visible]),r}},title:'{{t("Edit role")}}',properties:{title:{"x-component":"CollectionField","x-decorator":"FormItem"},name:{"x-component":"CollectionField","x-decorator":"FormItem","x-disabled":!0},default:{title:"","x-component":"CollectionField","x-decorator":"FormItem","x-content":'{{t("Default role")}}'},footer:{type:"void","x-component":"Action.Drawer.Footer",properties:{cancel:{title:'{{t("Cancel")}}',"x-component":"Action","x-component-props":{useAction:"{{ cm.useCancelAction }}"}},submit:{title:'{{t("Submit")}}',"x-component":"Action","x-component-props":{type:"primary",useAction:"{{ cm.useUpdateAction }}"}}}}}}}},ae=()=>{const{t:e}=O(),{data:t}=u.useResourceActionContext(),[r,n]=g.useState(!1),[a,o]=g.useState(null),{role:i,setRole:c}=g.useContext(P),l=((t==null?void 0:t.data)||[]).map(f=>({key:f.name,label:s.jsx(ae.Item,{item:f,onEdit:()=>{n(!0),o(f)}})})),v=({key:f})=>{c(((t==null?void 0:t.data)||[]).find(m=>m.name===f))};return g.useEffect(()=>{t!=null&&t.data.length&&c(t==null?void 0:t.data[0])},[t,c]),s.jsxs(s.Fragment,{children:[l.length?s.jsx(p.Menu,{style:{border:"none",maxHeight:"65vh",overflowY:"auto"},items:l,selectedKeys:[i==null?void 0:i.name],onSelect:v}):s.jsx(p.Empty,{image:p.Empty.PRESENTED_IMAGE_SIMPLE}),s.jsx(u.ActionContextProvider,{value:{visible:r,setVisible:n},children:s.jsx(u.RecordProvider,{record:a,collectionName:"departments",children:s.jsx(u.SchemaComponent,{scope:{t:e},schema:uo})})})]})};ae.Item=function({item:t,onEdit:r}){const{t:n}=O(),{refreshAsync:a}=u.useResourceActionContext(),{modal:o,message:i}=p.App.useApp(),c=u.useAPIClient(),l=()=>{o.confirm({title:n("Delete"),content:n("Are you sure you want to delete it?"),onOk:()=>S(this,null,function*(){yield c.resource("roles").destroy({filterByTk:t.name}),i.success(n("Deleted successfully")),yield a()})})},v=({key:f,domEvent:m})=>{switch(m.stopPropagation(),f){case"edit":r();break;case"delete":l()}};return s.jsxs(p.Row,{children:[s.jsx(p.Col,{flex:3,style:{display:"inline-flex",alignItems:"center"},children:s.jsxs("span",{style:{whiteSpace:"nowrap",width:"120px",overflow:"hidden",textOverflow:"ellipsis"},children:[s.jsx(G.TagOutlined,{}),s.jsx("span",{style:{marginLeft:"10px"},children:A.Schema.compile(t.title,{t:n})})]})}),s.jsxs(p.Col,{children:[t.default?s.jsx(p.Tag,{color:"success",bordered:!1,children:n("Default")}):null,s.jsx(p.Dropdown,{menu:{items:[{label:n("Edit"),key:"edit"},{label:n("Delete"),key:"delete"}],onClick:v},children:s.jsx(G.MoreOutlined,{})})]})]})};var po="__lodash_hash_undefined__";function ho(e){return this.__data__.set(e,po),this}var fo=ho;function vo(e){return this.__data__.has(e)}var go=vo,mo=_e,yo=fo,_o=go;function X(e){var t=-1,r=e==null?0:e.length;for(this.__data__=new mo;++t<r;)this.add(e[t])}X.prototype.add=X.prototype.push=yo,X.prototype.has=_o;var bo=X;function $o(e,t,r,n){for(var a=e.length,o=r+(n?1:-1);n?o--:++o<a;)if(t(e[o],o,e))return o;return-1}var Co=$o;function xo(e){return e!==e}var So=xo;function wo(e,t,r){for(var n=r-1,a=e.length;++n<a;)if(e[n]===t)return n;return-1}var Ao=wo,Po=Co,Io=So,To=Ao;function Oo(e,t,r){return t===t?To(e,t,r):Po(e,Io,r)}var Mo=Oo,Fo=Mo;function Do(e,t){var r=e==null?0:e.length;return!!r&&Fo(e,t,0)>-1}var Eo=Do;function No(e,t,r){for(var n=-1,a=e==null?0:e.length;++n<a;)if(r(t,e[n]))return!0;return!1}var ko=No;function qo(e,t){return e.has(t)}var jo=qo,Ho=L,Go=K,Uo=Ho(Go,"Set"),Ko=Uo;function zo(){}var Lo=zo;function Vo(e){var t=-1,r=Array(e.size);return e.forEach(function(n){r[++t]=n}),r}var qe=Vo,se=Ko,Wo=Lo,Bo=qe,Yo=1/0,Xo=se&&1/Bo(new se([,-0]))[1]==Yo?function(e){return new se(e)}:Wo,Jo=Xo,Zo=bo,Qo=Eo,Ro=ko,ei=jo,ti=Jo,ri=qe,ni=200;function ai(e,t,r){var n=-1,a=Qo,o=e.length,i=!0,c=[],l=c;if(r)i=!1,a=Ro;else if(o>=ni){var v=t?null:ti(e);if(v)return ri(v);i=!1,a=ei,l=new Zo}else l=t?[]:c;e:for(;++n<o;){var f=e[n],m=t?t(f):f;if(f=r||f!==0?f:0,i&&m===m){for(var x=l.length;x--;)if(l[x]===m)continue e;t&&l.push(m),c.push(f)}else a(l,m,r)||(l!==c&&l.push(m),c.push(f))}return c}var si=ai,oi=si;function ii(e){return e&&e.length?oi(e):[]}var ci=ii;const li=ue(ci),je=g.createContext([]),ui=e=>{const{data:t,loading:r}=u.useRequest({resource:"availableActions",action:"list"});return r?s.jsx(p.Spin,{}):s.jsx(je.Provider,{value:t==null?void 0:t.data,children:e.children})},pi=()=>g.useContext(je),di=e=>{var r;if(!e)return{};const t={};return(r=e==null?void 0:e.forEach)==null||r.call(e,n=>{const[a,o]=n.split(":");t[a]=o||"all"}),t},He=e=>{const t=[];for(const r in e)if(Object.prototype.hasOwnProperty.call(e,r)){const n=e[r];n==="all"?t.push(r):t.push(`${r}:${n}`)}return t},hi=A.connect(e=>{const{onChange:t}=e,r=pi(),n=u.useCompile(),{t:a}=C.useTranslation(),o=A.useField(),i=di(o.value);return s.jsx("div",{children:s.jsx(p.Table,{rowKey:"name",size:"small",pagination:!1,columns:[{dataIndex:"displayName",title:a("Action display name"),render:c=>n(c)},{dataIndex:"onNewRecord",title:a("Action type"),render:c=>c?s.jsx(p.Tag,{color:"green",children:a("Action on new records")}):s.jsx(p.Tag,{color:"geekblue",children:a("Action on existing records")})},{dataIndex:"enabled",title:a("Allow"),render:(c,l)=>s.jsx(p.Checkbox,{checked:c,"aria-label":`${l.name}_checkbox`,onChange:v=>{c?delete i[l.name]:i[l.name]="all",t(He(i))}})},{dataIndex:"scope",title:a("Data scope"),render:(c,l)=>!l.onNewRecord&&s.jsx(p.Select,{"data-testid":"select-data-scope",popupMatchSelectWidth:!1,size:"small",value:c,options:[{label:a("All records"),value:"all"},{label:a("Own records"),value:"own"}],onChange:v=>{i[l.name]=v,t(He(i))}})}],dataSource:r==null?void 0:r.map(c=>{let l="all",v=!1;return i[c.name]&&(v=!0,l=i[c.name]),N(w({},c),{enabled:v,scope:l})})})})}),fi=A.connect(e=>{const{t}=C.useTranslation();return s.jsxs(p.Checkbox.Group,{style:{width:"100%",display:"block"},value:e.value,onChange:r=>{const n=["ui.*","pm","pm.*","app"],a=n.map(i=>`!${i}`),o=li([...e.value||[],...r]).filter(i=>i&&!a.includes(i)).map(i=>!n.includes(i)||r!=null&&r.includes(i)?i:`!${i}`);for(const i of n)!o.includes(i)&&!o.includes(`!${i}`)&&o.push(`!${i}`);e.onChange(o)},children:[s.jsx("div",{style:{marginTop:16},children:s.jsx(p.Checkbox,{value:"ui.*",children:t("Allows to configure interface")})}),s.jsx("div",{style:{marginTop:8},children:s.jsx(p.Checkbox,{value:"pm",children:t("Allows to install, activate, disable plugins")})}),s.jsx("div",{style:{marginTop:8},children:s.jsx(p.Checkbox,{value:"pm.*",children:t("Allows to configure plugins")})}),s.jsx("div",{style:{marginTop:8},children:s.jsx(p.Checkbox,{value:"app",children:t("Allows to clear cache, reboot application")})})]})}),vi=({active:e})=>{const{role:t,setRole:r}=g.useContext(P),{t:n}=O(),a=u.useAPIClient(),{data:o}=u.useRequest(()=>a.resource("roles").get({filterByTk:t==null?void 0:t.name}).then(l=>{var f,m;const v=(f=l==null?void 0:l.data)==null?void 0:f.data;return(m=v.snippets)==null||m.forEach(x=>{v[x]=!0}),v}),{ready:e,refreshDeps:[t==null?void 0:t.name]}),i=Ze.useMemoizedFn(l=>S(this,null,function*(){yield a.resource("roles").update({filterByTk:t.name,values:l.values}),r(w(w({},t),l.values)),p.message.success(n("Saved successfully"))})),c=g.useMemo(()=>ce.createForm({values:o,effects(){ce.onFormValuesChange(l=>S(this,null,function*(){yield i(l)}))}}),[o,i]);return s.jsx(u.SchemaComponent,{components:{SnippetCheckboxGroup:fi,StrategyActions:hi},schema:{type:"void",name:_.uid(),"x-component":"FormV2","x-component-props":{form:c},properties:{snippets:{title:n("Configure permissions"),type:"boolean","x-decorator":"FormItem","x-component":"SnippetCheckboxGroup"},allowNewMenu:{title:n("Menu permissions"),"x-decorator":"FormItem","x-component":"Checkbox","x-content":n("New menu items are allowed to be accessed by default.")}}}})},Ge=Qe.createStyles(({css:e})=>e`
2
+ .ant-table-cell {
3
+ > .ant-space-horizontal {
4
+ .ant-space-item-split:has(+ .ant-space-item:empty) {
5
+ display: none;
6
+ }
7
+ }
8
+ }
9
+ `),Ue=g.createContext(null),Ke=(e={})=>{const t=[];for(const r in e)if(Object.prototype.hasOwnProperty.call(e,r)){const n=e[r],a={title:n.title,uid:n["x-uid"]};n.properties&&(a.children=Ke(n.properties)),t.push(a)}return t},gi=()=>g.useContext(Ue),ze=e=>{var o,i;const r={url:`uiSchemas:getProperties/${u.useAdminSchemaUid()}`},n=u.useRequest(r);if(n.loading)return s.jsx(p.Spin,{});const a=Ke((i=(o=n.data)==null?void 0:o.data)==null?void 0:i.properties);return s.jsx(Ue.Provider,{value:{service:n,items:a},children:e.children})},Le=e=>{if(!Array.isArray(e))return[];const t=[];for(const r of e)t.push(r.uid),t.push(...Le(r.children));return t},Ve=(e,t,r=[])=>{if(!e)return[];for(const n of e){if(r.push(n.uid),t(n))return r;if(n.children){const a=Ve(n.children,t,r);if(a.length)return a}r.pop()}return[]},We=(e=[],t=[])=>{for(const r of e)t.push(r.uid),r.children&&r.children.length&&We(r.children,t);return t},mi=({active:e})=>{const{styles:t}=Ge(),{role:r}=g.useContext(P),n=u.useAPIClient(),{items:a}=gi(),{t:o}=C.useTranslation(),i=Le(a),[c,l]=g.useState([]),{loading:v,refresh:f}=u.useRequest({resource:"roles.menuUiSchemas",resourceOf:r.name,action:"list",params:{paginate:!1}},{ready:!!r&&e,refreshDeps:[r==null?void 0:r.name],onSuccess(b){var d;l(((d=b==null?void 0:b.data)==null?void 0:d.map(y=>y["x-uid"]))||[])}}),m=n.resource("roles.menuUiSchemas",r.name),x=i.length===c.length,H=(b,d)=>S(this,null,function*(){const y=Ve(a,$=>$.uid===d.uid),E=We(d==null?void 0:d.children,[]);if(b){const $=E.concat(d.uid),T=c.filter(xi=>!$.includes(xi));l([...T]),yield m.remove({values:$})}else{const $=E.concat(y);l(T=>le.uniq([...T,...$])),yield m.add({values:$})}p.message.success(o("Saved successfully"))}),I=b=>b.map(d=>{const y=o(d.title);return d.children?N(w({},d),{title:y,children:I(d.children)}):N(w({},d),{title:y})});return s.jsx(p.Table,{className:t,loading:v,rowKey:"uid",pagination:!1,expandable:{defaultExpandAllRows:!0},columns:[{dataIndex:"title",title:o("Menu item title")},{dataIndex:"accessible",title:s.jsxs(s.Fragment,{children:[s.jsx(p.Checkbox,{checked:x,onChange:b=>S(this,null,function*(){x?yield m.set({values:[]}):yield m.set({values:i}),f(),p.message.success(o("Saved successfully"))})})," ",o("Accessible")]}),render:(b,d)=>{const y=c.includes(d.uid);return s.jsx(p.Checkbox,{checked:y,onChange:()=>H(y,d)})}}],dataSource:I(a)})},Be=(e=[],t=[])=>{for(const r of e)t.push(r.aclSnippet),r.children&&r.children.length&&Be(r.children,t);return t},yi=({active:e})=>{const t=u.useApp(),{styles:r}=Ge(),{role:n}=g.useContext(P),a=u.useAPIClient(),o=u.useCompile(),i=t.pluginSettingsManager.getList(!1),c=t.pluginSettingsManager.getAclSnippets(),[l,v]=g.useState([]),f=g.useMemo(()=>l.includes("pm.*")&&l.every(d=>!d.startsWith("!pm.")),[l]),{t:m}=C.useTranslation(),{loading:x,refresh:H}=u.useRequest({resource:"roles.snippets",resourceOf:n.name,action:"list",params:{paginate:!1}},{ready:!!n&&e,refreshDeps:[n==null?void 0:n.name],onSuccess(d){v((d==null?void 0:d.data)||[])}}),I=a.resource("roles.snippets",n.name),b=(d,y)=>S(this,null,function*(){const $=Be(y==null?void 0:y.children,[]).concat(y.aclSnippet);d?(yield I.add({values:$.map(T=>"!"+T)}),H()):(yield I.remove({values:$.map(T=>"!"+T)}),H()),p.message.success(m("Saved successfully"))});return s.jsx(p.Table,{className:r,loading:x,rowKey:"key",pagination:!1,expandable:{defaultExpandAllRows:!0},columns:[{dataIndex:"title",title:m("Plugin name"),render:d=>o(d)},{dataIndex:"accessible",title:s.jsxs(s.Fragment,{children:[s.jsx(p.Checkbox,{checked:f,onChange:()=>S(this,null,function*(){const d=c.map(y=>"!"+y);f?yield I.add({values:d}):yield I.remove({values:d}),H(),p.message.success(m("Saved successfully"))})})," ",m("Accessible")]}),render:(d,y)=>{const E=!l.includes("!"+y.aclSnippet);return s.jsx(p.Checkbox,{checked:E,onChange:()=>b(E,y)})}}],dataSource:i.filter(d=>d.isTopLevel!==!1).map(d=>d.showTabs!==!1?d:le.omit(d,"children"))})},J=e=>s.jsx("div",{style:{maxHeight:"60vh",overflowY:"auto"},children:e.children}),_i=({active:e})=>{var v;const{t}=O(),[r,n]=g.useState("general"),{role:a}=g.useContext(P),o=(v=a==null?void 0:a.snippets)==null?void 0:v.includes("pm.*"),c=u.useApp().getComponent("DataSourcePermissionManager"),l=g.useMemo(()=>[{key:"general",label:t("General permissions"),children:s.jsx(J,{children:s.jsx(vi,{active:r==="general"&&e})})},{key:"menu",label:t("Menu permissions"),children:s.jsx(J,{children:s.jsx(ze,{children:s.jsx(mi,{active:r==="menu"&&e})})})},...o?[{key:"plugin",label:t("Plugin settings permissions"),children:s.jsx(J,{children:s.jsx(yi,{active:r==="plugin"&&e})})}]:[],...c?[{key:"dataSource",label:t("Data source permissions"),children:s.jsx(J,{children:s.jsx(ze,{children:s.jsx(c,{role:a,active:r==="dataSource"&&e})})})}]:[]],[o,r,e,t]);return g.useEffect(()=>{n("general")},[a==null?void 0:a.name]),s.jsx(ui,{children:s.jsx(p.Tabs,{type:"card",activeKey:r,onChange:f=>n(f),items:l})})},bi=()=>{const{t:e}=O();return s.jsx(u.SchemaComponent,{scope:{t:e},schema:{type:"void",properties:{newRole:{type:"void",title:e("New role"),"x-component":"Action","x-component-props":{type:"text",icon:"PlusOutlined",style:{width:"100%",textAlign:"left"}},properties:{drawer:{type:"void","x-component":"Action.Drawer","x-decorator":"Form","x-decorator-props":{useValues(t){const r=u.useActionContext();return u.useRequest(()=>Promise.resolve({data:{name:`r_${_.uid()}`,snippets:["!ui.*","!pm","!pm.*"]}}),N(w({},t),{refreshDeps:[r.visible]}))}},title:e("New role"),properties:{title:{"x-component":"CollectionField","x-decorator":"FormItem"},name:{"x-component":"CollectionField","x-decorator":"FormItem",description:'{{t("Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.")}}'},default:{"x-component":"CollectionField","x-decorator":"FormItem",title:"","x-content":'{{t("Default role")}}'},footer:{type:"void","x-component":"Action.Drawer.Footer",properties:{cancel:{title:'{{t("Cancel")}}',"x-component":"Action","x-component-props":{useAction:"{{ cm.useCancelAction }}"}},submit:{title:'{{t("Submit")}}',"x-component":"Action","x-component-props":{type:"primary",useAction:"{{ cm.useCreateAction }}"}}}}}}}}}}})},Ye={name:"roles",filterTargetKey:"name",targetKey:"name",fields:[{type:"string",name:"title",interface:"input",uiSchema:{title:'{{t("Role display name")}}',type:"number","x-component":"Input",required:!0}},{type:"string",name:"name",interface:"input",uiSchema:{title:'{{t("Role UID")}}',type:"string","x-component":"Input"}},{type:"boolean",name:"default",interface:"boolean",uiSchema:{title:'{{t("Default role")}}',type:"boolean","x-component":"Checkbox"}}]},$i=()=>{const{t:e}=O(),t=u.usePlugin(Xe),[r,n]=g.useState("permissions"),a=Array.from(t.rolesManager.list()).map(([c,l])=>({key:c,label:A.Schema.compile(l.title,{t:e}),children:l.Component?g.createElement(l.Component,{active:r===c}):null})),[o,i]=g.useState(null);return s.jsx(P.Provider,{value:{role:o,setRole:i},children:s.jsx(p.Card,{children:s.jsxs(p.Row,{gutter:24,style:{flexWrap:"nowrap"},children:[s.jsx(p.Col,{flex:"280px",style:{borderRight:"1px solid #eee",minWidth:"250px"},children:s.jsx(u.ResourceActionProvider,{collection:Ye,request:{resource:"roles",action:"list",params:{pagination:!1,filter:{"name.$ne":"root"},showAnonymous:!0,sort:["createdAt"],appends:[]}},children:s.jsxs(u.CollectionProvider_deprecated,{collection:Ye,children:[s.jsx(p.Row,{children:s.jsx(bi,{})}),s.jsx(p.Divider,{style:{margin:"12px 0"}}),s.jsx(ae,{})]})})}),s.jsx(p.Col,{flex:"auto",style:{overflow:"hidden"},children:s.jsx(p.Tabs,{activeKey:r,onChange:c=>n(c),items:[{key:"permissions",label:e("Permissions"),children:s.jsx(_i,{active:r==="permissions"})},...a]})})]})})})};class Ci{constructor(){ie(this,"rolesManager",new k.Registry)}add(t,r){this.rolesManager.register(t,r)}list(){return this.rolesManager.getEntities()}}class Xe extends u.Plugin{constructor(){super(...arguments);ie(this,"rolesManager",new Ci)}load(){return S(this,null,function*(){this.app.pluginSettingsManager.add("users-permissions.roles",{title:'{{t("Roles & Permissions")}}',icon:"LockOutlined",Component:$i,aclSnippet:"pm.roles",sort:3})})}}h.RolesManagerContext=P,h.default=Xe,Object.defineProperties(h,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
@@ -0,0 +1 @@
1
+ export declare function useACLTranslation(): import("react-i18next").UseTranslationResponse<("acl" | "client")[], undefined>;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const ActionPermissions: React.FC<{
3
+ active: boolean;
4
+ }>;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare const AvailableActionsProvider: React.FC;
3
+ export declare const useAvailableActions: () => any[];
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const GeneralPermissions: React.FC<{
3
+ active: boolean;
4
+ }>;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const toItems: (properties?: {}) => any[];
3
+ export declare const useMenuItems: () => any;
4
+ export declare const MenuItemsProvider: (props: any) => React.JSX.Element;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const MenuPermissions: React.FC<{
3
+ active: boolean;
4
+ }>;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const Permissions: React.FC<{
3
+ active: boolean;
4
+ }>;
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export declare const PluginPermissions: React.FC<{
3
+ active: boolean;
4
+ }>;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare const RoleResourceCollectionContext: React.Context<any>;
3
+ export declare const RolesResourcesActions: React.ForwardRefExoticComponent<Omit<Partial<any>, "ref"> & React.RefAttributes<unknown>>;
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare const useRolesResourcesScopesSelectedRowKeys: () => any;
3
+ export declare const ScopeSelect: (props: any) => React.JSX.Element;
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const StrategyActions: React.ForwardRefExoticComponent<Omit<Partial<any>, "ref"> & React.RefAttributes<unknown>>;
@@ -0,0 +1 @@
1
+ export declare const useStyles: (props?: unknown) => import("antd-style").ReturnStyles<import("antd-style").SerializedStyles>;
@@ -0,0 +1,10 @@
1
+ /// <reference types="react" />
2
+ export type RolesManagerOptions = {
3
+ title: string;
4
+ Component: React.ComponentType<any>;
5
+ };
6
+ export declare class RolesManager {
7
+ rolesManager: any;
8
+ add(name: string, options: RolesManagerOptions): void;
9
+ list(): any;
10
+ }
@@ -0,0 +1,54 @@
1
+ import { ISchema } from '@formily/react';
2
+ export declare const roleEditSchema: {
3
+ type: string;
4
+ properties: {
5
+ [x: string]: {
6
+ type: string;
7
+ 'x-component': string;
8
+ 'x-decorator': string;
9
+ 'x-decorator-props': {
10
+ useValues: (options: any) => import("@nocobase/client").UseRequestResult<unknown>;
11
+ };
12
+ title: string;
13
+ properties: {
14
+ title: {
15
+ 'x-component': string;
16
+ 'x-decorator': string;
17
+ };
18
+ name: {
19
+ 'x-component': string;
20
+ 'x-decorator': string;
21
+ 'x-disabled': boolean;
22
+ };
23
+ default: {
24
+ title: string;
25
+ 'x-component': string;
26
+ 'x-decorator': string;
27
+ 'x-content': string;
28
+ };
29
+ footer: {
30
+ type: string;
31
+ 'x-component': string;
32
+ properties: {
33
+ cancel: {
34
+ title: string;
35
+ 'x-component': string;
36
+ 'x-component-props': {
37
+ useAction: string;
38
+ };
39
+ };
40
+ submit: {
41
+ title: string;
42
+ 'x-component': string;
43
+ 'x-component-props': {
44
+ type: string;
45
+ useAction: string;
46
+ };
47
+ };
48
+ };
49
+ };
50
+ };
51
+ };
52
+ };
53
+ };
54
+ export declare const roleCollectionsSchema: ISchema;
@@ -0,0 +1,67 @@
1
+ import { ISchema } from '@formily/react';
2
+ export declare const rolesResourcesScopesCollection: {
3
+ name: string;
4
+ fields: {
5
+ type: string;
6
+ name: string;
7
+ interface: string;
8
+ uiSchema: import("@formily/react").Stringify<{
9
+ [key: symbol]: any;
10
+ [key: `x-${string}`]: any;
11
+ [key: `x-${number}`]: any;
12
+ version?: string;
13
+ name?: import("@formily/react").SchemaKey;
14
+ title?: any;
15
+ description?: any;
16
+ default?: any;
17
+ readOnly?: boolean;
18
+ writeOnly?: boolean;
19
+ type?: import("@formily/react").SchemaTypes;
20
+ enum?: import("@formily/react").SchemaEnum<any>;
21
+ const?: any;
22
+ multipleOf?: number;
23
+ maximum?: number;
24
+ exclusiveMaximum?: number;
25
+ minimum?: number;
26
+ exclusiveMinimum?: number;
27
+ maxLength?: number;
28
+ minLength?: number;
29
+ pattern?: string | RegExp;
30
+ maxItems?: number;
31
+ minItems?: number;
32
+ uniqueItems?: boolean;
33
+ maxProperties?: number;
34
+ minProperties?: number;
35
+ required?: string | boolean | string[];
36
+ format?: string;
37
+ $ref?: string;
38
+ $namespace?: string;
39
+ definitions?: import("@formily/react").SchemaProperties<any, any, any, any, any, any, any, any>;
40
+ properties?: import("@formily/react").SchemaProperties<any, any, any, any, any, any, any, any>;
41
+ items?: import("@formily/react").SchemaItems<any, any, any, any, any, any, any, any>;
42
+ additionalItems?: import("@formily/react").Stringify<any>;
43
+ patternProperties?: import("@formily/react").SchemaProperties<any, any, any, any, any, any, any, any>;
44
+ additionalProperties?: import("@formily/react").Stringify<any>;
45
+ "x-value"?: any;
46
+ "x-index"?: number;
47
+ "x-pattern"?: any;
48
+ "x-display"?: any;
49
+ "x-validator"?: any;
50
+ "x-decorator"?: any;
51
+ "x-decorator-props"?: any;
52
+ "x-component"?: any;
53
+ "x-component-props"?: any;
54
+ "x-reactions"?: import("@formily/react").SchemaReactions<any>;
55
+ "x-content"?: any;
56
+ "x-data"?: any;
57
+ "x-visible"?: boolean;
58
+ "x-hidden"?: boolean;
59
+ "x-disabled"?: boolean;
60
+ "x-editable"?: boolean;
61
+ "x-read-only"?: boolean;
62
+ "x-read-pretty"?: boolean;
63
+ "x-compile-omitted"?: string[];
64
+ }>;
65
+ }[];
66
+ };
67
+ export declare const scopesSchema: ISchema;
@@ -1,11 +1,22 @@
1
1
  module.exports = {
2
- "@nocobase/client": "0.19.0-alpha.9",
3
- "@nocobase/acl": "0.19.0-alpha.9",
4
- "@nocobase/actions": "0.19.0-alpha.9",
5
- "@nocobase/cache": "0.19.0-alpha.9",
6
- "@nocobase/database": "0.19.0-alpha.9",
7
- "@nocobase/server": "0.19.0-alpha.9",
2
+ "@nocobase/client": "0.20.0-alpha.2",
3
+ "react": "18.2.0",
4
+ "@formily/shared": "2.3.0",
5
+ "antd": "5.12.8",
6
+ "@formily/react": "2.3.0",
7
+ "@ant-design/icons": "5.2.6",
8
+ "react-i18next": "11.18.6",
9
+ "@nocobase/utils": "0.20.0-alpha.2",
10
+ "@nocobase/actions": "0.20.0-alpha.2",
11
+ "@nocobase/cache": "0.20.0-alpha.2",
12
+ "@nocobase/database": "0.20.0-alpha.2",
13
+ "@nocobase/server": "0.20.0-alpha.2",
8
14
  "async-mutex": "0.3.2",
9
15
  "lodash": "4.17.21",
10
- "@nocobase/test": "0.19.0-alpha.9"
16
+ "@nocobase/test": "0.20.0-alpha.2",
17
+ "@formily/core": "2.3.0",
18
+ "ahooks": "3.7.8",
19
+ "@formily/antd-v5": "1.1.9",
20
+ "antd-style": "3.4.5",
21
+ "@nocobase/acl": "0.20.0-alpha.2"
11
22
  };
@@ -1,4 +1,6 @@
1
1
  {
2
2
  "The current user has no roles. Please try another account.": "The current user has no roles. Please try another account.",
3
- "The user role does not exist. Please try signing in again": "The user role does not exist. Please try signing in again"
3
+ "The user role does not exist. Please try signing in again": "The user role does not exist. Please try signing in again",
4
+ "New role": "New role",
5
+ "Permissions": "Permissions"
4
6
  }
@@ -1,4 +1,6 @@
1
1
  {
2
2
  "The current user has no roles. Please try another account.": "当前用户没有角色,请使用其他账号。",
3
- "The user role does not exist. Please try signing in again": "用户角色不存在,请尝试重新登录。"
3
+ "The user role does not exist. Please try signing in again": "用户角色不存在,请尝试重新登录。",
4
+ "New role": "新建角色",
5
+ "Permissions": "权限"
4
6
  }
@@ -95,9 +95,9 @@ var roles_default = (0, import_database.defineCollection)({
95
95
  {
96
96
  type: "hasMany",
97
97
  name: "resources",
98
- target: "rolesResources",
98
+ target: "dataSourcesRolesResources",
99
99
  sourceKey: "name",
100
- targetKey: "name"
100
+ foreignKey: "roleName"
101
101
  },
102
102
  {
103
103
  type: "set",
@@ -34,7 +34,9 @@ var rolesResources_default = (0, import_database.defineCollection)({
34
34
  fields: [
35
35
  {
36
36
  type: "belongsTo",
37
- name: "role"
37
+ name: "role",
38
+ foreignKey: "roleName",
39
+ targetKey: "name"
38
40
  },
39
41
  {
40
42
  type: "string",
@@ -1 +1,5 @@
1
1
  export { default } from './server';
2
+ export { RoleResourceActionModel } from './model/RoleResourceActionModel';
3
+ export { RoleResourceModel } from './model/RoleResourceModel';
4
+ export * from './middlewares/with-acl-meta';
5
+ export * from './middlewares/setCurrentRole';
@@ -16,6 +16,7 @@ var __copyProps = (to, from, except, desc) => {
16
16
  }
17
17
  return to;
18
18
  };
19
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
19
20
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
21
  // If the importer is in node compatibility mode or this is not an ESM
21
22
  // file that has been converted to a CommonJS file using a Babel-
@@ -27,7 +28,20 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
29
  var server_exports = {};
29
30
  __export(server_exports, {
31
+ RoleResourceActionModel: () => import_RoleResourceActionModel.RoleResourceActionModel,
32
+ RoleResourceModel: () => import_RoleResourceModel.RoleResourceModel,
30
33
  default: () => import_server.default
31
34
  });
32
35
  module.exports = __toCommonJS(server_exports);
33
36
  var import_server = __toESM(require("./server"));
37
+ var import_RoleResourceActionModel = require("./model/RoleResourceActionModel");
38
+ var import_RoleResourceModel = require("./model/RoleResourceModel");
39
+ __reExport(server_exports, require("./middlewares/with-acl-meta"), module.exports);
40
+ __reExport(server_exports, require("./middlewares/setCurrentRole"), module.exports);
41
+ // Annotate the CommonJS export names for ESM import in node:
42
+ 0 && (module.exports = {
43
+ RoleResourceActionModel,
44
+ RoleResourceModel,
45
+ ...require("./middlewares/with-acl-meta"),
46
+ ...require("./middlewares/setCurrentRole")
47
+ });
@@ -30,6 +30,7 @@ async function setCurrentRole(ctx, next) {
30
30
  if (!ctx.state.currentUser) {
31
31
  return next();
32
32
  }
33
+ const attachRoles = ctx.state.attachRoles || [];
33
34
  const cache = ctx.cache;
34
35
  const repository = ctx.db.getRepository("users.roles", ctx.state.currentUser.id);
35
36
  const roles = await cache.wrap(
@@ -38,22 +39,26 @@ async function setCurrentRole(ctx, next) {
38
39
  raw: true
39
40
  })
40
41
  );
41
- if (!roles.length) {
42
+ if (!roles.length && !attachRoles.length) {
42
43
  ctx.state.currentRole = void 0;
43
44
  return ctx.throw(401, {
44
45
  code: "USER_HAS_NO_ROLES_ERR",
45
46
  message: ctx.t("The current user has no roles. Please try another account.", { ns: "acl" })
46
47
  });
47
48
  }
48
- ctx.state.currentUser.roles = roles;
49
+ const rolesMap = /* @__PURE__ */ new Map();
50
+ attachRoles.forEach((role) => rolesMap.set(role.name, role));
51
+ roles.forEach((role) => rolesMap.set(role.name, role));
52
+ const userRoles = Array.from(rolesMap.values());
53
+ ctx.state.currentUser.roles = userRoles;
49
54
  if (currentRole) {
50
- ctx.state.currentRole = (_a = roles.find((role) => role.name === currentRole)) == null ? void 0 : _a.name;
55
+ ctx.state.currentRole = (_a = userRoles.find((role) => role.name === currentRole)) == null ? void 0 : _a.name;
51
56
  } else {
52
- const defaultRole = roles.find((item) => {
57
+ const defaultRole = userRoles.find((role) => {
53
58
  var _a2;
54
- return (_a2 = item == null ? void 0 : item.rolesUsers) == null ? void 0 : _a2.default;
59
+ return (_a2 = role == null ? void 0 : role.rolesUsers) == null ? void 0 : _a2.default;
55
60
  });
56
- ctx.state.currentRole = (_b = defaultRole || roles[0]) == null ? void 0 : _b.name;
61
+ ctx.state.currentRole = (_b = defaultRole || userRoles[0]) == null ? void 0 : _b.name;
57
62
  }
58
63
  if (!ctx.state.currentRole) {
59
64
  return ctx.throw(401, {
@@ -0,0 +1,2 @@
1
+ declare function createWithACLMetaMiddleware(): (ctx: any, next: any) => Promise<void>;
2
+ export { createWithACLMetaMiddleware };
@@ -0,0 +1,236 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var with_acl_meta_exports = {};
29
+ __export(with_acl_meta_exports, {
30
+ createWithACLMetaMiddleware: () => createWithACLMetaMiddleware
31
+ });
32
+ module.exports = __toCommonJS(with_acl_meta_exports);
33
+ var import_lodash = __toESM(require("lodash"));
34
+ var import_acl = require("@nocobase/acl");
35
+ var import_database = require("@nocobase/database");
36
+ function createWithACLMetaMiddleware() {
37
+ return async (ctx, next) => {
38
+ var _a, _b, _c;
39
+ await next();
40
+ const dataSourceKey = ctx.get("x-data-source");
41
+ const dataSource = ctx.app.dataSourceManager.dataSources.get(dataSourceKey);
42
+ const db = dataSource ? dataSource.collectionManager.db : ctx.db;
43
+ if (!db) {
44
+ return;
45
+ }
46
+ const acl = dataSource ? dataSource.acl : ctx.app.acl;
47
+ if (!ctx.action || !ctx.get("X-With-ACL-Meta") || ctx.status !== 200) {
48
+ return;
49
+ }
50
+ const { resourceName, actionName } = ctx.action;
51
+ if (!["list", "get"].includes(actionName)) {
52
+ return;
53
+ }
54
+ const collection = db.getCollection(resourceName);
55
+ if (!collection) {
56
+ return;
57
+ }
58
+ const Model = collection.model;
59
+ const primaryKeyField = Model.primaryKeyField || Model.primaryKeyAttribute;
60
+ const dataPath = ((_a = ctx.body) == null ? void 0 : _a.rows) ? "body.rows" : "body";
61
+ let listData = import_lodash.default.get(ctx, dataPath);
62
+ if (actionName == "get") {
63
+ listData = import_lodash.default.castArray(listData);
64
+ }
65
+ const inspectActions = ["view", "update", "destroy"];
66
+ const actionsParams = [];
67
+ for (const action of inspectActions) {
68
+ const actionCtx = {
69
+ db,
70
+ get: () => {
71
+ return void 0;
72
+ },
73
+ app: {
74
+ getDb() {
75
+ return db;
76
+ }
77
+ },
78
+ action: {
79
+ actionName: action,
80
+ name: action,
81
+ params: {},
82
+ resourceName: ctx.action.resourceName,
83
+ resourceOf: ctx.action.resourceOf,
84
+ mergeParams() {
85
+ }
86
+ },
87
+ state: {
88
+ currentRole: ctx.state.currentRole,
89
+ currentUser: (() => {
90
+ var _a2;
91
+ if (!ctx.state.currentUser) {
92
+ return null;
93
+ }
94
+ if (ctx.state.currentUser.toJSON) {
95
+ return (_a2 = ctx.state.currentUser) == null ? void 0 : _a2.toJSON();
96
+ }
97
+ return ctx.state.currentUser;
98
+ })()
99
+ },
100
+ permission: {},
101
+ throw(...args) {
102
+ throw new import_acl.NoPermissionError(...args);
103
+ }
104
+ };
105
+ try {
106
+ await acl.getActionParams(actionCtx);
107
+ } catch (e) {
108
+ if (e instanceof import_acl.NoPermissionError) {
109
+ continue;
110
+ }
111
+ throw e;
112
+ }
113
+ actionsParams.push([
114
+ action,
115
+ ((_b = actionCtx.permission) == null ? void 0 : _b.can) === null && !actionCtx.permission.skip ? null : ((_c = actionCtx.permission) == null ? void 0 : _c.parsedParams) || {},
116
+ actionCtx
117
+ ]);
118
+ }
119
+ const ids = (() => {
120
+ if (collection.options.tree) {
121
+ if (listData.length == 0)
122
+ return [];
123
+ const getAllNodeIds = (data) => [data[primaryKeyField], ...(data.children || []).flatMap(getAllNodeIds)];
124
+ return listData.map((tree) => getAllNodeIds(tree.toJSON())).flat();
125
+ }
126
+ return listData.map((item) => item[primaryKeyField]);
127
+ })();
128
+ const conditions = [];
129
+ const allAllowed = [];
130
+ for (const [action, params, actionCtx] of actionsParams) {
131
+ if (!params) {
132
+ continue;
133
+ }
134
+ if (import_lodash.default.isEmpty(params) || import_lodash.default.isEmpty(params.filter)) {
135
+ allAllowed.push(action);
136
+ continue;
137
+ }
138
+ const queryParams = collection.repository.buildQueryOptions({
139
+ ...params,
140
+ context: actionCtx
141
+ });
142
+ const actionSql = ctx.db.sequelize.queryInterface.queryGenerator.selectQuery(
143
+ Model.getTableName(),
144
+ {
145
+ where: (() => {
146
+ const filterObj = queryParams.where;
147
+ if (!db.options.underscored) {
148
+ return filterObj;
149
+ }
150
+ const isAssociationKey = (key) => {
151
+ return key.startsWith("$") && key.endsWith("$");
152
+ };
153
+ const iterate = (rootObj, path = []) => {
154
+ const obj = path.length == 0 ? rootObj : import_lodash.default.get(rootObj, path);
155
+ if (Array.isArray(obj)) {
156
+ for (let i = 0; i < obj.length; i++) {
157
+ if (obj[i] === null) {
158
+ continue;
159
+ }
160
+ if (typeof obj[i] === "object") {
161
+ iterate(rootObj, [...path, i]);
162
+ }
163
+ }
164
+ return;
165
+ }
166
+ Reflect.ownKeys(obj).forEach((key) => {
167
+ if (Array.isArray(obj) && key == "length") {
168
+ return;
169
+ }
170
+ if (typeof obj[key] === "object" && obj[key] !== null || typeof obj[key] === "symbol") {
171
+ iterate(rootObj, [...path, key]);
172
+ }
173
+ if (typeof key === "string" && key !== (0, import_database.snakeCase)(key)) {
174
+ const setKey = isAssociationKey(key) ? (() => {
175
+ const parts = key.split(".");
176
+ parts[parts.length - 1] = import_lodash.default.snakeCase(parts[parts.length - 1]);
177
+ const result = parts.join(".");
178
+ return result.endsWith("$") ? result : `${result}$`;
179
+ })() : (0, import_database.snakeCase)(key);
180
+ const setValue = import_lodash.default.cloneDeep(obj[key]);
181
+ import_lodash.default.unset(rootObj, [...path, key]);
182
+ import_lodash.default.set(rootObj, [...path, setKey], setValue);
183
+ }
184
+ });
185
+ };
186
+ iterate(filterObj);
187
+ return filterObj;
188
+ })(),
189
+ attributes: [primaryKeyField],
190
+ includeIgnoreAttributes: false
191
+ },
192
+ Model
193
+ );
194
+ const whereCase = actionSql.match(/WHERE (.*?);/)[1];
195
+ conditions.push({
196
+ whereCase,
197
+ action,
198
+ include: queryParams.include
199
+ });
200
+ }
201
+ const results = await collection.model.findAll({
202
+ where: {
203
+ [primaryKeyField]: ids
204
+ },
205
+ attributes: [
206
+ primaryKeyField,
207
+ ...conditions.map((condition) => {
208
+ return [ctx.db.sequelize.literal(`CASE WHEN ${condition.whereCase} THEN 1 ELSE 0 END`), condition.action];
209
+ })
210
+ ],
211
+ include: conditions.map((condition) => condition.include).flat()
212
+ });
213
+ const allowedActions = inspectActions.map((action) => {
214
+ if (allAllowed.includes(action)) {
215
+ return [action, ids];
216
+ }
217
+ return [action, results.filter((item) => Boolean(item.get(action))).map((item) => item.get(primaryKeyField))];
218
+ }).reduce((acc, [action, ids2]) => {
219
+ acc[action] = ids2;
220
+ return acc;
221
+ }, {});
222
+ if (actionName == "get") {
223
+ ctx.bodyMeta = {
224
+ ...ctx.bodyMeta || {},
225
+ allowedActions
226
+ };
227
+ }
228
+ if (actionName == "list") {
229
+ ctx.body.allowedActions = allowedActions;
230
+ }
231
+ };
232
+ }
233
+ // Annotate the CommonJS export names for ESM import in node:
234
+ 0 && (module.exports = {
235
+ createWithACLMetaMiddleware
236
+ });
@@ -3,5 +3,6 @@ import { ACL } from '@nocobase/acl';
3
3
  export declare class RoleModel extends Model {
4
4
  writeToAcl(options: {
5
5
  acl: ACL;
6
+ withOutStrategy?: boolean;
6
7
  }): void;
7
8
  }
@@ -31,10 +31,12 @@ class RoleModel extends import_database.Model {
31
31
  role: roleName
32
32
  });
33
33
  }
34
- role.setStrategy({
35
- ...this.get("strategy") || {},
36
- allowConfigure: this.get("allowConfigure")
37
- });
34
+ if (options.withOutStrategy !== true) {
35
+ role.setStrategy({
36
+ ...this.get("strategy") || {},
37
+ allowConfigure: this.get("allowConfigure")
38
+ });
39
+ }
38
40
  role.snippets = new Set(this.get("snippets"));
39
41
  }
40
42
  }
@@ -25,8 +25,8 @@ export declare class PluginACL extends Plugin {
25
25
  registerAssociationFieldsActions(): void;
26
26
  writeResourceToACL(resourceModel: RoleResourceModel, transaction: any): Promise<void>;
27
27
  writeActionToACL(actionModel: RoleResourceActionModel, transaction: any): Promise<void>;
28
- writeRolesToACL(): Promise<void>;
29
- writeRoleToACL(role: RoleModel, transaction?: any): Promise<void>;
28
+ writeRolesToACL(options: any): Promise<void>;
29
+ writeRoleToACL(role: RoleModel, options?: any): Promise<void>;
30
30
  beforeLoad(): Promise<void>;
31
31
  install(): Promise<void>;
32
32
  load(): Promise<void>;
@@ -32,7 +32,6 @@ __export(server_exports, {
32
32
  default: () => server_default
33
33
  });
34
34
  module.exports = __toCommonJS(server_exports);
35
- var import_acl = require("@nocobase/acl");
36
35
  var import_actions = require("@nocobase/actions");
37
36
  var import_database = require("@nocobase/database");
38
37
  var import_server = require("@nocobase/server");
@@ -47,6 +46,7 @@ var import_setCurrentRole = require("./middlewares/setCurrentRole");
47
46
  var import_RoleModel = require("./model/RoleModel");
48
47
  var import_RoleResourceActionModel = require("./model/RoleResourceActionModel");
49
48
  var import_RoleResourceModel = require("./model/RoleResourceModel");
49
+ var import_with_acl_meta = require("./middlewares/with-acl-meta");
50
50
  class GrantHelper {
51
51
  resourceTargetActionMap = /* @__PURE__ */ new Map();
52
52
  targetActionResourceMap = /* @__PURE__ */ new Map();
@@ -128,16 +128,20 @@ class PluginACL extends import_server.Plugin {
128
128
  grantHelper: this.grantHelper
129
129
  });
130
130
  }
131
- async writeRolesToACL() {
131
+ async writeRolesToACL(options) {
132
132
  const roles = await this.app.db.getRepository("roles").find({
133
133
  appends: ["resources", "resources.actions"]
134
134
  });
135
135
  for (const role of roles) {
136
- await this.writeRoleToACL(role);
136
+ await this.writeRoleToACL(role, options);
137
137
  }
138
138
  }
139
- async writeRoleToACL(role, transaction = null) {
140
- role.writeToAcl({ acl: this.acl });
139
+ async writeRoleToACL(role, options = {}) {
140
+ const transaction = options == null ? void 0 : options.transaction;
141
+ role.writeToAcl({ acl: this.acl, withOutStrategy: true });
142
+ if (options.withOutResources) {
143
+ return;
144
+ }
141
145
  let resources = role.get("resources");
142
146
  if (!resources) {
143
147
  resources = await role.getResources({ transaction });
@@ -212,11 +216,36 @@ class PluginACL extends import_server.Plugin {
212
216
  }
213
217
  });
214
218
  this.app.on("acl:writeRoleToACL", async (roleModel) => {
215
- await this.writeRoleToACL(roleModel);
219
+ await this.writeRoleToACL(roleModel, {
220
+ withOutResources: true
221
+ });
222
+ await this.app.db.getRepository("dataSourcesRoles").updateOrCreate({
223
+ values: {
224
+ roleName: roleModel.get("name"),
225
+ dataSourceKey: "main",
226
+ strategy: roleModel.get("strategy")
227
+ },
228
+ filterKeys: ["roleName", "dataSourceKey"]
229
+ });
216
230
  });
217
231
  this.app.db.on("roles.afterSaveWithAssociations", async (model, options) => {
218
232
  const { transaction } = options;
219
- await this.writeRoleToACL(model, transaction);
233
+ await this.writeRoleToACL(model, {
234
+ withOutResources: true
235
+ });
236
+ await this.app.db.getRepository("dataSourcesRoles").updateOrCreate({
237
+ values: {
238
+ roleName: model.get("name"),
239
+ dataSourceKey: "main",
240
+ strategy: model.get("strategy")
241
+ },
242
+ filterKeys: ["roleName", "dataSourceKey"],
243
+ transaction
244
+ });
245
+ await this.app.emitAsync("acl:writeResources", {
246
+ roleName: model.get("name"),
247
+ transaction
248
+ });
220
249
  if (model.get("default")) {
221
250
  await this.app.db.getRepository("roles").update({
222
251
  values: {
@@ -244,17 +273,12 @@ class PluginACL extends import_server.Plugin {
244
273
  });
245
274
  await this.writeResourceToACL(resource, transaction);
246
275
  });
247
- this.app.db.on("rolesResources.afterDestroy", async (model, options) => {
248
- const role = this.acl.getRole(model.get("roleName"));
249
- if (role) {
250
- role.revokeResource(model.get("name"));
251
- }
252
- });
253
276
  this.app.db.on("collections.afterDestroy", async (model, options) => {
254
277
  const { transaction } = options;
255
- await this.app.db.getRepository("rolesResources").destroy({
278
+ await this.app.db.getRepository("dataSourcesRolesResources").destroy({
256
279
  filter: {
257
- name: model.get("name")
280
+ name: model.get("name"),
281
+ dataSourceKey: "main"
258
282
  },
259
283
  transaction
260
284
  });
@@ -263,9 +287,10 @@ class PluginACL extends import_server.Plugin {
263
287
  const { transaction } = options;
264
288
  const collectionName = model.get("collectionName");
265
289
  const fieldName = model.get("name");
266
- const resourceActions = await this.app.db.getRepository("rolesResourcesActions").find({
290
+ const resourceActions = await this.app.db.getRepository("dataSourcesRolesResourcesActions").find({
267
291
  filter: {
268
- "resource.name": collectionName
292
+ "resource.name": collectionName,
293
+ "resource.dataSourceKey": "main"
269
294
  },
270
295
  transaction,
271
296
  appends: ["resource"]
@@ -273,7 +298,7 @@ class PluginACL extends import_server.Plugin {
273
298
  for (const resourceAction of resourceActions) {
274
299
  const fields = resourceAction.get("fields");
275
300
  const newFields = [...fields, fieldName];
276
- await this.app.db.getRepository("rolesResourcesActions").update({
301
+ await this.app.db.getRepository("dataSourcesRolesResourcesActions").update({
277
302
  filterByTk: resourceAction.get("id"),
278
303
  values: {
279
304
  fields: newFields
@@ -287,17 +312,18 @@ class PluginACL extends import_server.Plugin {
287
312
  await mutex.runExclusive(async () => {
288
313
  const collectionName = model.get("collectionName");
289
314
  const fieldName = model.get("name");
290
- const resourceActions = await this.app.db.getRepository("rolesResourcesActions").find({
315
+ const resourceActions = await this.app.db.getRepository("dataSourcesRolesResourcesActions").find({
291
316
  filter: {
292
317
  "resource.name": collectionName,
293
- "fields.$anyOf": [fieldName]
318
+ "fields.$anyOf": [fieldName],
319
+ "resource.dataSourceKey": "main"
294
320
  },
295
321
  transaction: options.transaction
296
322
  });
297
323
  for (const resourceAction of resourceActions) {
298
324
  const fields = resourceAction.get("fields");
299
325
  const newFields = fields.filter((field) => field != fieldName);
300
- await this.app.db.getRepository("rolesResourcesActions").update({
326
+ await this.app.db.getRepository("dataSourcesRolesResourcesActions").update({
301
327
  filterByTk: resourceAction.get("id"),
302
328
  values: {
303
329
  fields: newFields
@@ -319,10 +345,14 @@ class PluginACL extends import_server.Plugin {
319
345
  const exists = await this.app.db.collectionExistsInDb("roles");
320
346
  if (exists) {
321
347
  this.log.info("write roles to ACL", { method: "writeRolesToACL" });
322
- await this.writeRolesToACL();
348
+ await this.writeRolesToACL(options);
323
349
  }
324
350
  };
325
- this.app.on("afterLoad", writeRolesToACL);
351
+ this.app.on("afterLoad", async () => {
352
+ await writeRolesToACL(this.app, {
353
+ withOutResources: true
354
+ });
355
+ });
326
356
  this.app.on("afterInstallPlugin", async (plugin) => {
327
357
  if (plugin.getName() !== "users") {
328
358
  return;
@@ -376,7 +406,7 @@ class PluginACL extends import_server.Plugin {
376
406
  }
377
407
  ]
378
408
  });
379
- const rolesResourcesScopes = this.app.db.getRepository("rolesResourcesScopes");
409
+ const rolesResourcesScopes = this.app.db.getRepository("dataSourcesRolesResourcesScopes");
380
410
  await rolesResourcesScopes.createMany({
381
411
  records: [
382
412
  {
@@ -555,186 +585,7 @@ class PluginACL extends import_server.Plugin {
555
585
  group: "after"
556
586
  }
557
587
  );
558
- const withACLMeta = async (ctx, next) => {
559
- var _a, _b, _c;
560
- await next();
561
- if (!ctx.action || !ctx.get("X-With-ACL-Meta") || ctx.status !== 200) {
562
- return;
563
- }
564
- const { resourceName, actionName } = ctx.action;
565
- if (!["list", "get"].includes(actionName)) {
566
- return;
567
- }
568
- const collection = ctx.db.getCollection(resourceName);
569
- if (!collection) {
570
- return;
571
- }
572
- const Model = collection.model;
573
- const primaryKeyField = Model.primaryKeyField || Model.primaryKeyAttribute;
574
- const dataPath = ((_a = ctx.body) == null ? void 0 : _a.rows) ? "body.rows" : "body";
575
- let listData = import_lodash.default.get(ctx, dataPath);
576
- if (actionName == "get") {
577
- listData = import_lodash.default.castArray(listData);
578
- }
579
- const inspectActions = ["view", "update", "destroy"];
580
- const actionsParams = [];
581
- for (const action of inspectActions) {
582
- const actionCtx = {
583
- db: ctx.db,
584
- action: {
585
- actionName: action,
586
- name: action,
587
- params: {},
588
- resourceName: ctx.action.resourceName,
589
- resourceOf: ctx.action.resourceOf,
590
- mergeParams() {
591
- }
592
- },
593
- state: {
594
- currentRole: ctx.state.currentRole,
595
- currentUser: (() => {
596
- var _a2;
597
- if (!ctx.state.currentUser) {
598
- return null;
599
- }
600
- if (ctx.state.currentUser.toJSON) {
601
- return (_a2 = ctx.state.currentUser) == null ? void 0 : _a2.toJSON();
602
- }
603
- return ctx.state.currentUser;
604
- })()
605
- },
606
- permission: {},
607
- throw(...args) {
608
- throw new import_acl.NoPermissionError(...args);
609
- }
610
- };
611
- try {
612
- await this.app.acl.getActionParams(actionCtx);
613
- } catch (e) {
614
- if (e instanceof import_acl.NoPermissionError) {
615
- continue;
616
- }
617
- throw e;
618
- }
619
- actionsParams.push([
620
- action,
621
- ((_b = actionCtx.permission) == null ? void 0 : _b.can) === null && !actionCtx.permission.skip ? null : ((_c = actionCtx.permission) == null ? void 0 : _c.parsedParams) || {},
622
- actionCtx
623
- ]);
624
- }
625
- const ids = (() => {
626
- if (collection.options.tree) {
627
- if (listData.length == 0)
628
- return [];
629
- const getAllNodeIds = (data) => [data[primaryKeyField], ...(data.children || []).flatMap(getAllNodeIds)];
630
- return listData.map((tree) => getAllNodeIds(tree.toJSON())).flat();
631
- }
632
- return listData.map((item) => item[primaryKeyField]);
633
- })();
634
- const conditions = [];
635
- const allAllowed = [];
636
- for (const [action, params, actionCtx] of actionsParams) {
637
- if (!params) {
638
- continue;
639
- }
640
- if (import_lodash.default.isEmpty(params) || import_lodash.default.isEmpty(params.filter)) {
641
- allAllowed.push(action);
642
- continue;
643
- }
644
- const queryParams = collection.repository.buildQueryOptions({
645
- ...params,
646
- context: actionCtx
647
- });
648
- const actionSql = ctx.db.sequelize.queryInterface.queryGenerator.selectQuery(
649
- Model.getTableName(),
650
- {
651
- where: (() => {
652
- const filterObj = queryParams.where;
653
- if (!this.db.options.underscored) {
654
- return filterObj;
655
- }
656
- const isAssociationKey = (key) => {
657
- return key.startsWith("$") && key.endsWith("$");
658
- };
659
- const iterate = (rootObj, path = []) => {
660
- const obj = path.length == 0 ? rootObj : import_lodash.default.get(rootObj, path);
661
- if (Array.isArray(obj)) {
662
- for (let i = 0; i < obj.length; i++) {
663
- if (obj[i] === null) {
664
- continue;
665
- }
666
- if (typeof obj[i] === "object") {
667
- iterate(rootObj, [...path, i]);
668
- }
669
- }
670
- return;
671
- }
672
- Reflect.ownKeys(obj).forEach((key) => {
673
- if (Array.isArray(obj) && key == "length") {
674
- return;
675
- }
676
- if (typeof obj[key] === "object" && obj[key] !== null || typeof obj[key] === "symbol") {
677
- iterate(rootObj, [...path, key]);
678
- }
679
- if (typeof key === "string" && key !== (0, import_database.snakeCase)(key)) {
680
- const setKey = isAssociationKey(key) ? (() => {
681
- const parts = key.split(".");
682
- parts[parts.length - 1] = import_lodash.default.snakeCase(parts[parts.length - 1]);
683
- const result = parts.join(".");
684
- return result.endsWith("$") ? result : `${result}$`;
685
- })() : (0, import_database.snakeCase)(key);
686
- const setValue = import_lodash.default.cloneDeep(obj[key]);
687
- import_lodash.default.unset(rootObj, [...path, key]);
688
- import_lodash.default.set(rootObj, [...path, setKey], setValue);
689
- }
690
- });
691
- };
692
- iterate(filterObj);
693
- return filterObj;
694
- })(),
695
- attributes: [primaryKeyField],
696
- includeIgnoreAttributes: false
697
- },
698
- Model
699
- );
700
- const whereCase = actionSql.match(/WHERE (.*?);/)[1];
701
- conditions.push({
702
- whereCase,
703
- action,
704
- include: queryParams.include
705
- });
706
- }
707
- const results = await collection.model.findAll({
708
- where: {
709
- [primaryKeyField]: ids
710
- },
711
- attributes: [
712
- primaryKeyField,
713
- ...conditions.map((condition) => {
714
- return [ctx.db.sequelize.literal(`CASE WHEN ${condition.whereCase} THEN 1 ELSE 0 END`), condition.action];
715
- })
716
- ],
717
- include: conditions.map((condition) => condition.include).flat()
718
- });
719
- const allowedActions = inspectActions.map((action) => {
720
- if (allAllowed.includes(action)) {
721
- return [action, ids];
722
- }
723
- return [action, results.filter((item) => Boolean(item.get(action))).map((item) => item.get(primaryKeyField))];
724
- }).reduce((acc, [action, ids2]) => {
725
- acc[action] = ids2;
726
- return acc;
727
- }, {});
728
- if (actionName == "get") {
729
- ctx.bodyMeta = {
730
- ...ctx.bodyMeta || {},
731
- allowedActions
732
- };
733
- }
734
- if (actionName == "list") {
735
- ctx.body.allowedActions = allowedActions;
736
- }
737
- };
588
+ const withACLMeta = (0, import_with_acl_meta.createWithACLMetaMiddleware)();
738
589
  this.app.use(
739
590
  async (ctx, next) => {
740
591
  try {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "displayName.zh-CN": "权限控制",
5
5
  "description": "Based on roles, resources, and actions, access control can precisely manage interface configuration permissions, data operation permissions, menu access permissions, and plugin permissions.",
6
6
  "description.zh-CN": "基于角色、资源和操作的权限控制,可以精确控制界面配置权限、数据操作权限、菜单访问权限、插件权限。",
7
- "version": "0.19.0-alpha.9",
7
+ "version": "0.20.0-alpha.2",
8
8
  "license": "AGPL-3.0",
9
9
  "main": "./dist/server/index.js",
10
10
  "homepage": "https://docs.nocobase.com/plugins/acl",
@@ -34,5 +34,5 @@
34
34
  "url": "git+https://github.com/nocobase/nocobase.git",
35
35
  "directory": "packages/plugins/acl"
36
36
  },
37
- "gitHead": "975f9c58a1995df6a8d7a4d191a0dc4a9769ebc5"
37
+ "gitHead": "6fb885dfc3554e4b0f29e9a7a1eecbbe85d0eebb"
38
38
  }