import mongoose from 'mongoose' import { User } from '../index.js' import { matchEncryptedString } from '../../utils/crypto.js' export const userSchema = new mongoose.Schema({ email: { type: String, immutable: true, lowercase: true }, username: { type: String, immutable: true }, encryptedPassword: { type: String, minlength: [8, 'TOO_FEW_CHARACTERS'], required: [true, 'PASSWORD_REQUIRED'] }, role: { type: String, required: true }, linkedTo: mongoose.SchemaTypes.ObjectId, apartments: [mongoose.SchemaTypes.ObjectId], sharingAllowed: { type: Boolean, default: false }, lastLogin: { type: Date, default: null }, confirmationToken: { type: String, default: null }, confirmationExpireAt: { type: Date, default: null }, emailConfirmed: { type: Boolean, default: false }, resetToken: { type: String, default: null }, resetExpireAt: { type: Date, default: null }, lastResetRequest: { type: Date, default: null }, createdBy: mongoose.SchemaTypes.ObjectId, createdAt: { type: Date, immutable: true, default: () => Date.now() }, updatedAt: { type: Date, default: () => Date.now() } }) userSchema.methods.comparePassword = async function (password) { return matchEncryptedString(password, this.password) || false } userSchema.statics.verifyPasswordResetAndUpdate = async function (token, data) { const user = await this.findOne({ resetToken: token }) if (user) { return await this.findOneAndUpdate({ _id: user._id }, data, { new: true, runValidators: true }) } return null } userSchema.statics.createBuildingUser = async function (accessor, data) { const isOwner = await this.findOne({ _id: accessor }) if (isOwner) { const exists = await User.findOne({ username: data.username }) if (exists) return null return await this.create(data) } return null } userSchema.statics.createNewAccount = async function (email, data) { const exists = await User.findOne({ email }) if (exists) return null const user = await User.create(data) return user } userSchema.statics.findUserAndVerify = async function (emailOrUsername, password) { const byUsername = await this.findOne({ username: emailOrUsername }).exec() const byEmail = await this.findOne({ email: emailOrUsername }).exec() const user = byUsername || byEmail if (user && matchEncryptedString(password, user.encryptedPassword)) { return this.findOne({ $or: [{ username: user.username }, { email: user.email || '2ad98ac316a093cd32f2b05296d98e3b' }] }) } return null } export default mongoose.model('User', userSchema)