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

refs 123281: ldap group sync settings form

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

+ 2 - 2
apps/app/src/components/Admin/UserGroup/ExternalGroup/ExternalGroupManagement.tsx

@@ -4,7 +4,7 @@ import { TabContent, TabPane } from 'reactstrap';
 
 import CustomNav from '~/components/CustomNavigation/CustomNav';
 
-import { LDAPGroupSyncSettings } from './LDAPGroupSyncSettings';
+import { LDAPGroupSyncSettingsForm } from './LDAPGroupSyncSettingsForm';
 
 export const ExternalGroupManagement: FC = () => {
   const [activeTab, setActiveTab] = useState('ldap');
@@ -35,7 +35,7 @@ export const ExternalGroupManagement: FC = () => {
     />
     <TabContent activeTab={activeTab} className="p-5">
       <TabPane tabId="ldap">
-        {activeComponents.has('ldap') && <LDAPGroupSyncSettings />}
+        {activeComponents.has('ldap') && <LDAPGroupSyncSettingsForm />}
       </TabPane>
     </TabContent>
   </>;

+ 74 - 22
apps/app/src/components/Admin/UserGroup/ExternalGroup/LDAPGroupSyncSettings.tsx → apps/app/src/components/Admin/UserGroup/ExternalGroup/LDAPGroupSyncSettingsForm.tsx

@@ -1,6 +1,46 @@
-import { FC } from 'react';
+import {
+  FC, useCallback, useEffect, useState,
+} from 'react';
+
+import { useTranslation } from 'react-i18next';
+
+import { apiv3Put } from '~/client/util/apiv3-client';
+import { toastError, toastSuccess } from '~/client/util/toastr';
+import { LDAPGroupSyncSettings } from '~/interfaces/external-user-group';
+import { useSWRxLDAPGroupSyncSettings } from '~/stores/external-user-group';
+
+export const LDAPGroupSyncSettingsForm: FC = () => {
+  const { t } = useTranslation('admin');
+
+  const { data: ldapGroupSyncSettings } = useSWRxLDAPGroupSyncSettings();
+
+  const [formValues, setFormValues] = useState<LDAPGroupSyncSettings>({
+    ldapGroupsDN: '',
+    ldapGroupMembershipAttribute: '',
+    ldapGroupMembershipAttributeType: '',
+    ldapGroupChildGroupAttribute: '',
+    autoGenerateUserOnLDAPGroupSync: false,
+    preserveDeletedLDAPGroups: false,
+    ldapGroupNameAttribute: '',
+    ldapGroupDescriptionAttribute: '',
+  });
+
+  useEffect(() => {
+    if (ldapGroupSyncSettings != null) {
+      setFormValues(ldapGroupSyncSettings);
+    }
+  }, [ldapGroupSyncSettings, setFormValues]);
+
+  const submitHandler = useCallback(async() => {
+    try {
+      await apiv3Put('/external-user-groups/ldap/sync-settings', formValues);
+      toastSuccess('更新しました');
+    }
+    catch (err) {
+      toastError(err);
+    }
+  }, [formValues]);
 
-export const LDAPGroupSyncSettings: FC = () => {
   return <>
     <h3 className="border-bottom">LDAP グループ同期設定</h3>
     <div className="row form-group">
@@ -11,8 +51,8 @@ export const LDAPGroupSyncSettings: FC = () => {
           type="text"
           name="ldapGroupsDN"
           id="ldapGroupsDN"
-          defaultValue={''}
-          onChange={() => {}}
+          value={formValues.ldapGroupsDN}
+          onChange={e => setFormValues({ ...formValues, ldapGroupsDN: e.target.value })}
         />
         <p className="form-text text-muted">
           <small>グループ検索をするベース DN</small>
@@ -27,8 +67,8 @@ export const LDAPGroupSyncSettings: FC = () => {
           type="text"
           name="ldapGroupMembershipAttribute"
           id="ldapGroupMembershipAttribute"
-          defaultValue={''}
-          onChange={() => {}}
+          value={formValues.ldapGroupMembershipAttribute}
+          onChange={e => setFormValues({ ...formValues, ldapGroupMembershipAttribute: e.target.value })}
         />
         <p className="form-text text-muted">
           <small>
@@ -43,14 +83,15 @@ export const LDAPGroupSyncSettings: FC = () => {
         「所属メンバーを表す LDAP 属性」値の種類
       </label>
       <div className="col-md-6">
-        <input
+        <select
           className="form-control"
-          type="text"
           name="ldapGroupMembershipAttributeType"
           id="ldapGroupMembershipAttributeType"
-          defaultValue={''}
-          onChange={() => {}}
-        />
+          value={formValues.ldapGroupMembershipAttributeType}
+          onChange={e => setFormValues({ ...formValues, ldapGroupMembershipAttributeType: e.target.value })}>
+          <option value="DN">DN</option>
+          <option value="UID">UID</option>
+        </select>
         <p className="form-text text-muted">
           <small>
           グループの所属メンバーを表すグループオブジェクトの属性値は DN か UID か
@@ -66,9 +107,8 @@ export const LDAPGroupSyncSettings: FC = () => {
           type="text"
           name="ldapGroupChildGroupAttribute"
           id="ldapGroupChildGroupAttribute"
-          defaultValue={''}
-          onChange={() => {}}
-        />
+          value={formValues.ldapGroupChildGroupAttribute}
+          onChange={e => setFormValues({ ...formValues, ldapGroupChildGroupAttribute: e.target.value })}/>
         <p className="form-text text-muted">
           <small>
             グループに所属する子グループを表すグループオブジェクトの属性。属性値は DN である必要があります。<br />
@@ -90,8 +130,8 @@ export const LDAPGroupSyncSettings: FC = () => {
             className="custom-control-input"
             name="autoGenerateUserOnLDAPGroupSync"
             id="autoGenerateUserOnLDAPGroupSync"
-            checked={true}
-            onChange={(e) => {}}
+            checked={formValues.autoGenerateUserOnLDAPGroupSync}
+            onChange={() => setFormValues({ ...formValues, autoGenerateUserOnLDAPGroupSync: !formValues.autoGenerateUserOnLDAPGroupSync })}
           />
           <label
             className="custom-control-label"
@@ -115,8 +155,8 @@ export const LDAPGroupSyncSettings: FC = () => {
             className="custom-control-input"
             name="preserveDeletedLDAPGroups"
             id="preserveDeletedLDAPGroups"
-            checked={true}
-            onChange={(e) => {}}
+            checked={formValues.preserveDeletedLDAPGroups}
+            onChange={() => setFormValues({ ...formValues, preserveDeletedLDAPGroups: !formValues.preserveDeletedLDAPGroups })}
           />
           <label
             className="custom-control-label"
@@ -136,8 +176,8 @@ export const LDAPGroupSyncSettings: FC = () => {
           type="text"
           name="ldapGroupNameAttribute"
           id="ldapGroupNameAttribute"
-          defaultValue={''}
-          onChange={() => {}}
+          value={formValues.ldapGroupNameAttribute}
+          onChange={e => setFormValues({ ...formValues, ldapGroupNameAttribute: e.target.value })}
           placeholder="Default: cn"
         />
         <p className="form-text text-muted">
@@ -157,8 +197,8 @@ export const LDAPGroupSyncSettings: FC = () => {
           type="text"
           name="ldapGroupDescriptionAttribute"
           id="ldapGroupDescriptionAttribute"
-          defaultValue={''}
-          onChange={() => {}}
+          value={formValues.ldapGroupDescriptionAttribute}
+          onChange={e => setFormValues({ ...formValues, ldapGroupDescriptionAttribute: e.target.value })}
         />
         <p className="form-text text-muted">
           <small>
@@ -167,5 +207,17 @@ export const LDAPGroupSyncSettings: FC = () => {
         </p>
       </div>
     </div>
+
+    <div className="row my-3">
+      <div className="offset-3 col-5">
+        <button
+          type="button"
+          className="btn btn-primary"
+          onClick={submitHandler}
+        >
+          {t('Update')}
+        </button>
+      </div>
+    </div>
   </>;
 };

+ 10 - 0
apps/app/src/interfaces/external-user-group.ts

@@ -0,0 +1,10 @@
+export interface LDAPGroupSyncSettings {
+  ldapGroupsDN: string
+  ldapGroupMembershipAttribute: string
+  ldapGroupMembershipAttributeType: string
+  ldapGroupChildGroupAttribute: string
+  autoGenerateUserOnLDAPGroupSync: boolean
+  preserveDeletedLDAPGroups: boolean
+  ldapGroupNameAttribute: string
+  ldapGroupDescriptionAttribute?: string
+}

+ 77 - 0
apps/app/src/server/routes/apiv3/external-user-group.ts

@@ -0,0 +1,77 @@
+import { Router, Request } from 'express';
+import { body, validationResult } from 'express-validator';
+
+import Crowi from '~/server/crowi';
+import { ApiV3Response } from '~/server/routes/apiv3/interfaces/apiv3-response';
+import loggerFactory from '~/utils/logger';
+
+const logger = loggerFactory('growi:routes:apiv3:external-user-group');
+
+const router = Router();
+
+interface AuthorizedRequest extends Request {
+  user?: any
+}
+
+module.exports = (crowi: Crowi): Router => {
+  const loginRequiredStrictly = require('~/server/middlewares/login-required')(crowi);
+  const adminRequired = require('../../middlewares/admin-required')(crowi);
+
+  const validators = {
+    ldapSyncSettings: [
+      body('ldapGroupsDN').exists().isString(),
+      body('ldapGroupMembershipAttribute').exists().isString(),
+      body('ldapGroupMembershipAttributeType').exists().isString(),
+      body('ldapGroupChildGroupAttribute').exists().isString(),
+      body('autoGenerateUserOnLDAPGroupSync').exists().isBoolean(),
+      body('preserveDeletedLDAPGroups').exists().isBoolean(),
+      body('ldapGroupNameAttribute').exists().isString(),
+      body('ldapGroupDescriptionAttribute').isString(),
+    ],
+  };
+
+  router.get('/ldap/sync-settings', loginRequiredStrictly, adminRequired, validators.ldapSyncSettings, async(req: AuthorizedRequest, res: ApiV3Response) => {
+    const settings = {
+      ldapGroupsDN: await crowi.configManager?.getConfig('crowi', 'external-user-group:ldap:groupsDN'),
+      ldapGroupMembershipAttribute: await crowi.configManager?.getConfig('crowi', 'external-user-group:ldap:groupMembershipAttribute'),
+      ldapGroupMembershipAttributeType: await crowi.configManager?.getConfig('crowi', 'external-user-group:ldap:groupMembershipAttributeType'),
+      ldapGroupChildGroupAttribute: await crowi.configManager?.getConfig('crowi', 'external-user-group:ldap:groupChildGroupAttribute'),
+      autoGenerateUserOnLDAPGroupSync: await crowi.configManager?.getConfig('crowi', 'external-user-group:ldap:autoGenerateUserOnGroupSync'),
+      preserveDeletedLDAPGroups: await crowi.configManager?.getConfig('crowi', 'external-user-group:ldap:preserveDeletedGroups'),
+      ldapGroupNameAttribute: await crowi.configManager?.getConfig('crowi', 'external-user-group:ldap:groupNameAttribute'),
+      ldapGroupDescriptionAttribute: await crowi.configManager?.getConfig('crowi', 'external-user-group:ldap:groupDescriptionAttribute'),
+    };
+
+    return res.apiv3(settings);
+  });
+
+  router.put('/ldap/sync-settings', loginRequiredStrictly, adminRequired, validators.ldapSyncSettings, async(req: AuthorizedRequest, res: ApiV3Response) => {
+    const requestParams = {
+      'external-user-group:ldap:groupsDN': req.body.ldapGroupsDN,
+      'external-user-group:ldap:groupMembershipAttribute': req.body.ldapGroupMembershipAttribute,
+      'external-user-group:ldap:groupMembershipAttributeType': req.body.ldapGroupMembershipAttributeType,
+      'external-user-group:ldap:groupChildGroupAttribute': req.body.ldapGroupChildGroupAttribute,
+      'external-user-group:ldap:autoGenerateUserOnGroupSync': req.body.autoGenerateUserOnLDAPGroupSync,
+      'external-user-group:ldap:preserveDeletedGroups': req.body.preserveDeletedLDAPGroups,
+      'external-user-group:ldap:groupNameAttribute': req.body.ldapGroupNameAttribute,
+      'external-user-group:ldap:groupDescriptionAttribute': req.body.ldapGroupDescriptionAttribute,
+    };
+
+    const errors = validationResult(req);
+    if (!errors.isEmpty()) {
+      return res.apiv3({}, 204);
+    }
+
+    try {
+      await crowi.configManager?.updateConfigsInTheSameNamespace('crowi', requestParams, true);
+      return res.status(204).json();
+    }
+    catch (err) {
+      logger.error(err);
+      return res.apiv3Err(err, 500);
+    }
+  });
+
+  return router;
+
+};

+ 1 - 0
apps/app/src/server/routes/apiv3/index.js

@@ -34,6 +34,7 @@ module.exports = (crowi, app) => {
   routerForAdmin.use('/notification-setting', require('./notification-setting')(crowi));
   routerForAdmin.use('/users', require('./users')(crowi));
   routerForAdmin.use('/user-groups', require('./user-group')(crowi));
+  routerForAdmin.use('/external-user-groups', require('./external-user-group')(crowi));
   routerForAdmin.use('/export', require('./export')(crowi));
   routerForAdmin.use('/import', importRoute(crowi));
   routerForAdmin.use('/search', require('./search')(crowi));

+ 13 - 0
apps/app/src/stores/external-user-group.ts

@@ -0,0 +1,13 @@
+import useSWR, { SWRResponse } from 'swr';
+
+import { apiv3Get } from '~/client/util/apiv3-client';
+import { LDAPGroupSyncSettings } from '~/interfaces/external-user-group';
+
+export const useSWRxLDAPGroupSyncSettings = (): SWRResponse<LDAPGroupSyncSettings, Error> => {
+  return useSWR(
+    '/external-user-groups/ldap/sync-settings',
+    endpoint => apiv3Get(endpoint).then((response) => {
+      return response.data;
+    }),
+  );
+};