فهرست منبع

installer api v1 => v3 & XHRized

Taichi Masuyama 3 سال پیش
والد
کامیت
14631115f8

+ 38 - 4
packages/app/src/components/InstallerForm.tsx

@@ -1,10 +1,14 @@
-import { memo, useCallback, useState } from 'react';
+import {
+  FormEventHandler, memo, useCallback, useState,
+} from 'react';
 
 import i18next from 'i18next';
 import { useTranslation, i18n } from 'next-i18next';
 
 import { i18n as i18nConfig } from '^/config/next-i18next.config';
 
+import { apiv3Post } from '~/client/util/apiv3-client';
+
 const InstallerForm = memo((): JSX.Element => {
   const { t } = useTranslation();
 
@@ -23,8 +27,7 @@ const InstallerForm = memo((): JSX.Element => {
     setValidUserName(res.data.valid);
   }, []);
 
-  // TODO: XHRize https://redmine.weseek.co.jp/issues/105252
-  const submitHandler = useCallback((e) => {
+  const submitHandler: FormEventHandler = useCallback(async(e: any) => {
     e.preventDefault();
 
     if (isSubmittingDisabled) {
@@ -35,6 +38,37 @@ const InstallerForm = memo((): JSX.Element => {
     setTimeout(() => {
       setSubmittingDisabled(false);
     }, 3000);
+
+    if (e.target.elements == null) {
+      return;
+    }
+
+    const formData = e.target.elements;
+
+    const {
+      'registerForm[username]': { value: username },
+      'registerForm[name]': { value: name },
+      'registerForm[email]': { value: email },
+      'registerForm[password]': { value: password },
+    } = formData;
+
+    const data = {
+      registerForm: {
+        username,
+        name,
+        email,
+        password,
+        'app:globalLang': formData['registerForm[app:globalLang]'].value,
+      },
+    };
+
+    try {
+      await apiv3Post('/installer', data);
+      window.location.href = '/';
+    }
+    catch (err) {
+      // TODO: show toastr https://redmine.weseek.co.jp/issues/105441
+    }
   }, [isSubmittingDisabled]);
 
   const hasErrorClass = isValidUserName ? '' : ' has-error';
@@ -53,7 +87,7 @@ const InstallerForm = memo((): JSX.Element => {
         </div>
       </div>
       <div className="row">
-        <form role="form" action="/_api/v3/installer" method="post" id="register-form" className="col-md-12" onSubmit={submitHandler}>
+        <form role="form" id="register-form" className="col-md-12" onSubmit={submitHandler}>
           <div className="dropdown mb-3">
             <div className="d-flex dropdown-with-icon">
               <i className="icon-bubbles border-0 rounded-0" />

+ 0 - 7
packages/app/src/server/routes/apiv3/index.js

@@ -40,13 +40,6 @@ module.exports = (crowi) => {
   // auth
   routerForAuth.use('/logout', require('./logout')(crowi));
 
-  // installer
-  const isInstalled = crowi.configManager.getConfig('crowi', 'app:installed');
-  if (!isInstalled) {
-    router.use('/installer', require('./installer')(crowi));
-  }
-
-
   router.use('/in-app-notification', require('./in-app-notification')(crowi));
 
   router.use('/personal-setting', require('./personal-setting')(crowi));

+ 13 - 19
packages/app/src/server/routes/apiv3/installer.ts

@@ -5,8 +5,9 @@ import ErrorV3 from '~/server/models/vo/error-apiv3';
 import loggerFactory from '~/utils/logger';
 
 import Crowi from '../../crowi';
+import { generateAddActivityMiddleware } from '../../middlewares/add-activity';
 import { apiV3FormValidator } from '../../middlewares/apiv3-form-validator';
-import { registerValidation, registerRules } from '../../middlewares/register-form-validator';
+import { registerRules } from '../../middlewares/register-form-validator';
 import { InstallerService, FailedToCreateAdminUserError } from '../../service/installer';
 
 import { ApiV3Response } from './interfaces/apiv3-response';
@@ -15,20 +16,17 @@ import { ApiV3Response } from './interfaces/apiv3-response';
 const logger = loggerFactory('growi:routes:apiv3:installer');
 
 
-type FormRequest = Request & { form: any };
+type FormRequest = Request & { form: any, logIn: any };
 
 module.exports = (crowi: Crowi): Router => {
-  const adminRequired = require('../../middlewares/admin-required')(crowi);
-  const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
-  const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
-  const applicationNotInstalled = require('../../middlewares/application-not-installed')(crowi);
+  const addActivity = generateAddActivityMiddleware(crowi);
 
   const activityEvent = crowi.event('activity');
 
   const router = express.Router();
 
   // eslint-disable-next-line max-len
-  router.post('/', applicationNotInstalled, accessTokenParser, loginRequiredStrictly, adminRequired, registerRules, registerValidation, apiV3FormValidator, async(req: FormRequest, res: ApiV3Response) => {
+  router.post('/', registerRules(), apiV3FormValidator, addActivity, async(req: FormRequest, res: ApiV3Response) => {
     const appService = crowi.appService;
     if (appService == null) {
       return res.apiv3Err(new ErrorV3('GROWI cannot be installed due to an internal error', 'app_service_not_setup'), 500);
@@ -54,27 +52,23 @@ module.exports = (crowi: Crowi): Router => {
     }
     catch (err) {
       if (err instanceof FailedToCreateAdminUserError) {
-        req.form.errors.push(req.t('message.failed_to_create_admin_user', { errMessage: err.message }));
+        return res.apiv3Err(new ErrorV3(err.message, 'failed_to_create_admin_user'));
       }
-      return res.render('installer');
+      return res.apiv3Err(new ErrorV3(err, 'failed_to_create_admin_user'));
     }
 
     await appService.setupAfterInstall();
 
+    const parameters = { action: SupportedAction.ACTION_USER_REGISTRATION_SUCCESS };
+    activityEvent.emit('update', res.locals.activity._id, parameters);
+
     // login with passport
     req.logIn(adminUser, (err) => {
-      if (err) {
-        req.flash('successMessage', req.t('message.complete_to_install1'));
-        req.session.redirectTo = '/';
-        return res.redirect('/login');
+      if (err != null) {
+        return res.apiv3Err(new ErrorV3(err, 'failed_to_login_after_install'));
       }
 
-      req.flash('successMessage', req.t('message.complete_to_install2'));
-
-      const parameters = { action: SupportedAction.ACTION_USER_REGISTRATION_SUCCESS };
-      activityEvent.emit('update', res.locals.activity._id, parameters);
-
-      return res.redirect('/');
+      return res.apiv3({ message: 'Installation completed (Logged in as an admin user)' });
     });
   });
 

+ 3 - 2
packages/app/src/server/routes/index.js

@@ -52,6 +52,8 @@ module.exports = function(crowi, app) {
   // const hackmd = require('./hackmd')(crowi, app);
   const ogp = require('./ogp')(crowi);
 
+  const apiv3Installer = require('./apiv3/installer')(crowi);
+
   const next = nextFactory(crowi);
 
   const unavailableWhenMaintenanceMode = generateUnavailableWhenMaintenanceModeMiddleware(crowi);
@@ -93,9 +95,8 @@ module.exports = function(crowi, app) {
 
   // installer
   if (!isInstalled) {
-    const installer = require('./installer')(crowi);
+    app.use('/_api/v3/installer', applicationNotInstalled, apiv3Installer);
     app.get('/installer'              , applicationNotInstalled, next.delegateToNext);
-    app.post('/installer'             , applicationNotInstalled , registerFormValidator.registerRules(), registerFormValidator.registerValidation, csrfProtection, addActivity, installer.install);
     return;
   }