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

Merge pull request #727 from weseek/imprv/refactor-acl-lsx

Imprv/refactor acl lsx
Yuki Takei 7 лет назад
Родитель
Сommit
a858ce8f49
3 измененных файлов с 85 добавлено и 64 удалено
  1. 2 0
      config/webpack.common.js
  2. 16 5
      src/client/js/components/PageList/PagePath.js
  3. 67 59
      src/server/models/page.js

+ 2 - 0
config/webpack.common.js

@@ -63,6 +63,7 @@ module.exports = (options) => {
       alias: {
         '@root': helpers.root('/'),
         '@commons': helpers.root('src/lib'),
+        '@client': helpers.root('src/client'),
         '@tmp': helpers.root('tmp'),
         '@alias/logger': helpers.root('src/lib/service/logger'),
         '@alias/locales': helpers.root('resource/locales'),
@@ -77,6 +78,7 @@ module.exports = (options) => {
           exclude: {
             test:    helpers.root('node_modules'),
             exclude: [  // include as a result
+              { test: helpers.root('node_modules', 'growi-plugin-') },
               helpers.root('node_modules/codemirror/src'),
               helpers.root('node_modules/string-width'),
               helpers.root('node_modules/is-fullwidth-code-point'), // depends from string-width

+ 16 - 5
src/client/js/components/PageList/PagePath.js

@@ -29,24 +29,35 @@ export default class PagePath extends React.Component {
 
   render() {
     const page = this.props.page;
+    const isShortPathOnly = this.props.isShortPathOnly;
     const pagePath = decodeURIComponent(page.path.replace(this.props.excludePathString.replace(/^\//, ''), ''));
     const shortPath = this.getShortPath(pagePath);
+
     const shortPathEscaped = escapeStringRegexp(shortPath);
     const pathPrefix = pagePath.replace(new RegExp(shortPathEscaped + '(/)?$'), '');
 
-    return (
-      <span className="page-path">
-        {pathPrefix}<strong>{shortPath}</strong>
-      </span>
-    );
+    let classNames = ['page-path'];
+    classNames = classNames.concat(this.props.additionalClassNames);
+
+    if (isShortPathOnly) {
+      return <span className={classNames.join(' ')}>{shortPath}</span>;
+    }
+    else {
+      return <span className={classNames.join(' ')}>{pathPrefix}<strong>{shortPath}</strong></span>;
+    }
+
   }
 }
 
 PagePath.propTypes = {
   page: PropTypes.object.isRequired,
+  isShortPathOnly: PropTypes.bool,
+  excludePathString: PropTypes.string,
+  additionalClassNames: PropTypes.array,
 };
 
 PagePath.defaultProps = {
   page: {},
+  additionalClassNames: [],
   excludePathString: '',
 };

+ 67 - 59
src/server/models/page.js

@@ -62,6 +62,16 @@ const pageSchema = new mongoose.Schema({
 pageSchema.plugin(uniqueValidator);
 
 
+
+const addSlashOfEnd = (path) => {
+  let returnPath = path;
+  if (!path.match(/\/$/)) {
+    returnPath += '/';
+  }
+  return returnPath;
+};
+
+
 class PageQueryBuilder {
   constructor(query) {
     this.query = query;
@@ -89,7 +99,7 @@ class PageQueryBuilder {
    */
   addConditionToListWithDescendants(path, option) {
     // ignore other pages than descendants
-    path = this.addSlashOfEnd(path);
+    path = addSlashOfEnd(path);
 
     // add option to escape the regex strings
     const combinedOption = Object.assign({isRegExpEscapedFromPath: true}, option);
@@ -170,6 +180,13 @@ class PageQueryBuilder {
 
     return this;
   }
+
+  addConditionToPagenate(offset, limit, sortOpt) {
+    this.query = this.query
+      .sort(sortOpt).skip(offset).limit(limit);
+
+    return this;
+  }
 }
 
 module.exports = function(crowi) {
@@ -589,32 +606,52 @@ module.exports = function(crowi) {
   };
 
   /**
-   * find the page that is match with `path` and its descendants
+   * find pages that is match with `path` and its descendants
    */
-  pageSchema.statics.findListWithDescendants = async function(path, userData, option) {
-    // ignore other pages than descendants
-    path = this.addSlashOfEnd(path);
-    // add option to escape the regex strings
-    const combinedOption = Object.assign({isRegExpEscapedFromPath: true}, option);
+  pageSchema.statics.findListWithDescendants = async function(path, user, option) {
+    const builder = new PageQueryBuilder(this.find());
+    builder.addConditionToListWithDescendants(path, option);
 
-    return await this.findListByStartWith(path, userData, combinedOption);
+    return await findListFromBuilderAndViewer(builder, user, option);
   };
 
   /**
    * find pages that start with `path`
    */
   pageSchema.statics.findListByStartWith = async function(path, user, option) {
-    validateCrowi();
+    const builder = new PageQueryBuilder(this.find());
+    builder.addConditionToListByStartWith(path, option);
 
-    const User = crowi.model('User');
+    return await findListFromBuilderAndViewer(builder, user, option);
+  };
+
+  /**
+   * find pages that is created by targetUser
+   *
+   * @param {User} targetUser
+   * @param {User} currentUser
+   * @param {any} option
+   */
+  pageSchema.statics.findListByCreator = async function(targetUser, currentUser, option) {
+    const opt = Object.assign({sort: 'createdAt', desc: -1}, option);
+    const builder = new PageQueryBuilder(this.find({ creator: targetUser._id }));
+
+    return await findListFromBuilderAndViewer(builder, currentUser, opt);
+  };
+
+  /**
+   * find pages by PageQueryBuilder
+   * @param {PageQueryBuilder} builder
+   * @param {User} user
+   * @param {any} option
+   */
+  async function findListFromBuilderAndViewer(builder, user, option) {
+    validateCrowi();
 
     const opt = Object.assign({sort: 'updatedAt', desc: -1}, option);
     const sortOpt = {};
     sortOpt[opt.sort] = opt.desc;
 
-    const builder = new PageQueryBuilder(this.find());
-    builder.addConditionToListByStartWith(path, option);
-
     // exclude trashed pages
     if (!opt.includeTrashed) {
       builder.addConditionToExcludeTrashed();
@@ -632,9 +669,11 @@ module.exports = function(crowi) {
     }
     builder.addConditionToFilteringByViewer(user, userGroups);
 
+    builder.addConditionToPagenate(opt.offset, opt.limit, sortOpt);
+
+    const User = crowi.model('User');
     const totalCount = await builder.query.exec('count');
     const q = builder.query
-      .sort(sortOpt).skip(opt.offset).limit(opt.limit)
       .populate({
         path: 'lastUpdateUser',
         model: 'User',
@@ -644,50 +683,21 @@ module.exports = function(crowi) {
 
     const result = { pages, totalCount, offset: opt.offset, limit: opt.limit };
     return result;
-  };
+  }
+
 
   /**
-   * find pages that is created by targetUser
-   *
-   * @param {User} targetUser
-   * @param {User} currentUser
-   * @param {any} option
+   * Throw error for growi-lsx-plugin (v1.x)
    */
-  pageSchema.statics.findListByCreator = async function(targetUser, currentUser, option) {
-    validateCrowi();
-
-    const User = crowi.model('User');
-
-    const opt = Object.assign({sort: 'createdAt', desc: -1, offset: 0}, option);
-    const sortOpt = {};
-    sortOpt[opt.sort] = opt.desc;
-
-    const baseQuery = this.find({ creator: targetUser._id });
-    const builder = new PageQueryBuilder(baseQuery)
-      .addConditionToExcludeTrashed()
-      .addConditionToExcludeRedirect();
-
-    // add grant conditions
-    let userGroups = null;
-    if (currentUser != null) {
-      const UserGroupRelation = crowi.model('UserGroupRelation');
-      userGroups = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(currentUser);
-    }
-    builder.addConditionToFilteringByViewer(currentUser, userGroups);
-
-    const totalCount = await builder.query.exec('count');
-    const q = builder.query
-      .sort(sortOpt).skip(opt.offset).limit(opt.limit)
-      .populate({
-        path: 'lastUpdateUser',
-        model: 'User',
-        select: User.USER_PUBLIC_FIELDS
-      });
-    const pages = await q.exec('find');
-
-    const result = { pages, totalCount, offset: opt.offset, limit: opt.limit };
-    return result;
+  pageSchema.statics.generateQueryToListByStartWith = function(path, user, option) {
+    const dummyQuery = this.find();
+    dummyQuery.exec = async() => {
+      throw new Error('Plugin version mismatch. Upgrade growi-lsx-plugin to v2.0.0 or above.');
+    };
+    return dummyQuery;
   };
+  pageSchema.statics.generateQueryToListWithDescendants = pageSchema.statics.generateQueryToListByStartWith;
+
 
   /**
    * find all templates applicable to the new page
@@ -1221,11 +1231,7 @@ module.exports = function(crowi) {
    * return path that added slash to the end for specified path
    */
   pageSchema.statics.addSlashOfEnd = function(path) {
-    let returnPath = path;
-    if (!path.match(/\/$/)) {
-      returnPath += '/';
-    }
-    return returnPath;
+    return addSlashOfEnd(path);
   };
 
   pageSchema.statics.GRANT_PUBLIC = GRANT_PUBLIC;
@@ -1235,5 +1241,7 @@ module.exports = function(crowi) {
   pageSchema.statics.GRANT_USER_GROUP = GRANT_USER_GROUP;
   pageSchema.statics.PAGE_GRANT_ERROR = PAGE_GRANT_ERROR;
 
+  pageSchema.statics.PageQueryBuilder = PageQueryBuilder;
+
   return mongoose.model('Page', pageSchema);
 };