user database improvements
This commit is contained in:
parent
5b95593d9c
commit
a9be4068b1
@ -1,5 +1,6 @@
|
||||
const { Collection } = require("@discordjs/collection");
|
||||
const { ObjectId } = require("mongodb");
|
||||
const { inspect } = require('node:util');
|
||||
|
||||
const { AbstractUserDatabase } = require("../interfaces/");
|
||||
const { User } = require("../structures");
|
||||
@ -25,6 +26,7 @@ class UserDatabase extends AbstractUserDatabase {
|
||||
async fetchUser (id, force = false) {
|
||||
|
||||
if (!force && this.cache.has(id)) return this.cache.get(id);
|
||||
if (id.includes('temp')) return null;
|
||||
|
||||
const data = await this.collection.findOne({ _id: ObjectId(id) });
|
||||
if (!data) return null;
|
||||
@ -36,12 +38,12 @@ class UserDatabase extends AbstractUserDatabase {
|
||||
|
||||
}
|
||||
|
||||
async findUser (name) {
|
||||
async findUser (username) {
|
||||
|
||||
let user = this.cache.find(u => u.name.toLowerCase() === name.toLowerCase());
|
||||
let user = this.cache.find(u => u.username.toLowerCase() === username.toLowerCase());
|
||||
if (user) return Promise.resolve(user);
|
||||
|
||||
const data = await this.collection.findOne({ name }, { collation: { locale: 'en', strength: 2 } });
|
||||
const data = await this.collection.findOne({ username }, { collation: { locale: 'en', strength: 2 } });
|
||||
if (!data) return null;
|
||||
|
||||
user = this._createUser(data);
|
||||
@ -72,29 +74,61 @@ class UserDatabase extends AbstractUserDatabase {
|
||||
|
||||
/**
|
||||
* Retrieves or creates a user based on a discord profile
|
||||
*
|
||||
* TODO: Somehow generalise this for any external OAuth profiles, passport normalises most profiles to the same fields
|
||||
* @param {*} profile
|
||||
* @return {*}
|
||||
* @memberof UserDatabase
|
||||
*/
|
||||
async userFromDiscord (profile) {
|
||||
|
||||
// TODO: Figure out what to do when a user already exists with the same username as the discord profile
|
||||
// Will break when logging in with discord to an existing account that doesn't have a linked account
|
||||
let user = this.cache.find((u) => u.externalProfiles.discord?.id === profile.id);
|
||||
if (user) return Promise.resolve(user);
|
||||
|
||||
const data = await this.collection.findOne({ 'externalProfiles.discord.id': profile.id });
|
||||
if (data) user = this._createUser(data);
|
||||
else {
|
||||
if (data) return Promise.resolve(this._createUser(data));
|
||||
|
||||
// If a user with the same username already exists, force the holder of the discord account to create a new account or log in to the other account and link them
|
||||
const existing = await this.collection.findOne({ username: profile.username }, { collation: { locale: 'en', strength: 2 } });
|
||||
if (existing) {
|
||||
const temp = this._createUser({ type: 'user', temporary: true, displayName: profile.username });
|
||||
temp.addExternalProfile('discord', profile);
|
||||
// TODO: need to store the user somewhere shared across the shards
|
||||
this.cache.set(temp.id, temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
this.logger.info(`Creating new user from Discord profile: ${profile.username} (${profile.id})`);
|
||||
user = this._createUser({ type: 'user', name: profile.username });
|
||||
user.addExternalProfile('discord', profile);
|
||||
await user.save();
|
||||
this.cache.set(user.id, user);
|
||||
}
|
||||
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new user from username and password
|
||||
*
|
||||
* @param {*} username
|
||||
* @param {*} password
|
||||
* @memberof UserDatabase
|
||||
*/
|
||||
async createUser (username, password) {
|
||||
|
||||
const user = this._createUser({
|
||||
username,
|
||||
type: 'user'
|
||||
});
|
||||
await user.setPassword(password);
|
||||
await this.updateUser(user);
|
||||
this.cache.set(user.id, user);
|
||||
return user;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates user entry
|
||||
*
|
||||
@ -102,14 +136,25 @@ class UserDatabase extends AbstractUserDatabase {
|
||||
* @memberof UserDatabase
|
||||
*/
|
||||
async updateUser (user) {
|
||||
if (user.id) await this.collection.updateOne({ _id: ObjectId(user.id) }, user.json);
|
||||
const { json } = user;
|
||||
this.logger.debug(`Storing user ${inspect(user.json)}`);
|
||||
if (user._id) await this.collection.updateOne({ _id: ObjectId(user._id) }, json);
|
||||
else {
|
||||
const result = await this.collection.insertOne(user.json);
|
||||
user.id = result.insertedId;
|
||||
const result = await this.collection.insertOne(json);
|
||||
user._id = result.insertedId;
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for creating user object
|
||||
* Not strictly necessary but it's here in case the constructor changes in a way that can easily be wrapped
|
||||
*
|
||||
* @param {object} data Raw user data
|
||||
* @return {user}
|
||||
* @memberof UserDatabase
|
||||
*/
|
||||
_createUser (data) {
|
||||
if (!data) throw new Error(`Missing data to create user`);
|
||||
return new User(this, data);
|
||||
|
Loading…
Reference in New Issue
Block a user