From 4b7af1457d14e5779d47fb4b6b65dc5b9f382d24 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 17 May 2018 11:39:04 +0800 Subject: [PATCH] =?UTF-8?q?[Update]=20=E7=B3=BB=E7=BB=9F=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=B8=85=E9=99=A4=E8=AE=A4=E8=AF=81=E7=9A=84?= =?UTF-8?q?=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/system_user.py | 7 +- apps/assets/models/base.py | 1 + .../templates/assets/system_user_detail.html | 25 +++++-- apps/i18n/zh/LC_MESSAGES/django.mo | Bin 33242 -> 33388 bytes apps/i18n/zh/LC_MESSAGES/django.po | 61 +++++++++++------- apps/users/models/group.py | 2 +- 6 files changed, 67 insertions(+), 29 deletions(-) diff --git a/apps/assets/api/system_user.py b/apps/assets/api/system_user.py index 1be316567..66d62232d 100644 --- a/apps/assets/api/system_user.py +++ b/apps/assets/api/system_user.py @@ -40,7 +40,7 @@ class SystemUserViewSet(BulkModelViewSet): permission_classes = (IsSuperUserOrAppUser,) -class SystemUserAuthInfoApi(generics.RetrieveUpdateAPIView): +class SystemUserAuthInfoApi(generics.RetrieveUpdateDestroyAPIView): """ Get system user auth info """ @@ -48,6 +48,11 @@ class SystemUserAuthInfoApi(generics.RetrieveUpdateAPIView): permission_classes = (IsSuperUserOrAppUser,) serializer_class = serializers.SystemUserAuthSerializer + def destroy(self, request, *args, **kwargs): + instance = self.get_object() + instance.clear_auth() + return Response(status=204) + class SystemUserPushApi(generics.RetrieveAPIView): """ diff --git a/apps/assets/models/base.py b/apps/assets/models/base.py index 11afd92cf..cb9bb96ae 100644 --- a/apps/assets/models/base.py +++ b/apps/assets/models/base.py @@ -107,6 +107,7 @@ class AssetUser(models.Model): def clear_auth(self): self._password = '' self._private_key = '' + self._public_key = '' self.save() def auto_gen_auth(self): diff --git a/apps/assets/templates/assets/system_user_detail.html b/apps/assets/templates/assets/system_user_detail.html index cc686a62b..9a7bc255a 100644 --- a/apps/assets/templates/assets/system_user_detail.html +++ b/apps/assets/templates/assets/system_user_detail.html @@ -107,14 +107,14 @@
-
+
{% trans 'Quick update' %}
- + - {% if system_user.auto_push %} + - {% endif %} + + + + + + {# #} {# #} {# ?u2HiM1)~BF{rI$5KGhZ{8VJPiu zQMcd|)PlY;52Lp9xS4NWH=VIw{}5EaNVCdV-haK{b*w{YEKT0sI*dSF$pj3?`B({8 zpkA-t7>#GJHWnV|ec;5S#z{k+KM1w(Y-;UX1!Na~LFR@wx$(w4Xw z(=ZbAt^O`*2LdN}_dE>sB@~50SOzs-460vU)B+OCWV2f}3ceMhCd{^m=~lnc>eu8< zu2j-hk36e6WnRMS)Zena%0zF(I;j4w%uc8!^hPahs5u(7MAw{dzKlBmb<_%1Oyp*1 zfDftAhv`1lK;NLA`|nXV=@jxm=L&x`z_aYJ9E&=C1~$b-sDTfo#`)FS|1ck*UWc$r z-gz;TtYbqeG++y}qjl(M`C!Y(paz(3`4V$2YQpWPaSossas;)&d{p~Q)J=6Jd%3?$ zL0c7yIx)(Ow)(neB5HtUmbb&2-JJNqrHbGNB96ahCFY;vnU=xEbdV-6%hf z{(k)7SYL?yf15%J8gwLLI`$_z5r2`thgDJU%3VUo??e|nM|mltK5?4RbF+bnCA9UY zh-ub0fU=Gd7El^jGQaPbPKTc;4MzQ6P#O>+U@7+Cm(K|E>IIl>?I$Ke-fWjZisvi zJD*d2iijqL5jrjrZxQ#%`AOxxgWqBk;!WZ!;%`F7@4Ekd>^Wc2sWx$s@?|2L7)kyk zF^MQaX%UNVEHNX&#YWPcM4BX|1ObBxrCqH|8CafR~$p5 zj$&93%M%f7SHZF0+S9QYQNbD}TKy;3g1TGyowc>cYvjIn-|E(2p5}kkPAqGxy}FfK zQVwSFaPkI}{~>g|MqU#$3H>tIK%PYC({dv&CUhJ!U!=T>NG7^cSIz3(1r+{6{6d3{ zjvoL1Jx$xgWKsBlD9K{Rk$-AEex~jQvDESp@m2DI<2lNokgO$k5FN=~q7mi2-t+G` zyX=Gj{ELPQI05St^C-WMM+hAUhzitwK>UZY9}7B+G2{iuqgI%UpHjb+(3kXkcn-G` ztthwDKh{1)@;!-;Gej)qAj^LsuSfY0%l~Wsf)8kW-13DcRn9AvU&s4amutpj3F=dc z_bE>x7HKP*64R+{hB{7q`2PMx-5{bbSt2o$a!LH!`i`VLoAP6*V<^#yd@2@aXZlz_ zwdwecd<4$1diNH|L}D!!^RNt2o^nMTkDH0zghPxY&J+I1IsP~9h%gqkkvvL`9IN&I>&T<=zrGUpl5%@uCozQ3|BLWp{Fb;%JVU=Xh;r6{1a)_a z#>5mtM=@eC5lr+WbY#>?QjdR!}6=t%^+HH(!*B@Pf2E_ee!}FAj5~;)coxUdSnRQaypYmnm8>>5l z>#W=l(}-8-7esWRJXbEjIVL7@XPMmnvB@walu=;t#xFKBeDQoyLu0|pEnH7aLL_a1@q zjVi~-H*HXV^X2aSg39E7JndrcD#zo(x>Xm}Pd>MEMgHXVn^OnOuNaU&bN;WhmpT6f DXY(YG delta 11471 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 diff --git a/apps/i18n/zh/LC_MESSAGES/django.po b/apps/i18n/zh/LC_MESSAGES/django.po index 8f95f9291..196c3fb36 100644 --- a/apps/i18n/zh/LC_MESSAGES/django.po +++ b/apps/i18n/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: 2018-05-08 17:24+0800\n" +"POT-Creation-Date: 2018-05-17 11:32+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: Jumpserver team\n" @@ -17,22 +17,22 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: assets/api/node.py:96 +#: assets/api/node.py:106 msgid "New node {}" msgstr "新节点 {}" -#: assets/api/node.py:225 +#: assets/api/node.py:242 msgid "更新节点资产硬件信息: {}" msgstr "" -#: assets/api/node.py:238 +#: assets/api/node.py:255 msgid "测试节点下资产是否可连接: {}" msgstr "" #: assets/forms/asset.py:24 assets/models/asset.py:66 assets/models/user.py:103 #: assets/templates/assets/asset_detail.html:183 #: assets/templates/assets/asset_detail.html:191 -#: assets/templates/assets/system_user_detail.html:166 perms/models.py:33 +#: assets/templates/assets/system_user_detail.html:175 perms/models.py:33 msgid "Nodes" msgstr "节点管理" @@ -438,7 +438,7 @@ msgstr "默认资产组" msgid "User" msgstr "用户" -#: assets/models/label.py:18 assets/models/node.py:15 +#: assets/models/label.py:18 assets/models/node.py:18 #: assets/templates/assets/label_list.html:15 common/models.py:27 msgid "Value" msgstr "值" @@ -535,7 +535,7 @@ msgstr "测试系统用户可连接性: {}" msgid "定期测试系统用户可连接性: {}" msgstr "" -#: assets/tasks.py:401 +#: assets/tasks.py:402 msgid "推送系统用户到入资产: {}" msgstr "" @@ -660,7 +660,7 @@ msgstr "重置" #: common/templates/common/ldap_setting.html:60 #: common/templates/common/terminal_setting.html:103 #: perms/templates/perms/asset_permission_create_update.html:70 -#: terminal/templates/terminal/session_list.html:120 +#: terminal/templates/terminal/session_list.html:124 #: terminal/templates/terminal/terminal_update.html:48 #: users/templates/users/_user.html:47 #: users/templates/users/forgot_password.html:44 @@ -782,8 +782,8 @@ msgstr "选择节点" #: assets/templates/assets/admin_user_detail.html:100 #: assets/templates/assets/asset_detail.html:200 -#: assets/templates/assets/asset_list.html:634 -#: assets/templates/assets/system_user_detail.html:183 +#: assets/templates/assets/asset_list.html:636 +#: assets/templates/assets/system_user_detail.html:192 #: assets/templates/assets/system_user_list.html:138 templates/_modal.html:22 #: terminal/templates/terminal/session_detail.html:108 #: users/templates/users/user_detail.html:362 @@ -963,19 +963,19 @@ msgstr "仅显示当前节点资产" msgid "Displays all child node assets" msgstr "显示所有子节点资产" -#: assets/templates/assets/asset_list.html:215 +#: assets/templates/assets/asset_list.html:217 msgid "Create node failed" msgstr "创建节点失败" -#: assets/templates/assets/asset_list.html:227 +#: assets/templates/assets/asset_list.html:229 msgid "Have child node, cancel" msgstr "存在子节点,不能删除" -#: assets/templates/assets/asset_list.html:229 +#: assets/templates/assets/asset_list.html:231 msgid "Have assets, cancel" msgstr "存在资产,不能删除" -#: assets/templates/assets/asset_list.html:629 +#: assets/templates/assets/asset_list.html:631 #: assets/templates/assets/system_user_list.html:133 #: users/templates/users/user_detail.html:357 #: users/templates/users/user_detail.html:382 @@ -984,20 +984,20 @@ msgstr "存在资产,不能删除" msgid "Are you sure?" msgstr "你确认吗?" -#: assets/templates/assets/asset_list.html:630 +#: assets/templates/assets/asset_list.html:632 msgid "This will delete the selected assets !!!" msgstr "删除选择资产" -#: assets/templates/assets/asset_list.html:638 +#: assets/templates/assets/asset_list.html:640 msgid "Asset Deleted." msgstr "已被删除" -#: assets/templates/assets/asset_list.html:639 -#: assets/templates/assets/asset_list.html:644 +#: assets/templates/assets/asset_list.html:641 +#: assets/templates/assets/asset_list.html:646 msgid "Asset Delete" msgstr "删除" -#: assets/templates/assets/asset_list.html:643 +#: assets/templates/assets/asset_list.html:645 msgid "Asset Deleting failed." msgstr "删除失败" @@ -1032,6 +1032,7 @@ msgid "Create gateway" msgstr "创建网关" #: assets/templates/assets/domain_gateway_list.html:87 +#: assets/templates/assets/domain_gateway_list.html:89 #: common/templates/common/email_setting.html:58 #: common/templates/common/ldap_setting.html:58 msgid "Test connection" @@ -1080,10 +1081,23 @@ msgstr "家目录" msgid "Uid" msgstr "Uid" -#: assets/templates/assets/system_user_detail.html:174 +#: assets/templates/assets/system_user_detail.html:153 +#: assets/templates/assets/system_user_detail.html:339 +msgid "Clear auth" +msgstr "清除认证信息" + +#: assets/templates/assets/system_user_detail.html:156 +msgid "Clear" +msgstr "清除" + +#: assets/templates/assets/system_user_detail.html:183 msgid "Add to node" msgstr "添加到节点" +#: assets/templates/assets/system_user_detail.html:339 +msgid "success" +msgstr "成功" + #: assets/templates/assets/system_user_list.html:18 #: assets/views/system_user.py:45 msgid "Create system user" @@ -2113,15 +2127,16 @@ msgstr "时长" msgid "Monitor" msgstr "监控" -#: terminal/templates/terminal/session_list.html:105 +#: terminal/templates/terminal/session_list.html:106 +#: terminal/templates/terminal/session_list.html:108 msgid "Terminate" msgstr "终断" -#: terminal/templates/terminal/session_list.html:116 +#: terminal/templates/terminal/session_list.html:120 msgid "Terminate selected" msgstr "终断所选" -#: terminal/templates/terminal/session_list.html:136 +#: terminal/templates/terminal/session_list.html:140 msgid "Terminate task send, waiting ..." msgstr "终断任务已发送,请等待" diff --git a/apps/users/models/group.py b/apps/users/models/group.py index 128fbdbcb..48ed2e949 100644 --- a/apps/users/models/group.py +++ b/apps/users/models/group.py @@ -11,7 +11,7 @@ __all__ = ['UserGroup'] class UserGroup(NoDeleteModelMixin): id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=128, verbose_name=_('Name')) + name = models.CharField(max_length=128, unique=True, verbose_name=_('Name')) comment = models.TextField(blank=True, verbose_name=_('Comment')) date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date created'))
{% trans 'Auto push' %}: @@ -130,8 +130,8 @@
{% trans 'Push system user now' %}: @@ -139,8 +139,8 @@
{% trans 'Test assets connective' %}: @@ -149,6 +149,15 @@
{% trans 'Clear auth' %}: + + + +
{% trans 'Change auth period' %}:#} @@ -239,6 +248,7 @@ $(document).ready(function () { if($('#id_protocol_type').text() === 'rdp'){ $('.only-ssh').addClass('hidden') } + $(".panel-body .table tr:visible:first").addClass('no-borders-tr'); $('.select2').select2() .on('select2:select', function(evt) { var data = evt.params.data; @@ -321,6 +331,13 @@ $(document).ready(function () { success: success, flash_message: false }); +}).on('click', '.btn-clear-auth', function () { + var the_url = '{% url "api-assets:system-user-auth-info" pk=system_user.id %}'; + APIUpdateAttr({ + url: the_url, + method: 'DELETE', + success_message: "{% trans 'Clear auth' %}" + " {% trans 'success' %}" + }); }) {% endblock %} diff --git a/apps/i18n/zh/LC_MESSAGES/django.mo b/apps/i18n/zh/LC_MESSAGES/django.mo index 36220e3219e13e2f33a24be9281b1ef120ef808e..6b02da8fad05df4e52dd43f5833a98e2ab222cc0 100644 GIT binary patch delta 11602 zcmYk?37k(=AII@)3^UAX%w*q2Gh=5MV=3EUm|?^uyD~&$X^5z?T}yUFO_nKHqM}FE zC{MD}o=idAO|MPlIO!fQiB|rCcg#QAE zBg)Tl%HzIp$2mxOSQXVe&gxo@GaJ|7BuuF7I7bRO&K7(NXVoRAJ}#ay@Ge%u67?PD zQH;lCn1$7Ft$7rSI*#kyr=W?8G;o{%j7A!q8fH9(kvGP|*dEotBSzq048-wR4yR!d zuCV$KFq(WT>b&FVk2f)Z`JKBIxM-(vg5yMDBo@c&W&)NVZ-H7!7YxA+td7I62gq1btEchN0eyY}EO4EnkY7aHG|Kin?I;AO$Vp1Zsspqb9hH+M;`?f&H3# z3k*Z$rBMUMpw5d&4VYx6p)RNgY9Se@c}AgjZXEJiS1hUbzdr>{JO(wv6s&=BEZ>TH zCU&Ck-F~c&Cr|_V^D(D^BTze02DOkHsD(E~joS>>FWK@mETZ?n8wGXjgBtK@tc)X3 zC+1lD64XLhp$6Ju`A6nn)U7#)8s{Wx>o1|U{2$aj!F(R8UnIKPnkp2^V=QVbTcajU zLv3|8)WbIf^>9tWKDYq&I$c9e6y4lgU;=8~mZ)*sq9*Kw+R5Iic`}-_|FIN?Qo(nQ z^P0H;^_jic`~>TfpGHj>*1~a8umx%-W}zmSkJ_QPa2u{cEo4ATZ{keU`B|uiEp6#~ zh4-k?mTf>?@eb4q52FS=iMpp3EWd8~1Jne?TY2|B4As9fYC*M7SKI`3ehbusQ!Ve} zQqW5Jpgx-iqVCl=dwR}mtzcWM)f<6n&1-Z%KtuKO_o5bZ z0CnECsCkZKgx>#r3fj8csE&bcya~gxFnJkNeFfAG#Goc_jJopXs0Fq~jnfJBko849 zQ!k_5o;Oho+>BcAK8$95=a>q38+Gr?xAndQYMJd(6FzMYK}|RUb*0&;g}sh(_#Qrt z2hksIp!(l7{gSB`l3MlG%Sv9MaC)nkdv2#bQxxh1$~gsD*Y%y(I%I&&F!x(@_1_ zVK3Z*IxoDvXC>4E>Yx^wfDJIEJ^QbY6R6PZHWzE*O00l+s4KgIdKRvuCc1^X!uzO& z1*LempcLu~YnTbBXP~*|9nEf5-_NBGNQW%*1=KB=gj(2q)P&1WTm3F-;*U|U(|*(h z$F2Un)!#rZEHKquSS0GaIMf9tpl*TNghCq%=~xaIp`O;wsDZ!206dOb&{^{;YM~EM zTN>8EYkwHEum-3LYlp+JGd_pAP~+9_=xcYKrWABrVyTHypNjtfycu>v)~ zYSe-@U^U!{y0QzXiGN4+zlmDVJ=C*PBF($CaTuiczbyrAZ5ML@>UA28dS7Q^Fy^8b z_%7<<*@QJQAB$l`C(rVz^I}owHNp^VgSyak)B<}*z5f{$w3S0p9mk??V${I7s0FP= zEp#hZ#?Mh#d=d5VUO|mhScf#! z7WYBjyG+!*8;-hnQ&FD}xmW@}L~Zc_jKCwPhc_R!llL(cgCF<$mBTRdYN+!YKhFNE zB9)2;*bB8qub>88iE7`9TG#>9iHA`S;W_g+)UCRKy2AUY{)M}G3kgGAKn2u-8lcWk zaw+JFQc+ts5Vi6VI1ndV{W;Wtf1n1qiw&^&6W$IrN1dOJ;n)|o&@9v~n1s5JT+}#g zPz!dqP|$=sQ3HQt4JT1MkdIp6ZPb8~-Mk57QBQGG^u4|qMV^8h=PA^LS=K%gbxU7D zUHKfOpX=mMC`rZJr~$X4?&(hRYt)IyQNLWyU<&$m_a^FyYVVCxvA@;lqbB+b(+cta zV>Wq*p8SBt{kXpn_rE>g7`b!^I{k%NL zj6jW7#*9TRuz{J3u2$BQg5LK5r~&6ip>buGi3ziYinjp|1RC>p0b%ZN7@S!o`-qgL-J!TKyK(z&J&O8(yMnsVYvw;@ zQFnmX5RO_|SxmqxmUpxEzNjsH#_C_dMDmH2Z!x!{7O>ayW9BLI9A?pe8P(72^|W_I z&zfUV3z=cQVlJ@uCFUB`g0`Zr?0}hvI{yS}g0tog)XoL)siyi!;)SPJTuc8*P6t#eLsQ3M2tKVhydFWdZYM!&^6`$PyyH*i6$eS<<)v=n{5Q~y0 zS)O8fH`LqE7qyU~RzD7P{uFbb)h{tun(t#6^E(@@VmIo<&&{K#pJYFq_pvB>*=Ibf zpl_k51vIq0t+l6P9Q8ddpKQ)VeU#5bS5N&43L0pyb;v_~iF}XR+6z{H4b|_qJ~P$`p&2e=w)VPa{pD4Nrg@rZjLu+nF~=@xYF{?sPlGN{+Z?9 zp+2gAM130;9qjchf!fK^sMk9IHQ(cd*?;|#=|_cj;tkY_w_AsUSd9FnnU7k?Rn!8U zA>Kp*sP{br{jjE42kVf>oBgmQ`8+evr7(z!5<|TKUqr3UwR|q-lIK`ndzjZR0b5c3 zh~*Q^mrx6wgSwD6t$rN_lW#HiSiO7DDvnvjFQ^kQVR5`?20rUeToQw+FKfn`31%zQ zPIN-;&@+~2S^Ess_^*5IuJfKXtiwPWKCyhCdB{9%UPcY@H`c%)KF$hbBI;H(#SmX(jsmsAV=Xlgu>KLVBQfB-0#ejyI>H7BC+*-y%=fSw%q;ZnTDd z<{_&;ZTX+5iSAn-I>sBY9O??Ak&k`n5zAMZpQ09a47GqWs0Ez&$^E}!6@^~#8bZx- zW;L@R@(x?% z`eCROvQaxV$?9{kH2HGNw^@Dw)$b?snpq^