Spaces:
Sleeping
Sleeping
fix: update config and import
Browse files- backend/.env.example +2 -1
- backend/src/app.module.ts +1 -4
- backend/src/config/config.ts +1 -0
- backend/src/config/database.ts +6 -3
- backend/src/config/typeorm.ts +7 -3
- backend/src/modules/authentication/authentication.controller.spec.ts +0 -20
- backend/src/modules/authentication/authentication.controller.ts +7 -6
- backend/src/modules/authentication/authentication.guard.ts +47 -45
- backend/src/modules/authentication/authentication.module.ts +6 -7
- backend/src/modules/authentication/authentication.service.spec.ts +0 -18
- backend/src/modules/authentication/authentication.service.ts +7 -7
- backend/src/modules/user/user.controller.ts +5 -3
- backend/src/modules/user/user.module.ts +1 -1
- backend/src/modules/user/user.service.ts +4 -7
backend/.env.example
CHANGED
@@ -3,4 +3,5 @@ DB_PORT=5432
|
|
3 |
DB_USER='pbl6_jw8s_user'
|
4 |
DB_PASSWORD=''
|
5 |
DB_NAME='pbl6_jw8s'
|
6 |
-
JWT_KEY
|
|
|
|
3 |
DB_USER='pbl6_jw8s_user'
|
4 |
DB_PASSWORD=''
|
5 |
DB_NAME='pbl6_jw8s'
|
6 |
+
JWT_KEY= ''
|
7 |
+
DB_SSL_ENABLED=true # default is true to connect with remote database
|
backend/src/app.module.ts
CHANGED
@@ -9,10 +9,7 @@ import { AppLoggerMiddleware } from './common/middlewares/app-logger.middleware.
|
|
9 |
import { DeviceInfoMiddleware } from './common/middlewares/device-info.middleware.js';
|
10 |
import { UserModule } from './modules/user/user.module.js';
|
11 |
import { BranchModule } from './modules/branch/branch.module.js';
|
12 |
-
import { AuthenticationModule } from './modules/authentication/authentication.module';
|
13 |
-
import {AccessControlModule, ACGuard} from 'nest-access-control'
|
14 |
-
import { APP_GUARD } from '@nestjs/core';
|
15 |
-
|
16 |
@Module({
|
17 |
imports: [
|
18 |
ConfigModule.forRoot({
|
|
|
9 |
import { DeviceInfoMiddleware } from './common/middlewares/device-info.middleware.js';
|
10 |
import { UserModule } from './modules/user/user.module.js';
|
11 |
import { BranchModule } from './modules/branch/branch.module.js';
|
12 |
+
import { AuthenticationModule } from './modules/authentication/authentication.module.js';
|
|
|
|
|
|
|
13 |
@Module({
|
14 |
imports: [
|
15 |
ConfigModule.forRoot({
|
backend/src/config/config.ts
CHANGED
@@ -7,5 +7,6 @@ export const configuration = () => {
|
|
7 |
'db.password': process.env.DB_PASSWORD,
|
8 |
'db.name': process.env.DB_NAME,
|
9 |
'db.slow_limit': Number(process.env.DB_SLOW_LIMIT) || 500, // ms
|
|
|
10 |
};
|
11 |
};
|
|
|
7 |
'db.password': process.env.DB_PASSWORD,
|
8 |
'db.name': process.env.DB_NAME,
|
9 |
'db.slow_limit': Number(process.env.DB_SLOW_LIMIT) || 500, // ms
|
10 |
+
'db.ssl_enabled': process.env.DB_SSL_ENABLED,
|
11 |
};
|
12 |
};
|
backend/src/config/database.ts
CHANGED
@@ -13,6 +13,7 @@ export class DatabaseConfigService implements TypeOrmOptionsFactory {
|
|
13 |
constructor(private readonly configService: ConfigService) {}
|
14 |
|
15 |
createTypeOrmOptions(): TypeOrmModuleOptions {
|
|
|
16 |
return {
|
17 |
type: 'postgres',
|
18 |
host: this.configService.get('db.host'),
|
@@ -21,9 +22,11 @@ export class DatabaseConfigService implements TypeOrmOptionsFactory {
|
|
21 |
database: this.configService.get('db.name'),
|
22 |
password: this.configService.get('db.password'),
|
23 |
entities: [path.join(__dirname, '../**/*.entity{.ts,.js}')],
|
24 |
-
ssl:
|
25 |
-
|
26 |
-
|
|
|
|
|
27 |
maxQueryExecutionTime: this.configService.get('db.slow_limit'),
|
28 |
};
|
29 |
}
|
|
|
13 |
constructor(private readonly configService: ConfigService) {}
|
14 |
|
15 |
createTypeOrmOptions(): TypeOrmModuleOptions {
|
16 |
+
const isSslEnabled = this.configService.get('db.ssl_enabled') !== 'false';
|
17 |
return {
|
18 |
type: 'postgres',
|
19 |
host: this.configService.get('db.host'),
|
|
|
22 |
database: this.configService.get('db.name'),
|
23 |
password: this.configService.get('db.password'),
|
24 |
entities: [path.join(__dirname, '../**/*.entity{.ts,.js}')],
|
25 |
+
ssl: isSslEnabled
|
26 |
+
? {
|
27 |
+
rejectUnauthorized: false,
|
28 |
+
}
|
29 |
+
: false,
|
30 |
maxQueryExecutionTime: this.configService.get('db.slow_limit'),
|
31 |
};
|
32 |
}
|
backend/src/config/typeorm.ts
CHANGED
@@ -9,6 +9,8 @@ const __dirname = path.dirname(__filename);
|
|
9 |
|
10 |
const migrationsPath = 'src/migrations/*.ts';
|
11 |
|
|
|
|
|
12 |
export default new DataSource({
|
13 |
type: 'postgres',
|
14 |
host: process.env.DB_HOST,
|
@@ -17,8 +19,10 @@ export default new DataSource({
|
|
17 |
username: process.env.DB_USER,
|
18 |
password: process.env.DB_PASSWORD,
|
19 |
entities: [path.join(__dirname, '../**/*.entity{.ts,.js}')],
|
20 |
-
ssl:
|
21 |
-
|
22 |
-
|
|
|
|
|
23 |
migrations: [migrationsPath],
|
24 |
});
|
|
|
9 |
|
10 |
const migrationsPath = 'src/migrations/*.ts';
|
11 |
|
12 |
+
const isSslEnabled = process.env.DB_SSL_ENABLED !== 'false';
|
13 |
+
|
14 |
export default new DataSource({
|
15 |
type: 'postgres',
|
16 |
host: process.env.DB_HOST,
|
|
|
19 |
username: process.env.DB_USER,
|
20 |
password: process.env.DB_PASSWORD,
|
21 |
entities: [path.join(__dirname, '../**/*.entity{.ts,.js}')],
|
22 |
+
ssl: isSslEnabled
|
23 |
+
? {
|
24 |
+
rejectUnauthorized: false,
|
25 |
+
}
|
26 |
+
: false,
|
27 |
migrations: [migrationsPath],
|
28 |
});
|
backend/src/modules/authentication/authentication.controller.spec.ts
DELETED
@@ -1,20 +0,0 @@
|
|
1 |
-
import { Test, TestingModule } from '@nestjs/testing';
|
2 |
-
import { AuthenticationController } from './authentication.controller';
|
3 |
-
import { AuthenticationService } from './authentication.service';
|
4 |
-
|
5 |
-
describe('AuthenticationController', () => {
|
6 |
-
let controller: AuthenticationController;
|
7 |
-
|
8 |
-
beforeEach(async () => {
|
9 |
-
const module: TestingModule = await Test.createTestingModule({
|
10 |
-
controllers: [AuthenticationController],
|
11 |
-
providers: [AuthenticationService],
|
12 |
-
}).compile();
|
13 |
-
|
14 |
-
controller = module.get<AuthenticationController>(AuthenticationController);
|
15 |
-
});
|
16 |
-
|
17 |
-
it('should be defined', () => {
|
18 |
-
expect(controller).toBeDefined();
|
19 |
-
});
|
20 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/src/modules/authentication/authentication.controller.ts
CHANGED
@@ -1,4 +1,3 @@
|
|
1 |
-
|
2 |
import {
|
3 |
Body,
|
4 |
Controller,
|
@@ -7,11 +6,10 @@ import {
|
|
7 |
HttpStatus,
|
8 |
Post,
|
9 |
Request,
|
10 |
-
UseGuards
|
11 |
} from '@nestjs/common';
|
12 |
-
import {
|
13 |
-
import {
|
14 |
-
|
15 |
@Controller('authentication')
|
16 |
export class AuthenticationController {
|
17 |
constructor(private AuthenticationService: AuthenticationService) {}
|
@@ -20,7 +18,10 @@ export class AuthenticationController {
|
|
20 |
@HttpCode(HttpStatus.OK)
|
21 |
@Post('login')
|
22 |
signIn(@Body() signInDto: Record<string, any>) {
|
23 |
-
return this.AuthenticationService.signIn(
|
|
|
|
|
|
|
24 |
}
|
25 |
|
26 |
// @UseGuards(AuthenticationGuard)
|
|
|
|
|
1 |
import {
|
2 |
Body,
|
3 |
Controller,
|
|
|
6 |
HttpStatus,
|
7 |
Post,
|
8 |
Request,
|
|
|
9 |
} from '@nestjs/common';
|
10 |
+
import { AuthenticationService } from './authentication.service.js';
|
11 |
+
import { Public } from './authentication.decorator.js';
|
12 |
+
|
13 |
@Controller('authentication')
|
14 |
export class AuthenticationController {
|
15 |
constructor(private AuthenticationService: AuthenticationService) {}
|
|
|
18 |
@HttpCode(HttpStatus.OK)
|
19 |
@Post('login')
|
20 |
signIn(@Body() signInDto: Record<string, any>) {
|
21 |
+
return this.AuthenticationService.signIn(
|
22 |
+
signInDto.username,
|
23 |
+
signInDto.password,
|
24 |
+
);
|
25 |
}
|
26 |
|
27 |
// @UseGuards(AuthenticationGuard)
|
backend/src/modules/authentication/authentication.guard.ts
CHANGED
@@ -1,49 +1,51 @@
|
|
1 |
-
|
2 |
import {
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
const request = context.switchToHttp().getRequest();
|
28 |
-
const token = this.extractTokenFromHeader(request);
|
29 |
-
if (!token) {
|
30 |
-
throw new UnauthorizedException();
|
31 |
-
}
|
32 |
-
try {
|
33 |
-
const payload = await this.jwtService.verifyAsync(token, {
|
34 |
-
secret: jwtConstants.secret,
|
35 |
-
});
|
36 |
-
// 💡 We're assigning the payload to the request object here
|
37 |
-
// so that we can access it in our route handlers
|
38 |
-
request['user'] = payload;
|
39 |
-
} catch {
|
40 |
-
throw new UnauthorizedException();
|
41 |
-
}
|
42 |
return true;
|
43 |
}
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
|
|
48 |
}
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import {
|
2 |
+
CanActivate,
|
3 |
+
ExecutionContext,
|
4 |
+
Injectable,
|
5 |
+
UnauthorizedException,
|
6 |
+
} from '@nestjs/common';
|
7 |
+
import { JwtService } from '@nestjs/jwt';
|
8 |
+
import { jwtConstants } from './constants.js';
|
9 |
+
import { Request } from 'express';
|
10 |
+
import { Reflector } from '@nestjs/core';
|
11 |
+
import { IS_PUBLIC_KEY } from './authentication.decorator.js';
|
12 |
+
@Injectable()
|
13 |
+
export class AuthenticationGuard implements CanActivate {
|
14 |
+
constructor(
|
15 |
+
private jwtService: JwtService,
|
16 |
+
private reflector: Reflector,
|
17 |
+
) {}
|
18 |
+
|
19 |
+
async canActivate(context: ExecutionContext): Promise<boolean> {
|
20 |
+
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
|
21 |
+
context.getHandler(),
|
22 |
+
context.getClass(),
|
23 |
+
]);
|
24 |
+
if (isPublic) {
|
25 |
+
// 💡 See this condition
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
return true;
|
27 |
}
|
28 |
+
|
29 |
+
const request = context.switchToHttp().getRequest();
|
30 |
+
const token = this.extractTokenFromHeader(request);
|
31 |
+
if (!token) {
|
32 |
+
throw new UnauthorizedException();
|
33 |
}
|
34 |
+
try {
|
35 |
+
const payload = await this.jwtService.verifyAsync(token, {
|
36 |
+
secret: jwtConstants.secret,
|
37 |
+
});
|
38 |
+
// 💡 We're assigning the payload to the request object here
|
39 |
+
// so that we can access it in our route handlers
|
40 |
+
request['user'] = payload;
|
41 |
+
} catch {
|
42 |
+
throw new UnauthorizedException();
|
43 |
+
}
|
44 |
+
return true;
|
45 |
+
}
|
46 |
+
|
47 |
+
private extractTokenFromHeader(request: Request): string | undefined {
|
48 |
+
const [type, token] = request.headers.authorization?.split(' ') ?? [];
|
49 |
+
return type === 'Bearer' ? token : undefined;
|
50 |
+
}
|
51 |
+
}
|
backend/src/modules/authentication/authentication.module.ts
CHANGED
@@ -1,11 +1,10 @@
|
|
1 |
-
|
2 |
import { Module } from '@nestjs/common';
|
3 |
-
import { AuthenticationService } from './authentication.service';
|
4 |
-
import { UserModule } from '../user/user.module';
|
5 |
import { JwtModule } from '@nestjs/jwt';
|
6 |
-
import { AuthenticationController } from './authentication.controller';
|
7 |
-
import { jwtConstants } from './constants';
|
8 |
-
import { AuthenticationGuard } from './authentication.guard';
|
9 |
import { APP_GUARD } from '@nestjs/core';
|
10 |
@Module({
|
11 |
imports: [
|
@@ -21,7 +20,7 @@ import { APP_GUARD } from '@nestjs/core';
|
|
21 |
{
|
22 |
provide: APP_GUARD,
|
23 |
useClass: AuthenticationGuard,
|
24 |
-
}
|
25 |
],
|
26 |
controllers: [AuthenticationController],
|
27 |
exports: [AuthenticationService],
|
|
|
|
|
1 |
import { Module } from '@nestjs/common';
|
2 |
+
import { AuthenticationService } from './authentication.service.js';
|
3 |
+
import { UserModule } from '../user/user.module.js';
|
4 |
import { JwtModule } from '@nestjs/jwt';
|
5 |
+
import { AuthenticationController } from './authentication.controller.js';
|
6 |
+
import { jwtConstants } from './constants.js';
|
7 |
+
import { AuthenticationGuard } from './authentication.guard.js';
|
8 |
import { APP_GUARD } from '@nestjs/core';
|
9 |
@Module({
|
10 |
imports: [
|
|
|
20 |
{
|
21 |
provide: APP_GUARD,
|
22 |
useClass: AuthenticationGuard,
|
23 |
+
},
|
24 |
],
|
25 |
controllers: [AuthenticationController],
|
26 |
exports: [AuthenticationService],
|
backend/src/modules/authentication/authentication.service.spec.ts
DELETED
@@ -1,18 +0,0 @@
|
|
1 |
-
import { Test, TestingModule } from '@nestjs/testing';
|
2 |
-
import { AuthenticationService } from './authentication.service';
|
3 |
-
|
4 |
-
describe('AuthenticationService', () => {
|
5 |
-
let service: AuthenticationService;
|
6 |
-
|
7 |
-
beforeEach(async () => {
|
8 |
-
const module: TestingModule = await Test.createTestingModule({
|
9 |
-
providers: [AuthenticationService],
|
10 |
-
}).compile();
|
11 |
-
|
12 |
-
service = module.get<AuthenticationService>(AuthenticationService);
|
13 |
-
});
|
14 |
-
|
15 |
-
it('should be defined', () => {
|
16 |
-
expect(service).toBeDefined();
|
17 |
-
});
|
18 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/src/modules/authentication/authentication.service.ts
CHANGED
@@ -1,23 +1,23 @@
|
|
1 |
-
|
2 |
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
3 |
-
import { UserService } from '../user/user.service';
|
4 |
import * as bcrypt from 'bcrypt';
|
5 |
import { JwtService } from '@nestjs/jwt';
|
6 |
@Injectable()
|
7 |
export class AuthenticationService {
|
8 |
constructor(
|
9 |
private usersService: UserService,
|
10 |
-
private jwtService: JwtService
|
11 |
) {}
|
12 |
|
13 |
-
async signIn(
|
|
|
|
|
|
|
14 |
const user = await this.usersService.findOne(username);
|
15 |
-
if (!user || await !bcrypt.compare(pass, user.hash_password)) {
|
16 |
throw new UnauthorizedException();
|
17 |
}
|
18 |
const payload = { sub: user.id, username: user.id };
|
19 |
-
// TODO: Generate a JWT and return it here
|
20 |
-
// instead of the user object
|
21 |
return {
|
22 |
access_token: await this.jwtService.signAsync(payload),
|
23 |
};
|
|
|
|
|
1 |
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
2 |
+
import { UserService } from '../user/user.service.js';
|
3 |
import * as bcrypt from 'bcrypt';
|
4 |
import { JwtService } from '@nestjs/jwt';
|
5 |
@Injectable()
|
6 |
export class AuthenticationService {
|
7 |
constructor(
|
8 |
private usersService: UserService,
|
9 |
+
private jwtService: JwtService,
|
10 |
) {}
|
11 |
|
12 |
+
async signIn(
|
13 |
+
username: string,
|
14 |
+
pass: string,
|
15 |
+
): Promise<{ access_token: string }> {
|
16 |
const user = await this.usersService.findOne(username);
|
17 |
+
if (!user || (await !bcrypt.compare(pass, user.hash_password))) {
|
18 |
throw new UnauthorizedException();
|
19 |
}
|
20 |
const payload = { sub: user.id, username: user.id };
|
|
|
|
|
21 |
return {
|
22 |
access_token: await this.jwtService.signAsync(payload),
|
23 |
};
|
backend/src/modules/user/user.controller.ts
CHANGED
@@ -1,13 +1,15 @@
|
|
1 |
import { Controller, Get, Param } from '@nestjs/common';
|
2 |
-
import { UserService } from './user.service';
|
3 |
-
import { UserEntity } from 'src/entities/user.entity';
|
4 |
|
5 |
@Controller('users')
|
6 |
export class UsersController {
|
7 |
constructor(private readonly usersService: UserService) {}
|
8 |
|
9 |
@Get(':username')
|
10 |
-
async getUser(
|
|
|
|
|
11 |
return this.usersService.findOne(username);
|
12 |
}
|
13 |
}
|
|
|
1 |
import { Controller, Get, Param } from '@nestjs/common';
|
2 |
+
import { UserService } from './user.service.js';
|
3 |
+
import { UserEntity } from 'src/entities/user.entity.js';
|
4 |
|
5 |
@Controller('users')
|
6 |
export class UsersController {
|
7 |
constructor(private readonly usersService: UserService) {}
|
8 |
|
9 |
@Get(':username')
|
10 |
+
async getUser(
|
11 |
+
@Param('username') username: string,
|
12 |
+
): Promise<UserEntity | undefined> {
|
13 |
return this.usersService.findOne(username);
|
14 |
}
|
15 |
}
|
backend/src/modules/user/user.module.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
import { Module } from '@nestjs/common';
|
2 |
-
import { UserService } from './user.service';
|
3 |
|
4 |
@Module({
|
5 |
providers: [UserService],
|
|
|
1 |
import { Module } from '@nestjs/common';
|
2 |
+
import { UserService } from './user.service.js';
|
3 |
|
4 |
@Module({
|
5 |
providers: [UserService],
|
backend/src/modules/user/user.service.ts
CHANGED
@@ -1,18 +1,15 @@
|
|
1 |
import { Injectable } from '@nestjs/common';
|
2 |
import { InjectRepository } from '@nestjs/typeorm';
|
3 |
import { Repository } from 'typeorm';
|
4 |
-
import { UserEntity } from '
|
5 |
-
|
6 |
export type User = any;
|
7 |
|
8 |
@Injectable()
|
9 |
export class UserService {
|
10 |
-
constructor(
|
11 |
-
@InjectRepository(UserEntity)
|
12 |
-
private usersRepository: Repository<UserEntity>,
|
13 |
-
) {}
|
14 |
|
15 |
async findOne(username: string): Promise<UserEntity | undefined> {
|
16 |
-
return
|
17 |
}
|
18 |
}
|
|
|
1 |
import { Injectable } from '@nestjs/common';
|
2 |
import { InjectRepository } from '@nestjs/typeorm';
|
3 |
import { Repository } from 'typeorm';
|
4 |
+
import { UserEntity } from '../../entities/user.entity.js';
|
5 |
+
|
6 |
export type User = any;
|
7 |
|
8 |
@Injectable()
|
9 |
export class UserService {
|
10 |
+
constructor() {}
|
|
|
|
|
|
|
11 |
|
12 |
async findOne(username: string): Promise<UserEntity | undefined> {
|
13 |
+
return UserEntity.findOne({ where: { id: username } });
|
14 |
}
|
15 |
}
|