@nocobase/plugin-acl 0.19.0-alpha.9 → 0.20.0-alpha.10
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/dist/client/NewRole.d.ts +2 -0
- package/dist/client/RolesManagement.d.ts +2 -0
- package/dist/client/RolesManagerProvider.d.ts +5 -0
- package/dist/client/RolesMenu.d.ts +7 -0
- package/dist/client/index.d.ts +5 -2
- package/dist/client/index.js +9 -1
- package/dist/client/locale.d.ts +1 -0
- package/dist/client/permissions/ActionPermissions.d.ts +4 -0
- package/dist/client/permissions/AvailableActions.d.ts +3 -0
- package/dist/client/permissions/GeneralPermissions.d.ts +4 -0
- package/dist/client/permissions/MenuItemsProvider.d.ts +4 -0
- package/dist/client/permissions/MenuPermissions.d.ts +4 -0
- package/dist/client/permissions/Permissions.d.ts +4 -0
- package/dist/client/permissions/PluginPermissions.d.ts +4 -0
- package/dist/client/permissions/RolesResourcesActions.d.ts +3 -0
- package/dist/client/permissions/ScopeSelect.d.ts +3 -0
- package/dist/client/permissions/StrategyActions.d.ts +2 -0
- package/dist/client/permissions/style.d.ts +1 -0
- package/dist/client/roles-manager.d.ts +10 -0
- package/dist/client/schemas/roles.d.ts +54 -0
- package/dist/client/schemas/scopes.d.ts +67 -0
- package/dist/externalVersion.js +18 -7
- package/dist/locale/en-US.json +3 -1
- package/dist/locale/zh-CN.json +3 -1
- package/dist/server/collections/roles.js +2 -2
- package/dist/server/collections/rolesResources.js +3 -1
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.js +14 -0
- package/dist/server/middlewares/setCurrentRole.js +11 -6
- package/dist/server/middlewares/with-acl-meta.d.ts +2 -0
- package/dist/server/middlewares/with-acl-meta.js +236 -0
- package/dist/server/model/RoleModel.d.ts +1 -0
- package/dist/server/model/RoleModel.js +6 -4
- package/dist/server/server.d.ts +2 -2
- package/dist/server/server.js +59 -204
- package/package.json +4 -4
package/dist/client/index.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Plugin } from '@nocobase/client';
|
|
2
|
-
|
|
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
|
|
7
|
+
export default ACLPlugin;
|
|
8
|
+
export { RolesManagerContext } from './RolesManagerProvider';
|
package/dist/client/index.js
CHANGED
|
@@ -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(d,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):(d=typeof globalThis!="undefined"?globalThis:d||self,u(d["@nocobase/plugin-acl"]={},d["@nocobase/client"],d.jsxRuntime,d.react,d.antd,d["@formily/react"],d["@ant-design/icons"],d["react-i18next"],d["@formily/shared"],d["@nocobase/utils"],d["@formily/core"],d.ahooks,d.lodash,d["antd-style"]))})(this,function(d,u,s,g,p,I,G,S,x,k,de,Qe,Z,Re){"use strict";var Si=Object.defineProperty,wi=Object.defineProperties;var Ai=Object.getOwnPropertyDescriptors;var Ze=Object.getOwnPropertySymbols;var Pi=Object.prototype.hasOwnProperty,Ii=Object.prototype.propertyIsEnumerable;var ue=(d,u,s)=>u in d?Si(d,u,{enumerable:!0,configurable:!0,writable:!0,value:s}):d[u]=s,P=(d,u)=>{for(var s in u||(u={}))Pi.call(u,s)&&ue(d,s,u[s]);if(Ze)for(var s of Ze(u))Ii.call(u,s)&&ue(d,s,u[s]);return d},E=(d,u)=>wi(d,Ai(u));var pe=(d,u,s)=>(ue(d,typeof u!="symbol"?u+"":u,s),s);var w=(d,u,s)=>new Promise((g,p)=>{var I=x=>{try{S(s.next(x))}catch(k){p(k)}},G=x=>{try{S(s.throw(x))}catch(k){p(k)}},S=x=>x.done?g(x.value):Promise.resolve(x.value).then(I,G);S((s=s.apply(d,u)).next())});function T(){return S.useTranslation(["acl","client"],{nsMode:"fallback"})}const A=g.createContext({role:null});A.displayName="RolesManagerContext";var U=typeof globalThis!="undefined"?globalThis:typeof window!="undefined"?window:typeof global!="undefined"?global:typeof self!="undefined"?self:{};function he(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var et=Array.isArray,q=et,tt=typeof U=="object"&&U&&U.Object===Object&&U,rt=tt,nt=rt,at=typeof self=="object"&&self&&self.Object===Object&&self,st=nt||at||Function("return this")(),K=st,ot=K,it=ot.Symbol,z=it,fe=z,ve=Object.prototype,ct=ve.hasOwnProperty,lt=ve.toString,j=fe?fe.toStringTag:void 0;function ut(e){var t=ct.call(e,j),r=e[j];try{e[j]=void 0;var n=!0}catch(i){}var a=lt.call(e);return n&&(t?e[j]=r:delete e[j]),a}var pt=ut,dt=Object.prototype,ht=dt.toString;function ft(e){return ht.call(e)}var vt=ft,ge=z,gt=pt,mt=vt,yt="[object Null]",_t="[object Undefined]",me=ge?ge.toStringTag:void 0;function bt(e){return e==null?e===void 0?_t:yt:me&&me in Object(e)?gt(e):mt(e)}var Q=bt;function $t(e){return e!=null&&typeof e=="object"}var R=$t,Ct=Q,xt=R,St="[object Symbol]";function wt(e){return typeof e=="symbol"||xt(e)&&Ct(e)==St}var ee=wt,At=q,Pt=ee,It=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Tt=/^\w*$/;function Ot(e,t){if(At(e))return!1;var r=typeof e;return r=="number"||r=="symbol"||r=="boolean"||e==null||Pt(e)?!0:Tt.test(e)||!It.test(e)||t!=null&&e in Object(t)}var Mt=Ot;function Ft(e){var t=typeof e;return e!=null&&(t=="object"||t=="function")}var te=Ft,Dt=Q,Nt=te,Et="[object AsyncFunction]",kt="[object Function]",qt="[object GeneratorFunction]",jt="[object Proxy]";function Ht(e){if(!Nt(e))return!1;var t=Dt(e);return t==kt||t==qt||t==Et||t==jt}var Gt=Ht,Ut=K,Kt=Ut["__core-js_shared__"],zt=Kt,re=zt,ye=function(){var e=/[^.]+$/.exec(re&&re.keys&&re.keys.IE_PROTO||"");return e?"Symbol(src)_1."+e:""}();function Lt(e){return!!ye&&ye in e}var Vt=Lt,Wt=Function.prototype,Bt=Wt.toString;function Yt(e){if(e!=null){try{return Bt.call(e)}catch(t){}try{return e+""}catch(t){}}return""}var Xt=Yt,Jt=Gt,Zt=Vt,Qt=te,Rt=Xt,er=/[\\^$.*+?()[\]{}|]/g,tr=/^\[object .+?Constructor\]$/,rr=Function.prototype,nr=Object.prototype,ar=rr.toString,sr=nr.hasOwnProperty,or=RegExp("^"+ar.call(sr).replace(er,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function ir(e){if(!Qt(e)||Zt(e))return!1;var t=Jt(e)?or:tr;return t.test(Rt(e))}var cr=ir;function lr(e,t){return e==null?void 0:e[t]}var ur=lr,pr=cr,dr=ur;function hr(e,t){var r=dr(e,t);return pr(r)?r:void 0}var L=hr,fr=L,vr=fr(Object,"create"),V=vr,_e=V;function gr(){this.__data__=_e?_e(null):{},this.size=0}var mr=gr;function yr(e){var t=this.has(e)&&delete this.__data__[e];return this.size-=t?1:0,t}var _r=yr,br=V,$r="__lodash_hash_undefined__",Cr=Object.prototype,xr=Cr.hasOwnProperty;function Sr(e){var t=this.__data__;if(br){var r=t[e];return r===$r?void 0:r}return xr.call(t,e)?t[e]:void 0}var wr=Sr,Ar=V,Pr=Object.prototype,Ir=Pr.hasOwnProperty;function Tr(e){var t=this.__data__;return Ar?t[e]!==void 0:Ir.call(t,e)}var Or=Tr,Mr=V,Fr="__lodash_hash_undefined__";function Dr(e,t){var r=this.__data__;return this.size+=this.has(e)?0:1,r[e]=Mr&&t===void 0?Fr:t,this}var Nr=Dr,Er=mr,kr=_r,qr=wr,jr=Or,Hr=Nr;function O(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])}}O.prototype.clear=Er,O.prototype.delete=kr,O.prototype.get=qr,O.prototype.has=jr,O.prototype.set=Hr;var Gr=O;function Ur(){this.__data__=[],this.size=0}var Kr=Ur;function zr(e,t){return e===t||e!==e&&t!==t}var be=zr,Lr=be;function Vr(e,t){for(var r=e.length;r--;)if(Lr(e[r][0],t))return r;return-1}var W=Vr,Wr=W,Br=Array.prototype,Yr=Br.splice;function Xr(e){var t=this.__data__,r=Wr(t,e);if(r<0)return!1;var n=t.length-1;return r==n?t.pop():Yr.call(t,r,1),--this.size,!0}var Jr=Xr,Zr=W;function Qr(e){var t=this.__data__,r=Zr(t,e);return r<0?void 0:t[r][1]}var Rr=Qr,en=W;function tn(e){return en(this.__data__,e)>-1}var rn=tn,nn=W;function an(e,t){var r=this.__data__,n=nn(r,e);return n<0?(++this.size,r.push([e,t])):r[n][1]=t,this}var sn=an,on=Kr,cn=Jr,ln=Rr,un=rn,pn=sn;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=on,M.prototype.delete=cn,M.prototype.get=ln,M.prototype.has=un,M.prototype.set=pn;var dn=M,hn=L,fn=K,vn=hn(fn,"Map"),gn=vn,$e=Gr,mn=dn,yn=gn;function _n(){this.size=0,this.__data__={hash:new $e,map:new(yn||mn),string:new $e}}var bn=_n;function $n(e){var t=typeof e;return t=="string"||t=="number"||t=="symbol"||t=="boolean"?e!=="__proto__":e===null}var Cn=$n,xn=Cn;function Sn(e,t){var r=e.__data__;return xn(t)?r[typeof t=="string"?"string":"hash"]:r.map}var B=Sn,wn=B;function An(e){var t=wn(this,e).delete(e);return this.size-=t?1:0,t}var Pn=An,In=B;function Tn(e){return In(this,e).get(e)}var On=Tn,Mn=B;function Fn(e){return Mn(this,e).has(e)}var Dn=Fn,Nn=B;function En(e,t){var r=Nn(this,e),n=r.size;return r.set(e,t),this.size+=r.size==n?0:1,this}var kn=En,qn=bn,jn=Pn,Hn=On,Gn=Dn,Un=kn;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=qn,F.prototype.delete=jn,F.prototype.get=Hn,F.prototype.has=Gn,F.prototype.set=Un;var Ce=F,xe=Ce,Kn="Expected a function";function ne(e,t){if(typeof e!="function"||t!=null&&typeof t!="function")throw new TypeError(Kn);var r=function(){var n=arguments,a=t?t.apply(this,n):n[0],i=r.cache;if(i.has(a))return i.get(a);var o=e.apply(this,n);return r.cache=i.set(a,o)||i,o};return r.cache=new(ne.Cache||xe),r}ne.Cache=xe;var zn=ne,Ln=zn,Vn=500;function Wn(e){var t=Ln(e,function(n){return r.size===Vn&&r.clear(),n}),r=t.cache;return t}var Bn=Wn,Yn=Bn,Xn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Jn=/\\(\\)?/g,Zn=Yn(function(e){var t=[];return e.charCodeAt(0)===46&&t.push(""),e.replace(Xn,function(r,n,a,i){t.push(a?i.replace(Jn,"$1"):n||r)}),t}),Qn=Zn;function Rn(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 ea=Rn,Se=z,ta=ea,ra=q,na=ee,aa=1/0,we=Se?Se.prototype:void 0,Ae=we?we.toString:void 0;function Pe(e){if(typeof e=="string")return e;if(ra(e))return ta(e,Pe)+"";if(na(e))return Ae?Ae.call(e):"";var t=e+"";return t=="0"&&1/e==-aa?"-0":t}var sa=Pe,oa=sa;function ia(e){return e==null?"":oa(e)}var ca=ia,la=q,ua=Mt,pa=Qn,da=ca;function ha(e,t){return la(e)?e:ua(e,t)?[e]:pa(da(e))}var Y=ha,fa=ee,va=1/0;function ga(e){if(typeof e=="string"||fa(e))return e;var t=e+"";return t=="0"&&1/e==-va?"-0":t}var ae=ga,ma=Y,ya=ae;function _a(e,t){t=ma(t,e);for(var r=0,n=t.length;e!=null&&r<n;)e=e[ya(t[r++])];return r&&r==n?e:void 0}var ba=_a,$a=L,Ca=function(){try{var e=$a(Object,"defineProperty");return e({},"",{}),e}catch(t){}}(),Ie=Ca,Te=Ie;function xa(e,t,r){t=="__proto__"&&Te?Te(e,t,{configurable:!0,enumerable:!0,value:r,writable:!0}):e[t]=r}var Sa=xa,wa=Sa,Aa=be,Pa=Object.prototype,Ia=Pa.hasOwnProperty;function Ta(e,t,r){var n=e[t];(!(Ia.call(e,t)&&Aa(n,r))||r===void 0&&!(t in e))&&wa(e,t,r)}var Oa=Ta,Ma=9007199254740991,Fa=/^(?:0|[1-9]\d*)$/;function Da(e,t){var r=typeof e;return t=t==null?Ma:t,!!t&&(r=="number"||r!="symbol"&&Fa.test(e))&&e>-1&&e%1==0&&e<t}var Oe=Da,Na=Oa,Ea=Y,ka=Oe,Me=te,qa=ae;function ja(e,t,r,n){if(!Me(e))return e;t=Ea(t,e);for(var a=-1,i=t.length,o=i-1,c=e;c!=null&&++a<i;){var l=qa(t[a]),f=r;if(l==="__proto__"||l==="constructor"||l==="prototype")return e;if(a!=o){var v=c[l];f=n?n(v,l,c):void 0,f===void 0&&(f=Me(v)?v:ka(t[a+1])?[]:{})}Na(c,l,f),c=c[l]}return e}var Ha=ja,Ga=ba,Ua=Ha,Ka=Y;function za(e,t,r){for(var n=-1,a=t.length,i={};++n<a;){var o=t[n],c=Ga(e,o);r(c,o)&&Ua(i,Ka(o,e),c)}return i}var La=za;function Va(e,t){return e!=null&&t in Object(e)}var Wa=Va,Ba=Q,Ya=R,Xa="[object Arguments]";function Ja(e){return Ya(e)&&Ba(e)==Xa}var Za=Ja,Fe=Za,Qa=R,De=Object.prototype,Ra=De.hasOwnProperty,es=De.propertyIsEnumerable,ts=Fe(function(){return arguments}())?Fe:function(e){return Qa(e)&&Ra.call(e,"callee")&&!es.call(e,"callee")},Ne=ts,rs=9007199254740991;function ns(e){return typeof e=="number"&&e>-1&&e%1==0&&e<=rs}var as=ns,ss=Y,os=Ne,is=q,cs=Oe,ls=as,us=ae;function ps(e,t,r){t=ss(t,e);for(var n=-1,a=t.length,i=!1;++n<a;){var o=us(t[n]);if(!(i=e!=null&&r(e,o)))break;e=e[o]}return i||++n!=a?i:(a=e==null?0:e.length,!!a&&ls(a)&&cs(o,a)&&(is(e)||os(e)))}var ds=ps,hs=Wa,fs=ds;function vs(e,t){return e!=null&&fs(e,t,hs)}var gs=vs,ms=La,ys=gs;function _s(e,t){return ms(e,t,function(r,n){return ys(e,n)})}var bs=_s;function $s(e,t){for(var r=-1,n=t.length,a=e.length;++r<n;)e[a+r]=t[r];return e}var Cs=$s,Ee=z,xs=Ne,Ss=q,ke=Ee?Ee.isConcatSpreadable:void 0;function ws(e){return Ss(e)||xs(e)||!!(ke&&e&&e[ke])}var As=ws,Ps=Cs,Is=As;function qe(e,t,r,n,a){var i=-1,o=e.length;for(r||(r=Is),a||(a=[]);++i<o;){var c=e[i];t>0&&r(c)?t>1?qe(c,t-1,r,n,a):Ps(a,c):n||(a[a.length]=c)}return a}var Ts=qe,Os=Ts;function Ms(e){var t=e==null?0:e.length;return t?Os(e,1):[]}var Fs=Ms;function Ds(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 Ns=Ds,Es=Ns,je=Math.max;function ks(e,t,r){return t=je(t===void 0?e.length-1:t,0),function(){for(var n=arguments,a=-1,i=je(n.length-t,0),o=Array(i);++a<i;)o[a]=n[t+a];a=-1;for(var c=Array(t+1);++a<t;)c[a]=n[a];return c[t]=r(o),Es(e,this,c)}}var qs=ks;function js(e){return function(){return e}}var Hs=js;function Gs(e){return e}var Us=Gs,Ks=Hs,He=Ie,zs=Us,Ls=He?function(e,t){return He(e,"toString",{configurable:!0,enumerable:!1,value:Ks(t),writable:!0})}:zs,Vs=Ls,Ws=800,Bs=16,Ys=Date.now;function Xs(e){var t=0,r=0;return function(){var n=Ys(),a=Bs-(n-r);if(r=n,a>0){if(++t>=Ws)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}var Js=Xs,Zs=Vs,Qs=Js,Rs=Qs(Zs),eo=Rs,to=Fs,ro=qs,no=eo;function ao(e){return no(ro(e,void 0,to),e+"")}var so=ao,oo=bs,io=so,co=io(function(e,t){return e==null?{}:oo(e,t)}),lo=co;const uo=he(lo),po={type:"object",properties:{[x.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:uo(t,["title","name","default"])}),E(P({},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 }}"}}}}}}}},se=()=>{const{t:e}=T(),{data:t}=u.useResourceActionContext(),[r,n]=g.useState(!1),[a,i]=g.useState(null),{role:o,setRole:c}=g.useContext(A),l=((t==null?void 0:t.data)||[]).map(v=>({key:v.name,label:s.jsx(se.Item,{item:v,onEdit:()=>{n(!0),i(v)}})})),f=({key:v})=>{c(((t==null?void 0:t.data)||[]).find(m=>m.name===v))};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:[o==null?void 0:o.name],onSelect:f}):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:po})})})]})};se.Item=function({item:t,onEdit:r}){const{t:n}=T(),{refreshAsync:a}=u.useResourceActionContext(),{modal:i,message:o}=p.App.useApp(),c=u.useAPIClient(),l=()=>{i.confirm({title:n("Delete"),content:n("Are you sure you want to delete it?"),onOk:()=>w(this,null,function*(){yield c.resource("roles").destroy({filterByTk:t.name}),o.success(n("Deleted successfully")),yield a()})})},f=({key:v,domEvent:m})=>{switch(m.stopPropagation(),v){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:I.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:f},children:s.jsx(G.MoreOutlined,{})})]})]})};const oe=g.createContext([]);oe.displayName="AvailableActionsContext";const ho=e=>{const{data:t,loading:r}=u.useRequest({resource:"availableActions",action:"list"});return r?s.jsx(p.Spin,{}):s.jsx(oe.Provider,{value:t==null?void 0:t.data,children:e.children})},fo=()=>g.useContext(oe);var vo="__lodash_hash_undefined__";function go(e){return this.__data__.set(e,vo),this}var mo=go;function yo(e){return this.__data__.has(e)}var _o=yo,bo=Ce,$o=mo,Co=_o;function X(e){var t=-1,r=e==null?0:e.length;for(this.__data__=new bo;++t<r;)this.add(e[t])}X.prototype.add=X.prototype.push=$o,X.prototype.has=Co;var xo=X;function So(e,t,r,n){for(var a=e.length,i=r+(n?1:-1);n?i--:++i<a;)if(t(e[i],i,e))return i;return-1}var wo=So;function Ao(e){return e!==e}var Po=Ao;function Io(e,t,r){for(var n=r-1,a=e.length;++n<a;)if(e[n]===t)return n;return-1}var To=Io,Oo=wo,Mo=Po,Fo=To;function Do(e,t,r){return t===t?Fo(e,t,r):Oo(e,Mo,r)}var No=Do,Eo=No;function ko(e,t){var r=e==null?0:e.length;return!!r&&Eo(e,t,0)>-1}var qo=ko;function jo(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 Ho=jo;function Go(e,t){return e.has(t)}var Uo=Go,Ko=L,zo=K,Lo=Ko(zo,"Set"),Vo=Lo;function Wo(){}var Bo=Wo;function Yo(e){var t=-1,r=Array(e.size);return e.forEach(function(n){r[++t]=n}),r}var Ge=Yo,ie=Vo,Xo=Bo,Jo=Ge,Zo=1/0,Qo=ie&&1/Jo(new ie([,-0]))[1]==Zo?function(e){return new ie(e)}:Xo,Ro=Qo,ei=xo,ti=qo,ri=Ho,ni=Uo,ai=Ro,si=Ge,oi=200;function ii(e,t,r){var n=-1,a=ti,i=e.length,o=!0,c=[],l=c;if(r)o=!1,a=ri;else if(i>=oi){var f=t?null:ai(e);if(f)return si(f);o=!1,a=ni,l=new ei}else l=t?[]:c;e:for(;++n<i;){var v=e[n],m=t?t(v):v;if(v=r||v!==0?v:0,o&&m===m){for(var C=l.length;C--;)if(l[C]===m)continue e;t&&l.push(m),c.push(v)}else a(l,m,r)||(l!==c&&l.push(m),c.push(v))}return c}var ci=ii,li=ci;function ui(e){return e&&e.length?li(e):[]}var pi=ui;const di=he(pi),hi=e=>{var r;if(!e)return{};const t={};return(r=e==null?void 0:e.forEach)==null||r.call(e,n=>{const[a,i]=n.split(":");t[a]=i||"all"}),t},Ue=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},fi=I.connect(e=>{const{onChange:t}=e,r=fo(),n=u.useCompile(),{t:a}=S.useTranslation(),i=I.useField(),o=hi(i.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:f=>{c?delete o[l.name]:o[l.name]="all",t(Ue(o))}})},{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:f=>{o[l.name]=f,t(Ue(o))}})}],dataSource:r==null?void 0:r.map(c=>{let l="all",f=!1;return o[c.name]&&(f=!0,l=o[c.name]),E(P({},c),{enabled:f,scope:l})})})})}),vi=I.connect(e=>{const{t}=S.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(o=>`!${o}`),i=di([...e.value||[],...r]).filter(o=>o&&!a.includes(o)).map(o=>!n.includes(o)||r!=null&&r.includes(o)?o:`!${o}`);for(const o of n)!i.includes(o)&&!i.includes(`!${o}`)&&i.push(`!${o}`);e.onChange(i)},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")})})]})}),gi=({active:e})=>{const{role:t,setRole:r}=g.useContext(A),{t:n}=T(),a=u.useAPIClient(),{data:i}=u.useRequest(()=>a.resource("roles").get({filterByTk:t==null?void 0:t.name}).then(l=>{var v,m;const f=(v=l==null?void 0:l.data)==null?void 0:v.data;return(m=f.snippets)==null||m.forEach(C=>{f[C]=!0}),f}),{ready:e,refreshDeps:[t==null?void 0:t.name]}),o=Qe.useMemoizedFn(l=>w(this,null,function*(){yield a.resource("roles").update({filterByTk:t.name,values:l.values}),r(P(P({},t),l.values)),p.message.success(n("Saved successfully"))})),c=g.useMemo(()=>de.createForm({values:i,effects(){de.onFormValuesChange(l=>w(this,null,function*(){yield o(l)}))}}),[i,o]);return s.jsx(u.SchemaComponent,{components:{SnippetCheckboxGroup:vi,StrategyActions:fi},schema:{type:"void",name:x.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.")}}}})},ce=g.createContext(null);ce.displayName="MenuItemsContext";const 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},mi=()=>g.useContext(ce),ze=e=>{var i,o;const r={url:`uiSchemas:getProperties/${u.useAdminSchemaUid()}`},n=u.useRequest(r);if(n.loading)return s.jsx(p.Spin,{});const a=Ke((o=(i=n.data)==null?void 0:i.data)==null?void 0:o.properties);return s.jsx(ce.Provider,{value:{service:n,items:a},children:e.children})},Le=Re.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
|
+
`),Ve=e=>{if(!Array.isArray(e))return[];const t=[];for(const r of e)t.push(r.uid),t.push(...Ve(r.children));return t},We=(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=We(n.children,t,r);if(a.length)return a}r.pop()}return[]},Be=(e=[],t=[])=>{for(const r of e)t.push(r.uid),r.children&&r.children.length&&Be(r.children,t);return t},yi=({active:e})=>{const{styles:t}=Le(),{role:r}=g.useContext(A),n=u.useAPIClient(),{items:a}=mi(),{t:i}=S.useTranslation(),o=Ve(a),[c,l]=g.useState([]),{loading:f,refresh:v}=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 y;l(((y=b==null?void 0:b.data)==null?void 0:y.map(h=>h["x-uid"]))||[])}}),m=n.resource("roles.menuUiSchemas",r.name),C=o.length===c.length,le=(b,y)=>w(this,null,function*(){const h=We(a,$=>$.uid===y.uid),_=Be(y==null?void 0:y.children,[]);if(b){const $=_.concat(y.uid),N=c.filter(H=>!$.includes(H));l([...N]),yield m.remove({values:$})}else{const $=_.concat(h);l(N=>Z.uniq([...N,...$])),yield m.add({values:$})}p.message.success(i("Saved successfully"))}),D=b=>b.map(y=>{const h=i(y.title);return y.children?E(P({},y),{title:h,children:D(y.children)}):E(P({},y),{title:h})});return s.jsx(p.Table,{className:t,loading:f,rowKey:"uid",pagination:!1,expandable:{defaultExpandAllRows:!0},columns:[{dataIndex:"title",title:i("Menu item title")},{dataIndex:"accessible",title:s.jsxs(s.Fragment,{children:[s.jsx(p.Checkbox,{checked:C,onChange:b=>w(this,null,function*(){C?yield m.set({values:[]}):yield m.set({values:o}),v(),p.message.success(i("Saved successfully"))})})," ",i("Accessible")]}),render:(b,y)=>{const h=c.includes(y.uid);return s.jsx(p.Checkbox,{checked:h,onChange:()=>le(h,y)})}}],dataSource:D(a)})},Ye=(e=[],t=[])=>{for(const r of e)t.push(r.aclSnippet),r.children&&r.children.length&&Ye(r.children,t);return t},_i=({active:e})=>{const t=u.useApp(),{styles:r}=Le(),{role:n}=g.useContext(A),a=u.useAPIClient(),i=u.useCompile(),o=t.pluginSettingsManager.getList(!1),c=t.pluginSettingsManager.getAclSnippets(),[l,f]=g.useState([]),v=g.useMemo(()=>Z.flatMap(o,h=>h.children?[h,...h.children]:h),[o]),m=g.useMemo(()=>l.includes("pm.*")&&l.every(h=>!h.startsWith("!pm.")),[l]),{t:C}=S.useTranslation(),{loading:le,refresh:D}=u.useRequest({resource:"roles.snippets",resourceOf:n.name,action:"list",params:{paginate:!1}},{ready:!!n&&e,refreshDeps:[n==null?void 0:n.name],onSuccess(h){f((h==null?void 0:h.data.filter(_=>v.find($=>_.includes(`!${$.aclSnippet}`)||!_.startsWith("!pm."))))||[])}}),b=a.resource("roles.snippets",n.name),y=(h,_)=>w(this,null,function*(){const N=Ye(_==null?void 0:_.children,[]).concat(_.aclSnippet);h?(yield b.add({values:N.map(H=>"!"+H)}),D()):(yield b.remove({values:N.map(H=>"!"+H)}),D()),p.message.success(C("Saved successfully"))});return s.jsx(p.Table,{className:r,loading:le,rowKey:"key",pagination:!1,expandable:{defaultExpandAllRows:!0},columns:[{dataIndex:"title",title:C("Plugin name"),render:h=>i(h)},{dataIndex:"accessible",title:s.jsxs(s.Fragment,{children:[s.jsx(p.Checkbox,{checked:m,onChange:()=>w(this,null,function*(){const h=c.map(_=>"!"+_);m?yield b.add({values:h}):yield b.remove({values:h}),D(),p.message.success(C("Saved successfully"))})})," ",C("Accessible")]}),render:(h,_)=>{const $=!l.includes("!"+_.aclSnippet);return s.jsx(p.Checkbox,{checked:$,onChange:()=>y($,_)})}}],dataSource:o.filter(h=>h.isTopLevel!==!1).map(h=>h.showTabs!==!1?h:Z.omit(h,"children"))})},J=e=>s.jsx("div",{style:{maxHeight:"60vh",overflowY:"auto"},children:e.children}),bi=({active:e})=>{var f;const{t}=T(),[r,n]=g.useState("general"),{role:a}=g.useContext(A),i=(f=a==null?void 0:a.snippets)==null?void 0:f.includes("pm.*"),c=u.useApp().getComponent("DataSourcePermissionManager"),l=g.useMemo(()=>[{key:"general",label:t("General"),children:s.jsx(J,{children:s.jsx(gi,{active:r==="general"&&e})})},{key:"menu",label:t("Menu"),children:s.jsx(J,{children:s.jsx(ze,{children:s.jsx(yi,{active:r==="menu"&&e})})})},...i?[{key:"plugin",label:t("Plugin settings"),children:s.jsx(J,{children:s.jsx(_i,{active:r==="plugin"&&e})})}]:[],...c?[{key:"dataSource",label:t("Data sources"),children:s.jsx(J,{children:s.jsx(ze,{children:s.jsx(c,{role:a,active:r==="dataSource"&&e})})})}]:[]],[i,r,e,t]);return g.useEffect(()=>{n("general")},[a==null?void 0:a.name]),s.jsx(ho,{children:s.jsx(p.Tabs,{type:"card",activeKey:r,onChange:v=>n(v),items:l})})},$i=()=>{const{t:e}=T();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_${x.uid()}`,snippets:["!ui.*","!pm","!pm.*"]}}),E(P({},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 }}"}}}}}}}}}}})},Xe={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"}}]},Ci=()=>{const{t:e}=T(),t=u.usePlugin(Je),[r,n]=g.useState("permissions"),a=Array.from(t.rolesManager.list()).map(([c,l])=>({key:c,label:I.Schema.compile(l.title,{t:e}),children:l.Component?g.createElement(l.Component,{active:r===c}):null})),[i,o]=g.useState(null);return s.jsx(A.Provider,{value:{role:i,setRole:o},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:Xe,request:{resource:"roles",action:"list",params:{pagination:!1,filter:{"name.$ne":"root"},showAnonymous:!0,sort:["createdAt"],appends:[]}},children:s.jsxs(u.CollectionProvider_deprecated,{collection:Xe,children:[s.jsx(p.Row,{children:s.jsx($i,{})}),s.jsx(p.Divider,{style:{margin:"12px 0"}}),s.jsx(se,{})]})})}),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(bi,{active:r==="permissions"})},...a]})})]})})})};class xi{constructor(){pe(this,"rolesManager",new k.Registry)}add(t,r){this.rolesManager.register(t,r)}list(){return this.rolesManager.getEntities()}}class Je extends u.Plugin{constructor(){super(...arguments);pe(this,"rolesManager",new xi)}load(){return w(this,null,function*(){this.app.pluginSettingsManager.add("users-permissions.roles",{title:'{{t("Roles & Permissions")}}',icon:"LockOutlined",Component:Ci,aclSnippet:"pm.acl.roles",sort:3})})}}d.RolesManagerContext=A,d.default=Je,Object.defineProperties(d,{__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 @@
|
|
|
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;
|
package/dist/externalVersion.js
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
"@nocobase/client": "0.
|
|
3
|
-
"
|
|
4
|
-
"@
|
|
5
|
-
"
|
|
6
|
-
"@
|
|
7
|
-
"@
|
|
2
|
+
"@nocobase/client": "0.20.0-alpha.10",
|
|
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.10",
|
|
10
|
+
"@nocobase/actions": "0.20.0-alpha.10",
|
|
11
|
+
"@nocobase/cache": "0.20.0-alpha.10",
|
|
12
|
+
"@nocobase/database": "0.20.0-alpha.10",
|
|
13
|
+
"@nocobase/server": "0.20.0-alpha.10",
|
|
8
14
|
"async-mutex": "0.3.2",
|
|
9
15
|
"lodash": "4.17.21",
|
|
10
|
-
"@nocobase/test": "0.
|
|
16
|
+
"@nocobase/test": "0.20.0-alpha.10",
|
|
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.10"
|
|
11
22
|
};
|
package/dist/locale/en-US.json
CHANGED
|
@@ -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
|
}
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -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: "
|
|
98
|
+
target: "dataSourcesRolesResources",
|
|
99
99
|
sourceKey: "name",
|
|
100
|
-
|
|
100
|
+
foreignKey: "roleName"
|
|
101
101
|
},
|
|
102
102
|
{
|
|
103
103
|
type: "set",
|
package/dist/server/index.d.ts
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -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
|
-
|
|
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 =
|
|
55
|
+
ctx.state.currentRole = (_a = userRoles.find((role) => role.name === currentRole)) == null ? void 0 : _a.name;
|
|
51
56
|
} else {
|
|
52
|
-
const defaultRole =
|
|
57
|
+
const defaultRole = userRoles.find((role) => {
|
|
53
58
|
var _a2;
|
|
54
|
-
return (_a2 =
|
|
59
|
+
return (_a2 = role == null ? void 0 : role.rolesUsers) == null ? void 0 : _a2.default;
|
|
55
60
|
});
|
|
56
|
-
ctx.state.currentRole = (_b = defaultRole ||
|
|
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,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
|
+
});
|
|
@@ -31,10 +31,12 @@ class RoleModel extends import_database.Model {
|
|
|
31
31
|
role: roleName
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
}
|
package/dist/server/server.d.ts
CHANGED
|
@@ -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,
|
|
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>;
|
package/dist/server/server.js
CHANGED
|
@@ -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,
|
|
140
|
-
|
|
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,
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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("
|
|
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",
|
|
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("
|
|
409
|
+
const rolesResourcesScopes = this.app.db.getRepository("dataSourcesRolesResourcesScopes");
|
|
380
410
|
await rolesResourcesScopes.createMany({
|
|
381
411
|
records: [
|
|
382
412
|
{
|
|
@@ -541,6 +571,10 @@ class PluginACL extends import_server.Plugin {
|
|
|
541
571
|
const action = (_b = (_a = ctx.permission) == null ? void 0 : _a.can) == null ? void 0 : _b.action;
|
|
542
572
|
if (action == "destroy" && !ctx.action.resourceName.includes(".")) {
|
|
543
573
|
const repository = import_actions.utils.getRepositoryFromParams(ctx);
|
|
574
|
+
if (!repository) {
|
|
575
|
+
await next();
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
544
578
|
const filteredCount = await repository.count(ctx.permission.mergedParams);
|
|
545
579
|
const queryCount = await repository.count(ctx.permission.rawParams);
|
|
546
580
|
if (queryCount > filteredCount) {
|
|
@@ -555,186 +589,7 @@ class PluginACL extends import_server.Plugin {
|
|
|
555
589
|
group: "after"
|
|
556
590
|
}
|
|
557
591
|
);
|
|
558
|
-
const withACLMeta =
|
|
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
|
-
};
|
|
592
|
+
const withACLMeta = (0, import_with_acl_meta.createWithACLMetaMiddleware)();
|
|
738
593
|
this.app.use(
|
|
739
594
|
async (ctx, next) => {
|
|
740
595
|
try {
|
package/package.json
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
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.
|
|
7
|
+
"version": "0.20.0-alpha.10",
|
|
8
8
|
"license": "AGPL-3.0",
|
|
9
9
|
"main": "./dist/server/index.js",
|
|
10
|
-
"homepage": "https://docs.nocobase.com/
|
|
11
|
-
"homepage.zh-CN": "https://docs-cn.nocobase.com/
|
|
10
|
+
"homepage": "https://docs.nocobase.com/handbook/acl",
|
|
11
|
+
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/acl",
|
|
12
12
|
"keywords": [
|
|
13
13
|
"Users & permissions"
|
|
14
14
|
],
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
35
35
|
"directory": "packages/plugins/acl"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "453e0774dae21750e96c7ddd2019c8889a0314d6"
|
|
38
38
|
}
|