From 31f098449f1587891914280fc2efde5630277a43 Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 18 Jan 2021 14:56:02 +0800 Subject: [PATCH 01/15] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20OPTION=20?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=20choices=20=E5=AD=97=E6=AE=B5=E9=80=89?= =?UTF-8?q?=E9=A1=B9;=20=E4=BF=AE=E6=94=B9display=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E7=BF=BB=E8=AF=91=20(=E6=98=BE=E7=A4=BA=E5=90=8D=E7=A7=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/drf/metadata.py | 5 ++- apps/locale/zh/LC_MESSAGES/django.mo | Bin 61771 -> 62040 bytes apps/locale/zh/LC_MESSAGES/django.po | 42 ++++++++++++---------- apps/tickets/serializers/ticket/ticket.py | 10 ++++-- 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/apps/common/drf/metadata.py b/apps/common/drf/metadata.py index eda1dd561..7d2332006 100644 --- a/apps/common/drf/metadata.py +++ b/apps/common/drf/metadata.py @@ -73,9 +73,8 @@ class SimpleMetadataWithFilters(SimpleMetadata): elif getattr(field, 'fields', None): field_info['children'] = self.get_serializer_info(field) - if (not field_info.get('read_only') and - not isinstance(field, (serializers.RelatedField, serializers.ManyRelatedField)) and - hasattr(field, 'choices')): + if not isinstance(field, (serializers.RelatedField, serializers.ManyRelatedField)) \ + and hasattr(field, 'choices'): field_info['choices'] = [ { 'value': choice_value, diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index b346f48041df5120529d322fa01b86d486c44439..179dd212ddf28f22805f0d82d8bc3e3ec73a637d 100644 GIT binary patch delta 18911 zcmZYG1(a1)`^WJE0|UbVLk-Q$(A@(J-QC^YDcx|95RnGyl#mcfK|rKqq}xH14rviZ zP{9B9clX18v0l$wo6mlpooAnO?+m=YCvFAA+zIeqOBQF2$JH^w^U`BvI?tON$Mb3x zRo3%{R`a~SoA^MWx2ro;%$h{eq2 z7*0F_)8Hax|K4^ih`TW_K1Pj8+syNFVkrz`eXk3ZTqGu7KHQ91@j9kvr*XOM7~-%N zo_7uZ!VtXN((@AFJxqwt&39&SE4T5~n4I=3m;$3P9@bVn>wAri95@2A<0_1cCsFgAZ^QZP$ZwEHiXm;? z4l|;5o(q+aM7;x5EN+0>cqi05F$i_XQ!p7WK)p*F(0?+hJ3f!P(Vs9qK5Of9N1L#n znW%!>i--3=D> zQPIvzqVA{~>X|o3P1MfX`=BNofjXJxsFPWbeEPgSsB!yH8#{`c_XO&MVlXp4!y=fx zgXa}SUv(-asEoq2xDz$O1=K<@s3W|E1@L#vXYS}0%!|6SNYsYQqK>*YYJ6kVd~L10 z6KbRVojz|El?)`tpzd%fYQQ1X1ktDg=TUF>71T*RN1Z_IPRmTy1VbJ=0yNJ3MIdDT^Olbt2tRC)pP@ z?-)$N`raf}a3Sgue1-ZZJBr%z4b+Zbq9*dXxRZ#F>KB3fekg%@X{)0aYJ+jH4+i2u z)FT>!dN(GaPZQ3iqB~rQ8n_OX--Vg*0O}6!pcZ#@PSl+h$9Px)b@Vk* z<6B$)Bh)-Yy7Kwgoqu8t^H3j~WvCr~W%-?`0sAdJgF2BPQT=XWMtq8TtCMtdcU%ee zajuE#-xW1~Kh%asb>sYX=hI2V$AuV(D^Vx09(829Q4>U)=P`o#XN-?;Q4ss8*M@0*CMolmPwXpKK2sWBu3#{)E(SJO?VHr;8XJ-)WY$5x&@MA z5OG#afca66rUcf&R;d1Kka>OHW-8jzb_~WnW;CkfMdT;3_Y3NziuQ8f-IcHcaeIqb zVL9RhsBy7-ySG0Wa}p=DxFl-5@)(cxy=qi6pq|+r^$0qk-roMGmuLcJ!!Ix#qp=|V zin%duA9n&(P$$&_b+R2$kEEaF$DuYb8RP5oKg${xS;I=yH{yDAz-UZ}=PbU4n&3Wa zp{E#(FD)PYBR4Jxl~0C|7>0Tj4N>zALSG^(W2tC|GcW{Kpq|}U)B@jQVmyL+i7ui( zw!fnKy++Lwr?2au4E4p77WFBJME$s}iP}&%)H^b;FXyj;qe*CiDX5oik+~ezz8W>b zHp`zyO>oKL>!^wEpziE9jKH_36AbI;=Fg65FN(V1iv2i$eML4V5rQqPLr;uNJk%V4 znrJj?LlaRaF$eW1)?pZK#`Smx^$3UecPBC*wa#*jzqELxk4k<>^>U-oj)OcU;K-Un8S~vo=U>=Ob zlBj`wQ45T~+&JFyn^BMKJ4}N6F#yk@=DUPCnVYDeCEg%sX5{32UKJ|3v)ZVar6p>? z{uqj*P#cpiFpHT}240V5TNr~!L3bmnXsF%ATCdG~zii6M> zL1i)(?Q{d`&UT?TbO`l!pEs|dCcc4s=8sWF{oMQu^{n5b-v0E%_!|_KFdJeD;$El? zd_0Wv*UsmW&<@w5Hn1DDz+p^@KcG(H2I|fqSo{{X@xbA(e{w8DoEr0BO)Q8*QJG|u)_XLZ^VdTEkkFlYBWyy{(Iv+y3`3nnQ%s9(P#Ya)@i?qOyc9L@1Jw7&Yt+m7 z1~p%tk#7DF)QzY2QPEN7M;%QW)H7;`ny54C4hNw&Iu?uJMAU}%p%yrbI+@d`M|8{L zr>K*QJ<9b9MlGBimG@<{N`BNrQK&ntjM`8;)XO&r^(dC17T$rnqwi4@MWZ%w4pZS> z^DSm04jt{jA4-|EF+!jJHdJ&1KFp8PP$#h0Jc~MsTbK@iHxu*d(h%oDoj@hj7f>y; zHR_S}F$bbHszh~tktY}jU!Y#XSE%tp6WmcJLETse)I0^u5d6TBr@RK%GcO)SV2l zcr0q-S>^)NkuJCPt*B4MLDWWn#$0$Gb?3=GaT_Xt+OV%Q6}{aRuoAXJz5UBkpW{8K zja@`-^cHI3hp3JHi8}f?6W#Yl8q_0*MBP9aRKLNf8=HXfa2oOw`nR*pdLX(%!!?_C{9Cd{0M5?Sxl_Y|BqDkZ0?~J zdTkxvnQwfL2_$C~UWNQ`yh#ZssJ^$*o6yp&gpc`RlE` zK|;^$9TvfmDeiZ@%BZ94hC1S*m=V7~EpP~1<0G^BRL|>9yavND=`{O?No+;j9V_5b z)H@M0o#&s6O1bI$ri(psD6T;bh?wDC!cnM=uEH#M5DVaa9EhoBy5EYYVr}AGs83J4 zS^T{c!*L__MSVQOXS+vN+($)s(g^jok3{`^Ux~%>D(a;R{oHLJ11c_wdUO?0kDwYR z#|EfJ)5YRms3RYP+Ry^j7uOa{h`wklI^s(hjCWBJKerAqF$r zL5_v4y&&o+i=j4B26ZxZP#bN6+E54ViM>#tni$j#yhWXGl0`g!Efl)QEtm<*5a&lN z&Jv68nrHXFff#J{cPWVEp_`O60J&ujQQ05)06_c&g`eYDS8$6aI7 zulUJHzQNb-sN?aiqm89SJ(_UTqs)!kpf8e&j--m&3d4!}TZdVw0jp3S!>_Rr#$W~v z-sHZxa-vSE9!6kKRQnXHjO#H88~hEUiDU8nw&~uFQ%Ol;^j7ynWRAHKb>v$tK8Si( z&YHiN4^i*RUlzYJgPC3ZQ=3^){R*LOxVS&&?CVm|+u8&*pq<$pQxgxjcs8ova@0iY zEx*O$z2*_~q_tl#Z(uUUJweT*=cK>9cnPTFz#`ZJ+o0awU8s&PPz%1r>=3<2IZm|vBGf!J@+Z)zh8RoSGM|}m%%B}^fs|%u)WQWY1dE{-u4-`? ziw9#C@^dg0ccV6T*1WTW=bwngD-xP8@LOjh)W%Yv76`LAA7&(uLfvr-)X8N8-ChMQ`OR)PljgooUUSW)$jCRW%!1z9VYF{^m&Y6LW^S5Ot%gP>=L0 zr_cM&5+}^7<|8ae$A3@*OMU0QfGVOE?1P$UD60Ka)E!Mn-RWx7jcqlLm@%mFk1$Z* zy?;_kP2!Ciy2nkN4>e&KiyNU9>SXpr|DB^29BKJU7SBNa7++%fwU~`~leJ&Q5Pkk{ zQ_)UeSVJIR?3ysS8G%|juf>t5h09yMrsW%$Z7tsm)o*~sqbweentvMlH1Q%!tS~pB zzG(JfRlI}hmuIirXkpaERZtVvLp_StmhX+~Kg8nE*8VA~|9op-y_fUXL>owi;SN-M z2{qw$)T4QZdKB^ZxrxJ26J<3EnPtsdW^>fZb}@%pehO;d1^aw%qOI1j&pe5`gDV!_ zu=ok;Q}73BgR%F!e#uZ9N@He2eNh!Q8)IJLA*gv*n;U#oG;o`_-x^M#7Px5nJLYrD zO#U4f$4m#@_*STiyPJJ2Kg1kw&cq7zTWYcICKVmgQ!Ie74!XDyDz1#Wov0hyXYomkFQ6Xn4b;zshnPn{|3ePBg-T&j8hT?kT!ks|1Zv#AN%-=gEe$P-Cz^JqZ%(s-<%?lz*7qt=(GFW%Ltk?gYT##>0cT=b+=M!*g}(O{-6IntiwQa1ghg$b2^3-FGd~h9?Ks^Ep)-Wje*23 zP(S_tM)eOq=KeK2)J%MSV(U zq846@8n+$QFWU0AEdR{n*eBdKt}ld25FPWOjyMW6K^@DtH+!N^Vi4+?k3=mv#aw_I z_ocP(viuL`Wz0eQZHp70^l!lDrJq$kQ*N;)(cuOokjfIIHS{!!TolptPPQD&$+)#@@ zM~&ZuI>{&29&pCpP&n!Y^O%K|*XO?k6`ep;C9uAAXoI?w&gM{avbhvPXy0NUu>3jH zJa^3JsDWvHFSv$;sISQ6sDXLR;;2Ve1vNoE)H~4B;sL1s!!4eO+R!v} zDeA;FVlq7CqoRp!peDX=@pIHfuTUN1UUUYqx%9%iCQ2Wb%Z%l?bWauHpV=-5i{XcYk!C89~|Sx=Rz$UX_iEtNCk@&Max3bNqEQQ8wf0-)Gt_)_J7j;IYTL@l%i^+mE9Q{!FKBYTIMC*mj9KRar^NL0RtSs%5bW%Hd+`kEDLH|ji7VL-WKh&IQ`Sqw@V76Gi9d*NdTS*Z0^U^;#N_fXM* z7=MD_$xsWtLk$eRVGCn=;@qf5R1Gz*rP&#^;76$OgUxZ~40DOOUiv)#b&84x9!4F_ z3Dm?FQTc0_1Mi}~a1!5i7DU~7BhBISR7N|c8{b1>i2yzl-Ix-RNu z=b+|WcAxXtk?bT9h)1l$Nz{>Ew)_j!GyfY?V4`2$Kc8nZBT@5ILG^2BaTnCQ15h_Q z9JTNa)JE3%tiv{QH)?_d*5RV%uc4mlUCX~Ty$5cA1gHg)qK-DZSqya}Rn1PAiTGpG zhJCB7vc=qs+TjU{@1TzKxyA7xx}ArjCI~n4n8i_dTm>s)ZHs4`^HDdr41-wT+iDGa ztl^Mr@GhekxPejl#LV`{<=dj}v=?f^k*IIX=@zd<-N+7PA@2;T{}qcL_+y^`3u_2? z>^dYzEu0zkG8VA7joA}5;ZW4VV^Isu!BV&pGvFgkh(S-BDN!eq8FfNkF+iXHK2$Ve zf7F1H)?t!4!<>h`XkUt2F!-t4Ko$%jE{2+?Bx;_@SQ8td7F>$@G_A(0co}{An7yI0 z62qRkFOY+%&+{*+JA93~FyU|RZ$!mV?LATL6HzbULexT=F=Z^i*iaig{oHNrJgWcC z=CkMa^FQ|Q?&w2McMy)6C?{%y0;p#ji6K}GncwSA(N&M2L2Os=Y$|$5zPmbdjdJ+^ zTt}a2{u<|BnhyJ|({;?xiiIhQ>5vS&U?*!|$-oZ8S1}H4e^|Z&^<(6plK=23MDQ|Us@kcnAGZPsW@7T z8fS0CtlwYMOR{`R;u(}*D22(jp-iU!t&N+3 zlgYim+EdR@`*)NC)N||Yh+v`;l&|Qu#d=P`nUp?sY)H|Si9UHKm#7yfcY+CaQ-AZp z0{l(an?Rh;au?~B*~V97>{{ym=(CTaYqbBj zqivFo=FjF*b3P8DJfyUvykX2e)D=K|7^OP(^^{7KyTrPd;|PpU;4b&=6l8<5v9rJE zw3~9O>s4rAs)Ya1A|Ib>wQ!hukK>HH)vFj~;voiim zJ^vP#tW0vfP4WO2l0RUBrc+-??h9;3Sw(#a>W6HN4<>#>{uxELRh#^JN;~5BS2?Ty zPChNkl=^mf{XvKK9ea=qwtOG@{6oDyjSX-Lv94TLoA@T>0A)Mn5+x386H(U=`g}!6 z>OyY``M;^R#&hI-3kX(IiO+Eyq@Ke%b|d$Kx_%dKNSpo>68NjYNqaO`1i|KcjjQ`)ytbj{HJJ3KR!e@-yRpW^Ol?90H3#8vPRvHruID4X;# z^~bbjVca$9d&oDWq@f-`DNB7N=AjgzUcu%~N&iOFtKmPE^FOE?7SzGF47f|lLeVve z(u#>{GpG(_C-qR;#$YAlx&B@}OLDU)!Ndi~=fQczTj=*MW~b;Xfg!Z(+Ckasqr+7y z^(bQ~-xKREWH0FW5_Nq;y*K4GMOQ&gLMdw#6(#qGGLx~H)Pd`J+FR0I3H6KG4=(Km z*_hIJkG%i$H$;DH$StLw7JtQV*0!B~vB_0YN3Lp?&q-caCx`#f z!u&ac{7K44>d){B4%PG5)ts_|WHe@`Y@_5M*42@TkGiV=&)ocY#xxAG76y%z-hOQBV_VxM>T@ZjTRr@)_-J^uF)v2$Hcv8Op3!PX&7*d{8gK* z5xL_OU4J^f4#ausw~2VV>hw)WJ&cl$I38`Curki0EdwQ|#=86G3y1p0N^s4h9MvFTqh|Pt$l(&!(VwA6W4O%$z7rT8mC&$zy4k8d>`X7 zpbF)~t2(=`Zv*OJLP}=JO-c^h3etJG4d~6-jFj@U&7pLmG^0;$auL*bQWj8>lB=%I z|NH9%9l~hPb&mQSN)bBg%0OvCe4e6f4E?^ey5b(h)o?$hE@L(l|4#cSl;`9+QW9AI z!PE;`J)Qn_rkE|VjD`y|?4pcS2lD!OzQ0NlmuBLJBxYhb@$c^&vAoqQ)7F8uWtfQ4 zf}*Pi2_$#YWjGww9)KVhKF;UB;s8z{e$ z3u9a)^=~L$DH|!e7TJ9M^DkjRTLwI*W|zX+4S4`$8=~w+*E_8hhsKMDoRgELMFOpgPLI$ z%0cpnDfy`nqQs$|o__DIo>a;QY|B?ITZ;G*ow^U`+pGPsZM9pK$P@2<;QO>iu8@cv z_vY`tziRj08B_1C*_?CR`K`TU|8H`3+3i#QlRL3J;y<}qJ5v5{Zd_Ak$Z{?jt{{trR_2Ug{uxBvhE delta 18625 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\n" "Language-Team: JumpServer team\n" @@ -74,7 +74,6 @@ msgstr "种类" #: terminal/models/storage.py:18 terminal/models/storage.py:58 #: tickets/models/ticket.py:38 #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:25 -#: tickets/serializers/ticket/ticket.py:19 #: users/templates/users/user_granted_database_app.html:35 msgid "Type" msgstr "类型" @@ -508,8 +507,7 @@ msgstr "每行一个命令" #: assets/models/cmd_filter.py:56 audits/models.py:57 #: authentication/templates/authentication/_access_key_modal.html:34 -#: tickets/models/ticket.py:43 tickets/serializers/ticket/ticket.py:20 -#: users/templates/users/_granted_assets.html:29 +#: tickets/models/ticket.py:43 users/templates/users/_granted_assets.html:29 #: users/templates/users/user_asset_permission.html:44 #: users/templates/users/user_asset_permission.html:79 #: users/templates/users/user_database_app_permission.html:42 @@ -1093,8 +1091,7 @@ msgid "Reason" msgstr "原因" #: audits/models.py:106 tickets/models/ticket.py:47 -#: tickets/serializers/ticket/ticket.py:21 xpack/plugins/cloud/models.py:224 -#: xpack/plugins/cloud/models.py:282 +#: xpack/plugins/cloud/models.py:224 xpack/plugins/cloud/models.py:282 msgid "Status" msgstr "状态" @@ -1804,7 +1801,7 @@ msgstr "当前组织不能被删除" #: orgs/mixins/models.py:56 orgs/mixins/serializers.py:25 orgs/models.py:41 #: orgs/models.py:422 orgs/serializers.py:100 -#: tickets/serializers/ticket/ticket.py:74 +#: tickets/serializers/ticket/ticket.py:78 msgid "Organization" msgstr "组织" @@ -2864,7 +2861,7 @@ msgstr "申请人" #: tickets/models/ticket.py:55 msgid "Applicant display" -msgstr "申请人" +msgstr "申请人 (显示名称)" #: tickets/models/ticket.py:60 msgid "Processor" @@ -2872,7 +2869,7 @@ msgstr "处理人" #: tickets/models/ticket.py:63 msgid "Processor display" -msgstr "处理人" +msgstr "处理人 (显示名称)" #: tickets/models/ticket.py:67 msgid "Assignees" @@ -2880,15 +2877,16 @@ msgstr "受理人" #: tickets/models/ticket.py:70 msgid "Assignees display" -msgstr "受理人" +msgstr "受理人 (显示名称)" #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:22 msgid "Category display" -msgstr "种类" +msgstr "种类 (显示名称)" #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:29 +#: tickets/serializers/ticket/ticket.py:19 msgid "Type display" -msgstr "类型" +msgstr "类型 (显示名称)" #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:33 msgid "Application group" @@ -2905,7 +2903,7 @@ msgstr "批准的应用" #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:56 msgid "Approve applications display" -msgstr "批准的应用" +msgstr "批准的应用 (显示名称)" #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:60 #: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:57 @@ -2914,7 +2912,7 @@ msgstr "批准的系统用户" #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:65 msgid "Approve system user display" -msgstr "批准的系统用户" +msgstr "批准的系统用户 (显示名称)" #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:89 msgid "No `Application` are found under Organization `{}`" @@ -2938,7 +2936,7 @@ msgstr "主机名组" #: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:61 #: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:69 msgid "Approve assets display" -msgstr "批准的资产" +msgstr "批准的资产 (显示名称)" #: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:48 msgid "Approve assets" @@ -2952,17 +2950,25 @@ msgstr "在组织 `{}` 下没有发现 `资产`" msgid "Login datetime" msgstr "登录日期" -#: tickets/serializers/ticket/ticket.py:92 +#: tickets/serializers/ticket/ticket.py:21 +msgid "Action display" +msgstr "动作 (显示名称)" + +#: tickets/serializers/ticket/ticket.py:24 +msgid "Status display" +msgstr "状态(显示名称)" + +#: tickets/serializers/ticket/ticket.py:96 msgid "" "The `type` in the submission data (`{}`) is different from the type in the " "request url (`{}`)" msgstr "提交数据中的类型 (`{}`) 与请求URL地址中的类型 (`{}`) 不一致" -#: tickets/serializers/ticket/ticket.py:102 +#: tickets/serializers/ticket/ticket.py:106 msgid "The organization `{}` does not exist" msgstr "组织 `{}` 不存在" -#: tickets/serializers/ticket/ticket.py:113 +#: tickets/serializers/ticket/ticket.py:117 msgid "None of the assignees belong to Organization `{}` admins" msgstr "所有受理人都不属于组织 `{}` 下的管理员" diff --git a/apps/tickets/serializers/ticket/ticket.py b/apps/tickets/serializers/ticket/ticket.py index b6ffc5140..1ca217adb 100644 --- a/apps/tickets/serializers/ticket/ticket.py +++ b/apps/tickets/serializers/ticket/ticket.py @@ -16,9 +16,13 @@ __all__ = [ class TicketSerializer(OrgResourceModelSerializerMixin): - type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type')) - action_display = serializers.ReadOnlyField(source='get_action_display', label=_('Action')) - status_display = serializers.ReadOnlyField(source='get_status_display', label=_('Status')) + type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type display')) + action_display = serializers.ReadOnlyField( + source='get_action_display', label=_('Action display') + ) + status_display = serializers.ReadOnlyField( + source='get_status_display', label=_('Status display') + ) meta = MethodSerializer() class Meta: From f6622f5e01cf2ce441365d293bf9c4d56ef2613a Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 18 Jan 2021 15:04:53 +0800 Subject: [PATCH 02/15] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/zh/LC_MESSAGES/django.mo | Bin 62040 -> 62041 bytes apps/locale/zh/LC_MESSAGES/django.po | 2 +- apps/users/views/profile/reset.py | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 179dd212ddf28f22805f0d82d8bc3e3ec73a637d..df0dea23028d5c12270fb00e674a8c1db58050d8 100644 GIT binary patch delta 8073 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 delta 8072 zcmXZge_+UU9>?+Twk)%0h50er{8)Z%xmjY9A4MU$Gm`Z4bS-s;lYUUix13I{EYtE2UGC~YT%Qu{|?V3PMRBRglcyIY9XCb;}oG5 z($D!~Jdb$9+&FX?O(L1Zz4k$@M?4KPa3<Pn$5`TnR0i|rkFG4VsFBVUhtc=n*~v>JQk=cxYe7liuG zsFUo5T1YR{$@~Vj(BY^B{SHf+KN>?JheQ=>2S1~Z_}qnIq72&_dy)SYYJzcCg!f=4 zT#c=8KbB*(D2m#^8oL+u4E%)Zm%ccPx-)-tC523!hPumVQ4QCj7P14+Pl%#js1rE0 zB<$cDRKL@xqi*tS*l~N*>sE-m(yLJ8+<@vo5_NT>Fjj*}6mpngI-bB6{~ATVCckK@ zE+~qQVhN63#?ze0LU2Fv*JYfL7WP~e-ADY<-=k7ozAN z-CBg zn{6d(#Z{<@zDJ!*!UlfQVJ2#VEY!ks9T(W%sHgoZ)F=0LY>iK1CtQ!UpJt3Tz;_fh z;Lo<+#;|}UsQRw9C#v1$cn%J6ex$wKjzhJ($MICu!e?L;{0nM>Wg9tvP4ET@b*Mz` zxC(V8hfojY52y)KHw80o2V01`s{ZyG=Wj)gH^EM}f3mYSasFzsfP@yZ9CfEJ*jH_( zt+rp{rL_AWs$Y*+!`spqHQqSXIFnHIkD@j-6SdJY)W+7tE^M<^r~$r2b^I2a;%S>v z5eDvr8nBn+VW{>cwiIi3j+$_?^D`XJLj4$z7rSBwwk5IJ4fdjTa2U1HQ_d&zVb_2S zZA;X|7dq~On)ov32RT2~{?_?1NV_CAt+#~!H=@S< zy&doT#4X&vCYa{LZ0tk4#PKJnllcnsF=1ZztL*_7POS$5C&`e9XZu&VOo8VRQ1)w$MI4pMnPN zVDnwk4fPOSj#}VN&X2bbqWb+ATi|TW#MP*i+JRb7!oS0Z<{VVq4E5}^#bmwzT|*)2 ziE3~;YT_ZNqZ;k{yX^z0c2n(4%qCuhYG2{}zflu?U=L$5@hQ|#zn?IL`J>b~c~wYc z*rr&AxH;;FPAk+2UH|o`6fHUggL1CTuj1VsNbCWpiX8uw#4zMw`4YIo)xHm>rm~s@9_J7$Q38t zFtIXxa?>$|hMiDHT!iyT zX*V16}^~GE4_#M26_^9KocS8H_*p7TLs^28XPoer(pvFD!`Z#G<*ikm>2=nYk z&UZ(hK!3+WTz@laC%4&2_A$Ez)2T1FTbzFn)5zBZO?(D*Bz4{m6Xv5<+TC%n zz226fb~?^JjTaJcMm@~OP*-!_dtssZsCoL@ftaTEe@JbCzid!PU+M-+Q9FFz^%bb6 z_AMNUhcO*Hy&rbe%MP+5>}}Y9b`wzTA8|ZavEKg`6m%pT>^9U&-^X0s=eW)XA)ki& zLN-M8%d)YJwZV(K^@sDY=Cd020Dlu_%p{RQ3L&e zYFB4>=-(7IVSC4yqZT?0^&J_D>NgWL&!XLa|6e7c1#EYND%3znY{H%}Pz%(8x}pZ^ zX$RVCU0>q3)K0<-+CSoWA!@!AdpLg;HjvN?w_^q##fBK|4G&o()Py}y?XE;Eq}2Hd zj$_nG{mIU<3+!^#iL646_og~%pxt;bR-=ye7;2zjPz_T)3?HDzsC+i+2s@za2jB?2 z2J>(gw#I7LpFy=xtqT1+qUMdexNr&TB>FfWYOh00Fw*f@)B^5yeu{m}&a-8xlU#$^ z(00^>)viAjjH442G~j7BNZuDFtdDvIGEp77q6X}VTIki-6>mi?Z~v%t*G|99DjxN ziT{W7Fr_+dpb@6%{m)SWJJ~|i!`BBj(QtbcYC$FTPSgUXxPCTj$MbACs{Ibvf9U*v zyo3Dr7^}m`k3z@$Pz#xZns^cFr`|HuKrf;u+=yD>PSmINpzG^=9NIOo*{CbabKD0t z?qJ8mKj!@PtJbX~w2|tIOlv4?2Ov^Fx0}vVkZ6>^`R?6 z`o+Fc7 z#TvT}8kUIsFQ7HyM4j=YbX6l$P#Rg52IGR+?LzTs0CI!u0b8?Nyl}MhJ|OK`e)lbTZGzB zKkSRYKFawkG20dMP&<4UQ*e#*70&<5`MszK4q_o5w{5=+`QM^;ItDe~WYiaPrsHL( zjjWF;Xrf)H4*MK`;rNtIIu`01q9$&GdKmK^-)u`!<4r Date: Mon, 18 Jan 2021 15:15:38 +0800 Subject: [PATCH 03/15] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20AssetUserFilt?= =?UTF-8?q?erBackend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset_user.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/api/asset_user.py b/apps/assets/api/asset_user.py index 7c78f3f51..e2844a5e5 100644 --- a/apps/assets/api/asset_user.py +++ b/apps/assets/api/asset_user.py @@ -28,7 +28,7 @@ logger = get_logger(__name__) class AssetUserFilterBackend(filters.BaseFilterBackend): def filter_queryset(self, request, queryset, view): kwargs = {} - for field in view.filter_fields: + for field in view.filterset_fields: value = request.GET.get(field) if not value: continue From 230ef2f662a4a50aef21f50b92b0b794927af932 Mon Sep 17 00:00:00 2001 From: xinwen Date: Mon, 18 Jan 2021 15:01:41 +0800 Subject: [PATCH 04/15] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=A6=BB=E5=BC=80=E7=BB=84=E7=BB=87=E4=BF=A1=E5=8F=B7?= =?UTF-8?q?=E8=A2=AB=E8=A6=86=E7=9B=96=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/orgs/signals_handler.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/orgs/signals_handler.py b/apps/orgs/signals_handler.py index 5f918ee21..57c7f5490 100644 --- a/apps/orgs/signals_handler.py +++ b/apps/orgs/signals_handler.py @@ -122,18 +122,18 @@ def refresh_user_amount_on_user_create_or_delete(user_id): @receiver(post_save, sender=User) -def on_user_create(sender, instance, created, **kwargs): +def on_user_create_refresh_cache(sender, instance, created, **kwargs): if created: refresh_user_amount_on_user_create_or_delete(instance.id) @receiver(pre_delete, sender=User) -def on_user_delete(sender, instance, **kwargs): +def on_user_delete_refresh_cache(sender, instance, **kwargs): refresh_user_amount_on_user_create_or_delete(instance.id) @receiver(m2m_changed, sender=OrganizationMember) -def on_org_user_changed(sender, action, instance, reverse, pk_set, **kwargs): +def on_org_user_changed_refresh_cache(sender, action, instance, reverse, pk_set, **kwargs): if not action.startswith(POST_PREFIX): return From 243eedc4f9c63882ac2ec5b8b80f3c97e5d10a00 Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 18 Jan 2021 17:11:30 +0800 Subject: [PATCH 05/15] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=B7=A5?= =?UTF-8?q?=E5=8D=95body=20html=E6=98=BE=E7=A4=BA=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E5=8F=8A=E7=BF=BB=E8=AF=91=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/zh/LC_MESSAGES/django.mo | Bin 62041 -> 63233 bytes apps/locale/zh/LC_MESSAGES/django.po | 199 ++++++++++++++++------ apps/tickets/handler/apply_application.py | 32 ++-- apps/tickets/handler/apply_asset.py | 36 ++-- apps/tickets/handler/base.py | 66 ++++--- apps/tickets/handler/login_confirm.py | 8 +- apps/tickets/signals_handler/ticket.py | 18 -- apps/tickets/utils.py | 39 ++--- 8 files changed, 231 insertions(+), 167 deletions(-) diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index df0dea23028d5c12270fb00e674a8c1db58050d8..62f5281f5327828c2a26dd4c340d62fee69d9e54 100644 GIT binary patch delta 20908 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≥7HFe4U8`)cq^jX3C7+|K92L{mCn4+3;lVomg;t=agIf)+bciwWe$Q z-sI`i{<-s%=ds)WdF&2xp2x}QZ~LEYy4z0Lx9eaQ&z%YH-aa%vdH1^H*$a|qEKT0O zuR@?3rL3BMXU$^wMRzmq?cdtBFMTrky(y`4r~M}xXdj9HKYO~*#H~H+?j(&pc+4-M z(bT)Wdzm|5?%bSA1x7%EYafa_{X{`c(4Ui`*?)m*kcEQkHFYyCkek z4XpBf&uP=n+?6t6V%mh>`%Y`|KBJ^PsV6e|+vno;p(VHWY;yOLH1ekfK9z2Lv?^s; z{H;9`$fqparl;jS&kBJl%h%nWzUle7xgU|7_t%wY$n$Q=yLa4Pljt6dyE7+s5|4d< R%F1=A%Vs5QyT38R{{g$@v-JP~ delta 19218 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\n" "Language-Team: JumpServer team\n" @@ -2839,6 +2839,137 @@ msgstr "拒绝" msgid "Closed" msgstr "关闭" +#: tickets/handler/apply_application.py:55 +msgid "Applied category" +msgstr "申请的种类" + +#: tickets/handler/apply_application.py:56 +msgid "Applied type" +msgstr "申请的类型" + +#: tickets/handler/apply_application.py:57 +msgid "Applied application group" +msgstr "申请的应用组" + +#: tickets/handler/apply_application.py:58 tickets/handler/apply_asset.py:59 +msgid "Applied system user group" +msgstr "申请的系统用户组" + +#: tickets/handler/apply_application.py:59 tickets/handler/apply_asset.py:61 +msgid "Applied date start" +msgstr "申请的开始日期" + +#: tickets/handler/apply_application.py:60 tickets/handler/apply_asset.py:62 +msgid "Applied date expired" +msgstr "申请的失效日期" + +#: tickets/handler/apply_application.py:75 +msgid "Approved applications" +msgstr "批准的应用" + +#: tickets/handler/apply_application.py:76 tickets/handler/apply_asset.py:79 +msgid "Approved system users" +msgstr "批准的系统用户" + +#: tickets/handler/apply_application.py:77 tickets/handler/apply_asset.py:81 +msgid "Approved date start" +msgstr "批准的开始日期" + +#: tickets/handler/apply_application.py:78 tickets/handler/apply_asset.py:82 +msgid "Approved date expired" +msgstr "批准的失效日期" + +#: tickets/handler/apply_application.py:95 tickets/handler/apply_asset.py:98 +msgid "Created by ticket ({}) ({})" +msgstr "通过工单创建 ({}) ({})" + +#: tickets/handler/apply_application.py:99 tickets/handler/apply_asset.py:102 +msgid "" +"Created by the ticket, ticket title: {}, ticket applicant: {}, ticket " +"processor: {}, ticket ID: {}" +msgstr "" +"通过工单创建, 工单标题: {}, 工单申请人: {}, 工单处理人: {}, 工单 ID: {}" + +#: tickets/handler/apply_asset.py:57 +msgid "Applied IP group" +msgstr "申请的IP组" + +#: tickets/handler/apply_asset.py:58 +msgid "Applied hostname group" +msgstr "申请的主机名组" + +#: tickets/handler/apply_asset.py:60 +msgid "Applied actions" +msgstr "申请的动作" + +#: tickets/handler/apply_asset.py:78 +msgid "Approved assets" +msgstr "批准的资产" + +#: tickets/handler/apply_asset.py:80 +msgid "Approved actions" +msgstr "批准的动作" + +#: tickets/handler/base.py:62 +msgid "User {} {} the ticket" +msgstr "用户 {} {} 这个工单" + +#: tickets/handler/base.py:89 +msgid "Ticket basic info" +msgstr "工单基本信息" + +#: tickets/handler/base.py:90 +msgid "Ticket title" +msgstr "工单标题" + +#: tickets/handler/base.py:91 +msgid "Ticket type" +msgstr "工单类型" + +#: tickets/handler/base.py:92 +msgid "Ticket applicant" +msgstr "工单申请人" + +#: tickets/handler/base.py:93 +msgid "Ticket assignees" +msgstr "工单受理人" + +#: tickets/handler/base.py:94 +msgid "Ticket processor" +msgstr "工单处理人" + +#: tickets/handler/base.py:94 +msgid "No" +msgstr "无" + +#: tickets/handler/base.py:95 +msgid "Ticket action" +msgstr "工单动作" + +#: tickets/handler/base.py:96 +msgid "Ticket status" +msgstr "工单状态" + +#: tickets/handler/base.py:114 +msgid "Ticket applied info" +msgstr "工单申请信息" + +#: tickets/handler/base.py:124 +msgid "Ticket approved info" +msgstr "工单批准信息" + +#: tickets/handler/login_confirm.py:16 +msgid "Applied login IP" +msgstr "申请的登录IP" + +#: tickets/handler/login_confirm.py:17 +msgid "Applied login city" +msgstr "申请的登录城市" + +#: tickets/handler/login_confirm.py:18 +msgid "Applied login datetime" +msgstr "申请的登录日期" + #: tickets/models/comment.py:19 msgid "User display name" msgstr "用户显示名称" @@ -2974,65 +3105,23 @@ msgstr "所有受理人都不属于组织 `{}` 下的管理员" #: tickets/utils.py:21 msgid "New Ticket: {} ({})" -msgstr "新建工单: {} ({})" +msgstr "新工单: {} ({})" -#: tickets/utils.py:26 -#, python-brace-format -msgid "" -"
\n" -"

Your has a new ticket

\n" -"
\n" -" Ticket: \n" -"
\n" -" {body}\n" -"
\n" -" click here to review \n" -"
\n" -"
\n" -" " -msgstr "" -"
\n" -"

你有一个新工单

\n" -"
\n" -" 工单: \n" -"
\n" -" {body}\n" -"
\n" -" 点击查看 \n" -"
\n" -"
\n" -" " +#: tickets/utils.py:33 +msgid "Your has a new ticket, from applicant - {}" +msgstr "你有一个新的工单, 来自申请人 - {}" -#: tickets/utils.py:51 +#: tickets/utils.py:35 +msgid "click here to review" +msgstr "点击查看" + +#: tickets/utils.py:48 msgid "Ticket has processed: {} ({})" msgstr "工单已处理: {} ({})" -#: tickets/utils.py:53 -#, python-brace-format -msgid "" -"\n" -"
\n" -"

Your ticket has been processed

\n" -"
\n" -" Ticket: \n" -"
\n" -" {body}\n" -"
\n" -"
\n" -"
\n" -" " -msgstr "" -"\n" -"
\n" -"

你的工单已被处理

\n" -"
\n" -" 工单: \n" -"
\n" -" {body}\n" -"
\n" -"
\n" -"
\n" -" " +#: tickets/utils.py:57 +msgid "Your ticket has been ({}) processed" +msgstr "你的工单已被 ({}) 处理" #: users/api/user.py:199 msgid "Could not reset self otp, use profile reset instead" diff --git a/apps/tickets/handler/apply_application.py b/apps/tickets/handler/apply_application.py index 28eb82697..d9c72e2bf 100644 --- a/apps/tickets/handler/apply_application.py +++ b/apps/tickets/handler/apply_application.py @@ -1,4 +1,4 @@ -from django.utils.translation import ugettext as __ +from django.utils.translation import ugettext as _ from orgs.utils import tmp_to_org, tmp_to_root_org from applications.models import Application from applications.const import ApplicationCategoryChoices, ApplicationTypeChoices @@ -52,12 +52,12 @@ class Handler(BaseHandler): {}: {}, {}: {}, '''.format( - __('Applied category'), apply_category_display, - __('Applied type'), apply_type_display, - __('Applied application group'), apply_application_group, - __('Applied system user group'), apply_system_user_group, - __('Applied date start'), apply_date_start, - __('Applied date expired'), apply_date_expired, + _('Applied category'), apply_category_display, + _('Applied type'), apply_type_display, + _('Applied application group'), apply_application_group, + _('Applied system user group'), apply_system_user_group, + _('Applied date start'), apply_date_start, + _('Applied date expired'), apply_date_expired, ) return applied_body @@ -72,10 +72,10 @@ class Handler(BaseHandler): {}: {}, {}: {}, '''.format( - __('Approved applications'), approve_applications_display, - __('Approved system users'), approve_system_users_display, - __('Approved date start'), approve_date_start, - __('Approved date expired'), approve_date_expired + _('Approved applications'), approve_applications_display, + _('Approved system users'), approve_system_users_display, + _('Approved date start'), approve_date_start, + _('Approved date expired'), approve_date_expired ) return approved_body @@ -92,10 +92,10 @@ class Handler(BaseHandler): approve_system_users_id = self.ticket.meta.get('approve_system_users', []) approve_date_start = self.ticket.meta.get('approve_date_start') approve_date_expired = self.ticket.meta.get('approve_date_expired') - permission_name = '{}({})'.format( - __('Created by ticket ({})'.format(self.ticket.title)), str(self.ticket.id)[:4] + permission_name = _('Created by ticket ({}) ({})'.format( + self.ticket.title, str(self.ticket.id)[:4]) ) - permission_comment = __( + permission_comment = _( 'Created by the ticket, ' 'ticket title: {}, ' 'ticket applicant: {}, ' @@ -108,10 +108,10 @@ class Handler(BaseHandler): ) permissions_data = { 'id': self.ticket.id, - 'name': permission_name, + 'name': str(permission_name), 'category': apply_category, 'type': apply_type, - 'comment': permission_comment, + 'comment': str(permission_comment), 'created_by': '{}:{}'.format(str(self.__class__.__name__), str(self.ticket.id)), 'date_start': approve_date_start, 'date_expired': approve_date_expired, diff --git a/apps/tickets/handler/apply_asset.py b/apps/tickets/handler/apply_asset.py index 4114c04b3..d01a5c6b1 100644 --- a/apps/tickets/handler/apply_asset.py +++ b/apps/tickets/handler/apply_asset.py @@ -1,5 +1,5 @@ from .base import BaseHandler -from django.utils.translation import ugettext as __ +from django.utils.translation import ugettext as _ from perms.models import AssetPermission, Action from assets.models import Asset, SystemUser @@ -54,12 +54,12 @@ class Handler(BaseHandler): {}: {}, {}: {} '''.format( - __('Applied IP group'), apply_ip_group, - __("Applied hostname group"), apply_hostname_group, - __("Applied system user group"), apply_system_user_group, - __("Applied actions"), apply_actions_display, - __('Applied date start'), apply_date_start, - __('Applied date expired'), apply_date_expired, + _('Applied IP group'), apply_ip_group, + _("Applied hostname group"), apply_hostname_group, + _("Applied system user group"), apply_system_user_group, + _("Applied actions"), apply_actions_display, + _('Applied date start'), apply_date_start, + _('Applied date expired'), apply_date_expired, ) return applied_body @@ -75,11 +75,11 @@ class Handler(BaseHandler): {}: {}, {}: {} '''.format( - __('Approved assets'), approve_assets_display, - __('Approved system users'), approve_system_users_display, - __('Approved actions'), ', '.join(approve_actions_display), - __('Approved date start'), approve_date_start, - __('Approved date expired'), approve_date_expired, + _('Approved assets'), approve_assets_display, + _('Approved system users'), approve_system_users_display, + _('Approved actions'), ', '.join(approve_actions_display), + _('Approved date start'), approve_date_start, + _('Approved date expired'), approve_date_expired, ) return approved_body @@ -95,23 +95,25 @@ class Handler(BaseHandler): approve_actions = self.ticket.meta.get('approve_actions', Action.NONE) approve_date_start = self.ticket.meta.get('approve_date_start') approve_date_expired = self.ticket.meta.get('approve_date_expired') - permission_name = '{}({})'.format( - __('Created by ticket ({})'.format(self.ticket.title)), str(self.ticket.id)[:4] + permission_name = _('Created by ticket ({}) ({})'.format( + self.ticket.title, str(self.ticket.id)[:4]) ) - permission_comment = __( + permission_comment = _( 'Created by the ticket, ' 'ticket title: {}, ' 'ticket applicant: {}, ' 'ticket processor: {}, ' 'ticket ID: {}' ''.format( - self.ticket.title, self.ticket.applicant_display, self.ticket.processor_display, + self.ticket.title, + self.ticket.applicant_display, + self.ticket.processor_display, str(self.ticket.id) ) ) permission_data = { 'id': self.ticket.id, - 'name': permission_name, + 'name': str(permission_name), 'comment': permission_comment, 'created_by': '{}:{}'.format(str(self.__class__.__name__), str(self.ticket.id)), 'actions': approve_actions, diff --git a/apps/tickets/handler/base.py b/apps/tickets/handler/base.py index e1820dc0b..f55b51a37 100644 --- a/apps/tickets/handler/base.py +++ b/apps/tickets/handler/base.py @@ -1,6 +1,8 @@ -from django.utils.translation import ugettext as __ +from django.utils.translation import ugettext as _ from common.utils import get_logger -from tickets.utils import send_ticket_processed_mail_to_applicant +from tickets.utils import ( + send_ticket_processed_mail_to_applicant, send_ticket_applied_mail_to_assignees +) logger = get_logger(__name__) @@ -14,9 +16,11 @@ class BaseHandler(object): # on action def _on_open(self): self.ticket.applicant_display = str(self.ticket.applicant) + self.ticket.assignees_display = [str(assignee) for assignee in self.ticket.assignees.all()] meta_display = getattr(self, '_construct_meta_display_of_open', lambda: {})() self.ticket.meta.update(meta_display) self.ticket.save() + self._send_applied_mail_to_assignees() def _on_approve(self): meta_display = getattr(self, '_construct_meta_display_of_approve', lambda: {})() @@ -41,11 +45,12 @@ class BaseHandler(object): return method() # email + def _send_applied_mail_to_assignees(self): + logger.debug('Send applied email to assignees: {}'.format(self.ticket.assignees_display)) + send_ticket_applied_mail_to_assignees(self.ticket) + def _send_processed_mail_to_applicant(self): - msg = 'Ticket ({}) has processed, send mail to applicant ({})'.format( - self.ticket.title, self.ticket.applicant_display - ) - logger.debug(msg) + logger.debug('Send processed mail to applicant: {}'.format(self.ticket.applicant_display)) send_ticket_processed_mail_to_applicant(self.ticket) # comments @@ -54,13 +59,18 @@ class BaseHandler(object): user_display = str(user) action_display = self.ticket.get_action_display() data = { - 'body': __('User {} {} the ticket'.format(user_display, action_display)), + 'body': _('User {} {} the ticket'.format(user_display, action_display)), 'user': user, 'user_display': user_display } return self.ticket.comments.create(**data) # body + body_html_format = ''' + {}: +
{}
+ ''' + def get_body(self): old_body = self.ticket.meta.get('body') if old_body: @@ -71,9 +81,7 @@ class BaseHandler(object): return basic_body + meta_body def _construct_basic_body(self): - body = ''' - {}: - {}: {}, + basic_body = '''{}: {}, {}: {}, {}: {}, {}: {}, @@ -81,15 +89,15 @@ class BaseHandler(object): {}: {}, {}: {} '''.format( - __("Ticket basic info"), - __('Ticket title'), self.ticket.title, - __('Ticket type'), self.ticket.get_type_display(), - __('Ticket applicant'), self.ticket.applicant_display, - __('Ticket assignees'), self.ticket.assignees_display, - __('Ticket processor'), self.ticket.processor_display, - __('Ticket action'), self.ticket.get_action_display(), - __('Ticket status'), self.ticket.get_status_display() + _('Ticket title'), self.ticket.title, + _('Ticket type'), self.ticket.get_type_display(), + _('Ticket applicant'), self.ticket.applicant_display, + _('Ticket assignees'), self.ticket.assignees_display, + _('Ticket processor'), self.ticket.processor_display or _('No'), + _('Ticket action'), self.ticket.get_action_display(), + _('Ticket status'), self.ticket.get_status_display() ) + body = self.body_html_format.format(_("Ticket basic info"), basic_body) return body def _construct_meta_body(self): @@ -102,21 +110,11 @@ class BaseHandler(object): return body def _base_construct_meta_body_of_open(self): - open_body = ''' - {}: - {} - '''.format( - __('Ticket applied info'), - getattr(self, '_construct_meta_body_of_open', lambda: 'No')() - ) - return open_body + meta_body_of_open = getattr(self, '_construct_meta_body_of_open', lambda: 'No')() + body = self.body_html_format.format(_('Ticket applied info'), meta_body_of_open) + return body def _base_construct_meta_body_of_approve(self): - approve_body = ''' - {}: - {} - '''.format( - __('Ticket approved info'), - getattr(self, '_construct_meta_body_of_approve', lambda: 'No')() - ) - return approve_body + meta_body_of_approve = getattr(self, '_construct_meta_body_of_approve', lambda: 'No')() + body = self.body_html_format.format(_('Ticket approved info'), meta_body_of_approve) + return body diff --git a/apps/tickets/handler/login_confirm.py b/apps/tickets/handler/login_confirm.py index 21419022f..b1d491cfc 100644 --- a/apps/tickets/handler/login_confirm.py +++ b/apps/tickets/handler/login_confirm.py @@ -1,4 +1,4 @@ -from django.utils.translation import ugettext as __ +from django.utils.translation import ugettext as _ from .base import BaseHandler @@ -13,8 +13,8 @@ class Handler(BaseHandler): {}: {}, {}: {} '''.format( - __("Applied login IP"), apply_login_ip, - __("Applied login city"), apply_login_city, - __("Applied login datetime"), apply_login_datetime, + _("Applied login IP"), apply_login_ip, + _("Applied login city"), apply_login_city, + _("Applied login datetime"), apply_login_datetime, ) return applied_body diff --git a/apps/tickets/signals_handler/ticket.py b/apps/tickets/signals_handler/ticket.py index 7e8bc8d5d..aae620295 100644 --- a/apps/tickets/signals_handler/ticket.py +++ b/apps/tickets/signals_handler/ticket.py @@ -1,11 +1,9 @@ # -*- coding: utf-8 -*- # from django.dispatch import receiver -from django.db.models.signals import m2m_changed from common.utils import get_logger from tickets.models import Ticket -from tickets.utils import send_ticket_applied_mail_to_assignees from ..signals import post_change_ticket_action @@ -15,19 +13,3 @@ logger = get_logger(__name__) @receiver(post_change_ticket_action, sender=Ticket) def on_post_change_ticket_action(sender, ticket, action, **kwargs): ticket.handler.dispatch(action) - - -@receiver(m2m_changed, sender=Ticket.assignees.through) -def on_ticket_assignees_changed(sender, instance, action, reverse, model, pk_set, **kwargs): - if reverse: - return - if action != 'post_add': - return - logger.debug('Receives ticket and assignees changed signal, ticket: {}'.format(instance.title)) - instance.assignees_display = [str(assignee) for assignee in instance.assignees.all()] - instance.save() - assignees = model.objects.filter(pk__in=pk_set) - assignees_display = [str(assignee) for assignee in assignees] - logger.debug('Send applied email to assignees: {}'.format(assignees_display)) - send_ticket_applied_mail_to_assignees(instance, assignees) - diff --git a/apps/tickets/utils.py b/apps/tickets/utils.py index ebd4c22b8..523d0f102 100644 --- a/apps/tickets/utils.py +++ b/apps/tickets/utils.py @@ -11,10 +11,10 @@ from . import const logger = get_logger(__file__) -def send_ticket_applied_mail_to_assignees(ticket, assignees): - if not assignees: +def send_ticket_applied_mail_to_assignees(ticket): + if not ticket.assignees: logger.debug("Not found assignees, ticket: {}({}), assignees: {}".format( - ticket, str(ticket.id), assignees) + ticket, str(ticket.id), ticket.assignees) ) return @@ -22,25 +22,22 @@ def send_ticket_applied_mail_to_assignees(ticket, assignees): ticket_detail_url = urljoin( settings.SITE_URL, const.TICKET_DETAIL_URL.format(id=str(ticket.id)) ) - message = _( - """
-

Your has a new ticket

+ message = """ +
+

{title} {ticket_detail_url_description}

- Ticket: -
- {body} -
- click here to review + {body}
""".format( + title=_('Your has a new ticket, from applicant - {}').format(str(ticket.applicant)), + ticket_detail_url=ticket_detail_url, + ticket_detail_url_description=_('click here to review'), body=ticket.body.replace('\n', '
'), - ticket_detail_url=ticket_detail_url - ) ) if settings.DEBUG: logger.debug(message) - recipient_list = [assignee.email for assignee in assignees] + recipient_list = [assignee.email for assignee in ticket.assignees.all()] send_mail_async.delay(subject, message, recipient_list, html_message=message) @@ -48,22 +45,18 @@ def send_ticket_processed_mail_to_applicant(ticket): if not ticket.applicant: logger.error("Not found applicant: {}({})".format(ticket.title, ticket.id)) return - subject = _('Ticket has processed: {} ({})').format(ticket.title, ticket.get_type_display()) - message = _( - """ + subject = _('Ticket has processed: {} ({})').format(ticket.title, ticket.processor_display) + message = """
-

Your ticket has been processed

+

{title}

- Ticket: -
- {body} -
+ {body}
""".format( + title=_('Your ticket has been ({}) processed').format(ticket.processor_display), body=ticket.body.replace('\n', '
'), ) - ) if settings.DEBUG: logger.debug(message) recipient_list = [ticket.applicant.email] From 7b8f932dcd791c268a29214a434d7c4a32f06e12 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 18 Jan 2021 15:17:57 +0800 Subject: [PATCH 06/15] =?UTF-8?q?perf:=20=E5=8E=BB=E6=8E=89=E5=87=A0?= =?UTF-8?q?=E4=B8=AA=E4=B8=8D=E7=94=A8=E7=9A=84api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/api/auth.py | 1 - apps/terminal/api/terminal.py | 39 +-------------------------------- apps/terminal/urls/api_urls.py | 2 -- 3 files changed, 1 insertion(+), 41 deletions(-) diff --git a/apps/authentication/api/auth.py b/apps/authentication/api/auth.py index 310aa3d4a..6886fa2f0 100644 --- a/apps/authentication/api/auth.py +++ b/apps/authentication/api/auth.py @@ -4,7 +4,6 @@ import uuid from django.core.cache import cache from django.shortcuts import get_object_or_404 -from rest_framework.permissions import AllowAny from rest_framework.response import Response from rest_framework.views import APIView diff --git a/apps/terminal/api/terminal.py b/apps/terminal/api/terminal.py index 14213316c..26b030ff8 100644 --- a/apps/terminal/api/terminal.py +++ b/apps/terminal/api/terminal.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # -from collections import OrderedDict import logging import uuid @@ -8,7 +7,6 @@ from django.core.cache import cache from django.shortcuts import get_object_or_404 from rest_framework import viewsets from rest_framework.views import APIView, Response -from rest_framework.permissions import AllowAny from common.drf.api import JMSBulkModelViewSet from common.utils import get_object_or_none @@ -18,7 +16,7 @@ from .. import serializers from .. import exceptions __all__ = [ - 'TerminalViewSet', 'TerminalTokenApi', 'StatusViewSet', 'TerminalConfig', + 'TerminalViewSet', 'StatusViewSet', 'TerminalConfig', ] logger = logging.getLogger(__file__) @@ -69,41 +67,6 @@ class TerminalViewSet(JMSBulkModelViewSet): queryset = queryset.filter(id__in=filtered_queryset_id) return queryset - def get_permissions(self): - if self.action == "create": - self.permission_classes = (AllowAny,) - return super().get_permissions() - - -class TerminalTokenApi(APIView): - permission_classes = (AllowAny,) - queryset = Terminal.objects.filter(is_deleted=False) - - def get(self, request, *args, **kwargs): - try: - terminal = self.queryset.get(id=kwargs.get('terminal')) - except Terminal.DoesNotExist: - terminal = None - - token = request.query_params.get("token") - - if terminal is None: - return Response('May be reject by administrator', status=401) - - if token is None or cache.get(token, "") != str(terminal.id): - return Response('Token is not valid', status=401) - - if not terminal.is_accepted: - return Response("Terminal was not accepted yet", status=400) - - if not terminal.user or not terminal.user.access_key: - return Response("No access key generate", status=401) - - access_key = terminal.user.access_key() - data = OrderedDict() - data['access_key'] = {'id': access_key.id, 'secret': access_key.secret} - return Response(data, status=200) - class StatusViewSet(viewsets.ModelViewSet): queryset = Status.objects.all() diff --git a/apps/terminal/urls/api_urls.py b/apps/terminal/urls/api_urls.py index 5a8efe8e8..077494d01 100644 --- a/apps/terminal/urls/api_urls.py +++ b/apps/terminal/urls/api_urls.py @@ -27,8 +27,6 @@ urlpatterns = [ api.SessionReplayViewSet.as_view({'get': 'retrieve', 'post': 'create'}), name='session-replay'), path('tasks/kill-session/', api.KillSessionAPI.as_view(), name='kill-session'), - path('terminals//access-key/', api.TerminalTokenApi.as_view(), - name='terminal-access-key'), path('terminals/config/', api.TerminalConfig.as_view(), name='terminal-config'), path('commands/export/', api.CommandExportApi.as_view(), name="command-export"), path('commands/insecure-command/', api.InsecureCommandAlertAPI.as_view(), name="command-alert"), From a0cb16e5c40a8473ea0c22bd990a347eef4edcbe Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 18 Jan 2021 18:03:40 +0800 Subject: [PATCH 07/15] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E5=85=B3?= =?UTF-8?q?=E9=97=AD=E5=B7=A5=E5=8D=95API=E6=9D=83=E9=99=90,=20=E7=94=B3?= =?UTF-8?q?=E8=AF=B7=E4=BA=BA=E6=9C=89=E6=9D=83=E9=99=90=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E5=B7=A5=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/tickets/api/ticket.py | 4 ++-- apps/tickets/permissions/ticket.py | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/tickets/api/ticket.py b/apps/tickets/api/ticket.py index 79d49b37d..07b6ec89e 100644 --- a/apps/tickets/api/ticket.py +++ b/apps/tickets/api/ticket.py @@ -12,7 +12,7 @@ from common.permissions import IsValidUser, IsOrgAdmin from tickets import serializers from tickets.models import Ticket -from tickets.permissions.ticket import IsAssignee, NotClosed +from tickets.permissions.ticket import IsAssignee, IsAssigneeOrApplicant, NotClosed __all__ = ['TicketViewSet'] @@ -68,7 +68,7 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet): instance.reject(processor=request.user) return Response(serializer.data) - @action(detail=True, methods=[PUT], permission_classes=[IsOrgAdmin, IsAssignee, NotClosed]) + @action(detail=True, methods=[PUT], permission_classes=[IsAssigneeOrApplicant, NotClosed]) def close(self, request, *args, **kwargs): instance = self.get_object() serializer = self.get_serializer(instance) diff --git a/apps/tickets/permissions/ticket.py b/apps/tickets/permissions/ticket.py index c16db9fe6..dbc74e6a9 100644 --- a/apps/tickets/permissions/ticket.py +++ b/apps/tickets/permissions/ticket.py @@ -7,6 +7,12 @@ class IsAssignee(permissions.BasePermission): return obj.has_assignee(request.user) +class IsAssigneeOrApplicant(IsAssignee): + + def has_object_permission(self, request, view, obj): + return super().has_object_permission(request, view, obj) or obj.applicant == request.user + + class NotClosed(permissions.BasePermission): def has_object_permission(self, request, view, obj): return not obj.status_closed From 5fae91949981bad2f39e7cead7a74e39a5be0873 Mon Sep 17 00:00:00 2001 From: xinwen Date: Mon, 18 Jan 2021 17:22:19 +0800 Subject: [PATCH 08/15] =?UTF-8?q?fix:=20=E8=B7=B3=E6=9D=BF=E6=9C=BA?= =?UTF-8?q?=E5=8D=B1=E9=99=A9=E5=91=BD=E4=BB=A4=E5=91=8A=E8=AD=A6=E5=8F=91?= =?UTF-8?q?=E9=80=81=E9=82=AE=E4=BB=B6=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/utils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/terminal/utils.py b/apps/terminal/utils.py index d2e5b8e91..918266b56 100644 --- a/apps/terminal/utils.py +++ b/apps/terminal/utils.py @@ -71,12 +71,18 @@ def get_session_replay_url(session): def send_command_alert_mail(command): session_obj = Session.objects.get(id=command['session']) + + input = command['input'] + if isinstance(input, str): + input = input.replace('\r\n', ' ').replace('\r', ' ').replace('\n', ' ') + subject = _("Insecure Command Alert: [%(name)s->%(login_from)s@%(remote_addr)s] $%(command)s") % { 'name': command['user'], 'login_from': session_obj.get_login_from_display(), 'remote_addr': session_obj.remote_addr, - 'command': command['input'] + 'command': input } + recipient_list = settings.SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER.split(',') message = _(""" Command: %(command)s From 0842553f8a74e3d1b7f0623d1ff3f238a4397227 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 19 Jan 2021 14:36:41 +0800 Subject: [PATCH 09/15] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20celery=20?= =?UTF-8?q?=E7=AD=89=E6=97=A5=E5=BF=97=E6=96=87=E4=BB=B6=E7=9A=84=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E6=BC=8F=E6=B4=9E=20(#5469)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: xinwen --- apps/ops/utils.py | 8 +++++++- apps/ops/ws.py | 2 +- data/caution.txt | 2 ++ 3 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 data/caution.txt diff --git a/apps/ops/utils.py b/apps/ops/utils.py index d8c186dd6..5ce4494a6 100644 --- a/apps/ops/utils.py +++ b/apps/ops/utils.py @@ -1,11 +1,13 @@ # ~*~ coding: utf-8 ~*~ import os +import uuid from django.utils.translation import ugettext_lazy as _ from common.utils import get_logger, get_object_or_none from common.tasks import send_mail_async from orgs.utils import org_aware_func +from jumpserver.const import PROJECT_DIR from .models import Task, AdHoc @@ -79,8 +81,12 @@ def send_server_performance_mail(path, usage, usages): def get_task_log_path(base_path, task_id, level=2): task_id = str(task_id) + try: + uuid.UUID(task_id) + except: + return os.path.join(PROJECT_DIR, 'data', 'caution.txt') + rel_path = os.path.join(*task_id[:level], task_id + '.log') path = os.path.join(base_path, rel_path) os.makedirs(os.path.dirname(path), exist_ok=True) return path - diff --git a/apps/ops/ws.py b/apps/ops/ws.py index f21c79570..e9cb38d28 100644 --- a/apps/ops/ws.py +++ b/apps/ops/ws.py @@ -22,7 +22,7 @@ class TaskLogWebsocket(JsonWebsocketConsumer): def connect(self): user = self.scope["user"] - if user.is_authenticated and user.is_org_admin: + if user.is_authenticated: self.accept() else: self.close() diff --git a/data/caution.txt b/data/caution.txt new file mode 100644 index 000000000..4e85670a1 --- /dev/null +++ b/data/caution.txt @@ -0,0 +1,2 @@ + 你想偷看啥 !!! + What are you trying to peek at !!! \ No newline at end of file From 9126c7780dd2b83c5286a796d63e2f92f03d725a Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 19 Jan 2021 15:44:19 +0800 Subject: [PATCH 10/15] =?UTF-8?q?perf:=20=E5=B7=A5=E5=8D=95=E4=BC=98?= =?UTF-8?q?=E5=8C=96(=E5=AE=A1=E6=89=B9=E4=BA=BA=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E5=A1=AB=E5=86=99=E5=B7=A5=E5=8D=95=E5=AF=B9=E5=BA=94=E7=9A=84?= =?UTF-8?q?=E6=8E=88=E6=9D=83=E8=A7=84=E5=88=99=E5=90=8D=E7=A7=B0)=20(#546?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf: 工单优化(审批人可以填写工单对应的授权规则名称) * perf: 工单优化(优化推荐的资产、应用、系统用户等逻辑) * perf: 工单优化(优化工单邮件内容) * perf: MethodSerializer优化(优化当Serializer不需要时, 默认可以不传递对应字段) Co-authored-by: Bai --- apps/applications/serializers/application.py | 32 +++++----- apps/terminal/serializers/storage.py | 54 +++++++++++------ apps/tickets/handler/apply_application.py | 18 +++--- apps/tickets/handler/apply_asset.py | 23 ++++---- apps/tickets/handler/base.py | 8 +-- apps/tickets/serializers/ticket/meta/meta.py | 1 + .../meta/ticket_type/apply_application.py | 26 ++++++++- .../ticket/meta/ticket_type/apply_asset.py | 28 ++++++++- .../ticket/meta/ticket_type/common.py | 30 ++++++++++ apps/tickets/serializers/ticket/ticket.py | 39 +++++++------ apps/tickets/utils.py | 58 ++++++++++--------- 11 files changed, 214 insertions(+), 103 deletions(-) create mode 100644 apps/tickets/serializers/ticket/meta/ticket_type/common.py diff --git a/apps/applications/serializers/application.py b/apps/applications/serializers/application.py index 8f6d103c0..f6bb60516 100644 --- a/apps/applications/serializers/application.py +++ b/apps/applications/serializers/application.py @@ -18,22 +18,28 @@ class ApplicationSerializerMixin(serializers.Serializer): attrs = MethodSerializer() def get_attrs_serializer(self): - serializer_class = None + default_serializer = serializers.Serializer(read_only=True) if isinstance(self.instance, models.Application): - instance_type = self.instance.type - serializer_class = type_serializer_classes_mapping.get(instance_type) + _type = self.instance.type + _category = self.instance.category else: - request = self.context['request'] - query_type = request.query_params.get('type') - query_category = request.query_params.get('category') - if query_type: - serializer_class = type_serializer_classes_mapping.get(query_type) - elif query_category: - serializer_class = category_serializer_classes_mapping.get(query_category) + _type = self.context['request'].query_params.get('type') + _category = self.context['request'].query_params.get('category') - if serializer_class is None: - serializer_class = serializers.Serializer - serializer = serializer_class() + if _type: + serializer_class = type_serializer_classes_mapping.get(_type) + elif _category: + serializer_class = category_serializer_classes_mapping.get(_category) + else: + serializer_class = default_serializer + + if not serializer_class: + serializer_class = default_serializer + + if isinstance(serializer_class, type): + serializer = serializer_class() + else: + serializer = serializer_class return serializer diff --git a/apps/terminal/serializers/storage.py b/apps/terminal/serializers/storage.py index dcac31c16..ab4a813c7 100644 --- a/apps/terminal/serializers/storage.py +++ b/apps/terminal/serializers/storage.py @@ -113,16 +113,25 @@ class ReplayStorageSerializer(serializers.ModelSerializer): return _meta def get_meta_serializer(self): - serializer_class = None - query_type = self.context['request'].query_params.get('type') - if query_type: - serializer_class = replay_storage_type_serializer_classes_mapping.get(query_type) + default_serializer = serializers.Serializer(read_only=True) + if isinstance(self.instance, ReplayStorage): - instance_type = self.instance.type - serializer_class = replay_storage_type_serializer_classes_mapping.get(instance_type) - if serializer_class is None: - serializer_class = serializers.Serializer - serializer = serializer_class() + _type = self.instance.type + else: + _type = self.context['request'].query_params.get('type') + + if _type: + serializer_class = replay_storage_type_serializer_classes_mapping.get(_type) + else: + serializer_class = default_serializer + + if not serializer_class: + serializer_class = default_serializer + + if isinstance(serializer_class, type): + serializer = serializer_class() + else: + serializer = serializer_class return serializer @@ -187,14 +196,23 @@ class CommandStorageSerializer(serializers.ModelSerializer): return _meta def get_meta_serializer(self): - serializer_class = None - query_type = self.context['request'].query_params.get('type') - if query_type: - serializer_class = command_storage_type_serializer_classes_mapping.get(query_type) + default_serializer = serializers.Serializer(read_only=True) + if isinstance(self.instance, CommandStorage): - instance_type = self.instance.type - serializer_class = command_storage_type_serializer_classes_mapping.get(instance_type) - if serializer_class is None: - serializer_class = serializers.Serializer - serializer = serializer_class() + _type = self.instance.type + else: + _type = self.context['request'].query_params.get('type') + + if _type: + serializer_class = command_storage_type_serializer_classes_mapping.get(_type) + else: + serializer_class = default_serializer + + if not serializer_class: + serializer_class = default_serializer + + if isinstance(serializer_class, type): + serializer = serializer_class() + else: + serializer = serializer_class return serializer diff --git a/apps/tickets/handler/apply_application.py b/apps/tickets/handler/apply_application.py index d9c72e2bf..83f62b417 100644 --- a/apps/tickets/handler/apply_application.py +++ b/apps/tickets/handler/apply_application.py @@ -88,12 +88,13 @@ class Handler(BaseHandler): apply_category = self.ticket.meta.get('apply_category') apply_type = self.ticket.meta.get('apply_type') + approve_permission_name = self.ticket.meta.get('approve_permission_name', '') approved_applications_id = self.ticket.meta.get('approve_applications', []) approve_system_users_id = self.ticket.meta.get('approve_system_users', []) approve_date_start = self.ticket.meta.get('approve_date_start') approve_date_expired = self.ticket.meta.get('approve_date_expired') - permission_name = _('Created by ticket ({}) ({})'.format( - self.ticket.title, str(self.ticket.id)[:4]) + permission_created_by = '{}:{}'.format( + str(self.ticket.__class__.__name__), str(self.ticket.id) ) permission_comment = _( 'Created by the ticket, ' @@ -101,18 +102,19 @@ class Handler(BaseHandler): 'ticket applicant: {}, ' 'ticket processor: {}, ' 'ticket ID: {}' - ''.format( - self.ticket.title, self.ticket.applicant_display, - self.ticket.processor_display, str(self.ticket.id) - ) + ).format( + self.ticket.title, + self.ticket.applicant_display, + self.ticket.processor_display, + str(self.ticket.id) ) permissions_data = { 'id': self.ticket.id, - 'name': str(permission_name), + 'name': approve_permission_name, 'category': apply_category, 'type': apply_type, 'comment': str(permission_comment), - 'created_by': '{}:{}'.format(str(self.__class__.__name__), str(self.ticket.id)), + 'created_by': permission_created_by, 'date_start': approve_date_start, 'date_expired': approve_date_expired, } diff --git a/apps/tickets/handler/apply_asset.py b/apps/tickets/handler/apply_asset.py index d01a5c6b1..71507e7ae 100644 --- a/apps/tickets/handler/apply_asset.py +++ b/apps/tickets/handler/apply_asset.py @@ -90,13 +90,14 @@ class Handler(BaseHandler): if asset_permission: return asset_permission + approve_permission_name = self.ticket.meta.get('approve_permission_name', ) approve_assets_id = self.ticket.meta.get('approve_assets', []) approve_system_users_id = self.ticket.meta.get('approve_system_users', []) approve_actions = self.ticket.meta.get('approve_actions', Action.NONE) approve_date_start = self.ticket.meta.get('approve_date_start') approve_date_expired = self.ticket.meta.get('approve_date_expired') - permission_name = _('Created by ticket ({}) ({})'.format( - self.ticket.title, str(self.ticket.id)[:4]) + permission_created_by = '{}:{}'.format( + str(self.ticket.__class__.__name__), str(self.ticket.id) ) permission_comment = _( 'Created by the ticket, ' @@ -104,18 +105,18 @@ class Handler(BaseHandler): 'ticket applicant: {}, ' 'ticket processor: {}, ' 'ticket ID: {}' - ''.format( - self.ticket.title, - self.ticket.applicant_display, - self.ticket.processor_display, - str(self.ticket.id) - ) + ).format( + self.ticket.title, + self.ticket.applicant_display, + self.ticket.processor_display, + str(self.ticket.id) ) + permission_data = { 'id': self.ticket.id, - 'name': str(permission_name), - 'comment': permission_comment, - 'created_by': '{}:{}'.format(str(self.__class__.__name__), str(self.ticket.id)), + 'name': approve_permission_name, + 'comment': str(permission_comment), + 'created_by': permission_created_by, 'actions': approve_actions, 'date_start': approve_date_start, 'date_expired': approve_date_expired, diff --git a/apps/tickets/handler/base.py b/apps/tickets/handler/base.py index f55b51a37..a0092a96a 100644 --- a/apps/tickets/handler/base.py +++ b/apps/tickets/handler/base.py @@ -86,17 +86,17 @@ class BaseHandler(object): {}: {}, {}: {}, {}: {}, - {}: {}, {}: {} '''.format( _('Ticket title'), self.ticket.title, _('Ticket type'), self.ticket.get_type_display(), + _('Ticket status'), self.ticket.get_status_display(), + _('Ticket action'), self.ticket.get_action_display(), _('Ticket applicant'), self.ticket.applicant_display, _('Ticket assignees'), self.ticket.assignees_display, - _('Ticket processor'), self.ticket.processor_display or _('No'), - _('Ticket action'), self.ticket.get_action_display(), - _('Ticket status'), self.ticket.get_status_display() ) + if self.ticket.status_closed: + basic_body += '''{}: {}'''.format(_('Ticket processor'), self.ticket.processor_display) body = self.body_html_format.format(_("Ticket basic info"), basic_body) return body diff --git a/apps/tickets/serializers/ticket/meta/meta.py b/apps/tickets/serializers/ticket/meta/meta.py index 1b3c071a8..b423805f4 100644 --- a/apps/tickets/serializers/ticket/meta/meta.py +++ b/apps/tickets/serializers/ticket/meta/meta.py @@ -29,5 +29,6 @@ type_serializer_classes_mapping = { const.TicketTypeChoices.login_confirm.value: { 'default': login_confirm.LoginConfirmSerializer, action_open: login_confirm.ApplySerializer, + action_approve: login_confirm.LoginConfirmSerializer(read_only=True), } } diff --git a/apps/tickets/serializers/ticket/meta/ticket_type/apply_application.py b/apps/tickets/serializers/ticket/meta/ticket_type/apply_application.py index 220c04199..4b5bb00e2 100644 --- a/apps/tickets/serializers/ticket/meta/ticket_type/apply_application.py +++ b/apps/tickets/serializers/ticket/meta/ticket_type/apply_application.py @@ -1,11 +1,13 @@ from rest_framework import serializers from django.utils.translation import ugettext_lazy as _ from django.db.models import Q +from perms.models import ApplicationPermission from applications.models import Application from applications.const import ApplicationCategoryChoices, ApplicationTypeChoices from assets.models import SystemUser from orgs.utils import tmp_to_org from tickets.models import Ticket +from .common import DefaultPermissionName __all__ = [ 'ApplyApplicationSerializer', 'ApplySerializer', 'ApproveSerializer', @@ -47,6 +49,9 @@ class ApplySerializer(serializers.Serializer): class ApproveSerializer(serializers.Serializer): # 审批信息 + approve_permission_name = serializers.CharField( + max_length=128, default=DefaultPermissionName(), label=_('Permission name') + ) approve_applications = serializers.ListField( required=True, child=serializers.UUIDField(), label=_('Approve applications'), allow_null=True @@ -72,6 +77,19 @@ class ApproveSerializer(serializers.Serializer): required=True, label=_('Date expired'), allow_null=True ) + def validate_approve_permission_name(self, permission_name): + if not isinstance(self.root.instance, Ticket): + return permission_name + + with tmp_to_org(self.root.instance.org_id): + already_exists = ApplicationPermission.objects.filter(name=permission_name).exists() + if not already_exists: + return permission_name + + raise serializers.ValidationError(_( + 'Permission named `{}` already exists'.format(permission_name) + )) + def validate_approve_applications(self, approve_applications): if not isinstance(self.root.instance, Ticket): return [] @@ -118,6 +136,9 @@ class ApplyApplicationSerializer(ApplySerializer, ApproveSerializer): return [] apply_application_group = value.get('apply_application_group', []) + if not apply_application_group: + return [] + apply_type = value.get('apply_type') queries = Q() for application in apply_application_group: @@ -133,8 +154,11 @@ class ApplyApplicationSerializer(ApplySerializer, ApproveSerializer): if not isinstance(self.root.instance, Ticket): return [] - apply_type = value.get('apply_type') apply_system_user_group = value.get('apply_system_user_group', []) + if not apply_system_user_group: + return [] + + apply_type = value.get('apply_type') protocol = SystemUser.get_protocol_by_application_type(apply_type) queries = Q() for system_user in apply_system_user_group: diff --git a/apps/tickets/serializers/ticket/meta/ticket_type/apply_asset.py b/apps/tickets/serializers/ticket/meta/ticket_type/apply_asset.py index ab613e19c..acdd217e1 100644 --- a/apps/tickets/serializers/ticket/meta/ticket_type/apply_asset.py +++ b/apps/tickets/serializers/ticket/meta/ticket_type/apply_asset.py @@ -2,9 +2,11 @@ from django.utils.translation import ugettext_lazy as _ from django.db.models import Q from rest_framework import serializers from perms.serializers import ActionsField +from perms.models import AssetPermission from assets.models import Asset, SystemUser from orgs.utils import tmp_to_org from tickets.models import Ticket +from .common import DefaultPermissionName __all__ = [ @@ -44,6 +46,9 @@ class ApplySerializer(serializers.Serializer): class ApproveSerializer(serializers.Serializer): # 审批信息 + approve_permission_name = serializers.CharField( + max_length=128, default=DefaultPermissionName(), label=_('Permission name') + ) approve_assets = serializers.ListField( required=True, allow_null=True, child=serializers.UUIDField(), label=_('Approve assets') ) @@ -76,6 +81,19 @@ class ApproveSerializer(serializers.Serializer): required=True, label=_('Date expired'), allow_null=True ) + def validate_approve_permission_name(self, permission_name): + if not isinstance(self.root.instance, Ticket): + return permission_name + + with tmp_to_org(self.root.instance.org_id): + already_exists = AssetPermission.objects.filter(name=permission_name).exists() + if not already_exists: + return permission_name + + raise serializers.ValidationError(_( + 'Permission named `{}` already exists'.format(permission_name) + )) + def validate_approve_assets(self, approve_assets): if not isinstance(self.root.instance, Ticket): return [] @@ -118,10 +136,13 @@ class ApplyAssetSerializer(ApplySerializer, ApproveSerializer): apply_ip_group = value.get('apply_ip_group', []) apply_hostname_group = value.get('apply_hostname_group', []) - queries = Q(ip__in=apply_ip_group) + queries = Q() + if apply_ip_group: + queries |= Q(ip__in=apply_ip_group) for hostname in apply_hostname_group: queries |= Q(hostname__icontains=hostname) - + if not queries: + return [] with tmp_to_org(self.root.instance.org_id): assets_id = Asset.objects.filter(queries).values_list('id', flat=True)[:5] assets_id = [str(asset_id) for asset_id in assets_id] @@ -132,6 +153,9 @@ class ApplyAssetSerializer(ApplySerializer, ApproveSerializer): return [] apply_system_user_group = value.get('apply_system_user_group', []) + if not apply_system_user_group: + return [] + queries = Q() for system_user in apply_system_user_group: queries |= Q(username__icontains=system_user) diff --git a/apps/tickets/serializers/ticket/meta/ticket_type/common.py b/apps/tickets/serializers/ticket/meta/ticket_type/common.py new file mode 100644 index 000000000..2d43f6a81 --- /dev/null +++ b/apps/tickets/serializers/ticket/meta/ticket_type/common.py @@ -0,0 +1,30 @@ +from django.utils.translation import ugettext as _ +from tickets.models import Ticket + + +__all__ = ['DefaultPermissionName', 'get_default_permission_name'] + + +def get_default_permission_name(ticket): + name = '' + if isinstance(ticket, Ticket): + name = _('Created by ticket ({}-{})').format(ticket.title, str(ticket.id)[:4]) + return name + + +class DefaultPermissionName(object): + default = None + + @staticmethod + def _construct_default_permission_name(serializer_field): + permission_name = '' + ticket = serializer_field.root.instance + if isinstance(ticket, Ticket): + permission_name = get_default_permission_name(ticket) + return permission_name + + def set_context(self, serializer_field): + self.default = self._construct_default_permission_name(serializer_field) + + def __call__(self): + return self.default diff --git a/apps/tickets/serializers/ticket/ticket.py b/apps/tickets/serializers/ticket/ticket.py index 1ca217adb..c28b9a9f1 100644 --- a/apps/tickets/serializers/ticket/ticket.py +++ b/apps/tickets/serializers/ticket/ticket.py @@ -38,31 +38,34 @@ class TicketSerializer(OrgResourceModelSerializerMixin): ] def get_meta_serializer(self): - request = self.context['request'] - default_serializer_class = serializers.Serializer + default_serializer = serializers.Serializer(read_only=True) if isinstance(self.instance, Ticket): _type = self.instance.type else: - _type = request.query_params.get('type') + _type = self.context['request'].query_params.get('type') - if not _type: - return default_serializer_class() + if _type: + action_serializer_classes_mapping = type_serializer_classes_mapping.get(_type) + if action_serializer_classes_mapping: + query_action = self.context['request'].query_params.get('action') + action = query_action if query_action else self.context['view'].action + serializer_class = action_serializer_classes_mapping.get(action) + if not serializer_class: + serializer_class = action_serializer_classes_mapping.get('default') + else: + serializer_class = default_serializer + else: + serializer_class = default_serializer - action_serializer_classes_mapping = type_serializer_classes_mapping.get(_type) - if not action_serializer_classes_mapping: - return default_serializer_class() + if not serializer_class: + serializer_class = default_serializer - query_action = request.query_params.get('action') - _action = query_action if query_action else self.context['view'].action - serializer_class = action_serializer_classes_mapping.get(_action) - if serializer_class: - return serializer_class() + if isinstance(serializer_class, type): + serializer = serializer_class() + else: + serializer = serializer_class - serializer_class = action_serializer_classes_mapping.get('default') - if serializer_class: - return serializer_class() - - return default_serializer_class() + return serializer class TicketDisplaySerializer(TicketSerializer): diff --git a/apps/tickets/utils.py b/apps/tickets/utils.py index 523d0f102..1bd789fda 100644 --- a/apps/tickets/utils.py +++ b/apps/tickets/utils.py @@ -10,6 +10,20 @@ from . import const logger = get_logger(__file__) +EMAIL_TEMPLATE = ''' +
+

+ {title} + + {ticket_detail_url_description} + +

+
+ {body} +
+
+''' + def send_ticket_applied_mail_to_assignees(ticket): if not ticket.assignees: @@ -18,22 +32,13 @@ def send_ticket_applied_mail_to_assignees(ticket): ) return - subject = _('New Ticket: {} ({})'.format(ticket.title, ticket.get_type_display())) - ticket_detail_url = urljoin( - settings.SITE_URL, const.TICKET_DETAIL_URL.format(id=str(ticket.id)) - ) - message = """ -
-

{title} {ticket_detail_url_description}

-
- {body} -
-
- """.format( - title=_('Your has a new ticket, from applicant - {}').format(str(ticket.applicant)), - ticket_detail_url=ticket_detail_url, - ticket_detail_url_description=_('click here to review'), - body=ticket.body.replace('\n', '
'), + ticket_detail_url = urljoin(settings.SITE_URL, const.TICKET_DETAIL_URL.format(id=str(ticket.id))) + subject = _('New Ticket - {} ({})').format(ticket.title, ticket.get_type_display()) + message = EMAIL_TEMPLATE.format( + title=_('Your has a new ticket, applicant - {}').format(str(ticket.applicant_display)), + ticket_detail_url=ticket_detail_url, + ticket_detail_url_description=_('click here to review'), + body=ticket.body.replace('\n', '
'), ) if settings.DEBUG: logger.debug(message) @@ -45,18 +50,15 @@ def send_ticket_processed_mail_to_applicant(ticket): if not ticket.applicant: logger.error("Not found applicant: {}({})".format(ticket.title, ticket.id)) return - subject = _('Ticket has processed: {} ({})').format(ticket.title, ticket.processor_display) - message = """ -
-

{title}

-
- {body} -
-
- """.format( - title=_('Your ticket has been ({}) processed').format(ticket.processor_display), - body=ticket.body.replace('\n', '
'), - ) + + ticket_detail_url = urljoin(settings.SITE_URL, const.TICKET_DETAIL_URL.format(id=str(ticket.id))) + subject = _('Ticket has processed - {} ({})').format(ticket.title, ticket.processor_display) + message = EMAIL_TEMPLATE.format( + title=_('Your ticket has been processed, processor - {}').format(ticket.processor_display), + ticket_detail_url=ticket_detail_url, + ticket_detail_url_description=_('click here to review'), + body=ticket.body.replace('\n', '
'), + ) if settings.DEBUG: logger.debug(message) recipient_list = [ticket.applicant.email] From 9fee82cd14bd2c18a5713fe1ad294cbfe2b430be Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 19 Jan 2021 19:03:42 +0800 Subject: [PATCH 11/15] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E5=BD=95?= =?UTF-8?q?=E5=83=8F=E5=AD=98=E5=82=A8endpoint=E6=A0=A1=E9=AA=8C=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/serializers/storage.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/terminal/serializers/storage.py b/apps/terminal/serializers/storage.py index ab4a813c7..0f3bb4df4 100644 --- a/apps/terminal/serializers/storage.py +++ b/apps/terminal/serializers/storage.py @@ -14,6 +14,13 @@ from .. import const # -------------------------- +def replay_storage_endpoint_format_validator(endpoint): + h = urlparse(endpoint) + if h.path: + raise serializers.ValidationError(_('Endpoint invalid: remove path `{}`').format(h.path)) + return endpoint + + class ReplayStorageTypeBaseSerializer(serializers.Serializer): BUCKET = serializers.CharField( required=True, max_length=1024, label=_('Bucket'), allow_null=True @@ -27,6 +34,7 @@ class ReplayStorageTypeBaseSerializer(serializers.Serializer): allow_null=True, ) ENDPOINT = serializers.CharField( + validators=[replay_storage_endpoint_format_validator], required=True, max_length=1024, label=_('Endpoint'), allow_null=True, ) @@ -38,6 +46,7 @@ class ReplayStorageTypeS3Serializer(ReplayStorageTypeBaseSerializer): Such as: http://s3.cn-north-1.amazonaws.com.cn ''' ENDPOINT = serializers.CharField( + validators=[replay_storage_endpoint_format_validator], required=True, max_length=1024, label=_('Endpoint'), help_text=_(endpoint_help_text), allow_null=True, ) @@ -67,6 +76,7 @@ class ReplayStorageTypeOSSSerializer(ReplayStorageTypeBaseSerializer): Such as: http://oss-cn-hangzhou.aliyuncs.com ''' ENDPOINT = serializers.CharField( + validators=[replay_storage_endpoint_format_validator], max_length=1024, label=_('Endpoint'), help_text=_(endpoint_help_text), allow_null=True, ) @@ -139,7 +149,7 @@ class ReplayStorageSerializer(serializers.ModelSerializer): # --------------------------- -def es_host_format_validator(host): +def command_storage_es_host_format_validator(host): h = urlparse(host) default_error_msg = _('The address format is incorrect') if h.scheme not in ['http', 'https']: @@ -163,8 +173,8 @@ class CommandStorageTypeESSerializer(serializers.Serializer): (eg: http://www.jumpserver.a.com, http://www.jumpserver.b.com) ''' HOSTS = serializers.ListField( - child=serializers.CharField(validators=[es_host_format_validator]), label=_('Hosts'), - help_text=_(hosts_help_text), allow_null=True + child=serializers.CharField(validators=[command_storage_es_host_format_validator]), + label=_('Hosts'), help_text=_(hosts_help_text), allow_null=True ) INDEX = serializers.CharField( max_length=1024, default='jumpserver', label=_('Index'), allow_null=True From 4de2ae607d9d75c1d4472ebd773208827683643c Mon Sep 17 00:00:00 2001 From: xinwen Date: Tue, 19 Jan 2021 18:57:47 +0800 Subject: [PATCH 12/15] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E5=AE=A1=E8=AE=A1->=20=E6=89=B9=E9=87=8F=E5=91=BD?= =?UTF-8?q?=E4=BB=A4->=20=E7=94=A8=E6=88=B7=E6=98=BE=E7=A4=BA=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/audits/serializers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/audits/serializers.py b/apps/audits/serializers.py index 53a17298d..b94ffa8c9 100644 --- a/apps/audits/serializers.py +++ b/apps/audits/serializers.py @@ -86,8 +86,7 @@ class CommandExecutionSerializer(serializers.ModelSerializer): @classmethod def setup_eager_loading(cls, queryset): """ Perform necessary eager loading of data. """ - queryset = queryset.annotate(user_display=F('user__name'))\ - .annotate(run_as_display=F('run_as__name')) + queryset = queryset.prefetch_related('user', 'run_as', 'hosts') return queryset From 44a42e4739b6dfa2748f1a170f3598c00f3d7927 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 19 Jan 2021 19:41:05 +0800 Subject: [PATCH 13/15] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E7=9B=B8=E5=85=B3tickets=E4=B8=BA=E8=87=AA=E5=B7=B1?= =?UTF-8?q?=E7=94=B3=E8=AF=B7=E7=9A=84=E6=88=96=E8=80=85=E5=BE=85=E5=8F=97?= =?UTF-8?q?=E7=90=86=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/tickets/api/ticket.py | 2 +- apps/tickets/models/ticket.py | 32 +++----------------------------- 2 files changed, 4 insertions(+), 30 deletions(-) diff --git a/apps/tickets/api/ticket.py b/apps/tickets/api/ticket.py index 07b6ec89e..91a585298 100644 --- a/apps/tickets/api/ticket.py +++ b/apps/tickets/api/ticket.py @@ -50,7 +50,7 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet): instance = serializer.save() instance.open(applicant=self.request.user) - @action(detail=False, methods=[POST]) + @action(detail=False, methods=[POST], permission_classes=[IsValidUser, ]) def open(self, request, *args, **kwargs): return super().create(request, *args, **kwargs) diff --git a/apps/tickets/models/ticket.py b/apps/tickets/models/ticket.py index 97d99e4b3..41d23c8b0 100644 --- a/apps/tickets/models/ticket.py +++ b/apps/tickets/models/ticket.py @@ -148,35 +148,9 @@ class Ticket(CommonModelMixin, OrgModelMixin): @classmethod def get_user_related_tickets(cls, user): - queries = None - tickets = cls.all() - if user.is_superuser: - pass - elif user.is_super_auditor: - pass - elif user.is_org_admin: - admin_orgs_id = [ - str(org_id) for org_id in user.admin_orgs.values_list('id', flat=True) - ] - assigned_tickets_id = [ - str(ticket_id) for ticket_id in user.assigned_tickets.values_list('id', flat=True) - ] - queries = Q(applicant=user) - queries |= Q(processor=user) - queries |= Q(org_id__in=admin_orgs_id) - queries |= Q(id__in=assigned_tickets_id) - elif user.is_org_auditor: - audit_orgs_id = [ - str(org_id) for org_id in user.audit_orgs.values_list('id', flat=True) - ] - queries = Q(org_id__in=audit_orgs_id) - elif user.is_common_user: - queries = Q(applicant=user) - else: - tickets = cls.objects.none() - if queries: - tickets = tickets.filter(queries) - return tickets.distinct() + queries = Q(applicant=user) | Q(assignees=user) + tickets = cls.all().filter(queries).distinct() + return tickets @classmethod def all(cls): From 46fbc19697e5df7f985be320cb1c6d23c2123013 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 19 Jan 2021 20:04:14 +0800 Subject: [PATCH 14/15] =?UTF-8?q?i18n:=20=E4=BF=AE=E6=94=B9=E7=BF=BB?= =?UTF-8?q?=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/zh/LC_MESSAGES/django.mo | Bin 63233 -> 63477 bytes apps/locale/zh/LC_MESSAGES/django.po | 227 ++++++++++++++------------- 2 files changed, 120 insertions(+), 107 deletions(-) diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 62f5281f5327828c2a26dd4c340d62fee69d9e54..0e3edb30136a63e17b399f49266e65f8db05ef09 100644 GIT binary patch delta 19701 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 delta 19499 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 Lmr(Bc7N7qE5Paa~ diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index b3c6392c0..d5e9ddc26 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-01-18 16:42+0800\n" +"POT-Creation-Date: 2021-01-19 20:03+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -58,22 +58,22 @@ msgid "Name" msgstr "名称" #: applications/models/application.py:12 -#: applications/serializers/application.py:41 assets/models/label.py:21 +#: applications/serializers/application.py:47 assets/models/label.py:21 #: perms/models/application_permission.py:20 #: perms/serializers/application/permission.py:16 #: perms/serializers/application/user_permission.py:33 -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:18 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:20 msgid "Category" msgstr "种类" #: applications/models/application.py:15 -#: applications/serializers/application.py:42 assets/models/cmd_filter.py:52 +#: applications/serializers/application.py:48 assets/models/cmd_filter.py:52 #: perms/models/application_permission.py:23 #: perms/serializers/application/permission.py:17 #: perms/serializers/application/user_permission.py:34 #: terminal/models/storage.py:18 terminal/models/storage.py:58 #: tickets/models/ticket.py:38 -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:25 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:27 #: users/templates/users/user_granted_database_app.html:35 msgid "Type" msgstr "类型" @@ -268,7 +268,7 @@ msgstr "主机名" #: assets/models/asset.py:194 assets/models/domain.py:54 #: assets/models/user.py:120 terminal/serializers/session.py:29 -#: terminal/serializers/storage.py:59 +#: terminal/serializers/storage.py:68 msgid "Protocol" msgstr "协议" @@ -292,7 +292,7 @@ msgstr "激活" #: assets/models/asset.py:203 assets/models/cluster.py:19 #: assets/models/user.py:66 templates/_nav.html:44 -#: xpack/plugins/cloud/models.py:143 xpack/plugins/cloud/serializers.py:126 +#: xpack/plugins/cloud/models.py:143 xpack/plugins/cloud/serializers.py:137 msgid "Admin user" msgstr "管理用户" @@ -602,7 +602,7 @@ msgstr "ssh私钥" #: users/templates/users/user_asset_permission.html:41 #: users/templates/users/user_asset_permission.html:73 #: users/templates/users/user_asset_permission.html:158 -#: xpack/plugins/cloud/models.py:139 xpack/plugins/cloud/serializers.py:127 +#: xpack/plugins/cloud/models.py:139 xpack/plugins/cloud/serializers.py:138 msgid "Node" msgstr "节点" @@ -994,10 +994,10 @@ msgstr "成功" #: audits/models.py:43 ops/models/command.py:28 perms/models/base.py:52 #: terminal/models/session.py:51 -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:41 -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:69 -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:38 -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:73 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:43 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:74 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:40 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:78 #: xpack/plugins/change_auth_plan/models.py:177 #: xpack/plugins/change_auth_plan/models.py:307 #: xpack/plugins/gathered_user/models.py:76 @@ -1129,7 +1129,7 @@ msgstr "是否成功" msgid "Result" msgstr "结果" -#: audits/serializers.py:79 terminal/serializers/storage.py:157 +#: audits/serializers.py:79 terminal/serializers/storage.py:177 msgid "Hosts" msgstr "主机" @@ -1783,11 +1783,11 @@ msgstr "定期清除Celery日志" msgid "Task log" msgstr "任务列表" -#: ops/utils.py:62 +#: ops/utils.py:64 msgid "Update task content: {}" msgstr "更新任务内容: {}" -#: ops/utils.py:72 +#: ops/utils.py:74 msgid "Disk used more than 80%: {} => {}" msgstr "磁盘使用率超过 80%: {} => {}" @@ -1801,7 +1801,7 @@ msgstr "当前组织不能被删除" #: orgs/mixins/models.py:56 orgs/mixins/serializers.py:25 orgs/models.py:41 #: orgs/models.py:422 orgs/serializers.py:100 -#: tickets/serializers/ticket/ticket.py:78 +#: tickets/serializers/ticket/ticket.py:81 msgid "Organization" msgstr "组织" @@ -1901,10 +1901,10 @@ msgid "User group" msgstr "用户组" #: perms/models/base.py:53 -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:44 -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:72 -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:41 -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:76 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:46 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:77 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:43 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:81 #: users/models/user.py:556 users/templates/users/user_detail.html:93 #: users/templates/users/user_profile.html:120 msgid "Date expired" @@ -2714,60 +2714,64 @@ msgstr "是否可重放" msgid "Can join" msgstr "是否可加入" -#: terminal/serializers/storage.py:19 +#: terminal/serializers/storage.py:20 +msgid "Endpoint invalid: remove path `{}`" +msgstr "端点无效: 移除路径 `{}`" + +#: terminal/serializers/storage.py:26 msgid "Bucket" msgstr "桶名称" -#: terminal/serializers/storage.py:22 +#: terminal/serializers/storage.py:29 msgid "Access key" msgstr "" -#: terminal/serializers/storage.py:26 +#: terminal/serializers/storage.py:33 msgid "Secret key" msgstr "" -#: terminal/serializers/storage.py:30 terminal/serializers/storage.py:41 -#: terminal/serializers/storage.py:70 +#: terminal/serializers/storage.py:38 terminal/serializers/storage.py:50 +#: terminal/serializers/storage.py:80 msgid "Endpoint" msgstr "端点" -#: terminal/serializers/storage.py:56 xpack/plugins/cloud/models.py:276 +#: terminal/serializers/storage.py:65 xpack/plugins/cloud/models.py:276 msgid "Region" msgstr "地域" -#: terminal/serializers/storage.py:80 +#: terminal/serializers/storage.py:90 msgid "Container name" msgstr "容器名称" -#: terminal/serializers/storage.py:82 +#: terminal/serializers/storage.py:92 msgid "Account name" msgstr "账户名称" -#: terminal/serializers/storage.py:83 +#: terminal/serializers/storage.py:93 msgid "Account key" msgstr "账户密钥" -#: terminal/serializers/storage.py:86 +#: terminal/serializers/storage.py:96 msgid "Endpoint suffix" msgstr "端点后缀" -#: terminal/serializers/storage.py:135 +#: terminal/serializers/storage.py:154 msgid "The address format is incorrect" msgstr "地址格式不正确" -#: terminal/serializers/storage.py:142 +#: terminal/serializers/storage.py:161 msgid "Host invalid" msgstr "主机无效" -#: terminal/serializers/storage.py:145 +#: terminal/serializers/storage.py:164 msgid "Port invalid" msgstr "端口无效" -#: terminal/serializers/storage.py:161 +#: terminal/serializers/storage.py:180 msgid "Index" msgstr "索引" -#: terminal/serializers/storage.py:164 +#: terminal/serializers/storage.py:183 msgid "Doc type" msgstr "文档类型" @@ -2775,14 +2779,14 @@ msgstr "文档类型" msgid "Not found" msgstr "没有发现" -#: terminal/utils.py:74 +#: terminal/utils.py:79 #, python-format msgid "" "Insecure Command Alert: [%(name)s->%(login_from)s@%(remote_addr)s] $" "%(command)s" msgstr "危险命令告警: [%(name)s->%(login_from)s@%(remote_addr)s] $%(command)s" -#: terminal/utils.py:81 +#: terminal/utils.py:87 #, python-format msgid "" "\n" @@ -2879,11 +2883,7 @@ msgstr "批准的开始日期" msgid "Approved date expired" msgstr "批准的失效日期" -#: tickets/handler/apply_application.py:95 tickets/handler/apply_asset.py:98 -msgid "Created by ticket ({}) ({})" -msgstr "通过工单创建 ({}) ({})" - -#: tickets/handler/apply_application.py:99 tickets/handler/apply_asset.py:102 +#: tickets/handler/apply_application.py:100 tickets/handler/apply_asset.py:103 msgid "" "Created by the ticket, ticket title: {}, ticket applicant: {}, ticket " "processor: {}, ticket ID: {}" @@ -2914,47 +2914,43 @@ msgstr "批准的动作" msgid "User {} {} the ticket" msgstr "用户 {} {} 这个工单" -#: tickets/handler/base.py:89 -msgid "Ticket basic info" -msgstr "工单基本信息" - -#: tickets/handler/base.py:90 +#: tickets/handler/base.py:91 msgid "Ticket title" msgstr "工单标题" -#: tickets/handler/base.py:91 +#: tickets/handler/base.py:92 msgid "Ticket type" msgstr "工单类型" -#: tickets/handler/base.py:92 -msgid "Ticket applicant" -msgstr "工单申请人" - #: tickets/handler/base.py:93 -msgid "Ticket assignees" -msgstr "工单受理人" +msgid "Ticket status" +msgstr "工单状态" #: tickets/handler/base.py:94 -msgid "Ticket processor" -msgstr "工单处理人" - -#: tickets/handler/base.py:94 -msgid "No" -msgstr "无" - -#: tickets/handler/base.py:95 msgid "Ticket action" msgstr "工单动作" +#: tickets/handler/base.py:95 +msgid "Ticket applicant" +msgstr "工单申请人" + #: tickets/handler/base.py:96 -msgid "Ticket status" -msgstr "工单状态" +msgid "Ticket assignees" +msgstr "工单受理人" + +#: tickets/handler/base.py:99 +msgid "Ticket processor" +msgstr "工单处理人" + +#: tickets/handler/base.py:100 +msgid "Ticket basic info" +msgstr "工单基本信息" #: tickets/handler/base.py:114 msgid "Ticket applied info" msgstr "工单申请信息" -#: tickets/handler/base.py:124 +#: tickets/handler/base.py:119 msgid "Ticket approved info" msgstr "工单批准信息" @@ -3010,73 +3006,87 @@ msgstr "受理人" msgid "Assignees display" msgstr "受理人 (显示名称)" -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:22 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:24 msgid "Category display" msgstr "种类 (显示名称)" -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:29 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:31 #: tickets/serializers/ticket/ticket.py:19 msgid "Type display" msgstr "类型 (显示名称)" -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:33 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:35 msgid "Application group" msgstr "应用组" -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:37 -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:26 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:39 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:28 msgid "System user group" msgstr "系统用户组" -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:51 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:53 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:50 +msgid "Permission name" +msgstr "授权名称" + +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:56 msgid "Approve applications" msgstr "批准的应用" -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:56 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:61 msgid "Approve applications display" msgstr "批准的应用 (显示名称)" -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:60 -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:57 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:65 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:62 msgid "Approve system users" msgstr "批准的系统用户" -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:65 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:70 msgid "Approve system user display" msgstr "批准的系统用户 (显示名称)" -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:89 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:90 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:94 +msgid "Permission named `{}` already exists" +msgstr "授权名称 `{}` 已存在" + +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:107 msgid "No `Application` are found under Organization `{}`" msgstr "在组织 `{}` 下没有发现 `应用`" -#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:107 -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:106 +#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:125 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:124 msgid "No `SystemUser` are found under Organization `{}`" msgstr "在组织 `{}` 下没有发现 `系统用户`" -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:18 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:20 msgid "IP group" msgstr "IP组" -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:22 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:24 msgid "Hostname group" msgstr "主机名组" -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:34 -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:52 -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:61 -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:69 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:36 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:57 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:66 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:74 msgid "Approve assets display" msgstr "批准的资产 (显示名称)" -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:48 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:53 msgid "Approve assets" msgstr "批准的资产" -#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:90 +#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:108 msgid "No `Asset` are found under Organization `{}`" msgstr "在组织 `{}` 下没有发现 `资产`" +#: tickets/serializers/ticket/meta/ticket_type/common.py:11 +msgid "Created by ticket ({}-{})" +msgstr "通过工单创建 ({}-{})" + #: tickets/serializers/ticket/meta/ticket_type/login_confirm.py:20 msgid "Login datetime" msgstr "登录日期" @@ -3089,39 +3099,39 @@ msgstr "动作 (显示名称)" msgid "Status display" msgstr "状态(显示名称)" -#: tickets/serializers/ticket/ticket.py:96 +#: tickets/serializers/ticket/ticket.py:99 msgid "" "The `type` in the submission data (`{}`) is different from the type in the " "request url (`{}`)" msgstr "提交数据中的类型 (`{}`) 与请求URL地址中的类型 (`{}`) 不一致" -#: tickets/serializers/ticket/ticket.py:106 +#: tickets/serializers/ticket/ticket.py:109 msgid "The organization `{}` does not exist" msgstr "组织 `{}` 不存在" -#: tickets/serializers/ticket/ticket.py:117 +#: tickets/serializers/ticket/ticket.py:120 msgid "None of the assignees belong to Organization `{}` admins" msgstr "所有受理人都不属于组织 `{}` 下的管理员" -#: tickets/utils.py:21 -msgid "New Ticket: {} ({})" -msgstr "新工单: {} ({})" +#: tickets/utils.py:36 +msgid "New Ticket - {} ({})" +msgstr "新工单 - {} ({})" -#: tickets/utils.py:33 -msgid "Your has a new ticket, from applicant - {}" -msgstr "你有一个新的工单, 来自申请人 - {}" +#: tickets/utils.py:38 +msgid "Your has a new ticket, applicant - {}" +msgstr "你有一个新的工单, 申请人 - {}" -#: tickets/utils.py:35 +#: tickets/utils.py:40 tickets/utils.py:59 msgid "click here to review" msgstr "点击查看" -#: tickets/utils.py:48 -msgid "Ticket has processed: {} ({})" -msgstr "工单已处理: {} ({})" +#: tickets/utils.py:55 +msgid "Ticket has processed - {} ({})" +msgstr "工单已处理 - {} ({})" #: tickets/utils.py:57 -msgid "Your ticket has been ({}) processed" -msgstr "你的工单已被 ({}) 处理" +msgid "Your ticket has been processed, processor - {}" +msgstr "你的工单已被处理, 处理人 - {}" #: users/api/user.py:199 msgid "Could not reset self otp, use profile reset instead" @@ -3358,7 +3368,7 @@ msgstr "安全令牌验证" #: users/templates/users/_base_otp.html:14 users/templates/users/_user.html:13 #: users/templates/users/user_profile_update.html:55 -#: xpack/plugins/cloud/models.py:125 xpack/plugins/cloud/serializers.py:125 +#: xpack/plugins/cloud/models.py:125 xpack/plugins/cloud/serializers.py:136 msgid "Account" msgstr "账户" @@ -4322,7 +4332,7 @@ msgstr "实例名称" msgid "Instance name and Partial IP" msgstr "实例名称和部分IP" -#: xpack/plugins/cloud/models.py:128 xpack/plugins/cloud/serializers.py:101 +#: xpack/plugins/cloud/models.py:128 xpack/plugins/cloud/serializers.py:112 msgid "Regions" msgstr "地域" @@ -4334,7 +4344,7 @@ msgstr "实例" msgid "Hostname strategy" msgstr "主机名策略" -#: xpack/plugins/cloud/models.py:147 xpack/plugins/cloud/serializers.py:129 +#: xpack/plugins/cloud/models.py:147 xpack/plugins/cloud/serializers.py:140 msgid "Always update" msgstr "总是更新" @@ -4466,15 +4476,15 @@ msgstr "租户ID" msgid "Subscription ID" msgstr "订阅ID" -#: xpack/plugins/cloud/serializers.py:99 +#: xpack/plugins/cloud/serializers.py:110 msgid "History count" msgstr "执行次数" -#: xpack/plugins/cloud/serializers.py:100 +#: xpack/plugins/cloud/serializers.py:111 msgid "Instance count" msgstr "实例个数" -#: xpack/plugins/cloud/serializers.py:128 +#: xpack/plugins/cloud/serializers.py:139 #: xpack/plugins/gathered_user/serializers.py:20 msgid "Periodic display" msgstr "定时执行" @@ -4566,3 +4576,6 @@ msgstr "旗舰版" #: xpack/plugins/license/models.py:77 msgid "Community edition" msgstr "社区版" + +#~ msgid "No" +#~ msgstr "无" From 09d91d8bf365b5abd528e059d74c5db413c83437 Mon Sep 17 00:00:00 2001 From: xinwen Date: Tue, 19 Jan 2021 17:29:44 +0800 Subject: [PATCH 15/15] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=B9=B3=E5=8F=B0=E5=88=9B=E5=BB=BA=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/serializers/asset.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/assets/serializers/asset.py b/apps/assets/serializers/asset.py index 66effa20b..a8ce0f3ee 100644 --- a/apps/assets/serializers/asset.py +++ b/apps/assets/serializers/asset.py @@ -2,7 +2,7 @@ # from rest_framework import serializers from django.db.models import F - +from django.core.validators import RegexValidator from django.utils.translation import ugettext_lazy as _ from orgs.mixins.serializers import BulkOrgResourceModelSerializer @@ -177,6 +177,14 @@ class AssetDisplaySerializer(AssetSerializer): class PlatformSerializer(serializers.ModelSerializer): meta = serializers.DictField(required=False, allow_null=True) + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + # TODO 修复 drf SlugField RegexValidator bug,之后记得删除 + validators = self.fields['name'].validators + if isinstance(validators[-1], RegexValidator): + validators.pop() + class Meta: model = Platform fields = [