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

Merge pull request #4589 from weseek/feat/switch-pathlink-and-permalink

feat: Switch pathlink and permalink
Haku Mizuki 4 лет назад
Родитель
Сommit
0362d49255

+ 0 - 25
packages/app/src/server/models/obsolete-page.js

@@ -556,31 +556,6 @@ export const getPageSchema = (crowi) => {
     return this.findOne({ path });
   };
 
-  /**
-   * @param {string} path Page path
-   * @param {User} user User instance
-   * @param {UserGroup[]} userGroups List of UserGroup instances
-   */
-  pageSchema.statics.findByPathAndViewer = async function(path, user, userGroups) {
-    if (path == null) {
-      throw new Error('path is required.');
-    }
-
-    const baseQuery = this.findOne({ path });
-
-    let relatedUserGroups = userGroups;
-    if (user != null && relatedUserGroups == null) {
-      validateCrowi();
-      const UserGroupRelation = crowi.model('UserGroupRelation');
-      relatedUserGroups = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user);
-    }
-
-    const queryBuilder = new PageQueryBuilder(baseQuery);
-    queryBuilder.addConditionToFilteringByViewer(user, relatedUserGroups, true);
-
-    return await queryBuilder.query.exec();
-  };
-
   /**
    * @param {string} path Page path
    * @param {User} user User instance

+ 24 - 2
packages/app/src/server/models/page.ts

@@ -10,7 +10,7 @@ import nodePath from 'path';
 import { getOrCreateModel, pagePathUtils } from '@growi/core';
 import loggerFactory from '../../utils/logger';
 import Crowi from '../crowi';
-import { IPage } from '~/interfaces/page';
+import { IPage } from '../../interfaces/page';
 import { getPageSchema, PageQueryBuilder } from './obsolete-page';
 
 const { isTopPage } = pagePathUtils;
@@ -157,12 +157,34 @@ schema.statics.getParentIdAndFillAncestors = async function(path: string): Promi
   return parentId;
 };
 
+schema.statics.findByPathAndViewer = async function(path: string | null, user, userGroups, useFindOne = true): Promise<IPage[]> {
+  if (path == null) {
+    throw new Error('path is required.');
+  }
+
+  const baseQuery = useFindOne ? this.findOne({ path }) : this.find({ path });
+
+  let relatedUserGroups = userGroups;
+  if (user != null && relatedUserGroups == null) {
+    const UserGroupRelation: any = mongoose.model('UserGroupRelation');
+    relatedUserGroups = await UserGroupRelation.findAllUserGroupIdsRelatedToUser(user);
+  }
+
+  const queryBuilder = new PageQueryBuilder(baseQuery);
+  queryBuilder.addConditionToFilteringByViewer(user, relatedUserGroups, true);
+
+  return queryBuilder.query.exec();
+};
+
+
+/*
+ * Merge obsolete page model methods and define new methods which depend on crowi instance
+ */
 export default (crowi: Crowi): any => {
   // add old page schema methods
   const pageSchema = getPageSchema(crowi);
   schema.methods = { ...pageSchema.methods, ...schema.methods };
   schema.statics = { ...pageSchema.statics, ...schema.statics };
 
-
   return getOrCreateModel<PageDocument, PageModel>('Page', schema);
 };

+ 3 - 3
packages/app/src/server/routes/index.js

