Просмотр исходного кода

Merge branch 'feat/ldap-group-sync' into imprv/132883-133247-alert-user-before-external-user-group-sync-exec

Futa Arai 2 лет назад
Родитель
Сommit
4ab47b2bca

+ 3 - 2
apps/app/public/static/locales/en_US/admin.json

@@ -1085,7 +1085,8 @@
       "name_mapper_detail": "Attribute to map as group name",
       "updated_group_sync_settings": "Updated LDAP group sync settings",
       "password": "Password",
-      "password_detail": "Login password is necessary because Bind type is set to User Bind"
+      "password_detail": "Login password is necessary because Bind type is set to User Bind",
+      "auth_not_set": "Enable and configure LDAP auth in security settings before sync"
     },
     "keycloak": {
       "group_sync_settings": "Keycloak Group Sync Settings",
@@ -1101,7 +1102,7 @@
       "group_sync_client_secret_detail": "Id of the secret used to authenticate to request to Keycloak admin API",
       "updated_group_sync_settings": "Updated Keycloak group sync settings",
       "preserve_deleted_keycloak_groups": "Preserve Deleted Keycloak Groups",
-      "auth_not_set": "Please set up and enable OIDC or SAML with Keycloak in security settings before sync"
+      "auth_not_set": "Enable and configure OIDC or SAML with Keycloak in security settings before sync"
     },
     "auto_generate_user_on_sync": "Auto Generate User on Sync",
     "description_mapper_detail": "Attribute to map as group description. Description can be edited after sync. However, when a mapper is set, the edited value can possibly be overwritten by the next sync."

+ 3 - 2
apps/app/public/static/locales/ja_JP/admin.json

@@ -1095,7 +1095,8 @@
       "name_mapper_detail": "グループの「名前」として読み込む属性",
       "updated_group_sync_settings": "LDAP グループ同期設定を更新しました",
       "password": "パスワード",
-      "password_detail": "認証設定がユーザ Bind のため、ログイン時のパスワードの入力が必要となります"
+      "password_detail": "認証設定がユーザ Bind のため、ログイン時のパスワードの入力が必要となります",
+      "auth_not_set": "同期実行前にセキュリティ設定で LDAP 認証を有効にし、設定してください"
     },
     "keycloak": {
       "group_sync_settings": "Keycloak グループ同期設定",
@@ -1111,7 +1112,7 @@
       "group_sync_client_secret_detail": "Keycloak admin API にリクエストするための認証に使う client の secret",
       "updated_group_sync_settings": "Keycloak グループ同期設定を更新しました",
       "preserve_deleted_keycloak_groups": "Keycloak から削除されたグループを GROWI に残す",
-      "auth_not_set": "同期実行前にセキュリティ設定で Keycloak を使った OIDC または SAML 認証を設定し、有効にしてください"
+      "auth_not_set": "同期実行前にセキュリティ設定で Keycloak を使った OIDC または SAML 認証を有効にし、設定してください"
     },
     "auto_generate_user_on_sync": "作成されていない GROWI アカウントを自動生成する",
     "description_mapper_detail": "グループの「説明」として読み込む属性。「説明」は同期後に編集可能です。ただし、mapper が設定されている場合、編集内容は再同期によって上書きされます。"

+ 3 - 2
apps/app/public/static/locales/zh_CN/admin.json

@@ -1094,7 +1094,8 @@
       "name_mapper_detail": "Attribute to map as group name",
       "updated_group_sync_settings": "Updated LDAP group sync settings",
       "password": "Password",
-      "password_detail": "Login password is necessary because Bind type is set to User Bind"
+      "password_detail": "Login password is necessary because Bind type is set to User Bind",
+      "auth_not_set": "Enable and configure LDAP auth in security settings before sync"
     },
     "keycloak": {
       "group_sync_settings": "Keycloak Group Sync Settings",
@@ -1110,7 +1111,7 @@
       "group_sync_client_secret_detail": "Id of the secret used to authenticate to request to Keycloak admin API",
       "updated_group_sync_settings": "Updated Keycloak group sync settings",
       "preserve_deleted_keycloak_groups": "Preserve Deleted Keycloak Groups",
-      "auth_not_set": "Please set up and enable OIDC or SAML with Keycloak in security settings before sync"
+      "auth_not_set": "Enable and configure OIDC or SAML with Keycloak in security settings before sync"
     },
     "auto_generate_user_on_sync": "Auto Generate User on Sync",
     "description_mapper_detail": "Attribute to map as group description. Description can be edited after sync. However, when a mapper is set, the edited value can possibly be overwritten by the next sync."

