Yuki Takei пре 2 година
родитељ
комит
ca894eae13

+ 1 - 0
apps/app/src/interfaces/share-link.ts

@@ -10,6 +10,7 @@ export type IShareLink = {
   createdAt: Date,
   createdAt: Date,
   expiredAt?: Date,
   expiredAt?: Date,
   description: string,
   description: string,
+  isExpired: () => boolean,
 };
 };
 
 
 export type IShareLinkHasId = IShareLink & HasObjectId;
 export type IShareLinkHasId = IShareLink & HasObjectId;

+ 52 - 35
apps/app/src/server/middlewares/certify-shared-file/certify-shared-file.ts

@@ -1,54 +1,71 @@
+import type { IAttachment } from '@growi/core';
+import type { NextFunction, Request, Response } from 'express';
+
+import type { IShareLink } from '~/interfaces/share-link';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
-const url = require('url');
+import { getModelSafely } from '../../util/mongoose-utils';
+
 
 
 const logger = loggerFactory('growi:middleware:certify-shared-fire');
 const logger = loggerFactory('growi:middleware:certify-shared-fire');
 
 
-export const generateCertifySharedFileMiddleware = (crowi) => {
 
 
-  return async(req, res, next) => {
-    const { referer } = req.headers;
+interface RequestToAllowShareLink extends Request {
+  isSharedPage?: boolean,
+}
 
 
-    // Attachments cannot be viewed by clients who do not send referer.
-    // https://github.com/weseek/growi/issues/2819
-    if (referer == null) {
-      return next();
-    }
+export const certifySharedFileMiddleware = async(req: RequestToAllowShareLink, res: Response, next: NextFunction): Promise<void> => {
 
 
-    const { path } = url.parse(referer);
+  const { referer } = req.headers;
 
 
-    if (!path.startsWith('/share/')) {
-      return next();
-    }
+  // Attachments cannot be viewed by clients who do not send referer.
+  // https://github.com/weseek/growi/issues/2819
+  if (referer == null) {
+    return next();
+  }
 
 
-    const fileId = req.params.id || null;
+  const refererUrl = new URL(referer);
 
 
-    const Attachment = crowi.model('Attachment');
-    const ShareLink = crowi.model('ShareLink');
+  if (!refererUrl.pathname.startsWith('/share/')) {
+    return next();
+  }
 
 
-    const attachment = await Attachment.findOne({ _id: fileId });
+  const fileId = req.params.id || null;
 
 
-    if (attachment == null) {
-      return next();
-    }
+  const Attachment = getModelSafely<IAttachment>('Attachment');
+  const ShareLink = getModelSafely<IShareLink>('ShareLink');
+
+  if (Attachment == null) {
+    logger.warn('Could not get Attachment model. next() is called without processing anything.');
+    return next();
+  }
+  if (ShareLink == null) {
+    logger.warn('Could not get Attachment model. next() is called without processing anything.');
+    return next();
+  }
+
+  const attachment = await Attachment.findOne({ _id: fileId });
+
+  if (attachment == null) {
+    return next();
+  }
+
+  const shareLinks = await ShareLink.find({ relatedPage: attachment.page });
 
 
-    const shareLinks = await ShareLink.find({ relatedPage: attachment.page });
+  // If sharelinks don't exist, skip it
+  if (shareLinks.length === 0) {
+    return next();
+  }
 
 
-    // If sharelinks don't exist, skip it
-    if (shareLinks.length === 0) {
-      return next();
+  // Is there a valid share link
+  shareLinks.map((sharelink) => {
+    if (!sharelink.isExpired()) {
+      logger.debug('Confirmed target file belong to a share page');
+      req.isSharedPage = true;
     }
     }
+    return;
+  });
 
 
-    // Is there a valid share link
-    shareLinks.map((sharelink) => {
-      if (!sharelink.isExpired()) {
-        logger.debug('Confirmed target file belong to a share page');
-        req.isSharedPage = true;
-      }
-      return;
-    });
-
-    next();
-  };
+  next();
 
 
 };
 };

