From 059a8de44a0a692eaec372ad4a70814a7258505a Mon Sep 17 00:00:00 2001 From: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Date: Tue, 28 May 2019 12:11:55 +0800 Subject: [PATCH 1/9] =?UTF-8?q?[Bufix]=20=E4=BF=AE=E5=A4=8D=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E6=9B=B4=E6=96=B0=E6=97=B6password=5Fstrategy?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E4=B8=8D=E8=83=BD=E4=B8=BA=E7=A9=BA=E7=9A=84?= =?UTF-8?q?bug=20(#2741)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/users/forms.py | 31 +++++++++++++++++++------------ apps/users/views/user.py | 4 ++-- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/apps/users/forms.py b/apps/users/forms.py index cbca9c4fd..43ef0b594 100644 --- a/apps/users/forms.py +++ b/apps/users/forms.py @@ -21,13 +21,7 @@ class UserCheckOtpCodeForm(forms.Form): otp_code = forms.CharField(label=_('MFA code'), max_length=6) -class UserCreateUpdateForm(OrgModelForm): - EMAIL_SET_PASSWORD = _('Reset link will be generated and sent to the user') - CUSTOM_PASSWORD = _('Set password') - PASSWORD_STRATEGY_CHOICES = ( - (0, EMAIL_SET_PASSWORD), - (1, CUSTOM_PASSWORD) - ) +class UserCreateUpdateFormMixin(OrgModelForm): role_choices = ((i, n) for i, n in User.ROLE_CHOICES if i != User.ROLE_APP) password = forms.CharField( label=_('Password'), widget=forms.PasswordInput, @@ -42,10 +36,6 @@ class UserCreateUpdateForm(OrgModelForm): widget=forms.Textarea(attrs={'placeholder': _('ssh-rsa AAAA...')}), help_text=_('Paste user id_rsa.pub here.') ) - password_strategy = forms.ChoiceField( - choices=PASSWORD_STRATEGY_CHOICES, required=True, initial=0, - widget=forms.RadioSelect(), label=_('Password strategy') - ) class Meta: model = User @@ -65,7 +55,7 @@ class UserCreateUpdateForm(OrgModelForm): def __init__(self, *args, **kwargs): self.request = kwargs.pop("request", None) - super(UserCreateUpdateForm, self).__init__(*args, **kwargs) + super(UserCreateUpdateFormMixin, self).__init__(*args, **kwargs) roles = [] # Super admin user @@ -115,6 +105,23 @@ class UserCreateUpdateForm(OrgModelForm): return user +class UserCreateForm(UserCreateUpdateFormMixin): + EMAIL_SET_PASSWORD = _('Reset link will be generated and sent to the user') + CUSTOM_PASSWORD = _('Set password') + PASSWORD_STRATEGY_CHOICES = ( + (0, EMAIL_SET_PASSWORD), + (1, CUSTOM_PASSWORD) + ) + password_strategy = forms.ChoiceField( + choices=PASSWORD_STRATEGY_CHOICES, required=True, initial=0, + widget=forms.RadioSelect(), label=_('Password strategy') + ) + + +class UserUpdateForm(UserCreateUpdateFormMixin): + pass + + class UserProfileForm(forms.ModelForm): username = forms.CharField(disabled=True) name = forms.CharField(disabled=True) diff --git a/apps/users/views/user.py b/apps/users/views/user.py index 69ed441ba..963be613f 100644 --- a/apps/users/views/user.py +++ b/apps/users/views/user.py @@ -75,7 +75,7 @@ class UserListView(AdminUserRequiredMixin, TemplateView): class UserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView): model = User - form_class = forms.UserCreateUpdateForm + form_class = forms.UserCreateForm template_name = 'users/user_create.html' success_url = reverse_lazy('users:user-list') success_message = create_success_msg @@ -108,7 +108,7 @@ class UserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView): class UserUpdateView(AdminUserRequiredMixin, SuccessMessageMixin, UpdateView): model = User - form_class = forms.UserCreateUpdateForm + form_class = forms.UserUpdateForm template_name = 'users/user_update.html' context_object_name = 'user_object' success_url = reverse_lazy('users:user-list') From dc4bf669b0d86477a43d9b9e4bc21047ea42a995 Mon Sep 17 00:00:00 2001 From: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Date: Tue, 28 May 2019 17:05:31 +0800 Subject: [PATCH 2/9] =?UTF-8?q?[Update]=20=E4=BF=AE=E6=94=B9RemoteApp?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E6=96=87=E4=BB=B6=20(#2742)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/applications/migrations/0001_initial.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/applications/migrations/0001_initial.py b/apps/applications/migrations/0001_initial.py index 35d6dc103..221fd5e22 100644 --- a/apps/applications/migrations/0001_initial.py +++ b/apps/applications/migrations/0001_initial.py @@ -21,7 +21,7 @@ class Migration(migrations.Migration): ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('name', models.CharField(max_length=128, verbose_name='Name')), - ('type', models.CharField(choices=[('Browser', (('chrome', 'Chrome'),)), ('Database tools', (('mysql_workbench', 'MySQL Workbench'),)), ('Virtualization tools', (('vmware_client', 'VMware Client'),)), ('custom', 'Custom')], default='chrome', max_length=128, verbose_name='App type')), + ('type', models.CharField(choices=[('Browser', (('chrome', 'Chrome'),)), ('Database tools', (('mysql_workbench', 'MySQL Workbench'),)), ('Virtualization tools', (('vmware_client', 'vSphere Client'),)), ('custom', 'Custom')], default='chrome', max_length=128, verbose_name='App type')), ('path', models.CharField(max_length=128, verbose_name='App path')), ('params', common.fields.model.EncryptJsonDictTextField(blank=True, default={}, max_length=4096, null=True, verbose_name='Parameters')), ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), From 00e986a64ed429a436981a01907cd78abfd221c7 Mon Sep 17 00:00:00 2001 From: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Date: Wed, 29 May 2019 10:11:58 +0800 Subject: [PATCH 3/9] =?UTF-8?q?[Update]=20=E4=BC=98=E5=8C=96LDAP=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=AF=BC=E5=85=A5=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E8=B7=A8=E9=A1=B5=E9=80=89=E5=8F=96=E7=9A=84?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=94=A8=E6=88=B7=20(#2745)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/settings/api.py | 46 +++++++++++++++++-- .../settings/_ldap_list_users_modal.html | 6 +-- .../templates/settings/ldap_setting.html | 5 +- apps/settings/utils.py | 1 - 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/apps/settings/api.py b/apps/settings/api.py index d7c789603..29986637e 100644 --- a/apps/settings/api.py +++ b/apps/settings/api.py @@ -5,7 +5,9 @@ import os import json import jms_storage +from rest_framework import generics from rest_framework.views import Response, APIView +from rest_framework.pagination import LimitOffsetPagination from django.conf import settings from django.core.mail import send_mail from django.utils.translation import ugettext_lazy as _ @@ -89,19 +91,55 @@ class LDAPTestingAPI(APIView): return Response({"error": "Have user but attr mapping error"}, status=401) -class LDAPUserListApi(APIView): +class LDAPUserListApi(generics.ListAPIView): + pagination_class = LimitOffsetPagination permission_classes = (IsOrgAdmin,) - def get(self, request): + def get_queryset(self): util = LDAPUtil() try: users = util.search_user_items() except Exception as e: users = [] logger.error(e, exc_info=True) + # 前端data_table会根据row.id对table.selected值进行操作 + for user in users: + user['id'] = user['username'] + return users + + def filter_queryset(self, queryset): + search = self.request.query_params.get('search') + if not search: + return queryset + search = search.lower() + queryset = [ + q for q in queryset + if + search in q['username'].lower() + or search in q['name'].lower() + or search in q['email'].lower() + ] + return queryset + + def sort_queryset(self, queryset): + order_by = self.request.query_params.get('order') + if not order_by: + order_by = 'existing' + if order_by.startswith('-'): + order_by = order_by.lstrip('-') + reverse = True else: - users = sorted(users, key=lambda u: (u['existing'], u['username'])) - return Response(users) + reverse = False + queryset = sorted(queryset, key=lambda x: x[order_by], reverse=reverse) + return queryset + + def list(self, request, *args, **kwargs): + queryset = self.filter_queryset(self.get_queryset()) + queryset = self.sort_queryset(queryset) + page = self.paginate_queryset(queryset) + if page is not None: + return self.get_paginated_response(page) + return Response(queryset) class LDAPUserSyncAPI(APIView): diff --git a/apps/settings/templates/settings/_ldap_list_users_modal.html b/apps/settings/templates/settings/_ldap_list_users_modal.html index 9609d80ce..c0d062714 100644 --- a/apps/settings/templates/settings/_ldap_list_users_modal.html +++ b/apps/settings/templates/settings/_ldap_list_users_modal.html @@ -52,7 +52,7 @@ var ldap_users_table = 0; function initLdapUsersTable() { if(ldap_users_table){ - return + return ldap_users_table } var options = { ele: $('#ldap_list_users_table'), @@ -73,10 +73,10 @@ function initLdapUsersTable() { {data: "username" },{data: "username" }, {data: "name" }, {data:"email"}, {data:'existing'} ], - pageLength: 10 + pageLength: 15 }; - ldap_users_table = jumpserver.initDataTable(options); + ldap_users_table = jumpserver.initServerSideDataTable(options); return ldap_users_table } diff --git a/apps/settings/templates/settings/ldap_setting.html b/apps/settings/templates/settings/ldap_setting.html index d19a84292..58e4ae71b 100644 --- a/apps/settings/templates/settings/ldap_setting.html +++ b/apps/settings/templates/settings/ldap_setting.html @@ -110,10 +110,7 @@ $(document).ready(function () { }); }) .on("click","#btn_ldap_modal_confirm",function () { - var username_list=[]; - $("tbody input[type='checkbox']:checked").each(function () { - username_list.push($(this).attr('id')); - }); + var username_list = ldap_users_table.selected; if (username_list.length === 0){ var msg = "{% trans 'User is not currently selected, please check the user you want to import'%}"; diff --git a/apps/settings/utils.py b/apps/settings/utils.py index 563f5fc3a..adcd2c839 100644 --- a/apps/settings/utils.py +++ b/apps/settings/utils.py @@ -61,7 +61,6 @@ class LDAPUtil: try: user = User.objects.get(username=username) except Exception as e: - logger.info(e) return None else: return user From 9c55450a9ebb2fd229259d32df88aed1e50eec4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=85=AB=E5=8D=83=E6=B5=81?= <40739051+jym503558564@users.noreply.github.com> Date: Wed, 29 May 2019 10:13:19 +0800 Subject: [PATCH 4/9] =?UTF-8?q?[Bugfix]=20=E4=BF=AE=E5=A4=8D=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E8=A1=A8=E5=8F=AF=E4=BB=A5=E9=80=89=E6=8B=A9=E5=A4=9A?= =?UTF-8?q?=E9=A1=B5=E7=9A=84=E8=B5=84=E6=BA=90=E6=95=B0=E6=8D=AE=20(#2744?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Bugfix] 修复资源表可以选择多页的资源数据 * [Bugfix]修改小问题 --- .../templates/assets/admin_user_list.html | 26 +++++++------------ apps/assets/templates/assets/asset_list.html | 24 +++-------------- .../templates/assets/system_user_list.html | 18 ++++--------- .../templates/users/user_group_list.html | 23 +++++++--------- apps/users/templates/users/user_list.html | 26 +++++-------------- 5 files changed, 34 insertions(+), 83 deletions(-) diff --git a/apps/assets/templates/assets/admin_user_list.html b/apps/assets/templates/assets/admin_user_list.html index c182ba4c4..4f4356539 100644 --- a/apps/assets/templates/assets/admin_user_list.html +++ b/apps/assets/templates/assets/admin_user_list.html @@ -63,7 +63,8 @@ {% block content_bottom_left %}{% endblock %} {% block custom_foot_js %}