+ 3 - 3
apps/app/src/components/SavePageControls/GrantSelector/GrantSelector.tsx

@@ -1,7 +1,6 @@
 import React, { useCallback, useState } from 'react';
 
-import { isPopulated } from '@growi/core';
-import type { GroupType, IGrantedGroup } from '@growi/core';
+import { isPopulated, GroupType, type IGrantedGroup } from '@growi/core';
 import { useTranslation } from 'next-i18next';
 import {
   UncontrolledDropdown,
@@ -185,7 +184,8 @@ export const GrantSelector = (props: Props): JSX.Element => {
         { myUserGroups.map((group) => {
           return (
             <button key={group.item._id} type="button" className="list-group-item list-group-item-action" onClick={() => groupListItemClickHandler(group)}>
-              <h5>{group.item.name}</h5>
+              <h5 className="d-inline-block">{group.item.name}</h5>
+              {group.type === GroupType.externalUserGroup && <span className="ml-2 badge badge-pill badge-info">external</span>}
               {/* TODO: Replace <div className="small">(TBD) List group members</div> */}
             </button>
           );

+ 4 - 2
apps/app/src/features/external-user-group/client/components/ExternalUserGroup/SyncExecution.tsx

@@ -84,11 +84,13 @@ export const SyncExecution = ({
   const onSyncExecConfirmBtnClick = useCallback(async() => {
     setIsAlertModalOpen(false);
     try {
-      await requestSyncAPI(currentSubmitEvent);
-      setProgress({ total: 0, current: 0 });
+      // set sync status before requesting to API, so that setting to syncFailed does not get overwritten
       setSyncStatus(SyncStatus.syncExecuting);
+      setProgress({ total: 0, current: 0 });
+      await requestSyncAPI(currentSubmitEvent);
     }
     catch (errs) {
+      setSyncStatus(SyncStatus.syncFailed);
       toastError(t(errs[0]?.code));
     }
   }, [t, requestSyncAPI, currentSubmitEvent]);

+ 18 - 3
apps/app/src/features/external-user-group/server/routes/apiv3/external-user-group.ts

@@ -314,8 +314,23 @@ module.exports = (crowi: Crowi): Router => {
       );
     }
 
+    const isLdapEnabled = await configManager.getConfig('crowi', 'security:passport-ldap:isEnabled');
+    if (!isLdapEnabled) {
+      return res.apiv3Err(
+        new ErrorV3('Authentication using ldap is not set', 'external_user_group.ldap.auth_not_set'), 422,
+      );
+    }
+
+    try {
+      await crowi.ldapUserGroupSyncService?.init(req.user.name, req.body.password);
+    }
+    catch (e) {
+      return res.apiv3Err(
+        new ErrorV3('LDAP group sync failed', 'external_user_group.sync_failed'), 500,
+      );
+    }
+
     // Do not await for sync to finish. Result (completed, failed) will be notified to the client by socket-io.
-    await crowi.ldapUserGroupSyncService?.init(req.user.name, req.body.password);
     crowi.ldapUserGroupSyncService?.syncExternalUserGroups();
 
     return res.apiv3({}, 202);
@@ -352,12 +367,12 @@ module.exports = (crowi: Crowi): Router => {
     const authProviderType = getAuthProviderType();
     if (authProviderType == null) {
       return res.apiv3Err(
-        new ErrorV3('Authentication using keycloak is not set', 'external_user_group.keycloak.auth_not_set'), 500,
+        new ErrorV3('Authentication using keycloak is not set', 'external_user_group.keycloak.auth_not_set'), 422,
       );
     }
 
-    // Do not await for sync to finish. Result (completed, failed) will be notified to the client by socket-io.
     crowi.keycloakUserGroupSyncService?.init(authProviderType);
+    // Do not await for sync to finish. Result (completed, failed) will be notified to the client by socket-io.
     crowi.keycloakUserGroupSyncService?.syncExternalUserGroups();
 
     return res.apiv3({}, 202);