2
0
Эх сурвалжийг харах

WIP: GC-1224 refactor page

* refactor PageQueryBuilder
Yuki Takei 7 жил өмнө
parent
commit
c70dfd8d2f
1 өөрчлөгдсөн 118 нэмэгдсэн , 103 устгасан
  1. 118 103
      src/server/models/page.js

+ 118 - 103
src/server/models/page.js

@@ -67,15 +67,102 @@ class PageQueryBuilder {
     this.query = query;
   }
 
+  /**
+   * generate the query to find the page that is match with `path` and its descendants
+   */
+  addConditionToListWithDescendants(path, option) {
+    // ignore other pages than descendants
+    path = this.addSlashOfEnd(path);
+
+    // add option to escape the regex strings
+    const combinedOption = Object.assign({isRegExpEscapedFromPath: true}, option);
+
+    this.addConditionToListByStartWith(path, combinedOption);
+
+    return this;
+  }
+
+  /**
+   * generate the query to find pages that start with `path`
+   *
+   * (GROWI) If 'isRegExpEscapedFromPath' is true, `path` should have `/` at the end
+   *   -> returns '{path}/*' and '{path}' self.
+   * (Crowi) If 'isRegExpEscapedFromPath' is false and `path` has `/` at the end
+   *   -> returns '{path}*'
+   * (Crowi) If 'isRegExpEscapedFromPath' is false and `path` doesn't have `/` at the end
+   *   -> returns '{path}*'
+   *
+   * *option*
+   *   - includeDeletedPage -- if true, search deleted pages (default: false)
+   *   - isRegExpEscapedFromPath -- if true, the regex strings included in `path` is escaped (default: false)
+   */
+  addConditionToListByStartWith(path, option) {
+    const pathCondition = [];
+    const includeDeletedPage = option.includeDeletedPage || false;
+    const isRegExpEscapedFromPath = option.isRegExpEscapedFromPath || false;
+
+    /*
+     * 1. add condition for finding the page completely match with `path` w/o last slash
+     */
+    let pathSlashOmitted = path;
+    if (path.match(/\/$/)) {
+      pathSlashOmitted = path.substr(0, path.length -1);
+      pathCondition.push({path: pathSlashOmitted});
+    }
+
+    /*
+     * 2. add decendants
+     */
+    const pattern = (isRegExpEscapedFromPath)
+      ? escapeStringRegexp(path)  // escape
+      : pathSlashOmitted;
+
+    const queryReg = new RegExp('^' + pattern);
+    pathCondition.push({path: queryReg});
+
+    this.query = this.query
+      .and({ redirectTo: null })
+      .and({
+        $or: pathCondition
+      });
+
+    if (!includeDeletedPage) {
+      this.query = this.query
+        .and({
+          $or: [
+            {status: null},
+            {status: STATUS_PUBLISHED},
+          ]
+        });
+    }
+
+    return this;
+  }
+
   addConditionToFilteringByViewer(user, userGroups) {
-    this.query = this.query.or([
+    const grantConditions = [
       {grant: null},
       {grant: GRANT_PUBLIC},
-      {grant: GRANT_RESTRICTED, grantedUsers: user._id},
-      {grant: GRANT_SPECIFIED, grantedUsers: user._id},
-      {grant: GRANT_OWNER, grantedUsers: user._id},
-      {grant: GRANT_USER_GROUP, grantedGroup: { $in: userGroups }},
-    ]);
+    ];
+
+    if (user != null) {
+      grantConditions.push(
+        {grant: GRANT_RESTRICTED, grantedUsers: user._id},
+        {grant: GRANT_SPECIFIED, grantedUsers: user._id},
+        {grant: GRANT_OWNER, grantedUsers: user._id},
+      );
+    }
+
+    if (userGroups != null) {
+      grantConditions.push(
+        {grant: GRANT_USER_GROUP, grantedGroup: { $in: userGroups }},
+      );
+    }
+
+    this.query = this.query
+      .and({
+        $or: grantConditions
+      });
 
     return this;
   }
