fix: Prisma issue fix + Auth done
This commit is contained in:
@@ -5,7 +5,7 @@ import { UserModule } from './user/user.module';
|
|||||||
import { AuthModule } from './auth/auth.module';
|
import { AuthModule } from './auth/auth.module';
|
||||||
import { RequestContextMiddleware } from 'core/als/request-context.middleware';
|
import { RequestContextMiddleware } from 'core/als/request-context.middleware';
|
||||||
import { RequestContextModule } from 'core/als/request-context.module';
|
import { RequestContextModule } from 'core/als/request-context.module';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
import { PrismaModule } from './prisma/prisma.module';
|
import { PrismaModule } from './prisma/prisma.module';
|
||||||
import { APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
|
import { APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
|
||||||
import { ResponseInterceptor } from 'common/interceptors/response.interceptor';
|
import { ResponseInterceptor } from 'common/interceptors/response.interceptor';
|
||||||
@@ -72,7 +72,26 @@ import { ExpressAdapter } from '@bull-board/express';
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AppModule implements NestModule {
|
export class AppModule implements NestModule {
|
||||||
|
constructor(private readonly configService: ConfigService) { };
|
||||||
|
|
||||||
configure(consumer: MiddlewareConsumer) {
|
configure(consumer: MiddlewareConsumer) {
|
||||||
consumer.apply(RequestContextMiddleware).forRoutes('*paths');
|
consumer.apply(RequestContextMiddleware).forRoutes('*paths');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure all required env vars are present
|
||||||
|
onModuleInit() {
|
||||||
|
const requiredEnvVars = [
|
||||||
|
"TOKEN_SECRET",
|
||||||
|
"DATABASE_URL",
|
||||||
|
"BULL_MQ_REDIS_HOST",
|
||||||
|
"BULL_MQ_REDIS_PORT"
|
||||||
|
]
|
||||||
|
|
||||||
|
const missingEnvVars = requiredEnvVars.filter((envVar) => !(this.configService.get<string | number>(envVar)))
|
||||||
|
|
||||||
|
if (missingEnvVars.length > 0) {
|
||||||
|
Logger.error(`One or more env variables are missing. Add: ${missingEnvVars.join(', ')} to env file.`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,10 +76,17 @@ export class AuthController {
|
|||||||
@IsTempToken()
|
@IsTempToken()
|
||||||
@UseGuards(AuthGuard)
|
@UseGuards(AuthGuard)
|
||||||
@Post('/complete-profile')
|
@Post('/complete-profile')
|
||||||
async completeUserProfile(@Body() body: CompleteProfileSetupRequestDTO): Promise<string> {
|
async completeUserProfile(@Body() body: CompleteProfileSetupRequestDTO) {
|
||||||
await this.authService.completeProfileSetup(body);
|
const { accessToken, refreshToken, user } = await this.authService.completeProfileSetup(body);
|
||||||
|
|
||||||
return 'Welcome';
|
return {
|
||||||
|
message: "Welcome to our app",
|
||||||
|
data: {
|
||||||
|
accessToken,
|
||||||
|
refreshToken,
|
||||||
|
user
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logout() { }
|
logout() { }
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ import { AuthController } from './auth.controller';
|
|||||||
import { APP_GUARD } from '@nestjs/core';
|
import { APP_GUARD } from '@nestjs/core';
|
||||||
import { AuthGuard } from './guards/auth.guard';
|
import { AuthGuard } from './guards/auth.guard';
|
||||||
import { UserModule } from 'src/user/user.module';
|
import { UserModule } from 'src/user/user.module';
|
||||||
import { JwtModule } from '@nestjs/jwt';
|
|
||||||
import { RequestContextModule } from 'core/als/request-context.module';
|
import { RequestContextModule } from 'core/als/request-context.module';
|
||||||
import { BullModule } from '@nestjs/bullmq';
|
import { BullModule } from '@nestjs/bullmq';
|
||||||
import { PrismaModule } from 'src/prisma/prisma.module';
|
import { PrismaModule } from 'src/prisma/prisma.module';
|
||||||
|
import { JwtModule } from '@nestjs/jwt';
|
||||||
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
@Global()
|
@Global()
|
||||||
@Module({
|
@Module({
|
||||||
@@ -23,8 +24,16 @@ import { PrismaModule } from 'src/prisma/prisma.module';
|
|||||||
BullModule.registerQueue({
|
BullModule.registerQueue({
|
||||||
name: "mail"
|
name: "mail"
|
||||||
}),
|
}),
|
||||||
|
JwtModule.registerAsync({
|
||||||
|
global: true,
|
||||||
|
imports: [ConfigModule],
|
||||||
|
inject: [ConfigService],
|
||||||
|
useFactory: (config: ConfigService) => ({
|
||||||
|
secret: config.get<string>("TOKEN_SECRET"),
|
||||||
|
signOptions: { expiresIn: '7d' }
|
||||||
|
})
|
||||||
|
}),
|
||||||
UserModule,
|
UserModule,
|
||||||
JwtModule,
|
|
||||||
RequestContextModule,
|
RequestContextModule,
|
||||||
PrismaModule
|
PrismaModule
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export class AuthService {
|
|||||||
const now = Number(new Date()) / 1000;
|
const now = Number(new Date()) / 1000;
|
||||||
|
|
||||||
if (!otpExists)
|
if (!otpExists)
|
||||||
throw new BadRequestException("No user found")
|
throw new BadRequestException("No OTP request found")
|
||||||
else if (otpExists.otp !== dto.otp)
|
else if (otpExists.otp !== dto.otp)
|
||||||
throw new BadRequestException("Invalid OTP")
|
throw new BadRequestException("Invalid OTP")
|
||||||
else if ((Number(otpExists.expiresAt) / 1000 < now)) {
|
else if ((Number(otpExists.expiresAt) / 1000 < now)) {
|
||||||
@@ -217,43 +217,36 @@ export class AuthService {
|
|||||||
|
|
||||||
resetPassword() { }
|
resetPassword() { }
|
||||||
|
|
||||||
// TODO: Use nest jwt
|
// TODO: If remember me is there, sign for like 30d maybe
|
||||||
private async genSignedTokens(token: TokenInputType) {
|
private async genSignedTokens(token: TokenInputType) {
|
||||||
const accessToken = await this.jwtService.signAsync(token, {
|
const accessToken = await this.jwtService.signAsync(token);
|
||||||
secret: 'demo',
|
|
||||||
});
|
|
||||||
|
|
||||||
const refreshToken = await this.jwtService.signAsync(
|
const refreshToken = await this.jwtService.signAsync(
|
||||||
{
|
{
|
||||||
userId: token.userId,
|
userId: token.userId,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
secret: 'demo',
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return { accessToken, refreshToken };
|
return { accessToken, refreshToken };
|
||||||
}
|
}
|
||||||
|
|
||||||
private async genSignedTempToken(token: OTPTokenInputType) {
|
private async genSignedTempToken(token: OTPTokenInputType) {
|
||||||
const accessToken = await this.jwtService.signAsync(token, {
|
const accessToken = await this.jwtService.signAsync(token);
|
||||||
secret: 'demo',
|
|
||||||
});
|
|
||||||
|
|
||||||
const refreshToken = await this.jwtService.signAsync(
|
const refreshToken = await this.jwtService.signAsync(
|
||||||
{
|
{
|
||||||
userId: token.userId,
|
userId: token.userId,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
secret: 'demo',
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return { accessToken, refreshToken };
|
return { accessToken, refreshToken };
|
||||||
}
|
}
|
||||||
|
|
||||||
private genOtp() {
|
genOtp(): number {
|
||||||
return 123456;
|
const array = new Uint32Array(1);
|
||||||
|
crypto.getRandomValues(array);
|
||||||
|
const otp = array[0] % 900000 + 100000;
|
||||||
|
return otp;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { Reflector } from '@nestjs/core';
|
|||||||
import { PUBLIC_KEY, TEMP_TOKEN_KEY } from 'common/keys';
|
import { PUBLIC_KEY, TEMP_TOKEN_KEY } from 'common/keys';
|
||||||
import { UserService } from 'src/user/user.service';
|
import { UserService } from 'src/user/user.service';
|
||||||
import { USER_ACCOUNT_STATUS } from 'prisma/generated/prisma/enums';
|
import { USER_ACCOUNT_STATUS } from 'prisma/generated/prisma/enums';
|
||||||
|
import { ConfigService } from '@nestjs/config';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthGuard implements CanActivate {
|
export class AuthGuard implements CanActivate {
|
||||||
@@ -21,6 +22,7 @@ export class AuthGuard implements CanActivate {
|
|||||||
private readonly jwtService: JwtService,
|
private readonly jwtService: JwtService,
|
||||||
private readonly requestContext: RequestContextService,
|
private readonly requestContext: RequestContextService,
|
||||||
private readonly userService: UserService,
|
private readonly userService: UserService,
|
||||||
|
private readonly configService: ConfigService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
async canActivate(context: ExecutionContext) {
|
async canActivate(context: ExecutionContext) {
|
||||||
@@ -42,9 +44,12 @@ export class AuthGuard implements CanActivate {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const payload: JwtPayload = await this.jwtService.verifyAsync(token, {
|
const payload: JwtPayload = await this.jwtService.verifyAsync(token, {
|
||||||
secret: 'demo',
|
secret: this.configService.get<string>("TOKEN_SECRET"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (isTempToken && payload.status !== USER_ACCOUNT_STATUS.pending)
|
||||||
|
throw new UnauthorizedException()
|
||||||
|
|
||||||
|
|
||||||
// TODO: Redis + Org too, blacklist token
|
// TODO: Redis + Org too, blacklist token
|
||||||
const userExists = await this.userService.findById(payload.userId);
|
const userExists = await this.userService.findById(payload.userId);
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ import { TransactionClient } from 'prisma/generated/prisma/internal/prismaNamesp
|
|||||||
export class PrismaService
|
export class PrismaService
|
||||||
extends PrismaClient
|
extends PrismaClient
|
||||||
implements OnModuleDestroy, OnModuleInit {
|
implements OnModuleDestroy, OnModuleInit {
|
||||||
|
|
||||||
|
private readonly db: PrismaClient;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly ctx: RequestContextService,
|
private readonly ctx: RequestContextService,
|
||||||
private readonly configService: ConfigService,
|
private readonly configService: ConfigService,
|
||||||
@@ -31,6 +34,8 @@ export class PrismaService
|
|||||||
adapter: adapter,
|
adapter: adapter,
|
||||||
log: ['info', 'warn'],
|
log: ['info', 'warn'],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.db = new PrismaClient({ adapter, log: ['warn', 'info', 'error'] })
|
||||||
}
|
}
|
||||||
async onModuleInit() {
|
async onModuleInit() {
|
||||||
try {
|
try {
|
||||||
@@ -51,6 +56,6 @@ export class PrismaService
|
|||||||
* Else returns itself.
|
* Else returns itself.
|
||||||
* */
|
* */
|
||||||
get client(): TransactionClient {
|
get client(): TransactionClient {
|
||||||
return this.ctx.tx ?? this;
|
return this.ctx.tx ?? this.db;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,14 +56,14 @@ export class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async findUserForAuth(email: string) {
|
async findUserForAuth(email: string) {
|
||||||
return await this.prisma.user.findUnique({
|
return await this.prisma.client.user.findUnique({
|
||||||
where: { email },
|
where: { email },
|
||||||
omit: { password: false }, // Password is omitted by default, we are just reverting it
|
omit: { password: false }, // Password is omitted by default, we are just reverting it
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async findById(id: string) {
|
async findById(id: string) {
|
||||||
return await this.prisma.user.findUnique({
|
return await this.prisma.client.user.findUnique({
|
||||||
where: {
|
where: {
|
||||||
id: id,
|
id: id,
|
||||||
},
|
},
|
||||||
@@ -71,8 +71,7 @@ export class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async findByEmail(email: string) {
|
async findByEmail(email: string) {
|
||||||
const client = this.prisma.client.user ?? this.prisma.user;
|
return await this.prisma.client.user.findUnique({
|
||||||
return await client.findUnique({
|
|
||||||
where: {
|
where: {
|
||||||
email: email,
|
email: email,
|
||||||
},
|
},
|
||||||
@@ -80,7 +79,7 @@ export class UserService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateRefreshToken(id: string, refreshToken: string) {
|
async updateRefreshToken(id: string, refreshToken: string) {
|
||||||
return await this.prisma.user.update({
|
return await this.prisma.client.user.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: { refreshToken },
|
data: { refreshToken },
|
||||||
});
|
});
|
||||||
@@ -90,8 +89,7 @@ export class UserService {
|
|||||||
* USER OTP SERVICES
|
* USER OTP SERVICES
|
||||||
* */
|
* */
|
||||||
async findByEmailInOTP(email: string) {
|
async findByEmailInOTP(email: string) {
|
||||||
const client = this.prisma.client.userOTP ?? this.prisma.userOTP;
|
return await this.prisma.client.userOTP.findUnique({
|
||||||
return await client.findUnique({
|
|
||||||
where: {
|
where: {
|
||||||
email,
|
email,
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user