chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import inquirer from 'inquirer';
|
||||
import { promisify } from 'util';
|
||||
import chalk from 'chalk';
|
||||
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
|
||||
import Message from '@fiora/database/mongoose/models/message';
|
||||
import History from '@fiora/database/mongoose/models/history';
|
||||
|
||||
export async function deleteMessages() {
|
||||
const shouldDeleteAllMessages = await inquirer.prompt({
|
||||
type: 'confirm',
|
||||
name: 'result',
|
||||
message: 'Confirm to delete all messages?',
|
||||
});
|
||||
if (!shouldDeleteAllMessages.result) {
|
||||
return;
|
||||
}
|
||||
|
||||
await initMongoDB();
|
||||
|
||||
const deleteResult = await Message.deleteMany({});
|
||||
console.log('Delete result:', deleteResult);
|
||||
|
||||
const deleteHistoryResult = await History.deleteMany({});
|
||||
console.log('Delete history result:', deleteHistoryResult);
|
||||
|
||||
const shouldDeleteAllFiles = await inquirer.prompt({
|
||||
type: 'confirm',
|
||||
name: 'result',
|
||||
message: 'Confirm to delete all message files(Except OSS files)?',
|
||||
});
|
||||
if (!shouldDeleteAllFiles.result) {
|
||||
return;
|
||||
}
|
||||
|
||||
const files = await promisify(fs.readdir)(
|
||||
path.resolve(__dirname, '../../server/public/'),
|
||||
);
|
||||
const iamgesAndFiles = files.filter(
|
||||
(filename) =>
|
||||
filename.startsWith('ImageMessage_') ||
|
||||
filename.startsWith('FileMessage_'),
|
||||
);
|
||||
const unlinkAsync = promisify(fs.unlink);
|
||||
await Promise.all(
|
||||
iamgesAndFiles.map((file) =>
|
||||
unlinkAsync(path.resolve(__dirname, '../../server/public/', file)),
|
||||
),
|
||||
);
|
||||
console.log('Delete files:', chalk.green(iamgesAndFiles.length.toString()));
|
||||
console.log(chalk.red(iamgesAndFiles.join('\n')));
|
||||
|
||||
console.log(chalk.green('Successfully deleted all messages'));
|
||||
}
|
||||
|
||||
async function run() {
|
||||
await deleteMessages();
|
||||
process.exit(0);
|
||||
}
|
||||
export default run;
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Delete users created today and their related data
|
||||
*/
|
||||
import chalk from 'chalk';
|
||||
|
||||
import inquirer from 'inquirer';
|
||||
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
|
||||
import User from '@fiora/database/mongoose/models/user';
|
||||
import { deleteUser } from './deleteUser';
|
||||
|
||||
export async function deleteTodayRegisteredUsers() {
|
||||
await initMongoDB();
|
||||
|
||||
const now = new Date();
|
||||
const time = new Date(
|
||||
`${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()} 00:00:00`,
|
||||
);
|
||||
const users = await User.find({
|
||||
createTime: {
|
||||
$gte: time,
|
||||
},
|
||||
});
|
||||
console.log(
|
||||
`There are ${chalk.green(
|
||||
users.length.toString(),
|
||||
)} newly registered users today`,
|
||||
);
|
||||
if (users.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shouldDeleteUsers = await inquirer.prompt({
|
||||
type: 'confirm',
|
||||
name: 'result',
|
||||
message: 'Confirm to delete these users?',
|
||||
});
|
||||
if (!shouldDeleteUsers.result) {
|
||||
return;
|
||||
}
|
||||
await Promise.all(
|
||||
users.map((user) => deleteUser(user._id.toString(), false)),
|
||||
);
|
||||
|
||||
console.log(
|
||||
chalk.green('Successfully deleted today’s newly registered users'),
|
||||
);
|
||||
}
|
||||
|
||||
async function run() {
|
||||
await deleteTodayRegisteredUsers();
|
||||
process.exit(0);
|
||||
}
|
||||
export default run;
|
||||
@@ -0,0 +1,117 @@
|
||||
/* eslint-disable no-console */
|
||||
import chalk from 'chalk';
|
||||
|
||||
import inquirer from 'inquirer';
|
||||
import User from '@fiora/database/mongoose/models/user';
|
||||
import Message from '@fiora/database/mongoose/models/message';
|
||||
import Group, { GroupDocument } from '@fiora/database/mongoose/models/group';
|
||||
import Friend from '@fiora/database/mongoose/models/friend';
|
||||
import History from '@fiora/database/mongoose/models/history';
|
||||
import initMongoDB, { mongoose } from '@fiora/database/mongoose/initMongoDB';
|
||||
|
||||
export async function deleteUser(userIdOrName: string, confirm = true) {
|
||||
if (!userIdOrName) {
|
||||
console.log(chalk.red('Wrong command, [userIdOrName] is missing.'));
|
||||
return;
|
||||
}
|
||||
|
||||
await initMongoDB();
|
||||
|
||||
try {
|
||||
const user = await User.findOne(
|
||||
mongoose.isValidObjectId(userIdOrName)
|
||||
? { _id: userIdOrName }
|
||||
: { username: userIdOrName },
|
||||
);
|
||||
if (user) {
|
||||
console.log(
|
||||
'Found user:',
|
||||
chalk.blue(user._id.toString()),
|
||||
chalk.green(user.username),
|
||||
);
|
||||
|
||||
if (confirm) {
|
||||
const shouldDeleteUser = await inquirer.prompt({
|
||||
type: 'confirm',
|
||||
name: 'result',
|
||||
message: 'Confirm to delete user?',
|
||||
});
|
||||
if (!shouldDeleteUser.result) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const messages = await Message.find({ from: user._id });
|
||||
const deleteHistoryResult = await History.deleteMany({
|
||||
message: {
|
||||
$in: messages.map((message) => message.id),
|
||||
},
|
||||
});
|
||||
console.log('Delete history result:', deleteHistoryResult);
|
||||
|
||||
console.log(chalk.yellow('Delete messages created by this user'));
|
||||
const deleteMessageResult = await Message.deleteMany({
|
||||
from: user._id,
|
||||
});
|
||||
console.log('Delete result:', deleteMessageResult);
|
||||
|
||||
console.log(
|
||||
chalk.yellow('Leave the group that the user has joined'),
|
||||
);
|
||||
const groups = await Group.find({
|
||||
members: user._id,
|
||||
});
|
||||
// eslint-disable-next-line no-inner-declarations
|
||||
async function leaveGroup(group: GroupDocument) {
|
||||
if (!user) {
|
||||
return;
|
||||
}
|
||||
console.log('Leave', group.name);
|
||||
const index = group.members.indexOf(user?._id);
|
||||
group.members.splice(index, 1);
|
||||
if (group.creator?.toString() === user?._id.toString()) {
|
||||
// @ts-ignore
|
||||
group.creator = null;
|
||||
}
|
||||
await group.save();
|
||||
}
|
||||
await Promise.all(groups.map(leaveGroup));
|
||||
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'Delete the friend relationship related to this user',
|
||||
),
|
||||
);
|
||||
const deleteFriendResult1 = await Friend.deleteMany({
|
||||
from: user._id,
|
||||
});
|
||||
const deleteFriendResult2 = await Friend.deleteMany({
|
||||
to: user._id,
|
||||
});
|
||||
console.log(
|
||||
'Delete result:',
|
||||
deleteFriendResult1,
|
||||
deleteFriendResult2,
|
||||
);
|
||||
|
||||
console.log(chalk.yellow('Delete this user'));
|
||||
const deleteUserResult = await User.deleteMany({
|
||||
_id: user._id,
|
||||
});
|
||||
console.log('Delete result:', deleteUserResult);
|
||||
|
||||
console.log(chalk.green('Successfully deleted user'));
|
||||
} else {
|
||||
console.log(chalk.red(`User [${userIdOrName}] does not exist`));
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(chalk.red('Failed to delete user!', err.message));
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const userIdOrName = process.argv[3];
|
||||
await deleteUser(userIdOrName);
|
||||
process.exit(0);
|
||||
}
|
||||
export default run;
|
||||
@@ -0,0 +1,57 @@
|
||||
import chalk from 'chalk';
|
||||
import cp from 'child_process';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import detect from 'detect-port';
|
||||
import server from '@fiora/config/server';
|
||||
import initRedis from '@fiora/database/redis/initRedis';
|
||||
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
|
||||
|
||||
export async function doctor() {
|
||||
console.log(chalk.yellow('===== Run Fiora Doctor ====='));
|
||||
|
||||
const nodeVersion = cp.execSync('node --version').toString();
|
||||
console.log(
|
||||
chalk.green(`node ${nodeVersion.slice(0, nodeVersion.length - 1)}`),
|
||||
);
|
||||
|
||||
await initMongoDB();
|
||||
console.log(chalk.green('MongoDB is OK'));
|
||||
|
||||
await (async () =>
|
||||
new Promise((resolve) => {
|
||||
const redis = initRedis();
|
||||
redis.on('connect', resolve);
|
||||
}))();
|
||||
console.log(chalk.green('Redis is OK'));
|
||||
|
||||
const avaliablePort = await detect(server.port);
|
||||
if (avaliablePort === server.port) {
|
||||
console.log(chalk.green(`Port [${server.port}] is OK`));
|
||||
} else {
|
||||
console.log(chalk.red(`Port [${server.port}] was occupied`));
|
||||
}
|
||||
|
||||
const indexFilePath = path.resolve(
|
||||
__dirname,
|
||||
'../../server/public/index.html',
|
||||
);
|
||||
const indexFile = fs.readFileSync(indexFilePath);
|
||||
if (!indexFile) {
|
||||
console.log(chalk.red('Homepage not exists'));
|
||||
} else if (indexFile.toString().includes('默认首页')) {
|
||||
console.log(
|
||||
chalk.red(
|
||||
'Homepage is default. Please build web client by [yarn build:web]',
|
||||
),
|
||||
);
|
||||
} else {
|
||||
console.log(chalk.green(`Homepage is OK`));
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
await doctor();
|
||||
process.exit(0);
|
||||
}
|
||||
export default run;
|
||||
@@ -0,0 +1,50 @@
|
||||
import chalk from 'chalk';
|
||||
import inquirer from 'inquirer';
|
||||
import User from '@fiora/database/mongoose/models/user';
|
||||
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
|
||||
|
||||
export async function fixUsersAvatar(
|
||||
searchValue: string,
|
||||
replaceValue: string,
|
||||
) {
|
||||
searchValue = searchValue || 'fioraavatar';
|
||||
replaceValue = replaceValue || 'fiora/avatar';
|
||||
|
||||
await initMongoDB();
|
||||
|
||||
const users = await User.find({ avatar: { $regex: 'fioraavatar' } });
|
||||
if (users.length) {
|
||||
console.log(chalk.red('Oh No!'), "Some user's avatar is wrong");
|
||||
users.forEach((user) => {
|
||||
console.log(user._id, user.username, user.avatar);
|
||||
});
|
||||
|
||||
const shouldFix = await inquirer.prompt({
|
||||
type: 'confirm',
|
||||
name: 'result',
|
||||
message: 'Confirm to fix?',
|
||||
});
|
||||
if (shouldFix.result) {
|
||||
await Promise.all(
|
||||
users.map((user) => {
|
||||
user.avatar = user.avatar.replace(
|
||||
searchValue,
|
||||
replaceValue,
|
||||
);
|
||||
return user.save();
|
||||
}),
|
||||
);
|
||||
console.log(chalk.green('Congratulations! Fixed!'));
|
||||
}
|
||||
} else {
|
||||
console.log(chalk.green('OK!'), "All user's avatar is corrent");
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const searchValue = process.argv[3];
|
||||
const replaceValue = process.argv[4];
|
||||
await fixUsersAvatar(searchValue, replaceValue);
|
||||
process.exit(0);
|
||||
}
|
||||
export default run;
|
||||
@@ -0,0 +1,29 @@
|
||||
import chalk from 'chalk';
|
||||
import User from '@fiora/database/mongoose/models/user';
|
||||
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
|
||||
|
||||
export async function getUserId(username: string) {
|
||||
if (!username) {
|
||||
console.log(chalk.red('Wrong command, [username] is missing.'));
|
||||
return;
|
||||
}
|
||||
|
||||
await initMongoDB();
|
||||
|
||||
const user = await User.findOne({ username });
|
||||
if (!user) {
|
||||
console.log(chalk.red(`User [${username}] does not exist`));
|
||||
} else {
|
||||
console.log(
|
||||
`The userId of [${username}] is:`,
|
||||
chalk.green(user._id.toString()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const username = process.argv[3];
|
||||
await getUserId(username);
|
||||
process.exit(0);
|
||||
}
|
||||
export default run;
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Register
|
||||
*/
|
||||
|
||||
import bcrypt from 'bcryptjs';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
|
||||
import User, { UserDocument } from '../../database/mongoose/models/user';
|
||||
import Group from '../../database/mongoose/models/group';
|
||||
|
||||
import { SALT_ROUNDS } from '../../utils/const';
|
||||
import getRandomAvatar from '../../utils/getRandomAvatar';
|
||||
|
||||
export async function register(username: string, password: string) {
|
||||
if (!username) {
|
||||
console.log(chalk.red('Wrong command, [username] is missing.'));
|
||||
return;
|
||||
}
|
||||
if (!password) {
|
||||
console.log(chalk.red('Wrong command, [password] is missing.'));
|
||||
return;
|
||||
}
|
||||
|
||||
await initMongoDB();
|
||||
|
||||
const user = await User.findOne({ username });
|
||||
if (user) {
|
||||
console.log(chalk.red('The username already exists'));
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultGroup = await Group.findOne({ isDefault: true });
|
||||
if (!defaultGroup) {
|
||||
console.log(chalk.red('Default group does not exist'));
|
||||
return;
|
||||
}
|
||||
|
||||
const salt = await bcrypt.genSalt(SALT_ROUNDS);
|
||||
const hash = await bcrypt.hash(password, salt);
|
||||
|
||||
let newUser = null;
|
||||
try {
|
||||
newUser = await User.create({
|
||||
username,
|
||||
salt,
|
||||
password: hash,
|
||||
avatar: getRandomAvatar(),
|
||||
} as UserDocument);
|
||||
} catch (createError) {
|
||||
if (createError.name === 'ValidationError') {
|
||||
console.log(
|
||||
chalk.red(
|
||||
'Username contains unsupported characters or the length exceeds the limit',
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
console.log(chalk.red('Error:'), createError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!defaultGroup.creator) {
|
||||
defaultGroup.creator = newUser._id;
|
||||
}
|
||||
if (newUser) {
|
||||
defaultGroup.members.push(newUser._id);
|
||||
}
|
||||
await defaultGroup.save();
|
||||
|
||||
console.log(chalk.green(`Successfully created user [${username}]`));
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const username = process.argv[3];
|
||||
const password = process.argv[4];
|
||||
await register(username, password);
|
||||
process.exit(0);
|
||||
}
|
||||
export default run;
|
||||
@@ -0,0 +1,35 @@
|
||||
import chalk from 'chalk';
|
||||
import initMongoDB from '@fiora/database/mongoose/initMongoDB';
|
||||
import Group from '@fiora/database/mongoose/models/group';
|
||||
|
||||
export async function updateDefaultGroupName(newName: string) {
|
||||
if (!newName) {
|
||||
console.log(chalk.red('Wrong command, [newName] is missing.'));
|
||||
return;
|
||||
}
|
||||
|
||||
await initMongoDB();
|
||||
|
||||
const group = await Group.findOne({ isDefault: true });
|
||||
if (!group) {
|
||||
console.log(chalk.red('Default group does not exist'));
|
||||
} else {
|
||||
group.name = newName;
|
||||
try {
|
||||
await group.save();
|
||||
console.log(chalk.green('Update default group name success!'));
|
||||
} catch (err) {
|
||||
console.log(
|
||||
chalk.red('Update default group name fail!'),
|
||||
err.message,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const newName = process.argv[3];
|
||||
await updateDefaultGroupName(newName);
|
||||
process.exit(0);
|
||||
}
|
||||
export default run;
|
||||
Reference in New Issue
Block a user