Browse Source

Improved to forbid insert for v5 pages collection import

Taichi Masuyama 4 years ago
parent
commit
d93c2ed3b6

+ 3 - 0
packages/app/resource/locales/en_US/admin/admin.json

@@ -189,6 +189,9 @@
     "beta_warning": "This function is Beta.",
     "import_from": "Import from {{from}}",
     "import_growi_archive": "Import GROWI archive",
+    "error": {
+      "only_upsert_available": "Only 'Upsert' option is available for pages collection."
+    },
     "growi_settings": {
       "description_of_import_mode": {
         "about": "When you import data with the same name as an existing one, choose from the following three modes below.",

+ 3 - 0
packages/app/resource/locales/ja_JP/admin/admin.json

@@ -207,6 +207,9 @@
     "beta_warning": "この機能はベータ版です",
     "import_from": "{{from}} からインポート",
     "import_growi_archive": "GROWI アーカイブをインポート",
+    "error": {
+      "only_upsert_available": "pages コレクションには 'Upsert' オプションのみ対応しています"
+    },
     "growi_settings": {
       "description_of_import_mode": {
         "about": "既存のデータと同名であるデータをインポートする際の挙動は以下の3つのモードから選べます。",

+ 3 - 0
packages/app/resource/locales/zh_CN/admin/admin.json

@@ -199,6 +199,9 @@
     "beta_warning": "这个函数是Beta。",
     "import_from": "Import from {{from}}",
     "import_growi_archive": "Import GROWI archive",
+    "error": {
+      "only_upsert_available": "Only 'Upsert' option is available for pages collection."
+    },
     "growi_settings": {
       "description_of_import_mode": {
         "about": "When you import data with the same name as an existing one, choose from the following three modes below.",

+ 6 - 1
packages/app/src/components/Admin/ImportData/GrowiArchive/ImportForm.jsx

@@ -287,7 +287,9 @@ class ImportForm extends React.Component {
   }
 
   async import() {
-    const { appContainer, fileName, onPostImport } = this.props;
+    const {
+      appContainer, fileName, onPostImport, t,
+    } = this.props;
     const { selectedCollections, optionsMap } = this.state;
 
     // init progress data
@@ -312,6 +314,9 @@ class ImportForm extends React.Component {
       toastSuccess(undefined, 'Import process has requested.');
     }
     catch (err) {
+      if (err.code === 'only_upsert_available') {
+        toastError(t('admin:importer_management.error.only_upsert_available'));
+      }
       toastError(err, 'Import request failed.');
     }
   }

+ 12 - 1
packages/app/src/server/routes/apiv3/import.js

@@ -206,8 +206,19 @@ module.exports = (crowi) => {
    */
   router.post('/', accessTokenParser, loginRequired, adminRequired, csrf, async(req, res) => {
     // TODO: add express validator
-
     const { fileName, collections, optionsMap } = req.body;
+
+    // pages collection can only be imported by upsert if isV5Compatible is true
+    const isV5Compatible = crowi.configManager.getConfig('crowi', 'app:isV5Compatible');
+    const isImportPagesCollection = collections.includes('pages');
+    if (isV5Compatible && isImportPagesCollection) {
+      const option = new GrowiArchiveImportOption(null, optionsMap.pages);
+      if (option.mode !== 'upsert') {
+        return res.apiv3Err(new ErrorV3('Upsert is only available for importing pages collection.', 'only_upsert_available'));
+      }
+    }
+
+
     const zipFile = importService.getFile(fileName);
 
     // return response first

+ 0 - 8
packages/app/src/server/routes/apiv3/overwrite-params/pages.js

@@ -32,14 +32,6 @@ class PageOverwriteParamsFactory {
       params.lastUpdateUser = userId;
     }
 
-    params.path = (value, { document, schema, propertyName }) => {
-      if (isTopPage(value)) {
-        return `/imported_top_page_${format(new Date(), 'yyyyMMddHHmmss a')}`;
-      }
-
-      return value;
-    };
-
     params.grant = (value, { document, schema, propertyName }) => {
       if (option.makePublicForGrant2 && value === 2) {
         return GRANT_PUBLIC;

+ 1 - 1
packages/app/src/server/routes/apiv3/pages.js

@@ -714,7 +714,7 @@ module.exports = (crowi) => {
     try {
       if (!isV5Compatible) {
         // this method throws and emit socketIo event when error occurs
-        crowi.pageService.v5InitialMigration(); // not await
+        crowi.pageService.normalizeAllPublicPages(); // not await
       }
     }
     catch (err) {

+ 6 - 4
packages/app/src/server/service/import.js

@@ -184,10 +184,10 @@ class ImportService {
 
     const isV5Compatible = this.crowi.configManager.getConfig('crowi', 'app:isV5Compatible');
     const isImportPagesCollection = collections.includes('pages');
-    const shouldMigratePages = isV5Compatible && isImportPagesCollection;
+    const shouldNormalizePages = isV5Compatible && isImportPagesCollection;
 
     // set isV5Compatible to false
-    if (shouldMigratePages) await this.crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'app:isV5Compatible': false });
+    if (shouldNormalizePages) await this.crowi.configManager.updateConfigsInTheSameNamespace('crowi', { 'app:isV5Compatible': false });
 
     // process serially so as not to waste memory
     const promises = collections.map((collectionName) => {
@@ -206,8 +206,8 @@ class ImportService {
       }
     }
 
-    // run v5InitialMigration
-    if (shouldMigratePages) await this.crowi.pageService.v5InitialMigration();
+    // run normalizeAllPublicPages
+    if (shouldNormalizePages) await this.crowi.pageService.normalizeAllPublicPages();
 
     this.currentProgressingStatus = null;
     this.emitTerminateEvent();
@@ -343,6 +343,8 @@ class ImportService {
 
     // upsert
     switch (collectionName) {
+      case 'pages':
+        return bulk.find({ path: document.path }).upsert().replaceOne(document);
       default:
         return bulk.find({ _id: document._id }).upsert().replaceOne(document);
     }

+ 1 - 1
packages/app/src/server/service/page.ts

@@ -1878,7 +1878,7 @@ class PageService {
   }
 
   // TODO: use socket to send status to the client
-  async v5InitialMigration() {
+  async normalizeAllPublicPages() {
     // const socket = this.crowi.socketIoService.getAdminSocket();
 
     let isUnique;

+ 2 - 2
packages/app/test/integration/service/v5-migration.test.js

@@ -75,7 +75,7 @@ describe('V5 page migration', () => {
 
   });
 
-  describe('v5InitialMigration()', () => {
+  describe('normalizeAllPublicPages()', () => {
     jest.setTimeout(60000);
     let createPagePaths;
     let allPossiblePagePaths;
@@ -132,7 +132,7 @@ describe('V5 page migration', () => {
       ]);
 
       // migrate
-      await crowi.pageService.v5InitialMigration(Page.GRANT_PUBLIC);
+      await crowi.pageService.normalizeAllPublicPages(Page.GRANT_PUBLIC);
       jest.setTimeout(30000);
     });