| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- import path from 'path';
- import type { IAttachment } from '@growi/core';
- import { addSeconds } from 'date-fns/addSeconds';
- import {
- Schema, type Model, type Document, Types,
- } from 'mongoose';
- import mongoosePaginate from 'mongoose-paginate-v2';
- import uniqueValidator from 'mongoose-unique-validator';
- import loggerFactory from '~/utils/logger';
- import { AttachmentType } from '../interfaces/attachment';
- import { getOrCreateModel } from '../util/mongoose-utils';
- // eslint-disable-next-line no-unused-vars
- const logger = loggerFactory('growi:models:attachment');
- function generateFileHash(fileName) {
- const hash = require('crypto').createHash('md5');
- hash.update(`${fileName}_${Date.now()}`);
- return hash.digest('hex');
- }
- type GetValidTemporaryUrl = () => string | null | undefined;
- type CashTemporaryUrlByProvideSec = (temporaryUrl: string, lifetimeSec: number) => Promise<IAttachmentDocument>;
- export interface IAttachmentDocument extends IAttachment, Document {
- getValidTemporaryUrl: GetValidTemporaryUrl
- cashTemporaryUrlByProvideSec: CashTemporaryUrlByProvideSec,
- }
- export interface IAttachmentModel extends Model<IAttachmentDocument> {
- createWithoutSave: (
- pageId, user, originalName: string, fileFormat: string, fileSize: number, attachmentType: AttachmentType,
- ) => IAttachmentDocument;
- }
- const attachmentSchema = new Schema({
- page: { type: Schema.Types.ObjectId, ref: 'Page', index: true },
- creator: { type: Schema.Types.ObjectId, ref: 'User', index: true },
- filePath: { type: String }, // DEPRECATED: remains for backward compatibility for v3.3.x or below
- fileName: { type: String, required: true, unique: true },
- fileFormat: { type: String, required: true },
- fileSize: { type: Number, default: 0 },
- originalName: { type: String },
- temporaryUrlCached: { type: String },
- temporaryUrlExpiredAt: { type: Date },
- attachmentType: {
- type: String,
- enum: AttachmentType,
- required: true,
- },
- }, {
- timestamps: { createdAt: true, updatedAt: false },
- });
- attachmentSchema.plugin(uniqueValidator);
- attachmentSchema.plugin(mongoosePaginate);
- // virtual
- attachmentSchema.virtual('filePathProxied').get(function() {
- return `/attachment/${this._id}`;
- });
- attachmentSchema.virtual('downloadPathProxied').get(function() {
- return `/download/${this._id}`;
- });
- attachmentSchema.set('toObject', { virtuals: true });
- attachmentSchema.set('toJSON', { virtuals: true });
- attachmentSchema.statics.createWithoutSave = function(
- pageId, user, originalName: string, fileFormat: string, fileSize: number, attachmentType: AttachmentType,
- ) {
- // eslint-disable-next-line @typescript-eslint/no-this-alias
- const Attachment = this;
- const extname = path.extname(originalName);
- let fileName = generateFileHash(originalName);
- if (extname.length > 1) { // ignore if empty or '.' only
- fileName = `${fileName}${extname}`;
- }
- const attachment = new Attachment();
- attachment.page = pageId;
- attachment.creator = user._id;
- attachment.originalName = originalName;
- attachment.fileName = fileName;
- attachment.fileFormat = fileFormat;
- attachment.fileSize = fileSize;
- attachment.attachmentType = attachmentType;
- return attachment;
- };
- const getValidTemporaryUrl: GetValidTemporaryUrl = function(this: IAttachmentDocument) {
- if (this.temporaryUrlExpiredAt == null) {
- return null;
- }
- // return null when expired url
- if (this.temporaryUrlExpiredAt.getTime() < new Date().getTime()) {
- return null;
- }
- return this.temporaryUrlCached;
- };
- attachmentSchema.methods.getValidTemporaryUrl = getValidTemporaryUrl;
- const cashTemporaryUrlByProvideSec: CashTemporaryUrlByProvideSec = function(this: IAttachmentDocument, temporaryUrl, lifetimeSec) {
- if (temporaryUrl == null) {
- throw new Error('url is required.');
- }
- this.temporaryUrlCached = temporaryUrl;
- this.temporaryUrlExpiredAt = addSeconds(new Date(), lifetimeSec);
- return this.save();
- };
- attachmentSchema.methods.cashTemporaryUrlByProvideSec = cashTemporaryUrlByProvideSec;
- export const Attachment = getOrCreateModel<IAttachmentDocument, IAttachmentModel>('Attachment', attachmentSchema);
|