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

refactor application-not-installed.ts

Yuki Takei 1 год назад
Родитель
Сommit
2c9ad08675

+ 35 - 8
apps/app/src/server/middlewares/application-not-installed.ts

@@ -1,14 +1,41 @@
-/** @param {import('~/server/crowi').default} crowi Crowi instance */
-module.exports = (crowi) => {
+import type { NextFunction, Request, Response } from 'express';
+import createError, { isHttpError } from 'http-errors';
+
+import type Crowi from '../crowi';
+
+export const generateCheckerMiddleware = (crowi: Crowi) => async(req: Request, res: Response, next: NextFunction): Promise<void> => {
   const { appService } = crowi;
 
-  return async(req, res, next) => {
-    const isDBInitialized = await appService.isDBInitialized(true);
+  const isDBInitialized = await appService.isDBInitialized(true);
+
+  if (isDBInitialized) {
+    return next(createError(409, 'Application is already installed'));
+  }
+
+  return next();
+};
 
-    if (isDBInitialized) {
-      return res.redirect('/');
-    }
+export const allreadyInstalledMiddleware = async(req: Request, res: Response, next: NextFunction): Promise<void> => {
+  return next(createError(409, 'Application is already installed'));
+};
 
+export const handleAsApiError = (error: Error, req: Request, res: Response, next: NextFunction): void => {
+  if (error == null) {
     return next();
-  };
+  }
+
+  if (isHttpError(error)) {
+    const httpError = error as createError.HttpError;
+    res.status(httpError.status).json({ message: httpError.message });
+    return;
+  }
+
+  next();
+};
+
+export const redirectToTopOnError = (error: Error, req: Request, res: Response, next: NextFunction): void => {
+  if (error != null) {
+    return res.redirect('/');
+  }
+  return next();
 };

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

@@ -1,5 +1,6 @@
 import growiPlugin from '~/features/growi-plugin/server/routes/apiv3/admin';
 import { factory as openaiRouteFactory } from '~/features/openai/server/routes';
+import { allreadyInstalledMiddleware } from '~/server/middlewares/application-not-installed';
 import loggerFactory from '~/utils/logger';
 
 import { generateAddActivityMiddleware } from '../../middlewares/add-activity';
@@ -71,8 +72,11 @@ module.exports = (crowi, app) => {
     userActivation.validateRegisterForm, userActivation.registerAction(crowi));
 
   // installer
+  routerForAdmin.use('/installer', isInstalled
+    ? allreadyInstalledMiddleware
+    : require('./installer')(crowi));
+
   if (!isInstalled) {
-    routerForAdmin.use('/installer', require('./installer')(crowi));
     return [router, routerForAdmin, routerForAuth];
   }
 

+ 8 - 5
apps/app/src/server/routes/apiv3/installer.ts

@@ -8,6 +8,7 @@ import loggerFactory from '~/utils/logger';
 
 import type Crowi from '../../crowi';
 import { generateAddActivityMiddleware } from '../../middlewares/add-activity';
+import * as applicationNotInstalled from '../../middlewares/application-not-installed';
 import { registerRules, registerValidation } from '../../middlewares/register-form-validator';
 import { InstallerService, FailedToCreateAdminUserError } from '../../service/installer';
 
@@ -27,6 +28,12 @@ module.exports = (crowi: Crowi): Router => {
 
   const router = express.Router();
 
+  // check application is not installed yet
+  router.use(
+    applicationNotInstalled.generateCheckerMiddleware(crowi),
+    applicationNotInstalled.handleAsApiError,
+  );
+
   const minPasswordLength = configManager.getConfig('app:minPasswordLength');
 
   /**
@@ -73,10 +80,6 @@ module.exports = (crowi: Crowi): Router => {
    */
   // eslint-disable-next-line max-len
   router.post('/', registerRules(minPasswordLength), registerValidation, 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);
-    }
 
     if (!req.form.isValid) {
       const errors = req.form.errors;
@@ -109,7 +112,7 @@ module.exports = (crowi: Crowi): Router => {
       return res.apiv3Err(new ErrorV3(err, 'failed_to_install'));
     }
 
-    await appService.setupAfterInstall();
+    await crowi.appService.setupAfterInstall();
 
     const parameters = { action: SupportedAction.ACTION_USER_REGISTRATION_SUCCESS };
     activityEvent.emit('update', res.locals.activity._id, parameters);

+ 5 - 2
apps/app/src/server/routes/index.js

@@ -6,6 +6,7 @@ import { middlewareFactory as rateLimiterFactory } from '~/features/rate-limiter
 import { accessTokenParser } from '../middlewares/access-token-parser';
 import { generateAddActivityMiddleware } from '../middlewares/add-activity';
 import apiV1FormValidator from '../middlewares/apiv1-form-validator';
+import * as applicationNotInstalled from '../middlewares/application-not-installed';
 import { excludeReadOnlyUser, excludeReadOnlyUserIfCommentNotAllowed } from '../middlewares/exclude-read-only-user';
 import injectResetOrderByTokenMiddleware from '../middlewares/inject-reset-order-by-token-middleware';
 import injectUserRegistrationOrderByTokenMiddleware from '../middlewares/inject-user-registration-order-by-token-middleware';
@@ -30,7 +31,6 @@ autoReap.options.reapOnError = true; // continue reaping the file even if an err
 /** @param {import('~/server/crowi').default} crowi Crowi instance */
 module.exports = function(crowi, app) {
   const autoReconnectToSearch = require('../middlewares/auto-reconnect-to-search')(crowi);
-  const applicationNotInstalled = require('../middlewares/application-not-installed')(crowi);
   const applicationInstalled = require('../middlewares/application-installed')(crowi);
   const loginRequiredStrictly = require('../middlewares/login-required')(crowi);
   const loginRequired = require('../middlewares/login-required')(crowi, true);
@@ -83,7 +83,10 @@ module.exports = function(crowi, app) {
   app.get('/admin'                    , applicationInstalled, loginRequiredStrictly , adminRequired , next.delegateToNext);
 
   // installer
-  app.get('/installer'                , applicationNotInstalled, next.delegateToNext);
+  app.get('/installer',
+    applicationNotInstalled.generateCheckerMiddleware(crowi),
+    next.delegateToNext,
+    applicationNotInstalled.redirectToTopOnError);
 
   // OAuth
   app.get('/passport/google'                      , loginPassport.loginWithGoogle, loginPassport.loginFailureForExternalAccount);