diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 5bcb3f572..ca378770f 100644 Binary files a/apps/locale/zh/LC_MESSAGES/django.mo and b/apps/locale/zh/LC_MESSAGES/django.mo differ diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index f0494f3de..3ac062914 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: 2019-03-27 12:48+0800\n" +"POT-Creation-Date: 2019-03-28 12:41+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: Jumpserver team\n" @@ -165,7 +165,7 @@ msgstr "SSH网关,支持代理SSH,RDP和VNC" #: perms/templates/perms/asset_permission_list.html:53 #: perms/templates/perms/asset_permission_list.html:72 #: perms/templates/perms/asset_permission_user.html:54 settings/models.py:29 -#: settings/templates/settings/_ldap_list_users_modal.html:35 +#: settings/templates/settings/_ldap_list_users_modal.html:38 #: settings/templates/settings/command_storage_create.html:41 #: settings/templates/settings/replay_storage_create.html:44 #: settings/templates/settings/terminal_setting.html:80 @@ -207,7 +207,7 @@ msgstr "名称" #: authentication/templates/authentication/new_login.html:90 #: ops/models/adhoc.py:164 perms/templates/perms/asset_permission_list.html:74 #: perms/templates/perms/asset_permission_user.html:55 -#: settings/templates/settings/_ldap_list_users_modal.html:34 users/forms.py:13 +#: settings/templates/settings/_ldap_list_users_modal.html:37 users/forms.py:13 #: users/models/user.py:52 users/templates/users/_select_user_modal.html:14 #: users/templates/users/user_detail.html:67 #: users/templates/users/user_list.html:24 @@ -1025,8 +1025,8 @@ msgstr "其它" #: settings/templates/settings/basic_setting.html:61 #: settings/templates/settings/command_storage_create.html:79 #: settings/templates/settings/email_setting.html:62 -#: settings/templates/settings/ldap_setting.html:62 -#: settings/templates/settings/replay_storage_create.html:152 +#: settings/templates/settings/ldap_setting.html:61 +#: settings/templates/settings/replay_storage_create.html:151 #: settings/templates/settings/security_setting.html:70 #: settings/templates/settings/terminal_setting.html:68 #: terminal/templates/terminal/terminal_update.html:45 @@ -1061,8 +1061,8 @@ msgstr "重置" #: settings/templates/settings/basic_setting.html:62 #: settings/templates/settings/command_storage_create.html:80 #: settings/templates/settings/email_setting.html:63 -#: settings/templates/settings/ldap_setting.html:63 -#: settings/templates/settings/replay_storage_create.html:153 +#: settings/templates/settings/ldap_setting.html:64 +#: settings/templates/settings/replay_storage_create.html:152 #: settings/templates/settings/security_setting.html:71 #: settings/templates/settings/terminal_setting.html:70 #: terminal/templates/terminal/command_list.html:103 @@ -1087,7 +1087,8 @@ msgid "Asset detail" msgstr "资产详情" #: assets/templates/assets/_user_asset_detail_modal.html:23 -#: templates/_modal.html:21 +#: settings/templates/settings/_ldap_list_users_modal.html:96 +#: templates/_modal.html:22 msgid "Close" msgstr "关闭" @@ -1259,7 +1260,7 @@ msgstr "选择节点" #: assets/templates/assets/system_user_detail.html:182 #: assets/templates/assets/system_user_list.html:143 #: settings/templates/settings/terminal_setting.html:165 -#: templates/_modal.html:22 terminal/templates/terminal/session_detail.html:108 +#: templates/_modal.html:23 terminal/templates/terminal/session_detail.html:108 #: users/templates/users/user_detail.html:388 #: users/templates/users/user_detail.html:414 #: users/templates/users/user_detail.html:437 @@ -1392,6 +1393,7 @@ msgid "Create asset" msgstr "创建资产" #: assets/templates/assets/asset_list.html:73 +#: settings/templates/settings/_ldap_list_users_modal.html:97 #: users/templates/users/user_list.html:7 #: xpack/plugins/license/templates/license/license_detail.html:101 msgid "Import" @@ -1611,7 +1613,7 @@ msgstr "创建网关" #: assets/templates/assets/domain_gateway_list.html:99 #: assets/templates/assets/domain_gateway_list.html:101 #: settings/templates/settings/email_setting.html:61 -#: settings/templates/settings/ldap_setting.html:61 +#: settings/templates/settings/ldap_setting.html:62 msgid "Test connection" msgstr "测试连接" @@ -2834,38 +2836,33 @@ msgstr "资产授权用户列表" msgid "Asset permission asset list" msgstr "资产授权资产列表" -#: settings/api.py:23 +#: settings/api.py:26 msgid "Test mail sent to {}, please check" msgstr "邮件已经发送{}, 请检查" -#: settings/api.py:47 +#: settings/api.py:50 msgid "Test ldap success" msgstr "连接LDAP成功" -#: settings/api.py:77 settings/utils.py:23 -msgid "Search no entry matched in ou {}" -msgstr "在ou:{}中没有匹配条目" - -#: settings/api.py:86 +#: settings/api.py:87 msgid "Match {} s users" msgstr "匹配 {} 个用户" -#: settings/api.py:109 -msgid "" -"User is not currently selected, please check the user you want to import" -msgstr "当前无勾选用户,请勾选你想要导入的用户" +#: settings/api.py:120 +msgid "succeed: {} failed: {} total: {}" +msgstr "成功:{} 失败:{} 总数:{}" -#: settings/api.py:139 settings/api.py:175 +#: settings/api.py:142 settings/api.py:178 msgid "" "Error: Account invalid (Please make sure the information such as Access key " "or Secret key is correct)" msgstr "错误:账户无效 (请确保 Access key 或 Secret key 等信息正确)" -#: settings/api.py:145 settings/api.py:181 +#: settings/api.py:148 settings/api.py:184 msgid "Create succeed" msgstr "创建成功" -#: settings/api.py:163 settings/api.py:201 +#: settings/api.py:166 settings/api.py:204 #: settings/templates/settings/terminal_setting.html:151 msgid "Delete succeed" msgstr "删除成功" @@ -3108,24 +3105,28 @@ msgid "" "characters" msgstr "开启后,用户密码修改、重置必须包含特殊字符" -#: settings/models.py:126 users/templates/users/reset_password.html:68 +#: settings/models.py:128 users/templates/users/reset_password.html:68 #: users/templates/users/user_profile.html:20 msgid "Setting" msgstr "设置" #: settings/templates/settings/_ldap_list_users_modal.html:7 -msgid "Ldap users" -msgstr "Ldap 用户列表" +msgid "LDAP user list" +msgstr "LDAP 用户列表" -#: settings/templates/settings/_ldap_list_users_modal.html:36 +#: settings/templates/settings/_ldap_list_users_modal.html:9 +msgid "Please submit the LDAP configuration before import" +msgstr "请先提交LDAP配置再进行导入" + +#: settings/templates/settings/_ldap_list_users_modal.html:39 #: users/models/user.py:56 users/templates/users/user_detail.html:71 #: users/templates/users/user_profile.html:59 msgid "Email" msgstr "邮件" -#: settings/templates/settings/_ldap_list_users_modal.html:37 -msgid "Is imported" -msgstr "是否已经导入" +#: settings/templates/settings/_ldap_list_users_modal.html:40 +msgid "Existing" +msgstr "已存在" #: settings/templates/settings/basic_setting.html:15 #: settings/templates/settings/email_setting.html:15 @@ -3182,8 +3183,13 @@ msgid "Doc type" msgstr "文档类型" #: settings/templates/settings/ldap_setting.html:65 -msgid "Sync User" -msgstr "同步用户" +msgid "Bulk import" +msgstr "一键导入" + +#: settings/templates/settings/ldap_setting.html:116 +msgid "" +"User is not currently selected, please check the user you want to import" +msgstr "当前无勾选用户,请勾选你想要导入的用户" #: settings/templates/settings/replay_storage_create.html:66 msgid "Bucket" @@ -3289,44 +3295,17 @@ msgstr "删除失败" msgid "Are you sure about deleting it?" msgstr "您确定删除吗?" -#: settings/utils.py:30 -msgid "Have user but attr mapping error" -msgstr "有用户但attr映射错误" - -#: settings/utils.py:60 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:86 -msgid "No" -msgstr "否" - #: settings/utils.py:69 -#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:84 -msgid "Yes" -msgstr "是" +msgid "User does not exist" +msgstr "用户不存在" -#: settings/utils.py:137 -msgid "" -"Import {} users successfully; import {} users failed, the database already " -"exists with the same name" -msgstr "导入 {} 个用户成功; 导入 {} 这些用户失败,数据库已经存在同名的用户" +#: settings/utils.py:72 +msgid "The user source is not LDAP" +msgstr "用户来源不是LDAP" -#: settings/utils.py:142 -msgid "" -"Import {} users successfully; import {} users failed, the database already " -"exists with the same name; import {}users failed, Because’TypeError' object " -"has no attribute 'keys'" -msgstr "" -"导入 {} 个用户成功; 导入 {} 这些用户失败,数据库已经存在同名的用户; 导入 {} " -"这些用户失败,因为对象没有属性'keys'" - -#: settings/utils.py:148 -msgid "Import {} users successfully" -msgstr "导入 {} 个用户成功" - -#: settings/utils.py:151 -msgid "" -"Import {} users successfully;import {} users failed, Because’TypeError' " -"object has no attribute 'keys'" -msgstr "导入 {} 个用户成功; 导入 {} 这些用户失败,因为对象没有属性'keys'" +#: settings/utils.py:146 +msgid "Search no entry matched in ou {}" +msgstr "在ou:{}中没有匹配条目" #: settings/views.py:18 settings/views.py:44 settings/views.py:70 #: settings/views.py:99 settings/views.py:126 settings/views.py:138 @@ -4920,6 +4899,14 @@ msgstr "更改资产上的用户密码时,将会使用与该资产关联的管 msgid "Length" msgstr "长度" +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:84 +msgid "Yes" +msgstr "是" + +#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:86 +msgid "No" +msgstr "否" + #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:134 msgid "Run plan manually" msgstr "手动执行计划" @@ -5369,6 +5356,33 @@ msgstr "创建组织" msgid "Update org" msgstr "更新组织" +#~ msgid "Sync User" +#~ msgstr "同步用户" + +#~ msgid "Have user but attr mapping error" +#~ msgstr "有用户但attr映射错误" + +#~ msgid "" +#~ "Import {} users successfully; import {} users failed, the database " +#~ "already exists with the same name" +#~ msgstr "导入 {} 个用户成功; 导入 {} 这些用户失败,数据库已经存在同名的用户" + +#~ msgid "" +#~ "Import {} users successfully; import {} users failed, the database " +#~ "already exists with the same name; import {}users failed, " +#~ "Because’TypeError' object has no attribute 'keys'" +#~ msgstr "" +#~ "导入 {} 个用户成功; 导入 {} 这些用户失败,数据库已经存在同名的用户; 导入 " +#~ "{} 这些用户失败,因为对象没有属性'keys'" + +#~ msgid "Import {} users successfully" +#~ msgstr "导入 {} 个用户成功" + +#~ msgid "" +#~ "Import {} users successfully;import {} users failed, Because’TypeError' " +#~ "object has no attribute 'keys'" +#~ msgstr "导入 {} 个用户成功; 导入 {} 这些用户失败,因为对象没有属性'keys'" + #~ msgid "Monitor" #~ msgstr "监控" diff --git a/apps/settings/api.py b/apps/settings/api.py index ff265c076..a65df113d 100644 --- a/apps/settings/api.py +++ b/apps/settings/api.py @@ -5,18 +5,21 @@ import os import json import jms_storage -from ldap3 import Server, Connection from rest_framework.views import Response, APIView from django.conf import settings from django.core.mail import send_mail from django.utils.translation import ugettext_lazy as _ from .models import Setting -from .utils import get_ldap_users_list, save_user +from .utils import LDAPUtil from common.permissions import IsOrgAdmin, IsSuperUser +from common.utils import get_logger from .serializers import MailTestSerializer, LDAPTestSerializer +logger = get_logger(__file__) + + class MailTestingAPI(APIView): permission_classes = (IsOrgAdmin,) serializer_class = MailTestSerializer @@ -46,78 +49,78 @@ class LDAPTestingAPI(APIView): serializer_class = LDAPTestSerializer success_message = _("Test ldap success") + @staticmethod + def get_ldap_util(serializer): + host = serializer.validated_data["AUTH_LDAP_SERVER_URI"] + bind_dn = serializer.validated_data["AUTH_LDAP_BIND_DN"] + password = serializer.validated_data["AUTH_LDAP_BIND_PASSWORD"] + use_ssl = serializer.validated_data.get("AUTH_LDAP_START_TLS", False) + search_ougroup = serializer.validated_data["AUTH_LDAP_SEARCH_OU"] + search_filter = serializer.validated_data["AUTH_LDAP_SEARCH_FILTER"] + attr_map = serializer.validated_data["AUTH_LDAP_USER_ATTR_MAP"] + try: + attr_map = json.loads(attr_map) + except json.JSONDecodeError: + return Response({"error": "AUTH_LDAP_USER_ATTR_MAP not valid"}, status=401) + + util = LDAPUtil( + use_settings_config=False, server_uri=host, bind_dn=bind_dn, + password=password, use_ssl=use_ssl, + search_ougroup=search_ougroup, search_filter=search_filter, + attr_map=attr_map + ) + return util + def post(self, request): serializer = self.serializer_class(data=request.data) - if serializer.is_valid(): - host = serializer.validated_data["AUTH_LDAP_SERVER_URI"] - bind_dn = serializer.validated_data["AUTH_LDAP_BIND_DN"] - password = serializer.validated_data["AUTH_LDAP_BIND_PASSWORD"] - use_ssl = serializer.validated_data.get("AUTH_LDAP_START_TLS", False) - search_ougroup = serializer.validated_data["AUTH_LDAP_SEARCH_OU"] - search_filter = serializer.validated_data["AUTH_LDAP_SEARCH_FILTER"] - attr_map = serializer.validated_data["AUTH_LDAP_USER_ATTR_MAP"] - - try: - attr_map = json.loads(attr_map) - except json.JSONDecodeError: - return Response({"error": "AUTH_LDAP_USER_ATTR_MAP not valid"}, status=401) - - server = Server(host, use_ssl=use_ssl) - conn = Connection(server, bind_dn, password) - try: - conn.bind() - except Exception as e: - return Response({"error": str(e)}, status=401) - - users = [] - for search_ou in str(search_ougroup).split("|"): - ok = conn.search(search_ou, search_filter % ({"user": "*"}), - attributes=list(attr_map.values())) - if not ok: - return Response({"error": _("Search no entry matched in ou {}").format(search_ou)}, status=401) - - for entry in conn.entries: - user = {} - for attr, mapping in attr_map.items(): - if hasattr(entry, mapping): - user[attr] = getattr(entry, mapping) - users.append(user) - if len(users) > 0: - return Response({"msg": _("Match {} s users").format(len(users))}) - else: - return Response({"error": "Have user but attr mapping error"}, status=401) - else: + if not serializer.is_valid(): return Response({"error": str(serializer.errors)}, status=401) + util = self.get_ldap_util(serializer) -class LDAPSyncAPI(APIView): + try: + users = util.get_search_user_items() + except Exception as e: + return Response({"error": str(e)}, status=401) + + if len(users) > 0: + return Response({"msg": _("Match {} s users").format(len(users))}) + else: + return Response({"error": "Have user but attr mapping error"}, status=401) + + +class LDAPUserListApi(APIView): permission_classes = (IsOrgAdmin,) def get(self, request): - ldap_users_list = get_ldap_users_list() - if not isinstance(ldap_users_list, list): - return Response(ldap_users_list, status=401) - return Response(ldap_users_list) + util = LDAPUtil() + try: + users = util.get_search_user_items() + except Exception as e: + users = [] + logger.error(e, exc_info=True) + else: + users = sorted(users, key=lambda u: (u['existing'], u['username'])) + return Response(users) -class LDAPConfirmSyncAPI(APIView): +class LDAPUserSyncAPI(APIView): permission_classes = (IsOrgAdmin,) def post(self, request): user_names = request.data.get('user_names', '') - if not user_names: - error = _('User is not currently selected, please check the user ' - 'you want to import') - return Response({'error': error}, status=401) - ldap_users_list = get_ldap_users_list(user_names=user_names) - if not isinstance(ldap_users_list, list): - return Response(ldap_users_list, status=401) - - save_result = save_user(ldap_users_list) - if 'error' in save_result.keys(): - return Response(save_result, status=401) - return Response(save_result) + util = LDAPUtil() + try: + result = util.sync_users(username_set=user_names) + except Exception as e: + logger.error(e, exc_info=True) + return Response({'error': str(e)}, status=401) + else: + msg = _("succeed: {} failed: {} total: {}").format( + result['succeed'], result['failed'], result['total'] + ) + return Response({'msg': msg}) class ReplayStorageCreateAPI(APIView): diff --git a/apps/settings/models.py b/apps/settings/models.py index 3364037a3..524fa9349 100644 --- a/apps/settings/models.py +++ b/apps/settings/models.py @@ -79,6 +79,8 @@ class Setting(models.Model): obj.cleaned_value = data else: value = obj.cleaned_value + if value is None: + value = {} value.update(data) obj.cleaned_value = value obj.save() diff --git a/apps/settings/templates/settings/_ldap_list_users_modal.html b/apps/settings/templates/settings/_ldap_list_users_modal.html index 433cfc92e..2009e9b58 100644 --- a/apps/settings/templates/settings/_ldap_list_users_modal.html +++ b/apps/settings/templates/settings/_ldap_list_users_modal.html @@ -4,7 +4,10 @@ {% block modal_class %}modal-lg{% endblock %} {% block modal_id %}ldap_list_users_modal{% endblock %} -{% block modal_title%}{% trans "Ldap users" %}{% endblock %} +{% block modal_title%}{% trans "LDAP user list" %}{% endblock %} + +{% block modal_help_message%}
{% trans 'Please submit the LDAP configuration before import' %}
{% endblock %} + {% block modal_body %} @@ -34,7 +37,7 @@ {% trans 'Username' %} {% trans 'Name' %} {% trans 'Email' %} - {% trans 'Is imported' %} + {% trans 'Existing' %} @@ -47,16 +50,25 @@