Update moongo

This commit is contained in:
2026-03-25 20:14:41 +01:00
parent 3ad16d8f32
commit 3eb40a1e26
30 changed files with 418 additions and 331 deletions
+1 -1
View File
@@ -229,7 +229,7 @@ export async function removeFriend(accountId: string, friendId: string) {
const existing = await findFriendRequest(accountId, friendId);
if (existing) {
existing.remove();
existing.deleteOne();
}
}
+3 -3
View File
@@ -289,12 +289,12 @@ export class AdminServerActions implements IAdminServerActions, SocketServer {
}
@Method({ promise: true })
async getPoniesCreators(account: string) {
const items: ICharacter[] = await Character.find({ account }, '_id name creator').lean().exec();
return items.map(({ _id, name, creator }) => <PonyCreator>{ _id, name, creator });
const items = await Character.find({ account }, '_id name creator').lean<ICharacter[]>().exec();
return items.map(({ _id, name, creator }) => <PonyCreator>{ _id: _id.toString(), name, creator });
}
@Method({ promise: true })
async getPoniesForAccount(account: string) {
return await Character.find({ account }).lean().exec();
return await Character.find({ account }).lean().exec() as any;
}
@Method({ promise: true })
async getDetailsForAccount(accountId: string) {
+1 -1
View File
@@ -183,7 +183,7 @@ export async function removeAccount(service: AdminService, accountId: string) {
if (account) {
checkIfNotAdmin(account, `remove account: ${accountId}`);
await account.remove();
await account.deleteOne();
service.removedItem('accounts', accountId);
}
+5 -4
View File
@@ -6,7 +6,7 @@ import {
} from '../../common/adminInterfaces';
import { execAsync } from '../serverUtils';
import {
IAccount, Account, Origin, Event, iterate, ISession, Session, SupporterInvite as DBSupporterInvite,
Account, Origin, Event, iterate, ISession, Session, SupporterInvite as DBSupporterInvite,
findAccount, ISupporterInvite, ID
} from '../db';
import { servers, serverStatus, loginServers } from '../internal';
@@ -157,7 +157,7 @@ export async function getChat(search: string, date: string, caseInsensitive: boo
}
export async function getChatForAccounts(accountIds: string[], date: string) {
const accounts: Partial<IAccount>[] = await Account.find({ _id: { $in: accountIds } }, '_id merges').lean().exec();
const accounts = await Account.find({ _id: { $in: accountIds } }, '_id merges').lean().exec();
const map = new Map<string, string>();
const ids = flatten(accounts.map(a => [a._id.toString(), ...(a.merges || []).map(a => a.id)]));
@@ -174,6 +174,7 @@ export async function getChatForAccounts(accountIds: string[], date: string) {
const fixed = chat.replace(/^([0-9:]+) \[([a-f0-9]{24})\]/gmu, (_, date, id) =>
`${date} ${map.has(id) ? map.get(id) : `[${id}]`}`);
return fixed;
}
@@ -187,11 +188,11 @@ export async function clearSessions(accountId: string) {
const user = data && data.passport && data.passport.user;
if (user === accountId) {
clearIds.push(session._id);
clearIds.push(session._id.toString());
}
}
} catch (e) {
logger.error('Error when claring session', e, session._id, session.session);
logger.error('Error when clearing session', e, session._id, session.session);
}
});
+7 -7
View File
@@ -137,19 +137,19 @@ async function merge(
Promise.all([
SupporterInvite.updateMany({ source: merge._id }, { source: account._id }).exec(),
SupporterInvite.updateMany({ target: merge._id }, { target: account._id }).exec(),
]).then(() => SupporterInvite.remove({ target: account._id, source: account._id }).exec()),
]).then(() => SupporterInvite.deleteOne({ target: account._id, source: account._id }).exec()),
Promise.all([
FriendRequest.updateMany({ source: merge._id }, { source: account._id }).exec(),
FriendRequest.updateMany({ target: merge._id }, { target: account._id }).exec(),
]).then(() => FriendRequest.remove({ target: account._id, source: account._id }).exec()),
]).then(() => FriendRequest.deleteOne({ target: account._id, source: account._id }).exec()),
Promise.all([
HideRequest.updateMany({ source: merge._id }, { source: account._id }).exec(),
HideRequest.updateMany({ target: merge._id }, { target: account._id }).exec(),
]).then(() => HideRequest.remove({ target: account._id, source: account._id }).exec()),
]).then(() => HideRequest.deleteOne({ target: account._id, source: account._id }).exec()),
]);
await removeDuplicateFriendRequests(id);
await merge.remove();
await merge.deleteOne();
await kickFromAllServers(withId);
await removedDocument('accounts', withId);
await updateCharacterCount(id);
@@ -175,7 +175,7 @@ async function removeDuplicateFriendRequests(id: string) {
}
if (removeRequests.length) {
await FriendRequest.remove({ _id: { $in: removeRequests } }).exec();
await FriendRequest.deleteOne({ _id: { $in: removeRequests } }).exec();
}
}
@@ -227,7 +227,7 @@ export async function split(
const friendsToRemove = [...(keep.friends || []), ...(split.friends || [])];
await FriendRequest.deleteMany({
await FriendRequest.deleteOne({
$or: [
{ target: account._id, source: { $in: friendsToRemove } },
{ source: account._id, target: { $in: friendsToRemove } },
@@ -243,7 +243,7 @@ export async function split(
const hidesToRemove = [...(keep.hides || []), ...(split.hides || [])].map(hide => hide.id);
await HideRequest.deleteMany({
await HideRequest.deleteOne({
$or: [
{ source: account._id, target: { $in: hidesToRemove } },
],
+2 -2
View File
@@ -75,7 +75,7 @@ export async function removeCharacter(service: AdminService, characterId: string
return;
await kickFromAllServersByCharacter(characterId);
await character.remove();
await character.deleteOne();
await updateCharacterCount(character.account);
logRemovedCharacter(character);
service.ponies.removed(characterId);
@@ -83,7 +83,7 @@ export async function removeCharacter(service: AdminService, characterId: string
async function removeCharacters(character: ICharacter[], accountId: string, removedDocument: RemovedDocument) {
await Bluebird.map(character, async c => {
await c.remove();
await c.deleteOne();
await removedDocument('ponies', c._id.toString());
logRemovedCharacter(c);
}, { concurrency: 4 });
+3 -3
View File
@@ -88,7 +88,7 @@ export const createSavePony =
character.desc = typeof data.desc === 'string' ? data.desc.substr(0, PLAYER_DESC_MAX_LENGTH) : '';
character.name = data.name;
character.tag = data.tag;
character.site = auth ? auth._id : null;
character.site = auth?._id;
character.info = info;
character.flags = flags;
character.lastUsed = new Date();
@@ -115,9 +115,9 @@ export const createSavePony =
}
if (created) {
log(account._id, `created pony "${character.name}"`);
log(account._id.toString(), `created pony "${character.name}"`);
} else if (nameChanged) {
log(account._id, `renamed pony "${oldName}" => "${character.name}"`);
log(account._id.toString(), `renamed pony "${oldName}" => "${character.name}"`);
}
return toPonyObject(character);
+1 -1
View File
@@ -65,7 +65,7 @@ export async function updateAuthInfo(
}
if (!auth.account && accountId) {
changes.account = Types.ObjectId(accountId);
changes.account = new Types.ObjectId(accountId);
}
if (Object.keys(changes).length > 0) {
+2 -2
View File
@@ -4,7 +4,7 @@ require('source-map-support').install();
import 'core-js/stable/promise/finally';
import 'reflect-metadata';
import * as Promise from 'bluebird';
import * as Bluebird from 'bluebird';
import * as fs from 'fs';
import { argv } from 'yargs';
@@ -16,4 +16,4 @@ import { argv } from 'yargs';
(global as any).TESTS = false;
(global as any).performance = Date;
Promise.promisifyAll(fs);
Bluebird.promisifyAll(fs);
+3 -2
View File
@@ -2,7 +2,7 @@ import { repeat } from 'lodash';
import { toByteArray } from 'base64-js';
import { encodeString } from 'ag-sockets/dist/utf8';
import { PonyOptions, EntityState, UpdateFlags } from '../common/interfaces';
import { ICharacter, IAccount, Character, MongoQuery, queryCharacter } from './db';
import { ICharacter, IAccount, Character, queryCharacter } from './db';
import { isForbiddenName } from '../common/security';
import { supporterLevel } from '../common/adminUtils';
import { CharacterFlags, CharacterState, ServerConfig, CharacterStateFlags } from '../common/adminInterfaces';
@@ -22,6 +22,7 @@ import { saySystem } from './chat';
import { isPonyFlying } from '../common/entityUtils';
import { createCharacterState, updateClientCharacter } from './playerUtils';
import { encodeExpression } from '../common/encoders/expressionEncoder';
import { QueryFilter } from 'mongoose';
export const defaultCharacterState: CharacterState = { x: 0, y: 0 };
@@ -177,7 +178,7 @@ export function logRemovedCharacter({ _id, account, name, info }: ICharacter) {
log(systemMessage(`${account}`, `removed pony [${_id}] "${name}" ${info}`));
}
export async function swapCharacter(client: IClient, { server }: World, query: MongoQuery<ICharacter>) {
export async function swapCharacter(client: IClient, { server }: World, query: QueryFilter<ICharacter>) {
if (client.isSwitchingMap)
return;
+26 -27
View File
@@ -1,4 +1,4 @@
import { model, Schema, Types, Document, Query } from 'mongoose';
import { model, Schema, Types, Document, Query, QueryFilter, UpdateQuery } from 'mongoose';
import {
TimestampsBase, EventBase, CharacterBase, AccountBase, AuthBase, OriginBase, OriginInfoBase, CharacterState,
SupporterInviteBase, FriendRequestBase, HideRequestBase, MergeHideData
@@ -9,6 +9,7 @@ import { FriendData } from '../common/interfaces';
import { replaceEmojis } from '../common/emoji';
import { filterForbidden } from './characterUtils';
import { filterName } from '../common/swears';
import { compact, noop } from 'lodash';
//set('debug', true); // debug mongoose
@@ -205,13 +206,13 @@ export const Origin = model<IOrigin>('Origin', originSchema);
export const Session = model<ISession>('session', sessionSchema);
export const Character = model<ICharacter>('Character', characterSchema);
accountSchema.post('remove', function (doc: Document) {
accountSchema.post('deleteOne', function (doc: Document) {
Promise.all([
Character.deleteMany({ account: doc._id }).exec(),
Event.deleteMany({ account: doc._id }).exec(),
Auth.deleteMany({ account: doc._id }).exec(),
FriendRequest.deleteMany({ $or: [{ target: doc._id }, { source: doc._id }] }).exec(),
HideRequest.deleteMany({ $or: [{ target: doc._id }, { source: doc._id }] }).exec(),
Character.deleteOne({ account: doc._id }).exec(),
Event.deleteOne({ account: doc._id }).exec(),
Auth.deleteOne({ account: doc._id }).exec(),
FriendRequest.deleteOne({ $or: [{ target: doc._id }, { source: doc._id }] }).exec(),
HideRequest.deleteOne({ $or: [{ target: doc._id }, { source: doc._id }] }).exec(),
]).catch(logger.error);
});
@@ -249,15 +250,11 @@ export interface MongoUpdateExpr<T> extends MongoUpdateExprField<T> {
$addToSet?: any;
}
export type MongoQuery<T> = {
[P in keyof T]?: T[P] | MongoQueryExpr<T[P]>;
};
export type MongoUpdate<T> = {
[P in keyof T]?: T[P] | MongoUpdateExprField<T[P]>;
} & MongoUpdateExpr<T>;
export function iterate<T>(query: Query<T>, onData: (doc: T) => void) {
export function iterate<T>(query: Query<T, T>, onData: (doc: T) => void) {
return new Promise<void>(resolve => {
query.cursor()
.on('data', onData)
@@ -290,7 +287,7 @@ export type FindCharacter = (characterId: ID, accountId: ID) => Promise<ICharact
export type FindCharacterSafe = (characterId: ID, accountId: ID) => Promise<ICharacter>;
export type FindCharacters = (accountId: ID, fields?: string) => Promise<ICharacter[]>;
export type UpdateCharacterState = (characterId: ID, serverName: string, state: CharacterState) => Promise<void>;
export type QueryCharacter = (query: MongoQuery<ICharacter>, fields?: string) => Promise<ICharacter | undefined>;
export type QueryCharacter = (query: QueryFilter<ICharacter>, fields?: string) => Promise<ICharacter | undefined>;
export function createCharacter(account: IAccount) {
return new Character({ account: account._id, creator: `${account.name} [${account._id}]` });
@@ -323,12 +320,13 @@ export function findLatestCharacters(account: ID, count: number): Promise<IChara
.exec();
}
export function removeCharacter(id: ID, account: ID): Promise<ICharacter | undefined> {
return Character.findOneAndRemove({ _id: id, account }).exec().then(nullToUndefined);
export async function removeCharacter(id: ID, account: ID): Promise<ICharacter | undefined> {
const doc = await Character.findOneAndDelete({ _id: id, account }).exec();
return doc ?? undefined;
}
export const updateCharacterState: UpdateCharacterState = (characterId, serverName, state) =>
Character.updateOne({ _id: characterId }, { [`state.${serverName}`]: state }).exec().then(nullToUndefined);
Character.updateOne({ _id: characterId }, { [`state.${serverName}`]: state }).exec().then(noop);
export const queryCharacter: QueryCharacter = (query, fields) =>
Character.findOne(query, fields).exec() as any;
@@ -338,8 +336,8 @@ export const queryCharacter: QueryCharacter = (query, fields) =>
export type FindAuth = (authId: ID, accountId: ID, fields?: string) => Promise<IAuth | undefined>;
export type FindAuths = (accountId: ID, fields?: string) => Promise<IAuth[]>;
export type CountAuths = (accountId: ID) => Promise<number>;
export type QueryAuths = (query: MongoQuery<IAuth>, fields?: string) => Promise<IAuth[]>;
export type UpdateAuth = (authId: ID, update: MongoUpdate<IAuth>) => Promise<void>;
export type QueryAuths = (query: QueryFilter<IAuth>, fields?: string) => Promise<IAuth[]>;
export type UpdateAuth = (authId: ID, update: UpdateQuery<IAuth>) => Promise<void>;
export const findAuthByOpenId = (openId: string, provider: string): Promise<IAuth | undefined> =>
Auth.findOne({ openId, provider }).exec().then(nullToUndefined);
@@ -363,22 +361,23 @@ export const queryAuths: QueryAuths = (query, fields) =>
Auth.find(query, fields).lean().exec();
export const updateAuth: UpdateAuth = (id, update) =>
Auth.updateOne({ _id: id }, update).exec();
Auth.updateOne({ _id: id }, update).exec().then(noop);
// accounts
export type FindAccountSafe = (accountId: ID, projection?: string) => Promise<IAccount>;
export type UpdateAccount = (accountId: ID, update: MongoUpdate<IAccount>) => Promise<void>;
export type UpdateAccounts = (query: MongoQuery<IAccount>, update: MongoUpdate<IAccount>) => Promise<void>;
export type QueryAccounts = (query: MongoQuery<IAccount>, fields?: string) => Promise<IAccount[]>;
export type QueryAccount = (query: MongoQuery<IAccount>, fields?: string) => Promise<IAccount | undefined>;
export type UpdateAccounts = (query: QueryFilter<IAccount>, update: MongoUpdate<IAccount>) => Promise<void>;
export type QueryAccounts = (query: QueryFilter<IAccount>, fields?: string) => Promise<IAccount[]>;
export type QueryAccount = (query: QueryFilter<IAccount>, fields?: string) => Promise<IAccount | undefined>;
export const findAccount = (account: ID, projection?: string): Promise<IAccount | undefined> =>
Account.findById(account, projection).exec().then(nullToUndefined);
export function checkIfAdmin(account: ID): Promise<boolean> {
return Account.findOne({ _id: account }, 'roles').lean().exec()
.then(a => a && isAdmin(a));
.then(a => a && isAdmin(a)).then(r => !!r);
}
export function findAccountSafe(account: ID, projection?: string): Promise<IAccount> {
@@ -387,10 +386,10 @@ export function findAccountSafe(account: ID, projection?: string): Promise<IAcco
}
export const updateAccount: UpdateAccount = (accountId, update) =>
Account.updateOne({ _id: accountId }, update).exec();
Account.updateOne({ _id: accountId }, update).exec().then(noop);
export const updateAccounts: UpdateAccounts = (query, update) =>
Account.updateMany(query, update).exec();
Account.updateMany(query, update).exec().then(noop);
export const queryAccounts: QueryAccounts = (query, fields) =>
Account.find(query, fields).lean().exec();
@@ -428,8 +427,8 @@ export async function findFriends(accountId: ID, withCharacters: boolean): Promi
let characters: ICharacter[] = [];
if (withCharacters) {
const characterIds = accounts.map(a => a.lastCharacter).filter(id => id);
characters = await Character.find({ _id: { $in: characterIds } }, '_id name info').lean().exec();
const characterIds = compact(accounts.map(a => a.lastCharacter?.toString()));
characters = await Character.find({ _id: { $in: characterIds } }, '_id name info').lean<ICharacter[]>().exec();
}
return accounts.map(a => {
+4 -4
View File
@@ -49,7 +49,7 @@ export function createLiveEndPoint<T extends Doc>(
.tap(item => {
if (item) {
removedItem(item._id.toString());
return item.remove() as any;
return item.deleteOne() as any;
}
})
.tap(item => item && afterDelete && afterDelete(item))
@@ -86,12 +86,12 @@ export function createLiveEndPoint<T extends Doc>(
function findItemsExact(date: Date): Promise<T[]> {
return Promise.resolve(model.find({ updatedAt: date }, fields.join(' '))
.lean()
.lean<T[]>()
.exec());
}
function hasItem(items: T[], id: string) {
return items.some(i => i._id === id);
return items.some(i => i._id.toString() === id);
}
function addTailItems(items: T[]): Promise<{ items: T[]; more: boolean; }> {
@@ -108,7 +108,7 @@ export function createLiveEndPoint<T extends Doc>(
}
return findItemsExact(items[items.length - 1].updatedAt)
.then(other => other.filter(i => !hasItem(items, i._id)))
.then(other => other.filter(i => !hasItem(items, i?._id.toString())))
.then(other => [...items, ...other])
.then(items => ({ items, more: true }));
}
+1 -1
View File
@@ -101,7 +101,7 @@ const cleanupStrayAuths = (removedDocument: RemovedDocument) =>
const date = fromNow(-1 * DAY);
const query = { account: { $exists: false }, updatedAt: { $lt: date }, createdAt: { $lt: date } };
const items = await queryAuths(query, '_id');
await Auth.deleteMany(query).exec();
await Auth.deleteOne(query).exec();
await Bluebird.map(items, item => removedDocument('auths', item._id.toString()), { concurrency: 4 });
logPerformance(`[async] cleanupAccountAlerts (${Date.now() - start}ms)`);
};
+3 -3
View File
@@ -1,7 +1,7 @@
import { Request } from 'express';
import { truncate } from 'lodash';
import { Reporter } from './serverInterfaces';
import { Event, IEvent, IOriginInfo, ID, IAccount } from './db';
import { Event, IOriginInfo, ID, IAccount } from './db';
import { logger, system } from './logger';
import { ServerConfig } from '../common/adminInterfaces';
import { getOrigin } from './originUtils';
@@ -32,7 +32,7 @@ const createLogEvent =
return Event.updateOne({ _id: event._id }, { desc: event.desc, count: event.count + 1 }).exec();
} else {
return Event.create(<IEvent>{ server, account, pony, type, message, origin, desc });
return Event.create({ server, account, pony, type, message, origin, desc }) as any;
}
})
.catch(logger.error);
@@ -97,7 +97,7 @@ export function create(server: ServerConfig, account?: ID, pony?: ID, originInfo
/* istanbul ignore next */
export function createFromRequest(server: ServerConfig, req: Request, pony?: any) {
const user = req && req.user as IAccount | undefined;
const account = user ? user.id : undefined;
const account = user?._id?.toString();
const origin = req ? getOrigin(req) : undefined;
return create(server, account, pony, origin);
}
+1 -1
View File
@@ -27,7 +27,7 @@ export const validAccount = (server: ServerConfig): RequestHandler => (req, res,
const accountId = req.body.accountId as string;
const accountName = req.body.accountName as string;
if (!account || account.id !== accountId) {
if (!account || account._id.toString() !== accountId) {
if (!/#$/.test(accountId)) {
createFromRequest(server, req).warn(ACCOUNT_ERROR, `${accountName} [${accountId}] (${req.path})`);
}
+1 -1
View File
@@ -31,7 +31,7 @@ export default function (server: ServerConfig, settings: Settings, removedDocume
savePonyHandler(req.user as IAccount, req.body.pony, createFromRequest(server, req))));
app.post('/pony/remove', offline, hash, validAccount, wrap(server, req =>
removePonyHandler(req.body.id, (req.user as IAccount).id)));
removePonyHandler(req.body.id, (req.user as IAccount)?._id.toString())));
return app;
}
+1 -2
View File
@@ -1,5 +1,4 @@
import { Router } from 'express';
import { noop } from 'lodash';
import { findAllCharacters, findAllVisibleAuths, IAccount, Account } from '../db';
import { offline, hash, handleJSON } from '../requestUtils';
import { createGetAccountData } from '../api/account';
@@ -27,7 +26,7 @@ export default function (server: ServerConfig, settings: Settings) {
(lastBrowserId && account.lastBrowserId !== lastBrowserId)) {
account.lastUserAgent = lastUserAgent;
account.lastBrowserId = lastBrowserId;
Account.updateOne({ _id: account._id }, { lastUserAgent, lastBrowserId }, noop);
Account.updateOne({ _id: account._id }, { lastUserAgent, lastBrowserId });
}
return await getAccountData(account);
+10 -5
View File
@@ -84,8 +84,8 @@ const ignoreErrors = [
function kickCurrentUser(req: Request) {
const user = req.user as IAccount | undefined;
if (user) {
kickFromAllServers(user.id)
if (user?._id) {
kickFromAllServers(user._id?.toString())
.catch(e => logger.error(e));
}
}
@@ -97,7 +97,7 @@ function logIn(req: Request, account: IAccount) {
});
}
function isMerge(accountId: string) {
function isMerge(accountId: string | undefined) {
const minTime = fromNow(-10 * MINUTE).getTime();
remove(mergeRequests, r => r.time < minTime);
return mergeRequests.some(r => r.accountId === accountId);
@@ -186,7 +186,7 @@ async function handleAuth(
req: Request, res: Response, error: Error | null, account: IAccount | null,
) {
const user = req.user as IAccount | undefined;
const merge = isMerge(user && user.id);
const merge = isMerge(user?._id?.toString());
try {
if (error) {
@@ -359,7 +359,12 @@ export function authRoutes(
return [account._id.toString(), account.name];
}));
passport.use(new LocalStrategy((login, _pass, done) => Account.findById(login, done)));
passport.use(new LocalStrategy((login, _pass, done) =>
Account.findById(login)
.then(data => done(undefined, data as any))
.catch(e => done(e)))
);
app.get('/local', passport.authenticate('local', { successRedirect: '/', failureRedirect: '/failed-login' }));
}
+14 -11
View File
@@ -9,7 +9,7 @@ import * as expressSession from 'express-session';
import * as serveFavicon from 'serve-favicon';
import * as Rollbar from 'rollbar';
import { Passport } from 'passport';
import * as connectMongo from 'connect-mongo';
import MongoStore from 'connect-mongo';
import * as express from 'express';
import { WebSocketServer } from '@encharm/cws';
import { compact, once } from 'lodash';
@@ -67,14 +67,11 @@ function getServiceWorker() {
}
}
mongoose.connect(config.db, {
reconnectTries: Number.MAX_VALUE,
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
});
const clientP = mongoose.connect(config.db, {
autoIndex: true,
serverSelectionTimeoutMS: 5000,
}).then(m => m.connection.getClient());
const MongoStore = connectMongo(expressSession);
const app = express();
const production = app.get('env') === 'production';
const maxAge = production ? YEAR : 0;
@@ -163,8 +160,14 @@ app.use(require('cookie-parser')());
if (args.login || args.admin) {
passport.serializeUser<string>((account, done) => done(null, (account as IAccount)._id.toString()));
passport.deserializeUser<string>((id, done) =>
Account.findById(id, (err, a) => done(err, a && !isBanned(a) ? a : false)));
passport.deserializeUser<string>(async (id, done) => {
try {
const account = await Account.findById(id).exec();
done(undefined, account && !isBanned(account) ? account : false);
} catch (error) {
done(error);
}
});
}
const ignore = [
@@ -198,7 +201,7 @@ const createSession = () => expressSession({
cookie: {
maxAge: WEEK * 2,
},
store: new MongoStore({ mongooseConnection: mongoose.connection }),
store: new MongoStore({ client: clientP }),
});
const statsPath = pathTo('logs', `stats-${server.id}.csv`);
+4 -4
View File
@@ -96,12 +96,12 @@ export class SupporterInvitesService {
type LeanInvite = ISupporterInvite & { source: IAccount };
export async function updateSupporterInvites(model: Model<ISupporterInvite>) {
const invites: LeanInvite[] = await model.find({}, '_id active')
const invites = await model.find({}, '_id active')
.populate('source', '_id supporter patreon roles')
.lean()
.lean<LeanInvite[]>()
.exec();
const itemsBySource = toPairs(groupBy(invites, i => i.source._id as string));
const itemsBySource = toPairs(groupBy(invites, i => i.source._id));
const itemsToUpdate = itemsBySource
.map(([_, items]) => {
const source = items[0].source;
@@ -123,5 +123,5 @@ export async function updateSupporterInvites(model: Model<ISupporterInvite>) {
return model.updateMany({ _id: { $in: ids } }, { active }).exec();
}));
await model.deleteMany({ active: false, updatedAt: { $lt: fromNow(-100 * DAY) } }).exec();
await model.deleteOne({ active: false, updatedAt: { $lt: fromNow(-100 * DAY) } }).exec();
}
+3 -3
View File
@@ -62,7 +62,7 @@ export function genId() {
}
export function genObjectId() {
return Types.ObjectId(genId());
return new Types.ObjectId(genId());
}
export function mockClient(fields: any = {}): IClient {
@@ -81,8 +81,8 @@ export function mockClient(fields: any = {}): IClient {
friends: new Set<string>(),
accountSettings: {},
originalRequest: { headers: {} },
account: { id: accountId, _id: Types.ObjectId(accountId), ignores: [] },
character: { id: characterId, _id: Types.ObjectId(characterId) },
account: { id: accountId, _id: new Types.ObjectId(accountId), ignores: [] },
character: { id: characterId, _id: new Types.ObjectId(characterId) },
isMod: false,
pony,
map: createServerMap('', 0, 1, 1),
+2 -2
View File
@@ -54,7 +54,7 @@ describe('api pony', () => {
describe('for existing character', () => {
const characterId = genId();
const characterObjectId = Types.ObjectId(characterId);
const characterObjectId = new Types.ObjectId(characterId);
let character: ICharacter;
let account = { _id: 'accid' } as any;
@@ -212,7 +212,7 @@ describe('api pony', () => {
beforeEach(() => {
character = {
_id: Types.ObjectId(characterId),
_id: new Types.ObjectId(characterId),
save() { return this; }
} as any;
+6 -6
View File
@@ -14,7 +14,7 @@ describe('authUtils', () => {
describe('updateAuthInfo()', () => {
it('updates url and name fields', async () => {
const updateAuth = stub();
const a = auth({ _id: 'bar' });
const a = auth({ _id: new Types.ObjectId('bar') });
await updateAuthInfo(updateAuth, a, profile({ username: 'foo', url: 'bar' }), undefined);
@@ -33,7 +33,7 @@ describe('authUtils', () => {
it('updates email field (from empty)', async () => {
const updateAuth = stub();
const a = auth({ _id: 'bar' });
const a = auth({ _id: new Types.ObjectId('bar') });
await updateAuthInfo(updateAuth, a, profile({ emails: ['b', 'c'] }), undefined);
@@ -44,7 +44,7 @@ describe('authUtils', () => {
it('saves updated auth', async () => {
const updateAuth = stub();
await updateAuthInfo(updateAuth, auth({ _id: 'bar' }), profile({ username: 'foo' }), undefined);
await updateAuthInfo(updateAuth, auth({ _id: new Types.ObjectId('bar') }), profile({ username: 'foo' }), undefined);
assert.calledWith(updateAuth, 'bar', { name: 'foo' });
});
@@ -55,20 +55,20 @@ describe('authUtils', () => {
await updateAuthInfo(stub(), a, profile({ username: 'foo', url: 'bar' }), accountId);
expect(a.account).eql(Types.ObjectId(accountId));
expect(a.account).eql(new Types.ObjectId(accountId));
});
it('does not save auth if nothing changed', async () => {
const updateAuth = stub();
await updateAuthInfo(updateAuth, auth({ _id: 'bar', name: 'foo' }), profile({ username: 'foo' }), undefined);
await updateAuthInfo(updateAuth, auth({ _id: new Types.ObjectId('bar'), name: 'foo' }), profile({ username: 'foo' }), undefined);
assert.notCalled(updateAuth);
});
it('does nothing if email list is the same', async () => {
const updateAuth = stub();
const a = auth({ _id: 'bar', emails: ['a', 'b'] });
const a = auth({ _id: new Types.ObjectId('bar'), emails: ['a', 'b'] });
await updateAuthInfo(updateAuth, a, profile({ emails: ['b', 'a'] }), undefined);
+10 -7
View File
@@ -12,13 +12,14 @@ import { createServerMap } from '../../server/serverMap';
import { CounterService } from '../../server/services/counter';
import { createCharacterState } from '../../server/playerUtils';
import { hasFlag } from '../../common/utils';
import { Types } from 'mongoose';
describe('characterUtils', () => {
describe('createPony()', () => {
const defaultState: CharacterState = { x: 0, y: 0, flags: 0 };
it('creates pony entity', () => {
const pony = createPony(account({ _id: '' }), character({ name: 'foo' }), defaultState);
const pony = createPony(account({ _id: new Types.ObjectId('') }), character({ name: 'foo' }), defaultState);
expect(pony).not.undefined;
expect(pony.type).equal(entities.pony.type);
@@ -27,7 +28,7 @@ describe('characterUtils', () => {
it('sets initial position for character from state', () => {
const main: CharacterState = { ...defaultState, x: 1, y: 2 };
const pony = createPony(account({ _id: '' }), character({ name: 'foo' }), main);
const pony = createPony(account({ _id: new Types.ObjectId('') }), character({ name: 'foo' }), main);
expect(pony.x).eql(1, 'x');
expect(pony.y).eql(2, 'y');
@@ -36,7 +37,7 @@ describe('characterUtils', () => {
it('sets facing from state', () => {
const main: CharacterState = { ...defaultState, flags: CharacterStateFlags.Right };
const pony = createPony(account({ _id: '' }), character({ name: 'foo' }), main);
const pony = createPony(account({ _id: new Types.ObjectId('') }), character({ name: 'foo' }), main);
expect(pony.state).equal(EntityState.FacingRight);
});
@@ -44,7 +45,7 @@ describe('characterUtils', () => {
it('sets extra flag from state', () => {
const main: CharacterState = { ...defaultState, flags: CharacterStateFlags.Extra };
const pony = createPony(account({ _id: '' }), character({ name: 'foo' }), main);
const pony = createPony(account({ _id: new Types.ObjectId('') }), character({ name: 'foo' }), main);
expect(pony.options!.extra).true;
});
@@ -52,7 +53,7 @@ describe('characterUtils', () => {
it('sets held item from state', () => {
const main: CharacterState = { ...defaultState, hold: 'apple' };
const pony = createPony(account({ _id: '' }), character({ name: 'foo' }), main);
const pony = createPony(account({ _id: new Types.ObjectId('') }), character({ name: 'foo' }), main);
expect(pony.options!.hold).equal(entities.apple.type);
});
@@ -60,7 +61,9 @@ describe('characterUtils', () => {
it('ignores held item from state if type is invalid', () => {
const main: CharacterState = { ...defaultState, hold: 'does_not_exist' };
const pony = createPony(account({ _id: '' }), character({ name: 'foo' }), main);
const pony = createPony(account({ _id: new Types.ObjectId('')
}), character({ name: 'foo' }), main);
expect(pony.options!.hold).undefined;
});
@@ -143,7 +146,7 @@ describe('characterUtils', () => {
updatePony(entity1, account({ _id: genObjectId() }), character({ name: 'Foo', info: OFFLINE_PONY }));
updatePony(
entity2, account({ _id: '' }), character({ name: 'Bar', info: 'DAT/AADapSD/1wC7Li42QAJkJEAT8ADAAxADhAYQFGAQAA==' }));
entity2, account({ _id: new Types.ObjectId('') }), character({ name: 'Bar', info: 'DAT/AADapSD/1wC7Li42QAJkJEAT8ADAAxADhAYQFGAQAA==' }));
expect(entity1.canFly).false;
expect(entity2.canFly).true;
+2 -2
View File
@@ -99,7 +99,7 @@ describe('liveEndPoint', () => {
const find = stubFind([{ _id: 'aaa' }, { _id: 'bbb' }]);
return liveEndPoint.getAll()
.then(() => assert.calledWithMatch(find, { updatedAt: { $gt: new Date(0) } }, '_id name desc'));
.then(() => assert.calledWithMatch(find as any, { updatedAt: { $gt: new Date(0) } }, '_id name desc'));
});
it('passes given timestamp to find method', () => {
@@ -107,7 +107,7 @@ describe('liveEndPoint', () => {
const find = stubFind([{ _id: 'aaa' }, { _id: 'bbb' }]);
return liveEndPoint.getAll(timestamp)
.then(() => assert.calledWithMatch(find, { updatedAt: { $gt: new Date(timestamp) } }, '_id name desc'));
.then(() => assert.calledWithMatch(find as any, { updatedAt: { $gt: new Date(timestamp) } }, '_id name desc'));
});
describe('if items exceed limit', () => {
+1 -1
View File
@@ -12,7 +12,7 @@ describe('originUtils', () => {
beforeEach(() => {
clock = useFakeTimers();
update = stub(Account, 'update').returns({ exec: () => Promise.resolve() } as any);
update = stub(Account as any, 'update').returns({ exec: () => Promise.resolve() } as any);
});
afterEach(() => {
+8 -8
View File
@@ -55,11 +55,11 @@ describe('serverUtils', () => {
const id = genId();
expect(toPonyObject(character({
_id: Types.ObjectId(id),
_id: new Types.ObjectId(id),
name: 'foo',
desc: 'aaa',
info: 'info',
site: Types.ObjectId('000000000000000000000002'),
site: new Types.ObjectId('000000000000000000000002'),
tag: 'tag',
lastUsed: new Date(123),
}))).eql({
@@ -79,7 +79,7 @@ describe('serverUtils', () => {
const id = genId();
expect(toPonyObject(character({
_id: Types.ObjectId(id),
_id: new Types.ObjectId(id),
name: 'foo',
}))).eql({
id: id,
@@ -96,7 +96,7 @@ describe('serverUtils', () => {
it('sets hide support field', () => {
const output = toPonyObject(character({
_id: Types.ObjectId(genId()),
_id: new Types.ObjectId(genId()),
name: 'foo',
flags: CharacterFlags.HideSupport,
}));
@@ -106,7 +106,7 @@ describe('serverUtils', () => {
it('sets respawn at spawn field', () => {
const output = toPonyObject(character({
_id: Types.ObjectId(genId()),
_id: new Types.ObjectId(genId()),
name: 'foo',
flags: CharacterFlags.RespawnAtSpawn,
}));
@@ -124,11 +124,11 @@ describe('serverUtils', () => {
const id = genId();
expect(toPonyObjectAdmin(character({
_id: Types.ObjectId(id),
_id: new Types.ObjectId(id),
name: 'foo',
desc: 'aaa',
info: 'info',
site: Types.ObjectId('000000000000000000000001'),
site: new Types.ObjectId('000000000000000000000001'),
tag: 'tag',
lastUsed: new Date(123),
creator: 'foo bar',
@@ -156,7 +156,7 @@ describe('serverUtils', () => {
const id = genId();
expect(toSocialSite(auth({
_id: Types.ObjectId(id),
_id: new Types.ObjectId(id),
name: 'foo',
provider: 'github',
url: 'foo.com',
@@ -29,7 +29,6 @@ describe('SupporterInvitesService', () => {
countDocuments: stub(),
create: stub(),
deleteOne: stub(),
deleteMany: stub(),
updateMany: stub(),
} as any;
log = stub();
@@ -43,7 +42,7 @@ describe('SupporterInvitesService', () => {
describe('getInvites()', () => {
it('returns all invites from given client', async () => {
const client = mockClient();
model.find.withArgs({ source: client.account._id }).returns({
model.find.withArgs({ source: client.account._id } as any).returns({
exec: stub().resolves([
{ _id: 'foo', name: 'Foo', info: 'info', active: true, anotherField: 'xyz' },
])
@@ -292,7 +291,7 @@ describe('SupporterInvitesService', () => {
await service.uninvite(requester, 'foobar');
assert.calledWithMatch(model.deleteOne, { _id: 'foobar', source: requester.account._id });
assert.calledWithMatch(model.deleteOne as any, { _id: 'foobar', source: requester.account._id });
});
});
@@ -312,12 +311,12 @@ describe('SupporterInvitesService', () => {
{ _id: 'aaa', active: false, source: { supporter: SupporterFlags.Supporter1 } },
{ _id: 'bbb', active: true, source: { supporter: SupporterFlags.Supporter1 } },
];
model.find.withArgs({}, '_id active')
model.find.withArgs({} as any, '_id active')
.returns({
populate: stub().withArgs('source', '_id supporter patreon roles')
.returns({ lean: stub().returns(exec(data)) })
} as any);
model.deleteMany.returns({ exec: stub() } as any);
model.deleteOne.returns({ exec: stub() } as any);
model.updateMany.returns({ exec: stub() } as any);
await updateSupporterInvites(model as any);
@@ -331,7 +330,7 @@ describe('SupporterInvitesService', () => {
{ _id: 'bbb', active: true, source: {} },
];
model.find.returns({ populate: stub().returns({ lean: stub().returns(exec(data)) }) } as any);
model.deleteMany.returns({ exec: stub() } as any);
model.deleteOne.returns({ exec: stub() } as any);
model.updateMany.returns({ exec: stub() } as any);
await updateSupporterInvites(model as any);
@@ -345,7 +344,7 @@ describe('SupporterInvitesService', () => {
{ _id: 'bbb', active: true, source: {} },
];
model.find.returns({ populate: stub().returns({ lean: stub().returns(exec(data)) }) } as any);
model.deleteMany.returns({ exec: stub() } as any);
model.deleteOne.returns({ exec: stub() } as any);
model.updateMany.returns({ exec: stub() } as any);
await updateSupporterInvites(model as any);
@@ -360,7 +359,7 @@ describe('SupporterInvitesService', () => {
{ _id: 'bbb', active: false, source: {} },
];
model.find.returns({ populate: stub().returns({ lean: stub().returns(exec(data)) }) } as any);
model.deleteMany.returns({ exec: stub() } as any);
model.deleteOne.returns({ exec: stub() } as any);
model.updateMany.returns({ exec: stub() } as any);
await updateSupporterInvites(model as any);
@@ -370,12 +369,12 @@ describe('SupporterInvitesService', () => {
it('removes old inactive entries', async () => {
model.find.returns({ populate: stub().returns({ lean: stub().returns({ exec: stub() }) }) } as any);
model.deleteMany.returns({ exec: stub() } as any);
model.deleteOne.returns({ exec: stub() } as any);
clock.setSystemTime(123 * DAY);
await updateSupporterInvites(model as any);
assert.calledWithMatch(model.deleteMany, { active: false, updatedAt: { $lt: new Date(23 * DAY) } });
assert.calledWithMatch(model.deleteOne as any, { active: false, updatedAt: { $lt: new Date(23 * DAY) } });
});
});
});