@@ -139,7 +139,7 @@ module.exports = function(crowi, app) {
   // my drafts
   app.get('/me/drafts'                , loginRequiredStrictly, me.drafts.list);
 
-  app.get('/:id([0-9a-z]{24})'       , loginRequired , page.redirector);
+  app.get('/:id([0-9a-z]{24})'       , loginRequired , page.showPage);
   app.get('/_r/:id([0-9a-z]{24})'    , loginRequired , page.redirector); // alias
   app.get('/attachment/:id([0-9a-z]{24})' , certifySharedFile , loginRequired, attachment.api.get);
   app.get('/attachment/profile/:id([0-9a-z]{24})' , loginRequired, attachment.api.get);
@@ -196,7 +196,7 @@ module.exports = function(crowi, app) {
 
   app.get('/share/:linkId', page.showSharedPage);
 
-  app.get('/*/$'                   , loginRequired , page.showPageWithEndOfSlash, page.notFound);
-  app.get('/*'                     , loginRequired , autoReconnectToSearch, page.showPage, page.notFound);
+  app.get('/*/$'                   , loginRequired , page.redirectorWithEndOfSlash, page.notFound);
+  app.get('/*'                     , loginRequired , autoReconnectToSearch, page.redirector, page.notFound);
 
 };

+ 39 - 13
packages/app/src/server/routes/page.js

@@ -1,4 +1,5 @@
 import { pagePathUtils } from '@growi/core';
+import urljoin from 'url-join';
 import loggerFactory from '~/utils/logger';
 
 import UpdatePost from '../models/update-post';
@@ -279,10 +280,10 @@ module.exports = function(crowi, app) {
   }
 
   async function showPageForPresentation(req, res, next) {
-    const path = getPathFromRequest(req);
+    const id = req.params.id;
     const { revisionId } = req.query;
 
-    let page = await Page.findByPathAndViewer(path, req.user);
+    let page = await Page.findByIdAndViewer(id, req.user);
 
     if (page == null) {
       next();
@@ -333,22 +334,25 @@ module.exports = function(crowi, app) {
   }
 
   async function showPageForGrowiBehavior(req, res, next) {
-    const path = getPathFromRequest(req);
+    const id = req.params.id;
     const revisionId = req.query.revision;
 
-    let page = await Page.findByPathAndViewer(path, req.user);
+    let page = await Page.findByIdAndViewer(id, req.user);
 
     if (page == null) {
       // check the page is forbidden or just does not exist.
-      req.isForbidden = await Page.count({ path }) > 0;
+      req.isForbidden = await Page.count({ _id: id }) > 0;
       return next();
     }
+
+    const { path } = page; // this must exist
+
     if (page.redirectTo) {
       debug(`Redirect to '${page.redirectTo}'`);
       return res.redirect(`${encodeURI(page.redirectTo)}?redirectFrom=${encodeURIComponent(path)}`);
     }
 
-    logger.debug('Page is found when processing pageShowForGrowiBehavior', page._id, page.path);
+    logger.debug('Page is found when processing pageShowForGrowiBehavior', page._id, path);
 
     const limit = 50;
     const offset = parseInt(req.query.offset) || 0;
@@ -373,7 +377,7 @@ module.exports = function(crowi, app) {
     const sharelinksNumber = await ShareLink.countDocuments({ relatedPage: page._id });
     renderVars.sharelinksNumber = sharelinksNumber;
 
-    if (isUserPage(page.path)) {
+    if (isUserPage(path)) {
       // change template
       view = 'layout-growi/user_page';
       await addRenderVarsForUserPage(renderVars, page);
@@ -558,16 +562,38 @@ module.exports = function(crowi, app) {
   /**
    * redirector
    */
-  actions.redirector = async function(req, res) {
-    const id = req.params.id;
+  async function redirector(req, res, next, path) {
+    const pages = await Page.findByPathAndViewer(path, req.user, null, false);
 
-    const page = await Page.findByIdAndViewer(id, req.user);
+    if (pages.length >= 2) {
+      // TODO: return res.render('layout-growi/select_same_path_page', renderVars);
+      // TODO: put redirectFrom into renderVars
+      return res.send('Two or more pages found.');
+    }
 
-    if (page != null) {
-      return res.redirect(encodeURI(page.path));
+    const queryParams = new URLSearchParams();
+    Object.entries(req.query).forEach(([key, value], i) => {
+      queryParams.append(key, value);
+    });
+
+    if (pages.length === 1) {
+      return res.safeRedirect(`/${pages[0]._id}?${queryParams.toString()}`);
     }
 
-    return res.redirect('/');
+    return next(); // to page.notFound
+  }
+
+  actions.redirector = async function(req, res, next) {
+    const path = getPathFromRequest(req);
+
+    return redirector(req, res, next, path);
+  };
+
+  actions.redirectorWithEndOfSlash = async function(req, res, next) {
+    const _path = getPathFromRequest(req);
+    const path = pathUtils.removeTrailingSlash(_path);
+
+    return redirector(req, res, next, path);
   };