+ 2 - 3
apps/app/src/server/routes/index.js

@@ -6,7 +6,7 @@ import { middlewareFactory as rateLimiterFactory } from '~/features/rate-limiter
 import { generateAddActivityMiddleware } from '../middlewares/add-activity';
 import { generateAddActivityMiddleware } from '../middlewares/add-activity';
 import apiV1FormValidator from '../middlewares/apiv1-form-validator';
 import apiV1FormValidator from '../middlewares/apiv1-form-validator';
 import { generateCertifyBrandLogoMiddleware } from '../middlewares/certify-brand-logo';
 import { generateCertifyBrandLogoMiddleware } from '../middlewares/certify-brand-logo';
-import { generateCertifySharedFileMiddleware } from '../middlewares/certify-shared-file';
+import { certifySharedFileMiddleware } from '../middlewares/certify-shared-file';
 import { excludeReadOnlyUser } from '../middlewares/exclude-read-only-user';
 import { excludeReadOnlyUser } from '../middlewares/exclude-read-only-user';
 import injectResetOrderByTokenMiddleware from '../middlewares/inject-reset-order-by-token-middleware';
 import injectResetOrderByTokenMiddleware from '../middlewares/inject-reset-order-by-token-middleware';
 import injectUserRegistrationOrderByTokenMiddleware from '../middlewares/inject-user-registration-order-by-token-middleware';
 import injectUserRegistrationOrderByTokenMiddleware from '../middlewares/inject-user-registration-order-by-token-middleware';
@@ -34,7 +34,6 @@ module.exports = function(crowi, app) {
   const loginRequiredStrictly = require('../middlewares/login-required')(crowi);
   const loginRequiredStrictly = require('../middlewares/login-required')(crowi);
   const loginRequired = require('../middlewares/login-required')(crowi, true);
   const loginRequired = require('../middlewares/login-required')(crowi, true);
   const adminRequired = require('../middlewares/admin-required')(crowi);
   const adminRequired = require('../middlewares/admin-required')(crowi);
-  const certifySharedFile = generateCertifySharedFileMiddleware(crowi);
   const certifyBrandLogo = generateCertifyBrandLogoMiddleware(crowi);
   const certifyBrandLogo = generateCertifyBrandLogoMiddleware(crowi);
   const addActivity = generateAddActivityMiddleware(crowi);
   const addActivity = generateAddActivityMiddleware(crowi);
 
 
@@ -157,7 +156,7 @@ module.exports = function(crowi, app) {
 
 
   app.get('/me'                                   , loginRequiredStrictly, next.delegateToNext);
   app.get('/me'                                   , loginRequiredStrictly, next.delegateToNext);
   app.get('/me/*'                                 , loginRequiredStrictly, next.delegateToNext);
   app.get('/me/*'                                 , loginRequiredStrictly, next.delegateToNext);
-  app.get('/attachment/:id([0-9a-z]{24})' , certifySharedFile , loginRequired, attachment.api.get);
+  app.get('/attachment/:id([0-9a-z]{24})'         , certifySharedFileMiddleware , loginRequired, attachment.api.get);
   app.get('/attachment/profile/:id([0-9a-z]{24})' , loginRequired, attachment.api.get);
   app.get('/attachment/profile/:id([0-9a-z]{24})' , loginRequired, attachment.api.get);
   app.get('/attachment/:pageId/:fileName'       , loginRequired, attachment.api.obsoletedGetForMongoDB); // DEPRECATED: remains for backward compatibility for v3.3.x or below
   app.get('/attachment/:pageId/:fileName'       , loginRequired, attachment.api.obsoletedGetForMongoDB); // DEPRECATED: remains for backward compatibility for v3.3.x or below
   app.get('/download/:id([0-9a-z]{24})'         , loginRequired, attachment.api.download);
   app.get('/download/:id([0-9a-z]{24})'         , loginRequired, attachment.api.download);