From ebfb3caeecf4a483e0858ec411296fb9bf7239ce Mon Sep 17 00:00:00 2001 From: zhangwenjian Date: Sun, 15 Mar 2020 20:41:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=90=86=E4=BB=A3=E7=A0=81=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1735f619b0622cef0d25c4800d6f27cd.jpg | Bin 30661 -> 0 bytes .../193c18d2-ba46-48e9-ace1-0f774d16706a.jpeg | Bin 27325 -> 0 bytes .../802e4e8d-076f-4bfd-ab1c-668e96684b9a.jpeg | Bin 27325 -> 0 bytes .../abe81acd-7320-4a1a-86e6-a57075ede104.jpeg | 0 .../dab3404f-e77c-4166-81b4-c67451a8fd25.jpeg | Bin 27325 -> 0 bytes .../github.com/casbin/casbin/.gitignore | 30 -- .../github.com/casbin/casbin/.travis.yml | 14 - .../vendor/github.com/casbin/casbin/LICENSE | 201 -------- .../vendor/github.com/casbin/casbin/README.md | 274 ---------- .../github.com/casbin/casbin/casbin-logo.png | Bin 34267 -> 0 bytes .../github.com/casbin/casbin/config/config.go | 266 ---------- .../casbin/casbin/effect/default_effector.go | 75 --- .../casbin/casbin/effect/effector.go | 31 -- .../github.com/casbin/casbin/enforcer.go | 483 ------------------ .../casbin/casbin/enforcer_cached.go | 85 --- .../github.com/casbin/casbin/enforcer_safe.go | 200 -------- .../casbin/casbin/enforcer_synced.go | 223 -------- .../casbin/casbin/enforcer_synced_safe.go | 63 --- .../casbin/casbin/errors/rbac_errors.go | 24 - .../vendor/github.com/casbin/casbin/go.mod | 3 - .../vendor/github.com/casbin/casbin/go.sum | 2 - .../github.com/casbin/casbin/internal_api.go | 85 --- .../casbin/casbin/log/default_logger.go | 42 -- .../github.com/casbin/casbin/log/log_util.go | 37 -- .../github.com/casbin/casbin/log/logger.go | 30 -- .../casbin/casbin/management_api.go | 265 ---------- .../casbin/casbin/model/assertion.go | 60 --- .../casbin/casbin/model/function.go | 40 -- .../github.com/casbin/casbin/model/model.go | 130 ----- .../github.com/casbin/casbin/model/policy.go | 146 ------ .../casbin/casbin/persist/adapter.go | 55 -- .../casbin/casbin/persist/adapter_filtered.go | 29 -- .../casbin/persist/file-adapter/adapter.go | 117 ----- .../persist/file-adapter/adapter_filtered.go | 138 ----- .../persist/file-adapter/adapter_mock.go | 100 ---- .../casbin/casbin/persist/watcher.go | 29 -- .../rbac/default-role-manager/role_manager.go | 298 ----------- .../casbin/casbin/rbac/role_manager.go | 38 -- .../github.com/casbin/casbin/rbac_api.go | 205 -------- .../casbin/casbin/rbac_api_synced.go | 121 ----- .../casbin/casbin/rbac_api_with_domains.go | 44 -- .../casbin/rbac_api_with_domains_synced.go | 52 -- .../casbin/casbin/util/builtin_operators.go | 160 ------ .../github.com/casbin/casbin/util/util.go | 151 ------ 44 files changed, 4346 deletions(-) delete mode 100644 src/goadmin/static/uploadfile/1735f619b0622cef0d25c4800d6f27cd.jpg delete mode 100644 src/goadmin/static/uploadfile/193c18d2-ba46-48e9-ace1-0f774d16706a.jpeg delete mode 100644 src/goadmin/static/uploadfile/802e4e8d-076f-4bfd-ab1c-668e96684b9a.jpeg delete mode 100644 src/goadmin/static/uploadfile/abe81acd-7320-4a1a-86e6-a57075ede104.jpeg delete mode 100644 src/goadmin/static/uploadfile/dab3404f-e77c-4166-81b4-c67451a8fd25.jpeg delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/.gitignore delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/.travis.yml delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/LICENSE delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/README.md delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/casbin-logo.png delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/config/config.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/effect/default_effector.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/effect/effector.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/enforcer.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/enforcer_cached.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/enforcer_safe.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/enforcer_synced.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/enforcer_synced_safe.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/errors/rbac_errors.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/go.mod delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/go.sum delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/internal_api.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/log/default_logger.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/log/log_util.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/log/logger.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/management_api.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/model/assertion.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/model/function.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/model/model.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/model/policy.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/persist/adapter.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/persist/adapter_filtered.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter_filtered.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter_mock.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/persist/watcher.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/rbac/default-role-manager/role_manager.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/rbac/role_manager.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/rbac_api.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/rbac_api_synced.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/rbac_api_with_domains.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/rbac_api_with_domains_synced.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/util/builtin_operators.go delete mode 100644 src/goadmin/vendor/github.com/casbin/casbin/util/util.go diff --git a/src/goadmin/static/uploadfile/1735f619b0622cef0d25c4800d6f27cd.jpg b/src/goadmin/static/uploadfile/1735f619b0622cef0d25c4800d6f27cd.jpg deleted file mode 100644 index 1cd4c81cf7a7bf8e1bfe0110feea54a5d4cf7878..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30661 zcmdqJWmFtX*ET%3yK8WF_aK45;1YtnTW}|V;O_2(!JWZf!UT7Bceey0?{Ln&&V8P5 zJ%7Hn-d}IC=+#v*whENpBXY*chyJX~x%=r#7sBrq>` z!oed$Z^TAJL4)@G|2+Qm0&tLF0k8l#7#aX94h$R)%%4F31pojGg8-HGzXu#F3?dRT z3IaTI*cuxE0~Hzp2@3%k0|gNY0Du9&!oedTBH`dtb4#fs;}L4SPn|`;8tlyzyG;?)x_ee@kYiOLN=i`^rHn;p-L?Y)E+}Hm`-oiR` z;QB=ls0c4|{7Vod=rRaJ{hA6n()w2?S#L{Ka(Ex$aQ`D_}gc24L z8f_CC)=WUpVeQ;oJ7nKWiOt)^6V_dSA*#-ENnMIE>YMxzKThunWG4sq{~lZP7dn22 z6E}yDy5dX3{1`N8Tvoy1iSwk|iRt@G)-R&eE+euW#@sVIbR=NQZSjN_yvCt<377W= zpl)pXo1g1OjgZK;%%F4wOB^fcJ$Q^mixVyn(p$T=3z8Q)meiprp}NWU7Q2%`Fq*mY zQR~F?dj1#BN@uYUa9lUqjZ`uF0W9YIuB7`SJnU`GXI&;uA( ze?wQAa!&0(AH3zBh|xmtTM2CJ(BS=h;-b^4jP&QK(4$q)w;#N%Sfs_cTL=jQ-OLY! z?^%1tMD3!#Bv->&zG+y@R6u0My=}jX`Sn37!8~JkH)7++7d8fTGH1iKCq=<`Yeevr;c&x?8_=E`;DY6m|CFj+3Q$*yq@$!ENShcXY_sLEeRwd=Vprf(fk| z-kX<8mz$j=(NxyPkA}N%+)aKETh0t~o86!AHi;~HaP{xhJmvdmd8ohgF?7t=q7&vbLWi0qAIN4x`rFMecg4Dl9N@xe9f^E zfh+pTH9;vxOw?hGsILcvy+{aM3;uj>%8L&B!y*F?Dbp8wB`}$|gd|frMj2g_mRhYz ztVya5@Ocg42epN-ll+-S%9Ve_~(vQYoCQUgp@ikN>-DK5C?WaAQ?t5x-rfL zb=?v-aoZreJn@e7GSEv?@9CiU&ES1`1Fj~f6OG|4FAkatDfvNPFS(~BmdNzG-GGhQ zxxzf7kztSP`^Jh2lMA#fI$Ddaj@7aSpZVmRO^&E}{Kv9lBSG_d_Okn*%w!w&8e!_+ z`R15R&;8kTRe}gEMoA|WSHt{C-PzacA4bOXPsN$-&H}8A%7J-S1|$)fgA~70R4&=u1}Ccw(4>xd#Y$W`o1j2GOOz`6aZ- zPON!!2UF|iM>%-7vYKdZ;YHKuIiqLU%;{&dVz5CJFb2*#xCu(ejr(dTvU%+p+J0cT zkzWbA8ha^rUwHy;ZJGM@v`*-o-s+F&H~0uN*a~KyqT-tlh7*#R_4^q?0uS0svA5i@ zJwoYwa$@VS|E* z;LBM;`@(@iq|z{Npd;KPNI)1BHChq-u;Laf{OwGs;kcPJxnkHg?y=6}B@4a-qvZ5) zzTSgZJg_5R4c8`NlqidzTt9rm2*rDzVnfK0uR~7_Vhgg$mLnE?%ZUf`8

GE<}vs ztwa6*xSdR&=l2&~OgugI*2$OCyF}K4QHIOZw^hV25T=SE%wJJrF`=*h8%iJ|bd{R= zyJmc9ba*U_I&D}=<0Y`&Slmui^AVWzji?!AaWPjT+AHh(GS>aw)E~EN%h;VK@To8s zr57EScyH?L8%!^~5CdK{JA?-o;Y}z_Ss-G{P^=w>5}XFCBm}xlMn7FfxM|wH?;acW*(|iW+1p|@F4QzhMq*LVt%Qta zXMg3|5zg=VWH@nKed7}?Lc^(f zTZ*~Y^wj-(<5!)b-xbS^YB)O$3!9(MW+vxVnQAP_llHjppVtW(o@*v5O<8oYOK2NE zl`0FjX6g>Xn!dR;k2VZ*T@3Gm7>72dMbb>DgX0i>s_=JpFV65cpz7)5JkZQ4CZFcm{Mgt~5) zg+|5x0ET14+>?=0>qj$lRs5Wv#RD3(rP=&5?cXUzqtsmwuvi&ij7db83H5Q`!6Qk`Jl(l8jH4Lbiw3PMU|du)w5YD7Y8nF{>IQ`&}h z7Pfyl($Q*cAV?*#Aj~D~U+rq*3bPEPE3>qdV?s>|RdVy0mrH?P;bU%+tuUct;A0Ld ze`Bj@2kW>}f@nz?s}MUAn6#I6E{gA+x}iQsGF7BiRKMka&iu~_0?odv6|`7cvYDA1f0F}*`QFu&VYlCs{PUx`6AyA zIp$}~x_VPZy;`$NPKQ@*r^b|DE-wNHZrZPTIt#kclr;YU#BgKMwWALc=}W~mo*7sK zZ7t7Jgk+~}n!JWPgvsc4F%+p$ACa$5hl ze5z!3n6Yx-(hZAogzvt+tA;_FzzlG|XFIFqlCU z7~E8Vf6nZ*khRxhE6G00-7%BnPB(Ok3i}PbzO6kz`)akw!H4HB1@=?k=$NVYEBVPk z9?$UV(s_#H{%?@>c_pV*#N!v8oyu5e z!I;aKgI_6`E|hA=(+9yYlwhD@Ol1TTl>0U#O5Zu1OzEH|+M8+@n<+NXhSA_VJ>eVh z@4c~q^#{PxK2?=NtHFV%TUwqkn>4RIU_@9c2DU~75w(?O1z?bKRI8r|_|}U{Rsq}f zK4$acYS^KH2cj{cUhfuL`b2I!d;L7uwIRhfW#L(`ejl9K`DI-K@T$J(l^Azo$of+gzW$c5Lq#;eo6S_|fvsv<6PsLb|?WkM;PR-5(e4Uby;V zauEQU?-L)T?i!%s{*CcnC|8(%%T~QrLPYx25eiTUa4Wi zi!pwC8Y`vv^FY7*Cj}0HqKQ^kmS@|5?6wXMg>NJ7>pA7pCKw~s2f9D#Ff7PXyI|m9 zF{zGNx4=B&DFs@`*~^iOt}X=@a6z7$XwDGrR66Z=|5Bz)rJauUsk5|^cZ*9Y#+pjo zQD-Fw6^WHjpE{NsT-X~MH1@W`HwuwIJrj{G8nh6p-2Xlh#dyVjF`Ska96j-=Z9>k9 z(lj~n+T_bm3btww+HUb!|B0@P#6pm>F6%{g`cBB^?-B=T>|&YNpnt2&e*iXAcL-m= zL=DNzdLf_`>Px4x&Y7+CV4P;s&QapjJi)Lz1?RTm()!>6La2@^d4?iU;h)=KDtUri zs0clZp}OialT6mhgvKyyBVkspU-DC6Jf42@(s_Q~7W|4^8#McooB@(_`PgcM{`-F* zh#sTiU!5SNq^VywG#w5QU$H(t!MaZ$bfxwx#i2cClfL4}Xd6fy{eJGnijTold2?`N zh1~5LtL5BfC{5h$DK9NGJUerDCPC?J4=Uny=3r@kO~ep*=qD;LW=htP5d}4}qTS11 zG72=Co>A+*1+FRe%b#@l(2h`!QJ4)Ji=W$yhYL0YG_shpz%=axkDh*2xd2d9yR?X1J?-WmW*r0y6|t?*FJLx;w&JKg}&ly#NOd%GdV_K$-Fl7_6UdJv5UCj+w zAof&WZ8+y}#8Q5YU~*@hs4XHT-+XSfH*4Eekj_?_ib?*!yt@y9TjF&2zy;_0LhliY z(epRk>oC8*AWl{M0R$-D_kZHGmYtT%_ zIf~Ovpgx$s18Cm_Y6E9XvBpq(s#UQHdI|*-IC0` z;%=$fqE$EYxwUg=^H(PveAxZ~{K9Hhl{fN%V2+&M8;$0}@1OVh5c~ekpuyCpL$%aL zYVQkFOFP*ny~R-{x`LkrfLL_Pmx%;c}TuQQ&6=n=Pq}AaiT*Z zL&u6vff?&eh!`lbb7_1Gf*LTfnxs%w=CYGiE{Ar_4V_4Gw`-;76~8rT9)6}!D)4U7u#SvD{b5zd($Ci;SaiCV^#sR%X`L~) z=v3bPZSSS@6KSBi2LnHwof0&L&tB zOV>O-;a{E-8X90+wxqIxarLawX!@dNz9no-9ds3&NFi~<+ZiOS+d9|Ru-twb)&v!y z@#>G}7JU^;STKK7aP?>>iy)m)Fcls-jrzL!r3RS!@zL_N#g_;*ySmqw(}$F=#}8I8 zINXzh1mBjAwi~(1i7D7ds8D6NK>ak|b~d&YT7jW* zuS9$Epgu=X!(Jo%C1|2My*Q%3R(<`&56ufe zolbeMq@q(wUm;-VSjj1*84CYks%MG|)`2$vfQ9n%2v^tXl3iTt-ms(iUNdJnyeI4m z6;(PH!Yiwo`z~-}O$;qbROg;1Hnz;o7qNYGUTX+}B8p=*#@fo0VN1hom|m%T2F}*& z8^iK3=LHB~TMg+zgc0A|ph8BYQrKi|pOm2L#-N#I4Z(EdBG zCZdLq(N4lHPs}H4nG37QUC+V+i=R|m2tU&59F1?37T?_DGxAOGY>SQ;Q#i7V%s;ik zwWYh$+q?bhu+;s`ww_m>CRz23@7E2sa8aXL#Fzq^l$)ESnaHZOBL?AuTCpR0ZdqS` ziBT9A@d=u3cZXyPnRt`D=sU2hQoJ{*>CiEnnOWmOH{F`FHjU9{QycvT&`;dLH2 zl>V4%3n?6Cyb$JVzc%CW9bGjXO;b5zPZbSF&T7e-Ew?hysR6h7+rb9#md2! zqPo!zSIDegD8FOoj`=EQhhIz`CcgGItVN)6k7Mtfg5nF;JQMRRh!rKlR1m;rE(x%@ zMgW2$)$L1EIm}~P7Tr86cF*Vb zqrp=K58Oj^Ay;AgsJ=RRJFKr|vLlC`X(fnrdRk9C9LC4AbxqHU=j0a{O3Auunde$B zUVr@X-1x)sRX0f==BD4T)@=4q%{1)kwJ_|jIa5hfH7&S~8q~j$KuF?xks5JQ08=vZ zd!gIw`<3mh`r>BQAnuuW%tR*JphO+NrMmSWO3o8l1zS>ZyPXaKF{1X`*}Qj@kUxOR z-%YpK9GG7PRnfgaf<^;mz2CeqrHI{cs1~0TZwnwQuO@6fud12@pMgo1nIklDZ?RVi z@pV+OEaZgD7WoIb;jyJiHQx(7l3w%$tiDZaKOHXVwnHqm2~5eR0)Tr%&u-`vx9C zwdiO*q6GD}nm+Aridwr@Nzdv#ezVHs$kKPQO#feyNCVBPr%HB1;5QFrdX2iWnjGimou$FD5e#0V;jyN`Z1o9kT~4 z!|iUjVcC>#UvHXLu0RtVOY?Q^AA`#Aw8ocHQ)I;dBd=*QTHGaI{*g8LF`_n_ccW#D zAR1~nBurv4FLpDYc?k>qBmEL@wb1|O*OBUrlPy_CaTLKL4Kz`*Q=7_|3AFcMj%9Y# zMACz)R?aU7fHLxiaWoCll}l;T4cJoQ&D5BNx4(sPJzvTm&>M6?)k9}U`%^b<{VjGfmmot z@l0^5-Cg1%+R5I6Jbt-#l;@jcNN?&@dXZvsmEC=F|IXoA)`-IsNy+sM6KU`dfb=M; zFXYIp63hRSZOc@XKgr3X)W*nW)O;N0J5-nG=b4EQ>rD5s1JA`?Ld&sJ+DhNXKkz-v zQq7#ad+&!ZwVr>Wjy!S1!6-E6SD0hs21__#Q>ZepJX6saO+8xj&}`tj;uX57-d{y& zTYIYKN9vn3H$kOeiDu`tGB>HSY6*;1teT?)Cp4(X}()9%VG47*l&wOzEII_=jdH3Unefm&{0yppl7!pvz<(95~bJ7z6hy57-w8OSTUSr&wY6 z&AyJw4w=cY5;s^v+N0SNdZBQBuj7$!pCfO{&&%SHW_)C2l|VneLgN79LW(l6h{5Kk z;wfgHTLTDfUl;s}wm=zIUR}B0MGomlLVPTNZL&19UEceJ8foXBbZqx`FskG;PNM z?X~*G(oi#?7Kp%Is-dX@;_@gUEqO`RBt*uIq$j5jE9Z4~&{GBU*w)5m3KI&! zZ5MX{;Lf{_rsU>}l|@I8B;nY57GAtdQ%_;CJ?X8!9UCevY&6hwHz#u%>5kRe&#EC= z;L=-17Hs=E=X8p-flkM7uq3~UIjnV}nbljghoa4y*%_Q#Uc<`az>z28Y`47~grUoo zBq%UjRjjrtwFv8My6eijn5}uvbCNe~k*&qi>mpD;D*0ZhY|S{fck{{lxMa&7{*0N0_5`hDfzVa2IN+r&f)mQZz1Jp8qav-L}IK zyJ_iQTLVjIgp(nkR_OARUykE_@8X->!nD&BzS(c33zkb>kwK;O8<-5FIx0m{&J*2e zNj;ST&JW3rX%gNN8YW;Z=EPy1*(%bU*YpE;N!K~%Rk&Ct?1o8=o(Dm~men4ldX>QZ z@UAi77%y`TX~e=JTo5Kawj|YO7=w*<{?@QrL&cKn)O8-aE(`q_ovFIf?2;BEomc*0 zVpPOIn=oPO@wJL!U5lFiXBbD-zRi$>p3=_KpGf`V^Kn&qsynT++F8?gNtYg8u5$ia z$v#5ho2U)Zi1k-qEzh#29lU}I9+5Vtvv;=XLA-44L|7&%@PtWN^ zhg3U_>E$f&JWnYtwrqM+Pk^tN2!DNGd{OU3__`7q&CD?l{#qhL8iQpnxP z|K7c$J5}=xWuyRNG9ilsgGA;c#|rjdtbRo+7sUP*2G;}BraTNKXriMu!OR`f!3o%| zO6F_A!e40wz10Zcm0SYroicvz9zYU5JRaFSf!B|VwP^0fByksz%TemfYJ3$~!EHt>L%=JR8 zbv9Fp!q)LGYOqPUlt+y@mI*PqS{cM#s*w$Z85c?E8%x1#;!?vv(#v3$EC-)R3YTiU zTm@Id@Ug%}4XqY&+G+1QrL{QbJ$O8udVo0adKM zU_3WBcGsl~hyUBw9R(2ux|-e#!*=bp`LU@p@EFELCC|k0yEtOXju;p>)k{(mtUmxw z0!o9FQooIcra8T$yY`PGN8c%;`vaOM`wn11;SL&iCto%6*IXy6{s6|aRnx3=p!~60 zwA4#>0wK(I_ZV3E?qY1zmCXm~rLU(_ROPV~MV>R28jXzqS&6@*QWkdD&RQf>EDPqp znT~!%ue_15+ei{FZGM(=AirjJU#&QQ*9meDZFHtf8# zT|O=%6GRoWmCz`z>1B015}n(*dW4I;fy}jUiyMf=n~yO;*%V!Uf40GXG?*6cO;};q z{DbF~<2bC5SXajqF%4{j2`3OU3hZVVbZjtu7$uQ2@J&bf;FQFrwix|ac0BIgL4%w%;YH>8aeQKA6Cx;x3#moB0vQs zpNW@J5i*w2i%`VY`Ci5wNq)o@2_flp&@;P>#qDmp?c88;%isGlC_9~4VU?|C`JB_C zs4=GdC$DagE#KpTm%9J$I}{Z1ysq5z^ic?7K*WNjX(_r&0JZaiZ~go7B)fMC!=0s; zxxYn=%+9-}g>Q3CcZ~*yvdcbILU)^bG|M5L5Bc5+|HyR!+HSyjc7&lhPv3Jl|xThm#zo`F{&fb&k5FM*nL+vwY zVG`uUzwTq-qVLv0*8GWN!S#BZyf+w66hIXnE99RJ=o2KLgmY4833+}oGm zt}S}(SFCGZ4W7SA?Ws$Zo>poGlXMp82}Y$5XCxMTaj-6jlj3_j#=^4F$T)wkF%N?G zjxdlgHk7D-S1h}E{EoStsWmvAlVoZ=0)l={YkOZ+H}v6r`Xv1bTEBA;e zRw%sv^;Rm!4b*y|vvBzMW%&Es{AyTel0h?& z|9FL}LL)o_{7!VFFMjw~vzrAHUl@L$^rpDlw0-CiEP9u>Sx)g#|9Z`5z2M$s^W; znVJvg3-()uVm}?C_K$8F!QZR`3UQ1V>^q^`OU9kXGQc08NoQ0jWojZkOPa#R99#`p z$Qcei1lnra&IQ`LL$^eAMCSSy0&SpYpsf-DpjQ)SE(z5{WC{a`fJ-B2p#&2d8b+X@ zg{nOGGfY8^#l=(iwRcO(YIl*cWvP&_Sz;~23vFKaxHCz z8g8ef>Sld6+T2_?CbI)u()IJr z{;grlc-TP$i_3%uWlI_;?`-2j>Hfgado$QTyfBv*3kH+Vha&es25 zFNo^bqg5WXi0SBYpM8`M@s1|_1U%&FI^!QUTHlu-t|#)-uaJt)Y*b3)+VA4tOh)!K zAVh5~xoR4f9z~$EEdB$i37)NU#tLzQ788G5p;u?Gan&k+&a%JGOk4Jl;ru;=)LS4| zr0dPd#e+-3=8zkDJvtPx1$_;c&P6-tf`KzG_8v!H1)E>X}kxs{_GT(7|@Z{*mtv>f{oO^LK@d zYS2WznjaQ(vYE|T@4tk--g|Pejal^zOI=*0Z+qHv5M#nV8(&x+wn-Yy(B!7m<>pya zdHpGh0{_XN0Zwm$k2@Axx(t8`gbBFga>#3+_f7x0zhsx5?_N#ZLe|i`aj0SYsf5LN z%vB_`wa2|HpkuFTaeQO|9`^XS%}0Zq__3Y_>6N6Ay)I_#+**(DLo>ZbmqmFj6)t4r zZ8SDT1`p1MUy7h3qg*z6lki#Bbk$)}@s@Tnf)x+7P*VFO+z-Dr?AKxuK=)jBwQd-8 z-z}+H6jxd0+%?>e5T>&$$-i5PM75W%EBPTIV~!eme6-kdIrWj};yt-+SU92%s2fPP zc-?>c;lN%Xj+DEr)Uge8)}M72_VHG8-#42G2j<-0Pr>nki)87?549Q3N1m{6g4^HMMC-Zbt^6_2Ag>)R2?VYc4RFZV4nnn*J;x<0`s zlJ1bgDcuF;%U6ssO8Uyxt56+lR&sFKVfp>p#~ttf+-YrAU@ZDu*_rf9>YT!f-McT- zrBgOdvqtBE^;M1nS2ZHzt0XjAzS|f6ou|B}o1b;I03^{cjFhJmtRFaeXzGJ2NG#irGxO^*4er&TN6N=-nPD`IuV8Ydvta zxtwX`-7?&K8X3vLS|{Y#81G$GzZhiI36A@w8xz#ld0te@hb>xW+PF0A=bYCB{w!0G z@JwycMyh!0bnIXO+F2U$@Ff-^DJKq7ksvczBZs`=GFv*!h&!uHvDcXLAFg$sT$BDD z9+cx^;sjcD^2~tJENb~$pfA6>gWZ(});`b*5IuD;PM48Iw4RHXIB?#3s(#U#`08}I z_RBt)YR*3S!Orp!m7wOY5@75Q<-ym)ghtWMtLiHm}& zZ>->7EuHyy$8W8zS4>o0;I18Ojq;>w%G`plMWyDjY*4j56_XYC1SvAj5%;oIpMmNl)s;0l9E9G$TX@ zSNQ=}I@_?*DE|0@&G9b@^~!1CjH#$}gD4L0On6Qv+!<56n5V*UGLa;8y%v|lR8h5fX#8-MvD{S@+I6%Ql=h8z(oh=M}w2L2+nnhOX!3QcNn z2}})1evGML(Y(66n*U)N?|ccYtBLt}P>Pgr`7BKeXF2una^VI2_1D6~+erttRcF?kdS**$efxisnJF2jTs(_vZGKO_Go9L;f!2g2?+H${*_{1KD}7VB zVz)1mOpVr)nU`sSth^k(AxYU(wU|GT(Vk8BeeM)aC8rs$3ZY08B{j(&9B_R;`VlE= zEQwFpZD+-ZptTd2Sh*VgPNP~GSJ6Ok|B_wvkA?KqxQYfvUyQU*N45X zL)q=PL;H%asrFBewVWEl{p91ngxyLp&3<;k^bEh(p^rli?t!)l`` zP{&}>9n!TXDbVHWz?fDZ>|bO}87ptiIj&VV9T_0=YxaqcX*#_)LQxtdg|B(Etb-msT zdCBkd6MjvZhHF-QAuvxtPLweD!?da~e)hu6u5hInS2r6=PYd2zyXOsIXeAK>b>$hFrk`qNlQ zPYwk~%RM-wtwqf!U)77B=Zf~ojU$~@GvAFUa%2p#ebq*Ct?pYNx+e|x(mIa(raO49 zP~s`^o|w2zD*Q31l8wLGT!wgR0c-*w1`xnCSL{YDl}&-H<6@c0YGe~JHw2ryzgKQv zqRv)|-zFzNHorrb9`V`w@7@RjT8hF-U^xrjnHD1ft|t|&v$pc~+W5joF&yHiPL`wY zcZ+7rt1;m;jM#YeX4w#O}tQ z%-4S9n@wosGtI~`vpzACC*@{QQTJwy=FDAymB(o4$I9)l-m;S*$wg@0WyJS1Qhq1( zj6`192!?^W*${zWbG|xaidAn;S?EsnepR9^v6F7)yrP|-yM44!T*Sis-h2qmEpY)$ zxo8=s@5DuaNYi_ZX?=Wq*VdXuAj}-8kim$YVBYU86eEge0E5btob3K1!z~F<9aKV1 zu1knEN;v=)vPNraPJ=A7nzJr=HjimkasjAh@{_~K1u29qgTo6=E8n#SyH%IC#3Fth zQ>PW$IZ7#CN(j2P5Njul5FvJ?rJB$8o36#f>+RY@#*tC8@azYt=veu? z!-AV5YYB&iqvwYP^*4I#Co4EfXN8zf4&(ih??OKuAJ{4-PeP4BY+(!ZZ2Ptu0Hwj? z!q*f9{eEwMF-|p9SDn~TnT3C?drW`LB|L5oXbMd|;!{$0U|pK&S+?Kq|9 zgtjUA*@m?tB5hazd(=>%n@e0`zRD}XAmfEsg`jlWaSy9!tPdkjDD@f>GiA);?e5QO zJ$NwzGnT*PPg2KYNQ~Qc)CC5UE7MH>0BE<#Jw9r*n|R1`EMHw`)d{4LEBP&bNcSF? zFnTRL-`>5aJe~5MaNIEDrwKRpOfoiu6rAx|-tN&%r)o0jr|Vn0wr0-ntf`kDXYMRO zvshDKB`{lAI*9@bMHKu9!_&LJ7|Lxb-M@8OucJIxgtIl1gKKqo+iR|H-6}rl8#PFj z-SKpD?vP{mF6_(5GKtPOoBJqDX89T)c}8fpJvSLi3cnCe)S%j<(B_yaVLj(DDahvm@gn9YkxrzZtYyp*eL8m2jJ=^A!$^hF9#fqu~XM-s4-& zk9zH+XWvCX=kW47REn@y+jncvo&+ar{ABBOF&oN^`957F!KPEg;kTxkbBGs7m$R4D z{;qXs|DdMkJYOG-tD083k}i{-8H#Q4!^bnYQ`&iE(d1CL_YmPb`8lvn{A>Cr54V|x zw5bV+x%d0u{D~8{B3v6LXDBcU8HwNuCm7XXKn|i&k6gd{GzMOyHU&t~x3GQRWG1}o z>EBPr*Y%fmu{yHKIhfV+u~(1sz0(|So^b?~)7Q`)D7ws*sJJ(1uesIZx~F7p`Z34- zRlSt{*Pdu!J8j(Ya^D`GDww+RVJ2@MGWagY{dLUGts6qd73?W8f&ZF5b_im<(e;1_ zdj0|3YcLJ#@3Fi+EL_NA_eXbE^KU|*Y~H;8l_@^z53MLLc!UunxE;;gVhqj&Olhrn z(DR)@Lm8CBO@;wNY1tRTRtdi(7ie-K$wvV_8#y|4ylr%kthg^IAJsgbQ5(~Z%!~+1 z*aq9vJt4&;5WV)2y4Y>f-r!qLZ7-WXBJ>xY%2zjK%gb|$k(z}GSEJY=OZUY9ZOminnNfl1LkH0*Kk(EKy}iO z+@Cj-gsk$_{zhJN>trmpPVqy=XK`OTgoJw6NOZq=8#mEv6g_*mj`BaZ>)rbMG152j z8d+IcSu@ZmPbj^Kr(})Zk&U=H?1CuJ9nxE}R3U?nYT0=|?VcV-AkIWuL=x1aStoPn;#I#sp>enE#&fD8vjc_^GYlTBX2mwa- zr_0&tb;->uGjGV&TCqX K7VW1^j(dp&Zv88u~c3pg9bLkXBf9z&Iq7G}QpBpvgQ zUWT8foxXAEq_*&2Q7#+O)YqQ_+m_Dl)2EZG_-}%G4JQs+897zJ+Iiw-EluAnXBz5| z^oM7+%!5lPrYEah4CxwxlD)OMbB&;_RY^AVqvuMVD^+W> zFe^#dZJ4zRwtG-+-SuM18825YZf=@jSCe}EfE-1nOSka@J(=b6``|H7)=8Wd3O~h# z2YQwyz4AV~q^OOw!Grq~-rsv&lSwTECd4P;PC>o)U0v??G02{`#SOZpQN3=7pnV7~ zkMl&qRthGI2egWoTN`02KNtP*fbPXbJk3%y&z*znH)vH{wj2qNfE8K*VjfO|JRGg7+YbJT9KME+f@E=m(q!vn0 z{{?fI2wpa2Q8PqlpsXA!T)tn|hrEw7`a$kjoOt`cfEPv4ef>K_Xo>#9T>9PKZC2az>#SF-Cz7fWn%pU(ETt@l)E;d_E>yE@Eyf^zZWz zt;5lCu4zm&20sFFcmbr-am49Pq3g`{mlxn^J_^OgBvl6KWK?Q)r2e7Tr!+XV=%lNK^p;1_jmK2koXF zYSXKNcliUEA4^59()$sK$4!rT2Qii8W%|N8SQsfs4$Ky&ZvQ+ z2JI`C%mo&g;e7@$Y6LO8*!qk8H)(h<;YGoQl;IWwbw#G|UFOn&i7fC1P@^w{8hzZ0 z(Ql<7WZK5NzKt}0F8FC{{hDhh;0uQFLwc8lWqghQ&*MX+1a*n&u)r0%|3T8bepj6+ zQN2a{+rr->#`8d020wa0VFB`s8$cYV-112vf|gO>t$1)|y`TeV9vd8$!EEvu*M6#r z!1RIwB)Q1(`{vRxK~x@8{C@x*o(DpL^9qh-4gL6Cb)a6Zt?+~;4`iz3&aRalZedK} zdOC6l;jL@ET&3<)&NyL*a%Sn|h}b|pJ1@%APQNFFf4Tphi)EnmIja46J8)suj~mv^ ziA;uCiwY0X37dEeUi*-pIB$QcMMB7|$^H~m?kc&~+Lw2C()bieLsHZ+W%?qE2H9Cnnedm2!xQ} z4k19W3GvnK!8DlyIXK~cXti$?h@QRxaV!ix#xWAt$W`4`QDGaSj?JT zyQ{mZy1Kf$yQ=4-aoZLxLeJ$b!3)3^$U1% z@{}r^7$b`W=Xs1Nj*52^m9VA_^9F@(V%X2Uc@@IKGNuXP_7So!xwQ@|)L-Nuejo|? z>@nB^al1brgFp@Ik4sVlK`f{sgty2p1tZ%v#^>^m&n)b9?+8Qs@y6^Emt@b5gGBu{bKlSM)-HdjFOKoFQpC$0cyK7m30G?)iD_$@R7>fRA`A(Ftidb|BV4 zK0%K^K@Uz)9=TcmeqQ94P7tHmR-l5o{?`zo(cR{kj+aNCNMFg}4@Xp!1%`n~i&cgY zPc!w?cO&s_Hj%tFE5|wUH_g6h0j$n5a&t*cos*nSRu=AEPm&B;`GGi}|G1=upv2+J zhAP!>koV!;h)?OWSe`CA5>2||pIQ`*qu(B2*Z>Te1r3m@9|3-{c;X7;S;EK1?l}^~ zqW576pdl+7Hz0=LrByN!N-%o{0&pyKzwd)0&Dj#n*#eiGy{df@wZ4r=!5R z+)F(Ykoqn#h~xod1D}rkpTd0)k0~0RQ8`B~hTlhL^?y z%#qlCc_Q}~$D_qeEWqB)rObq8U-Z`-dkgOkRSrOSzj#NyN*`tLbU!7To9?u7So{sz zJNZ(6@wEYWT3riL30KaQl;J$8Gn_~k_h#GsKbeNC*(Vy>#A=BIdrKOt>L zsrD9)1=ygqHt2_x$roEn`{0Az-S_-f&9Z9NXZ%2{hhVc^Q)eCgk`AduuK&5 z_l}PX<__OPvMLjTH@Ydqx7-NI!P zdtPp;>N=^beVrMLp|}Z)kE1d5V&BJ+Rt3!=;$qD6*UuMM@})$VbiWFo;tpC}?Zbzh z{u-k3U#mmq1F?KB3UXEIF~a!`vbe;#3~JliWoUmsV4B=0o=Pef$(Kaw#7gE+CCD3L z?93~6VgBU)#k*jF+@%Pj96XZ2kf9IMTe}^t@y))cp?+vygP4Lk7 z3{}#>&?bW5M%83evC4zLBFL1+@7 zAh^*ed2|-iX|Y?>kcMb6H47b4=X%j8*wBrOt@ce7*Cj&9INx~tj@JjG) z)2l??Ukur`OPBpexPulqdCL2a_aZo+yQ`b{gN}w<2cTmFo>rcqs8`W<28%IF%ns3B zis~%P9)XYPe3hou&2H8&{5NXu6!O3E_S`_#YxeCU?1=|Un+S%M?4z{0C~)BV<92-Sqj z5Uu|tP)~M}$`}4bnW^)$8$a9Vw#3vOK<-Udk^@I2I<{v@D+&+wOwBt1E&Etc)Y1RJ z$eV@i+CEBk)Js6I6}jh{M4yrLq2YtQaf`V>4G+)eZrCc9)ZYRUN8c;3CUTeIEgkSA zuK3y-4812I>o219&HurTf56>B2XHw6+-tfKF#2B3J+9LOEm?T)ERq4)!jwj~RS<9@N{g(LZrb<3YPqO;a}pM;d}QrZoc%LK^%_#?8t#3)oWR z*~+ZB-2m))&p+7DnJ&V{?zQtQZlmT_sYs^==w%tUdqtnRSM&*A!r3~wlcz#gvv!XV z08PzZqHa<(<0to-Br+7t}=FZ3#4oNq3u znF=P#Dg!F!U*DsxDPz@o95-hgyZL;i;(=cN1=bM!coYKfKdbS?p-Cd1Zi$;kzsx&utrgiqWOK>j0h!@l)h`ea8|>vgm{n=EPD?v3!|8itIpM>3 zSy=A~lI3mW1SmMy;B}!P)g*?u{iMCH@BHe3u{vo?(+|+tW57oD{4vq|3)my18FXZW zp$i1VNScz9-;+^9*wI|yET~T|T{Ml@{!#BLNBscWZA+sjfb;2e~@1KHV<%tXq4%N(~E%!)vTd5jGE4wB&>XOs}<*YeR0DaoGaYTHP=8-r@#E+8y22!IqAX+ zZX?{UH1&{-rTwA`R?$mq@m7CbeNA`}d$e>M2gL*%DI>*2Hz&$?ucU1RijO_bn3yDG z5fVBT?UbG6y1}zEC?Sr)w&4c{$>B5CUnFW9$~CE?>|xiOlCp!&bdH%=2Ki|n(^kjL zJQ7qe2m@hHYJz-efKG}2*+$2?ac}rm&kN7e;NZVgc9Gs*W%31BAso{xEo|VFe~j6E?2Y|7)dW$WmfcV7=^(# zs|Co442}BfsAs3McDpR+>KK@@zh<3Euju)_Sjfo2Qz&N?3fC^dp}>qOGK3Nhd#@Hv zRLEG)POK%tLBSzGq#(yw9f+hI43mZh!*Xojm4bFVeNGRhY-t#M0?_x-o zjYhhLj&2|zoi2oFO>hlWYFv zHzq1Of(jd#L%N1PA$P9N7mgMUmI70a_uN8=PnIfmvx-3C!Zy-ZZc7WIrMG@Ug;;7n zpimGaOD$Czxj|dgEoGftz(gU_iB-iR+Wsa18W^MPhv_EqK1Q;gmaN~cqKru-j@`W7 zxKobrS5T3YZomCa?1XLqBjY9j5CQ-s0l?JZ!Q@N9dd9o{8BQ*#M6xHcDs7+t-aRI2 z-j2RwvV7j>tLYpM8KtOH%GGv)mBX!a7c~ulp`kLBudY@HW)@A)U_kPpo!I~!YX)U3 zRx@P4mdT`-g_{^^0%X}o)2Nk$GUsQjb>J`YCQv%Zwx2n z08e*-i|pQL2~@tnTbv0p47@{8cdO*weU!Z(y|7pZpFY8{@t6$*IAwTk%-!&X{PLh( zb?ff=*viJ|J(mGv>}=Az*K8LIOt6fp>Sag~84nrO-G{!il)5pC!ah87@2e`i(9~vK zVO~TVfj)a6JfrG`z{nF$!L-(QI2DFgcb;Px=It*cVe(1j?iZp&u*jr{IJ{m7rq=}g z9GxkSaBG&(6SkLX39CIHd>Qm9ciTU+&bCW=BbOE$b<=lHymm#Sr|0O63m5*pz6HUz zV^cDw*Pjw9iEJ)j!DTL_ImH9{FdtnkMGo0dBE;-+%vhIKbZR!xBTs$ak+qXi{ZU0n?kUkC>aXg;QbZksgUJ$m!$h$!n^OS?KB%M_*5)A&f7M{Oger4U?i=IG{` zxi>r#Kc^8osOWD$+=tdWb8rSfb}V6fD5ACZ?HUeho5^-T-$--7=z#ef6stJ6I_@2n z?_PhloN)3RgtTqGY>f?#L+!|!=Ddk#jBn)OBq!jZVBma~nl8+aobP^J8L~H2N59U~ zaQyMua~UFzt5Xn;BM!Ny5-t?*FxTY__n?U^--9Rrh|;~}PZX89TC3D`Wjx2REG9dU zPb2wtIP^S+C{)+RoPhM%p1o9MykL&qyiwmAx;2g$BE)mLzhAkh5zRscjeK2KhdXqC zA4>$6ndC&5oi*)<*z2hTc+ItPQpqrN>iS1o4F1^~rv^836dlhKB1GlqH<|IB2<~3& z>@3TV>ul9ncNwidpCs2#a=s?QZ5f~T%M)%j^tLGi`_`{e)iRA2g=BQia%%&bTE4I# zGU*x{#OhSX;WxMCUgv_o-_9}$wZImVuim~4Bp3AlT;L4|kK3n`IcRw`E z5aU5@5o99Ilp%wfDxDSVChc$I{47uT3S5gXRcj`Wc&=KMa9GeuJvtrN!zv zyY2EG<2LhMW)SviBK`)gM`+&byk4UNqvDmb`ziacsi$f~nmDa9AKy+rT^90}@SAx5 z8Lwu5;xhq=A}kqRDN(Jq$w_*-a^0l)?Hs7=_^N4+2WD0SJwN>^yr1)Ac<^;~_o$nL zmaPsUcIvRL!Iq#Q7&|hvY`z>R+P_cJynrbn#+|TX??q@C0 zSgdfB6j3A8xX2d%oQiG;mg@wz+%tV{U{|c2GDCt0yMuFRGAkbNy<-a zVx1a1X)_AfuEb3E-gPQ-(&VF2u^bY%xz7C)Q81BUv>9zp^qh$Io0yt{g{lf)(qGEX z$@yw1-F2}Efj7!YYrtbsZrg8A`RH|T`5`0cZ&0c#pQqd<{y3%kxvnB~j4(7ldzcnD z6|a=1B$zrXNkAbNa6&|4abv`fG*fK`;{O`vTo%>KAaC^N#o%e@E;HT0NR)hYC zupHrMKs?_!B0Q2MFIA#t0?`3RBqC-of6q)~uAap3HdBS!r(L|=m_CbhG_?M0nRdU! za+N$`v#{AR9*I37aSwW<{rx<_alxmXjJ7wdMs(d+AbmDKkun zxNADgt=QBMGJt|%;$?3QRKm~2lAv$7~~ zm#1b#ezjeTwZ+%)uRXAQhND$7Yq}y;Z0N}ae#}g~(O&a@NN{Q=;%ALuWdyPjgKha1 z^qH8hj~Oj&|CQJqi68IC)kHl+J9#OANFm&C^l+Riy~ct_6&jk#Dz?~LPUPIX#ldF_ zW0Ydn2BUG1EGb%yPfqz^>!Aj_A&5jM#SE1j#;0e>hILesXRhytbVjz}T!$(2UG`r+ zE9hj7^XV}pe_=*Wy#KbraJIS5pwhbL-IiZQgfE($qt8uNd$`SOWOiVKvLSlcNU@oQ zq}RZ+(!)qZH|jdg|6n$C+=~HPW%VUOOm?OM)*)_f^ty`3Hg_a<3?=_Gsj%m?LMnn4 zM;P|R%*>kvvzG+HOPdi1o*CU0KdR@WDt29Ad*z@e;!`C$FnZ`jW*iEOa*#RLVfA@+ z+cVNoL^5!kAr)kjC^e04q%YsPW;m$r)Pl!g|IJg!Pv}cK;1z`p4iOs1%_@A}$ha-8 z=O2JgnJ#B+&s&%J9Y-!UiQ>qh46?Tum`vfmU5DDmi<{^@qVH(i{Wa3&kPt{Y2Xi@>?$MM9o_m0{Du0I|^QvvAl?YTB3IaUNk?lHtl`xQ^gl zI0?K^1k+2?%Y5>hakizebaJs}fH_YC5m=qiLqegmX{NO`;&G|t2d|1)$@$=pM&G{T z$tcm{$tX1JPj(aRXz!uyq1aP~PUfg=$Vwj94~n&0EAMYsPi+au+RJOFCGm>t%g4)$ zy8wHssZ!$}Cs<-(e!kWyLDucSrk*h1NwRNA)4z|8+@KR5LE?Cmpoh2v_?GW<0|W-7 zsSq*URM_(*hWUXV*WA$Td?tARavJJ7!I!q9u_)70nYNd`litCj8i4y#QD`BcN;x)o zqi@vOrBYN*G12esR0EH`6m|A>czDL@5pY>c5amCYwX7Y;x81C7B6O)}mQ&$Wc7sCz z_mMgLd7tS0bCoFdEV?7?i}4}rHOKp`@{^bpQK49@$l~rAV?+eE7oMU(K3JhB(xbQ5 zw3#ybod|Bx?CIV#2yWGFLxA_#QRA@m$J=*=>){U$ouu(5(|PaiD%+|35jdzRR?-K& zcOKoneni5{64IXH-yi|y>KBSqa|6z%b?7&F&rh&Vry9#X9ng>2;H5YZgOgfvZUVMj zCc*RLJ}hy*#_U7g#;}%ovIVREp|4In13Ws74;9*$jyegolUPuFlxz9~rKV1cA?>iI2H1PgwGgYmzM5 z%NpXeM9LNX*_b~SA2BX{>X#a9emgCzLqs%f^NeHJyZZA+&|1Os{nAp%eps*c){!}) zp%{1l6Zf|c9MJy zK5w7LKcM&gX<^%=h3!!oJfD)K=A;AChS`1!wTpJ?#e4g>ufF zC|rLcme#&WYIE-CbE!Vo_;v|POZpA+54$S4hpvo(5~bAF`dYbQaZhmO35QH3P9UV zEz!OX*wy`R8{#cx=I+Z{F(Jgv48h1V{J!1?Vhg7fT5aPCMCXm8z83~LQZ|jXUgHFY z$D34B!#R%9Jw~roo{}rG>xs)}QhLq3YC+?h^Gp-!wc$)THF#@W@jcZva6uo6i761h z(d`YG)=6xGVc6I&qOf|Z$h9d;D)_MtB2t0gAO(W;QKJgxQWm}wFyDg(TA#;Gh^xeT zJTgs#91R;)sO4VcL^Vi`eD6!}bg5#Xl^0Zv>D9g^{TnnC{u{Jh+*FLYk(Is`Du+!Q z(E3@dN6^9MmwGDEJ2$lzuVgq{VHE>ARVMaYDd^Bo?vwHgy(;cgy&eOR+l0xY9-){! zH?|h{vAqVJlMsF9{cXdOINYyWRxz6jU6{|KB7Oa5p9lmzEuMNB%R?v9dj@`W7x+Y#plmHIbUIRF zCA<1{f!&PR?iYvJpvw5B`jL@dMNM%HRliVpS8Lk)!zGQ^y73{hX43TX^x_sJL)jW3 zN*uuQ+G8UbgyO1IG z9^+3NTV&QVkJyPVVA<>qESnRGoU|n!Q(jjZbDVa)@J3xIv%2DvN=bPlE7SJlpJj91 zc63twEyxy$?#yF(;*zrDRu1zxCHeWw45#6E$Pxu`b;@aXLdlQ8-8Hnt(Gh)5N*n`O zNbBoU;NoI3X?}LHC&&o-G!@;-i|Hu2dIWuDTv#)!E^BYimGI_7?%&MH0;^&LiH>D% z4has2r8XMx+(=-#?N7C@XTEo?)p-LU-K4`odXrKUGPSVheW&Psg>tpa2gy2*f^wru zH*H!kEXm&qTiI#_PQL3IQ|5|`Ew|>aU>3^}Op5U8_WkyGagyB|_0oqN+P9-wWl6-w zH<)x09(C>~(?GGLokv|C>%Ys+20xr-&^Cd>nwo*H;AWUVDkaV`IyRh%WF@>Q_?9gX za>C*M8w9Na6CY_56ncH0QEe+{eM0f#b9?rO`L5eV4&HV>@7!f9bvpIb)E+q#i?aGn zt=ZIGR$0%;c-`u;S4oif@7)T?p|XrzN&|K?#j02)k@YSirIqWO_=50&od<3VAV83Bw`G`bLl`l!vL)Dn=xWWWECJ}q;vU2h#7Lps0 ziT0S&v0&rW?2ACJk@ITS0=!U#Q~tTjTC_0rhnT09dZ<&+lK3*S}RJ38)H~ z$GIiTE+www6K? zaD{OZIzYBmg{B^9Yg74kSP3jjL%p#lCJMc-X*9{$sMgrd%IBHxR~1{W7qyEh_eC)b zR+DGTHC1pS4fJ9tve8 zxBj^-J}bT&D3sNSu4`Ogor%Q8ZrMRO9K=iYV(_M-$aA|46Ma3cEf$EdEJ@>T^F`lp zA2eqV6&(>3YopGcG>9my&+9c#{Nku}9T`blyQv<|+7T{qF@Lcj-hYx1lkyvsV)z@> zuI2ohf#7%m*U;$G4T|&6`G#2BD~zNYMcgy^UqvE^UyPc9vu=NGLvn6=*DpvDCm8O; zl78VH6FE~n61??81mZ2E*S~Dh`pSyR)5`$vm|_&g#~OhF8T$4Q34mRYHJ1UvGE~qs zy=_X-cK(`2J&1V{elMkHDYj8OmOa1fOSt|yvcysc9F-Y#gn{@W#m-aa!2zdwZui)0 zK}jQzb+<~coJ1!}g{4)j$r&bKX_=(vi*(q3&8C@FzD@hWlafg4zizCh#Ra*n4a#>d z)dsm(u(;Pk|d3Gn{{OJF9 z$s@>pn>F8$0(~(+CJEh*pZFp8!c*W6ec819*|hF%g?a=8MCoYAFL&k86u`i*17xCn ze3^qpyRHL#7wl1u76tB~p3*PZmV}UeXH?GSa176_kn)vwRZJbz*QLrxhnL%|V2@fv*VqvBoJtnM&%Qi$!s)o;y3O?Qf$U_%&){Wd zi{0z^79`#D^6%&VNw;;TVG;J4gBE-Q7e?QbY$jq8uY}U7D!p>Z(fcjdvY_T^g64*8 z7?afj0z;KM`qUZFvH`!$iBKcx3dhQ`Lrl}^1AEprE;WiADP}`q(FWW^)lW~UY2Ay{ zy>q?6Z@0L;*09w|!-?`DR#0lfyS_qpq&9qH)XlBYTL^tv@R`$Yr_@4we$iD5o}0=> zQNqVb)W^xt(9k_A{><;H7}RB!QvP|OBISYw^cKXRzurJ@H5MV-$vpw_ne?bfHt4jb zeW%J}FlxEF7ALup_ojl_eV*Kg%`T)~`0(o~y};RSBZ)$RGmpfL!QP|;cOK-~aN6)aTC}>*wI@nh^+Kkuj)VN=&|C5Mi-^rMv&%i;dkgfgq`1l=c360X< zpeS)oy4&Zq?Q>gll3XSY2Kxc5r!~-R{mTWMgE+ePt|WmLBT@zOQgU2i4&uY+S{NRt_^zn!$Ue@Vq^t2Ol5dnF*Q_q0dL@!O9MugX&sGa&mBWvmP2%tH&k zG=*A2-o&qM%v2wemkg!005Y(6#n=iz34inCWw3y1eTg2vKx;!ojEM+%`Z~#!;9d3% zaV0(tjb0i(RpQYoFpPg?L}6r0ji)6@rG9Jx_SPwZB~(llbtv%aKJWpSV&^L>|1<&_ z82WyJF~EAM;zPW&r=i*3XBD8-TNE*LW>lHSwxix4#g0?vAg=74g=l6?gYE*$Xf3DU zO17Nr*5_7~j?+{W%J{)j$&$jK;CAT@TK%upR304;$}*r$erGcrlc)BEPfvIEYrY?x z*eLJ}P9HUiY?FUN?iRag%<lms{FQnSt3f;2Ezeg0 zW7wup7Ng_=`o?O@l$t0bJgCyYIM>%84#l9WVlty1Zc4$N8e{k!whS0o>ol)iuez#f zWFB8n2~2E?tEI4G5HB0cU~cN1QP0#;s2Pw}kkn4S^JSMN4cvNPPJ>17VtAtD9Vvu! z{2Ile*Iep1NZba1MQn&b+NK;0cJ5p1H9I(|3THrxfvOwdddd}~nybY!%_#vDh=Ap& zb56@8?|~PiLJB9t$|b!gvh`ApX=9n_767PPs#>OAs<~K}s?d}I3x!(V z$UJ{S#)le-UZJTqOn`Vv{I3l6=;|dO!Uyh|v`Sa^loJ%{85Xxm75!VX*iz@O8vi@d z(jYe&Vrq#19U#}xWh2R;EQ@Ie2ssGofGqpq!&r^t^w+29a@omZLY#gN{Z%jKYiQdl zdyP+y-U%At6qA`>W`qt3_j86$*+vB(e<>L?={mxHx#=!AlbC50>!A9@Rw>{t1WZ3I z&Ov=kc7WFrgLk*;LplH%Hdx>xN0W8`vbw-!U=-pJK`Vv#=odNrQiNA#6_F@MrW5g5P&UZJJ$tEeLjK`FJT*@ zC!5q;-5;hGU$rK=_0knwhXw!k(UAne{}X zp<D~A?Pr_^A{kJqP zU56;c_yP@QzN%DBDj$wO_kndtdBzx|9>>&O_~em#=23<1&E32&DdmhQol?@^ z-ey=EQM<$bwd^)n>M2`unp^)Nbmx+O)D}{I=WP1nd*~ipMBd=W*@@^fn%2g*nJ5{k znM&g`BA`ws&2H{>H0rSe|ll@oU3uH)?W^&%3!g~fuQzIynJ4%c(;ed^d^HBeoh1OC4@i*;PLC!SqVP0x*y zUAodtm-bI%ynj;w2*x{M5UMUz((HA?r_Ij9O;Gc1^kpTqH>wMjHHRz?z3E!E$L{|Z z`T5w+0*t7t;S;^z7I`d!IaR0`dde12cQ3Y&mke^Yst>YEe7P#by>~C^Le%e%gMj~k zE%$z40bqG%u?t}N$02m>pGv;}T{F-jAO5SlAhJ_hGhK5YzxDqt`5#^PSII=w??}7y zK()|~f9c~7N)Js>0cD)p-|NjTMhyQ8*R2B^0F4tsw}^T5RyF74{foH$F6SP)8JFb$ ztTotwx{v+M!s8%76Z4Axr9N*UwOd^%r&<4k^tvF_{3h$KG>|dGD zI6j#aEf~fjd&t-yMZjh=;hx2p{w9r~2J%D5XA)x9kY9mn*j}869o6=EIu=j6NAYWq zbbh?Qp|!p@rFgjMRgUsAuMz9`#}+FblaqpL0VFWi*#(cDiR|iO$wqb060>jQ;BTi0 zrr_{nI>i|nzRtQZS357Emkm=t=VRE@V+>?`SN7ckg6xgRfQ%ptGNB#YSdLTvcJ%6E)q7ur0)>o7ht-`;q@n$#JiQVJz>%5Wpqy05VnI%=Iy=M%SLCR`; z#Hw)FMdI<4OPgugKGgw~i1eE~9UUP%Hy)tzX68ITs0z*JHcUa!>zX4XY}nZo+x`do zKXPEo?B!i_IxCGrLc*NNeY1F|Gv?9>3#W49^0bnrkjmk8z!Y!TMzyF`A{(q4beDwUw zQw9q=C|hPSxBe)Ek7}yX2L}F{v1MwafNH?+Ftqr1TT>iAG|vSk8xFWG{`d6%0>jmV AYybcN diff --git a/src/goadmin/static/uploadfile/193c18d2-ba46-48e9-ace1-0f774d16706a.jpeg b/src/goadmin/static/uploadfile/193c18d2-ba46-48e9-ace1-0f774d16706a.jpeg deleted file mode 100644 index ecf30c45d26924c26d9c1f5a2ee33957f1875294..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27325 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 - -## Backers - -Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/casbin#backer)] - - - -## Sponsors - -Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/casbin#sponsor)] - - - - - - - - - - - - -## License - -This project is licensed under the [Apache 2.0 license](LICENSE). - -## Contact - -If you have any issues or feature requests, please contact us. PR is welcomed. -- https://github.com/casbin/casbin/issues -- hsluoyz@gmail.com -- Tencent QQ group: [546057381](//shang.qq.com/wpa/qunwpa?idkey=8ac8b91fc97ace3d383d0035f7aa06f7d670fd8e8d4837347354a31c18fac885) diff --git a/src/goadmin/vendor/github.com/casbin/casbin/casbin-logo.png b/src/goadmin/vendor/github.com/casbin/casbin/casbin-logo.png deleted file mode 100644 index 7e5d1ecf95b4f0a47e297dc1269b2faa309837d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34267 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[F1lucH={v$u@` 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:value to the configuration. -func (c *Config) AddConfig(section string, option string, value string) bool { - if section == "" { - section = DEFAULT_SECTION - } - - if _, ok := c.data[section]; !ok { - c.data[section] = make(map[string]string) - } - - _, ok := c.data[section][option] - c.data[section][option] = value - - return !ok -} - -func (c *Config) parse(fname string) (err error) { - c.Lock() - f, err := os.Open(fname) - if err != nil { - return err - } - defer c.Unlock() - defer f.Close() - - buf := bufio.NewReader(f) - return c.parseBuffer(buf) -} - -func (c *Config) parseBuffer(buf *bufio.Reader) error { - var section string - var lineNum int - var buffer bytes.Buffer - var canWrite bool - for { - if canWrite { - if err := c.write(section, lineNum, &buffer); err != nil { - return err - } else { - canWrite = false - } - } - lineNum++ - line, _, err := buf.ReadLine() - if err == io.EOF { - // force write when buffer is not flushed yet - if buffer.Len() > 0 { - if err := c.write(section, lineNum, &buffer); err != nil { - return err - } - } - break - } else if err != nil { - return err - } - - line = bytes.TrimSpace(line) - switch { - case bytes.Equal(line, []byte{}), bytes.HasPrefix(line, DEFAULT_COMMENT_SEM), - bytes.HasPrefix(line, DEFAULT_COMMENT): - canWrite = true - continue - case bytes.HasPrefix(line, []byte{'['}) && bytes.HasSuffix(line, []byte{']'}): - // force write when buffer is not flushed yet - if buffer.Len() > 0 { - if err := c.write(section, lineNum, &buffer); err != nil { - return err - } - canWrite = false - } - section = string(line[1 : len(line)-1]) - default: - var p []byte - if bytes.HasSuffix(line, DEFAULT_MULTI_LINE_SEPARATOR) { - p = bytes.TrimSpace(line[:len(line)-1]) - } else { - p = line - canWrite = true - } - - if _, err := buffer.Write(p); err != nil { - return err - } - } - } - - return nil -} - -func (c *Config) write(section string, lineNum int, b *bytes.Buffer) error { - if b.Len() <= 0 { - return nil - } - - optionVal := bytes.SplitN(b.Bytes(), []byte{'='}, 2) - if len(optionVal) != 2 { - return fmt.Errorf("parse the content error : line %d , %s = ? ", lineNum, optionVal[0]) - } - option := bytes.TrimSpace(optionVal[0]) - value := bytes.TrimSpace(optionVal[1]) - c.AddConfig(section, string(option), string(value)) - - // flush buffer after adding - b.Reset() - - return nil -} - -// Bool lookups up the value using the provided key and converts the value to a bool -func (c *Config) Bool(key string) (bool, error) { - return strconv.ParseBool(c.get(key)) -} - -// Int lookups up the value using the provided key and converts the value to a int -func (c *Config) Int(key string) (int, error) { - return strconv.Atoi(c.get(key)) -} - -// Int64 lookups up the value using the provided key and converts the value to a int64 -func (c *Config) Int64(key string) (int64, error) { - return strconv.ParseInt(c.get(key), 10, 64) -} - -// Float64 lookups up the value using the provided key and converts the value to a float64 -func (c *Config) Float64(key string) (float64, error) { - return strconv.ParseFloat(c.get(key), 64) -} - -// String lookups up the value using the provided key and converts the value to a string -func (c *Config) String(key string) string { - return c.get(key) -} - -// Strings lookups up the value using the provided key and converts the value to an array of string -// by splitting the string by comma -func (c *Config) Strings(key string) []string { - v := c.get(key) - if v == "" { - return nil - } - return strings.Split(v, ",") -} - -// Set sets the value for the specific key in the Config -func (c *Config) Set(key string, value string) error { - c.Lock() - defer c.Unlock() - if len(key) == 0 { - return errors.New("key is empty") - } - - var ( - section string - option string - ) - - keys := strings.Split(strings.ToLower(key), "::") - if len(keys) >= 2 { - section = keys[0] - option = keys[1] - } else { - option = keys[0] - } - - c.AddConfig(section, option, value) - return nil -} - -// section.key or key -func (c *Config) get(key string) string { - var ( - section string - option string - ) - - keys := strings.Split(strings.ToLower(key), "::") - if len(keys) >= 2 { - section = keys[0] - option = keys[1] - } else { - section = DEFAULT_SECTION - option = keys[0] - } - - if value, ok := c.data[section][option]; ok { - return value - } - - return "" -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/effect/default_effector.go b/src/goadmin/vendor/github.com/casbin/casbin/effect/default_effector.go deleted file mode 100644 index bf8ae80d..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/effect/default_effector.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2018 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package effect - -import "errors" - -// DefaultEffector is default effector for Casbin. -type DefaultEffector struct { -} - -// NewDefaultEffector is the constructor for DefaultEffector. -func NewDefaultEffector() *DefaultEffector { - e := DefaultEffector{} - return &e -} - -// MergeEffects merges all matching results collected by the enforcer into a single decision. -func (e *DefaultEffector) MergeEffects(expr string, effects []Effect, results []float64) (bool, error) { - result := false - if expr == "some(where (p_eft == allow))" { - result = false - for _, eft := range effects { - if eft == Allow { - result = true - break - } - } - } else if expr == "!some(where (p_eft == deny))" { - result = true - for _, eft := range effects { - if eft == Deny { - result = false - break - } - } - } else if expr == "some(where (p_eft == allow)) && !some(where (p_eft == deny))" { - result = false - for _, eft := range effects { - if eft == Allow { - result = true - } else if eft == Deny { - result = false - break - } - } - } else if expr == "priority(p_eft) || deny" { - result = false - for _, eft := range effects { - if eft != Indeterminate { - if eft == Allow { - result = true - } else { - result = false - } - break - } - } - } else { - return false, errors.New("unsupported effect") - } - - return result, nil -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/effect/effector.go b/src/goadmin/vendor/github.com/casbin/casbin/effect/effector.go deleted file mode 100644 index 52271b3f..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/effect/effector.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2018 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package effect - -// Effect is the result for a policy rule. -type Effect int - -// Values for policy effect. -const ( - Allow Effect = iota - Indeterminate - Deny -) - -// Effector is the interface for Casbin effectors. -type Effector interface { - // MergeEffects merges all matching results collected by the enforcer into a single decision. - MergeEffects(expr string, effects []Effect, results []float64) (bool, error) -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/enforcer.go b/src/goadmin/vendor/github.com/casbin/casbin/enforcer.go deleted file mode 100644 index 33cdb89b..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/enforcer.go +++ /dev/null @@ -1,483 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -import ( - "errors" - "fmt" - - "github.com/Knetic/govaluate" - "github.com/casbin/casbin/effect" - "github.com/casbin/casbin/log" - "github.com/casbin/casbin/model" - "github.com/casbin/casbin/persist" - fileadapter "github.com/casbin/casbin/persist/file-adapter" - "github.com/casbin/casbin/rbac" - defaultrolemanager "github.com/casbin/casbin/rbac/default-role-manager" - "github.com/casbin/casbin/util" -) - -// Enforcer is the main interface for authorization enforcement and policy management. -type Enforcer struct { - modelPath string - model model.Model - fm model.FunctionMap - eft effect.Effector - - adapter persist.Adapter - watcher persist.Watcher - rm rbac.RoleManager - - enabled bool - autoSave bool - autoBuildRoleLinks bool -} - -// NewEnforcer creates an enforcer via file or DB. -// File: -// e := casbin.NewEnforcer("path/to/basic_model.conf", "path/to/basic_policy.csv") -// MySQL DB: -// a := mysqladapter.NewDBAdapter("mysql", "mysql_username:mysql_password@tcp(127.0.0.1:3306)/") -// e := casbin.NewEnforcer("path/to/basic_model.conf", a) -func NewEnforcer(params ...interface{}) *Enforcer { - e := &Enforcer{} - - parsedParamLen := 0 - if len(params) >= 1 { - enableLog, ok := params[len(params)-1].(bool) - if ok { - e.EnableLog(enableLog) - - parsedParamLen++ - } - } - - if len(params)-parsedParamLen == 2 { - switch p0 := params[0].(type) { - case string: - switch p1 := params[1].(type) { - case string: - e.InitWithFile(p0, p1) - default: - e.InitWithAdapter(p0, p1.(persist.Adapter)) - } - default: - switch params[1].(type) { - case string: - panic("Invalid parameters for enforcer.") - default: - e.InitWithModelAndAdapter(p0.(model.Model), params[1].(persist.Adapter)) - } - } - } else if len(params)-parsedParamLen == 1 { - switch p0 := params[0].(type) { - case string: - e.InitWithFile(p0, "") - default: - e.InitWithModelAndAdapter(p0.(model.Model), nil) - } - } else if len(params)-parsedParamLen == 0 { - e.InitWithFile("", "") - } else { - panic("Invalid parameters for enforcer.") - } - - return e -} - -// InitWithFile initializes an enforcer with a model file and a policy file. -func (e *Enforcer) InitWithFile(modelPath string, policyPath string) { - a := fileadapter.NewAdapter(policyPath) - e.InitWithAdapter(modelPath, a) -} - -// InitWithAdapter initializes an enforcer with a database adapter. -func (e *Enforcer) InitWithAdapter(modelPath string, adapter persist.Adapter) { - m := NewModel(modelPath, "") - e.InitWithModelAndAdapter(m, adapter) - - e.modelPath = modelPath -} - -// InitWithModelAndAdapter initializes an enforcer with a model and a database adapter. -func (e *Enforcer) InitWithModelAndAdapter(m model.Model, adapter persist.Adapter) { - e.adapter = adapter - - e.model = m - e.model.PrintModel() - e.fm = model.LoadFunctionMap() - - e.initialize() - - // Do not initialize the full policy when using a filtered adapter - fa, ok := e.adapter.(persist.FilteredAdapter) - if e.adapter != nil && (!ok || ok && !fa.IsFiltered()) { - // error intentionally ignored - e.LoadPolicy() - } -} - -func (e *Enforcer) initialize() { - e.rm = defaultrolemanager.NewRoleManager(10) - e.eft = effect.NewDefaultEffector() - e.watcher = nil - - e.enabled = true - e.autoSave = true - e.autoBuildRoleLinks = true -} - -// NewModel creates a model. -func NewModel(text ...string) model.Model { - m := make(model.Model) - - if len(text) == 2 { - if text[0] != "" { - m.LoadModel(text[0]) - } - } else if len(text) == 1 { - m.LoadModelFromText(text[0]) - } else if len(text) != 0 { - panic("Invalid parameters for model.") - } - - return m -} - -// LoadModel reloads the model from the model CONF file. -// Because the policy is attached to a model, so the policy is invalidated and needs to be reloaded by calling LoadPolicy(). -func (e *Enforcer) LoadModel() { - e.model = NewModel() - e.model.LoadModel(e.modelPath) - e.model.PrintModel() - e.fm = model.LoadFunctionMap() -} - -// GetModel gets the current model. -func (e *Enforcer) GetModel() model.Model { - return e.model -} - -// SetModel sets the current model. -func (e *Enforcer) SetModel(m model.Model) { - e.model = m - e.fm = model.LoadFunctionMap() -} - -// GetAdapter gets the current adapter. -func (e *Enforcer) GetAdapter() persist.Adapter { - return e.adapter -} - -// SetAdapter sets the current adapter. -func (e *Enforcer) SetAdapter(adapter persist.Adapter) { - e.adapter = adapter -} - -// SetWatcher sets the current watcher. -func (e *Enforcer) SetWatcher(watcher persist.Watcher) { - e.watcher = watcher - // error intentionally ignored - watcher.SetUpdateCallback(func(string) { e.LoadPolicy() }) -} - -// SetRoleManager sets the current role manager. -func (e *Enforcer) SetRoleManager(rm rbac.RoleManager) { - e.rm = rm -} - -// SetEffector sets the current effector. -func (e *Enforcer) SetEffector(eft effect.Effector) { - e.eft = eft -} - -// ClearPolicy clears all policy. -func (e *Enforcer) ClearPolicy() { - e.model.ClearPolicy() -} - -// LoadPolicy reloads the policy from file/database. -func (e *Enforcer) LoadPolicy() error { - e.model.ClearPolicy() - if err := e.adapter.LoadPolicy(e.model); err != nil && err.Error() != "invalid file path, file path cannot be empty" { - return err - } - - e.model.PrintPolicy() - if e.autoBuildRoleLinks { - e.BuildRoleLinks() - } - return nil -} - -// LoadFilteredPolicy reloads a filtered policy from file/database. -func (e *Enforcer) LoadFilteredPolicy(filter interface{}) error { - e.model.ClearPolicy() - - var filteredAdapter persist.FilteredAdapter - - // Attempt to cast the Adapter as a FilteredAdapter - switch adapter := e.adapter.(type) { - case persist.FilteredAdapter: - filteredAdapter = adapter - default: - return errors.New("filtered policies are not supported by this adapter") - } - if err := filteredAdapter.LoadFilteredPolicy(e.model, filter); err != nil && err.Error() != "invalid file path, file path cannot be empty" { - return err - } - - e.model.PrintPolicy() - if e.autoBuildRoleLinks { - e.BuildRoleLinks() - } - return nil -} - -// IsFiltered returns true if the loaded policy has been filtered. -func (e *Enforcer) IsFiltered() bool { - filteredAdapter, ok := e.adapter.(persist.FilteredAdapter) - if !ok { - return false - } - return filteredAdapter.IsFiltered() -} - -// SavePolicy saves the current policy (usually after changed with Casbin API) back to file/database. -func (e *Enforcer) SavePolicy() error { - if e.IsFiltered() { - return errors.New("cannot save a filtered policy") - } - if err := e.adapter.SavePolicy(e.model); err != nil { - return err - } - if e.watcher != nil { - return e.watcher.Update() - } - return nil -} - -// EnableEnforce changes the enforcing state of Casbin, when Casbin is disabled, all access will be allowed by the Enforce() function. -func (e *Enforcer) EnableEnforce(enable bool) { - e.enabled = enable -} - -// EnableLog changes whether Casbin will log messages to the Logger. -func (e *Enforcer) EnableLog(enable bool) { - log.GetLogger().EnableLog(enable) -} - -// EnableAutoSave controls whether to save a policy rule automatically to the adapter when it is added or removed. -func (e *Enforcer) EnableAutoSave(autoSave bool) { - e.autoSave = autoSave -} - -// EnableAutoBuildRoleLinks controls whether to rebuild the role inheritance relations when a role is added or deleted. -func (e *Enforcer) EnableAutoBuildRoleLinks(autoBuildRoleLinks bool) { - e.autoBuildRoleLinks = autoBuildRoleLinks -} - -// BuildRoleLinks manually rebuild the role inheritance relations. -func (e *Enforcer) BuildRoleLinks() { - // error intentionally ignored - e.rm.Clear() - e.model.BuildRoleLinks(e.rm) -} - -// Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act). -func (e *Enforcer) Enforce(rvals ...interface{}) bool { - if !e.enabled { - return true - } - - functions := make(map[string]govaluate.ExpressionFunction) - for key, function := range e.fm { - functions[key] = function - } - if _, ok := e.model["g"]; ok { - for key, ast := range e.model["g"] { - rm := ast.RM - functions[key] = util.GenerateGFunction(rm) - } - } - - expString := e.model["m"]["m"].Value - expression, err := govaluate.NewEvaluableExpressionWithFunctions(expString, functions) - if err != nil { - panic(err) - } - - rTokens := make(map[string]int, len(e.model["r"]["r"].Tokens)) - for i, token := range e.model["r"]["r"].Tokens { - rTokens[token] = i - } - pTokens := make(map[string]int, len(e.model["p"]["p"].Tokens)) - for i, token := range e.model["p"]["p"].Tokens { - pTokens[token] = i - } - - parameters := enforceParameters{ - rTokens: rTokens, - rVals: rvals, - - pTokens: pTokens, - } - - var policyEffects []effect.Effect - var matcherResults []float64 - if policyLen := len(e.model["p"]["p"].Policy); policyLen != 0 { - policyEffects = make([]effect.Effect, policyLen) - matcherResults = make([]float64, policyLen) - if len(e.model["r"]["r"].Tokens) != len(rvals) { - panic( - fmt.Sprintf( - "Invalid Request Definition size: expected %d got %d rvals: %v", - len(e.model["r"]["r"].Tokens), - len(rvals), - rvals)) - } - for i, pvals := range e.model["p"]["p"].Policy { - // log.LogPrint("Policy Rule: ", pvals) - if len(e.model["p"]["p"].Tokens) != len(pvals) { - panic( - fmt.Sprintf( - "Invalid Policy Rule size: expected %d got %d pvals: %v", - len(e.model["p"]["p"].Tokens), - len(pvals), - pvals)) - } - - parameters.pVals = pvals - - result, err := expression.Eval(parameters) - // log.LogPrint("Result: ", result) - - if err != nil { - policyEffects[i] = effect.Indeterminate - panic(err) - } - - switch result := result.(type) { - case bool: - if !result { - policyEffects[i] = effect.Indeterminate - continue - } - case float64: - if result == 0 { - policyEffects[i] = effect.Indeterminate - continue - } else { - matcherResults[i] = result - } - default: - panic(errors.New("matcher result should be bool, int or float")) - } - - if j, ok := parameters.pTokens["p_eft"]; ok { - eft := parameters.pVals[j] - if eft == "allow" { - policyEffects[i] = effect.Allow - } else if eft == "deny" { - policyEffects[i] = effect.Deny - } else { - policyEffects[i] = effect.Indeterminate - } - } else { - policyEffects[i] = effect.Allow - } - - if e.model["e"]["e"].Value == "priority(p_eft) || deny" { - break - } - - } - } else { - policyEffects = make([]effect.Effect, 1) - matcherResults = make([]float64, 1) - - parameters.pVals = make([]string, len(parameters.pTokens)) - - result, err := expression.Eval(parameters) - // log.LogPrint("Result: ", result) - - if err != nil { - policyEffects[0] = effect.Indeterminate - panic(err) - } - - if result.(bool) { - policyEffects[0] = effect.Allow - } else { - policyEffects[0] = effect.Indeterminate - } - } - - // log.LogPrint("Rule Results: ", policyEffects) - - result, err := e.eft.MergeEffects(e.model["e"]["e"].Value, policyEffects, matcherResults) - if err != nil { - panic(err) - } - - // Log request. - if log.GetLogger().IsEnabled() { - reqStr := "Request: " - for i, rval := range rvals { - if i != len(rvals)-1 { - reqStr += fmt.Sprintf("%v, ", rval) - } else { - reqStr += fmt.Sprintf("%v", rval) - } - } - reqStr += fmt.Sprintf(" ---> %t", result) - log.LogPrint(reqStr) - } - - return result -} - -// assumes bounds have already been checked -type enforceParameters struct { - rTokens map[string]int - rVals []interface{} - - pTokens map[string]int - pVals []string -} - -// implements govaluate.Parameters -func (p enforceParameters) Get(name string) (interface{}, error) { - if name == "" { - return nil, nil - } - - switch name[0] { - case 'p': - i, ok := p.pTokens[name] - if !ok { - return nil, errors.New("No parameter '" + name + "' found.") - } - return p.pVals[i], nil - case 'r': - i, ok := p.rTokens[name] - if !ok { - return nil, errors.New("No parameter '" + name + "' found.") - } - return p.rVals[i], nil - default: - return nil, errors.New("No parameter '" + name + "' found.") - } -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/enforcer_cached.go b/src/goadmin/vendor/github.com/casbin/casbin/enforcer_cached.go deleted file mode 100644 index 1d1fcfc3..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/enforcer_cached.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2018 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -import ( - "sync" -) - -// CachedEnforcer wraps Enforcer and provides decision cache -type CachedEnforcer struct { - *Enforcer - m map[string]bool - enableCache bool - locker *sync.RWMutex -} - -// NewCachedEnforcer creates a cached enforcer via file or DB. -func NewCachedEnforcer(params ...interface{}) *CachedEnforcer { - e := &CachedEnforcer{} - e.Enforcer = NewEnforcer(params...) - e.enableCache = true - e.m = make(map[string]bool) - e.locker = new(sync.RWMutex) - return e -} - -// EnableCache determines whether to enable cache on Enforce(). When enableCache is enabled, cached result (true | false) will be returned for previous decisions. -func (e *CachedEnforcer) EnableCache(enableCache bool) { - e.enableCache = enableCache -} - -// Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act). -// if rvals is not string , ingore the cache -func (e *CachedEnforcer) Enforce(rvals ...interface{}) bool { - if !e.enableCache { - return e.Enforcer.Enforce(rvals...) - } - - key := "" - for _, rval := range rvals { - if val, ok := rval.(string); ok { - key += val + "$$" - } else { - return e.Enforcer.Enforce(rvals...) - } - } - - if res, ok := e.getCachedResult(key); ok { - return res - } else { - res := e.Enforcer.Enforce(rvals...) - e.setCachedResult(key, res) - return res - } -} - -func (e *CachedEnforcer) getCachedResult(key string) (res bool, ok bool) { - e.locker.RLock() - defer e.locker.RUnlock() - res, ok = e.m[key] - return res, ok -} - -func (e *CachedEnforcer) setCachedResult(key string, res bool) { - e.locker.Lock() - defer e.locker.Unlock() - e.m[key] = res -} - -// InvalidateCache deletes all the existing cached decisions. -func (e *CachedEnforcer) InvalidateCache() { - e.m = make(map[string]bool) -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/enforcer_safe.go b/src/goadmin/vendor/github.com/casbin/casbin/enforcer_safe.go deleted file mode 100644 index adeedf6e..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/enforcer_safe.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -import ( - "fmt" -) - -// NewEnforcerSafe calls NewEnforcer in a safe way, returns error instead of causing panic. -func NewEnforcerSafe(params ...interface{}) (e *Enforcer, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - e = nil - } - }() - - e = NewEnforcer(params...) - err = nil - return -} - -// LoadModelSafe calls LoadModel in a safe way, returns error instead of causing panic. -func (e *Enforcer) LoadModelSafe() (err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - } - }() - - e.LoadModel() - err = nil - return -} - -// EnforceSafe calls Enforce in a safe way, returns error instead of causing panic. -func (e *Enforcer) EnforceSafe(rvals ...interface{}) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.Enforce(rvals...) - err = nil - return -} - -// AddPolicySafe calls AddPolicy in a safe way, returns error instead of causing panic. -func (e *Enforcer) AddPolicySafe(params ...interface{}) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.AddNamedPolicy("p", params...) - err = nil - return -} - -// RemovePolicySafe calls RemovePolicy in a safe way, returns error instead of causing panic. -func (e *Enforcer) RemovePolicySafe(params ...interface{}) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.RemoveNamedPolicy("p", params...) - err = nil - return -} - -// RemoveFilteredPolicySafe calls RemoveFilteredPolicy in a safe way, returns error instead of causing panic. -func (e *Enforcer) RemoveFilteredPolicySafe(fieldIndex int, fieldValues ...string) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.RemoveFilteredNamedPolicy("p", fieldIndex, fieldValues...) - err = nil - return -} - -// AddGroupingPolicySafe calls AddGroupingPolicy in a safe way, returns error instead of causing panic. -func (e *Enforcer) AddGroupingPolicySafe(params ...interface{}) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.AddGroupingPolicy(params...) - err = nil - return -} - -// AddNamedGroupingPolicySafe calls AddNamedGroupingPolicy in a safe way, returns error instead of causing panic. -func (e *Enforcer) AddNamedGroupingPolicySafe(ptype string, params ...interface{}) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.AddNamedGroupingPolicy(ptype, params...) - err = nil - return -} - -// AddNamedPolicySafe calls AddNamedPolicy in a safe way, returns error instead of causing panic. -func (e *Enforcer) AddNamedPolicySafe(ptype string, params ...interface{}) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.AddNamedPolicy(ptype, params...) - err = nil - return -} - -// RemoveGroupingPolicySafe calls RemoveGroupingPolicy in a safe way, returns error instead of causing panic. -func (e *Enforcer) RemoveGroupingPolicySafe(params ...interface{}) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.RemoveGroupingPolicy(params...) - err = nil - return -} - -// RemoveFilteredGroupingPolicySafe calls RemoveFilteredGroupingPolicy in a safe way, returns error instead of causing panic. -func (e *Enforcer) RemoveFilteredGroupingPolicySafe(fieldIndex int, fieldValues ...string) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.RemoveFilteredGroupingPolicy(fieldIndex, fieldValues...) - err = nil - return -} - -// RemoveNamedGroupingPolicySafe calls RemoveNamedGroupingPolicy in a safe way, returns error instead of causing panic. -func (e *Enforcer) RemoveNamedGroupingPolicySafe(ptype string, params ...interface{}) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.RemoveNamedGroupingPolicy(ptype, params...) - err = nil - return -} - -// RemoveFilteredNamedGroupingPolicySafe calls RemoveFilteredNamedGroupingPolicy in a safe way, returns error instead of causing panic. -func (e *Enforcer) RemoveFilteredNamedGroupingPolicySafe(ptype string, fieldIndex int, fieldValues ...string) (result bool, err error) { - defer func() { - if r := recover(); r != nil { - err = fmt.Errorf("%v", r) - result = false - } - }() - - result = e.RemoveFilteredNamedGroupingPolicy(ptype, fieldIndex, fieldValues...) - err = nil - return -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/enforcer_synced.go b/src/goadmin/vendor/github.com/casbin/casbin/enforcer_synced.go deleted file mode 100644 index f752c71f..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/enforcer_synced.go +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -import ( - "log" - "sync" - "time" - - "github.com/casbin/casbin/persist" -) - -// SyncedEnforcer wraps Enforcer and provides synchronized access -type SyncedEnforcer struct { - *Enforcer - m sync.RWMutex - autoLoad bool -} - -// NewSyncedEnforcer creates a synchronized enforcer via file or DB. -func NewSyncedEnforcer(params ...interface{}) *SyncedEnforcer { - e := &SyncedEnforcer{} - e.Enforcer = NewEnforcer(params...) - e.autoLoad = false - return e -} - -// StartAutoLoadPolicy starts a go routine that will every specified duration call LoadPolicy -func (e *SyncedEnforcer) StartAutoLoadPolicy(d time.Duration) { - e.autoLoad = true - go func() { - n := 1 - log.Print("Start automatically load policy") - for { - if !e.autoLoad { - log.Print("Stop automatically load policy") - break - } - - // error intentionally ignored - e.LoadPolicy() - // Uncomment this line to see when the policy is loaded. - // log.Print("Load policy for time: ", n) - n++ - time.Sleep(d) - } - }() -} - -// StopAutoLoadPolicy causes the go routine to exit. -func (e *SyncedEnforcer) StopAutoLoadPolicy() { - e.autoLoad = false -} - -// SetWatcher sets the current watcher. -func (e *SyncedEnforcer) SetWatcher(watcher persist.Watcher) { - e.watcher = watcher - // error intentionally ignored - watcher.SetUpdateCallback(func(string) { e.LoadPolicy() }) -} - -// ClearPolicy clears all policy. -func (e *SyncedEnforcer) ClearPolicy() { - e.m.Lock() - defer e.m.Unlock() - e.Enforcer.ClearPolicy() -} - -// LoadPolicy reloads the policy from file/database. -func (e *SyncedEnforcer) LoadPolicy() error { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.LoadPolicy() -} - -// SavePolicy saves the current policy (usually after changed with Casbin API) back to file/database. -func (e *SyncedEnforcer) SavePolicy() error { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.SavePolicy() -} - -// BuildRoleLinks manually rebuild the role inheritance relations. -func (e *SyncedEnforcer) BuildRoleLinks() { - e.m.RLock() - defer e.m.RUnlock() - e.Enforcer.BuildRoleLinks() -} - -// Enforce decides whether a "subject" can access a "object" with the operation "action", input parameters are usually: (sub, obj, act). -func (e *SyncedEnforcer) Enforce(rvals ...interface{}) bool { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.Enforce(rvals...) -} - -// GetAllSubjects gets the list of subjects that show up in the current policy. -func (e *SyncedEnforcer) GetAllSubjects() []string { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetAllSubjects() -} - -// GetAllObjects gets the list of objects that show up in the current policy. -func (e *SyncedEnforcer) GetAllObjects() []string { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetAllObjects() -} - -// GetAllActions gets the list of actions that show up in the current policy. -func (e *SyncedEnforcer) GetAllActions() []string { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetAllActions() -} - -// GetAllRoles gets the list of roles that show up in the current policy. -func (e *SyncedEnforcer) GetAllRoles() []string { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetAllRoles() -} - -// GetPolicy gets all the authorization rules in the policy. -func (e *SyncedEnforcer) GetPolicy() [][]string { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetPolicy() -} - -// GetFilteredPolicy gets all the authorization rules in the policy, field filters can be specified. -func (e *SyncedEnforcer) GetFilteredPolicy(fieldIndex int, fieldValues ...string) [][]string { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetFilteredPolicy(fieldIndex, fieldValues...) -} - -// GetGroupingPolicy gets all the role inheritance rules in the policy. -func (e *SyncedEnforcer) GetGroupingPolicy() [][]string { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetGroupingPolicy() -} - -// GetFilteredGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified. -func (e *SyncedEnforcer) GetFilteredGroupingPolicy(fieldIndex int, fieldValues ...string) [][]string { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetFilteredGroupingPolicy(fieldIndex, fieldValues...) -} - -// HasPolicy determines whether an authorization rule exists. -func (e *SyncedEnforcer) HasPolicy(params ...interface{}) bool { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.HasPolicy(params...) -} - -// AddPolicy adds an authorization rule to the current policy. -// If the rule already exists, the function returns false and the rule will not be added. -// Otherwise the function returns true by adding the new rule. -func (e *SyncedEnforcer) AddPolicy(params ...interface{}) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.AddPolicy(params...) -} - -// RemovePolicy removes an authorization rule from the current policy. -func (e *SyncedEnforcer) RemovePolicy(params ...interface{}) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.RemovePolicy(params...) -} - -// RemoveFilteredPolicy removes an authorization rule from the current policy, field filters can be specified. -func (e *SyncedEnforcer) RemoveFilteredPolicy(fieldIndex int, fieldValues ...string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.RemoveFilteredPolicy(fieldIndex, fieldValues...) -} - -// HasGroupingPolicy determines whether a role inheritance rule exists. -func (e *SyncedEnforcer) HasGroupingPolicy(params ...interface{}) bool { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.HasGroupingPolicy(params...) -} - -// AddGroupingPolicy adds a role inheritance rule to the current policy. -// If the rule already exists, the function returns false and the rule will not be added. -// Otherwise the function returns true by adding the new rule. -func (e *SyncedEnforcer) AddGroupingPolicy(params ...interface{}) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.AddGroupingPolicy(params...) -} - -// RemoveGroupingPolicy removes a role inheritance rule from the current policy. -func (e *SyncedEnforcer) RemoveGroupingPolicy(params ...interface{}) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.RemoveGroupingPolicy(params...) -} - -// RemoveFilteredGroupingPolicy removes a role inheritance rule from the current policy, field filters can be specified. -func (e *SyncedEnforcer) RemoveFilteredGroupingPolicy(fieldIndex int, fieldValues ...string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.RemoveFilteredGroupingPolicy(fieldIndex, fieldValues...) -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/enforcer_synced_safe.go b/src/goadmin/vendor/github.com/casbin/casbin/enforcer_synced_safe.go deleted file mode 100644 index d61f4b7c..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/enforcer_synced_safe.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -// NewSyncedEnforcerSafe creates a synchronized enforcer via file or DB. -func NewSyncedEnforcerSafe(params ...interface{}) (enforcer *SyncedEnforcer, err error) { - e := &SyncedEnforcer{} - e.Enforcer, err = NewEnforcerSafe(params...) - - if err != nil { - return nil, err - } - - e.autoLoad = false - return e, nil -} - -// LoadModelSafe calls LoadModel in a safe way, returns error instead of causing panic. -func (e *SyncedEnforcer) LoadModelSafe() (err error) { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.LoadModelSafe() -} - -// EnforceSafe calls Enforce in a safe way, returns error instead of causing panic. -func (e *SyncedEnforcer) EnforceSafe(rvals ...interface{}) (result bool, err error) { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.EnforceSafe(rvals...) -} - -// AddPolicySafe calls AddPolicy in a safe way, returns error instead of causing panic. -func (e *SyncedEnforcer) AddPolicySafe(params ...interface{}) (result bool, err error) { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.AddPolicySafe(params...) -} - -// RemovePolicySafe calls RemovePolicy in a safe way, returns error instead of causing panic. -func (e *SyncedEnforcer) RemovePolicySafe(params ...interface{}) (result bool, err error) { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.RemovePolicySafe(params...) -} - -// RemoveFilteredPolicySafe calls RemoveFilteredPolicy in a safe way, returns error instead of causing panic. -func (e *SyncedEnforcer) RemoveFilteredPolicySafe(fieldIndex int, fieldValues ...string) (result bool, err error) { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.RemoveFilteredPolicySafe(fieldIndex, fieldValues...) -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/errors/rbac_errors.go b/src/goadmin/vendor/github.com/casbin/casbin/errors/rbac_errors.go deleted file mode 100644 index 68b1450c..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/errors/rbac_errors.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2018 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package errors - -import "errors" - -// Global errors for rbac defined here -var ( - ERR_NAME_NOT_FOUND = errors.New("error: name does not exist") - ERR_DOMAIN_PARAMETER = errors.New("error: domain should be 1 parameter") - ERR_NAMES12_NOT_FOUND = errors.New("error: name1 or name2 does not exist") -) diff --git a/src/goadmin/vendor/github.com/casbin/casbin/go.mod b/src/goadmin/vendor/github.com/casbin/casbin/go.mod deleted file mode 100644 index 289d866d..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module github.com/casbin/casbin - -require github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible diff --git a/src/goadmin/vendor/github.com/casbin/casbin/go.sum b/src/goadmin/vendor/github.com/casbin/casbin/go.sum deleted file mode 100644 index d1c7c352..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= diff --git a/src/goadmin/vendor/github.com/casbin/casbin/internal_api.go b/src/goadmin/vendor/github.com/casbin/casbin/internal_api.go deleted file mode 100644 index 6e6acead..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/internal_api.go +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -const ( - notImplemented = "not implemented" -) - -// addPolicy adds a rule to the current policy. -func (e *Enforcer) addPolicy(sec string, ptype string, rule []string) bool { - ruleAdded := e.model.AddPolicy(sec, ptype, rule) - if !ruleAdded { - return ruleAdded - } - - if e.adapter != nil && e.autoSave { - if err := e.adapter.AddPolicy(sec, ptype, rule); err != nil { - if err.Error() != notImplemented { - panic(err) - } - } - if e.watcher != nil { - // error intentionally ignored - e.watcher.Update() - } - } - - return ruleAdded -} - -// removePolicy removes a rule from the current policy. -func (e *Enforcer) removePolicy(sec string, ptype string, rule []string) bool { - ruleRemoved := e.model.RemovePolicy(sec, ptype, rule) - if !ruleRemoved { - return ruleRemoved - } - - if e.adapter != nil && e.autoSave { - if err := e.adapter.RemovePolicy(sec, ptype, rule); err != nil { - if err.Error() != notImplemented { - panic(err) - } - } - if e.watcher != nil { - // error intentionally ignored - e.watcher.Update() - } - } - - return ruleRemoved -} - -// removeFilteredPolicy removes rules based on field filters from the current policy. -func (e *Enforcer) removeFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) bool { - ruleRemoved := e.model.RemoveFilteredPolicy(sec, ptype, fieldIndex, fieldValues...) - if !ruleRemoved { - return ruleRemoved - } - - if e.adapter != nil && e.autoSave { - if err := e.adapter.RemoveFilteredPolicy(sec, ptype, fieldIndex, fieldValues...); err != nil { - if err.Error() != notImplemented { - panic(err) - } - } - if e.watcher != nil { - // error intentionally ignored - e.watcher.Update() - } - } - - return ruleRemoved -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/log/default_logger.go b/src/goadmin/vendor/github.com/casbin/casbin/log/default_logger.go deleted file mode 100644 index 74a04228..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/log/default_logger.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2018 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package log - -import "log" - -// DefaultLogger is the implementation for a Logger using golang log. -type DefaultLogger struct { - enable bool -} - -func (l *DefaultLogger) EnableLog(enable bool) { - l.enable = enable -} - -func (l *DefaultLogger) IsEnabled() bool { - return l.enable -} - -func (l *DefaultLogger) Print(v ...interface{}) { - if l.enable { - log.Print(v...) - } -} - -func (l *DefaultLogger) Printf(format string, v ...interface{}) { - if l.enable { - log.Printf(format, v...) - } -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/log/log_util.go b/src/goadmin/vendor/github.com/casbin/casbin/log/log_util.go deleted file mode 100644 index ef4b8165..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/log/log_util.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package log - -var logger Logger = &DefaultLogger{} - -// SetLogger sets the current logger. -func SetLogger(l Logger) { - logger = l -} - -// GetLogger returns the current logger. -func GetLogger() Logger { - return logger -} - -// LogPrint prints the log. -func LogPrint(v ...interface{}) { - logger.Print(v...) -} - -// LogPrintf prints the log with the format. -func LogPrintf(format string, v ...interface{}) { - logger.Printf(format, v...) -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/log/logger.go b/src/goadmin/vendor/github.com/casbin/casbin/log/logger.go deleted file mode 100644 index e3aadd1a..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/log/logger.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2018 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package log - -// Logger is the logging interface implementation. -type Logger interface { - //EnableLog controls whether print the message. - EnableLog(bool) - - //IsEnabled returns if logger is enabled. - IsEnabled() bool - - //Print formats using the default formats for its operands and logs the message. - Print(...interface{}) - - //Printf formats according to a format specifier and logs the message. - Printf(string, ...interface{}) -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/management_api.go b/src/goadmin/vendor/github.com/casbin/casbin/management_api.go deleted file mode 100644 index 355e17a7..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/management_api.go +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -// GetAllSubjects gets the list of subjects that show up in the current policy. -func (e *Enforcer) GetAllSubjects() []string { - return e.GetAllNamedSubjects("p") -} - -// GetAllNamedSubjects gets the list of subjects that show up in the current named policy. -func (e *Enforcer) GetAllNamedSubjects(ptype string) []string { - return e.model.GetValuesForFieldInPolicy("p", ptype, 0) -} - -// GetAllObjects gets the list of objects that show up in the current policy. -func (e *Enforcer) GetAllObjects() []string { - return e.GetAllNamedObjects("p") -} - -// GetAllNamedObjects gets the list of objects that show up in the current named policy. -func (e *Enforcer) GetAllNamedObjects(ptype string) []string { - return e.model.GetValuesForFieldInPolicy("p", ptype, 1) -} - -// GetAllActions gets the list of actions that show up in the current policy. -func (e *Enforcer) GetAllActions() []string { - return e.GetAllNamedActions("p") -} - -// GetAllNamedActions gets the list of actions that show up in the current named policy. -func (e *Enforcer) GetAllNamedActions(ptype string) []string { - return e.model.GetValuesForFieldInPolicy("p", ptype, 2) -} - -// GetAllRoles gets the list of roles that show up in the current policy. -func (e *Enforcer) GetAllRoles() []string { - return e.GetAllNamedRoles("g") -} - -// GetAllNamedRoles gets the list of roles that show up in the current named policy. -func (e *Enforcer) GetAllNamedRoles(ptype string) []string { - return e.model.GetValuesForFieldInPolicy("g", ptype, 1) -} - -// GetPolicy gets all the authorization rules in the policy. -func (e *Enforcer) GetPolicy() [][]string { - return e.GetNamedPolicy("p") -} - -// GetFilteredPolicy gets all the authorization rules in the policy, field filters can be specified. -func (e *Enforcer) GetFilteredPolicy(fieldIndex int, fieldValues ...string) [][]string { - return e.GetFilteredNamedPolicy("p", fieldIndex, fieldValues...) -} - -// GetNamedPolicy gets all the authorization rules in the named policy. -func (e *Enforcer) GetNamedPolicy(ptype string) [][]string { - return e.model.GetPolicy("p", ptype) -} - -// GetFilteredNamedPolicy gets all the authorization rules in the named policy, field filters can be specified. -func (e *Enforcer) GetFilteredNamedPolicy(ptype string, fieldIndex int, fieldValues ...string) [][]string { - return e.model.GetFilteredPolicy("p", ptype, fieldIndex, fieldValues...) -} - -// GetGroupingPolicy gets all the role inheritance rules in the policy. -func (e *Enforcer) GetGroupingPolicy() [][]string { - return e.GetNamedGroupingPolicy("g") -} - -// GetFilteredGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified. -func (e *Enforcer) GetFilteredGroupingPolicy(fieldIndex int, fieldValues ...string) [][]string { - return e.GetFilteredNamedGroupingPolicy("g", fieldIndex, fieldValues...) -} - -// GetNamedGroupingPolicy gets all the role inheritance rules in the policy. -func (e *Enforcer) GetNamedGroupingPolicy(ptype string) [][]string { - return e.model.GetPolicy("g", ptype) -} - -// GetFilteredNamedGroupingPolicy gets all the role inheritance rules in the policy, field filters can be specified. -func (e *Enforcer) GetFilteredNamedGroupingPolicy(ptype string, fieldIndex int, fieldValues ...string) [][]string { - return e.model.GetFilteredPolicy("g", ptype, fieldIndex, fieldValues...) -} - -// HasPolicy determines whether an authorization rule exists. -func (e *Enforcer) HasPolicy(params ...interface{}) bool { - return e.HasNamedPolicy("p", params...) -} - -// HasNamedPolicy determines whether a named authorization rule exists. -func (e *Enforcer) HasNamedPolicy(ptype string, params ...interface{}) bool { - if strSlice, ok := params[0].([]string); len(params) == 1 && ok { - return e.model.HasPolicy("p", ptype, strSlice) - } - - policy := make([]string, 0) - for _, param := range params { - policy = append(policy, param.(string)) - } - - return e.model.HasPolicy("p", ptype, policy) -} - -// AddPolicy adds an authorization rule to the current policy. -// If the rule already exists, the function returns false and the rule will not be added. -// Otherwise the function returns true by adding the new rule. -func (e *Enforcer) AddPolicy(params ...interface{}) bool { - return e.AddNamedPolicy("p", params...) -} - -// AddNamedPolicy adds an authorization rule to the current named policy. -// If the rule already exists, the function returns false and the rule will not be added. -// Otherwise the function returns true by adding the new rule. -func (e *Enforcer) AddNamedPolicy(ptype string, params ...interface{}) bool { - var ruleAdded bool - if strSlice, ok := params[0].([]string); len(params) == 1 && ok { - ruleAdded = e.addPolicy("p", ptype, strSlice) - } else { - policy := make([]string, 0) - for _, param := range params { - policy = append(policy, param.(string)) - } - - ruleAdded = e.addPolicy("p", ptype, policy) - } - - return ruleAdded -} - -// RemovePolicy removes an authorization rule from the current policy. -func (e *Enforcer) RemovePolicy(params ...interface{}) bool { - return e.RemoveNamedPolicy("p", params...) -} - -// RemoveFilteredPolicy removes an authorization rule from the current policy, field filters can be specified. -func (e *Enforcer) RemoveFilteredPolicy(fieldIndex int, fieldValues ...string) bool { - return e.RemoveFilteredNamedPolicy("p", fieldIndex, fieldValues...) -} - -// RemoveNamedPolicy removes an authorization rule from the current named policy. -func (e *Enforcer) RemoveNamedPolicy(ptype string, params ...interface{}) bool { - var ruleRemoved bool - if strSlice, ok := params[0].([]string); len(params) == 1 && ok { - ruleRemoved = e.removePolicy("p", ptype, strSlice) - } else { - policy := make([]string, 0) - for _, param := range params { - policy = append(policy, param.(string)) - } - - ruleRemoved = e.removePolicy("p", ptype, policy) - } - - return ruleRemoved -} - -// RemoveFilteredNamedPolicy removes an authorization rule from the current named policy, field filters can be specified. -func (e *Enforcer) RemoveFilteredNamedPolicy(ptype string, fieldIndex int, fieldValues ...string) bool { - return e.removeFilteredPolicy("p", ptype, fieldIndex, fieldValues...) -} - -// HasGroupingPolicy determines whether a role inheritance rule exists. -func (e *Enforcer) HasGroupingPolicy(params ...interface{}) bool { - return e.HasNamedGroupingPolicy("g", params...) -} - -// HasNamedGroupingPolicy determines whether a named role inheritance rule exists. -func (e *Enforcer) HasNamedGroupingPolicy(ptype string, params ...interface{}) bool { - if strSlice, ok := params[0].([]string); len(params) == 1 && ok { - return e.model.HasPolicy("g", ptype, strSlice) - } - - policy := make([]string, 0) - for _, param := range params { - policy = append(policy, param.(string)) - } - - return e.model.HasPolicy("g", ptype, policy) -} - -// AddGroupingPolicy adds a role inheritance rule to the current policy. -// If the rule already exists, the function returns false and the rule will not be added. -// Otherwise the function returns true by adding the new rule. -func (e *Enforcer) AddGroupingPolicy(params ...interface{}) bool { - return e.AddNamedGroupingPolicy("g", params...) -} - -// AddNamedGroupingPolicy adds a named role inheritance rule to the current policy. -// If the rule already exists, the function returns false and the rule will not be added. -// Otherwise the function returns true by adding the new rule. -func (e *Enforcer) AddNamedGroupingPolicy(ptype string, params ...interface{}) bool { - var ruleAdded bool - if strSlice, ok := params[0].([]string); len(params) == 1 && ok { - ruleAdded = e.addPolicy("g", ptype, strSlice) - } else { - policy := make([]string, 0) - for _, param := range params { - policy = append(policy, param.(string)) - } - - ruleAdded = e.addPolicy("g", ptype, policy) - } - - if e.autoBuildRoleLinks { - e.BuildRoleLinks() - } - return ruleAdded -} - -// RemoveGroupingPolicy removes a role inheritance rule from the current policy. -func (e *Enforcer) RemoveGroupingPolicy(params ...interface{}) bool { - return e.RemoveNamedGroupingPolicy("g", params...) -} - -// RemoveFilteredGroupingPolicy removes a role inheritance rule from the current policy, field filters can be specified. -func (e *Enforcer) RemoveFilteredGroupingPolicy(fieldIndex int, fieldValues ...string) bool { - return e.RemoveFilteredNamedGroupingPolicy("g", fieldIndex, fieldValues...) -} - -// RemoveNamedGroupingPolicy removes a role inheritance rule from the current named policy. -func (e *Enforcer) RemoveNamedGroupingPolicy(ptype string, params ...interface{}) bool { - var ruleRemoved bool - if strSlice, ok := params[0].([]string); len(params) == 1 && ok { - ruleRemoved = e.removePolicy("g", ptype, strSlice) - } else { - policy := make([]string, 0) - for _, param := range params { - policy = append(policy, param.(string)) - } - - ruleRemoved = e.removePolicy("g", ptype, policy) - } - - if e.autoBuildRoleLinks { - e.BuildRoleLinks() - } - return ruleRemoved -} - -// RemoveFilteredNamedGroupingPolicy removes a role inheritance rule from the current named policy, field filters can be specified. -func (e *Enforcer) RemoveFilteredNamedGroupingPolicy(ptype string, fieldIndex int, fieldValues ...string) bool { - ruleRemoved := e.removeFilteredPolicy("g", ptype, fieldIndex, fieldValues...) - - if e.autoBuildRoleLinks { - e.BuildRoleLinks() - } - return ruleRemoved -} - -// AddFunction adds a customized function. -func (e *Enforcer) AddFunction(name string, function func(args ...interface{}) (interface{}, error)) { - e.fm.AddFunction(name, function) -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/model/assertion.go b/src/goadmin/vendor/github.com/casbin/casbin/model/assertion.go deleted file mode 100644 index 0042ab1a..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/model/assertion.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "errors" - "strings" - - "github.com/casbin/casbin/log" - "github.com/casbin/casbin/rbac" -) - -// Assertion represents an expression in a section of the model. -// For example: r = sub, obj, act -type Assertion struct { - Key string - Value string - Tokens []string - Policy [][]string - RM rbac.RoleManager -} - -func (ast *Assertion) buildRoleLinks(rm rbac.RoleManager) { - ast.RM = rm - count := strings.Count(ast.Value, "_") - for _, rule := range ast.Policy { - if count < 2 { - panic(errors.New("the number of \"_\" in role definition should be at least 2")) - } - if len(rule) < count { - panic(errors.New("grouping policy elements do not meet role definition")) - } - - if count == 2 { - // error intentionally ignored - ast.RM.AddLink(rule[0], rule[1]) - } else if count == 3 { - // error intentionally ignored - ast.RM.AddLink(rule[0], rule[1], rule[2]) - } else if count == 4 { - // error intentionally ignored - ast.RM.AddLink(rule[0], rule[1], rule[2], rule[3]) - } - } - - log.LogPrint("Role links for: " + ast.Key) - ast.RM.PrintRoles() -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/model/function.go b/src/goadmin/vendor/github.com/casbin/casbin/model/function.go deleted file mode 100644 index 5c81d180..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/model/function.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import "github.com/casbin/casbin/util" - -// FunctionMap represents the collection of Function. -type FunctionMap map[string]func(args ...interface{}) (interface{}, error) - -// Function represents a function that is used in the matchers, used to get attributes in ABAC. -type Function func(args ...interface{}) (interface{}, error) - -// AddFunction adds an expression function. -func (fm FunctionMap) AddFunction(name string, function Function) { - fm[name] = function -} - -// LoadFunctionMap loads an initial function map. -func LoadFunctionMap() FunctionMap { - fm := make(FunctionMap) - - fm.AddFunction("keyMatch", util.KeyMatchFunc) - fm.AddFunction("keyMatch2", util.KeyMatch2Func) - fm.AddFunction("regexMatch", util.RegexMatchFunc) - fm.AddFunction("ipMatch", util.IPMatchFunc) - - return fm -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/model/model.go b/src/goadmin/vendor/github.com/casbin/casbin/model/model.go deleted file mode 100644 index 91de1279..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/model/model.go +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "strconv" - "strings" - - "github.com/casbin/casbin/config" - "github.com/casbin/casbin/log" - "github.com/casbin/casbin/util" -) - -// Model represents the whole access control model. -type Model map[string]AssertionMap - -// AssertionMap is the collection of assertions, can be "r", "p", "g", "e", "m". -type AssertionMap map[string]*Assertion - -var sectionNameMap = map[string]string{ - "r": "request_definition", - "p": "policy_definition", - "g": "role_definition", - "e": "policy_effect", - "m": "matchers", -} - -func loadAssertion(model Model, cfg config.ConfigInterface, sec string, key string) bool { - value := cfg.String(sectionNameMap[sec] + "::" + key) - return model.AddDef(sec, key, value) -} - -// AddDef adds an assertion to the model. -func (model Model) AddDef(sec string, key string, value string) bool { - ast := Assertion{} - ast.Key = key - ast.Value = value - - if ast.Value == "" { - return false - } - - if sec == "r" || sec == "p" { - ast.Tokens = strings.Split(ast.Value, ", ") - for i := range ast.Tokens { - ast.Tokens[i] = key + "_" + ast.Tokens[i] - } - } else { - ast.Value = util.RemoveComments(util.EscapeAssertion(ast.Value)) - } - - _, ok := model[sec] - if !ok { - model[sec] = make(AssertionMap) - } - - model[sec][key] = &ast - return true -} - -func getKeySuffix(i int) string { - if i == 1 { - return "" - } - - return strconv.Itoa(i) -} - -func loadSection(model Model, cfg config.ConfigInterface, sec string) { - i := 1 - for { - if !loadAssertion(model, cfg, sec, sec+getKeySuffix(i)) { - break - } else { - i++ - } - } -} - -// LoadModel loads the model from model CONF file. -func (model Model) LoadModel(path string) { - cfg, err := config.NewConfig(path) - if err != nil { - panic(err) - } - - loadSection(model, cfg, "r") - loadSection(model, cfg, "p") - loadSection(model, cfg, "e") - loadSection(model, cfg, "m") - - loadSection(model, cfg, "g") -} - -// LoadModelFromText loads the model from the text. -func (model Model) LoadModelFromText(text string) { - cfg, err := config.NewConfigFromText(text) - if err != nil { - panic(err) - } - - loadSection(model, cfg, "r") - loadSection(model, cfg, "p") - loadSection(model, cfg, "e") - loadSection(model, cfg, "m") - - loadSection(model, cfg, "g") -} - -// PrintModel prints the model to the log. -func (model Model) PrintModel() { - log.LogPrint("Model:") - for k, v := range model { - for i, j := range v { - log.LogPrintf("%s.%s: %s", k, i, j.Value) - } - } -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/model/policy.go b/src/goadmin/vendor/github.com/casbin/casbin/model/policy.go deleted file mode 100644 index fd564183..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/model/policy.go +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package model - -import ( - "github.com/casbin/casbin/log" - "github.com/casbin/casbin/rbac" - "github.com/casbin/casbin/util" -) - -// BuildRoleLinks initializes the roles in RBAC. -func (model Model) BuildRoleLinks(rm rbac.RoleManager) { - for _, ast := range model["g"] { - ast.buildRoleLinks(rm) - } -} - -// PrintPolicy prints the policy to log. -func (model Model) PrintPolicy() { - log.LogPrint("Policy:") - for key, ast := range model["p"] { - log.LogPrint(key, ": ", ast.Value, ": ", ast.Policy) - } - - for key, ast := range model["g"] { - log.LogPrint(key, ": ", ast.Value, ": ", ast.Policy) - } -} - -// ClearPolicy clears all current policy. -func (model Model) ClearPolicy() { - for _, ast := range model["p"] { - ast.Policy = nil - } - - for _, ast := range model["g"] { - ast.Policy = nil - } -} - -// GetPolicy gets all rules in a policy. -func (model Model) GetPolicy(sec string, ptype string) [][]string { - return model[sec][ptype].Policy -} - -// GetFilteredPolicy gets rules based on field filters from a policy. -func (model Model) GetFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) [][]string { - res := [][]string{} - - for _, rule := range model[sec][ptype].Policy { - matched := true - for i, fieldValue := range fieldValues { - if fieldValue != "" && rule[fieldIndex+i] != fieldValue { - matched = false - break - } - } - - if matched { - res = append(res, rule) - } - } - - return res -} - -// HasPolicy determines whether a model has the specified policy rule. -func (model Model) HasPolicy(sec string, ptype string, rule []string) bool { - for _, r := range model[sec][ptype].Policy { - if util.ArrayEquals(rule, r) { - return true - } - } - - return false -} - -// AddPolicy adds a policy rule to the model. -func (model Model) AddPolicy(sec string, ptype string, rule []string) bool { - if !model.HasPolicy(sec, ptype, rule) { - model[sec][ptype].Policy = append(model[sec][ptype].Policy, rule) - return true - } - return false -} - -// RemovePolicy removes a policy rule from the model. -func (model Model) RemovePolicy(sec string, ptype string, rule []string) bool { - for i, r := range model[sec][ptype].Policy { - if util.ArrayEquals(rule, r) { - model[sec][ptype].Policy = append(model[sec][ptype].Policy[:i], model[sec][ptype].Policy[i+1:]...) - return true - } - } - - return false -} - -// RemoveFilteredPolicy removes policy rules based on field filters from the model. -func (model Model) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) bool { - tmp := [][]string{} - res := false - for _, rule := range model[sec][ptype].Policy { - matched := true - for i, fieldValue := range fieldValues { - if fieldValue != "" && rule[fieldIndex+i] != fieldValue { - matched = false - break - } - } - - if matched { - res = true - } else { - tmp = append(tmp, rule) - } - } - - model[sec][ptype].Policy = tmp - return res -} - -// GetValuesForFieldInPolicy gets all values for a field for all rules in a policy, duplicated values are removed. -func (model Model) GetValuesForFieldInPolicy(sec string, ptype string, fieldIndex int) []string { - values := []string{} - - for _, rule := range model[sec][ptype].Policy { - values = append(values, rule[fieldIndex]) - } - - util.ArrayRemoveDuplicates(&values) - - return values -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/persist/adapter.go b/src/goadmin/vendor/github.com/casbin/casbin/persist/adapter.go deleted file mode 100644 index 7a5271b6..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/persist/adapter.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package persist - -import ( - "strings" - - "github.com/casbin/casbin/model" -) - -// LoadPolicyLine loads a text line as a policy rule to model. -func LoadPolicyLine(line string, model model.Model) { - if line == "" || strings.HasPrefix(line, "#") { - return - } - - tokens := strings.Split(line, ",") - for i := 0; i < len(tokens); i++ { - tokens[i] = strings.TrimSpace(tokens[i]) - } - - key := tokens[0] - sec := key[:1] - model[sec][key].Policy = append(model[sec][key].Policy, tokens[1:]) -} - -// Adapter is the interface for Casbin adapters. -type Adapter interface { - // LoadPolicy loads all policy rules from the storage. - LoadPolicy(model model.Model) error - // SavePolicy saves all policy rules to the storage. - SavePolicy(model model.Model) error - - // AddPolicy adds a policy rule to the storage. - // This is part of the Auto-Save feature. - AddPolicy(sec string, ptype string, rule []string) error - // RemovePolicy removes a policy rule from the storage. - // This is part of the Auto-Save feature. - RemovePolicy(sec string, ptype string, rule []string) error - // RemoveFilteredPolicy removes policy rules that match the filter from the storage. - // This is part of the Auto-Save feature. - RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/persist/adapter_filtered.go b/src/goadmin/vendor/github.com/casbin/casbin/persist/adapter_filtered.go deleted file mode 100644 index fab51e72..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/persist/adapter_filtered.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package persist - -import ( - "github.com/casbin/casbin/model" -) - -// FilteredAdapter is the interface for Casbin adapters supporting filtered policies. -type FilteredAdapter interface { - Adapter - - // LoadFilteredPolicy loads only policy rules that match the filter. - LoadFilteredPolicy(model model.Model, filter interface{}) error - // IsFiltered returns true if the loaded policy has been filtered. - IsFiltered() bool -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter.go b/src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter.go deleted file mode 100644 index 91bf7a9a..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter.go +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package fileadapter - -import ( - "bufio" - "bytes" - "errors" - "os" - "strings" - - "github.com/casbin/casbin/model" - "github.com/casbin/casbin/persist" - "github.com/casbin/casbin/util" -) - -// Adapter is the file adapter for Casbin. -// It can load policy from file or save policy to file. -type Adapter struct { - filePath string -} - -// NewAdapter is the constructor for Adapter. -func NewAdapter(filePath string) *Adapter { - return &Adapter{filePath: filePath} -} - -// LoadPolicy loads all policy rules from the storage. -func (a *Adapter) LoadPolicy(model model.Model) error { - if a.filePath == "" { - return errors.New("invalid file path, file path cannot be empty") - } - - return a.loadPolicyFile(model, persist.LoadPolicyLine) -} - -// SavePolicy saves all policy rules to the storage. -func (a *Adapter) SavePolicy(model model.Model) error { - if a.filePath == "" { - return errors.New("invalid file path, file path cannot be empty") - } - - var tmp bytes.Buffer - - for ptype, ast := range model["p"] { - for _, rule := range ast.Policy { - tmp.WriteString(ptype + ", ") - tmp.WriteString(util.ArrayToString(rule)) - tmp.WriteString("\n") - } - } - - for ptype, ast := range model["g"] { - for _, rule := range ast.Policy { - tmp.WriteString(ptype + ", ") - tmp.WriteString(util.ArrayToString(rule)) - tmp.WriteString("\n") - } - } - - return a.savePolicyFile(strings.TrimRight(tmp.String(), "\n")) -} - -func (a *Adapter) loadPolicyFile(model model.Model, handler func(string, model.Model)) error { - f, err := os.Open(a.filePath) - if err != nil { - return err - } - defer f.Close() - - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - handler(line, model) - } - return scanner.Err() -} - -func (a *Adapter) savePolicyFile(text string) error { - f, err := os.Create(a.filePath) - if err != nil { - return err - } - w := bufio.NewWriter(f) - // error intentionally ignored - w.WriteString(text) - w.Flush() - f.Close() - return nil -} - -// AddPolicy adds a policy rule to the storage. -func (a *Adapter) AddPolicy(sec string, ptype string, rule []string) error { - return errors.New("not implemented") -} - -// RemovePolicy removes a policy rule from the storage. -func (a *Adapter) RemovePolicy(sec string, ptype string, rule []string) error { - return errors.New("not implemented") -} - -// RemoveFilteredPolicy removes policy rules that match the filter from the storage. -func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error { - return errors.New("not implemented") -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter_filtered.go b/src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter_filtered.go deleted file mode 100644 index 0aa63604..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter_filtered.go +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package fileadapter - -import ( - "bufio" - "errors" - "os" - "strings" - - "github.com/casbin/casbin/model" - "github.com/casbin/casbin/persist" -) - -// FilteredAdapter is the filtered file adapter for Casbin. It can load policy -// from file or save policy to file and supports loading of filtered policies. -type FilteredAdapter struct { - *Adapter - filtered bool -} - -// Filter defines the filtering rules for a FilteredAdapter's policy. Empty values -// are ignored, but all others must match the filter. -type Filter struct { - P []string - G []string -} - -// NewFilteredAdapter is the constructor for FilteredAdapter. -func NewFilteredAdapter(filePath string) *FilteredAdapter { - a := FilteredAdapter{} - a.filtered = true - a.Adapter = NewAdapter(filePath) - return &a -} - -// LoadPolicy loads all policy rules from the storage. -func (a *FilteredAdapter) LoadPolicy(model model.Model) error { - a.filtered = false - return a.Adapter.LoadPolicy(model) -} - -// LoadFilteredPolicy loads only policy rules that match the filter. -func (a *FilteredAdapter) LoadFilteredPolicy(model model.Model, filter interface{}) error { - if filter == nil { - return a.LoadPolicy(model) - } - if a.filePath == "" { - return errors.New("invalid file path, file path cannot be empty") - } - - filterValue, ok := filter.(*Filter) - if !ok { - return errors.New("invalid filter type") - } - err := a.loadFilteredPolicyFile(model, filterValue, persist.LoadPolicyLine) - if err == nil { - a.filtered = true - } - return err -} - -func (a *FilteredAdapter) loadFilteredPolicyFile(model model.Model, filter *Filter, handler func(string, model.Model)) error { - f, err := os.Open(a.filePath) - if err != nil { - return err - } - defer f.Close() - - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - - if filterLine(line, filter) { - continue - } - - handler(line, model) - } - return scanner.Err() -} - -// IsFiltered returns true if the loaded policy has been filtered. -func (a *FilteredAdapter) IsFiltered() bool { - return a.filtered -} - -// SavePolicy saves all policy rules to the storage. -func (a *FilteredAdapter) SavePolicy(model model.Model) error { - if a.filtered { - return errors.New("cannot save a filtered policy") - } - return a.Adapter.SavePolicy(model) -} - -func filterLine(line string, filter *Filter) bool { - if filter == nil { - return false - } - p := strings.Split(line, ",") - if len(p) == 0 { - return true - } - var filterSlice []string - switch strings.TrimSpace(p[0]) { - case "p": - filterSlice = filter.P - case "g": - filterSlice = filter.G - } - return filterWords(p, filterSlice) -} - -func filterWords(line []string, filter []string) bool { - if len(line) < len(filter)+1 { - return true - } - var skipLine bool - for i, v := range filter { - if len(v) > 0 && strings.TrimSpace(v) != strings.TrimSpace(line[i+1]) { - skipLine = true - break - } - } - return skipLine -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter_mock.go b/src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter_mock.go deleted file mode 100644 index 0d7f83a7..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/persist/file-adapter/adapter_mock.go +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package fileadapter - -import ( - "bufio" - "errors" - "io" - "os" - "strings" - - "github.com/casbin/casbin/model" - "github.com/casbin/casbin/persist" -) - -// AdapterMock is the file adapter for Casbin. -// It can load policy from file or save policy to file. -type AdapterMock struct { - filePath string - errorValue string -} - -// NewAdapterMock is the constructor for AdapterMock. -func NewAdapterMock(filePath string) *AdapterMock { - a := AdapterMock{} - a.filePath = filePath - return &a -} - -// LoadPolicy loads all policy rules from the storage. -func (a *AdapterMock) LoadPolicy(model model.Model) error { - err := a.loadPolicyFile(model, persist.LoadPolicyLine) - return err -} - -// SavePolicy saves all policy rules to the storage. -func (a *AdapterMock) SavePolicy(model model.Model) error { - return nil -} - -func (a *AdapterMock) loadPolicyFile(model model.Model, handler func(string, model.Model)) error { - f, err := os.Open(a.filePath) - if err != nil { - return err - } - defer f.Close() - - buf := bufio.NewReader(f) - for { - line, err := buf.ReadString('\n') - line = strings.TrimSpace(line) - handler(line, model) - if err != nil { - if err == io.EOF { - return nil - } - } - } -} - -// SetMockErr sets string to be returned by of the mock during testing -func (a *AdapterMock) SetMockErr(errorToSet string) { - a.errorValue = errorToSet -} - -// GetMockErr returns a mock error or nil -func (a *AdapterMock) GetMockErr() error { - var returnError error - if a.errorValue != "" { - returnError = errors.New(a.errorValue) - } - return returnError -} - -// AddPolicy adds a policy rule to the storage. -func (a *AdapterMock) AddPolicy(sec string, ptype string, rule []string) error { - return a.GetMockErr() -} - -// RemovePolicy removes a policy rule from the storage. -func (a *AdapterMock) RemovePolicy(sec string, ptype string, rule []string) error { - return a.GetMockErr() -} - -// RemoveFilteredPolicy removes policy rules that match the filter from the storage. -func (a *AdapterMock) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error { - return a.GetMockErr() -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/persist/watcher.go b/src/goadmin/vendor/github.com/casbin/casbin/persist/watcher.go deleted file mode 100644 index 0d843606..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/persist/watcher.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package persist - -// Watcher is the interface for Casbin watchers. -type Watcher interface { - // SetUpdateCallback sets the callback function that the watcher will call - // when the policy in DB has been changed by other instances. - // A classic callback is Enforcer.LoadPolicy(). - SetUpdateCallback(func(string)) error - // Update calls the update callback of other instances to synchronize their policy. - // It is usually called after changing the policy in DB, like Enforcer.SavePolicy(), - // Enforcer.AddPolicy(), Enforcer.RemovePolicy(), etc. - Update() error - // Close stops and releases the watcher, the callback function will not be called any more. - Close() -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/rbac/default-role-manager/role_manager.go b/src/goadmin/vendor/github.com/casbin/casbin/rbac/default-role-manager/role_manager.go deleted file mode 100644 index d333cb63..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/rbac/default-role-manager/role_manager.go +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package defaultrolemanager - -import ( - "sync" - - "github.com/casbin/casbin/errors" - "github.com/casbin/casbin/log" - "github.com/casbin/casbin/rbac" -) - -type MatchingFunc func(arg1, arg2 string) bool - -// RoleManager provides a default implementation for the RoleManager interface -type RoleManager struct { - allRoles *sync.Map - maxHierarchyLevel int - hasPattern bool - matchingFunc MatchingFunc -} - -// NewRoleManager is the constructor for creating an instance of the -// default RoleManager implementation. -func NewRoleManager(maxHierarchyLevel int) rbac.RoleManager { - rm := RoleManager{} - rm.allRoles = &sync.Map{} - rm.maxHierarchyLevel = maxHierarchyLevel - rm.hasPattern = false - - return &rm -} - -func (rm *RoleManager) AddMatchingFunc(name string, fn MatchingFunc) { - rm.hasPattern = true - rm.matchingFunc = fn -} - -func (rm *RoleManager) hasRole(name string) bool { - var ok bool - if rm.hasPattern { - rm.allRoles.Range(func(key, value interface{}) bool { - if rm.matchingFunc(name, key.(string)) { - ok = true - } - return true - }) - } else { - _, ok = rm.allRoles.Load(name) - } - - return ok -} - -func (rm *RoleManager) createRole(name string) *Role { - if rm.hasPattern { - rm.allRoles.Range(func(key, value interface{}) bool { - if rm.matchingFunc(name, key.(string)) { - name = key.(string) - } - return true - }) - } - role, _ := rm.allRoles.LoadOrStore(name, newRole(name)) - return role.(*Role) -} - -// Clear clears all stored data and resets the role manager to the initial state. -func (rm *RoleManager) Clear() error { - rm.allRoles = &sync.Map{} - return nil -} - -// AddLink adds the inheritance link between role: name1 and role: name2. -// aka role: name1 inherits role: name2. -// domain is a prefix to the roles. -func (rm *RoleManager) AddLink(name1 string, name2 string, domain ...string) error { - if len(domain) == 1 { - name1 = domain[0] + "::" + name1 - name2 = domain[0] + "::" + name2 - } else if len(domain) > 1 { - return errors.ERR_DOMAIN_PARAMETER - } - - role1 := rm.createRole(name1) - role2 := rm.createRole(name2) - role1.addRole(role2) - return nil -} - -// DeleteLink deletes the inheritance link between role: name1 and role: name2. -// aka role: name1 does not inherit role: name2 any more. -// domain is a prefix to the roles. -func (rm *RoleManager) DeleteLink(name1 string, name2 string, domain ...string) error { - if len(domain) == 1 { - name1 = domain[0] + "::" + name1 - name2 = domain[0] + "::" + name2 - } else if len(domain) > 1 { - return errors.ERR_DOMAIN_PARAMETER - } - - if !rm.hasRole(name1) || !rm.hasRole(name2) { - return errors.ERR_NAMES12_NOT_FOUND - } - - role1 := rm.createRole(name1) - role2 := rm.createRole(name2) - role1.deleteRole(role2) - return nil -} - -// HasLink determines whether role: name1 inherits role: name2. -// domain is a prefix to the roles. -func (rm *RoleManager) HasLink(name1 string, name2 string, domain ...string) (bool, error) { - if len(domain) == 1 { - name1 = domain[0] + "::" + name1 - name2 = domain[0] + "::" + name2 - } else if len(domain) > 1 { - return false, errors.ERR_DOMAIN_PARAMETER - } - - if name1 == name2 { - return true, nil - } - - if !rm.hasRole(name1) || !rm.hasRole(name2) { - return false, nil - } - - role1 := rm.createRole(name1) - return role1.hasRole(name2, rm.maxHierarchyLevel), nil -} - -// GetRoles gets the roles that a subject inherits. -// domain is a prefix to the roles. -func (rm *RoleManager) GetRoles(name string, domain ...string) ([]string, error) { - if len(domain) == 1 { - name = domain[0] + "::" + name - } else if len(domain) > 1 { - return nil, errors.ERR_DOMAIN_PARAMETER - } - - if !rm.hasRole(name) { - return []string{}, nil - } - - roles := rm.createRole(name).getRoles() - if len(domain) == 1 { - for i := range roles { - roles[i] = roles[i][len(domain[0])+2:] - } - } - return roles, nil -} - -// GetUsers gets the users that inherits a subject. -// domain is an unreferenced parameter here, may be used in other implementations. -func (rm *RoleManager) GetUsers(name string, domain ...string) ([]string, error) { - if len(domain) == 1 { - name = domain[0] + "::" + name - } else if len(domain) > 1 { - return nil, errors.ERR_DOMAIN_PARAMETER - } - - if !rm.hasRole(name) { - return nil, errors.ERR_NAME_NOT_FOUND - } - - names := []string{} - rm.allRoles.Range(func(_, value interface{}) bool { - role := value.(*Role) - if role.hasDirectRole(name) { - names = append(names, role.name) - } - return true - }) - if len(domain) == 1 { - for i := range names { - names[i] = names[i][len(domain[0])+2:] - } - } - return names, nil -} - -// PrintRoles prints all the roles to log. -func (rm *RoleManager) PrintRoles() error { - line := "" - rm.allRoles.Range(func(_, value interface{}) bool { - if text := value.(*Role).toString(); text != "" { - if line == "" { - line = text - } else { - line += ", " + text - } - } - return true - }) - log.LogPrint(line) - return nil -} - -// Role represents the data structure for a role in RBAC. -type Role struct { - name string - roles []*Role -} - -func newRole(name string) *Role { - r := Role{} - r.name = name - return &r -} - -func (r *Role) addRole(role *Role) { - for _, rr := range r.roles { - if rr.name == role.name { - return - } - } - - r.roles = append(r.roles, role) -} - -func (r *Role) deleteRole(role *Role) { - for i, rr := range r.roles { - if rr.name == role.name { - r.roles = append(r.roles[:i], r.roles[i+1:]...) - return - } - } -} - -func (r *Role) hasRole(name string, hierarchyLevel int) bool { - if r.name == name { - return true - } - - if hierarchyLevel <= 0 { - return false - } - - for _, role := range r.roles { - if role.hasRole(name, hierarchyLevel-1) { - return true - } - } - return false -} - -func (r *Role) hasDirectRole(name string) bool { - for _, role := range r.roles { - if role.name == name { - return true - } - } - - return false -} - -func (r *Role) toString() string { - names := "" - if len(r.roles) == 0 { - return "" - } - for i, role := range r.roles { - if i == 0 { - names += role.name - } else { - names += ", " + role.name - } - } - - if len(r.roles) == 1 { - return r.name + " < " + names - } else { - return r.name + " < (" + names + ")" - } -} - -func (r *Role) getRoles() []string { - names := []string{} - for _, role := range r.roles { - names = append(names, role.name) - } - return names -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/rbac/role_manager.go b/src/goadmin/vendor/github.com/casbin/casbin/rbac/role_manager.go deleted file mode 100644 index b853bc93..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/rbac/role_manager.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package rbac - -// RoleManager provides interface to define the operations for managing roles. -type RoleManager interface { - // Clear clears all stored data and resets the role manager to the initial state. - Clear() error - // AddLink adds the inheritance link between two roles. role: name1 and role: name2. - // domain is a prefix to the roles (can be used for other purposes). - AddLink(name1 string, name2 string, domain ...string) error - // DeleteLink deletes the inheritance link between two roles. role: name1 and role: name2. - // domain is a prefix to the roles (can be used for other purposes). - DeleteLink(name1 string, name2 string, domain ...string) error - // HasLink determines whether a link exists between two roles. role: name1 inherits role: name2. - // domain is a prefix to the roles (can be used for other purposes). - HasLink(name1 string, name2 string, domain ...string) (bool, error) - // GetRoles gets the roles that a user inherits. - // domain is a prefix to the roles (can be used for other purposes). - GetRoles(name string, domain ...string) ([]string, error) - // GetUsers gets the users that inherits a role. - // domain is a prefix to the users (can be used for other purposes). - GetUsers(name string, domain ...string) ([]string, error) - // PrintRoles prints all the roles to log. - PrintRoles() error -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/rbac_api.go b/src/goadmin/vendor/github.com/casbin/casbin/rbac_api.go deleted file mode 100644 index 0364893b..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/rbac_api.go +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -import "github.com/casbin/casbin/util" - -// GetRolesForUser gets the roles that a user has. -func (e *Enforcer) GetRolesForUser(name string) ([]string, error) { - res, err := e.model["g"]["g"].RM.GetRoles(name) - return res, err -} - -// GetUsersForRole gets the users that has a role. -func (e *Enforcer) GetUsersForRole(name string) ([]string, error) { - res, err := e.model["g"]["g"].RM.GetUsers(name) - return res, err -} - -// HasRoleForUser determines whether a user has a role. -func (e *Enforcer) HasRoleForUser(name string, role string) (bool, error) { - roles, err := e.GetRolesForUser(name) - if err != nil { - return false, err - } - hasRole := false - for _, r := range roles { - if r == role { - hasRole = true - break - } - } - - return hasRole, nil -} - -// AddRoleForUser adds a role for a user. -// Returns false if the user already has the role (aka not affected). -func (e *Enforcer) AddRoleForUser(user string, role string) bool { - return e.AddGroupingPolicy(user, role) -} - -// DeleteRoleForUser deletes a role for a user. -// Returns false if the user does not have the role (aka not affected). -func (e *Enforcer) DeleteRoleForUser(user string, role string) bool { - return e.RemoveGroupingPolicy(user, role) -} - -// DeleteRolesForUser deletes all roles for a user. -// Returns false if the user does not have any roles (aka not affected). -func (e *Enforcer) DeleteRolesForUser(user string) bool { - return e.RemoveFilteredGroupingPolicy(0, user) -} - -// DeleteUser deletes a user. -// Returns false if the user does not exist (aka not affected). -func (e *Enforcer) DeleteUser(user string) bool { - return e.RemoveFilteredGroupingPolicy(0, user) -} - -// DeleteRole deletes a role. -func (e *Enforcer) DeleteRole(role string) { - e.RemoveFilteredGroupingPolicy(1, role) - e.RemoveFilteredPolicy(0, role) -} - -// DeletePermission deletes a permission. -// Returns false if the permission does not exist (aka not affected). -func (e *Enforcer) DeletePermission(permission ...string) bool { - return e.RemoveFilteredPolicy(1, permission...) -} - -// AddPermissionForUser adds a permission for a user or role. -// Returns false if the user or role already has the permission (aka not affected). -func (e *Enforcer) AddPermissionForUser(user string, permission ...string) bool { - return e.AddPolicy(util.JoinSlice(user, permission...)) -} - -// DeletePermissionForUser deletes a permission for a user or role. -// Returns false if the user or role does not have the permission (aka not affected). -func (e *Enforcer) DeletePermissionForUser(user string, permission ...string) bool { - return e.RemovePolicy(util.JoinSlice(user, permission...)) -} - -// DeletePermissionsForUser deletes permissions for a user or role. -// Returns false if the user or role does not have any permissions (aka not affected). -func (e *Enforcer) DeletePermissionsForUser(user string) bool { - return e.RemoveFilteredPolicy(0, user) -} - -// GetPermissionsForUser gets permissions for a user or role. -func (e *Enforcer) GetPermissionsForUser(user string) [][]string { - return e.GetFilteredPolicy(0, user) -} - -// HasPermissionForUser determines whether a user has a permission. -func (e *Enforcer) HasPermissionForUser(user string, permission ...string) bool { - return e.HasPolicy(util.JoinSlice(user, permission...)) -} - -// GetImplicitRolesForUser gets implicit roles that a user has. -// Compared to GetRolesForUser(), this function retrieves indirect roles besides direct roles. -// For example: -// g, alice, role:admin -// g, role:admin, role:user -// -// GetRolesForUser("alice") can only get: ["role:admin"]. -// But GetImplicitRolesForUser("alice") will get: ["role:admin", "role:user"]. -func (e *Enforcer) GetImplicitRolesForUser(name string, domain ...string) []string { - res := []string{} - roleSet := make(map[string]bool) - roleSet[name] = true - - q := make([]string, 0) - q = append(q, name) - - for len(q) > 0 { - name := q[0] - q = q[1:] - - roles, err := e.rm.GetRoles(name, domain...) - if err != nil { - panic(err) - } - for _, r := range roles { - if _, ok := roleSet[r]; !ok { - res = append(res, r) - q = append(q, r) - roleSet[r] = true - } - } - } - - return res -} - -// GetImplicitPermissionsForUser gets implicit permissions for a user or role. -// Compared to GetPermissionsForUser(), this function retrieves permissions for inherited roles. -// For example: -// p, admin, data1, read -// p, alice, data2, read -// g, alice, admin -// -// GetPermissionsForUser("alice") can only get: [["alice", "data2", "read"]]. -// But GetImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]]. -func (e *Enforcer) GetImplicitPermissionsForUser(user string, domain ...string) [][]string { - roles := e.GetImplicitRolesForUser(user, domain...) - roles = append([]string{user}, roles...) - - withDomain := false - if len(domain) == 1 { - withDomain = true - } else if len(domain) > 1 { - panic("error: domain should be 1 parameter") - } - - res := [][]string{} - permissions := [][]string{} - for _, role := range roles { - if withDomain { - permissions = e.GetPermissionsForUserInDomain(role, domain[0]) - } else { - permissions = e.GetPermissionsForUser(role) - } - res = append(res, permissions...) - } - - return res -} - -// GetImplicitUsersForPermission gets implicit users for a permission. -// For example: -// p, admin, data1, read -// p, bob, data1, read -// g, alice, admin -// -// GetImplicitUsersForPermission("data1", "read") will get: ["alice", "bob"]. -// Note: only users will be returned, roles (2nd arg in "g") will be excluded. -func (e *Enforcer) GetImplicitUsersForPermission(permission ...string) []string { - subjects := e.GetAllSubjects() - roles := e.GetAllRoles() - - users := util.SetSubtract(subjects, roles) - - res := []string{} - for _, user := range users { - req := util.JoinSliceAny(user, permission...) - if e.Enforce(req...) { - res = append(res, user) - } - } - - return res -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/rbac_api_synced.go b/src/goadmin/vendor/github.com/casbin/casbin/rbac_api_synced.go deleted file mode 100644 index c32a0731..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/rbac_api_synced.go +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -// GetRolesForUser gets the roles that a user has. -func (e *SyncedEnforcer) GetRolesForUser(name string) ([]string, error) { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetRolesForUser(name) -} - -// GetUsersForRole gets the users that has a role. -func (e *SyncedEnforcer) GetUsersForRole(name string) ([]string, error) { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetUsersForRole(name) -} - -// HasRoleForUser determines whether a user has a role. -func (e *SyncedEnforcer) HasRoleForUser(name string, role string) (bool, error) { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.HasRoleForUser(name, role) -} - -// AddRoleForUser adds a role for a user. -// Returns false if the user already has the role (aka not affected). -func (e *SyncedEnforcer) AddRoleForUser(user string, role string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.AddRoleForUser(user, role) -} - -// DeleteRoleForUser deletes a role for a user. -// Returns false if the user does not have the role (aka not affected). -func (e *SyncedEnforcer) DeleteRoleForUser(user string, role string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.DeleteRoleForUser(user, role) -} - -// DeleteRolesForUser deletes all roles for a user. -// Returns false if the user does not have any roles (aka not affected). -func (e *SyncedEnforcer) DeleteRolesForUser(user string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.DeleteRolesForUser(user) -} - -// DeleteUser deletes a user. -// Returns false if the user does not exist (aka not affected). -func (e *SyncedEnforcer) DeleteUser(user string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.DeleteUser(user) -} - -// DeleteRole deletes a role. -func (e *SyncedEnforcer) DeleteRole(role string) { - e.m.Lock() - defer e.m.Unlock() - e.Enforcer.DeleteRole(role) -} - -// DeletePermission deletes a permission. -// Returns false if the permission does not exist (aka not affected). -func (e *SyncedEnforcer) DeletePermission(permission ...string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.DeletePermission(permission...) -} - -// AddPermissionForUser adds a permission for a user or role. -// Returns false if the user or role already has the permission (aka not affected). -func (e *SyncedEnforcer) AddPermissionForUser(user string, permission ...string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.AddPermissionForUser(user, permission...) -} - -// DeletePermissionForUser deletes a permission for a user or role. -// Returns false if the user or role does not have the permission (aka not affected). -func (e *SyncedEnforcer) DeletePermissionForUser(user string, permission ...string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.DeletePermissionForUser(user, permission...) -} - -// DeletePermissionsForUser deletes permissions for a user or role. -// Returns false if the user or role does not have any permissions (aka not affected). -func (e *SyncedEnforcer) DeletePermissionsForUser(user string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.DeletePermissionsForUser(user) -} - -// GetPermissionsForUser gets permissions for a user or role. -func (e *SyncedEnforcer) GetPermissionsForUser(user string) [][]string { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.GetPermissionsForUser(user) -} - -// HasPermissionForUser determines whether a user has a permission. -func (e *SyncedEnforcer) HasPermissionForUser(user string, permission ...string) bool { - e.m.RLock() - defer e.m.RUnlock() - return e.Enforcer.HasPermissionForUser(user, permission...) -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/rbac_api_with_domains.go b/src/goadmin/vendor/github.com/casbin/casbin/rbac_api_with_domains.go deleted file mode 100644 index 9d81816e..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/rbac_api_with_domains.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -// GetUsersForRoleInDomain gets the users that has a role inside a domain. Add by Gordon -func (e *Enforcer) GetUsersForRoleInDomain(name string, domain string) []string { - res, _ := e.model["g"]["g"].RM.GetUsers(name, domain) - return res -} - -// GetRolesForUserInDomain gets the roles that a user has inside a domain. -func (e *Enforcer) GetRolesForUserInDomain(name string, domain string) []string { - res, _ := e.model["g"]["g"].RM.GetRoles(name, domain) - return res -} - -// GetPermissionsForUserInDomain gets permissions for a user or role inside a domain. -func (e *Enforcer) GetPermissionsForUserInDomain(user string, domain string) [][]string { - return e.GetFilteredPolicy(0, user, domain) -} - -// AddRoleForUserInDomain adds a role for a user inside a domain. -// Returns false if the user already has the role (aka not affected). -func (e *Enforcer) AddRoleForUserInDomain(user string, role string, domain string) bool { - return e.AddGroupingPolicy(user, role, domain) -} - -// DeleteRoleForUserInDomain deletes a role for a user inside a domain. -// Returns false if the user does not have the role (aka not affected). -func (e *Enforcer) DeleteRoleForUserInDomain(user string, role string, domain string) bool { - return e.RemoveGroupingPolicy(user, role, domain) -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/rbac_api_with_domains_synced.go b/src/goadmin/vendor/github.com/casbin/casbin/rbac_api_with_domains_synced.go deleted file mode 100644 index c2d3c063..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/rbac_api_with_domains_synced.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package casbin - -// GetUsersForRoleInDomain gets the users that has a role inside a domain. Add by Gordon -func (e *SyncedEnforcer) GetUsersForRoleInDomain(name string, domain string) []string { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.GetUsersForRoleInDomain(name, domain) -} - -// GetRolesForUserInDomain gets the roles that a user has inside a domain. -func (e *SyncedEnforcer) GetRolesForUserInDomain(name string, domain string) []string { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.GetRolesForUserInDomain(name, domain) -} - -// GetPermissionsForUserInDomain gets permissions for a user or role inside a domain. -func (e *SyncedEnforcer) GetPermissionsForUserInDomain(user string, domain string) [][]string { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.GetPermissionsForUserInDomain(user, domain) -} - -// AddRoleForUserInDomain adds a role for a user inside a domain. -// Returns false if the user already has the role (aka not affected). -func (e *SyncedEnforcer) AddRoleForUserInDomain(user string, role string, domain string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.AddRoleForUserInDomain(user, role, domain) -} - -// DeleteRoleForUserInDomain deletes a role for a user inside a domain. -// Returns false if the user does not have the role (aka not affected). -func (e *SyncedEnforcer) DeleteRoleForUserInDomain(user string, role string, domain string) bool { - e.m.Lock() - defer e.m.Unlock() - return e.Enforcer.DeleteRoleForUserInDomain(user, role, domain) -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/util/builtin_operators.go b/src/goadmin/vendor/github.com/casbin/casbin/util/builtin_operators.go deleted file mode 100644 index 53011e7e..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/util/builtin_operators.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package util - -import ( - "net" - "regexp" - "strings" - - "github.com/casbin/casbin/rbac" -) - -// KeyMatch determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *. -// For example, "/foo/bar" matches "/foo/*" -func KeyMatch(key1 string, key2 string) bool { - i := strings.Index(key2, "*") - if i == -1 { - return key1 == key2 - } - - if len(key1) > i { - return key1[:i] == key2[:i] - } - return key1 == key2[:i] -} - -// KeyMatchFunc is the wrapper for KeyMatch. -func KeyMatchFunc(args ...interface{}) (interface{}, error) { - name1 := args[0].(string) - name2 := args[1].(string) - - return bool(KeyMatch(name1, name2)), nil -} - -// KeyMatch2 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *. -// For example, "/foo/bar" matches "/foo/*", "/resource1" matches "/:resource" -func KeyMatch2(key1 string, key2 string) bool { - key2 = strings.Replace(key2, "/*", "/.*", -1) - - re := regexp.MustCompile(`(.*):[^/]+(.*)`) - for { - if !strings.Contains(key2, "/:") { - break - } - - key2 = re.ReplaceAllString(key2, "$1[^/]+$2") - } - - return RegexMatch(key1, "^" + key2 + "$") -} - -// KeyMatch2Func is the wrapper for KeyMatch2. -func KeyMatch2Func(args ...interface{}) (interface{}, error) { - name1 := args[0].(string) - name2 := args[1].(string) - - return bool(KeyMatch2(name1, name2)), nil -} - -// KeyMatch3 determines whether key1 matches the pattern of key2 (similar to RESTful path), key2 can contain a *. -// For example, "/foo/bar" matches "/foo/*", "/resource1" matches "/{resource}" -func KeyMatch3(key1 string, key2 string) bool { - key2 = strings.Replace(key2, "/*", "/.*", -1) - - re := regexp.MustCompile(`(.*)\{[^/]+\}(.*)`) - for { - if !strings.Contains(key2, "/{") { - break - } - - key2 = re.ReplaceAllString(key2, "$1[^/]+$2") - } - - return RegexMatch(key1, "^" + key2 + "$") -} - -// KeyMatch3Func is the wrapper for KeyMatch3. -func KeyMatch3Func(args ...interface{}) (interface{}, error) { - name1 := args[0].(string) - name2 := args[1].(string) - - return bool(KeyMatch3(name1, name2)), nil -} - -// RegexMatch determines whether key1 matches the pattern of key2 in regular expression. -func RegexMatch(key1 string, key2 string) bool { - res, err := regexp.MatchString(key2, key1) - if err != nil { - panic(err) - } - return res -} - -// RegexMatchFunc is the wrapper for RegexMatch. -func RegexMatchFunc(args ...interface{}) (interface{}, error) { - name1 := args[0].(string) - name2 := args[1].(string) - - return bool(RegexMatch(name1, name2)), nil -} - -// IPMatch determines whether IP address ip1 matches the pattern of IP address ip2, ip2 can be an IP address or a CIDR pattern. -// For example, "192.168.2.123" matches "192.168.2.0/24" -func IPMatch(ip1 string, ip2 string) bool { - objIP1 := net.ParseIP(ip1) - if objIP1 == nil { - panic("invalid argument: ip1 in IPMatch() function is not an IP address.") - } - - _, cidr, err := net.ParseCIDR(ip2) - if err != nil { - objIP2 := net.ParseIP(ip2) - if objIP2 == nil { - panic("invalid argument: ip2 in IPMatch() function is neither an IP address nor a CIDR.") - } - - return objIP1.Equal(objIP2) - } - - return cidr.Contains(objIP1) -} - -// IPMatchFunc is the wrapper for IPMatch. -func IPMatchFunc(args ...interface{}) (interface{}, error) { - ip1 := args[0].(string) - ip2 := args[1].(string) - - return bool(IPMatch(ip1, ip2)), nil -} - -// GenerateGFunction is the factory method of the g(_, _) function. -func GenerateGFunction(rm rbac.RoleManager) func(args ...interface{}) (interface{}, error) { - return func(args ...interface{}) (interface{}, error) { - name1 := args[0].(string) - name2 := args[1].(string) - - if rm == nil { - return name1 == name2, nil - } else if len(args) == 2 { - res, _ := rm.HasLink(name1, name2) - return res, nil - } else { - domain := args[2].(string) - res, _ := rm.HasLink(name1, name2, domain) - return res, nil - } - } -} diff --git a/src/goadmin/vendor/github.com/casbin/casbin/util/util.go b/src/goadmin/vendor/github.com/casbin/casbin/util/util.go deleted file mode 100644 index e25dc223..00000000 --- a/src/goadmin/vendor/github.com/casbin/casbin/util/util.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2017 The casbin Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package util - -import ( - "regexp" - "sort" - "strings" -) - -// EscapeAssertion escapes the dots in the assertion, because the expression evaluation doesn't support such variable names. -func EscapeAssertion(s string) string { - //Replace the first dot, because it can't be recognized by the regexp. - if (strings.HasPrefix(s, "r") || strings.HasPrefix(s, "p")) { - s = strings.Replace(s, ".", "_",1) - } - var regex = regexp.MustCompile(`(\|| |=|\)|\(|&|<|>|,|\+|-|!|\*|\/)(r|p)\.`) - s = regex.ReplaceAllStringFunc(s, func(m string) string { - return strings.Replace(m, ".", "_", 1) - }) - return s -} - -// RemoveComments removes the comments starting with # in the text. -func RemoveComments(s string) string { - pos := strings.Index(s, "#") - if pos == -1 { - return s - } - return strings.TrimSpace(s[0:pos]) -} - -// ArrayEquals determines whether two string arrays are identical. -func ArrayEquals(a []string, b []string) bool { - if len(a) != len(b) { - return false - } - - for i, v := range a { - if v != b[i] { - return false - } - } - return true -} - -// Array2DEquals determines whether two 2-dimensional string arrays are identical. -func Array2DEquals(a [][]string, b [][]string) bool { - if len(a) != len(b) { - return false - } - - for i, v := range a { - if !ArrayEquals(v, b[i]) { - return false - } - } - return true -} - -// ArrayRemoveDuplicates removes any duplicated elements in a string array. -func ArrayRemoveDuplicates(s *[]string) { - found := make(map[string]bool) - j := 0 - for i, x := range *s { - if !found[x] { - found[x] = true - (*s)[j] = (*s)[i] - j++ - } - } - *s = (*s)[:j] -} - -// ArrayToString gets a printable string for a string array. -func ArrayToString(s []string) string { - return strings.Join(s, ", ") -} - -// ParamsToString gets a printable string for variable number of parameters. -func ParamsToString(s ...string) string { - return strings.Join(s, ", ") -} - -// SetEquals determines whether two string sets are identical. -func SetEquals(a []string, b []string) bool { - if len(a) != len(b) { - return false - } - - sort.Strings(a) - sort.Strings(b) - - for i, v := range a { - if v != b[i] { - return false - } - } - return true -} - -// JoinSlice joins a string and a slice into a new slice. -func JoinSlice(a string, b ...string) []string { - res := make([]string, 0, len(b)+1) - - res = append(res, a) - for _, s := range b { - res = append(res, s) - } - - return res -} - -// JoinSliceAny joins a string and a slice into a new interface{} slice. -func JoinSliceAny(a string, b ...string) []interface{} { - res := make([]interface{}, 0, len(b)+1) - - res = append(res, a) - for _, s := range b { - res = append(res, s) - } - - return res -} - -// SetSubtract returns the elements in `a` that aren't in `b`. -func SetSubtract(a []string, b []string) []string { - mb := make(map[string]struct{}, len(b)) - for _, x := range b { - mb[x] = struct{}{} - } - var diff []string - for _, x := range a { - if _, found := mb[x]; !found { - diff = append(diff, x) - } - } - return diff -}