Yuki Takei 4 anni fa
parent
commit
a89d9915cc

+ 32 - 0
packages/app/src/server/crowi/index.js

@@ -22,6 +22,7 @@ import AttachmentService from '../service/attachment';
 import { SlackIntegrationService } from '../service/slack-integration';
 import { UserNotificationService } from '../service/user-notification';
 import SearchService from '../service/search';
+import { InstallerService } from '../service/installer';
 
 import Actiity from '../models/activity';
 
@@ -140,6 +141,8 @@ Crowi.prototype.init = async function() {
     this.setUpGlobalNotification(),
     this.setUpUserNotification(),
   ]);
+
+  await this.autoInstall();
 };
 
 Crowi.prototype.isPageId = function(pageId) {
@@ -372,6 +375,35 @@ Crowi.prototype.setupCsrf = async function() {
   return Promise.resolve();
 };
 
+Crowi.prototype.autoInstall = function() {
+  const isInstalled = this.configManager.getConfig('crowi', 'app:installed');
+  const username = this.configManager.getConfig('crowi', 'autoInstall:adminUsername');
+
+  if (isInstalled || username == null) {
+    return;
+  }
+
+  logger.info('Start automatic installation');
+
+  const firstAdminUserToSave = {
+    username,
+    name: this.configManager.getConfig('crowi', 'autoInstall:adminName'),
+    email: this.configManager.getConfig('crowi', 'autoInstall:adminEmail'),
+    password: this.configManager.getConfig('crowi', 'autoInstall:adminPassword'),
+    admin: true,
+  };
+  const globalLang = this.configManager.getConfig('crowi', 'autoInstall:globalLang');
+
+  const installerService = new InstallerService(this);
+
+  try {
+    installerService.install(firstAdminUserToSave, globalLang ?? 'en_US');
+  }
+  catch (err) {
+    logger.warn('Automatic installation failed.', err);
+  }
+};
+
 Crowi.prototype.getTokens = function() {
   return this.tokens;
 };

+ 3 - 0
packages/app/src/server/routes/installer.js

@@ -43,6 +43,9 @@ module.exports = function(crowi) {
       return res.render('installer');
     }
 
+    const appService = crowi.appService;
+    appService.setupAfterInstall();
+
     // login with passport
     req.logIn(adminUser, (err) => {
       if (err) {

+ 30 - 0
packages/app/src/server/service/config-loader.ts

@@ -172,6 +172,36 @@ const ENV_VAR_NAME_TO_CONFIG_INFO = {
     type:    ValueType.BOOLEAN,
     default: false,
   },
+  AUTO_INSTALL_ADMIN_USERNAME: {
+    ns:      'crowi',
+    key:     'autoInstall:adminUsername',
+    type:    ValueType.STRING,
+    default: null,
+  },
+  AUTO_INSTALL_ADMIN_NAME: {
+    ns:      'crowi',
+    key:     'autoInstall:adminName',
+    type:    ValueType.STRING,
+    default: null,
+  },
+  AUTO_INSTALL_ADMIN_EMAIL: {
+    ns:      'crowi',
+    key:     'autoInstall:adminEmail',
+    type:    ValueType.STRING,
+    default: null,
+  },
+  AUTO_INSTALL_ADMIN_PASSWORD: {
+    ns:      'crowi',
+    key:     'autoInstall:adminPassword',
+    type:    ValueType.STRING,
+    default: null,
+  },
+  AUTO_INSTALL_GLOBAL_LANG: {
+    ns:      'crowi',
+    key:     'autoInstall:globalLang',
+    type:    ValueType.STRING,
+    default: null,
+  },
   S2SMSG_PUBSUB_SERVER_TYPE: {
     ns:      'crowi',
     key:     's2sMessagingPubsub:serverType',

+ 7 - 10
packages/app/src/server/service/installer.ts

@@ -5,11 +5,11 @@ import ExtensibleCustomError from 'extensible-custom-error';
 
 import { IPage } from '~/interfaces/page';
 import { IUser } from '~/interfaces/user';
+import { Lang } from '~/interfaces/lang';
 import loggerFactory from '~/utils/logger';
 
 import { generateConfigsForInstalling } from '../models/config';
 
-import AppService from './app';
 import SearchService from './search';
 import ConfigManager from './config-manager';
 
@@ -53,7 +53,7 @@ export class InstallerService {
   }
 
   // eslint-disable-next-line @typescript-eslint/no-explicit-any
-  private async createInitialPages(owner, lang): Promise<any> {
+  private async createInitialPages(owner, lang: Lang): Promise<any> {
     const { localeDir } = this.crowi;
 
     const promises: Promise<IPage|undefined>[] = [];
@@ -80,7 +80,7 @@ export class InstallerService {
   /**
    * Execute only once for installing application
    */
-  private async initDB(globalLang: string): Promise<void> {
+  private async initDB(globalLang: Lang): Promise<void> {
     const configManager: ConfigManager = this.crowi.configManager;
 
     const initialConfig = generateConfigsForInstalling();
@@ -88,8 +88,8 @@ export class InstallerService {
     return configManager.updateConfigsInTheSameNamespace('crowi', initialConfig, true);
   }
 
-  async install(firstAdminUserToSave: IUser, language: string): Promise<IUser> {
-    await this.initDB(language);
+  async install(firstAdminUserToSave: IUser, globalLang: Lang): Promise<IUser> {
+    await this.initDB(globalLang);
 
     // TODO typescriptize models/user.js and remove eslint-disable-next-line
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -102,7 +102,7 @@ export class InstallerService {
       const {
         name, username, email, password,
       } = firstAdminUserToSave;
-      adminUser = await User.createUser(name, username, email, password, language);
+      adminUser = await User.createUser(name, username, email, password, globalLang);
       await adminUser.asyncMakeAdmin();
     }
     catch (err) {
@@ -110,10 +110,7 @@ export class InstallerService {
     }
 
     // create initial pages
-    await this.createInitialPages(adminUser, language);
-
-    const appService: AppService = this.crowi.appService;
-    appService.setupAfterInstall();
+    await this.createInitialPages(adminUser, globalLang);
 
     return adminUser;
   }