From 56519354b68a332948d05cec3c8dc321d7f7c8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AB=E5=8D=83=E6=B5=81?= <40739051+jym503558564@users.noreply.github.com> Date: Mon, 15 Apr 2019 14:37:45 +0800 Subject: [PATCH] Email reset password (#2547) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Update]更改英文登录界面标题,可两行 * [Update] 更改用户通过邮箱修改密码后,该链接就失效 * [Update]更改页面左上角logo_text图片 * [Update] 优化发送邮箱改密连接失效代码 * [Update] 优化发送邮箱改密连接失效代码(2) * [Update] 优化发送邮箱改密连接失效代码(3) * [Update] 更新interface一键恢复默认的翻译 * [Update] 更改登录失败 用户名密码错误信息的翻译 * [Update] 优化生成token并设置缓存的代码 --- apps/authentication/forms.py | 8 ++ .../templates/authentication/new_login.html | 14 +- apps/locale/zh/LC_MESSAGES/django.mo | Bin 70257 -> 71036 bytes apps/locale/zh/LC_MESSAGES/django.po | 129 ++++++++++++------ apps/users/models/user.py | 52 ++++--- apps/users/views/login.py | 10 +- 6 files changed, 140 insertions(+), 73 deletions(-) diff --git a/apps/authentication/forms.py b/apps/authentication/forms.py index c722629db..61b073e21 100644 --- a/apps/authentication/forms.py +++ b/apps/authentication/forms.py @@ -14,6 +14,14 @@ class UserLoginForm(AuthenticationForm): max_length=128, strip=False ) + error_messages = { + 'invalid_login': _( + "Please enter a correct username and password. Note that both " + "fields may be case-sensitive." + ), + 'inactive': _("This account is inactive."), + } + def confirm_login_allowed(self, user): if not user.is_staff: raise forms.ValidationError( diff --git a/apps/authentication/templates/authentication/new_login.html b/apps/authentication/templates/authentication/new_login.html index 9bd0fe581..c644e6fad 100644 --- a/apps/authentication/templates/authentication/new_login.html +++ b/apps/authentication/templates/authentication/new_login.html @@ -52,7 +52,7 @@ - +
@@ -60,19 +60,19 @@
-
- {{ JMS_TITLE }} +
+ {{ JMS_TITLE }}
-
+
{% trans 'Welcome back, please enter username and password to login' %}
-
+
{% csrf_token %} -
+
{% if block_login %}

{% trans 'Log in frequently and try again later' %}

{% elif password_expired %} @@ -92,7 +92,7 @@
-
+
{{ form.captcha }}
diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 1de7cffcd887449575ee499e7ca415e4d32357bd..6dcc86b5ae0b4d544a8e9774cd17af9f2b670f34 100644 GIT binary patch delta 21418 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 delta 20692 zcmZYH1)Nn?8}IQwFbp{iFw#Ra14DPq&><};-QCi4=#ZA~mIifbX#ok5kdRbB=?*1C z?(curGxz0l@BVz2-}O9e?X}ikd+&1&===V=F7VmPK;QLbfwMf0y|Fzn3=^gIy!U~g z_issMJ@08P&zp?Ta1i=xd)`<07Kh`QI-d7yfae8$?s*6Ca$V0$8_V++)hAE;&W4_s z3@118y!f~jljAxJVmNO+`&KRIZcA+Qcm&c2my_B@RJW=w-n$%z>X^WsHkW zF)_A9E&NMNgg$c;YMgnfaW8XChHs zS_b1`T}+EjQCm9zwV)~1J|8m^ufQ-og4)qr=+l+lrIG}nqOLHYx#z{f6qo?R%xsvH zxB!M=1#FG=P*=1aBk(ZlmOR8Bn4$%{gJY4$#CwZ%u|`YozbeaGx`tO+l(GSO>mH+4>a}yPRRYukA~7EpN40lG4cy1t2U~t3#vwlowL=TcwW$8vojz|b z6G zwHTY{&pSv(0~|3=o0rW$&Bv(M?KNtkfDY~hC>aJ3SI4+m7j+>`Q2o20`u9Oy=ork5 zOEER`dp}aq0PjY}CR||g8jMH01GRtys1KxLsEMwk7W%^413J42 zehTf z^$+Ue-mc`Royp&Y{nwS1C!vR`Hpa(}sGaGJx@Y52SGEFmWxG%V9z~sh5w+kyF#-OA zx}aEH-9#xdA#o&X+`<-D^HI@24N*^NdviEy!1<^XH=(OpcZri^=#cn-HNvui~-&K^ZL9HD(aXPHE~YV`(6TdLKN=CN~nQj_iz&@G*h7# z5RRHC59<7KsD)NWT}U0wh)pp)4#m&({x78Rl*Ap>K)>~L1KdC@;5KT-k5Ci5L+w~d zFV{aURwmAhIk2nc=b#q66!rS9K|K?jFcN>nV7>p3sA!^hm;__>b}J4=4UitSun03R zW+yI&A=nC&VK3yv(i@Gr@IL0jlwZ1?t%Q1r>!TLb6@9vr-c&TfFw}(OPz#!hiE*~I zuR@);3Ds{4s^4zZ4*iIFCeC0+yl(La)cA?|xcR)2|X-rP!o5< zQ0#~LT=)vL#miAAZpFN~3pL?=)I$G7jTf(<>lcn1H;2WAP~#UzEvTH2ing>Cs$+eO zz!n$_$C?vRpY4;(%~*~2ENUmx_je1bg_($b*Z`MdReX)QpmGD;EogvRfUg-9-Q&)v zD;S77aSRT^sDb?C#$BkD|At!d4b)EDvG^fsN1mhZZDvkZ{~W0C3!*NtoLL>&IiJ^n zing{R>V(1OXw*HOjD>IkYJk(Ig(Wcm}mo_fQLbih3wN zpca>JVdD`?&w9sgxz5*Qg1m!fvRE$6_Q-MNP01wa}BOop_1i7!qb7cjT2PV^?tRaS>50o? z25e~#$N0ocQRlBiUD#&S4({+-!(r6c9Y?+QH&G}4g<<#vbz-8C?h2Em?qLLK=klYr zv^;8}7S`Stb;UhUJJJ``e+X))d{d~Tp|S*H;V#s}xCb@CVbqqNMy>cC)D8rWa$BAf zwNnwOEiH-aR}BkdBh+}4P`6+v>Oz)cY`y<$si?z7)WBO^gLf3QfS*w(Ttp502kP~E zgu2pqs4MhFyDJPr^$$ipd?`>LOyQ{W>Z5L58^7HD{#3N}6H(8=3e?u@Hcz6i>^iF7 zW7HM~jd8DGDzhYN!seIvx$2v2iI!0m~EMb;G zT|p((f*Yfrl`m0OJ`{CJ$D$tIWvHFqj!}3Vvtfd9?0;4&1*oWFLo9&ZP*<=N1Mw7U z;B)3R)K=a`-P4yC7rpWB3ge;rr!q647MKJ5A3Ug?h#JrR*Mzl5Xsbq|CY*_SsODic z+=N=_Th!~7VS>BYQK)C4l35qEQ!Oz*w#OjsiQ1|DsD(~Ly{>a7u>acP?Ig5iM^OXZ zLY;UIb;48B0$*D`!B_5HCq?Z*M$``GLOpEdEZ-aTObo;9I2kqWHf)T0eAXe=MAtDJ zY5_$sK9)l5L?zVg)C4u)RMeNxV$6kGQ6FSCE$>Zow;(0zR%Jv@oCh_2VT*kwsc6f~ zSwm%vOI-bK?co)^b*i^SO6;S6j#1L$Y z+VMV^iut{PR4U-tsLz3ms1KSKsD&k*<{rY-s0lNf`A`pC6oz1Z)U(pg+6SQ)HUYJx zi%<{qH|8evsbL!xJrw&;D?g0c@C<5;-=JO}Z@Sx|)Tn$`)cH9rE@YNO?PNLBgf&nX zQs3e>s0-;bo&C>FWe^E%$qMVZ2K7*FGmoKO&#S1N`3JS7Az!w}x|8>Gj5})BVR2(qFEg%$M5J#XUNHfz-oD==`7_|cxP)~gg ziyKKdwdgh;&ar%-Yhq9Qq*~A zQ5TR0Gh!Lk&bC6`()O00V)`~y(Fe(C)IGj~`oZDNb`z#EbEEQ~Vqt8InrIqk#^v}4 z9!A~L%a{pc&v6rnV<+MosE2(!(%I2KAI)!lrl|HBkALuKjb=)7}_0aa+{0&=WPzNYqYEz~nd+)8IPPIEPXF z&#mPCYogmE^z^dOAcxEN=RyYgVv6=g^DFNp21Eat@3 z*8VGM-0P@u?xUWiH>hXJ7rfRb%Ay9WkNRL~iMpa*sLzE_s4HHG8gPTfJ5c?PVimlE z@iFr{x3FBO1(iT8pgm^6zDPfxH;;<8b_MF5ZbMCc2DQ>#7!UtJZN0bNJtL_w4q;K$ zPJN1+pf0L^Yt(|fp!yBQARK|($?@p_{+~ug6D>iV7>#;(c4I<3hPtBjsD=KHys6%E z{0?VsaJR71Mt5E{vk_{-cBs#ju9yeE!Ay7_tLpv#hf0zF?%gJyXyVT|^MK$nEQ<-g zb?<9+EI?cvwS}XwDy~ND+%wcpBw|(CiOi@4e&)3z>$xkmZ&?h&hN)n15qI z;!JzpcR_vBjt$w%a???nLt;2?#fn&DpWBfk7)CtST!ANv_oJSXDf^uZP+PqQwcyRD z_JgSWDT^*iFp=p zHg}u8V^nnF1xwtv_=Ux>54s7Gm?_QlW;kl0xlju&VwOkkL~XMTwj=I`>VFlp>T$VE zB|C|PKk^e93t>x~gi-j&%zenk-OP=s*Xj{!2eKV@1Lr}-#V{L2nH?-Y6-$txjp_Bc zo}m&-;wkD10*|;jsTq#Ju$5=eq;_pxkJ7k_gE$BLGoX6->hv1{`%FZ=`MRiy8(Y2`W+EPB@j}!@YcU9qny0M&!cq2L4Y#b}zBN2E|Fe9; zV{T!|Py?nwEwHdz4z-Y4m;hU2JnV*g`umxaQ0Fbj__+BP`>(`K5*pwLYD+I!{M_O= z$K3+bV|>~(o4L#)W*PG{)P>cvxCs^_ZfE)VmS5(hqI&Y(J$`Pofe0~NPKEwCGE zD~FmhPzzj(THtO>guhw-FNLQS;U;%(Nx-|{ETbAGx1SE!Wagqzlo{uj5xaMTqRFe_TVk;Uy$6AnQC zLQp#~*V?zBuJkAKoO#3AA1l`TA8^WbOpKZ^t;KmPE@^R1vkB@U?P!iboj2dwH)06! zF4O{#V_ZCE`K#tb^uPcAQc=hFr`^_tqE?>9%w`rc%c3T%X|}R_AJoD|SUlfcZEiu` zngbReJ#Fv*c@n`iT*VN)Zyn!S$AB}oLuOhtJ8HnfW+|LUT;Aeqs0;bid}jIoQ1iq& z%l>PCI;qrPmq<9u9$8o2zg?)=(jLsY&wYJx5n54QI4s4t(Xm<^Bn ztl_!&#`Mm)Up8@3AE~KP1D8ZCxC$o0TBuvs((;{A{d!qE46_iAvHV(8|7}@;GoTg_Y34JFq8_%=7B@r<+}!Mf+TsD22bWs@lzA0H^!I|sfy(rp%%~rQ(=|s4Jde?!acmcd!gryyP5e1|$O=~ZVcGlLm{WogfSmHpSiJ*;5} zDjsF=G;@yS7n|!Xzr);zTG$aRgcmHI@R}PhnVA8#uw1COqTn_5UlTU8hPJ3H?}8I? z7}moC*WLGj3)I%PF}tIl@`0#reU`su`P)8Ayunm-2>RU(lmQh- zpazVxe09{bQWtf_&CG6?oOq}?12yql)Hu7%^Ok>%8rK)_hpQw;T|rt*gPAS<6xFeU zSqJrb(cI#3s0GbL{p4DV>c86DVjeJmL49ytar(T6*6<#+;siI`YnBf6W3&qDgz9E9 z)P&tpJ1_wC-7y}E;A~X?lNgTIEe^ct7M>inz|t71_rDqyU3m+$y>;kj@gQ>qYJua; z1?DEyLJpW`P~+XO_PeNC^A2?@lHPLWkj(Fuw?tFa%KD-P7>T;l3FZuQ5vCx&8e`*L z)OiOnE1t6WC2GL|f4T*Jf?7aU^HcO`q6SnnKr^#5D&HS9z%bO7PPceDs{dB=pm_=- z$X~TM_FwM&B&Z$AVsSy#`IY{%_rETQC=xAE6EC$6t5G|!#p1ozeggH8d)DH|*8a+j zb=yr4Vuqo{jWqL_MQ^kJYA8)YS6UIXU?bEDhnN$reKzV!)>^#N+J8oE?Inw!V<_)Jz5`4p%N z%wlm7bH?dBf&Tvnw6=9Xy|po0#p) z9;gKkL@j9SJ)Qww$vkUVit&gyVtm|Y`TeMcoV55M>by6ofxP?fzabCB?1b$xGfu_$ z_&sXk-R3dW`4{f<45-63OWZ--%f}YSec&cejG8F7#br=C(E>G453?U?qM;UlW$|=# zG3vbam>+-eS>loT9<_krhi>2q97UWPHSl-lUev@VP#16(HSkr`C*ea(gjpWBh3CT@ z#N|=rcSk*pzHwAE&?3|cD=q%c++prBkC-RTbExyKn0L)rW~|4qJp{FbVP;;J_j%>0 z=zF^sM&f8pfSb&n<{|SG>Pj!8uKYggVSH(EnkO!w)y#vsz+#vVqfiTO=9l~5*%JLx zD;#a{9E(?4yd6VmKZF|aoaL{WcgZ zj+*Ev)IIwJJK`OSYd>@OPNrkDQe=47VkGtqW{l;mo0I}e2E$`;JF(x zA!@*67zZ<;Zc#Yq!hF`=47JeC7LP(LXqq_(V-qj7c=>bQe@(R364B-^^8jk%qo}9# zJO<(e%Rj|r#P7`{FWdsMn59tX*Ed_E`u8wLzOe6rS(aF69XF${WVglVt^Fo8B>&3d z8ZX^|Es<|r?@NmtzH$?HHv5~S&FSW1pHZAO*Yxj9cU%QD)piXFp#c?dw$Ni`YQoQm1ducBVHYDDKsW91F zXHJ|=Tmd!V6)b`eF*jy;=boWDn1Z+i=G1S%VN|{(u@2K>`hVSkB~VvX7j+BTqfYFH zRd6y^#0#j0IPAUK;t14&b7K!IfroJ&&c&Ypxt)vufj5Wwy$C90u_2bjd8jMDin^i# zUV#4(BFC^bar%G&?+YA(jqwVW#3Hc*+%3RQh{s@3oNsPGJp+4D3p|Ye_y4RVezy(} zQSbQ+)cg9z^6ydaePC=iPzY*=Qs5wr#Duug+P_8Z%y#nts{aXVzaBflz5joa&=x;2 zKcH3^66j6{L&bSf{YqgNR=4&}sE29@s^0=kj%!f2bg$(vn|I8Yfj)OaK%4;o)1DYL zKz_5dS3QsD(5{t-Ld;UmtTcYRhL@ybjfGm&J$7b6A}GpUAvEFMWKsfSjoJv>0mO_NWi0 ze%3zM@~co2ZMFD>c?C7$1JpuaVLFVLz>Ob)$`?e9UkQWs{x_ha6Pux)_6`|Ir;^kf+<^L^2}tTz-V}9(?NR3qM18W2we}3j0{nlHio{UzHBejL z3K`yi)Q-h};2evM8Av7OC_;TMgiQSV{mAdIjsvZI4bCQi1}j?I8f?xs z+^{~D_QqL!oBlCJA3lG)`!t-O9pS*`j{R~ zUEd>m{kY}+|8}gjo!^1B+?2Y+t!W=i{hHeJV9c~m?>LDsD=)vrnW@Jd5tdV&fs=<2 zU$RAXAQwU|<`_&{a>^%^f9P`#Ga$d}yz$iMQKE_KQhY->F)@h;lp8j}eXM8$-ijF& zS8+lnY)9XA)L&B{LA?uor{gP1bM?n^gmAVeSntX}*yz`dGOoz54 z^U`SuCLrb;^Zy<#sa>IMz4bp!eFuG(kk3K=e7E{rY7>j;1$QY}?r}Hz)b=S@7iN$DJfKxc<67_Y+FDn1>J@LPk?d0@3 zK%e_Mx>ItJZ$iF?&LQ?Cq*9)Qj;#)_81Y;tyhOZ&`cL>H{rXUJOm%o8EsiFxO~1d1 z|D)ujUdP(hbs}ROri78x*LKXYMgJR|=|r(OAtxQCSj*;*PX3u(N=gyROY+6&r=tyJ zBj@QzYmTB#A4G-h{6*B8QeTdFtWN{fhglyyrTecVfKDqYt4S7TkZu(Hzam_utsMEn z)VJ8go6MR16Zu#0xQsqAN5PnWoTDQaZTz0`K2X1HZOW&mp514i))Ca9v{DNPKMTA{ zl!tbYvmd4!zow}=0@WyYa@YBKz6^dJ41qayX_ z|IOv|W)YkwdBl?Wu#Qc%mij%)BToN=K7Zn8l%mwL&?h}5Htm}zg~<=c@9kVd|FMOC z_9NGfwlti#(emkuOU35?w;&ORKu2dfuEz$HrPPaXLRo85duHlm$fu`1h_-W-?}(!* zb0`6tfYOQj7pUVqOvHIf$bC!E&pI7PC=L1j=|4(-G|A_5($Sh+0QJSV6Mv+yzIL}! z*Y5-!Kak5!sZV_wUhrq#KL*fGzXP^&{sY=_5r0a3IrSRUd!zsPr|v((Nt7mNM5hh- zH`x@F5!5eZ5B!WaE&4hJQMys|X9E3wVJP*OqaT$L7APIexn(#n=E&hHKL1~Z9Hhrv z$^<&>rTj``GfZm(zM}q()i+b$Pdz0im5sKL!F7C2+kcdC)W4!#zkXtl>Ev6`Zyu#T z$>GF{b^SZ2?4xsK8{{i>AXk!3|B#=Dt0*VQ@ypA9e1dza6{7E1`joVD)p*T=%eGR!}|dz)BdwQ|94SRTL-oGqV%B5r@UdJqqLQv=r^2>pUK_9ER@y^(ugw6 z7RIk?Zvy#n`hSjFEnkYbEhQd(e?c9asr%~kkNYGZQuL?V!IZV+a;gW%C)DFpZqPoA zxGCi>gZ82fAg2o`M(!rY9A~IcA}Bi<$EW05QvM{@)AIWJXKy#j z#+-bDo>#4*JDwuWLq3;{u$sD#NOK2$3Q@m;(y?^*l0Y?IJw+p?-#A`WeDdkt{wXv4VNjX4!d2CD35rKo4bO=R% zJkLdYO>&PYzA+@GQGO*@LP+JQk0UBTnTc!7@!5VAbvs7(UV+B>z@rXl3PLU z7&fBl=wR)tccFw5&!*2SU4JzOiXu6Ny{i2M}*2lsy>K^YnoQgkFGeoJF3NZd7RQ%{8_DEb>z9ba-T*U#@e zlGQk27WI}SS5kB=#)7oP9BZi8q@ND`IdMGoTjZ7z$H(Qw)yS769!cp!y&?JZ7;~f{ zj{0Bh^A?fNv5@3S2Do5xQtG3~C&zlUZL^d9BKJ4-=hm+P?Hj4rr!=H(Jf%Ikp7g0s zJ)F{&I0(Nb*NyrQ6#WU>fBkzoal1co|0qv9;G_7WO&pt(_=EBPcT}hUPvn26WT*8R zv5uz>FB5Tf+P)#y&%JV3&c>Oe{hvaI&X^VJ(P1+6_LQS^T0q=~dL^7l8Ehw#@|MuQ z1Eu~)xhUeS7N4U}8|rz;=}5!*FNuGlzKz^p)P2JV`q~LYF_2D`u>w}4({b8EsfS=Y zJdAlMIu6nP1?3cF7w4>^{ZE`joEm?l&w7kG_EGi)+9bm(Q&}? z-{W`WCXzc!xu!;rPpv(Q^M=|v$|oT|m3Y3jPr__A@owskC`E|N==uLZ(3{SYHb6bh zYxNnljb*?+6#n+aD@*x*kAVzS`=ex2;uXY=ap*_+Fk&6|7$Xt&vXnpc^*N2oY?2*q z@Gr@Aq_n5hB6pXQ#^Xt19XF|0;he5`oU)1B9Q+>V;W+v|rVOAyiheqpQ=dV-A>{~l z9nGlcQKdMQ5m><{m_mnA#PKY?OuU{x4Pwn$RxwnMY&emQ{-S#A>5Et9&!kMHKAECp17#8QW#oN>2!>P1NFo__BmTfZE39)0 zat*BhJ8fBsV~)7gR}<(WX3^(7Mv^;=s~KZ7xt)~!#4*PP;!q2+x>I?ZNfw|yr^FmP z8DI~kBZ(|{kn`$`JqWn6a^9+!^0i z3{=r&tfXXOq;ZrNwwms^mi#f!+-kFYZEa65hvhz}{WszsloU2gu=Uf7d#s=8I-Xdc zYSar*FER3?4h7VM_+QC!h%$jr*(eXF*P#5u;J*`J4~X7WJ0xfHgTbv5MXw(JYhd&r zlOF^|U;Vmh!Wm;0r=C%1@rUT4OAe)oTQp<-q9qCzjIOfnefH=MzaLH*-TT4L!016w X&jv;}c(pzLjC3DvZp{`@Kl%Rwe\n" "Language-Team: Jumpserver team\n" @@ -172,7 +172,7 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC" #: settings/templates/settings/terminal_setting.html:102 terminal/models.py:22 #: terminal/models.py:241 terminal/templates/terminal/terminal_detail.html:43 #: terminal/templates/terminal/terminal_list.html:29 users/models/group.py:14 -#: users/models/user.py:54 users/templates/users/_select_user_modal.html:13 +#: users/models/user.py:61 users/templates/users/_select_user_modal.html:13 #: users/templates/users/user_detail.html:63 #: users/templates/users/user_group_detail.html:55 #: users/templates/users/user_group_list.html:12 @@ -208,7 +208,7 @@ msgstr "名称" #: ops/models/adhoc.py:164 perms/templates/perms/asset_permission_list.html:74 #: perms/templates/perms/asset_permission_user.html:55 #: settings/templates/settings/_ldap_list_users_modal.html:37 users/forms.py:13 -#: users/models/user.py:52 users/templates/users/_select_user_modal.html:14 +#: users/models/user.py:59 users/templates/users/_select_user_modal.html:14 #: users/templates/users/user_detail.html:67 #: users/templates/users/user_list.html:24 #: users/templates/users/user_profile.html:47 @@ -246,7 +246,7 @@ msgid "Password" msgstr "密码" #: assets/forms/user.py:29 assets/serializers/asset_user.py:27 -#: users/models/user.py:81 +#: users/models/user.py:88 msgid "Private key" msgstr "ssh私钥" @@ -437,7 +437,7 @@ msgstr "标签管理" #: assets/templates/assets/system_user_detail.html:100 #: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:15 perms/models.py:36 #: perms/models.py:89 perms/templates/perms/asset_permission_detail.html:98 -#: users/models/user.py:95 users/templates/users/user_detail.html:111 +#: users/models/user.py:102 users/templates/users/user_detail.html:111 #: xpack/plugins/change_auth_plan/models.py:103 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113 #: xpack/plugins/cloud/models.py:55 xpack/plugins/cloud/models.py:127 @@ -482,7 +482,7 @@ msgstr "创建日期" #: orgs/models.py:17 perms/models.py:38 perms/models.py:91 #: perms/templates/perms/asset_permission_detail.html:102 settings/models.py:34 #: terminal/models.py:32 terminal/templates/terminal/terminal_detail.html:63 -#: users/models/group.py:15 users/models/user.py:87 +#: users/models/group.py:15 users/models/user.py:94 #: users/templates/users/user_detail.html:127 #: users/templates/users/user_group_detail.html:67 #: users/templates/users/user_group_list.html:14 @@ -554,7 +554,7 @@ msgstr "带宽" msgid "Contact" msgstr "联系人" -#: assets/models/cluster.py:22 users/models/user.py:73 +#: assets/models/cluster.py:22 users/models/user.py:80 #: users/templates/users/user_detail.html:76 msgid "Phone" msgstr "手机" @@ -580,7 +580,7 @@ msgid "Default" msgstr "默认" #: assets/models/cluster.py:36 assets/models/label.py:14 -#: users/models/user.py:457 +#: users/models/user.py:473 msgid "System" msgstr "系统" @@ -728,7 +728,7 @@ msgstr "默认资产组" #: terminal/templates/terminal/command_list.html:72 #: terminal/templates/terminal/session_list.html:33 #: terminal/templates/terminal/session_list.html:71 users/forms.py:283 -#: users/models/user.py:32 users/models/user.py:445 +#: users/models/user.py:36 users/models/user.py:461 #: users/templates/users/user_group_detail.html:78 #: users/templates/users/user_group_list.html:13 users/views/user.py:386 #: xpack/plugins/orgs/forms.py:26 @@ -827,7 +827,7 @@ msgid "%(value)s is not an even number" msgstr "%(value)s is not an even number" #: assets/serializers/asset_user.py:23 users/forms.py:230 -#: users/models/user.py:84 users/templates/users/first_login.html:42 +#: users/models/user.py:91 users/templates/users/first_login.html:42 #: users/templates/users/user_password_update.html:46 #: users/templates/users/user_profile.html:68 #: users/templates/users/user_profile_update.html:43 @@ -1026,7 +1026,7 @@ msgstr "其它" #: settings/templates/settings/command_storage_create.html:79 #: settings/templates/settings/email_setting.html:62 #: settings/templates/settings/ldap_setting.html:61 -#: settings/templates/settings/replay_storage_create.html:151 +#: settings/templates/settings/replay_storage_create.html:152 #: settings/templates/settings/security_setting.html:70 #: settings/templates/settings/terminal_setting.html:68 #: terminal/templates/terminal/terminal_update.html:45 @@ -1062,7 +1062,7 @@ msgstr "重置" #: settings/templates/settings/command_storage_create.html:80 #: settings/templates/settings/email_setting.html:63 #: settings/templates/settings/ldap_setting.html:64 -#: settings/templates/settings/replay_storage_create.html:152 +#: settings/templates/settings/replay_storage_create.html:153 #: settings/templates/settings/security_setting.html:71 #: settings/templates/settings/terminal_setting.html:70 #: terminal/templates/terminal/command_list.html:103 @@ -1076,7 +1076,7 @@ msgstr "重置" #: users/templates/users/user_profile_update.html:64 #: users/templates/users/user_pubkey_update.html:77 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:72 -#: xpack/plugins/interface/templates/interface/interface.html:73 +#: xpack/plugins/interface/templates/interface/interface.html:74 msgid "Submit" msgstr "提交" @@ -1161,7 +1161,7 @@ msgstr "更新认证" #: assets/templates/assets/system_user_asset.html:350 #: users/templates/users/user_detail.html:307 #: users/templates/users/user_detail.html:334 -#: xpack/plugins/interface/views.py:31 +#: xpack/plugins/interface/views.py:34 msgid "Update successfully!" msgstr "更新成功" @@ -1271,6 +1271,7 @@ msgstr "选择节点" #: users/templates/users/user_profile.html:238 #: xpack/plugins/cloud/templates/cloud/account_create_update.html:34 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create.html:36 +#: xpack/plugins/interface/templates/interface/interface.html:103 #: xpack/plugins/orgs/templates/orgs/org_create_update.html:33 msgid "Confirm" msgstr "确认" @@ -1500,6 +1501,7 @@ msgstr "重命名失败,不能更改root节点的名称" #: users/templates/users/user_detail.html:476 #: users/templates/users/user_group_list.html:82 #: users/templates/users/user_list.html:202 +#: xpack/plugins/interface/templates/interface/interface.html:97 msgid "Are you sure?" msgstr "你确认吗?" @@ -1516,6 +1518,7 @@ msgstr "删除选择资产" #: users/templates/users/user_group_create_update.html:31 #: users/templates/users/user_group_list.html:86 #: users/templates/users/user_list.html:206 +#: xpack/plugins/interface/templates/interface/interface.html:101 #: xpack/plugins/orgs/templates/orgs/org_create_update.html:32 msgid "Cancel" msgstr "取消" @@ -1938,7 +1941,7 @@ msgid "User agent" msgstr "Agent" #: audits/models.py:99 audits/templates/audits/login_log_list.html:56 -#: users/forms.py:142 users/models/user.py:76 +#: users/forms.py:142 users/models/user.py:83 #: users/templates/users/first_login.html:45 msgid "MFA" msgstr "MFA" @@ -2125,7 +2128,17 @@ msgstr "" msgid "Invalid token or cache refreshed." msgstr "" -#: authentication/forms.py:29 users/forms.py:21 +#: authentication/forms.py:19 +msgid "" +"Please enter a correct username and password. Note that both fields may be " +"case-sensitive." +msgstr "请输入正确的用户名和密码. 注意它们是区分大小写." + +#: authentication/forms.py:22 +msgid "This account is inactive." +msgstr "此账户无效" + +#: authentication/forms.py:37 users/forms.py:21 msgid "MFA code" msgstr "MFA 验证码" @@ -2687,7 +2700,7 @@ msgstr "组织管理" #: perms/templates/perms/asset_permission_list.html:55 #: perms/templates/perms/asset_permission_list.html:75 #: perms/templates/perms/asset_permission_list.html:122 templates/_nav.html:14 -#: users/forms.py:253 users/models/group.py:26 users/models/user.py:60 +#: users/forms.py:253 users/models/group.py:26 users/models/user.py:67 #: users/templates/users/_select_user_modal.html:16 #: users/templates/users/user_detail.html:213 #: users/templates/users/user_list.html:26 @@ -2705,7 +2718,7 @@ msgstr "资产和节点至少选一个" #: perms/models.py:35 perms/models.py:88 #: perms/templates/perms/asset_permission_detail.html:90 -#: users/models/user.py:92 users/templates/users/user_detail.html:107 +#: users/models/user.py:99 users/templates/users/user_detail.html:107 #: users/templates/users/user_profile.html:116 msgid "Date expired" msgstr "失效日期" @@ -3123,7 +3136,7 @@ msgid "Please submit the LDAP configuration before import" msgstr "请先提交LDAP配置再进行导入" #: settings/templates/settings/_ldap_list_users_modal.html:39 -#: users/models/user.py:56 users/templates/users/user_detail.html:71 +#: users/models/user.py:63 users/templates/users/user_detail.html:71 #: users/templates/users/user_profile.html:59 msgid "Email" msgstr "邮件" @@ -3431,7 +3444,7 @@ msgstr "" #: templates/_nav.html:10 users/views/group.py:27 users/views/group.py:43 #: users/views/group.py:59 users/views/group.py:75 users/views/group.py:91 -#: users/views/login.py:151 users/views/user.py:68 users/views/user.py:83 +#: users/views/login.py:153 users/views/user.py:68 users/views/user.py:83 #: users/views/user.py:113 users/views/user.py:194 users/views/user.py:355 #: users/views/user.py:405 users/views/user.py:445 msgid "Users" @@ -3871,7 +3884,7 @@ msgstr "你可以使用ssh客户端工具连接终端" msgid "Could not reset self otp, use profile reset instead" msgstr "不能再该页面重置MFA, 请去个人信息页面重置" -#: users/forms.py:32 users/models/user.py:64 +#: users/forms.py:32 users/models/user.py:71 #: users/templates/users/_select_user_modal.html:15 #: users/templates/users/user_detail.html:87 #: users/templates/users/user_list.html:25 @@ -3964,53 +3977,53 @@ msgstr "复制你的公钥到这里" msgid "Select users" msgstr "选择用户" -#: users/models/user.py:31 users/models/user.py:453 +#: users/models/user.py:35 users/models/user.py:469 msgid "Administrator" msgstr "管理员" -#: users/models/user.py:33 +#: users/models/user.py:37 msgid "Application" msgstr "应用程序" -#: users/models/user.py:36 users/templates/users/user_profile.html:92 +#: users/models/user.py:40 users/templates/users/user_profile.html:92 #: users/templates/users/user_profile.html:159 #: users/templates/users/user_profile.html:162 msgid "Disable" msgstr "禁用" -#: users/models/user.py:37 users/templates/users/user_profile.html:90 +#: users/models/user.py:41 users/templates/users/user_profile.html:90 #: users/templates/users/user_profile.html:166 msgid "Enable" msgstr "启用" -#: users/models/user.py:38 users/templates/users/user_profile.html:88 +#: users/models/user.py:42 users/templates/users/user_profile.html:88 msgid "Force enable" msgstr "强制启用" -#: users/models/user.py:67 +#: users/models/user.py:74 msgid "Avatar" msgstr "头像" -#: users/models/user.py:70 users/templates/users/user_detail.html:82 +#: users/models/user.py:77 users/templates/users/user_detail.html:82 msgid "Wechat" msgstr "微信" -#: users/models/user.py:99 users/templates/users/user_detail.html:103 +#: users/models/user.py:106 users/templates/users/user_detail.html:103 #: users/templates/users/user_list.html:27 #: users/templates/users/user_profile.html:100 msgid "Source" msgstr "用户来源" -#: users/models/user.py:103 +#: users/models/user.py:110 msgid "Date password last updated" msgstr "最后更新密码日期" -#: users/models/user.py:129 users/templates/users/user_update.html:22 -#: users/views/login.py:45 users/views/login.py:104 users/views/user.py:418 +#: users/models/user.py:136 users/templates/users/user_update.html:22 +#: users/views/login.py:46 users/views/login.py:107 users/views/user.py:418 msgid "User auth from {}, go there change password" msgstr "用户认证源来自 {}, 请去相应系统修改密码" -#: users/models/user.py:456 +#: users/models/user.py:472 msgid "Administrator is the super user of system" msgstr "Administrator是初始的超级管理员" @@ -4658,40 +4671,40 @@ msgstr "更新用户组" msgid "User group granted asset" msgstr "用户组授权资产" -#: users/views/login.py:42 +#: users/views/login.py:43 msgid "Email address invalid, please input again" msgstr "邮箱地址错误,重新输入" -#: users/views/login.py:58 +#: users/views/login.py:59 msgid "Send reset password message" msgstr "发送重置密码邮件" -#: users/views/login.py:59 +#: users/views/login.py:60 msgid "Send reset password mail success, login your mail box and follow it " msgstr "" "发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)" -#: users/views/login.py:72 +#: users/views/login.py:73 msgid "Reset password success" msgstr "重置密码成功" -#: users/views/login.py:73 +#: users/views/login.py:74 msgid "Reset password success, return to login page" msgstr "重置密码成功,返回到登录页面" -#: users/views/login.py:88 users/views/login.py:107 +#: users/views/login.py:89 users/views/login.py:105 msgid "Token invalid or expired" msgstr "Token错误或失效" -#: users/views/login.py:100 +#: users/views/login.py:101 msgid "Password not same" msgstr "密码不一致" -#: users/views/login.py:113 users/views/user.py:128 users/views/user.py:428 +#: users/views/login.py:114 users/views/user.py:128 users/views/user.py:428 msgid "* Your password does not meet the requirements" msgstr "* 您的密码不符合要求" -#: users/views/login.py:151 +#: users/views/login.py:153 msgid "First login" msgstr "首次登录" @@ -5217,14 +5230,40 @@ msgid "Interface settings" msgstr "界面设置" #: xpack/plugins/interface/templates/interface/interface.html:15 -#: xpack/plugins/interface/views.py:21 +#: xpack/plugins/interface/views.py:24 msgid "Interface setting" msgstr "界面设置" -#: xpack/plugins/interface/views.py:20 +#: xpack/plugins/interface/templates/interface/interface.html:73 +#: xpack/plugins/interface/templates/interface/interface.html:108 +#: xpack/plugins/interface/templates/interface/interface.html:115 +msgid "Restore Default" +msgstr "恢复默认" + +#: xpack/plugins/interface/templates/interface/interface.html:98 +msgid "This will restore default Settings of the interface !!!" +msgstr "您确定要恢复默认初始化吗?" + +#: xpack/plugins/interface/templates/interface/interface.html:107 +msgid "Restore default successfully." +msgstr "恢复默认成功!" + +#: xpack/plugins/interface/templates/interface/interface.html:114 +msgid "Restore default failed." +msgstr "恢复默认失败!" + +#: xpack/plugins/interface/views.py:23 msgid "Interface" msgstr "界面" +#: xpack/plugins/interface/views.py:49 +msgid "It is already in the default setting state!" +msgstr "当前已经是初始化状态!" + +#: xpack/plugins/interface/views.py:53 +msgid "Restore default successfully!" +msgstr "恢复默认成功!" + #: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:94 #: xpack/plugins/license/templates/license/license_detail.html:50 #: xpack/plugins/license/views.py:31 @@ -5233,7 +5272,7 @@ msgstr "许可证" #: xpack/plugins/license/models.py:74 msgid "Standard edition" -msgstr "" +msgstr "标准版" #: xpack/plugins/license/models.py:76 msgid "Enterprise edition" diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 86751e359..9d2fc1a08 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -3,24 +3,28 @@ # import uuid import base64 +import string +import random from collections import OrderedDict from django.conf import settings from django.contrib.auth.hashers import make_password from django.contrib.auth.models import AbstractUser -from django.core import signing from django.core.cache import cache from django.db import models from django.utils.translation import ugettext_lazy as _ from django.utils import timezone from django.shortcuts import reverse -from common.utils import get_signer, date_expired_default +from common.utils import get_signer, date_expired_default, get_logger __all__ = ['User'] + signer = get_signer() +logger = get_logger(__file__) + class User(AbstractUser): ROLE_ADMIN = 'Admin' @@ -47,6 +51,9 @@ class User(AbstractUser): (SOURCE_OPENID, 'OpenID'), (SOURCE_RADIUS, 'Radius'), ) + + CACHE_KEY_USER_RESET_PASSWORD_PREFIX = "_KEY_USER_RESET_PASSWORD_{}" + id = models.UUIDField(default=uuid.uuid4, primary_key=True) username = models.CharField( max_length=128, unique=True, verbose_name=_('Username') @@ -346,9 +353,32 @@ class User(AbstractUser): return user_default def generate_reset_token(self): - return signer.sign_t( - {'reset': str(self.id), 'email': self.email}, expires_in=3600 - ) + letter = string.ascii_letters + string.digits + token =''.join([random.choice(letter) for _ in range(50)]) + self.set_cache(token) + return token + + def set_cache(self, token): + key = self.CACHE_KEY_USER_RESET_PASSWORD_PREFIX.format(token) + cache.set(key, {'id': self.id, 'email': self.email}, 3600) + + @classmethod + def validate_reset_password_token(cls, token): + try: + key = cls.CACHE_KEY_USER_RESET_PASSWORD_PREFIX.format(token) + value = cache.get(key) + user_id = value.get('id', '') + email = value.get('email', '') + user = cls.objects.get(id=user_id, email=email) + except (AttributeError, cls.DoesNotExist) as e: + logger.error(e, exc_info=True) + user = None + return user + + @classmethod + def expired_reset_password_token(cls, token): + key = cls.CACHE_KEY_USER_RESET_PASSWORD_PREFIX.format(token) + cache.delete(key) @property def otp_enabled(self): @@ -400,18 +430,6 @@ class User(AbstractUser): access_key = app.create_access_key() return app, access_key - @classmethod - def validate_reset_token(cls, token): - try: - data = signer.unsign_t(token) - user_id = data.get('reset', None) - user_email = data.get('email', '') - user = cls.objects.get(id=user_id, email=user_email) - - except (signing.BadSignature, cls.DoesNotExist): - user = None - return user - def reset_password(self, new_password): self.set_password(new_password) self.date_password_last_updated = timezone.now() diff --git a/apps/users/views/login.py b/apps/users/views/login.py index ca8bbf1ac..8f79b6f43 100644 --- a/apps/users/views/login.py +++ b/apps/users/views/login.py @@ -1,6 +1,7 @@ # ~*~ coding: utf-8 ~*~ from __future__ import unicode_literals +from django.core.cache import cache from django.shortcuts import render from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic import RedirectView @@ -84,7 +85,7 @@ class UserResetPasswordView(TemplateView): def get(self, request, *args, **kwargs): token = request.GET.get('token', '') - user = User.validate_reset_token(token) + user = User.validate_reset_password_token(token) if not user: kwargs.update({'errors': _('Token invalid or expired')}) else: @@ -100,12 +101,12 @@ class UserResetPasswordView(TemplateView): if password != password_confirm: return self.get(request, errors=_('Password not same')) - user = User.validate_reset_token(token) + user = User.validate_reset_password_token(token) + if not user: + return self.get(request, errors=_('Token invalid or expired')) if not user.can_update_password(): error = _('User auth from {}, go there change password'.format(user.source)) return self.get(request, errors=error) - if not user: - return self.get(request, errors=_('Token invalid or expired')) is_ok = check_password_rules(password) if not is_ok: @@ -115,6 +116,7 @@ class UserResetPasswordView(TemplateView): ) user.reset_password(password) + User.expired_reset_password_token(token) return HttpResponseRedirect(reverse('users:reset-password-success'))