From 87c7452d19c2c1515448634d0eb56b8a957ffce0 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 21 Oct 2019 17:02:16 +0800 Subject: [PATCH 01/10] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9email=20msg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/zh/LC_MESSAGES/django.mo | Bin 80914 -> 80782 bytes apps/locale/zh/LC_MESSAGES/django.po | 177 ++++++++++----------------- apps/settings/api.py | 14 ++- apps/users/utils.py | 27 ++-- 4 files changed, 93 insertions(+), 125 deletions(-) diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 62707d10805f7b734067ee4bc83b8bed3d839c0e..3c2a395cb88e66e85f4d74cc057378acebb9e6dd 100644 GIT binary patch delta 18303 zcmb{3XLwgtw#V_45E23b3?YP0=%Iy#j#TMHq^VTt9qC;_4jlr5K%^HbDpf%PihxuR zkS0Z`q9alj1RUBRaKFF*UiW#%nfvn2y!h<3&pCUqz4ksQ0cPer3YqyZWL8zbMX={J zYUg>=JkMLz!Slvqd`Hi_fE)2>kmpVBiuQfa9?QrlJP;35#J+PtVJX zC9pUqVLT2sKR|N!PGMoJ*vlo{4lfb+=;eD}1dV#VU8b*M6mbU(#le^xM`Bi-k72k0 zGvQ{`3iqMLIc{D=jdKGv&QsKLA#b`k0#%_XpGIaH`7s6)Q3Ex^G}r=Tu??!!qfiM= zLX~tSYAe3Pba(`F;rFO5xr-SvtdF}Mg$0OnqbljwprHXfp&lHA+KNS}jNiu>a5bs| zTQMyj#q@Z}yo8a&H&6?Df}Jr#U$@eJScG^qYU@^Ef9Cg&(ilufwSF8V{1jis5U$Er zsQwLD5uc+Hs5rotvKp#VbubPaU{M^1x^E$BrSD^F+=F#6*Fc>W_P-+yW&SRzge%N- zsM4ik1nxo|)+4CB{T(x+H^>ezYQiYg{W(x)qzG!O%A>|>WY=3^M&|dr*@eMah}cJ! z_5;)a8?hAbM4f@(Q4>5s-Jgc?y?}A3Ev$?>ORuBOKwr#>6EHI_Ge1FJ6YQj+Q+m`c zoW{b$zoI5cKg4BT8kJZTRLSe1&PWn!Pn)C08I2)00hQ=fR3dY&e?3MLZyG}VwW7Ur z=siAy%J4T#z$d8dC5O6!E1(jnhPtl-DuGt0`#Pewpf_r32AE?|TksAl!BytEq11mR z9iP&n0bd*DO5PQthzFxqG6gl!JE+pWhuLrgYT|vU>qk)&e2?1ei>Q@e#~k=C)K+C3 z?s?gB!Z*fkr2&xi& zF&p|At@nQ(4IRP_uEX1oD*Xxb3T7vMj9O8ak#6DwsJJw0g*8x#G{7v_6g5#7RKg?e z`c%|>v+xDI|L+GHoJPB04`$_tL#T-_p$2@2+SBx-Tmsop6BaZ}paw2$aV^w`Ckd5c zA5_JLqQ)7IW%d5gq@lgri`t_@mUHGM%2V#p>8~cn)n=6!t1Ea^N)287Qr3FrBD;xL?v*~ ze2z*aVw{^W8uffJRKoG71^Ja|#L}pZd9f=d;RL*c$4~?98t(=;h|2sZD)G~(75#!* zzyqw0!4uqJO+ww*9dqLltc9~(?0cta)THAsYN9d|-HNK9J~*{ehp{0R!}h4NG8HxO zGSqz=P>Fqp+PW`MEBqE!q3==S|7c#tIKBUW&``;9Q`rq=cmz#h9>HVns^jy1<9z&EXFWg zkGd}vwdcE0r9O=+^%d0fcTn&DGt_q>a;m$(1cngTK%Ip;Q>ni)??i`AWnWB(!%+i` zMNKpl^@UrB8h9J3lt)nmUc}P)4^-lj$*v*=Q4^I$-PZ`iv6;nflc|3?Iy%y!mG#23 zI1IyaG#0_h7>pmAo3H?Js`&%HO#B#C(Yn+4)g60aL)?j4NV@56>vE$KE$GwGO3R~G zR2#Lz=4LlkVk68+_$BciJn! zh6d<~%6Ks9P>sM1n2i0f!n^J_r4LaPt;Go3f|+nHYUL+T0SUS+b=N2;)H%2|s9yP&G)PNIFC7f>kDX2tNqV{+r>c{s!R0V%Rot1m2 zaiV9t`wL+Pz5j_cG+;GMgLSbmHbkwcKWaroQ7a#dI+X8Ne=2G#cA^$?(Bczz{Q@eH ztEdDXqY_Rxhx%*aXd1c@i&{Zx)azCowc@sRy))``4@4!Jf?DZ()O((ak$4pKo6}FI zgdSlr3`%heD1n-%VhZ)wN?xWT3l2i9d=e_5_4opALnU(9Jc+8rIaGzNptkHc)Z6d` zl|YX7oMkX8@yn>69UW0;ZJ2%zYvNIKMBz--2V*7br{ONlhnLJ}sEP8bWtf`(~kjk?~j1NTRU=l~LGycNo*72FilkqCBXT)In9O z8ET8VVpbfCs?1c>eG9NQeu!o92I`RKS>U#=Fj8^fOQfNd)&)( z`kSFD(F?QVEL17in%htnIE=dg0;=SHqTc_si`;Koaj42Q#CW~`t!U`RDds}dKbZ{S=cLh#Ml?=Dm3$G_z>l#g z-oio{y~N%3BI>@TSO&XbJkCQM#{H;7zeP=S(!7AG@UN(?ytjn<>&9nvXvLvR-2>S$ z8*x6&jTKOtziQXpS==49rvp&Wk3uCh9aYhtsD!>l9n$ZyIo?DqsM<2>pN~f8W$uuS zM;)SMa~`Ust56B7MIEM8R7tm?7H|r67A~MF`nz2Zd*3A%iy9{Z^?U_Xg4KK)8lZ`F zw6q&~p$^FaRH<~I5}1x!>0H!=AENI29JM9;Q7b)*1@RWkzBR4M;J?NRV5XI9j}MNnU~1T2PKt$!wJ0Shet$lPT8+fZ-AK`e|X z6f?i~kcL+5ec(#=0xHvd7>h+Lu8&HnG3x$~s1*;u95@cOvc=ZF2KD}biQ0;zs01&f z7JL(Zb=~572Q`C2yiu z8obsmBr__}9H_J87pI}js-j9&8&%4dsJ-orTKRO;1M@Kn*IN8fR05&v_`!rZP!nWa z?-SLuC!+>jWY<4LRpK+$*6l_u z;2Tt87g6K?fvWT))cxr;Xgu~m8x2id6!kzNYNd5B7F(b)9*#wEwDo^r?niy$uA0~mWC$$91Gw<)Ti_}RLQ(g+}>x#{DhTIiL}9XI39c9 z&sYnSHoAY|n1LGSB=WWOuHgtw-sFA;1b<5X3(}FF#x|^rdcgaPf6Iet9D;+e1YSd( ziKtZfx+Y>n;#ZJu_vT{}thL#Fkb0pG;{=SyWf+G?%?F#QzgCiOi~F~o`dFFRxA;rc zTX7e)1&>jC{|v`r_~(4Qa5_fexGyLv&c(ub7+=D>X4$RoUs8r*8TwakrT$v!4|L4N zvR|?zr zGh)!Lz<9ownT7@|jJi-0HE?6pfbFn2_D1dfT+EEiQ7hPlN??ceA44U431jhJm=$yF zc84+nm0%KP(EHzxhBEAh8h9LP;Mu5wm!kSNqWX8CN_p5kg;j|!ph};84}WWd1yB>u zL~Z3N)bndl3*C&-%g_oFHTBoG`8plig1e|g6TaVl%i~aoE*@)O9n}33QHjpL zw7AqD{*ga=U1UqGF$U-wggt@JJ(%J?aUVAwZq?;=nu$d4p!;H0MvXJUr|}()@`w0!3PZo;4ZyeYCEST= z&^yd8nh=62aW8C$Gf;=@464Mxqbe45#3hmkm1rT%9mEF>%MjN)>JszcqLG%4HJA@S zK~>@ys#IrD1OEec2L3{oKI1W0(mXhUI1w}97L3KOQR7@ejsFKm;C<8~3_cz>3%-|; zMkYG);VWbqFNsG}7QG$cqE?=Cf`Nm14e>4F?@sZPPyMI)Lj@kiT|7Vid)|3``3$cZ z{q@ed#GjxhjyUhOGzLR7Lvb1zxKJ9k;wl)4bx@^jVfH~)Xgun^l~^3tV@do06EMvM z*Iy3v5O=^L_%`Om4=@&Y>AF_#>X$Kr=($R+oDBnJNdFRyi!Kn+yMtbt0Po?UNhwnKd{dRsgJ_1r8}0`oC5 zuCwdg%mb*3p0@brCF-w3@z6R#esT{+qWbe&9B)>){>Elo)Wki_{^l_AZPWrLqQ;wP zE=DD~<|p4Zw$ssrj$^0?D*WvJf}keG5qHCuI1@YKRjh&a|KXfs9x%gxaqoY9RD$DB z<4(1B4i+U|=v!ltUATdHxo`*d7G%E6XBFF_`WK+SWM80Gbl5y=UNP^X?t5-V{p!w6 zQB*?ZO~0x&YNG~BGFzHm&4H*r9fMlQOjKnS*!4Z;G3&ozamW=nZX{{}c`dGnoFRVy zr=h**Vh(c`ykv`4np;o_9yGs4CG-nw;Cp7|Rd-(kYNgdM4c0*=-T(_>bBxgYKb%G= z9TNi`d_c?v*8d?Y!41~G3-c2nvG_JBfhQP>Ij=eMqY{oY%Ugdfv!P^uuc_V8((Gyu z)D2u8gId8P9D>Pq{h68Jx=S!S>I+u_(_sbF>sG^j9hK0Vs7j1LUybp0;T_aU7oy(p z4HoaW_$(@syQt^xo6pVg8?Haf%!67$QH$fT9C0PZY48$!vzYuN7*%&eq@G;$b(bzcQRaM-iNc{qR$}A@(9%3cOlBmi5e(BYT|f{ ztD^>Z+4`HK66$Q%N1#?d33cDQ<~-|PiV^httL?&O)bHopEk216#OEx&idBejSzPRv zTX6#F^w+kyGwQja7LPaQTK^i0w;&1n-a#75{3NP$*X@Ro+isv3vyhpHDs^>>o0;vc z|4oa>SUlb0W#)R+;ocgM{XaoN1KzY7o|@_Za0$hjWl>wu#NrO95|6?#oP?QihV?JC zcr~gbUs(Uwn1T41`t|;wr;!=2nGemdJ8th{Py^&OOPH0+x~K&-H@jK?2-Hd^S-i|# zZ*E0jhhx8W96`nBFeCnqO6<1vKSL#w_O3IFna?bVrMO-hHBJw+A1)*wYH{X!?)hx@ z*nbUJkPbbNfSRzP#r5sR#%5d88R=Y z>&NRhI&=u{+l37ObS2G>3G|n+_zjEuqY_?jt~NixNcy*+enuR?EO-Nzz+b2@X!w2i zd`6$f3v^^f9j3x|p)~4&3KrMKg2YMI-wy+a51Y_G3FGj4ERN4m&lh`OC_8l3l-U{^9h!2Q+j_pW20N z58Z%y%;H#->lIPo`VQ7V(VUIi(`6Qaf?DZzi}#|&KaSdp>(>7yAp4*0k-HF$dAK1C z^*}w;Kpjve?T%XMY)p^K?D|^k--J4xU!lH;=dAw`D#5gm-FVTcvymIK=>4xwLjyO% z?ARVvy5Xn<#+g&C|6SC83$1@GDxpoN=eJ`po;J^5Jn?xm{9pXwBCdpfT^jRf)WVC{ z9rHbL6`71mV4=m!F|gOD1a@2hcNSl^>wlWwU+%rnh<&+#HAZ9fQ#Wpjr@a4~pp11? zHf!Qb^w&pCm~8#?EM98yI*UIwcUu2p^CXtz`EwR$dgeZC(Wr3?KBN9>Bv?l^R6rnT7fx2%ePRA420^2=z@A+ob)@(KRq28insONw7X=uP}=08yb z2JznM`GZi^adh{dDq`g_*D0(F+wptkHYb1!Nu{FBzWj+)>ZYT(Eq zXK_@2ZB!yHPy=>BP23lA;t-49Mcp^gT!s2DZL;_r>iMgfj`_VicHyxZ8tf*FLJd^J zENj*@UqO92+n8@!|7cXg$*9+M3F?!30CoRi^CAZR{qGhHmF6Mpr(Rf^pujJa(Wp!t zp&o33g|UalGf*pAhD!7RM&W5xWv-il*!2e%rwMV_(_`TMk5q#P3YisA2_>0rPy_b1 z>jP1HHxac}i_BE>hmZxJP0+8k4k8c#VhUlmavpX<2I>e6cNa36Sw{4VOhzR%&-y<@-M=5T87D3N4Ru@}h5PQoi1cn(a-+U^Wl#^khI+7*#UoJ@O|f`B zYQhi9-KYg!G%usZxoJK$Lo&GgB7GXVAvH}vH=zET zq82A&;03g}8EX7isEWNAh<*OtOG5)LMU`$HYQSw4@3Hs<>b|oUU$OXi^RXG4*-aE> z7BMTEjm!?H|1G^Yh=wwqZ*D?mcnFoyb@P##?ge*$c2uH?H~}l665L@Pvg<#fD)S?1 zylYqiA7bF|K;t7_##K;1HX5T6dJA><=Ab58gPLHYxx=m>GJitdci;TWOq0d+r$=o; zBr2goS?v9fw;Rf%Ca7vQG+UTm%mJu@-Zp2MtL*ycsNa3|VKID!`ct!vktU?|@o?~Oo%-|A35>3dt;5B0!M%!I!6 z&ot+nOHh?qg?d{yVF-R>{fAL2KWqMmO6Zx?`yZ3t4Uk|~Lp_jWwnJ55fW^a66HY@7 zG~eP)cKs`CN&j~i$K`P2RYCq1!fR}C&7AiBze+%{R5wBQP8Z4xrtv#Eol&{ramgAITo+Lz<9a&6zS*Lk96e2+o+FlraUh9Qm7lN zp(gHbaWd8;{tPSQW2}T_^SVvwgG%6QoQEf@zh^#|@NV;5K0Zad;T|1IBstc7r5B<8 zV(A2`63*dM#&e*6Jd@+F0W0)KDxC6*+rm(A28!S(} z0$;~7SPlJBMO+2m#MkHuE*cd0zfrfu*2LSe4Q7pV73q(Sh?in3yopt?b}^@q+Vkz0 z6_26*0D9THk6KVz@xX$7FOzF{xy(4!4dqdvoT{iVL@n#Dhx+8aVsR_fgdI@t(;ys) zqfvkB`4BZ;niB4MdNV6#(WfXc4c(Av7b*oVFd^zNzK+_nA?8HXR=kIrc!kBA?fM?n zmYlHbw^8E+m2}U=qRvt&%%x9JZM)FH>|?%#I`xw+UTc1C?lZqLe?%p86LsjGT7R}u z_L`!uS4AzL3HmyPZ&=4*b1Z7bGb~Cmi%I0K zCAe{4MqPj1?3Td$ue}&*9nb)cpgj|83NLQ>=fc zx!C&Gm>W(1b8CEMevQifFe`0R4{Ok0p|Trq7^cyZ4%1L($5AUP{-U!SYJ%!!Gt|IcQ57193ve9j zxtvwppO*`v;s&S%G)GmY1?u^Bs6Pky#>_h9W2&UytTQ=na9S^QP}0co;E`!kZ@-!? zZ7{##hPLh;6nr>1wRfA}gJ131YgqO4vH$j;sspOG?mu);Y^N?=`VZ|lB(`U#!LgmY zb?X<~Wl*!Fn7_64J2|EoJL(`<8Qax zs8`3YxwdHH_01n$o%+R~tW^@DgJ_B z&wD1-^Co$ocl8y|8-;^9c-~38kKYD)-rF2>;p z7>XM)62HQ1cmQ+Z2`r4im@(Zw-z!ANlifWpGq%R^*cMZ83MS)TEQ60w6BO^^d8M!s z7Q_Kq8fRi6ZZ@wWIeU3~dR{Sn9hLB6JdG=R`kog-V`?v#={p!h{2_+oCd`l9Fcwc^ z7QBPm@i){Cv-WoLpEfA9K zN*Rk9kPr2`ltC@0H#2>_AmyA1cvXlr}zIy8hQxtxDGFPm@9p5vn=N3dL7h`UP3M0)8fIX9gasOG99CFHfo`dQ3-Fe z>jzQmeUCZx{$C68jzCQ~4WGbys3Tm9l-ApV zdGQFU5;stl2pQ?-i$Px#B+$?flTc?^7h|y*YN1Z3jMGsQkFxk}RAP%T53VuyqvpGS zy6>Tx`E@rghgte{>aPXr(V>akpb|(!mG(8%Q|qHDGz0Yv%tq~GDQd^-Q44Lg{{5(V ze?TR8&EiL>hdF|>YvVb68akVT)=>gAQ6<#EbudtRRAL=aCGBnTcvJ#2Q4`KX&9@Ad zz#7y>cAyg9k2=zms14mz0@}%a)WVrZxq&%Q3&&$sOhRSe19f8`+>Gg{1>RCC6n)m{0 z+#OV6zoL%Ld&BK8Cu+X@sQHVU<*=mQ|H?FUHm{(b+J4v-$6#5!jENXG-W^Fj)a%p| zL$DWW=lxL&j6j|J8>oe6V<;{}9qEUtaqBUJ^}R1?Xy8r^#cxnMJA!(s&Y3q*H~xm9 zn0bP`FB>X>7*u~DRD#7(<7?XW24)MaM1Onq3)9G;p@r6?7T%89!68&-e!?tx8#V3` z>ddoDbfwORdYHI-)THF40Ju9UH;35#G7mP94~B5K}VsD%cj#${kQ&arsWo76vyj-_;HXRA?Xx&^~= z2NuU~F&OWf4={oFky&68zpxV5K~;1Lw!xLy7(*tzjWkCcQD;=5y?h$l=?K)rF$uN9 zx#n_IVq48`a3k>#$j>V;V~Xb$!0c1qM#`c#@FZ%-H7u@!s!#*eQ4U6J+<%>h7M_6N z_%N}c>wkBe2*F*G0mNQF3d(;7&Tux>rb)%hNyX3Vi|0QRMz(<(#T53 zDpbasQ19h4o*Ok^K~$+rVI(G_-ilgwy*0+^ z{qI0SnGFtfkP=1_&qCd>1hv3s)P(y{B|L2XCs2u8K|QSZQD45SGhGFXqn?#&sCn9< z#`nf-djE&e(1hbK6HdWmI0JQ-pP_cN8MX7>Na?&I*8d1~6d`Z9jYOg1+^G8!FdECD z5~zbppgH;)(9SM&N9|xR>UEoh+VLX0{t@cw-hfK<1Zt{yC=*0%hO`fK6sbj08>)Cc1V>Zf7oEcefR#mxGsg}S0jI0#khF{lZr zVBn`7YUe9Z<36+NJ5ZI~gZiGF^=W8=^H>dkMkP?WDtUSlooF%t6$+Gx#)K$BLLd$IaUXb#!S+#eHuG4V7vN>Yk+NfT5eEm1q}V)nwoMob|Au=cTclMjY-(mHZsm#=BSoE6sO* z2WW>HHySl=HderoF%f@6J&X|xT%tKq3*|8rP!%qNI?8GbsK0hppAPM~nGH*Cn!>Edeyz3Hr0`-vQ#}-%~i{iLL~pcG_=4D z)IV4)I;|@sv@UQ3H^*3_W<=>`2%%-&nm`6TXD1L@(5YgRwM@MJ2crHSreI(R_!^@h0lN+8??KHbvdv9+hx! z%#6cPZ^x()see5hbLr4idKz`+k5HwKUg|Q=kNOUjM!hW!QHeA++oPW5KB$GpT7L#A z(M70d>@&=QTTzMaUP}Gdag+`XIE5j20hQ@BR3f)fJ9~to7`n{Gk*J;IK~=5-s?g>G@phtehstW1k{mCw|D_+r%SLTu0tjEBWm1FsE75Indu|<0m_A{ zWO>w18)G=OK_%J&^(^_X(om*jQKg!MD&@PVvt5VU`C-%zr?Cm%vbe^_E`ervhyD(z z1zLUL7Ve5!i3gxIG7`0cDVR;~|4bTTbS%Jd{LtdnsLVH7|1Q+Thfouqv+LJUmG~8P zbXk_W4Md_UQv@}CWmKhWqsBMKz~BE;X=vfTs2hf$b~+j3aRDmhFR=vfu>Nai#0vL? zD~Ea(>Y*OiRMdjQ%t_`ucKu^~Qt$t68d~rVOu(p>?o(O;RkDUy65C*5^ihetkEys9 zdt!-I?oTT-u^#bJ)F(O5YQ|zB4#7jHp8<{6Fjo;8J!ovgDX1G7e#$=+U^`65jaUW~ z*Scq-E$Ve0f{pQS$gz8;u{gfD&V7(pqkbCh!$iD*+DPnrXU+ATzjo4%jw(0}tKlw- zz0cfRQ5AIrbx>ztA4lVJcn=R_4DR`ylHw^WhS3}NlRH*5hhaJ5%~%1iZlM0!X@QOW zr3!~(XN;g6>DV7T;sxx04Zm=iFT)1J-(g$Kz1jUt7>HGgm!c9ni@EVG>UE6V;+~aa zn2k8aw?-qg6=vr`2h@)HVKAm+CVUNb<8ah#I|23Gn1&JfHtJ#i0NddT)O=aLbmQ`% zt`|nlpTEm>1tgO}r6x{~lBVComc>VL^O^+IgO> zZs+AOlDH8vpYOGyp$XIM!UWXBvrrQ*#?rV3mDnlNYjp{=g9oStGJWOx<4_3~!+3lO zW3dzJr{rs>1ZQG4*7p|EP=>2f6YoJy{CCvE|3LNMNA-tpbES+n^I{7938>P(g1xaP zYT;w3qr8f`|0b#ezhNBfd*R#NjtimAG7(jg%BUSbkGi29cEw&;1`lC*{2eteafe%= z8mfZzu_CrYJ&Y4kLxCleqVPCpHP2xv@eS06>>eg!(jNEeZjX(LN1^7~=hHYuW5iy5&BA8;_{!lSG$h(qabb(BB5-~r?#=RJRn-|M(P>Np=AJor7o zywJbz2bZ{i!Yw=lb)@q!vsPG1BO4uSF$}jNnR$Cqr95HYLRBdAq#IWpOA{wyS!|2R zIKlciU;*OuSR8{+StT)^_-QPl9d=Oz$KWV@59?#$A6*H%<67cZF%pZNcBQOn)#Y-&y)ZA|Uhs`sngs+=-%tvO>S+{{O)H=~- zAylGe&-$)Wn~v^uv_S266BfmtSQ4+`3mARQ{T|Q@YZLD`v;E}arsibS`@bKRV90ql zZv-mNg(a|nZ;kqPp$``1LOSX#$iV7&&ieEJ!@YJjP&;aFwljO0gHf;NSaUY&+4%&O zz(&*m${M>-6CN;6nwQOcsG|wK;C2#?s!V>=ef7;2*8hsd6U|wujV-cx8}bbK-T@jq zi%aGscfpIi==zJB)ldsPW4?q+s2ghH!R9Qxz79j_--elR59(;Y!J>E^BUs=2jYcRP zVVB$jQD%Nre<@Ug$=3fg7AAhq;sK}xeAM`N%_Vkyxw+B$cbVTx*7uIufRpBB^PUE9 zJ@~TQK{%!pN1`e*#+;5ya6anOx(dT^6Y6!_Vg7)+?H%YLzQw6hT~9ktU1-3ZN87%z$X@eij{~rTmLUtsDC&e59tUzTvy!<(Wp%Gpb{#M z`LLSBtx@;&K%M0PtcSuPeJuJwz!?y6SeMO-#SK`lkCE5^Ihv-f?D`fi?`eL zgVui>mC!}I{yS>t;Xk{DV$8g#{=yi6ei^$^6?4&1+u}AhAl2etScB`YTD$_avvsJa zf49XKQ4{}aap(;WtHDz(mvy^UP)Ddb_^e;$!Ad)_>FD z;G1sYDAYU&W)kY*P6^2Qx2B<;^tAz_&1tBF=9!;k6!8&@&!bBD7_(sbEq6U921;yk z8B_u_tiKUvBW|I7z5nfLXyV@HaC0*1A(@AoV3E1X+-&YeZQ!_h#rl6o?KJ!stALqg zrl79{8e7M6s5liPu?s4(0oFeTmB^ds+vW%6YAna~EvR{}nYVE+@vjzV+;;Q4bDQ(m zgiGnr4eL+~eqr%`8+h0}gF2GyX4oC~W40*1Lw|eJe7~aR3%%=%MD@p_<}Yk<`McC# zKVECmp@(p&U6_v1#Pcy3S6O`4;yb7Xir#aUF)LtB`m3RSMl?mu(+8EnDAX5pD(e23 zK8+kS=Aa&$kL~-i<|w4_Ni!kxCe(tv%>$_W z{bM%ZjCtJ#{A#iHz}*;$+F2~>#^TnWj9RFQ#q}(1iW>K#*~zY_nFF1^H;jg!($RL| z9n^&Hn=7#d@fWCX{dwyTd+5f+q0ThH;tHsp*0#6-<|b~5I*K&w_XBeNQ|!WAEWm)} zm>c(@COVHQ=~Yx>alg7Bvk9o{7Cy%{k1U|Uo>CFMB?`5R7@q_jDCF@d4F?% zIP8Gkh(AD;D(mlV;R2|*C@Rq^s08X+e=Cc-+x6GXaX6Q8GqDer`NO?sb5R>x^#||2 z8lPFm7IP;)MgM-(f{}l^8}g#!!WJi5{G?ge`kR|=uoB}_Eq)92VVjGZXX&5RUyXIv zvCRe^K<)S#>Z~rKUcao5-S|XQ;x$m?>f&TOHUO1qF^K#cYUri&~)W@8Z)? z0=>;4s0rV|JUGYtKehg?79U2P^%>Me4=sLd*K-HC{$i+SrY!2nDw_>3j@WNwjWpE4 zV^9;%GFMvvZd9TtP!nE4E&L1S#fKKh1iNv0%@SCW>y<1{Mcv;E!&u)-w+kc9NvK3- zTl}&4xw+H)4)x_cZQitgFO$1J67|}~qmH5}YJ79E0|x&6->WoKn&GI2V=`98xq$)v zc?Nak2`q-!EY6wP?JNORnWh+nFQO`wW)8IL!z`X)PQ$?aKT8d6SZ02KO6Y)j8a3e! zyM7OKc3~mzs0x}@%;(IWsKmyg=AUlyBGi1V(ATH+Ga5RR)8=LKHs+%LcT@>uLfwQ< zU|r&(s84ct>z{&JXfA34%TdqLX7d;ZHiFu~z0e@{^FLb_cOkb~2sKf0ROzc(+yt8t zr=oVY%v^77$Kv!KwD>-1o=jmbp&i*|NFo z`A|RoN}BahJM3U~N6pjM9PZ@5|FZ$J?81Ch#vfU{+1!gt?6_UOZvBr@4{=09P~gXI zB~;=qQ3(!0E&K-R^?eKV&~Cs`zCYfNfd+p>MxE_7^Pc(G43BgZ#h?<5NA0j8>LIOe z{Y_Exv_~!61NqWz{}PS>Kyw9qUjNZbL1w2VcaK82E%{4+{MI!Bo@&qfiS> zGH0XiUu@Suv3NZOUPFtIq2@n@enA>Hts{Gso3Jpdbcv`5Ygt_1;?}5z+gaSx;{N7H za}sKy+2+UQ7V}UP@4p6|r$c9QAC+mo9L`Fp1e>7}N;5~8Q&8jQqY_<@V{tPo!8$pe z%~03dqAJ%BHDB+Xy#M;v54VAzq7vGQ`r&aHwZI>!hc8#Oo2V>mfr@4w)b(a&XVij2 z%~9qAa~f)$Sw0PAw9GDiYHma=@Rj+kdBVJ8-bGCm6yuCFOQ7zrj`|I#A(p}ssNWSo zH2pQ!*lg}bmF6%iv7b<{&2@{TV_koKvp8y}$yflZSlk+wKs&RiIT)4jSQq==+t%@c z`I)=m?L{SW9JRnj>;KvMA6c9=&MowWSrm0-o0acH^VXJZ3yW4yAOu&x$sihj@=uj<}nqQ$7{sC2+`>5JvD&P(?7b-4>feBGR&N^Zt9Dw=; zzlGY^8q~OLsP(Q|99fWWX#+Yc7YqvgyN{7rmH2biA>2YG(5O(5_cpdh^|ji%}29H>e{xj@rZ|1b4Pe2KVL$)Lc0butH4kvsT| z{#mMUDfb&gU#!7}-DalJZs)Zzmi`u~e+=zz4n^%~GHOR}nG4P3c6}r2i}Mxg1F_5c z_hDB3F7=&toI;iQJgQ{(aTt1Kf&zd09FAIW0_yrSa}MghMRt9?^>4QRU8slg2h@>1 zG{ef0xW1*iX#}2Tbr4rY4XlrP3tHRt0jP=IK#g0BdYIOrevRF2{pZbF<{zl1K5IF5 zUpccn2EL^Yt)rFM5tUG1)I&Gg`rom5sa^ld`j4O8OLvQ6-*%Epav~k!#lfrx}vuCX7H`&x5L1Sq#Gz49tr<`{tEH#GZ~do9aMr%P`}coq81o#{S)zN;(4eFpF!Q{ zU!P&I5#nVQe}h`!I4Y47s0q%Y{xSFls?@QD9}>Jj zcYI7>1!sWcO8;mu4msaUHhh2uh6wmT#f%WN`q4d_V3s?7yg>@udy{>DUcD_zGBAn?Tb|XPq%2~zxV&|nKH(A8eUuj|M|ZZx7>fY zF{9=yjdT9{3@J(d*Uow6=YC=3tHhVDTs^tk+NlRi1p6uf|F!);>q=R3{A<&Jn%2si zk?C-e!hcoOw)nqB^*{1Npq|Z-=SxmW>iAd5|5+1i^gnOG0Eq{~GW= u3;EAv`X4D;j{jYn`^AMVv#z|q{>p+y|7o?rL=>3xYqiU@_S}&b-Tw\n" "Language-Team: Jumpserver team\n" @@ -95,7 +95,7 @@ msgstr "运行参数" #: terminal/templates/terminal/command_list.html:66 #: terminal/templates/terminal/session_list.html:28 #: terminal/templates/terminal/session_list.html:72 -#: xpack/plugins/change_auth_plan/forms.py:64 +#: xpack/plugins/change_auth_plan/forms.py:73 #: xpack/plugins/change_auth_plan/models.py:412 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:46 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54 @@ -112,7 +112,7 @@ msgstr "资产" #: applications/templates/applications/remote_app_detail.html:53 #: applications/templates/applications/remote_app_list.html:20 #: applications/templates/applications/user_remote_app_list.html:16 -#: assets/forms/asset.py:21 assets/forms/domain.py:73 assets/forms/user.py:75 +#: assets/forms/asset.py:21 assets/forms/domain.py:77 assets/forms/user.py:75 #: assets/forms/user.py:95 assets/models/base.py:28 assets/models/cluster.py:18 #: assets/models/cmd_filter.py:21 assets/models/domain.py:20 #: assets/models/group.py:20 assets/models/label.py:18 @@ -151,7 +151,7 @@ msgstr "资产" #: users/templates/users/user_list.html:35 #: users/templates/users/user_profile.html:51 #: users/templates/users/user_pubkey_update.html:57 -#: xpack/plugins/change_auth_plan/forms.py:47 +#: xpack/plugins/change_auth_plan/forms.py:56 #: xpack/plugins/change_auth_plan/models.py:63 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:61 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:12 @@ -322,6 +322,7 @@ msgstr "远程应用" #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:53 #: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:44 #: xpack/plugins/interface/templates/interface/interface.html:72 +#: xpack/plugins/orgs/templates/orgs/org_create_update.html:33 #: xpack/plugins/vault/templates/vault/vault_create.html:45 msgid "Reset" msgstr "重置" @@ -639,7 +640,7 @@ msgstr "网域" #: perms/templates/perms/asset_permission_list.html:53 #: perms/templates/perms/asset_permission_list.html:74 #: perms/templates/perms/asset_permission_list.html:124 -#: xpack/plugins/change_auth_plan/forms.py:65 +#: xpack/plugins/change_auth_plan/forms.py:74 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:55 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:15 #: xpack/plugins/cloud/models.py:157 @@ -668,7 +669,7 @@ msgstr "如果有多个的互相隔离的网络,设置资产属于的网域, #: assets/forms/asset.py:132 assets/forms/asset.py:136 #: assets/forms/domain.py:17 assets/forms/label.py:15 #: perms/templates/perms/asset_permission_asset.html:78 -#: xpack/plugins/change_auth_plan/forms.py:55 +#: xpack/plugins/change_auth_plan/forms.py:64 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:74 msgid "Select assets" msgstr "选择资产" @@ -677,15 +678,15 @@ msgstr "选择资产" msgid "Content should not be contain: {}" msgstr "内容不能包含: {}" -#: assets/forms/domain.py:51 +#: assets/forms/domain.py:55 msgid "Password should not contain special characters" msgstr "不能包含特殊字符" -#: assets/forms/domain.py:70 +#: assets/forms/domain.py:74 msgid "SSH gateway support proxy SSH,RDP,VNC" msgstr "SSH网关,支持代理SSH,RDP和VNC" -#: assets/forms/domain.py:74 assets/forms/user.py:76 assets/forms/user.py:96 +#: assets/forms/domain.py:78 assets/forms/user.py:76 assets/forms/user.py:96 #: assets/models/base.py:29 assets/models/gathered_user.py:16 #: assets/templates/assets/_asset_user_auth_update_modal.html:15 #: assets/templates/assets/_asset_user_auth_view_modal.html:21 @@ -706,7 +707,7 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC" #: users/templates/users/user_detail.html:67 #: users/templates/users/user_list.html:36 #: users/templates/users/user_profile.html:47 -#: xpack/plugins/change_auth_plan/forms.py:49 +#: xpack/plugins/change_auth_plan/forms.py:58 #: xpack/plugins/change_auth_plan/models.py:65 #: xpack/plugins/change_auth_plan/models.py:408 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:65 @@ -1451,7 +1452,7 @@ msgid "Update asset user auth" msgstr "更新资产用户认证信息" #: assets/templates/assets/_asset_user_auth_update_modal.html:23 -#: xpack/plugins/change_auth_plan/forms.py:51 +#: xpack/plugins/change_auth_plan/forms.py:60 msgid "Please input password" msgstr "请输入密码" @@ -1637,7 +1638,7 @@ msgstr "替换资产的管理员" #: assets/templates/assets/admin_user_detail.html:91 #: perms/templates/perms/asset_permission_asset.html:103 -#: xpack/plugins/change_auth_plan/forms.py:59 +#: xpack/plugins/change_auth_plan/forms.py:68 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:99 #: xpack/plugins/gathered_user/forms.py:36 msgid "Select nodes" @@ -1877,7 +1878,6 @@ msgstr "删除选择资产" #: users/templates/users/user_group_list.html:118 #: users/templates/users/user_list.html:254 #: xpack/plugins/interface/templates/interface/interface.html:101 -#: xpack/plugins/orgs/templates/orgs/org_create_update.html:33 msgid "Cancel" msgstr "取消" @@ -3394,33 +3394,33 @@ msgstr "远程应用授权用户列表" msgid "RemoteApp permission RemoteApp list" msgstr "远程应用授权远程应用列表" -#: settings/api.py:27 +#: settings/api.py:28 msgid "Test mail sent to {}, please check" msgstr "邮件已经发送{}, 请检查" -#: settings/api.py:55 +#: settings/api.py:67 msgid "Test ldap success" msgstr "连接LDAP成功" -#: settings/api.py:92 +#: settings/api.py:104 msgid "Match {} s users" msgstr "匹配 {} 个用户" -#: settings/api.py:151 +#: settings/api.py:163 msgid "succeed: {} failed: {} total: {}" msgstr "成功:{} 失败:{} 总数:{}" -#: settings/api.py:173 settings/api.py:209 +#: settings/api.py:185 settings/api.py:221 msgid "" "Error: Account invalid (Please make sure the information such as Access key " "or Secret key is correct)" msgstr "错误:账户无效 (请确保 Access key 或 Secret key 等信息正确)" -#: settings/api.py:179 settings/api.py:215 +#: settings/api.py:191 settings/api.py:227 msgid "Create succeed" msgstr "创建成功" -#: settings/api.py:197 settings/api.py:235 +#: settings/api.py:209 settings/api.py:247 #: settings/templates/settings/terminal_setting.html:154 msgid "Delete succeed" msgstr "删除成功" @@ -4536,7 +4536,7 @@ msgid "" "You should use your ssh client tools connect terminal: {}

{}" msgstr "你可以使用ssh客户端工具连接终端" -#: users/api/user.py:176 +#: users/api/user.py:173 msgid "Could not reset self otp, use profile reset instead" msgstr "不能再该页面重置MFA, 请去个人信息页面重置" @@ -4874,7 +4874,7 @@ msgid "Always young, always with tears in my eyes. Stay foolish Stay hungry" msgstr "永远年轻,永远热泪盈眶 stay foolish stay hungry" #: users/templates/users/reset_password.html:46 -#: users/templates/users/user_detail.html:379 users/utils.py:84 +#: users/templates/users/user_detail.html:379 users/utils.py:83 msgid "Reset password" msgstr "重置密码" @@ -5190,61 +5190,57 @@ msgid "" "corresponding private key." msgstr "新的公钥已设置成功,请下载对应的私钥" +# msgid "Update user" +# msgstr "更新用户" #: users/utils.py:24 #, python-format msgid "" "\n" -" \n" -"

\n" -" \n" -" Username: %(username)s.\n" -" \n" -" \n" -" click here to set your password\n" -" \n" -" \n" -" This link is valid for 1 hour. After it expires, request new one\n" -" \n" -" \n" +"

\n" +"

Your account has been created successfully

\n" +"
\n" +" Username: %(username)s\n" +"
\n" +" Password: \n" +" click here to set your password \n" +" (This link is valid for 1 hour. After it expires, request new one)\n" +"
\n" +"
\n" +"

---

\n" " Login direct\n" -" \n" -"

\n" +"
\n" +"
\n" " " msgstr "" "\n" -" \n" -"

\n" -" \n" -" 用户名: %(username)s.\n" -" \n" -" \n" -" " -"请点击这里设置密码\n" -" \n" -" \n" -" 这个链接有效期1小时, 超过时间您可以 重新申请\n" -" \n" -" \n" -" ---登录页面\n" -" \n" -"

\n" -" " +"
\n" +"

您的账户已创建成功

\n" +"
\n" +" 用户名: %(username)s\n" +"
\n" +" 密码: 请点击这里设置密码 (这个链接有效期1小时, 超过时" +"间您可以 重新申请)\n" +"
\n" +"
\n" +"

---

\n" +" 直接登录\n" +"
\n" +"
\n" +" " -#: users/utils.py:59 +#: users/utils.py:58 msgid "Create account successfully" msgstr "创建账户成功" -#: users/utils.py:63 +#: users/utils.py:62 #, python-format msgid "Hello %(name)s" msgstr "您好 %(name)s" -#: users/utils.py:86 +#: users/utils.py:85 #, python-format msgid "" "\n" @@ -5288,11 +5284,11 @@ msgstr "" "
\n" " " -#: users/utils.py:117 +#: users/utils.py:116 msgid "Security notice" msgstr "安全通知" -#: users/utils.py:119 +#: users/utils.py:118 #, python-format msgid "" "\n" @@ -5341,11 +5337,11 @@ msgstr "" "
\n" " " -#: users/utils.py:155 +#: users/utils.py:154 msgid "Expiration notice" msgstr "过期通知" -#: users/utils.py:157 +#: users/utils.py:156 #, python-format msgid "" "\n" @@ -5367,11 +5363,11 @@ msgstr "" "
\n" " " -#: users/utils.py:176 +#: users/utils.py:175 msgid "SSH Key Reset" msgstr "重置ssh密钥" -#: users/utils.py:178 +#: users/utils.py:177 #, python-format msgid "" "\n" @@ -5485,7 +5481,7 @@ msgstr "MFA 解绑成功,返回登录页面" msgid "Password length" msgstr "密码长度" -#: xpack/plugins/change_auth_plan/forms.py:66 +#: xpack/plugins/change_auth_plan/forms.py:75 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:60 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:81 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:17 @@ -5499,7 +5495,7 @@ msgstr "密码长度" msgid "Periodic perform" msgstr "定时执行" -#: xpack/plugins/change_auth_plan/forms.py:70 +#: xpack/plugins/change_auth_plan/forms.py:79 msgid "" "Tips: The username of the user on the asset to be modified. if the user " "exists, change the password; If the user does not exist, create the user." @@ -5507,12 +5503,12 @@ msgstr "" "提示:用户名为将要修改的资产上的用户的用户名。如果用户存在,则修改密码;如果" "用户不存在,则创建用户。" -#: xpack/plugins/change_auth_plan/forms.py:74 xpack/plugins/cloud/forms.py:90 +#: xpack/plugins/change_auth_plan/forms.py:83 xpack/plugins/cloud/forms.py:90 #: xpack/plugins/gathered_user/forms.py:44 msgid "Tips: (Units: hour)" msgstr "提示:(单位: 时)" -#: xpack/plugins/change_auth_plan/forms.py:75 xpack/plugins/cloud/forms.py:91 +#: xpack/plugins/change_auth_plan/forms.py:84 xpack/plugins/cloud/forms.py:91 #: xpack/plugins/gathered_user/forms.py:45 msgid "" "eg: Every Sunday 03:05 run <5 3 * * 0>
Tips: Using 5 digits linux " @@ -6307,45 +6303,6 @@ msgstr "创建" #~ msgid "Update user groups" #~ msgstr "更新用户组" -# msgid "Update user" -# msgstr "更新用户" -#~ msgid "" -#~ "\n" -#~ " \n" -#~ "

\n" -#~ " \n" -#~ " click here to set your password\n" -#~ " \n" -#~ " \n" -#~ " This link is valid for 1 hour. After it expires, request new one\n" -#~ " \n" -#~ " \n" -#~ " Login direct\n" -#~ " \n" -#~ "

\n" -#~ " " -#~ msgstr "" -#~ "\n" -#~ " \n" -#~ "

\n" -#~ " \n" -#~ " 请点击这里设置密码\n" -#~ " \n" -#~ " \n" -#~ " 这个链接有效期1小时, 超过时间您可以, 重新申请\n" -#~ " \n" -#~ " \n" -#~ " Login direct\n" -#~ " \n" -#~ "

\n" -#~ " " - #~ msgid "Template" #~ msgstr "模板" diff --git a/apps/settings/api.py b/apps/settings/api.py index d327bde17..22a295b68 100644 --- a/apps/settings/api.py +++ b/apps/settings/api.py @@ -5,6 +5,7 @@ import os import json import jms_storage +from smtplib import SMTPSenderRefused from rest_framework import generics from rest_framework.views import Response, APIView from django.conf import settings @@ -41,9 +42,20 @@ class MailTestingAPI(APIView): email_from = email_from or email_host_user email_recipient = email_recipient or email_from send_mail(subject, message, email_from, [email_recipient]) + except SMTPSenderRefused as e: + resp = e.smtp_error + if isinstance(resp, bytes): + for coding in ('gbk', 'utf8'): + try: + resp = resp.decode(coding) + except UnicodeDecodeError: + continue + else: + break + return Response({"error": str(resp)}, status=401) except Exception as e: + print(e) return Response({"error": str(e)}, status=401) - return Response({"msg": self.success_message.format(email_recipient)}) else: return Response({"error": str(serializer.errors)}, status=401) diff --git a/apps/users/utils.py b/apps/users/utils.py index 59400694e..30868358c 100644 --- a/apps/users/utils.py +++ b/apps/users/utils.py @@ -22,21 +22,20 @@ logger = logging.getLogger('jumpserver') def construct_user_created_email_body(user): default_body = _(""" - -

- - Username: %(username)s. - - - click here to set your password - - - This link is valid for 1 hour. After it expires, request new one - - +

+

Your account has been created successfully

+
+ Username: %(username)s +
+ Password: + click here to set your password + (This link is valid for 1 hour. After it expires, request new one) +
+
+

---

Login direct - -

+
+
""") % { 'username': user.username, 'rest_password_url': reverse('users:reset-password', external=True), From f984acf1b2a9eae90df4dccc1beefa13ccaf03c6 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 21 Oct 2019 17:14:49 +0800 Subject: [PATCH 02/10] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E5=AF=BC?= =?UTF-8?q?=E8=87=B4favorite=20=E5=92=8C=20empty=20=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E5=87=BA=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/perms/utils/asset_permission.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/perms/utils/asset_permission.py b/apps/perms/utils/asset_permission.py index 6754511d0..84da4e337 100644 --- a/apps/perms/utils/asset_permission.py +++ b/apps/perms/utils/asset_permission.py @@ -234,6 +234,9 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): if user_tree.contains(key): nodes_single_assets.pop(key) + if not nodes_single_assets: + return + # 如果要设置到ungroup中 if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE: node_key = Node.ungrouped_key @@ -336,8 +339,8 @@ class AssetPermissionUtilV2(AssetPermissionUtilCacheMixin): self.add_direct_nodes_to_user_tree(user_tree) self.add_single_assets_node_to_user_tree(user_tree) self.parse_user_tree_to_full_tree(user_tree) - self.add_empty_node_if_need(user_tree) self.add_favorite_node_if_need(user_tree) + self.add_empty_node_if_need(user_tree) self.set_user_tree_to_cache_if_need(user_tree) self.set_user_tree_to_local(user_tree) return user_tree From 86522627d3971f8af5127b28913f45b7657413cb Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 21 Oct 2019 19:07:35 +0800 Subject: [PATCH 03/10] =?UTF-8?q?[Update]=20=E4=BC=98=E5=8C=96=E6=8F=90?= =?UTF-8?q?=E4=BA=A4api=E6=8A=A5=E9=94=99=E6=97=B6=E6=BB=9A=E5=8A=A8?= =?UTF-8?q?=E5=88=B0=EF=BC=8C=E4=BC=98=E5=8C=96table=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E6=9F=90=E4=BA=9B=E5=88=97=E5=AE=BD=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/assets/admin_user_list.html | 39 +------------------ apps/assets/templates/assets/asset_list.html | 2 +- .../templates/assets/cmd_filter_list.html | 3 +- apps/assets/templates/assets/domain_list.html | 2 +- apps/assets/templates/assets/label_list.html | 3 +- .../templates/assets/system_user_list.html | 6 +-- .../perms/asset_permission_list.html | 2 +- apps/static/js/jumpserver.js | 5 ++- .../templates/users/user_group_list.html | 2 +- apps/users/templates/users/user_list.html | 2 +- 10 files changed, 15 insertions(+), 51 deletions(-) diff --git a/apps/assets/templates/assets/admin_user_list.html b/apps/assets/templates/assets/admin_user_list.html index 9568ceb30..7a4b2a2dc 100644 --- a/apps/assets/templates/assets/admin_user_list.html +++ b/apps/assets/templates/assets/admin_user_list.html @@ -70,43 +70,6 @@ function initTable() { var detail_btn = '' + cellData + ''; return detail_btn.replace('{{ DEFAULT_PK }}', rowData.id); }}, - {#{targets: 4, createdCell: function (td, cellData) {#} - {# var innerHtml = "";#} - {# var data = cellData.reachable;#} - {# if (data !== 0) {#} - {# innerHtml = "" + data + "";#} - {# } else {#} - {# innerHtml = "" + data + "";#} - {# }#} - {# $(td).html(innerHtml)#} - {#}},#} - {#{targets: 5, createdCell: function (td, cellData) {#} - {# var data = cellData.unreachable;#} - {# var innerHtml = "";#} - {# if (data !== 0) {#} - {# innerHtml = "" + data + "";#} - {# } else {#} - {# innerHtml = "" + data + "";#} - {# }#} - {# $(td).html('' + innerHtml + '');#} - {#}},#} - {#{targets: 6, createdCell: function (td, cellData, rowData) {#} - {# var val = 0;#} - {# var innerHtml = "";#} - {# var total = rowData.assets_amount;#} - {# var reachable = cellData.reachable;#} - {# if (total !== 0) {#} - {# val = reachable/total * 100;#} - {# }#} - {##} - {# if (val === 100) {#} - {# innerHtml = "" + val + "% ";#} - {# } else {#} - {# var num = new Number(val);#} - {# innerHtml = "" + num.toFixed(1) + "% ";#} - {# }#} - {# $(td).html('' + innerHtml + '');#} - {#}},#} {targets: 5, createdCell: function (td, cellData, rowData) { var update_btn = '{% trans "Update" %}'.replace('{{ DEFAULT_PK }}', cellData); var del_btn = '{% trans "Delete" %}'.replace('{{ DEFAULT_PK }}', cellData); @@ -116,7 +79,7 @@ function initTable() { columns: [ {data: function(){return ""}}, {data: "name"}, {data: "username" }, {data: "assets_amount", orderable: false}, {#{data: "connectivity_amount"}, {data: "connectivity_amount"}, {data: "connectivity_amount"},#} - {data: "comment"}, {data: "id", orderable: false} + {data: "comment"}, {data: "id", orderable: false, width: "100px"} ] }; admin_user_table = jumpserver.initServerSideDataTable(options); diff --git a/apps/assets/templates/assets/asset_list.html b/apps/assets/templates/assets/asset_list.html index b9892790d..63f31a0c6 100644 --- a/apps/assets/templates/assets/asset_list.html +++ b/apps/assets/templates/assets/asset_list.html @@ -177,7 +177,7 @@ function initTable() { data: "connectivity", orderable: false, width: '60px' - }, {data: "id", orderable: false} + }, {data: "id", orderable: false, width: "100px"} ], op_html: $('#actions').html() }; diff --git a/apps/assets/templates/assets/cmd_filter_list.html b/apps/assets/templates/assets/cmd_filter_list.html index b6d46a2c8..0582363c4 100644 --- a/apps/assets/templates/assets/cmd_filter_list.html +++ b/apps/assets/templates/assets/cmd_filter_list.html @@ -63,7 +63,8 @@ function initTable() { ajax_url: '{% url "api-assets:cmd-filter-list" %}', columns: [ {data: "id"}, {data: "name" }, {data: "rules", orderable: false}, - {data: "system_users", orderable: false}, {data: "comment"}, {data: "id", orderable: false} + {data: "system_users", orderable: false}, {data: "comment"}, + {data: "id", orderable: false, width: "100px"} ], op_html: $('#actions').html() }; diff --git a/apps/assets/templates/assets/domain_list.html b/apps/assets/templates/assets/domain_list.html index 6a0f36f40..2b82826a0 100644 --- a/apps/assets/templates/assets/domain_list.html +++ b/apps/assets/templates/assets/domain_list.html @@ -59,7 +59,7 @@ function initTable() { ajax_url: '{% url "api-assets:domain-list" %}', columns: [ {data: "id"}, {data: "name" }, {data: "asset_count", orderable: false }, - {data: "gateway_count", orderable: false }, {data: "comment" }, {data: "id", orderable: false} + {data: "gateway_count", orderable: false }, {data: "comment" }, {data: "id", orderable: false, width: "100px"} ], op_html: $('#actions').html() }; diff --git a/apps/assets/templates/assets/label_list.html b/apps/assets/templates/assets/label_list.html index 7d780deed..9ab735f7a 100644 --- a/apps/assets/templates/assets/label_list.html +++ b/apps/assets/templates/assets/label_list.html @@ -44,7 +44,8 @@ function initTable() { ajax_url: '{% url "api-assets:label-list" %}?sort=name', columns: [ {data: "id"}, {data: "name" }, {data: "value" }, - {data: "asset_count", orderable: false}, {data: "id", orderable: false} + {data: "asset_count", orderable: false}, + {data: "id", orderable: false, width: "100px"} ], op_html: $('#actions').html() }; diff --git a/apps/assets/templates/assets/system_user_list.html b/apps/assets/templates/assets/system_user_list.html index dcfaac8cc..e6b259585 100644 --- a/apps/assets/templates/assets/system_user_list.html +++ b/apps/assets/templates/assets/system_user_list.html @@ -3,10 +3,6 @@ {% block help_message %}
-{# 系统用户是 Jumpserver跳转登录资产时使用的用户,可以理解为登录资产用户,如 web, sa, dba(`ssh web@some-host`), 而不是使用某个用户的用户名跳转登录服务器(`ssh xiaoming@some-host`);#} -{# 简单来说是 用户使用自己的用户名登录Jumpserver, Jumpserver使用系统用户登录资产。#} -{# 系统用户创建时,如果选择了自动推送 Jumpserver会使用ansible自动推送系统用户到资产中,如果资产(交换机、windows)不支持ansible, 请手动填写账号密码。#} -{# 目前还不支持Windows的自动推送#} {% trans 'System user is Jumpserver jump login assets used by the users, can be understood as the user login assets, such as web, sa, the dba (` ssh web@some-host `), rather than using a user the username login server jump (` ssh xiaoming@some-host `); '%} {% trans 'In simple terms, users log into Jumpserver using their own username, and Jumpserver uses system users to log into assets. '%} {% trans 'When system users are created, if you choose auto push Jumpserver to use Ansible push system users into the asset, if the asset (Switch) does not support ansible, please manually fill in the account password.' %} @@ -91,7 +87,7 @@ function initTable() { columns: [ {data: "id" }, {data: "name" }, {data: "username" }, {data: "protocol"}, {data: "login_mode"}, {data: "assets_amount", orderable: false }, - {data: "comment" }, {data: "id", orderable: false } + {data: "comment" }, {data: "id", orderable: false, width: "100px"} ], op_html: $('#actions').html() }; diff --git a/apps/perms/templates/perms/asset_permission_list.html b/apps/perms/templates/perms/asset_permission_list.html index 2a493e16b..18e30bde8 100644 --- a/apps/perms/templates/perms/asset_permission_list.html +++ b/apps/perms/templates/perms/asset_permission_list.html @@ -190,7 +190,7 @@ function initTable() { {data: "id"}, {data: "name"}, {data: "users", orderable: false}, {data: "user_groups", orderable: false}, {data: "assets", orderable: false}, {data: "nodes", orderable: false}, {data: "system_users", orderable: false}, - {data: "is_valid", orderable: false}, {data: "id", orderable: false} + {data: "is_valid", orderable: false}, {data: "id", orderable: false, width: "100px"} ], select: {}, op_html: $('#actions').html() diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index 4f55cfb4f..4dceb01bf 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -201,7 +201,7 @@ function formSubmit(props) { var errors = jqXHR.responseJSON; var noneFieldErrorRef = props.form.children('.alert-danger'); if (noneFieldErrorRef.length !== 1) { - props.form.prepend(''); + props.form.prepend(''); noneFieldErrorRef = props.form.children('.alert-danger'); } var noneFieldErrorMsg = ""; @@ -247,6 +247,7 @@ function formSubmit(props) { noneFieldErrorRef.css('display', 'block'); noneFieldErrorRef.html(noneFieldErrorMsg); } + $('.has-error').get(0).scrollIntoView(); } }) @@ -453,6 +454,7 @@ jumpserver.initDataTable = function (options) { { targets: 0, orderable: false, + width: "20px", createdCell: function (td, cellData) { $(td).html(''.replace('99991937', cellData)); } @@ -550,6 +552,7 @@ jumpserver.initServerSideDataTable = function (options) { { targets: 0, orderable: false, + width: "20px", createdCell: function (td, cellData) { $(td).html(''.replace('99991937', cellData)); } diff --git a/apps/users/templates/users/user_group_list.html b/apps/users/templates/users/user_group_list.html index c2fa87357..3eb70e319 100644 --- a/apps/users/templates/users/user_group_list.html +++ b/apps/users/templates/users/user_group_list.html @@ -82,7 +82,7 @@ function initTable() { ], ajax_url: '{% url "api-users:user-group-list" %}?display=1', columns: [{data: function(){return ""}}, {data: "name" }, {data: "users", orderable: false}, - {data: "comment"}, {data: "id", orderable: false }], + {data: "comment"}, {data: "id", orderable: false, width:"100px"}], order: [], op_html: $('#actions').html() }; diff --git a/apps/users/templates/users/user_list.html b/apps/users/templates/users/user_list.html index d992416d1..cd9273681 100644 --- a/apps/users/templates/users/user_list.html +++ b/apps/users/templates/users/user_list.html @@ -125,7 +125,7 @@ function initTable() { {data: "groups_display", orderable: false}, {data: "source"}, {data: "is_valid", orderable: false}, - {data: "id", orderable: false} + {data: "id", orderable: false, width: "100px"} ], op_html: $('#actions').html() }; From 6ebe8e16bdffe0c472701c7093e79974e7121db7 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 21 Oct 2019 19:28:33 +0800 Subject: [PATCH 04/10] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E8=AF=BB?= =?UTF-8?q?=E5=8F=96=E6=97=A5=E5=BF=97=E6=97=B6=E5=8F=AF=E8=83=BD=E8=A7=A3?= =?UTF-8?q?=E7=A0=81=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/utils/encode.py | 4 ++++ apps/ops/ws.py | 20 ++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/apps/common/utils/encode.py b/apps/common/utils/encode.py index fc9467cba..d4e9c4cbe 100644 --- a/apps/common/utils/encode.py +++ b/apps/common/utils/encode.py @@ -182,3 +182,7 @@ def encrypt_password(password, salt=None): def get_signer(): signer = Signer(settings.SECRET_KEY) return signer + + +def ensure_last_char_is_ascii(data): + remain = '' diff --git a/apps/ops/ws.py b/apps/ops/ws.py index 1d2bea3c5..d6bff86a7 100644 --- a/apps/ops/ws.py +++ b/apps/ops/ws.py @@ -3,11 +3,13 @@ import os import threading import json -from celery.result import AsyncResult +from common.utils import get_logger from .celery.utils import get_celery_task_log_path from channels.generic.websocket import JsonWebsocketConsumer +logger = get_logger(__name__) + class CeleryLogWebsocket(JsonWebsocketConsumer): disconnected = False @@ -22,6 +24,7 @@ class CeleryLogWebsocket(JsonWebsocketConsumer): self.handle_task(task_id) def handle_task(self, task_id): + logger.info("Task id: {}".format(task_id)) log_path = get_celery_task_log_path(task_id) def func(): @@ -34,19 +37,24 @@ class CeleryLogWebsocket(JsonWebsocketConsumer): continue self.send_json({'message': '\r\n'}) try: - task_log_f = open(log_path) + logger.debug('Task log path: {}'.format(log_path)) + task_log_f = open(log_path, 'rb') break except OSError: return + if not task_log_f: + return + while not self.disconnected: data = task_log_f.readline() + if data: - data = data.replace('\n', '\r\n') - self.send_json({'message': data, 'task': task_id}) - if data.startswith('Task') and data.find('succeeded'): + data = data.replace(b'\n', b'\r\n') + self.send_json({'message': data.decode(errors='ignore'), 'task': task_id}) + if data.startswith(b'Task') and data.find(b'succeeded'): break - time.sleep(0.2) + time.sleep(0.1) task_log_f.close() thread = threading.Thread(target=func) thread.start() From a2f8f433215ed701579e6d2b7c3768846bc5f5c9 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 22 Oct 2019 11:31:15 +0800 Subject: [PATCH 05/10] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E6=9F=A5?= =?UTF-8?q?=E7=9C=8Bauth=20info=E5=8F=AF=E4=BB=A5=E5=85=B3=E9=97=ADmfa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset_user.py | 15 +++++++++++++-- apps/assets/backends/manager.py | 4 ++-- .../assets/templates/assets/_asset_user_list.html | 5 +++++ apps/jumpserver/conf.py | 1 + apps/jumpserver/context_processor.py | 1 + 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/apps/assets/api/asset_user.py b/apps/assets/api/asset_user.py index d3824f676..a07544e57 100644 --- a/apps/assets/api/asset_user.py +++ b/apps/assets/api/asset_user.py @@ -7,6 +7,7 @@ from rest_framework import filters from rest_framework_bulk import BulkModelViewSet from django.shortcuts import get_object_or_404 from django.http import Http404 +from django.conf import settings from common.permissions import IsOrgAdminOrAppUser, NeedMFAVerify from common.utils import get_object_or_none, get_logger @@ -110,12 +111,22 @@ class AssetUserViewSet(CommonApiMixin, BulkModelViewSet): class AssetUserExportViewSet(AssetUserViewSet): serializer_class = serializers.AssetUserExportSerializer http_method_names = ['get'] - permission_classes = [IsOrgAdminOrAppUser, NeedMFAVerify] + permission_classes = [IsOrgAdminOrAppUser] + + def get_permissions(self): + if settings.CONFIG.SECURITY_VIEW_AUTH_NEED_MFA: + self.permission_classes = [IsOrgAdminOrAppUser, NeedMFAVerify] + return super().get_permissions() class AssetUserAuthInfoApi(generics.RetrieveAPIView): serializer_class = serializers.AssetUserAuthInfoSerializer - permission_classes = [IsOrgAdminOrAppUser, NeedMFAVerify] + permission_classes = [IsOrgAdminOrAppUser] + + def get_permissions(self): + if settings.CONFIG.SECURITY_VIEW_AUTH_NEED_MFA: + self.permission_classes = [IsOrgAdminOrAppUser, NeedMFAVerify] + return super().get_permissions() def get_object(self): query_params = self.request.query_params diff --git a/apps/assets/backends/manager.py b/apps/assets/backends/manager.py index 201f19d43..75b9c38b8 100644 --- a/apps/assets/backends/manager.py +++ b/apps/assets/backends/manager.py @@ -41,8 +41,8 @@ class AssetUserManager: instances_map = {} instances = [] for name, backend in self.backends: - if name != "db" and self._prefer != name: - continue + # if name != "db": + # continue _instances = backend.filter( username=username, assets=assets, latest=latest, prefer=self._prefer, prefer_id=prefer_id, diff --git a/apps/assets/templates/assets/_asset_user_list.html b/apps/assets/templates/assets/_asset_user_list.html index a85a3056d..0d7c86be3 100644 --- a/apps/assets/templates/assets/_asset_user_list.html +++ b/apps/assets/templates/assets/_asset_user_list.html @@ -40,6 +40,7 @@ var prefer = null; var lastMFATime = "{{ request.session.MFA_VERIFY_TIME }}"; var testDatetime = "{% trans 'Test datetime: ' %}"; var mfaVerifyTTL = "{{ SECURITY_MFA_VERIFY_TTL }}"; +var mfaNeedCheck = "{{ SECURITY_VIEW_AUTH_NEED_MFA }}"; function initAssetUserTable() { var options = { @@ -112,6 +113,10 @@ $(document).ready(function(){ authAssetId = $(this).data("asset") ; authHostname = $(this).data("hostname"); authUsername = $(this).data('user'); + if (mfaNeedCheck !== 'True') { + $("#asset_user_auth_view").modal('show'); + return + } var now = new Date(); var nowTime = now.getTime() / 1000; if ( !lastMFATime || nowTime - lastMFATime > mfaVerifyTTL ) { diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 0df26d149..29dfeabbe 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -361,6 +361,7 @@ defaults = { 'TERMINAL_COMMAND_STORAGE': {}, 'SECURITY_MFA_AUTH': False, 'SECURITY_SERVICE_ACCOUNT_REGISTRATION': True, + 'SECURITY_VIEW_AUTH_NEED_MFA': True, 'SECURITY_LOGIN_LIMIT_COUNT': 7, 'SECURITY_LOGIN_LIMIT_TIME': 30, 'SECURITY_MAX_IDLE_TIME': 30, diff --git a/apps/jumpserver/context_processor.py b/apps/jumpserver/context_processor.py index 91a720fd7..0bd5186dd 100644 --- a/apps/jumpserver/context_processor.py +++ b/apps/jumpserver/context_processor.py @@ -18,6 +18,7 @@ def jumpserver_processor(request): 'COPYRIGHT': 'FIT2CLOUD 飞致云' + ' © 2014-2019', 'SECURITY_COMMAND_EXECUTION': settings.SECURITY_COMMAND_EXECUTION, 'SECURITY_MFA_VERIFY_TTL': settings.SECURITY_MFA_VERIFY_TTL, + 'SECURITY_VIEW_AUTH_NEED_MFA': settings.CONFIG.SECURITY_VIEW_AUTH_NEED_MFA, } return context From 3a10fd4160021cc0e52dcade5657947dd79b510f Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 22 Oct 2019 12:16:50 +0800 Subject: [PATCH 06/10] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9=E6=9F=A5?= =?UTF-8?q?=E7=9C=8Bauth=20info=E5=8F=AF=E4=BB=A5=E5=85=B3=E9=97=ADmfa?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/templates/assets/_asset_user_list.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/assets/templates/assets/_asset_user_list.html b/apps/assets/templates/assets/_asset_user_list.html index 0d7c86be3..3321e2578 100644 --- a/apps/assets/templates/assets/_asset_user_list.html +++ b/apps/assets/templates/assets/_asset_user_list.html @@ -40,7 +40,7 @@ var prefer = null; var lastMFATime = "{{ request.session.MFA_VERIFY_TIME }}"; var testDatetime = "{% trans 'Test datetime: ' %}"; var mfaVerifyTTL = "{{ SECURITY_MFA_VERIFY_TTL }}"; -var mfaNeedCheck = "{{ SECURITY_VIEW_AUTH_NEED_MFA }}"; +var mfaNeedCheck = "{{ SECURITY_VIEW_AUTH_NEED_MFA }}" === "True"; function initAssetUserTable() { var options = { @@ -113,7 +113,7 @@ $(document).ready(function(){ authAssetId = $(this).data("asset") ; authHostname = $(this).data("hostname"); authUsername = $(this).data('user'); - if (mfaNeedCheck !== 'True') { + if (!mfaNeedCheck){ $("#asset_user_auth_view").modal('show'); return } From 82a636956894ca651f3ff723e7d955347edb2d98 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 22 Oct 2019 15:38:49 +0800 Subject: [PATCH 07/10] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9term?= =?UTF-8?q?=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/backends/manager.py | 2 + apps/ops/templates/ops/celery_task_log.html | 5 ++- .../ops/command_execution_create.html | 44 +------------------ apps/perms/urls/api_urls.py | 18 ++++---- 4 files changed, 17 insertions(+), 52 deletions(-) diff --git a/apps/assets/backends/manager.py b/apps/assets/backends/manager.py index 75b9c38b8..ac81307df 100644 --- a/apps/assets/backends/manager.py +++ b/apps/assets/backends/manager.py @@ -67,6 +67,8 @@ class AssetUserManager: return AssetUserQuerySet(instances) def get(self, username, asset, **kwargs): + print(username) + print(asset) instances = self.filter(username, assets=[asset], **kwargs) if len(instances) == 1: return instances[0] diff --git a/apps/ops/templates/ops/celery_task_log.html b/apps/ops/templates/ops/celery_task_log.html index 8e99c356d..c7f177c6e 100644 --- a/apps/ops/templates/ops/celery_task_log.html +++ b/apps/ops/templates/ops/celery_task_log.html @@ -4,6 +4,7 @@ {% trans 'Task log' %} +