-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: setup local passport * feat: apply local passport & setup loccal strategy * feat: apply local auth guard & user login controller * feat: setup passport-jwt * feat: setup jwt env value & check whether jwt env is set during initialization * refactor: put insensitive user information into jwt * refactor: set config as global variables * feat: setup jwt settings * feat: apply jwt when login return jwt token * feat: setting default jwt secert for jest test * feat: setup jest test need modules * feat: add swagger description * feat: make local auth guard test * feat: make localStrategy test * feat: make jwt auth guard test * feat: make auth service test * refactor: reduce unnecessary code * refactor: reduce unnecessary return information * feat: make auth controller test login route * refactor: revise the filename definition which is use for user login unauthorized error * refactor: set mock environment variable * refactor: jest test use mock environment variable * feat: add JWT_SECRET .env.example * refactor: revised that Response instead of Respose * refactor: revised grammar questions about words * refactor: revised the error message of IsNotEmpty in login-user.dto.ts * fix: restore proper authentication * refactor: revised recommend in auth.service.ts * fix: delete email field in jwt payload * fix: delete default secret * fix: use forbidden when account information is wrong * refactor: make fake access token as a variable * feat: add unit test for non-existent account and wrong password * refactor: add type devDependencies about passport * fix: fix authController request type error * refactor: change jwt* to jwtAccess* * test: revised to match this functional description in localAuthGuard * refactor: remove meanless comment * refactor: delete jwtAccessConfigJest use by jwtAccessConfig * refactor: check all errors first and only respond when everything is correct * refactor: revised auth login api response description * refactor: revised spelling mistakes * test: change to httpException because the test will always passed due to the assertion * feat: add refresh token secret setting * feat: add auth refresh api * test: delete jwtAccessConfig * test: use time mock to achieve time acceleration * test: add refresh token unit test * feat: add validation field information in LocalAuthGuard * test: add validation field information in LocalAuthGuard * test: add a user found in UserService * test: add a script to test a file * test: add unit test coverage inspection scope * feat: enable BearerAuth functionality for Swagger * feat: add Swagger documentation for the refresh token API * refactor: correct spelling which is BadRequest * refactor: add swagger securitySchemes * test: optimize the code according to the suggestions * refactor: revise the document according to the OpenAPI specifications
- Loading branch information
Showing
38 changed files
with
1,251 additions
and
200 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,24 @@ | ||
import { type HttpException, ConflictException } from "@nestjs/common"; | ||
import { ConflictException } from "@nestjs/common"; | ||
import { ConfigModule } from "@nestjs/config"; | ||
import { JwtModule } from "@nestjs/jwt"; | ||
import { PassportModule } from "@nestjs/passport"; | ||
import { type TestingModule, Test } from "@nestjs/testing"; | ||
import { getRepositoryToken, TypeOrmModule } from "@nestjs/typeorm"; | ||
import { type Request } from "express"; | ||
import { dataSourceJest } from "src/config/data-source"; | ||
import jestConfig from "src/config/jest.config"; | ||
import { UserEntity } from "src/user/entities/user.entity"; | ||
import type { CreateUserRespose } from "src/user/resposes/create-user-respose"; | ||
import type { CreateUserResponse } from "src/user/responses/create-user-response"; | ||
import { UserService } from "src/user/user.service"; | ||
import type { Repository } from "typeorm"; | ||
|
||
import type { CreateUserDto } from "../user/dto/create-user.dto"; | ||
import { AuthController } from "./auth.controller"; | ||
import { AuthService } from "./auth.service"; | ||
import { type JwtUser } from "./jwt/jwt.interface"; | ||
import { JwtAccessStrategy } from "./jwt/jwt-access.strategy"; | ||
import { LocalStrategy } from "./local/local.strategy"; | ||
import { type GenerateTokenResponse } from "./responses/generate-token.response"; | ||
|
||
describe("AuthController", () => { | ||
let authController: AuthController; | ||
|
@@ -19,7 +28,14 @@ describe("AuthController", () => { | |
beforeEach(async () => { | ||
const module: TestingModule = await Test.createTestingModule({ | ||
controllers: [AuthController], | ||
imports: [TypeOrmModule.forRoot(dataSourceJest)], | ||
imports: [ | ||
ConfigModule.forRoot({ | ||
load: [jestConfig], | ||
}), | ||
PassportModule, | ||
TypeOrmModule.forRoot(dataSourceJest), | ||
JwtModule.register({}), | ||
], | ||
providers: [ | ||
AuthService, | ||
UserService, | ||
|
@@ -28,6 +44,8 @@ describe("AuthController", () => { | |
// 使用測試資料庫的 Repository | ||
useValue: UserEntity, | ||
}, | ||
LocalStrategy, | ||
JwtAccessStrategy, | ||
], | ||
}).compile(); | ||
|
||
|
@@ -39,43 +57,90 @@ describe("AuthController", () => { | |
}); | ||
|
||
describe("create", () => { | ||
const createUserDto: CreateUserDto = { | ||
account: "account", | ||
email: "[email protected]", | ||
name: "displayname", | ||
password: "Password@123", | ||
}; | ||
let mockedAuthService: jest.SpyInstance; | ||
|
||
beforeEach(async () => { | ||
mockedAuthService = jest.spyOn(authService, "register"); | ||
}); | ||
|
||
it("應該會創建一個使用者,並返回 201 狀態碼", async () => { | ||
const createUserDto: CreateUserDto = { | ||
account: "account", | ||
email: "[email protected]", | ||
name: "displayname", | ||
password: "Password@123", | ||
}; | ||
const expectedResponse: CreateUserRespose = { | ||
const expectedResponse: CreateUserResponse = { | ||
message: "創建成功", | ||
statusCode: 201, | ||
}; | ||
|
||
jest.spyOn(authService, "register").mockResolvedValue(expectedResponse); | ||
mockedAuthService.mockResolvedValue(expectedResponse); | ||
|
||
const result = await authController.register(createUserDto); | ||
|
||
expect(result).toEqual(expectedResponse); | ||
}); | ||
|
||
it("應該會發生資料使用者重覆,並返回 409 狀態碼", async () => { | ||
const createUserDto1: CreateUserDto = { | ||
account: "account1", | ||
email: "[email protected]", | ||
name: "displayname", | ||
password: "Password@123", | ||
await authService.register(createUserDto); | ||
await authService.register(createUserDto).catch(error => { | ||
expect(error).toBeInstanceOf(ConflictException); | ||
expect((error as ConflictException).getResponse()).toEqual({ | ||
error: "Conflict", | ||
message: ["email 已被註冊。", "account 已被註冊。"], | ||
statusCode: 409, | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("login and refresh", () => { | ||
const request: Request = { | ||
user: { | ||
id: 1, | ||
} as JwtUser, | ||
} as unknown as Request; | ||
const fakeAccessToken = "mocked_access_token"; | ||
const fakeRefreshToken = "mocked_refresh_token"; | ||
let mockedAuthService: jest.SpyInstance; | ||
|
||
beforeEach(async () => { | ||
jest | ||
.spyOn(authService, "generateAccessToken") | ||
.mockReturnValue(Promise.resolve(fakeAccessToken)); | ||
|
||
jest | ||
.spyOn(authService, "generateRefreshToken") | ||
.mockReturnValue(Promise.resolve(fakeRefreshToken)); | ||
|
||
mockedAuthService = jest.spyOn(authService, "sign"); | ||
}); | ||
|
||
it("should return access, refresh token and 201 http code when account information is correct.", async () => { | ||
const result = await authController.login(request); | ||
|
||
expect(mockedAuthService).toHaveBeenCalledWith(request.user); | ||
const expectedResponse: GenerateTokenResponse = { | ||
accessToken: fakeAccessToken, | ||
refreshToken: fakeRefreshToken, | ||
statusCode: 201, | ||
}; | ||
|
||
await authService.register(createUserDto1); | ||
await authService | ||
.register(createUserDto1) | ||
.catch((error: HttpException) => { | ||
expect(error).toBeInstanceOf(ConflictException); | ||
expect(error.getResponse()).toEqual({ | ||
error: "Conflict", | ||
message: ["email 已被註冊。", "account 已被註冊。"], | ||
statusCode: 409, | ||
}); | ||
}); | ||
expect(result).toEqual(expectedResponse); | ||
}); | ||
|
||
it("should return access, refresh token and 201 http code when refresh token is correct.", async () => { | ||
const result = await authController.refresh(request); | ||
|
||
expect(mockedAuthService).toHaveBeenCalledWith(request.user); | ||
const expectedResponse: GenerateTokenResponse = { | ||
accessToken: fakeAccessToken, | ||
refreshToken: fakeRefreshToken, | ||
statusCode: 201, | ||
}; | ||
|
||
expect(result).toEqual(expectedResponse); | ||
}); | ||
}); | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,29 @@ | ||
import { Module } from "@nestjs/common"; | ||
import { JwtModule } from "@nestjs/jwt"; | ||
import { PassportModule } from "@nestjs/passport"; | ||
import { TypeOrmModule } from "@nestjs/typeorm"; | ||
import { UserEntity } from "src/user/entities/user.entity"; | ||
import { UserModule } from "src/user/user.module"; | ||
|
||
import { AuthController } from "./auth.controller"; | ||
import { AuthService } from "./auth.service"; | ||
import { JwtAccessStrategy } from "./jwt/jwt-access.strategy"; | ||
import { JwtRefreshStrategy } from "./jwt/jwt-refresh.strategy"; | ||
import { LocalStrategy } from "./local/local.strategy"; | ||
|
||
@Module({ | ||
controllers: [AuthController], | ||
imports: [UserModule, TypeOrmModule.forFeature([UserEntity])], | ||
providers: [AuthService], | ||
imports: [ | ||
UserModule, | ||
PassportModule, | ||
TypeOrmModule.forFeature([UserEntity]), | ||
JwtModule.register({}), | ||
], | ||
providers: [ | ||
AuthService, | ||
LocalStrategy, | ||
JwtAccessStrategy, | ||
JwtRefreshStrategy, | ||
], | ||
}) | ||
export class AuthModule {} |
Oops, something went wrong.