Recoded the dbUser and its collection class. StoredPlayer and StoredPlayerCollection are also finished

This commit is contained in:
Daniel Ledda
2020-07-03 23:34:57 +02:00
parent 40a0d7289a
commit 0bddaa524b
12 changed files with 280 additions and 326 deletions

View File

@@ -1,6 +1,3 @@
- Make a whole new class for each model called "Player", "DbUser", etc. and wrap mongoose completely.
- Create a corresponding namespace "PlayerCollection", "DbUserCollection", etc. for the database model itself and its
corresponding methods.
- Decide on whether to always use the namespace to call methods and pass an id, with the returned objects "Player", - Decide on whether to always use the namespace to call methods and pass an id, with the returned objects "Player",
"DbUser", etc. all being immutable object copies with limited attributes and no methods, or actually create extra "DbUser", etc. all being immutable object copies with limited attributes and no methods, or actually create extra
classes that have methods that can be called (right now thinking the first idea is better). classes that have methods that can be called (right now thinking the first idea is better).

View File

@@ -1,6 +1,6 @@
import DbUser, {IDbUser, IDbUserDoc} from "../models/dbUser"; import DbUser, {IDbUser, IDbUserDoc} from "../models/dbUser_old";
import {RequestHandler} from "express"; import {RequestHandler} from "express";
import {IPlayer} from "../models/player"; import {IPlayer} from "../models/StoredPlayer";
export const whoAmI: RequestHandler = async (req, res) => { export const whoAmI: RequestHandler = async (req, res) => {
if (req.isAuthenticated()) { if (req.isAuthenticated()) {

View File

@@ -1,5 +1,5 @@
import passport from "passport"; import passport from "passport";
import DbUser from "../models/dbUser"; import DbUser from "../models/dbUser_old";
import {RequestHandler} from "express"; import {RequestHandler} from "express";
export const showLoginPage: RequestHandler = (req, res) => { export const showLoginPage: RequestHandler = (req, res) => {

View File

@@ -1,6 +1,6 @@
import DbUser, { IDbUser } from "../models/dbUser"; import DbUser, { IDbUser } from "../models/dbUser_old";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import Player, { IPlayer } from "../models/player"; import Player, { IPlayer } from "../models/StoredPlayer";
const DEFAULT_RULESET = "DEFAULT_RULESET"; const DEFAULT_RULESET = "DEFAULT_RULESET";
const UPPER_BONUS_THRESHOLD = 63; const UPPER_BONUS_THRESHOLD = 63;

View File

@@ -39,6 +39,7 @@ app.locals = {
initialisePassport(); initialisePassport();
app.use(passport.initialize()); app.use(passport.initialize());
app.use(passport.session()); app.use(passport.session());
app.use(Settings.serverRoot + "/static", express.static("static")); app.use(Settings.serverRoot + "/static", express.static("static"));
app.use(Settings.serverRoot, MainRouter); app.use(Settings.serverRoot, MainRouter);

View File

@@ -6,7 +6,7 @@ import {
} from "./stats"; } from "./stats";
import { import {
getMongoObjectCollection, getMongoObjectCollection,
MongoStoredObject, MongoStoredObjectCollection, StoredObject, StoredObjectCollection, MongoStoredObject, MongoStoredObjectCollection, StoredObject, StoredObjectCollection, tryQuery,
} from "./utils"; } from "./utils";
import {CellValue} from "../controllers/statsController"; import {CellValue} from "../controllers/statsController";
import mongo from "mongodb"; import mongo from "mongodb";
@@ -24,22 +24,22 @@ export interface StoredPlayerData {
} }
interface StoredPlayerCollection extends StoredObjectCollection<StoredPlayer> { interface StoredPlayerCollection extends StoredObjectCollection<StoredPlayer> {
findById(id: string): Promise<StoredPlayer>;
} }
class MongoStoredPlayerCollection class MongoStoredPlayerCollection
extends MongoStoredObjectCollection<MongoStoredPlayer, StoredPlayer> extends MongoStoredObjectCollection<StoredPlayerData, StoredPlayer>
implements StoredPlayerCollection { implements StoredPlayerCollection {
private updater: PlayerStatsUpdater; private updater: PlayerStatsUpdater;
constructor(collectionClient: mongo.Collection) { constructor(collectionClient: mongo.Collection) {
super(collectionClient); super(collectionClient, MongoStoredPlayer);
this.updater = new PlayerStatsUpdater(); this.updater = new PlayerStatsUpdater();
} }
async findById(id: string): Promise<StoredPlayer> { newPlayer(nick: string): Promise<StoredPlayer> {
const data = await this.findObjectById(id); return tryQuery(async () => {
return new MongoStoredPlayer(data); return this.create({nick});
});
} }
} }
@@ -49,7 +49,7 @@ export interface StoredPlayer extends StoredObject {
updateStats(results: PlayerGameResults & {outcome: OutcomeType}, ruleset: Ruleset): Promise<void>; updateStats(results: PlayerGameResults & {outcome: OutcomeType}, ruleset: Ruleset): Promise<void>;
} }
class MongoStoredPlayer extends MongoStoredObject<StoredPlayerData> implements StoredPlayer { export class MongoStoredPlayer extends MongoStoredObject<StoredPlayerData> implements StoredPlayer {
constructor(data: StoredPlayerData) { constructor(data: StoredPlayerData) {
super(data); super(data);
} }

215
src/models/StoredUser.ts Normal file
View File

@@ -0,0 +1,215 @@
import {SupportedLang} from "../enums";
import Player, {MongoStoredPlayer, StoredPlayer, StoredPlayerData} from "./StoredPlayer";
import {AccountStats} from "./stats";
import {SavedGameData, StoredSavedGame} from "./savedGame";
import {
GenericModelError, getMongoObjectCollection,
MongoStoredObject,
MongoStoredObjectCollection,
StoredObject,
StoredObjectCollection,
StoredObjectId,
tryQuery
} from "./utils";
import mongo from "mongodb";
import StoredPlayers from "./StoredPlayer";
import bcrypt from "bcrypt";
export class CredentialsTakenError extends Error {
public emailExists: boolean;
public usernameExists: boolean;
constructor(usernameExists: boolean, emailExists: boolean) {
super("Registration failure:" + usernameExists + emailExists);
this.usernameExists = usernameExists;
this.emailExists = emailExists;
this.name = "CredentialsTakenError";
}
}
export interface StoredUserData {
_id: string;
username: string;
email: string;
password: string;
lang: SupportedLang;
friends: string[];
player: StoredObjectId;
guests: StoredObjectId[];
accountStats: AccountStats;
savedGames: SavedGameData[];
}
export interface StoredUser extends StoredObject {
getLoginDetails(): Promise<LoginDetails>
preferredLang(): Promise<SupportedLang>;
getFriends(): Promise<StoredUser[]>;
getGuests(): Promise<StoredPlayer[]>;
getAccountStats(): Promise<AccountStats>;
getSavedGames(): Promise<StoredSavedGame[]>;
getMainPlayerInfo(): Promise<StoredPlayer>;
findGuestByNick(nick: string): Promise<StoredPlayer | null>;
changeLang(lang: SupportedLang): Promise<void>;
addGame(game: any): Promise<void>;
getGuestById(guestId: string): Promise<StoredPlayer>;
addGuest(nick: string): Promise<StoredPlayer>;
updateGuest(guestParams: GuestUpdateParams): Promise<StoredPlayer>;
deleteGuest(guestId: string): Promise<StoredPlayer | null>;
}
type GuestUpdateParams = { id: string, newNick: string };
type LoginDetails = { username: string, email: string, password: string };
class MongoStoredUser extends MongoStoredObject<StoredUserData> implements StoredUser {
constructor(data: StoredUserData) {
super(data);
}
async getLoginDetails(): Promise<LoginDetails> {
return {username: this.data.username, email: this.data.email, password: this.data.password};
}
async preferredLang(): Promise<SupportedLang> {
return this.data.lang;
}
async getFriends(): Promise<StoredUser[]> {
const friends: StoredUser[] = [];
for (const friendId in this.data.guests) {
const foundFriend = await StoredUsers.findById(friendId) as StoredUser;
friends.push(foundFriend);
}
return friends;
}
async getGuests(): Promise<StoredPlayer[]> {
const guests: StoredPlayer[] = [];
for (const guestId in this.data.guests) {
const foundGuest = await StoredPlayers.findById(guestId) as StoredPlayer;
guests.push(foundGuest);
}
return guests;
}
async getAccountStats(): Promise<AccountStats> {
return this.data.accountStats;
}
async getSavedGames(): Promise<StoredSavedGame[]> {
return this.data.savedGames.map(savedGame => new MongoStoredSavedGame(savedGame));
}
async getMainPlayerInfo(): Promise<StoredPlayer> {
return StoredPlayers.findById(this.data.player) as Promise<StoredPlayer>;
}
async findGuestByNick(nick: string): Promise<StoredPlayer | null> {
const guests = await this.getGuests();
for (const guest of guests) {
if (guest.nick() == nick) {
return guest;
}
}
return null;
}
async changeLang(lang: SupportedLang): Promise<void> {
this.data.lang = lang;
}
async addGame(game: SavedGameData): Promise<void> {
this.data.savedGames.push(game);
}
getGuestById(guestId: string): Promise<StoredPlayer> {
return StoredPlayers.findById(guestId) as Promise<StoredPlayer>;
}
async addGuest(nick: string): Promise<StoredPlayer> {
const newGuest = await StoredPlayers.newPlayer(nick);
this.data.guests.push(newGuest.id());
return newGuest;
}
async updateGuest(guestParams: GuestUpdateParams): Promise<StoredPlayer> {
const guest = await StoredPlayers.findById(guestParams.id) as StoredPlayer;
await guest.setNick(guestParams.newNick);
await StoredPlayers.save(guest);
return guest;
}
async deleteGuest(guestId: string): Promise<StoredPlayer | null> {
return StoredPlayers.deleteById(guestId);
}
}
export interface StoredUserCollection extends StoredObjectCollection<StoredUser> {
findByEmail(emailQuery: string): Promise<StoredUser | null>;
registerUser(loginDetails: LoginDetails): Promise<StoredUser>;
userWithEmailExists(email: string): Promise<boolean>;
userWithUsernameExists(username: string): Promise<boolean>;
getSerializedAuthUser(id: string): Promise<StoredUser>;
}
class MongoStoredUserCollection extends MongoStoredObjectCollection<StoredUserData, StoredUser> implements StoredUserCollection {
constructor(collectionClient: mongo.Collection) {
super(collectionClient, MongoStoredUser);
}
findById(id: string): Promise<StoredUser | null> {
return this.findObjectById(id);
}
findByEmail(emailQuery: string): Promise<StoredUser | null> {
return tryQuery(async () =>
await this.findObjectByAttribute("email", emailQuery)
);
}
private async addNewUser(loginDetails: LoginDetails): Promise<StoredUser> {
const newPlayer = await StoredPlayers.newPlayer(loginDetails.username);
return this.create({
username: loginDetails.username,
email: loginDetails.email,
password: loginDetails.password,
lang: SupportedLang.gb,
player: newPlayer.id()
});
}
async registerUser(loginDetails: LoginDetails): Promise<StoredUser> {
const usernameTaken = await this.userWithUsernameExists(loginDetails.username);
const emailTaken = await this.userWithEmailExists(loginDetails.email);
if (usernameTaken || emailTaken) {
throw new CredentialsTakenError(usernameTaken, emailTaken);
}
else {
const hashedPassword = await bcrypt.hash(loginDetails.password, 10);
return tryQuery(() =>
this.addNewUser({...loginDetails, password: hashedPassword})
);
}
}
async userWithEmailExists(email: string): Promise<boolean> {
const object = await this.findObjectByAttribute("email", email);
return object !== null;
}
async userWithUsernameExists(username: string): Promise<boolean> {
const object = await this.findObjectByAttribute("username", username);
return object !== null;
}
async getSerializedAuthUser(id: string): Promise<StoredUser> {
const dbResult = await this.findById(id);
if (dbResult) {
return dbResult;
}
else {
throw new GenericModelError("User not found!");
}
}
}
const StoredUsers = new MongoStoredUserCollection(getMongoObjectCollection("users"));
export default StoredUsers;

View File

@@ -1,263 +0,0 @@
import mongoose, {Model} from "mongoose";
import Player, {IPlayer, IPlayerDoc, PlayerSchema} from "./player";
import {AccountStatsSchema, IAccountStats, IAccountStatsDoc} from "./stats";
import SavedGame, {ISavedGame, ISavedGameDoc, SavedGameSchema} from "./savedGame";
import bcrypt from "bcrypt";
import {SupportedLang} from "../enums";
import {GenericModelError, globalSchemaOptions, ModelParameterError, tryQuery} from "./utils";
import {GameSubmission} from "../controllers/statsController";
export class CredentialsTakenError extends Error {
public emailExists: boolean;
public usernameExists: boolean;
constructor(usernameExists: boolean, emailExists: boolean) {
super("Registration failure:" + usernameExists + emailExists);
this.usernameExists = usernameExists;
this.emailExists = emailExists;
this.name = "CredentialsTakenError";
}
}
export interface IDbUser {
id: string;
username: string;
email: string;
password: string;
lang?: SupportedLang;
friends?: IDbUser[];
player?: IPlayer;
guests?: IPlayer[];
accountStats?: IAccountStats;
savedGames?: ISavedGame[];
getMainPlayerInfo(): Promise<IPlayer>;
findGuestByNick(nick: string): Promise<IPlayer | null>;
changeLang(lang: SupportedLang): void;
addGame(game: any): Promise<string | null>;
getGuests(): Promise<IPlayer[]>;
getGuest(guestId: string): Promise<IPlayer>;
addGuest(nick: string): Promise<IPlayer>;
updateGuest(guestParams: GuestUpdateParams): Promise<IPlayer>;
deleteGuest(guestId: string): Promise<IPlayer>;
}
type GuestUpdateParams = {id: string, newNick: string};
export interface IDbUserDoc extends mongoose.Document {
id: string;
username: string;
email: string;
password: string;
lang: SupportedLang;
friends: IDbUserDoc[];
player: IPlayerDoc;
guests: IPlayerDoc[];
accountStats: IAccountStatsDoc;
savedGames: mongoose.Types.Array<ISavedGameDoc>;
getMainPlayerInfo(): Promise<IPlayer>;
findGuestByNick(nick: string): Promise<IPlayer | null>;
changeLang(lang: SupportedLang): void;
addGame(game: any): Promise<string | null>;
getGuests(): Promise<IPlayer[]>;
getGuest(guestId: string): Promise<IPlayer>;
addGuest(nick: string): Promise<IPlayer>;
updateGuest(guestParams: GuestUpdateParams): Promise<IPlayer>;
deleteGuest(guestId: string): Promise<IPlayer>;
}
export interface IDbUserModel extends mongoose.Model<IDbUserDoc> {
findByEmail(emailQuery: string): IDbUserDoc;
addNewUser(user: IDbUser): IDbUserDoc;
registerUser(username: string, email: string, password: string): IDbUserDoc;
userWithEmailExists(email: string): Promise<boolean>;
userWithUsernameExists(username: string): Promise<boolean>;
getSerializedAuthUser(id: string): Promise<IDbUser>;
incrementTimesNoWinner(id: string): Promise<void>;
incrementGamesPlayed(id: string): Promise<void>;
}
export const DbUserSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
lang: { type: String, required: true },
friends: {type: [mongoose.Schema.Types.ObjectId], default: []},
player: {type: PlayerSchema, required: true, unique: true},
guests: {type: [PlayerSchema], default: []},
accountStats: {type: AccountStatsSchema, default: () => ({}) },
savedGames: {type: [SavedGameSchema], default: []},
}, {...globalSchemaOptions});
DbUserSchema.statics.findByEmail = async function (emailQuery: string) {
return tryQuery(() =>
this.findOne({email: emailQuery})
);
};
DbUserSchema.statics.addNewUser = async function (username: string, email: string, hashedPw: string) {
const player = new Player( { nick: username });
return tryQuery(() =>
this.create({
username: username,
email: email,
password: hashedPw,
lang: SupportedLang.gb,
player
})
);
};
DbUserSchema.statics.registerUser = async function (username: string, email: string, password: string) {
const usernameTaken = await this.userWithUsernameExists(username);
const emailTaken = await this.userWithEmailExists(email);
if (usernameTaken || emailTaken) {
throw new CredentialsTakenError(usernameTaken, emailTaken);
}
else {
const hashedPassword = await bcrypt.hash(password, 10);
return tryQuery(() =>
this.addNewUser(username, email, hashedPassword)
);
}
};
DbUserSchema.statics.userWithEmailExists = async function (email: string): Promise<boolean> {
return tryQuery(() => this.exists({email}));
};
DbUserSchema.statics.userWithUsernameExists = async function (username: string): Promise<boolean> {
return tryQuery(() => this.exists({username}));
};
DbUserSchema.statics.getSerializedAuthUser = async function (id: string): Promise<IDbUser> {
return tryQuery(() => {
return DbUser.findById(id, {id: 1, username: 1, password: 1, lang: 1, email: 1});
});
};
DbUserSchema.statics.incrementTimesNoWinner = async function (id: string): Promise<void> {
return tryQuery(() => {
return DbUser.findById(id, {id: 1, username: 1, password: 1, lang: 1, email: 1});
});
};
DbUserSchema.statics.incrementGamesPlayed = async function (id: string): Promise<void> {
return tryQuery(async () => {
const user = await DbUser.findById(id);
user.accountStats.gamesPlayed =
});
};
DbUserSchema.methods.getGuests = async function (this: IDbUser): Promise<IPlayer[]> {
const user: IDbUserDoc = await tryQuery(async () => {
return DbUser.findById(this.id, {"guests.nick": 1, "guests._id": 1}).exec();
});
return user.guests;
};
DbUserSchema.methods.getGuest = async function (this: IDbUser, guestId: string): Promise<IPlayer> {
return tryQuery(async () => {
const user = await DbUser.findById(this.id, {guests: {$elemMatch: {_id: guestId}}});
if (user!.guests.length > 0) {
return user!.guests[0];
}
else {
throw new ModelParameterError("Guest with ID " + guestId + " doesn't exist!");
}
});
};
DbUserSchema.methods.findGuestByNick = async function (this: IDbUser, guestNick: string): Promise<IPlayer | null> {
return tryQuery(async () => {
const user = await DbUser.findById(this.id, {guests: {$elemMatch: {nick: guestNick}}});
if (user!.guests.length > 0) {
return user!.guests[0];
}
else {
return null;
}
});
};
DbUserSchema.methods.addGuest = async function (this: IDbUser, newGuestNick: string): Promise<IPlayer> {
if (this.username !== newGuestNick) {
const guestLookup = await this.findGuestByNick(newGuestNick);
if (!guestLookup) {
return saveGuest(this, newGuestNick);
}
else {
throw new ModelParameterError(`Cannot add a guest with the same name of another guest in this account.`);
}
}
else {
throw new ModelParameterError("Cannot add a guest with the same name as the account holder's username.")
}
};
async function saveGuest(user: IDbUser, newGuestNick: string): Promise<IPlayer> {
const newGuest: IPlayerDoc = new Player();
newGuest.nick = newGuestNick;
await tryQuery(() => {
DbUser.findByIdAndUpdate(user.id, {$push: {guests: newGuest}}).exec();
});
return newGuest;
}
DbUserSchema.methods.updateGuest = async function (this: IDbUser, guestParams: GuestUpdateParams): Promise<IPlayer> {
return tryQuery(async () => {
const user = await DbUser.findById(this.id);
const updatableGuest = user!.guests.find(guest => guest.id === guestParams.id);
if (updatableGuest) {
updatableGuest.nick = guestParams.newNick;
await user!.save();
return updatableGuest;
}
else {
throw new ModelParameterError("Guest with ID " + guestParams.id + " doesn't exist!");
}
});
};
DbUserSchema.methods.deleteGuest = async function (this: IDbUser, guestId: string): Promise<IPlayer> {
return tryQuery(async () => {
const user = await DbUser.findById(this.id);
const deleteGuestIndex = user!.guests.findIndex(guest => guest.id === guestId);
if (deleteGuestIndex !== -1) {
const deletedGuest = user!.guests[deleteGuestIndex];
user!.guests[deleteGuestIndex].remove();
await user!.save();
return deletedGuest;
}
else {
throw new ModelParameterError("Guest with ID " + guestId + " doesn't exist!");
}
});
};
DbUserSchema.methods.addGame = async function (submission: GameSubmission): Promise<ISavedGame> {
const newGame = await SavedGame.createFromGameSubmission(submission);
await tryQuery(() => {
DbUser.findByIdAndUpdate(this.id, {$push: {savedGames: newGame}}).exec();
});
return newGame;
};
DbUserSchema.methods.changeLang = async function (lang: SupportedLang): Promise<void> {
if (lang in SupportedLang) {
await tryQuery(() =>
DbUser.findByIdAndUpdate(this.id, {lang: lang})
);
}
else {
throw new ModelParameterError(lang + " is not a supported language code!");
}
};
DbUserSchema.methods.getMainPlayerInfo = async function (): Promise<IPlayer> {
const user = await tryQuery(() =>
DbUser.findById(this.id, {"player.nick": 1, "player._id": 1}).exec()
);
return user.player;
};
const DbUser = mongoose.model<IDbUserDoc, IDbUserModel>("DbUser", DbUserSchema);
export default DbUser;

View File

@@ -1,45 +1,20 @@
import mongoose, {Types} from "mongoose"; import mongoose, {Types} from "mongoose";
import Player, {IPlayer} from "./player"; import Player, {IPlayer} from "./StoredPlayer";
import {GameSubmission} from "../controllers/statsController"; import {GameSubmission} from "../controllers/statsController";
import {tryQuery, globalSchemaOptions} from "./utils"; import {tryQuery, globalSchemaOptions, StoredObjectCollection, StoredObject} from "./utils";
import DbUser from "./dbUser"; import DbUser from "./dbUser_old";
import {Ruleset} from "../rulesets";
export interface ISavedGame { export interface SavedGameData {
id: string; id: string;
//rulesetUsed?: ruleset; rulesetUsed: RulesetData;
players: mongoose.Types.ObjectId[]; players: mongoose.Types.ObjectId[];
results: any[]; results: [];
} }
export interface ISavedGameDoc extends mongoose.Document { export interface StoredSavedGame extends StoredObject {
//rulesetUsed: mongoose.Types.ObjectId[];
id: string;
players: mongoose.Types.Array<mongoose.Types.ObjectId>;
results: mongoose.Types.Array<mongoose.Types.Subdocument>;
} }
export interface ISavedGameModel extends mongoose.Model<ISavedGameDoc> { export interface StoredSavedGameCollection extends StoredObjectCollection<StoredSavedGame> {
// virtual static methods createFromGameSubmission(submission: GameSubmission): Promise<StoredSavedGame>;
createFromGameSubmission(submission: GameSubmission): Promise<ISavedGameDoc>;
} }
export const SavedGameSchema = new mongoose.Schema({
//rulesetUsed: [mongoose.Schema.Types.ObjectId],
players: [mongoose.Schema.Types.ObjectId],
results: [mongoose.Schema.Types.Mixed],
}, {
timestamps: true,
...globalSchemaOptions
});
SavedGameSchema.statics.createFromGameSubmission = async function(submission: GameSubmission) {
const newGame = new SavedGame();
newGame.results.addToSet(...submission.results);
await tryQuery(async () => {
newGame.players.addToSet(...submission.players.map(player => player.id));
});
return newGame;
};
const SavedGame = mongoose.model<ISavedGameDoc, ISavedGameModel>("SavedGame", SavedGameSchema);
export default SavedGame;

View File

@@ -18,26 +18,55 @@ export function getMongoObjectCollection(collectionName: string) {
} }
} }
export type StoredObjectId = string;
export interface StoredObjectCollection<K> { export interface StoredObjectCollection<K> {
findById(id: string): Promise<K>; findById(id: string): Promise<K | null>;
} }
export abstract class MongoStoredObjectCollection<T extends MongoStoredObject<any>, K extends StoredObject> implements StoredObjectCollection<K> { export abstract class MongoStoredObjectCollection<D, K extends StoredObject> implements StoredObjectCollection<K> {
protected mongoDbClientCollection: mongo.Collection; protected mongoDbClientCollection: mongo.Collection;
protected constructor(collectionClient: mongo.Collection) { protected MongoStoredObject: new(data: D, ...args: any[]) => K;
protected constructor(collectionClient: mongo.Collection, objectConstructor: new (data: D, ...args: any[]) => K) {
this.mongoDbClientCollection = collectionClient; this.mongoDbClientCollection = collectionClient;
this.MongoStoredObject = objectConstructor;
} }
protected async findObjectById(id: string): Promise<any | null> { protected async findObjectById(id: string): Promise<any | null> {
return this.mongoDbClientCollection!.findOne({_id: id}); return tryQuery(async () =>
await this.mongoDbClientCollection.findOne({_id: id})
);
} }
abstract async findById(id: string): Promise<K>; protected async findObjectByAttribute(attribute: string, value: any): Promise<any | null> {
return tryQuery(async () =>
await this.mongoDbClientCollection.findOne({attribute: value})
);
}
async save(...objects: T[]): Promise<void> { protected async create(objectData: Partial<D>): Promise<K> {
for (const object of objects) { return tryQuery(async () =>
await this.mongoDbClientCollection.findOneAndUpdate({_id: object.id()}, {...object.rawData()}); await this.mongoDbClientCollection.insertOne(objectData)
} );
}
async deleteById(objectId: StoredObjectId): Promise<K | null> {
const deletedObject = this.findById(objectId);
await this.mongoDbClientCollection.deleteOne({_id: objectId});
return deletedObject;
}
async findById(id: string): Promise<K | null> {
const data = await this.findObjectById(id);
return new this.MongoStoredObject(data);
};
async save(...objects: K[]): Promise<void> {
await tryQuery(async () => {
for (const object of objects) {
await this.mongoDbClientCollection.findOneAndUpdate({_id: object.id()}, {...object.rawData()});
}
});
} }
} }

View File

@@ -1,7 +1,7 @@
import passport from "passport"; import passport from "passport";
import {Strategy as LocalStrategy, VerifyFunction} from "passport-local"; import {Strategy as LocalStrategy, VerifyFunction} from "passport-local";
import bcrypt from "bcrypt"; import bcrypt from "bcrypt";
import DbUser, {IDbUser} from "./models/dbUser"; import DbUser, {IDbUser} from "./models/dbUser_old";
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from "express";
export const requireAuthenticated = (req: Request, res: Response, next: NextFunction) => { export const requireAuthenticated = (req: Request, res: Response, next: NextFunction) => {

View File

@@ -1,7 +1,7 @@
import express from "express"; import express from "express";
import {requireAuthenticated} from "../passport-config"; import {requireAuthenticated} from "../passport-config";
import routers from "./routers"; import routers from "./routers";
import {IDbUser} from "../models/dbUser"; import {IDbUser} from "../models/dbUser_old";
import {ModelParameterError} from "../models/utils"; import {ModelParameterError} from "../models/utils";
const router = express.Router(); const router = express.Router();