add host and minglar admin APIs for registration, login, and retrieval of host details
This commit is contained in:
@@ -4,6 +4,8 @@ import ApiError from '../../../common/utils/helper/ApiError';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import { z } from 'zod';
|
||||
import { hostCompanyDetailsSchema } from '../../../common/utils/validation/host/hostCompanyDetails.validation';
|
||||
import { CreateMinglarDto, UpdateMinglarDto } from '../dto/minglar.dto';
|
||||
import { User } from '@prisma/client';
|
||||
|
||||
type HostCompanyDetailsInput = z.infer<typeof hostCompanyDetailsSchema>;
|
||||
|
||||
@@ -47,6 +49,134 @@ export class MinglarService {
|
||||
return true;
|
||||
}
|
||||
|
||||
async createHost(data: CreateMinglarDto) {
|
||||
return this.prisma.user.create({ data });
|
||||
}
|
||||
|
||||
async getAllHosts() {
|
||||
return this.prisma.user.findMany({ where: { roleXid: 3 } });
|
||||
}
|
||||
|
||||
async getHostById(id: number) {
|
||||
const host = await this.prisma.user.findUnique({
|
||||
where: { id },
|
||||
include: {
|
||||
HostHeader: {
|
||||
include: {
|
||||
currencies: true,
|
||||
cities: true,
|
||||
states: true,
|
||||
countries: true,
|
||||
HostBankDetails: true,
|
||||
HostDocuments: true,
|
||||
HostSuggestion: true,
|
||||
hostParent: true,
|
||||
HostTrack: true,
|
||||
Activities: true,
|
||||
},
|
||||
},
|
||||
UserOtp: true,
|
||||
Token: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!host || host.roleXid !== 4) {
|
||||
throw new ApiError(404, 'Host not found');
|
||||
}
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
async updateHost(id: number, data: UpdateMinglarDto) {
|
||||
return this.prisma.user.update({
|
||||
where: { id },
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
async deleteHost(id: number) {
|
||||
return this.prisma.user.delete({ where: { id } });
|
||||
}
|
||||
|
||||
async getHostByEmail(email: string): Promise<User> {
|
||||
return this.prisma.user.findUnique({ where: { emailAddress: email } });
|
||||
}
|
||||
|
||||
async verifyHostOtp(email: string, otp: string): Promise<boolean> {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { emailAddress: email },
|
||||
select: {
|
||||
id: true,
|
||||
emailAddress: true,
|
||||
UserOtp: {
|
||||
where: { isActive: true, isVerified: false },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
take: 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new ApiError(404, 'User not found.');
|
||||
}
|
||||
|
||||
const userOtp = user.UserOtp[0];
|
||||
|
||||
if (!userOtp) {
|
||||
throw new ApiError(400, 'No OTP found.');
|
||||
}
|
||||
|
||||
if (new Date() > userOtp.expiresOn) {
|
||||
throw new ApiError(400, 'OTP has expired.');
|
||||
}
|
||||
|
||||
const isMatch = await bcrypt.compare(otp, userOtp.otpCode);
|
||||
|
||||
if (!isMatch) {
|
||||
throw new ApiError(400, 'Invalid OTP.');
|
||||
}
|
||||
|
||||
await this.prisma.userOtp.update({
|
||||
where: { id: userOtp.id },
|
||||
data: {
|
||||
isVerified: true,
|
||||
verifiedOn: new Date(),
|
||||
isActive: false,
|
||||
},
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
async loginForMinglar(emailAddress: string, userPassword: string) {
|
||||
const existingUser = await this.prisma.user.findUnique({
|
||||
where: { emailAddress: emailAddress },
|
||||
});
|
||||
|
||||
if (!existingUser) {
|
||||
throw new ApiError(404, 'User not found');
|
||||
}
|
||||
|
||||
if (existingUser.roleXid !== 4) {
|
||||
throw new ApiError(403, 'Access denied. Not a host user.');
|
||||
}
|
||||
|
||||
const matchPassword = await bcrypt.compare(userPassword, existingUser.userPassword);
|
||||
if (!matchPassword) {
|
||||
throw new ApiError(401, 'Invalid credentials');
|
||||
}
|
||||
|
||||
return existingUser;
|
||||
}
|
||||
|
||||
async createHostUser(email: string) {
|
||||
const newUser = await this.prisma.user.create({
|
||||
data: { emailAddress: email, roleXid: 4 },
|
||||
});
|
||||
return newUser;
|
||||
}
|
||||
|
||||
|
||||
async addCompanyDetails(
|
||||
companyData: HostCompanyDetailsInput,
|
||||
documents: HostDocumentInput[] // Documents with S3 URLs
|
||||
|
||||
159
src/modules/minglaradmin/services/token.service.ts
Normal file
159
src/modules/minglaradmin/services/token.service.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import jwt, { JwtPayload } from "jsonwebtoken";
|
||||
import moment from "moment";
|
||||
import config from "../../../config/config";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export class TokenService {
|
||||
private generateToken(
|
||||
user_xid: number,
|
||||
expiresIn: Date,
|
||||
type: string,
|
||||
secret: string
|
||||
): { token: string; expires: Date } {
|
||||
const token = jwt.sign(
|
||||
{
|
||||
sub: user_xid,
|
||||
iat: moment().unix(),
|
||||
exp: moment(expiresIn).unix(),
|
||||
type,
|
||||
},
|
||||
secret
|
||||
);
|
||||
|
||||
return { token, expires: expiresIn };
|
||||
}
|
||||
|
||||
async generateAuthToken(
|
||||
user_xid: number,
|
||||
): Promise<{
|
||||
access: { token: string; expires: Date };
|
||||
refresh: { token: string; expires: Date };
|
||||
}> {
|
||||
const accessTokenExpires = moment()
|
||||
.add(config.jwt.accessExpirationMinutes, "minutes")
|
||||
.toDate();
|
||||
|
||||
const refreshTokenExpires = moment()
|
||||
.add(config.jwt.refreshExpirationDays, "days")
|
||||
.toDate();
|
||||
|
||||
const accessToken = this.generateToken(
|
||||
user_xid,
|
||||
accessTokenExpires,
|
||||
"access",
|
||||
config.jwt.secret
|
||||
);
|
||||
|
||||
const refreshToken = this.generateToken(
|
||||
user_xid,
|
||||
refreshTokenExpires,
|
||||
"refresh",
|
||||
config.jwt.secret
|
||||
);
|
||||
|
||||
await prisma.token.create({
|
||||
data: {
|
||||
token: refreshToken.token,
|
||||
expiringAt: refreshToken.expires,
|
||||
tokenType: "refresh",
|
||||
isBlackListed: false,
|
||||
|
||||
user: {
|
||||
connect: { id: user_xid },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
access: accessToken,
|
||||
refresh: refreshToken,
|
||||
};
|
||||
}
|
||||
|
||||
async generateAuthTokenAdmin(
|
||||
user_xid: number
|
||||
): Promise<{
|
||||
access: { token: string; expires: Date };
|
||||
refresh: { token: string; expires: Date };
|
||||
}> {
|
||||
const accessTokenExpires = moment()
|
||||
.add(config.jwt.accessExpirationMinutes, "minutes")
|
||||
.toDate();
|
||||
|
||||
const refreshTokenExpires = moment()
|
||||
.add(config.jwt.refreshExpirationDays, "days")
|
||||
.toDate();
|
||||
|
||||
const accessToken = this.generateToken(
|
||||
user_xid,
|
||||
accessTokenExpires,
|
||||
"access",
|
||||
config.jwt.secret
|
||||
);
|
||||
|
||||
const refreshToken = this.generateToken(
|
||||
user_xid,
|
||||
refreshTokenExpires,
|
||||
"refresh",
|
||||
config.jwt.secret
|
||||
);
|
||||
|
||||
await prisma.token.create({
|
||||
data: {
|
||||
token: refreshToken.token,
|
||||
expiringAt: refreshToken.expires,
|
||||
tokenType: "refresh",
|
||||
isBlackListed: false,
|
||||
user: {
|
||||
connect: { id: user_xid },
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
access: accessToken,
|
||||
refresh: refreshToken,
|
||||
};
|
||||
}
|
||||
|
||||
async revokeToken(user_xid: number, deviceId: string): Promise<boolean> {
|
||||
const existingToken = await prisma.token.findFirst({
|
||||
where: {
|
||||
id: user_xid,
|
||||
deviceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!existingToken) return false;
|
||||
|
||||
await prisma.token.delete({ where: { id: existingToken.id } });
|
||||
return true;
|
||||
}
|
||||
|
||||
async isTokenBlackListed(token: string): Promise<boolean> {
|
||||
const existing = await prisma.token.findUnique({
|
||||
where: { token },
|
||||
});
|
||||
return existing ? true : false;
|
||||
}
|
||||
|
||||
async verifyRefreshToken(
|
||||
token: string
|
||||
): Promise<string | JwtPayload | null> {
|
||||
try {
|
||||
return jwt.verify(token, config.jwt.secret);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async decodeToken(token: string): Promise<string | JwtPayload | null> {
|
||||
try {
|
||||
return jwt.decode(token);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user