From dddfe6da75f67334c8e07a95dd81f30be41e577f Mon Sep 17 00:00:00 2001 From: "Navy.gif" Date: Tue, 30 Jan 2024 11:06:50 +0200 Subject: [PATCH] bugfix to accidental privilege escalation --- src/server/components/UserDatabase.ts | 20 +++++++++++-------- .../interfaces/UserDatabaseInterface.ts | 1 + 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/server/components/UserDatabase.ts b/src/server/components/UserDatabase.ts index 086df2f..dad78e6 100644 --- a/src/server/components/UserDatabase.ts +++ b/src/server/components/UserDatabase.ts @@ -149,18 +149,20 @@ class UserDatabase implements UserDatabaseInterface return true; } - async fetchUsers ({ ids, page, pageSize, name, roleId }: UserQuery = {}): Promise + async fetchUsers ({ ids, page, pageSize, name, roleId, id }: UserQuery = {}): Promise { const query: Filter = {}; if (ids) ids = ids.map(r => typeof r === 'string' ? r : r.id as string); if (ids?.length) - query._id = { $in: ids.map(id => new ObjectId(id as string)) }; + query._id = { $in: ids.map(i => new ObjectId(i as string)) }; + else if (id) + query._id = new ObjectId(id); // Does not scale, but works for our users collection since it should always remain relatively small if (name) - query.name = { $regex: name, $options: 'i' }; + query.name = { $regex: `^${name}$`, $options: 'i' }; const findOptions: {limit?: number, skip?: number} = {}; if (typeof page !== 'undefined' && typeof pageSize !== 'undefined') @@ -184,7 +186,7 @@ class UserDatabase implements UserDatabaseInterface { if (user.roles?.length) user.roles = roles.filter(r => user.roles?.includes(r.id)); - u = this._createUser(user); + u = await this._createUser(user); if (!this.#disableCache) this.#cache.set(u.id, u); } @@ -607,7 +609,7 @@ class UserDatabase implements UserDatabaseInterface * @return {User} * @memberof UserDatabase */ - private _createUser (data: UserData & { _id?: ObjectId }): User + private async _createUser (data: UserData & { _id?: ObjectId }): Promise { if (!data) throw new Error('Missing data to create user'); @@ -616,9 +618,11 @@ class UserDatabase implements UserDatabaseInterface if (!data.id) data.id = new ObjectId(); - // if (data.roles) { - // data.roles = data.roles.map(role => this.#cache.get(role._id) || this._createRole(role as RoleData)); - // } + if (data.roles?.every(r => typeof r === 'string')) + { + const roles = await this.fetchRoles({ ids: data.roles }); + data.roles = roles; + } const user = new User(this.#server, data); return user; diff --git a/src/server/interfaces/UserDatabaseInterface.ts b/src/server/interfaces/UserDatabaseInterface.ts index 86c6a2e..d086c9d 100644 --- a/src/server/interfaces/UserDatabaseInterface.ts +++ b/src/server/interfaces/UserDatabaseInterface.ts @@ -4,6 +4,7 @@ import { Role, User, UserApplication } from '../structures/index.js'; import Entity from './Entity.js'; export type Query = { + id?: string, ids?: (string | T | TData)[], page?: number, pageSize?: number,