attachment.js 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import loggerFactory from '~/utils/logger';
  2. // disable no-return-await for model functions
  3. /* eslint-disable no-return-await */
  4. // eslint-disable-next-line no-unused-vars
  5. const path = require('path');
  6. const mongoose = require('mongoose');
  7. const uniqueValidator = require('mongoose-unique-validator');
  8. const mongoosePaginate = require('mongoose-paginate-v2');
  9. const { addSeconds } = require('date-fns');
  10. // eslint-disable-next-line no-unused-vars
  11. const logger = loggerFactory('growi:models:attachment');
  12. const ObjectId = mongoose.Schema.Types.ObjectId;
  13. module.exports = function(crowi) {
  14. function generateFileHash(fileName) {
  15. const hash = require('crypto').createHash('md5');
  16. hash.update(`${fileName}_${Date.now()}`);
  17. return hash.digest('hex');
  18. }
  19. const attachmentSchema = new mongoose.Schema({
  20. page: { type: ObjectId, ref: 'Page', index: true },
  21. creator: { type: ObjectId, ref: 'User', index: true },
  22. filePath: { type: String }, // DEPRECATED: remains for backward compatibility for v3.3.x or below
  23. fileName: { type: String, required: true, unique: true },
  24. originalName: { type: String },
  25. fileFormat: { type: String, required: true },
  26. fileSize: { type: Number, default: 0 },
  27. createdAt: { type: Date, default: Date.now },
  28. temporaryUrlCached: { type: String },
  29. temporaryUrlExpiredAt: { type: Date },
  30. });
  31. attachmentSchema.plugin(uniqueValidator);
  32. attachmentSchema.plugin(mongoosePaginate);
  33. attachmentSchema.virtual('filePathProxied').get(function() {
  34. return `/attachment/${this._id}`;
  35. });
  36. attachmentSchema.virtual('downloadPathProxied').get(function() {
  37. return `/download/${this._id}`;
  38. });
  39. attachmentSchema.set('toObject', { virtuals: true });
  40. attachmentSchema.set('toJSON', { virtuals: true });
  41. attachmentSchema.statics.createWithoutSave = function(pageId, user, fileStream, originalName, fileFormat, fileSize) {
  42. const Attachment = this;
  43. const extname = path.extname(originalName);
  44. let fileName = generateFileHash(originalName);
  45. if (extname.length > 1) { // ignore if empty or '.' only
  46. fileName = `${fileName}${extname}`;
  47. }
  48. const attachment = new Attachment();
  49. attachment.page = pageId;
  50. attachment.creator = user._id;
  51. attachment.originalName = originalName;
  52. attachment.fileName = fileName;
  53. attachment.fileFormat = fileFormat;
  54. attachment.fileSize = fileSize;
  55. attachment.createdAt = Date.now();
  56. return attachment;
  57. };
  58. attachmentSchema.methods.getValidTemporaryUrl = function() {
  59. if (this.temporaryUrlExpiredAt == null) {
  60. return null;
  61. }
  62. // return null when expired url
  63. if (this.temporaryUrlExpiredAt.getTime() < new Date().getTime()) {
  64. return null;
  65. }
  66. return this.temporaryUrlCached;
  67. };
  68. attachmentSchema.methods.cashTemporaryUrlByProvideSec = function(temporaryUrl, provideSec) {
  69. if (temporaryUrl == null) {
  70. throw new Error('url is required.');
  71. }
  72. this.temporaryUrlCached = temporaryUrl;
  73. this.temporaryUrlExpiredAt = addSeconds(new Date(), provideSec);
  74. return this.save();
  75. };
  76. return mongoose.model('Attachment', attachmentSchema);
  77. };