物理削除系の処理を削除
これらの処理はパフォーマンス的に現実的でないし、すべてのモデルの関係を把握している必要があり保守が困難 論理削除でなんとかする
This commit is contained in:
parent
d64dc45899
commit
108dcb3e61
@ -1,6 +1,5 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
|
||||||
|
|
||||||
const AccessToken = db.get<IAccessToken>('accessTokens');
|
const AccessToken = db.get<IAccessToken>('accessTokens');
|
||||||
AccessToken.createIndex('token');
|
AccessToken.createIndex('token');
|
||||||
@ -15,30 +14,3 @@ export type IAccessToken = {
|
|||||||
token: string;
|
token: string;
|
||||||
hash: string;
|
hash: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* AccessTokenを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteAccessToken(accessToken: string | mongo.ObjectID | IAccessToken) {
|
|
||||||
let a: IAccessToken;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(accessToken)) {
|
|
||||||
a = await AccessToken.findOne({
|
|
||||||
_id: accessToken
|
|
||||||
});
|
|
||||||
} else if (typeof accessToken === 'string') {
|
|
||||||
a = await AccessToken.findOne({
|
|
||||||
_id: new mongo.ObjectID(accessToken)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
a = accessToken as IAccessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (a == null) return;
|
|
||||||
|
|
||||||
// このAccessTokenを削除
|
|
||||||
await AccessToken.remove({
|
|
||||||
_id: a._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
|
||||||
|
|
||||||
const Blocking = db.get<IBlocking>('blocking');
|
const Blocking = db.get<IBlocking>('blocking');
|
||||||
Blocking.createIndex(['blockerId', 'blockeeId'], { unique: true });
|
Blocking.createIndex(['blockerId', 'blockeeId'], { unique: true });
|
||||||
@ -12,30 +11,3 @@ export type IBlocking = {
|
|||||||
blockeeId: mongo.ObjectID;
|
blockeeId: mongo.ObjectID;
|
||||||
blockerId: mongo.ObjectID;
|
blockerId: mongo.ObjectID;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Blockingを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteBlocking(blocking: string | mongo.ObjectID | IBlocking) {
|
|
||||||
let f: IBlocking;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(blocking)) {
|
|
||||||
f = await Blocking.findOne({
|
|
||||||
_id: blocking
|
|
||||||
});
|
|
||||||
} else if (typeof blocking === 'string') {
|
|
||||||
f = await Blocking.findOne({
|
|
||||||
_id: new mongo.ObjectID(blocking)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
f = blocking as IBlocking;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f == null) return;
|
|
||||||
|
|
||||||
// このBlockingを削除
|
|
||||||
await Blocking.remove({
|
|
||||||
_id: f._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import monkDb, { nativeDbConn } from '../db/mongodb';
|
import monkDb, { nativeDbConn } from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
|
||||||
|
|
||||||
const DriveFileThumbnail = monkDb.get<IDriveFileThumbnail>('driveFileThumbnails.files');
|
const DriveFileThumbnail = monkDb.get<IDriveFileThumbnail>('driveFileThumbnails.files');
|
||||||
DriveFileThumbnail.createIndex('metadata.originalId', { sparse: true, unique: true });
|
DriveFileThumbnail.createIndex('metadata.originalId', { sparse: true, unique: true });
|
||||||
@ -28,35 +27,3 @@ export type IDriveFileThumbnail = {
|
|||||||
contentType: string;
|
contentType: string;
|
||||||
metadata: IMetadata;
|
metadata: IMetadata;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* DriveFileThumbnailを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteDriveFileThumbnail(driveFile: string | mongo.ObjectID | IDriveFileThumbnail) {
|
|
||||||
let d: IDriveFileThumbnail;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(driveFile)) {
|
|
||||||
d = await DriveFileThumbnail.findOne({
|
|
||||||
_id: driveFile
|
|
||||||
});
|
|
||||||
} else if (typeof driveFile === 'string') {
|
|
||||||
d = await DriveFileThumbnail.findOne({
|
|
||||||
_id: new mongo.ObjectID(driveFile)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
d = driveFile as IDriveFileThumbnail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d == null) return;
|
|
||||||
|
|
||||||
// このDriveFileThumbnailのチャンクをすべて削除
|
|
||||||
await DriveFileThumbnailChunk.remove({
|
|
||||||
files_id: d._id
|
|
||||||
});
|
|
||||||
|
|
||||||
// このDriveFileThumbnailを削除
|
|
||||||
await DriveFileThumbnail.remove({
|
|
||||||
_id: d._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -4,10 +4,6 @@ import { pack as packFolder } from './drive-folder';
|
|||||||
import config from '../config';
|
import config from '../config';
|
||||||
import monkDb, { nativeDbConn } from '../db/mongodb';
|
import monkDb, { nativeDbConn } from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
import isObjectId from '../misc/is-objectid';
|
||||||
import Note, { deleteNote } from './note';
|
|
||||||
import MessagingMessage, { deleteMessagingMessage } from './messaging-message';
|
|
||||||
import User from './user';
|
|
||||||
import DriveFileThumbnail, { deleteDriveFileThumbnail } from './drive-file-thumbnail';
|
|
||||||
|
|
||||||
const DriveFile = monkDb.get<IDriveFile>('driveFiles.files');
|
const DriveFile = monkDb.get<IDriveFile>('driveFiles.files');
|
||||||
DriveFile.createIndex('md5');
|
DriveFile.createIndex('md5');
|
||||||
@ -77,64 +73,6 @@ export function validateFileName(name: string): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* DriveFileを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteDriveFile(driveFile: string | mongo.ObjectID | IDriveFile) {
|
|
||||||
let d: IDriveFile;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(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({ fileIds: 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 && u.avatarId.equals(d._id)) {
|
|
||||||
await User.update({ _id: u._id }, { $set: { avatarId: null } });
|
|
||||||
}
|
|
||||||
if (u.bannerId && u.bannerId.equals(d._id)) {
|
|
||||||
await User.update({ _id: u._id }, { $set: { bannerId: null } });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// このDriveFileのDriveFileThumbnailをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await DriveFileThumbnail.find({ 'metadata.originalId': d._id })
|
|
||||||
).map(x => deleteDriveFileThumbnail(x)));
|
|
||||||
|
|
||||||
// このDriveFileのチャンクをすべて削除
|
|
||||||
await DriveFileChunk.remove({
|
|
||||||
files_id: d._id
|
|
||||||
});
|
|
||||||
|
|
||||||
// このDriveFileを削除
|
|
||||||
await DriveFile.remove({
|
|
||||||
_id: d._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const packMany = async (
|
export const packMany = async (
|
||||||
files: any[],
|
files: any[],
|
||||||
options?: {
|
options?: {
|
||||||
|
@ -23,51 +23,6 @@ export function isValidFolderName(name: string): boolean {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* DriveFolderを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteDriveFolder(driveFolder: string | mongo.ObjectID | IDriveFolder) {
|
|
||||||
let d: IDriveFolder;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(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
|
* Pack a drive folder for API response
|
||||||
*/
|
*/
|
||||||
|
@ -15,33 +15,6 @@ export type IFavorite = {
|
|||||||
noteId: mongo.ObjectID;
|
noteId: mongo.ObjectID;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Favoriteを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteFavorite(favorite: string | mongo.ObjectID | IFavorite) {
|
|
||||||
let f: IFavorite;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(favorite)) {
|
|
||||||
f = await Favorite.findOne({
|
|
||||||
_id: favorite
|
|
||||||
});
|
|
||||||
} else if (typeof favorite === 'string') {
|
|
||||||
f = await Favorite.findOne({
|
|
||||||
_id: new mongo.ObjectID(favorite)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
f = favorite as IFavorite;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f == null) return;
|
|
||||||
|
|
||||||
// このFavoriteを削除
|
|
||||||
await Favorite.remove({
|
|
||||||
_id: f._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const packMany = async (
|
export const packMany = async (
|
||||||
favorites: any[],
|
favorites: any[],
|
||||||
me: any
|
me: any
|
||||||
|
@ -28,33 +28,6 @@ export type IFollowRequest = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* FollowRequestを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteFollowRequest(followRequest: string | mongo.ObjectID | IFollowRequest) {
|
|
||||||
let f: IFollowRequest;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(followRequest)) {
|
|
||||||
f = await FollowRequest.findOne({
|
|
||||||
_id: followRequest
|
|
||||||
});
|
|
||||||
} else if (typeof followRequest === 'string') {
|
|
||||||
f = await FollowRequest.findOne({
|
|
||||||
_id: new mongo.ObjectID(followRequest)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
f = followRequest as IFollowRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f == null) return;
|
|
||||||
|
|
||||||
// このFollowingを削除
|
|
||||||
await FollowRequest.remove({
|
|
||||||
_id: f._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pack a request for API response
|
* Pack a request for API response
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
|
||||||
|
|
||||||
const Following = db.get<IFollowing>('following');
|
const Following = db.get<IFollowing>('following');
|
||||||
Following.createIndex(['followerId', 'followeeId'], { unique: true });
|
Following.createIndex(['followerId', 'followeeId'], { unique: true });
|
||||||
@ -25,30 +24,3 @@ export type IFollowing = {
|
|||||||
sharedInbox?: string;
|
sharedInbox?: string;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Followingを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteFollowing(following: string | mongo.ObjectID | IFollowing) {
|
|
||||||
let f: IFollowing;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(following)) {
|
|
||||||
f = await Following.findOne({
|
|
||||||
_id: following
|
|
||||||
});
|
|
||||||
} else if (typeof following === 'string') {
|
|
||||||
f = await Following.findOne({
|
|
||||||
_id: new mongo.ObjectID(following)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
f = following as IFollowing;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (f == null) return;
|
|
||||||
|
|
||||||
// このFollowingを削除
|
|
||||||
await Following.remove({
|
|
||||||
_id: f._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
|
||||||
|
|
||||||
const MessagingHistory = db.get<IMessagingHistory>('messagingHistories');
|
const MessagingHistory = db.get<IMessagingHistory>('messagingHistories');
|
||||||
export default MessagingHistory;
|
export default MessagingHistory;
|
||||||
@ -12,30 +11,3 @@ export type IMessagingHistory = {
|
|||||||
partnerId: mongo.ObjectID;
|
partnerId: mongo.ObjectID;
|
||||||
messageId: mongo.ObjectID;
|
messageId: mongo.ObjectID;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* MessagingHistoryを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteMessagingHistory(messagingHistory: string | mongo.ObjectID | IMessagingHistory) {
|
|
||||||
let m: IMessagingHistory;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(messagingHistory)) {
|
|
||||||
m = await MessagingHistory.findOne({
|
|
||||||
_id: messagingHistory
|
|
||||||
});
|
|
||||||
} else if (typeof messagingHistory === 'string') {
|
|
||||||
m = await MessagingHistory.findOne({
|
|
||||||
_id: new mongo.ObjectID(messagingHistory)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
m = messagingHistory as IMessagingHistory;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m == null) return;
|
|
||||||
|
|
||||||
// このMessagingHistoryを削除
|
|
||||||
await MessagingHistory.remove({
|
|
||||||
_id: m._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -4,7 +4,6 @@ import { pack as packUser } from './user';
|
|||||||
import { pack as packFile } from './drive-file';
|
import { pack as packFile } from './drive-file';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
import isObjectId from '../misc/is-objectid';
|
||||||
import MessagingHistory, { deleteMessagingHistory } from './messaging-history';
|
|
||||||
import { length } from 'stringz';
|
import { length } from 'stringz';
|
||||||
|
|
||||||
const MessagingMessage = db.get<IMessagingMessage>('messagingMessages');
|
const MessagingMessage = db.get<IMessagingMessage>('messagingMessages');
|
||||||
@ -24,38 +23,6 @@ export function isValidText(text: string): boolean {
|
|||||||
return length(text.trim()) <= 1000 && text.trim() != '';
|
return length(text.trim()) <= 1000 && text.trim() != '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* MessagingMessageを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteMessagingMessage(messagingMessage: string | mongo.ObjectID | IMessagingMessage) {
|
|
||||||
let m: IMessagingMessage;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(messagingMessage)) {
|
|
||||||
m = await MessagingMessage.findOne({
|
|
||||||
_id: messagingMessage
|
|
||||||
});
|
|
||||||
} else if (typeof messagingMessage === 'string') {
|
|
||||||
m = await MessagingMessage.findOne({
|
|
||||||
_id: new mongo.ObjectID(messagingMessage)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
m = messagingMessage as IMessagingMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m == null) return;
|
|
||||||
|
|
||||||
// このMessagingMessageを指すMessagingHistoryをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await MessagingHistory.find({ messageId: m._id })
|
|
||||||
).map(x => deleteMessagingHistory(x)));
|
|
||||||
|
|
||||||
// このMessagingMessageを削除
|
|
||||||
await MessagingMessage.remove({
|
|
||||||
_id: m._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pack a messaging message for API response
|
* Pack a messaging message for API response
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
|
||||||
|
|
||||||
const Mute = db.get<IMute>('mute');
|
const Mute = db.get<IMute>('mute');
|
||||||
Mute.createIndex(['muterId', 'muteeId'], { unique: true });
|
Mute.createIndex(['muterId', 'muteeId'], { unique: true });
|
||||||
@ -12,30 +11,3 @@ export interface IMute {
|
|||||||
muterId: mongo.ObjectID;
|
muterId: mongo.ObjectID;
|
||||||
muteeId: mongo.ObjectID;
|
muteeId: mongo.ObjectID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Muteを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteMute(mute: string | mongo.ObjectID | IMute) {
|
|
||||||
let m: IMute;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(mute)) {
|
|
||||||
m = await Mute.findOne({
|
|
||||||
_id: mute
|
|
||||||
});
|
|
||||||
} else if (typeof mute === 'string') {
|
|
||||||
m = await Mute.findOne({
|
|
||||||
_id: new mongo.ObjectID(mute)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
m = mute as IMute;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m == null) return;
|
|
||||||
|
|
||||||
// このMuteを削除
|
|
||||||
await Mute.remove({
|
|
||||||
_id: m._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -33,33 +33,6 @@ export const validateReaction = $.str.or([
|
|||||||
'pudding'
|
'pudding'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
|
||||||
* NoteReactionを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteNoteReaction(noteReaction: string | mongo.ObjectID | INoteReaction) {
|
|
||||||
let n: INoteReaction;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(noteReaction)) {
|
|
||||||
n = await NoteReaction.findOne({
|
|
||||||
_id: noteReaction
|
|
||||||
});
|
|
||||||
} else if (typeof noteReaction === 'string') {
|
|
||||||
n = await NoteReaction.findOne({
|
|
||||||
_id: new mongo.ObjectID(noteReaction)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
n = noteReaction as INoteReaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n == null) return;
|
|
||||||
|
|
||||||
// このNoteReactionを削除
|
|
||||||
await NoteReaction.remove({
|
|
||||||
_id: n._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pack a reaction for API response
|
* Pack a reaction for API response
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
|
||||||
|
|
||||||
const NoteWatching = db.get<INoteWatching>('noteWatching');
|
const NoteWatching = db.get<INoteWatching>('noteWatching');
|
||||||
NoteWatching.createIndex(['userId', 'noteId'], { unique: true });
|
NoteWatching.createIndex(['userId', 'noteId'], { unique: true });
|
||||||
@ -12,30 +11,3 @@ export interface INoteWatching {
|
|||||||
userId: mongo.ObjectID;
|
userId: mongo.ObjectID;
|
||||||
noteId: mongo.ObjectID;
|
noteId: mongo.ObjectID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* NoteWatchingを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteNoteWatching(noteWatching: string | mongo.ObjectID | INoteWatching) {
|
|
||||||
let n: INoteWatching;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(noteWatching)) {
|
|
||||||
n = await NoteWatching.findOne({
|
|
||||||
_id: noteWatching
|
|
||||||
});
|
|
||||||
} else if (typeof noteWatching === 'string') {
|
|
||||||
n = await NoteWatching.findOne({
|
|
||||||
_id: new mongo.ObjectID(noteWatching)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
n = noteWatching as INoteWatching;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n == null) return;
|
|
||||||
|
|
||||||
// このNoteWatchingを削除
|
|
||||||
await NoteWatching.remove({
|
|
||||||
_id: n._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -6,13 +6,10 @@ import isObjectId from '../misc/is-objectid';
|
|||||||
import { length } from 'stringz';
|
import { length } from 'stringz';
|
||||||
import { IUser, pack as packUser } from './user';
|
import { IUser, pack as packUser } from './user';
|
||||||
import { pack as packApp } from './app';
|
import { pack as packApp } from './app';
|
||||||
import PollVote, { deletePollVote } from './poll-vote';
|
import PollVote from './poll-vote';
|
||||||
import Reaction, { deleteNoteReaction } from './note-reaction';
|
import Reaction from './note-reaction';
|
||||||
import { packMany as packFileMany, IDriveFile } from './drive-file';
|
import { packMany as packFileMany, IDriveFile } from './drive-file';
|
||||||
import NoteWatching, { deleteNoteWatching } from './note-watching';
|
import Favorite from './favorite';
|
||||||
import NoteReaction from './note-reaction';
|
|
||||||
import Favorite, { deleteFavorite } from './favorite';
|
|
||||||
import Notification, { deleteNotification } from './notification';
|
|
||||||
import Following from './following';
|
import Following from './following';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
|
|
||||||
@ -108,72 +105,6 @@ export type INote = {
|
|||||||
_files?: IDriveFile[];
|
_files?: IDriveFile[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Noteを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteNote(note: string | mongo.ObjectID | INote) {
|
|
||||||
let n: INote;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(note)) {
|
|
||||||
n = await Note.findOne({
|
|
||||||
_id: note
|
|
||||||
});
|
|
||||||
} else if (typeof note === 'string') {
|
|
||||||
n = await Note.findOne({
|
|
||||||
_id: new mongo.ObjectID(note)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
n = note as INote;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(n == null ? `Note: delete skipped ${note}` : `Note: deleting ${n._id}`);
|
|
||||||
|
|
||||||
if (n == null) return;
|
|
||||||
|
|
||||||
// このNoteへの返信をすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Note.find({ replyId: n._id })
|
|
||||||
).map(x => deleteNote(x)));
|
|
||||||
|
|
||||||
// このNoteのRenoteをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Note.find({ renoteId: n._id })
|
|
||||||
).map(x => deleteNote(x)));
|
|
||||||
|
|
||||||
// この投稿に対するNoteWatchingをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await NoteWatching.find({ noteId: n._id })
|
|
||||||
).map(x => deleteNoteWatching(x)));
|
|
||||||
|
|
||||||
// この投稿に対するNoteReactionをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await NoteReaction.find({ noteId: n._id })
|
|
||||||
).map(x => deleteNoteReaction(x)));
|
|
||||||
|
|
||||||
// この投稿に対するPollVoteをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await PollVote.find({ noteId: n._id })
|
|
||||||
).map(x => deletePollVote(x)));
|
|
||||||
|
|
||||||
// この投稿に対するFavoriteをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Favorite.find({ noteId: n._id })
|
|
||||||
).map(x => deleteFavorite(x)));
|
|
||||||
|
|
||||||
// この投稿に対するNotificationをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Notification.find({ noteId: n._id })
|
|
||||||
).map(x => deleteNotification(x)));
|
|
||||||
|
|
||||||
// このNoteを削除
|
|
||||||
await Note.remove({
|
|
||||||
_id: n._id
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`Note: deleted ${n._id}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const hideNote = async (packedNote: any, meId: mongo.ObjectID) => {
|
export const hideNote = async (packedNote: any, meId: mongo.ObjectID) => {
|
||||||
let hide = false;
|
let hide = false;
|
||||||
|
|
||||||
|
@ -51,33 +51,6 @@ export interface INotification {
|
|||||||
isRead: Boolean;
|
isRead: Boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Notificationを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteNotification(notification: string | mongo.ObjectID | INotification) {
|
|
||||||
let n: INotification;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(notification)) {
|
|
||||||
n = await Notification.findOne({
|
|
||||||
_id: notification
|
|
||||||
});
|
|
||||||
} else if (typeof notification === 'string') {
|
|
||||||
n = await Notification.findOne({
|
|
||||||
_id: new mongo.ObjectID(notification)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
n = notification as INotification;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n == null) return;
|
|
||||||
|
|
||||||
// このNotificationを削除
|
|
||||||
await Notification.remove({
|
|
||||||
_id: n._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const packMany = async (
|
export const packMany = async (
|
||||||
notifications: any[]
|
notifications: any[]
|
||||||
) => {
|
) => {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
|
||||||
|
|
||||||
const PollVote = db.get<IPollVote>('pollVotes');
|
const PollVote = db.get<IPollVote>('pollVotes');
|
||||||
export default PollVote;
|
export default PollVote;
|
||||||
@ -12,30 +11,3 @@ export interface IPollVote {
|
|||||||
noteId: mongo.ObjectID;
|
noteId: mongo.ObjectID;
|
||||||
choice: number;
|
choice: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* PollVoteを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deletePollVote(pollVote: string | mongo.ObjectID | IPollVote) {
|
|
||||||
let p: IPollVote;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(pollVote)) {
|
|
||||||
p = await PollVote.findOne({
|
|
||||||
_id: pollVote
|
|
||||||
});
|
|
||||||
} else if (typeof pollVote === 'string') {
|
|
||||||
p = await PollVote.findOne({
|
|
||||||
_id: new mongo.ObjectID(pollVote)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
p = pollVote as IPollVote;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == null) return;
|
|
||||||
|
|
||||||
// このPollVoteを削除
|
|
||||||
await PollVote.remove({
|
|
||||||
_id: p._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
|
||||||
|
|
||||||
const SwSubscription = db.get<ISwSubscription>('swSubscriptions');
|
const SwSubscription = db.get<ISwSubscription>('swSubscriptions');
|
||||||
export default SwSubscription;
|
export default SwSubscription;
|
||||||
@ -12,30 +11,3 @@ export interface ISwSubscription {
|
|||||||
auth: string;
|
auth: string;
|
||||||
publickey: string;
|
publickey: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* SwSubscriptionを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteSwSubscription(swSubscription: string | mongo.ObjectID | ISwSubscription) {
|
|
||||||
let s: ISwSubscription;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(swSubscription)) {
|
|
||||||
s = await SwSubscription.findOne({
|
|
||||||
_id: swSubscription
|
|
||||||
});
|
|
||||||
} else if (typeof swSubscription === 'string') {
|
|
||||||
s = await SwSubscription.findOne({
|
|
||||||
_id: new mongo.ObjectID(swSubscription)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
s = swSubscription as ISwSubscription;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s == null) return;
|
|
||||||
|
|
||||||
// このSwSubscriptionを削除
|
|
||||||
await SwSubscription.remove({
|
|
||||||
_id: s._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@ -14,33 +14,6 @@ export interface IUserList {
|
|||||||
userIds: mongo.ObjectID[];
|
userIds: mongo.ObjectID[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* UserListを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteUserList(userList: string | mongo.ObjectID | IUserList) {
|
|
||||||
let u: IUserList;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(userList)) {
|
|
||||||
u = await UserList.findOne({
|
|
||||||
_id: userList
|
|
||||||
});
|
|
||||||
} else if (typeof userList === 'string') {
|
|
||||||
u = await UserList.findOne({
|
|
||||||
_id: new mongo.ObjectID(userList)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
u = userList as IUserList;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (u == null) return;
|
|
||||||
|
|
||||||
// このUserListを削除
|
|
||||||
await UserList.remove({
|
|
||||||
_id: u._id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const pack = (
|
export const pack = (
|
||||||
userList: string | mongo.ObjectID | IUserList
|
userList: string | mongo.ObjectID | IUserList
|
||||||
) => new Promise<any>(async (resolve, reject) => {
|
) => new Promise<any>(async (resolve, reject) => {
|
||||||
|
@ -1,28 +1,15 @@
|
|||||||
import * as mongo from 'mongodb';
|
import * as mongo from 'mongodb';
|
||||||
const deepcopy = require('deepcopy');
|
const deepcopy = require('deepcopy');
|
||||||
const sequential = require('promise-sequential');
|
|
||||||
import rap from '@prezzemolo/rap';
|
import rap from '@prezzemolo/rap';
|
||||||
import db from '../db/mongodb';
|
import db from '../db/mongodb';
|
||||||
import isObjectId from '../misc/is-objectid';
|
import isObjectId from '../misc/is-objectid';
|
||||||
import Note, { packMany as packNoteMany, deleteNote } from './note';
|
import { packMany as packNoteMany } from './note';
|
||||||
import Following, { deleteFollowing } from './following';
|
import Following from './following';
|
||||||
import Blocking, { deleteBlocking } from './blocking';
|
import Blocking from './blocking';
|
||||||
import Mute, { deleteMute } from './mute';
|
import Mute from './mute';
|
||||||
import { getFriendIds } from '../server/api/common/get-friends';
|
import { getFriendIds } from '../server/api/common/get-friends';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import AccessToken, { deleteAccessToken } from './access-token';
|
import FollowRequest from './follow-request';
|
||||||
import NoteWatching, { deleteNoteWatching } from './note-watching';
|
|
||||||
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';
|
|
||||||
import PollVote, { deletePollVote } from './poll-vote';
|
|
||||||
import SwSubscription, { deleteSwSubscription } from './sw-subscription';
|
|
||||||
import Notification, { deleteNotification } from './notification';
|
|
||||||
import UserList, { deleteUserList } from './user-list';
|
|
||||||
import FollowRequest, { deleteFollowRequest } from './follow-request';
|
|
||||||
|
|
||||||
const User = db.get<IUser>('users');
|
const User = db.get<IUser>('users');
|
||||||
|
|
||||||
@ -168,161 +155,6 @@ export function isValidBirthday(birthday: string): boolean {
|
|||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
/**
|
|
||||||
* Userを物理削除します
|
|
||||||
*/
|
|
||||||
export async function deleteUser(user: string | mongo.ObjectID | IUser) {
|
|
||||||
let u: IUser;
|
|
||||||
|
|
||||||
// Populate
|
|
||||||
if (isObjectId(user)) {
|
|
||||||
u = await User.findOne({
|
|
||||||
_id: user
|
|
||||||
});
|
|
||||||
} else if (typeof user === 'string') {
|
|
||||||
u = await User.findOne({
|
|
||||||
_id: new mongo.ObjectID(user)
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
u = user as IUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(u == null ? `User: delete skipped ${user}` : `User: deleting ${u._id}`);
|
|
||||||
|
|
||||||
if (u == null) return;
|
|
||||||
|
|
||||||
// このユーザーのAccessTokenをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await AccessToken.find({ userId: u._id })
|
|
||||||
).map(x => deleteAccessToken(x)));
|
|
||||||
|
|
||||||
// このユーザーのNoteをすべて削除
|
|
||||||
await sequential((
|
|
||||||
await Note.find({ userId: u._id })
|
|
||||||
).map(x => () => deleteNote(x)));
|
|
||||||
|
|
||||||
// このユーザーのNoteReactionをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await NoteReaction.find({ userId: u._id })
|
|
||||||
).map(x => deleteNoteReaction(x)));
|
|
||||||
|
|
||||||
// このユーザーのNoteWatchingをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await NoteWatching.find({ userId: u._id })
|
|
||||||
).map(x => deleteNoteWatching(x)));
|
|
||||||
|
|
||||||
// このユーザーのPollVoteをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await PollVote.find({ userId: u._id })
|
|
||||||
).map(x => deletePollVote(x)));
|
|
||||||
|
|
||||||
// このユーザーのFavoriteをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Favorite.find({ userId: u._id })
|
|
||||||
).map(x => deleteFavorite(x)));
|
|
||||||
|
|
||||||
// このユーザーのMessageをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await MessagingMessage.find({ userId: u._id })
|
|
||||||
).map(x => deleteMessagingMessage(x)));
|
|
||||||
|
|
||||||
// このユーザーへのMessageをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await MessagingMessage.find({ recipientId: u._id })
|
|
||||||
).map(x => deleteMessagingMessage(x)));
|
|
||||||
|
|
||||||
// このユーザーの関わるMessagingHistoryをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await MessagingHistory.find({ $or: [{ partnerId: u._id }, { userId: u._id }] })
|
|
||||||
).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)));
|
|
||||||
|
|
||||||
// このユーザーのMuteをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Mute.find({ muterId: u._id })
|
|
||||||
).map(x => deleteMute(x)));
|
|
||||||
|
|
||||||
// このユーザーへのMuteをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Mute.find({ muteeId: u._id })
|
|
||||||
).map(x => deleteMute(x)));
|
|
||||||
|
|
||||||
// このユーザーのFollowingをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Following.find({ followerId: u._id })
|
|
||||||
).map(x => deleteFollowing(x)));
|
|
||||||
|
|
||||||
// このユーザーへのFollowingをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Following.find({ followeeId: u._id })
|
|
||||||
).map(x => deleteFollowing(x)));
|
|
||||||
|
|
||||||
// このユーザーのFollowRequestをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await FollowRequest.find({ followerId: u._id })
|
|
||||||
).map(x => deleteFollowRequest(x)));
|
|
||||||
|
|
||||||
// このユーザーへのFollowRequestをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await FollowRequest.find({ followeeId: u._id })
|
|
||||||
).map(x => deleteFollowRequest(x)));
|
|
||||||
|
|
||||||
// このユーザーのBlockingをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Blocking.find({ blockerId: u._id })
|
|
||||||
).map(x => deleteBlocking(x)));
|
|
||||||
|
|
||||||
// このユーザーへのBlockingをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Blocking.find({ blockeeId: u._id })
|
|
||||||
).map(x => deleteBlocking(x)));
|
|
||||||
|
|
||||||
// このユーザーのSwSubscriptionをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await SwSubscription.find({ userId: u._id })
|
|
||||||
).map(x => deleteSwSubscription(x)));
|
|
||||||
|
|
||||||
// このユーザーのNotificationをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Notification.find({ notifieeId: u._id })
|
|
||||||
).map(x => deleteNotification(x)));
|
|
||||||
|
|
||||||
// このユーザーが原因となったNotificationをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await Notification.find({ notifierId: u._id })
|
|
||||||
).map(x => deleteNotification(x)));
|
|
||||||
|
|
||||||
// このユーザーのUserListをすべて削除
|
|
||||||
await Promise.all((
|
|
||||||
await UserList.find({ userId: u._id })
|
|
||||||
).map(x => deleteUserList(x)));
|
|
||||||
|
|
||||||
// このユーザーが入っているすべてのUserListからこのユーザーを削除
|
|
||||||
await Promise.all((
|
|
||||||
await UserList.find({ userIds: u._id })
|
|
||||||
).map(x =>
|
|
||||||
UserList.update({ _id: x._id }, {
|
|
||||||
$pull: { userIds: u._id }
|
|
||||||
})
|
|
||||||
));
|
|
||||||
|
|
||||||
// このユーザーを削除
|
|
||||||
await User.remove({
|
|
||||||
_id: u._id
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`User: deleted ${u._id}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pack a user for API response
|
* Pack a user for API response
|
||||||
*
|
*
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import $ from 'cafy';
|
import $ from 'cafy';
|
||||||
import ID from '../../../../../misc/cafy-id';
|
import ID from '../../../../../misc/cafy-id';
|
||||||
import UserList, { deleteUserList } from '../../../../../models/user-list';
|
import UserList from '../../../../../models/user-list';
|
||||||
import { ILocalUser } from '../../../../../models/user';
|
import { ILocalUser } from '../../../../../models/user';
|
||||||
import getParams from '../../../get-params';
|
import getParams from '../../../get-params';
|
||||||
|
|
||||||
@ -37,7 +37,9 @@ export default (params: any, user: ILocalUser) => new Promise(async (res, rej) =
|
|||||||
return rej('list not found');
|
return rej('list not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteUserList(userList);
|
await UserList.remove({
|
||||||
|
_id: userList._id
|
||||||
|
});
|
||||||
|
|
||||||
res();
|
res();
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user