@@ -686,10 +773,9 @@ module.exports = function(crowi) {
    *
    * see the comment of `generateQueryToListByStartWith` function
    */
-  pageSchema.statics.findListByStartWith = function(path, userData, option) {
+  pageSchema.statics.findListByStartWith = async function(path, user, option) {
     validateCrowi();
 
-    const Page = this;
     const User = crowi.model('User');
 
     if (!option) {
@@ -706,107 +792,36 @@ module.exports = function(crowi) {
 
     const isPopulateRevisionBody = option.isPopulateRevisionBody || false;
 
-    return new Promise(function(resolve, reject) {
-      let q = Page.generateQueryToListByStartWith(path, userData, option)
-        .sort(sortOpt)
-        .skip(opt.offset)
-        .limit(opt.limit);
-
-      // retrieve revision data
-      if (isPopulateRevisionBody) {
-        q = q.populate('revision');
-      }
-      else {
-        q = q.populate('revision', '-body');  // exclude body
-      }
-
-      q.exec()
-        .then(function(pages) {
-          Page.populate(pages, {path: 'lastUpdateUser', model: 'User', select: User.USER_PUBLIC_FIELDS})
-          .then(resolve)
-          .catch(reject);
-        });
-    });
-  };
+    const builder = new PageQueryBuilder(this.find());
+    builder.addConditionToListByStartWith(path, option);
 
-  /**
-   * generate the query to find the page that is match with `path` and its descendants
-   */
-  pageSchema.statics.generateQueryToListWithDescendants = function(path, userData, option) {
-    var Page = this;
-
-    // ignore other pages than descendants
-    path = Page.addSlashOfEnd(path);
-
-    // add option to escape the regex strings
-    const combinedOption = Object.assign({isRegExpEscapedFromPath: true}, option);
-
-    return Page.generateQueryToListByStartWith(path, userData, combinedOption);
-  };
-
-  /**
-   * generate the query to find pages that start with `path`
-   *
-   * (GROWI) If 'isRegExpEscapedFromPath' is true, `path` should have `/` at the end
-   *   -> returns '{path}/*' and '{path}' self.
-   * (Crowi) If 'isRegExpEscapedFromPath' is false and `path` has `/` at the end
-   *   -> returns '{path}*'
-   * (Crowi) If 'isRegExpEscapedFromPath' is false and `path` doesn't have `/` at the end
-   *   -> returns '{path}*'
-   *
-   * *option*
-   *   - includeDeletedPage -- if true, search deleted pages (default: false)
-   *   - isRegExpEscapedFromPath -- if true, the regex strings included in `path` is escaped (default: false)
-   */
-  pageSchema.statics.generateQueryToListByStartWith = function(path, userData, option) {
-    var Page = this;
-    var pathCondition = [];
-    var includeDeletedPage = option.includeDeletedPage || false;
-    var isRegExpEscapedFromPath = option.isRegExpEscapedFromPath || false;
-
-    /*
-     * 1. add condition for finding the page completely match with `path` w/o last slash
-     */
-    let pathSlashOmitted = path;
-    if (path.match(/\/$/)) {
-      pathSlashOmitted = path.substr(0, path.length -1);
-      pathCondition.push({path: pathSlashOmitted});
+    // add grant conditions
+    let userGroups = null;
+    if (user != null) {
+      const UserGroupRelation = crowi.model('UserGroupRelation');
+      userGroups = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user);
     }
-
-    /*
-     * 2. add decendants
-     */
-    var pattern = (isRegExpEscapedFromPath)
-      ? escapeStringRegexp(path)  // escape
-      : pathSlashOmitted;
-
-    var queryReg = new RegExp('^' + pattern);
-    pathCondition.push({path: queryReg});
-
-    var q = Page.find({
-      redirectTo: null,
-      $or: [
-        {grant: null},
-        {grant: GRANT_PUBLIC},
-        {grant: GRANT_RESTRICTED, grantedUsers: userData._id},
-        {grant: GRANT_SPECIFIED, grantedUsers: userData._id},
-        {grant: GRANT_OWNER, grantedUsers: userData._id},
-        {grant: GRANT_USER_GROUP},
-      ], })
-      .and({
-        $or: pathCondition
+    builder.addConditionToFilteringByViewer(user, userGroups);
+
+    let q = builder.query
+      .sort(sortOpt)
+      .skip(opt.offset)
+      .limit(opt.limit)
+      .populate({
+        path: 'lastUpdateUser',
+        model: 'User',
+        select: User.USER_PUBLIC_FIELDS
       });
 
-    if (!includeDeletedPage) {
-      q.and({
-        $or: [
-          {status: null},
-          {status: STATUS_PUBLISHED},
-        ],
-      });
+    // retrieve revision data
+    if (isPopulateRevisionBody) {
+      q = q.populate('revision');
+    }
+    else {
+      q = q.populate('revision', '-body');  // exclude body
     }
 
-    return q;
+    return await q.exec();
   };
 
   async function pushRevision(pageData, newRevision, user, grant, grantUserGroupId) {