diff --git a/src/models/drive-file.ts b/src/models/drive-file.ts index c86570f0f..ff31ba05d 100644 --- a/src/models/drive-file.ts +++ b/src/models/drive-file.ts @@ -1,8 +1,11 @@ -import * as mongodb from 'mongodb'; +import * as mongo from 'mongodb'; import deepcopy = require('deepcopy'); import { pack as packFolder } from './drive-folder'; import config from '../config'; import monkDb, { nativeDbConn } from '../db/mongodb'; +import Note, { deleteNote } from './note'; +import MessagingMessage, { deleteMessagingMessage } from './messaging-message'; +import User from './user'; const DriveFile = monkDb.get('driveFiles.files'); @@ -10,9 +13,9 @@ DriveFile.createIndex('metadata.uri', { sparse: true, unique: true }); export default DriveFile; -const getGridFSBucket = async (): Promise => { +const getGridFSBucket = async (): Promise => { const db = await nativeDbConn(); - const bucket = new mongodb.GridFSBucket(db, { + const bucket = new mongo.GridFSBucket(db, { bucketName: 'driveFiles' }); return bucket; @@ -22,14 +25,14 @@ export { getGridFSBucket }; export type IMetadata = { properties: any; - userId: mongodb.ObjectID; - folderId: mongodb.ObjectID; + userId: mongo.ObjectID; + folderId: mongo.ObjectID; comment: string; uri: string; }; export type IDriveFile = { - _id: mongodb.ObjectID; + _id: mongo.ObjectID; uploadDate: Date; md5: string; filename: string; @@ -47,12 +50,56 @@ export function validateFileName(name: string): boolean { ); } +/** + * DriveFileを物理削除します + */ +export async function deleteDriveFile(driveFile: string | mongo.ObjectID | IDriveFile) { + let d: IDriveFile; + + // Populate + if (mongo.ObjectID.prototype.isPrototypeOf(driveFile)) { + d = await DriveFile.findOne({ + _id: driveFile + }); + } else if (typeof driveFile === 'string') { + d = await DriveFile.findOne({ + _id: new mongo.ObjectID(driveFile) + }); + } else { + d = driveFile as IDriveFile; + } + + if (d == null) return; + + // このDriveFileを添付しているNoteをすべて削除 + await Promise.all(( + await Note.find({ mediaIds: d._id }) + ).map(x => deleteNote(x))); + + // このDriveFileを添付しているMessagingMessageをすべて削除 + await Promise.all(( + await MessagingMessage.find({ fileId: d._id }) + ).map(x => deleteMessagingMessage(x))); + + // このDriveFileがアバターやバナーに使われていたらそれらのプロパティをnullにする + const u = await User.findOne({ _id: d.metadata.userId }); + if (u) { + if (u.avatarId.equals(d._id)) { + await User.update({ _id: u._id }, { $set: { avatarId: null } }); + } + if (u.bannerId.equals(d._id)) { + await User.update({ _id: u._id }, { $set: { bannerId: null } }); + } + } + + // このDriveFileを削除 + await DriveFile.remove({ + _id: d._id + }); +} + /** * Pack a drive file for API response - * - * @param {any} file - * @param {any} options? - * @return {Promise} */ export const pack = ( file: any, diff --git a/src/models/drive-folder.ts b/src/models/drive-folder.ts index 45cc9c964..e7961936a 100644 --- a/src/models/drive-folder.ts +++ b/src/models/drive-folder.ts @@ -21,12 +21,53 @@ export function isValidFolderName(name: string): boolean { ); } +/** + * DriveFolderを物理削除します + */ +export async function deleteDriveFolder(driveFolder: string | mongo.ObjectID | IDriveFolder) { + let d: IDriveFolder; + + // Populate + if (mongo.ObjectID.prototype.isPrototypeOf(driveFolder)) { + d = await DriveFolder.findOne({ + _id: driveFolder + }); + } else if (typeof driveFolder === 'string') { + d = await DriveFolder.findOne({ + _id: new mongo.ObjectID(driveFolder) + }); + } else { + d = driveFolder as IDriveFolder; + } + + if (d == null) return; + + // このDriveFolderに格納されているDriveFileがあればすべてルートに移動 + await DriveFile.update({ + 'metadata.folderId': d._id + }, { + $set: { + 'metadata.folderId': null + } + }); + + // このDriveFolderに格納されているDriveFolderがあればすべてルートに移動 + await DriveFolder.update({ + parentId: d._id + }, { + $set: { + parentId: null + } + }); + + // このDriveFolderを削除 + await DriveFolder.remove({ + _id: d._id + }); +} + /** * Pack a drive folder for API response - * - * @param {any} folder - * @param {any} options? - * @return {Promise} */ export const pack = ( folder: any, diff --git a/src/models/user.ts b/src/models/user.ts index 6155324be..b56cf03ef 100644 --- a/src/models/user.ts +++ b/src/models/user.ts @@ -13,6 +13,8 @@ import Favorite, { deleteFavorite } from './favorite'; import NoteReaction, { deleteNoteReaction } from './note-reaction'; import MessagingMessage, { deleteMessagingMessage } from './messaging-message'; import MessagingHistory, { deleteMessagingHistory } from './messaging-history'; +import DriveFile, { deleteDriveFile } from './drive-file'; +import DriveFolder, { deleteDriveFolder } from './drive-folder'; const User = db.get('users'); @@ -190,6 +192,14 @@ export async function deleteUser(user: string | mongo.ObjectID | IUser) { ).map(x => deleteMessagingHistory(x))); // このユーザーのDriveFileをすべて削除 + await Promise.all(( + await DriveFile.find({ 'metadata.userId': u._id }) + ).map(x => deleteDriveFile(x))); + + // このユーザーのDriveFolderをすべて削除 + await Promise.all(( + await DriveFolder.find({ userId: u._id }) + ).map(x => deleteDriveFolder(x))); // このユーザーのFollowingをすべて削除