nhb-express
Version:
Minimal Express + TypeScript scaffolder with modular structure and flexible stack choices.
107 lines (96 loc) • 2.21 kB
text/typescript
import { ErrorWithStatus } from '@/classes/ErrorWithStatus';
import { USER_ROLES } from '@/constants';
import type { IUserDoc, IUserModel } from '@/modules/user/user.types';
import type { TEmail } from '@/types';
import { hashPassword } from '@/utilities/authUtilities';
import { Schema, model } from 'mongoose';
import { STATUS_CODES } from 'nhb-toolbox/constants';
const userSchema = new Schema<IUserDoc>(
{
user_name: {
type: String,
trim: true,
unique: true,
},
email: {
type: String,
required: true,
trim: true,
unique: true,
},
first_name: {
type: String,
required: true,
trim: true,
},
last_name: {
type: String,
required: true,
trim: true,
},
password: {
type: String,
required: true,
trim: true,
select: false,
},
role: {
type: String,
enum: USER_ROLES,
default: 'user',
},
is_active: {
type: Boolean,
default: true,
},
},
{
timestamps: {
createdAt: 'created_at',
updatedAt: 'updated_at',
},
versionKey: false,
}
);
// * Hash password and create username before saving the user in DB.
userSchema.pre('save', async function () {
const base = this.first_name?.toLowerCase()?.replace(/\s+/g, '_');
let userName = base;
let suffix = 0;
while (await User.exists({ user_name: userName })) {
suffix += 1;
userName = `${base}_${suffix}`;
}
this.user_name = userName;
this.password = await hashPassword(this.password);
});
/** Static method to check if user exists */
userSchema.statics.validateUser = async function (email?: TEmail) {
if (!email) {
throw new ErrorWithStatus(
'Authentication Error',
'Please provide a valid email!',
STATUS_CODES.BAD_REQUEST,
'user'
);
}
const user: IUserDoc = await this.findOne({ email }).select('+password');
if (!user) {
throw new ErrorWithStatus(
'Not Found Error',
`No user found with email: ${email}!`,
STATUS_CODES.NOT_FOUND,
'user'
);
}
if (!user.is_active) {
throw new ErrorWithStatus(
'Authentication Error',
`User with email ${email} is not active!`,
STATUS_CODES.FORBIDDEN,
'user'
);
}
return user;
};
export const User = model<IUserDoc, IUserModel>('User', userSchema);