Skip to content

Commit 040f9a5

Browse files
committed
fix auth
1 parent 01a2896 commit 040f9a5

24 files changed

+175
-435
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
Warnings:
3+
4+
- A unique constraint covering the columns `[username]` on the table `user` will be added. If there are existing duplicate values, this will fail.
5+
6+
*/
7+
-- CreateIndex
8+
CREATE UNIQUE INDEX `user_username_key` ON `user`(`username`);

prisma/schema.prisma

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ datasource db {
1616
model user {
1717
id Int @id @default(autoincrement())
1818
email String? @unique @db.VarChar(100)
19-
username String? @db.VarChar(100)
19+
username String? @unique @db.VarChar(100)
2020
password String? @db.VarChar(100)
2121
2222
token_cache_login String? @db.VarChar(100)

src/app.module.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import { HttpModule } from "@nestjs/axios";
1111
import { UserModule } from "./modules/user/user.module";
1212
import { AuthenticateModule } from "./modules/authenticate/authenticate.module";
1313
import { appConfig, mailConfig } from "./config";
14-
import { MailModule } from "./modules/mail/mail.module";
1514
import { FileModule } from "./modules/file/file.module";
1615
import { AppController } from "./app.controller";
17-
import { ContactModule } from "./modules/contact/contact.module";
1816
import { DeviceModule } from './modules/device/device.module';
17+
import { Prisma } from "@prisma/client";
18+
import { PrismaModule } from "./modules/prisma/prisma.module";
1919

2020
@Module({
2121
imports: [
@@ -54,10 +54,9 @@ import { DeviceModule } from './modules/device/device.module';
5454
PassportModule.register({ session: true }),
5555
UserModule,
5656
AuthenticateModule,
57-
MailModule,
5857
FileModule,
59-
ContactModule,
6058
DeviceModule,
59+
PrismaModule,
6160
],
6261
controllers: [AppController],
6362
providers: [],

src/guards/roles/roles.guard.ts

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
1-
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
2-
import { Observable } from "rxjs";
3-
import { Reflector } from "@nestjs/core";
4-
import { GqlExecutionContext } from "@nestjs/graphql";
5-
import { ROLES_KEY } from "../../decorators/roles/roles.decorator";
6-
import { User } from "../../modules/user/entities/user.entity";
7-
import { Role } from "../../utils/types/role.enum";
1+
// import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common";
2+
// import { Observable } from "rxjs";
3+
// import { Reflector } from "@nestjs/core";
4+
// import { GqlExecutionContext } from "@nestjs/graphql";
5+
// import { ROLES_KEY } from "../../decorators/roles/roles.decorator";
6+
// import { User } from "../../modules/user/entities/user.entity";
7+
// import { Role } from "../../utils/types/role.enum";
88

9-
@Injectable()
10-
export class RolesGuard implements CanActivate {
11-
constructor(private reflector: Reflector) {}
9+
// @Injectable()
10+
// export class RolesGuard implements CanActivate {
11+
// constructor(private reflector: Reflector) {}
1212

13-
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
14-
const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [context.getHandler(), context.getClass()]);
13+
// canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
14+
// const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [context.getHandler(), context.getClass()]);
1515

16-
if (!requiredRoles) {
17-
return true;
18-
}
16+
// if (!requiredRoles) {
17+
// return true;
18+
// }
1919

20-
const ctx = GqlExecutionContext.create(context);
21-
const request = ctx.getContext().req;
20+
// const ctx = GqlExecutionContext.create(context);
21+
// const request = ctx.getContext().req;
2222

23-
const user: User = request.user;
23+
// const user: User = request.user;
2424

25-
if (user) {
26-
const roles = user.role;
27-
return requiredRoles.some((role) => roles.includes(role));
28-
}
25+
// if (user) {
26+
// const roles = user.role;
27+
// return requiredRoles.some((role) => roles.includes(role));
28+
// }
2929

30-
return false;
31-
}
32-
}
30+
// return false;
31+
// }
32+
// }

src/main.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import { AppModule } from "./app.module";
88
process.env.TZ = "Asia/Ho_Chi_Minh";
99

1010
async function bootstrap() {
11-
const app = await NestFactory.create(AppModule);
11+
const app = await NestFactory.create(AppModule, {
12+
logger: ['log', 'error', 'warn', 'debug', 'verbose'], // Ensure 'log' is included
13+
});
1214

1315
app.useGlobalPipes(
1416
new ValidationPipe({
@@ -20,7 +22,7 @@ async function bootstrap() {
2022

2123
app.use(
2224
session({
23-
name: "DAVINCI_SESSION_ID",
25+
name: "HARMONY_SESSION",
2426
secret: configService.get("session.secret"),
2527
resave: false,
2628
// when user is login, session is created, and if not, we don't

src/modules/authenticate/authenticate.module.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,23 @@ import { LocalStrategy } from "./strategies/local.strategy";
1010
import { UserModule } from "../user/user.module";
1111
import { JwtStrategy } from "./strategies/jwt.strategy";
1212
import { GoogleStrategy } from "./strategies/google.strategy";
13+
import { JwtModule } from "@nestjs/jwt";
14+
import { ConfigModule, ConfigService } from "@nestjs/config";
1315

1416
@Module({
1517
imports: [
1618
PassportModule,
1719
UserModule,
1820
HttpModule,
21+
ConfigModule,
22+
JwtModule.registerAsync({
23+
imports: [ConfigModule],
24+
useFactory: async (configService: ConfigService) => ({
25+
secret: configService.get<string>("JWT_SECRET"),
26+
signOptions: { expiresIn: "60m" },
27+
}),
28+
inject: [ConfigService],
29+
}),
1930
],
2031
providers: [AuthenticateResolver, AuthenticateService, LocalSerializer, LocalStrategy, JwtStrategy, Auth.OAuth2Client, GoogleStrategy],
2132
})

src/modules/authenticate/authenticate.service.ts

Lines changed: 80 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// import { session } from 'express-session';
2-
import { Injectable } from "@nestjs/common";
2+
import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
33
import bcrypt from "bcrypt";
44
import { GraphQLError } from "graphql";
55
import { google, Auth } from "googleapis";
66
import { JwtService } from "@nestjs/jwt";
7+
import { Logger } from '@nestjs/common';
78

89
import { LoginInput } from "./dto/login.dto";
910
import { RegisterAuthenticateInput } from "./dto/register.dto";
@@ -27,23 +28,25 @@ export class AuthenticateService {
2728
this.oauthClient = new google.auth.OAuth2(clientID, clientSecret);
2829
}
2930

30-
async validateUser(email: string, password: string) {
31+
async validateUser(username: string, pwd: string) {
3132
try {
33+
console.log("🚀 ~ file: authenticate.service.ts ~ line 57 ~ AuthenticateService ~ validateUser ~ email", username);
3234
const user = await this.prisma.user.findUniqueOrThrow({
33-
where: { email: email },
35+
where: { username: username },
3436
});
37+
console.log("🚀 ~ file: authenticate.service.ts ~ line 59 ~ AuthenticateService ~ validateUser ~ user", user);
3538

3639
if (!user) {
3740
throw new GraphQLError("User not found");
3841
}
3942

40-
const valid = await bcrypt.compare(password, user.password);
43+
const valid = await bcrypt.compare(pwd, user.password);
4144

4245
if (!valid) {
4346
throw new GraphQLError("Invalid password");
4447
}
4548

46-
return user
49+
return user;
4750
} catch (error) {
4851
throw error;
4952
}
@@ -53,7 +56,7 @@ export class AuthenticateService {
5356
try {
5457
const user = await this.prisma.user.findFirst({
5558
where: { email: registerAuthenticateInput.email },
56-
})
59+
});
5760

5861
if (user) {
5962
throw new GraphQLError("User already exists");
@@ -76,30 +79,76 @@ export class AuthenticateService {
7679
}
7780
return newUser;
7881
} catch (error) {
79-
console.log(error)
82+
console.log(error);
8083
throw error;
8184
}
8285
}
8386

87+
private async signTokens(userId: number, email: string) {
88+
const [accessToken, refreshToken] = await Promise.all([
89+
this.jwtService.signAsync(
90+
{
91+
sub: userId,
92+
email,
93+
},
94+
{
95+
secret: this.configService.get("JWT_SECRET"),
96+
expiresIn: "1h",
97+
},
98+
),
99+
this.jwtService.signAsync(
100+
{
101+
sub: userId,
102+
},
103+
{
104+
secret: this.configService.get("JWT_SECRET"),
105+
expiresIn: "7d",
106+
},
107+
),
108+
]);
109+
110+
return {
111+
accessToken,
112+
refreshToken,
113+
};
114+
}
115+
84116
async login(loginAuthenticateInput: LoginInput) {
85117
try {
86118
const user = await this.prisma.user.findFirst({
87-
where: { username: loginAuthenticateInput.username },
119+
where: {
120+
username: loginAuthenticateInput.username,
121+
},
88122
});
89123

90124
if (!user) {
91-
throw new GraphQLError("User not found");
125+
throw new HttpException("Not found", HttpStatus.NOT_FOUND);
92126
}
93127

94-
const valid = await bcrypt.compare(loginAuthenticateInput.password, user.password);
128+
const result = await bcrypt.compare(loginAuthenticateInput.password, user.password);
95129

96-
if (!valid) {
97-
throw new GraphQLError("Invalid password");
130+
if (!result) {
131+
throw new Error("Thông tin đăng nhập không hợp lệ");
98132
}
99133

100-
return user;
134+
const { accessToken, refreshToken } = await this.signTokens(user.id, user.email);
135+
136+
// Save to session
137+
await this.prisma.session.create({
138+
data: {
139+
userID: user.id,
140+
accessToken,
141+
refreshToken,
142+
},
143+
});
144+
145+
return {
146+
accessToken,
147+
refreshToken,
148+
user: user,
149+
};
101150
} catch (error) {
102-
throw error;
151+
throw new HttpException(error, HttpStatus.SERVICE_UNAVAILABLE);
103152
}
104153
}
105154

@@ -144,25 +193,25 @@ export class AuthenticateService {
144193
async googleLogin(accessToken: string) {
145194
const token: any = jwtDecode(accessToken);
146195
try {
147-
const user = await this.prisma.user.findFirst({ where: { email: token?.email } });
148-
if (!user) {
149-
await this.prisma.user.create({
150-
data: {
151-
username: token?.name,
152-
email: token?.email,
153-
password: token?.sub, // You might want to hash this or handle it differently
154-
},
155-
});
156-
}
157-
const authenticatedUser = await this.prisma.user.findFirst({ where: { email: token?.email } });
158-
if (!authenticatedUser) {
159-
throw new GraphQLError('Error');
160-
}
161-
return authenticatedUser;
196+
const user = await this.prisma.user.findFirst({ where: { email: token?.email } });
197+
if (!user) {
198+
await this.prisma.user.create({
199+
data: {
200+
username: token?.name,
201+
email: token?.email,
202+
password: token?.sub, // You might want to hash this or handle it differently
203+
},
204+
});
205+
}
206+
const authenticatedUser = await this.prisma.user.findFirst({ where: { email: token?.email } });
207+
if (!authenticatedUser) {
208+
throw new GraphQLError("Error");
209+
}
210+
return authenticatedUser;
162211
} catch (err) {
163-
throw new GraphQLError(err);
212+
throw new GraphQLError(err);
164213
}
165-
}
214+
}
166215

167216
async refreshToken(params: RefreshTokenInput, accessToken: string) {
168217
try {

src/modules/authenticate/dto/login.dto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { InputType, Field, ObjectType } from "@nestjs/graphql";
2-
import { IsString } from "class-validator";
2+
import { IsEmail, IsString } from "class-validator";
33
import { User } from "../../user/entities/user.entity";
44
import { BaseOneAbstractResult } from "../../base/dto/base-one.abstract-result";
55

src/modules/authenticate/guards/gql-auth.guard.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ExecutionContext, Injectable } from "@nestjs/common";
1+
import { ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common";
22
import { GqlExecutionContext } from "@nestjs/graphql";
33
import { AuthGuard } from "@nestjs/passport";
44

@@ -21,4 +21,11 @@ export class GqlLocalAuthGuard extends AuthGuard("local") {
2121

2222
return context.switchToHttp().getRequest();
2323
}
24+
handleRequest(err, user, info, context) {
25+
if (err || !user) {
26+
console.log("🚀 ~ file: gql-auth.guard.ts ~ line 47 ~ GqlLocalAuthGuard ~ handleRequest ~ err", err);
27+
throw err || new UnauthorizedException();
28+
}
29+
return user;
30+
}
2431
}

src/modules/authenticate/strategies/local.strategy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ export class LocalStrategy extends PassportStrategy(Strategy) {
1212
});
1313
}
1414

15-
async validate(email: string, password: string) {
16-
const user = await this.authService.validateUser(email, password);
15+
async validate(username: string, password: string) {
16+
const user = await this.authService.validateUser(username, password);
1717

1818
if (!user) {
1919
throw new GraphQLError("Credentials incorrect");

src/modules/contact/contact.module.ts

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/modules/contact/contact.resolver.ts

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)