| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- import type { IAttachment } from '@growi/core';
- import { addSeconds } from 'date-fns/addSeconds';
- import { type Document, type Model, Schema } from 'mongoose';
- import mongoosePaginate from 'mongoose-paginate-v2';
- import uniqueValidator from 'mongoose-unique-validator';
- import path from 'path';
- 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,
- ) {
- // biome-ignore lint/complexity/noUselessThisAlias: ignore
- 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);
|