From 6b7119ea7420ba94fcb893887395cc41350a9248 Mon Sep 17 00:00:00 2001 From: wangruidong <940853815@qq.com> Date: Wed, 22 Nov 2023 16:46:05 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20ldap=E6=8E=A5=E5=8F=A3=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E6=8D=A2=E6=88=90websocket=E8=BF=9E=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.mo | 3 - apps/locale/ja/LC_MESSAGES/django.po | 87 ++++++++++-------- apps/locale/zh/LC_MESSAGES/django.mo | 3 - apps/locale/zh/LC_MESSAGES/django.po | 89 ++++++++++-------- apps/settings/api/ldap.py | 105 +-------------------- apps/settings/urls/api_urls.py | 3 - apps/settings/urls/ws_urls.py | 1 + apps/settings/utils/ldap.py | 22 ++--- apps/settings/ws.py | 133 ++++++++++++++++++++++++++- 9 files changed, 240 insertions(+), 206 deletions(-) delete mode 100644 apps/locale/ja/LC_MESSAGES/django.mo delete mode 100644 apps/locale/zh/LC_MESSAGES/django.mo diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo deleted file mode 100644 index 80df7b71d..000000000 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c1af402f12b379a4943c141a1d75d1a0b38cfa873f29e70c9030dd25384944f6 -size 166114 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index c235e37a8..2bb689180 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-22 11:05+0800\n" +"POT-Creation-Date: 2023-11-22 16:43+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -2990,7 +2990,7 @@ msgstr "電話番号を設定して有効にする" msgid "Clear phone number to disable" msgstr "無効にする電話番号をクリアする" -#: authentication/middleware.py:94 settings/utils/ldap.py:679 +#: authentication/middleware.py:94 settings/utils/ldap.py:677 msgid "Authentication failed (before login check failed): {}" msgstr "認証に失敗しました (ログインチェックが失敗する前): {}" @@ -3780,6 +3780,7 @@ msgstr "華為雲" msgid "CMPP v2.0" msgstr "CMPP v2.0" +#: common/sdk/sms/endpoint.py:21 msgid "Custom type (File)" msgstr "カスタム(ファイル)" @@ -4724,23 +4725,16 @@ msgstr "テストの成功" msgid "Test mail sent to {}, please check" msgstr "{}に送信されたテストメールを確認してください" -#: settings/api/ldap.py:176 -msgid "Synchronization start, please wait." -msgstr "同期開始、お待ちください。" +#: settings/api/ldap.py:101 +msgid "" +"Users are not synchronized, please click the user synchronization button" +msgstr "ユーザーは同期されていません。「ユーザーを同期」ボタンをクリックしてください。" -#: settings/api/ldap.py:180 -msgid "Synchronization is running, please wait." -msgstr "同期が実行中です。しばらくお待ちください。" - -#: settings/api/ldap.py:185 -msgid "Synchronization error: {}" -msgstr "同期エラー: {}" - -#: settings/api/ldap.py:223 +#: settings/api/ldap.py:137 msgid "Get ldap users is None" msgstr "Ldapユーザーを取得するにはNone" -#: settings/api/ldap.py:233 +#: settings/api/ldap.py:147 msgid "Imported {} users successfully (Organization: {})" msgstr "{} 人のユーザーを正常にインポートしました (組織: {})" @@ -5889,100 +5883,104 @@ msgstr "LDAP ユーザーを定期的にインポートする" msgid "Registration periodic import ldap user task" msgstr "登録サイクルLDAPユーザータスクのインポート" -#: settings/utils/ldap.py:494 +#: settings/utils/ldap.py:492 msgid "ldap:// or ldaps:// protocol is used." msgstr "ldap:// または ldaps:// プロトコルが使用されます。" -#: settings/utils/ldap.py:505 +#: settings/utils/ldap.py:503 msgid "Host or port is disconnected: {}" msgstr "ホストまたはポートが切断されました: {}" -#: settings/utils/ldap.py:507 +#: settings/utils/ldap.py:505 msgid "The port is not the port of the LDAP service: {}" msgstr "ポートはLDAPサービスのポートではありません: {}" -#: settings/utils/ldap.py:509 +#: settings/utils/ldap.py:507 msgid "Please add certificate: {}" msgstr "証明書を追加してください: {}" -#: settings/utils/ldap.py:513 settings/utils/ldap.py:540 -#: settings/utils/ldap.py:570 settings/utils/ldap.py:598 +#: settings/utils/ldap.py:511 settings/utils/ldap.py:538 +#: settings/utils/ldap.py:568 settings/utils/ldap.py:596 msgid "Unknown error: {}" msgstr "不明なエラー: {}" -#: settings/utils/ldap.py:527 +#: settings/utils/ldap.py:525 msgid "Bind DN or Password incorrect" msgstr "DNまたはパスワードのバインドが正しくありません" -#: settings/utils/ldap.py:534 +#: settings/utils/ldap.py:532 msgid "Please enter Bind DN: {}" msgstr "バインドDN: {} を入力してください" -#: settings/utils/ldap.py:536 +#: settings/utils/ldap.py:534 msgid "Please enter Password: {}" msgstr "パスワードを入力してください: {}" -#: settings/utils/ldap.py:538 +#: settings/utils/ldap.py:536 msgid "Please enter correct Bind DN and Password: {}" msgstr "正しいバインドDNとパスワードを入力してください: {}" -#: settings/utils/ldap.py:556 +#: settings/utils/ldap.py:554 msgid "Invalid User OU or User search filter: {}" msgstr "無効なユーザー OU またはユーザー検索フィルター: {}" -#: settings/utils/ldap.py:587 +#: settings/utils/ldap.py:585 msgid "LDAP User attr map not include: {}" msgstr "LDAP ユーザーattrマップは含まれません: {}" -#: settings/utils/ldap.py:594 +#: settings/utils/ldap.py:592 msgid "LDAP User attr map is not dict" msgstr "LDAPユーザーattrマップはdictではありません" -#: settings/utils/ldap.py:613 +#: settings/utils/ldap.py:611 msgid "LDAP authentication is not enabled" msgstr "LDAP 認証が有効になっていない" -#: settings/utils/ldap.py:631 +#: settings/utils/ldap.py:629 msgid "Error (Invalid LDAP server): {}" msgstr "エラー (LDAPサーバーが無効): {}" -#: settings/utils/ldap.py:633 +#: settings/utils/ldap.py:631 msgid "Error (Invalid Bind DN): {}" msgstr "エラー (DNのバインドが無効): {}" -#: settings/utils/ldap.py:635 +#: settings/utils/ldap.py:633 msgid "Error (Invalid LDAP User attr map): {}" msgstr "エラー (LDAPユーザーattrマップが無効): {}" -#: settings/utils/ldap.py:637 +#: settings/utils/ldap.py:635 msgid "Error (Invalid User OU or User search filter): {}" msgstr "エラー (ユーザーOUまたはユーザー検索フィルターが無効): {}" -#: settings/utils/ldap.py:639 +#: settings/utils/ldap.py:637 msgid "Error (Not enabled LDAP authentication): {}" msgstr "エラー (LDAP認証が有効化されていません): {}" -#: settings/utils/ldap.py:641 +#: settings/utils/ldap.py:639 msgid "Error (Unknown): {}" msgstr "エラー (不明): {}" -#: settings/utils/ldap.py:644 +#: settings/utils/ldap.py:642 msgid "Succeed: Match {} s user" msgstr "成功: {} 人のユーザーに一致" -#: settings/utils/ldap.py:677 +#: settings/utils/ldap.py:653 +msgid "Please test the connection first" +msgstr "まず接続をテストしてください" + +#: settings/utils/ldap.py:675 msgid "Authentication failed (configuration incorrect): {}" msgstr "認証に失敗しました (設定が正しくありません): {}" -#: settings/utils/ldap.py:681 +#: settings/utils/ldap.py:679 msgid "Authentication failed (username or password incorrect): {}" msgstr "認証に失敗しました (ユーザー名またはパスワードが正しくありません): {}" -#: settings/utils/ldap.py:683 +#: settings/utils/ldap.py:681 msgid "Authentication failed (Unknown): {}" msgstr "認証に失敗しました (不明): {}" -#: settings/utils/ldap.py:686 +#: settings/utils/ldap.py:684 msgid "Authentication success: {}" msgstr "認証成功: {}" @@ -8719,6 +8717,15 @@ msgstr "エンタープライズプロフェッショナル版" msgid "Ultimate edition" msgstr "エンタープライズ・フラッグシップ・エディション" +#~ msgid "Synchronization start, please wait." +#~ msgstr "同期開始、お待ちください。" + +#~ msgid "Synchronization is running, please wait." +#~ msgstr "同期が実行中です。しばらくお待ちください。" + +#~ msgid "Synchronization error: {}" +#~ msgstr "同期エラー: {}" + #~ msgid "Copy" #~ msgstr "コピー" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo deleted file mode 100644 index ef1eef0a1..000000000 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8324031d40c7cbcd9e332221ee8f607396836b87907847b7f94e879269cc97c8 -size 135739 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 831ad1db2..da13efde4 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-11-22 11:05+0800\n" +"POT-Creation-Date: 2023-11-22 16:42+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -2961,7 +2961,7 @@ msgstr "设置手机号码启用" msgid "Clear phone number to disable" msgstr "清空手机号码禁用" -#: authentication/middleware.py:94 settings/utils/ldap.py:679 +#: authentication/middleware.py:94 settings/utils/ldap.py:677 msgid "Authentication failed (before login check failed): {}" msgstr "认证失败 (登录前检查失败): {}" @@ -3735,6 +3735,7 @@ msgstr "华为云" msgid "CMPP v2.0" msgstr "CMPP v2.0" +#: common/sdk/sms/endpoint.py:21 msgid "Custom type (File)" msgstr "自定义 (文件)" @@ -4672,23 +4673,16 @@ msgstr "测试成功" msgid "Test mail sent to {}, please check" msgstr "邮件已经发送{}, 请检查" -#: settings/api/ldap.py:176 -msgid "Synchronization start, please wait." -msgstr "同步开始,请稍等" +#: settings/api/ldap.py:101 +msgid "" +"Users are not synchronized, please click the user synchronization button" +msgstr "用户未同步,请点击同步用户按钮" -#: settings/api/ldap.py:180 -msgid "Synchronization is running, please wait." -msgstr "同步正在运行,请稍等" - -#: settings/api/ldap.py:185 -msgid "Synchronization error: {}" -msgstr "同步错误: {}" - -#: settings/api/ldap.py:223 +#: settings/api/ldap.py:137 msgid "Get ldap users is None" msgstr "获取 LDAP 用户为 None" -#: settings/api/ldap.py:233 +#: settings/api/ldap.py:147 msgid "Imported {} users successfully (Organization: {})" msgstr "成功导入 {} 个用户 ( 组织: {} )" @@ -5809,100 +5803,106 @@ msgstr "周期导入 LDAP 用户" msgid "Registration periodic import ldap user task" msgstr "注册周期导入 LDAP 用户 任务" -#: settings/utils/ldap.py:494 +#: settings/utils/ldap.py:492 msgid "ldap:// or ldaps:// protocol is used." msgstr "使用 ldap:// 或 ldaps:// 协议" -#: settings/utils/ldap.py:505 +#: settings/utils/ldap.py:503 msgid "Host or port is disconnected: {}" msgstr "主机或端口不可连接: {}" -#: settings/utils/ldap.py:507 +#: settings/utils/ldap.py:505 msgid "The port is not the port of the LDAP service: {}" msgstr "端口不是LDAP服务端口: {}" -#: settings/utils/ldap.py:509 +#: settings/utils/ldap.py:507 msgid "Please add certificate: {}" msgstr "请添加证书" -#: settings/utils/ldap.py:513 settings/utils/ldap.py:540 -#: settings/utils/ldap.py:570 settings/utils/ldap.py:598 +#: settings/utils/ldap.py:511 settings/utils/ldap.py:538 +#: settings/utils/ldap.py:568 settings/utils/ldap.py:596 msgid "Unknown error: {}" msgstr "未知错误: {}" -#: settings/utils/ldap.py:527 +#: settings/utils/ldap.py:525 msgid "Bind DN or Password incorrect" msgstr "绑定DN或密码错误" -#: settings/utils/ldap.py:534 +#: settings/utils/ldap.py:532 msgid "Please enter Bind DN: {}" msgstr "请输入绑定DN: {}" -#: settings/utils/ldap.py:536 +#: settings/utils/ldap.py:534 msgid "Please enter Password: {}" msgstr "请输入密码: {}" -#: settings/utils/ldap.py:538 +#: settings/utils/ldap.py:536 msgid "Please enter correct Bind DN and Password: {}" msgstr "请输入正确的绑定DN和密码: {}" -#: settings/utils/ldap.py:556 +#: settings/utils/ldap.py:554 msgid "Invalid User OU or User search filter: {}" msgstr "不合法的用户OU或用户过滤器: {}" -#: settings/utils/ldap.py:587 +#: settings/utils/ldap.py:585 msgid "LDAP User attr map not include: {}" msgstr "LDAP属性映射没有包含: {}" -#: settings/utils/ldap.py:594 +#: settings/utils/ldap.py:592 msgid "LDAP User attr map is not dict" msgstr "LDAP属性映射不合法" -#: settings/utils/ldap.py:613 +#: settings/utils/ldap.py:611 msgid "LDAP authentication is not enabled" msgstr "LDAP认证没有启用" -#: settings/utils/ldap.py:631 +#: settings/utils/ldap.py:629 msgid "Error (Invalid LDAP server): {}" msgstr "错误 (不合法的LDAP服务器地址): {}" -#: settings/utils/ldap.py:633 +#: settings/utils/ldap.py:631 msgid "Error (Invalid Bind DN): {}" msgstr "错误 (不合法的绑定DN): {}" -#: settings/utils/ldap.py:635 +#: settings/utils/ldap.py:633 msgid "Error (Invalid LDAP User attr map): {}" msgstr "错误 (不合法的LDAP属性映射): {}" -#: settings/utils/ldap.py:637 +#: settings/utils/ldap.py:635 msgid "Error (Invalid User OU or User search filter): {}" msgstr "错误 (不合法的用户OU或用户过滤器): {}" -#: settings/utils/ldap.py:639 +#: settings/utils/ldap.py:637 msgid "Error (Not enabled LDAP authentication): {}" msgstr "错误 (没有启用LDAP认证): {}" -#: settings/utils/ldap.py:641 +#: settings/utils/ldap.py:639 msgid "Error (Unknown): {}" msgstr "错误 (未知): {}" -#: settings/utils/ldap.py:644 +#: settings/utils/ldap.py:642 msgid "Succeed: Match {} s user" msgstr "成功匹配 {} 个用户" -#: settings/utils/ldap.py:677 +#: settings/utils/ldap.py:653 +#, fuzzy +#| msgid "Can test asset connectivity" +msgid "Please test the connection first" +msgstr "请先测试连接" + +#: settings/utils/ldap.py:675 msgid "Authentication failed (configuration incorrect): {}" msgstr "认证失败 (配置错误): {}" -#: settings/utils/ldap.py:681 +#: settings/utils/ldap.py:679 msgid "Authentication failed (username or password incorrect): {}" msgstr "认证失败 (用户名或密码不正确): {}" -#: settings/utils/ldap.py:683 +#: settings/utils/ldap.py:681 msgid "Authentication failed (Unknown): {}" msgstr "认证失败: (未知): {}" -#: settings/utils/ldap.py:686 +#: settings/utils/ldap.py:684 msgid "Authentication success: {}" msgstr "认证成功: {}" @@ -8599,6 +8599,15 @@ msgstr "企业专业版" msgid "Ultimate edition" msgstr "企业旗舰版" +#~ msgid "Synchronization start, please wait." +#~ msgstr "同步开始,请稍等" + +#~ msgid "Synchronization is running, please wait." +#~ msgstr "同步正在运行,请稍等" + +#~ msgid "Synchronization error: {}" +#~ msgstr "同步错误: {}" + #~ msgid "Copy" #~ msgstr "复制" diff --git a/apps/settings/api/ldap.py b/apps/settings/api/ldap.py index 486da3562..9c619e24d 100644 --- a/apps/settings/api/ldap.py +++ b/apps/settings/api/ldap.py @@ -28,71 +28,6 @@ from ..utils import ( logger = get_logger(__file__) -class LDAPTestingConfigAPI(AsyncApiMixin, CreateAPIView): - serializer_class = LDAPTestConfigSerializer - perm_model = Setting - rbac_perms = { - 'POST': 'settings.change_auth', - 'create': 'settings.change_auth', - } - - def is_need_async(self): - return True - - def create(self, request, *args, **kwargs): - serializer = self.serializer_class(data=request.data) - if not serializer.is_valid(): - return Response({"error": str(serializer.errors)}, status=400) - config = self.get_ldap_config(serializer) - ok, msg = LDAPTestUtil(config).test_config() - status = 200 if ok else 400 - return Response(msg, status=status) - - @staticmethod - def get_ldap_config(serializer): - server_uri = 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_ou = 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"] - auth_ldap = serializer.validated_data.get('AUTH_LDAP', False) - - if not password: - password = settings.AUTH_LDAP_BIND_PASSWORD - - config = { - 'server_uri': server_uri, - 'bind_dn': bind_dn, - 'password': password, - 'use_ssl': use_ssl, - 'search_ou': search_ou, - 'search_filter': search_filter, - 'attr_map': attr_map, - 'auth_ldap': auth_ldap - } - return config - - -class LDAPTestingLoginAPI(APIView): - serializer_class = LDAPTestLoginSerializer - perm_model = Setting - rbac_perms = { - 'POST': 'settings.change_auth' - } - - def post(self, request): - serializer = self.serializer_class(data=request.data) - if not serializer.is_valid(): - return Response({"error": str(serializer.errors)}, status=400) - username = serializer.validated_data['username'] - password = serializer.validated_data['password'] - ok, msg = LDAPTestUtil().test_login(username, password) - status = 200 if ok else 400 - return Response(msg, status=status) - - class LDAPUserListApi(generics.ListAPIView): serializer_class = LDAPUserSerializer perm_model = Setting @@ -162,31 +97,10 @@ class LDAPUserListApi(generics.ListAPIView): # 缓存有数据 if queryset is not None: return super().list(request, *args, **kwargs) - - sync_util = LDAPSyncUtil() - # 还没有同步任务 - if sync_util.task_no_start: - ok, msg = LDAPTestUtil().test_config() - if not ok: - return Response(data={'msg': msg}, status=400) - # 任务外部设置 task running 状态 - sync_util.set_task_status(sync_util.TASK_STATUS_IS_RUNNING) - t = threading.Thread(target=sync_ldap_user) - t.start() - data = {'msg': _('Synchronization start, please wait.')} - return Response(data=data, status=409) - # 同步任务正在执行 - if sync_util.task_is_running: - data = {'msg': _('Synchronization is running, please wait.')} - return Response(data=data, status=409) - # 同步任务执行结束 - if sync_util.task_is_over: - msg = sync_util.get_task_error_msg() - data = {'error': _('Synchronization error: {}'.format(msg))} + else: + data = {'msg': _('Users are not synchronized, please click the user synchronization button')} return Response(data=data, status=400) - return super().list(request, *args, **kwargs) - class LDAPUserImportAPI(APIView): perm_model = Setting @@ -232,18 +146,3 @@ class LDAPUserImportAPI(APIView): return Response({ 'msg': _('Imported {} users successfully (Organization: {})').format(count, orgs_name) }) - - -class LDAPCacheRefreshAPI(generics.RetrieveAPIView): - perm_model = Setting - rbac_perms = { - 'retrieve': 'settings.change_auth' - } - - def retrieve(self, request, *args, **kwargs): - try: - LDAPSyncUtil().clear_cache() - except Exception as e: - logger.error(str(e)) - return Response(data={'msg': str(e)}, status=400) - return Response(data={'msg': 'success'}) diff --git a/apps/settings/urls/api_urls.py b/apps/settings/urls/api_urls.py index 97055bc83..39a755845 100644 --- a/apps/settings/urls/api_urls.py +++ b/apps/settings/urls/api_urls.py @@ -8,11 +8,8 @@ app_name = 'common' urlpatterns = [ path('mail/testing/', api.MailTestingAPI.as_view(), name='mail-testing'), - path('ldap/testing/config/', api.LDAPTestingConfigAPI.as_view(), name='ldap-testing-config'), - path('ldap/testing/login/', api.LDAPTestingLoginAPI.as_view(), name='ldap-testing-login'), path('ldap/users/', api.LDAPUserListApi.as_view(), name='ldap-user-list'), path('ldap/users/import/', api.LDAPUserImportAPI.as_view(), name='ldap-user-import'), - path('ldap/cache/refresh/', api.LDAPCacheRefreshAPI.as_view(), name='ldap-cache-refresh'), path('wecom/testing/', api.WeComTestingAPI.as_view(), name='wecom-testing'), path('dingtalk/testing/', api.DingTalkTestingAPI.as_view(), name='dingtalk-testing'), path('feishu/testing/', api.FeiShuTestingAPI.as_view(), name='feishu-testing'), diff --git a/apps/settings/urls/ws_urls.py b/apps/settings/urls/ws_urls.py index b1555c957..7e8ae6100 100644 --- a/apps/settings/urls/ws_urls.py +++ b/apps/settings/urls/ws_urls.py @@ -6,4 +6,5 @@ app_name = 'common' urlpatterns = [ path('ws/setting/tools/', ws.ToolsWebsocket.as_asgi(), name='setting-tools-ws'), + path('ws/ldap/', ws.LdapWebsocket.as_asgi(), name='ldap-ws'), ] diff --git a/apps/settings/utils/ldap.py b/apps/settings/utils/ldap.py index d5fba8ce9..60babfa4e 100644 --- a/apps/settings/utils/ldap.py +++ b/apps/settings/utils/ldap.py @@ -277,6 +277,9 @@ class LDAPCacheUtil(object): class LDAPSyncUtil(object): + class LDAPSyncUtilException(Exception): + pass + CACHE_KEY_LDAP_USERS_SYNC_TASK_ERROR_MSG = 'CACHE_KEY_LDAP_USERS_SYNC_TASK_ERROR_MSG' CACHE_KEY_LDAP_USERS_SYNC_TASK_STATUS = 'CACHE_KEY_LDAP_USERS_SYNC_TASK_STATUS' @@ -328,34 +331,29 @@ class LDAPSyncUtil(object): def get_task_error_msg(self): logger.info('Get task error msg') - error_msg = cache.get(self.CACHE_KEY_LDAP_USERS_SYNC_TASK_ERROR_MSG) + error_msg = cache.get(self.CACHE_KEY_LDAP_USERS_SYNC_TASK_ERROR_MSG, '') return error_msg def delete_task_error_msg(self): logger.info('Delete task error msg') cache.delete(self.CACHE_KEY_LDAP_USERS_SYNC_TASK_ERROR_MSG) - def pre_sync(self): - self.set_task_status(self.TASK_STATUS_IS_RUNNING) - def sync(self): users = self.server_util.search() self.cache_util.set_users(users) - def post_sync(self): - self.set_task_status(self.TASK_STATUS_IS_OVER) - def perform_sync(self): logger.info('Start perform sync ldap users from server to cache') try: - self.pre_sync() + ok, msg = LDAPTestUtil().test_config() + if not ok: + raise self.LDAPSyncUtilException(msg) self.sync() except Exception as e: error_msg = str(e) logger.error(error_msg) self.set_task_error_msg(error_msg) finally: - self.post_sync() logger.info('End perform sync ldap users from server to cache') close_old_connections() @@ -650,9 +648,9 @@ class LDAPTestUtil(object): # test login def _test_before_login_check(self, username, password): - ok, msg = self.test_config() - if not ok: - raise LDAPConfigurationError(msg) + from settings.ws import CACHE_KEY_LDAP_TEST_CONFIG_TASK_STATUS, TASK_STATUS_IS_OVER + if cache.get(CACHE_KEY_LDAP_TEST_CONFIG_TASK_STATUS) != TASK_STATUS_IS_OVER: + raise self.LDAPBeforeLoginCheckError(_('Please test the connection first')) backend = LDAPAuthorizationBackend() ok, msg = backend.pre_check(username, password) diff --git a/apps/settings/ws.py b/apps/settings/ws.py index a8ae2c398..38bc54af0 100644 --- a/apps/settings/ws.py +++ b/apps/settings/ws.py @@ -1,19 +1,38 @@ # -*- coding: utf-8 -*- # import json +import asyncio from channels.generic.websocket import AsyncJsonWebsocketConsumer +from django.core.cache import cache +from django.conf import settings from common.db.utils import close_old_connections from common.utils import get_logger +from settings.serializers import ( + LDAPTestConfigSerializer, + LDAPTestLoginSerializer +) +from settings.tasks import sync_ldap_user +from settings.utils import ( + LDAPSyncUtil, LDAPTestUtil +) from .tools import ( verbose_ping, verbose_telnet, verbose_nmap, verbose_tcpdump, verbose_traceroute ) - logger = get_logger(__name__) +CACHE_KEY_LDAP_TEST_CONFIG_MSG = 'CACHE_KEY_LDAP_TEST_CONFIG_MSG' +CACHE_KEY_LDAP_TEST_LOGIN_MSG = 'CACHE_KEY_LDAP_TEST_LOGIN_MSG' +CACHE_KEY_LDAP_SYNC_USER_MSG = 'CACHE_KEY_LDAP_SYNC_USER_MSG' +CACHE_KEY_LDAP_TEST_CONFIG_TASK_STATUS = 'CACHE_KEY_LDAP_TEST_CONFIG_TASK_STATUS' +CACHE_KEY_LDAP_TEST_LOGIN_TASK_STATUS = 'CACHE_KEY_LDAP_TEST_LOGIN_TASK_STATUS' +CACHE_KEY_LDAP_SYNC_USER_TASK_STATUS = 'CACHE_KEY_LDAP_SYNC_USER_TASK_STATUS' +TASK_STATUS_IS_RUNNING = 'RUNNING' +TASK_STATUS_IS_OVER = 'OVER' + class ToolsWebsocket(AsyncJsonWebsocketConsumer): @@ -60,7 +79,7 @@ class ToolsWebsocket(AsyncJsonWebsocketConsumer): logger.info(f'Receive request tcpdump: {params}') await verbose_tcpdump(display=self.send_msg, **params) - async def imitate_traceroute(self,dest_ips): + async def imitate_traceroute(self, dest_ips): params = {'dest_ips': dest_ips} await verbose_traceroute(display=self.send_msg, **params) @@ -78,3 +97,113 @@ class ToolsWebsocket(AsyncJsonWebsocketConsumer): async def disconnect(self, code): await self.close() close_old_connections() + + +class LdapWebsocket(AsyncJsonWebsocketConsumer): + async def connect(self): + user = self.scope["user"] + if user.is_authenticated: + await self.accept() + else: + await self.close() + + async def receive(self, text_data=None, bytes_data=None, **kwargs): + data = json.loads(text_data) + msg_type = data.pop('msg_type', 'testing_config') + try: + tool_func = getattr(self, f'run_{msg_type.lower()}') + await asyncio.to_thread(tool_func, data) + if msg_type == 'testing_config': + ok, msg = cache.get(CACHE_KEY_LDAP_TEST_CONFIG_MSG) + elif msg_type == 'sync_user': + ok, msg = cache.get(CACHE_KEY_LDAP_SYNC_USER_MSG) + else: + ok, msg = cache.get(CACHE_KEY_LDAP_TEST_LOGIN_MSG) + await self.send_msg(ok, msg) + except Exception as error: + await self.send_msg(msg='Exception: %s' % error) + + async def send_msg(self, ok=True, msg=''): + await self.send_json({'ok': ok, 'msg': f'{msg}'}) + + async def disconnect(self, code): + await self.close() + close_old_connections() + + @staticmethod + def get_ldap_config(serializer): + server_uri = 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_ou = 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"] + auth_ldap = serializer.validated_data.get('AUTH_LDAP', False) + + if not password: + password = settings.AUTH_LDAP_BIND_PASSWORD + + config = { + 'server_uri': server_uri, + 'bind_dn': bind_dn, + 'password': password, + 'use_ssl': use_ssl, + 'search_ou': search_ou, + 'search_filter': search_filter, + 'attr_map': attr_map, + 'auth_ldap': auth_ldap + } + return config + + @staticmethod + def task_is_over(task_key): + return cache.get(task_key) == TASK_STATUS_IS_OVER + + @staticmethod + def set_task_status_over(task_key): + cache.set(task_key, TASK_STATUS_IS_OVER, 120) + + @staticmethod + def set_task_msg(task_key, ok, msg): + cache.set(task_key, (ok, msg), 120) + + def run_testing_config(self, data): + while True: + if self.task_is_over(CACHE_KEY_LDAP_TEST_CONFIG_TASK_STATUS): + break + else: + serializer = LDAPTestConfigSerializer(data=data) + if not serializer.is_valid(): + self.send_msg(msg=f'error: {str(serializer.errors)}') + config = self.get_ldap_config(serializer) + ok, msg = LDAPTestUtil(config).test_config() + self.set_task_status_over(CACHE_KEY_LDAP_TEST_CONFIG_TASK_STATUS) + self.set_task_msg(CACHE_KEY_LDAP_TEST_CONFIG_MSG, ok, msg) + + def run_testing_login(self, data): + while True: + if self.task_is_over(CACHE_KEY_LDAP_TEST_LOGIN_TASK_STATUS): + break + else: + serializer = LDAPTestLoginSerializer(data=data) + if not serializer.is_valid(): + self.send_msg(msg=f'error: {str(serializer.errors)}') + username = serializer.validated_data['username'] + password = serializer.validated_data['password'] + ok, msg = LDAPTestUtil().test_login(username, password) + self.set_task_status_over(CACHE_KEY_LDAP_TEST_LOGIN_TASK_STATUS) + self.set_task_msg(CACHE_KEY_LDAP_TEST_LOGIN_MSG, ok, msg) + + def run_sync_user(self, data): + while True: + if self.task_is_over(CACHE_KEY_LDAP_SYNC_USER_TASK_STATUS): + break + else: + sync_util = LDAPSyncUtil() + sync_util.clear_cache() + sync_ldap_user() + msg = sync_util.get_task_error_msg() + ok = False if msg else True + self.set_task_status_over(CACHE_KEY_LDAP_SYNC_USER_TASK_STATUS) + self.set_task_msg(CACHE_KEY_LDAP_SYNC_USER_MSG, ok, msg)