nhb-express
Version:
Minimal Express + TypeScript scaffolder with modular structure and flexible stack choices.
84 lines (71 loc) • 2.53 kB
text/typescript
import { db } from '#/drizzle';
import { users } from '#/drizzle/schema/users';
import configs from '@/configs';
import { ErrorWithStatus } from '@/errors/ErrorWithStatus';
import { processLogin } from '@/modules/auth/auth.utils';
import type { InsertUser, TLoginCredentials } from '@/modules/user/user.types';
import { findUserByEmail, userCols } from '@/modules/user/user.utils';
import type { DecodedUser } from '@/types/interfaces';
import { generateToken, hashPassword, verifyToken } from '@/utilities/authUtilities';
import { pickFields } from 'nhb-toolbox';
import { STATUS_CODES } from 'nhb-toolbox/constants';
class AuthServices {
/**
* * Register a user in the database.
* @param payload Required data to register a user.
* @returns The registered user info or throws error if error occurs.
*/
async registerUserInDB(payload: InsertUser) {
const hashedPass = await hashPassword(payload.password);
const [user] = await db
.insert(users)
.values({ ...payload, password: hashedPass })
.returning(userCols);
if (!user) {
throw new ErrorWithStatus(
'Creation Error',
'Cannot create user right now! Please try again later!',
STATUS_CODES.INTERNAL_SERVER_ERROR,
'CREATE /auth/register'
);
}
return user;
}
/**
* * Login user.
* @param payload Login credentials (`email` and `password`).
* @returns Token as object.
*/
async loginUser(payload: TLoginCredentials) {
// * Validate and extract user from DB.
const user = await findUserByEmail(payload.email, true);
return await processLogin(payload?.password, user);
}
/**
* * Refresh access token (Get new one).
* @param token Refresh token from client.
* @returns New access token.
*/
async refreshToken(token: string): Promise<{ token: string }> {
// * Verify and decode token
const { email } = verifyToken(configs.refreshSecret, token);
// * Validate and extract user from DB.
const user = await findUserByEmail(email);
// * Create token and send to the client.
const accessToken = generateToken(
pickFields(user, ['email', 'role']),
configs.accessSecret,
configs.accessExpireTime
);
return { token: accessToken };
}
/**
* * Get the current logged-in user's info from DB.
* @param client User details from decoded JWT token.
* @returns The user details without the password field.
*/
async getCurrentUserFromDB(client: DecodedUser | undefined) {
return await findUserByEmail(client?.email);
}
}
export const authServices = new AuthServices();