feat: add auth module
This commit is contained in:
parent
d3b4cd0f00
commit
67f60f1137
@ -25,6 +25,8 @@
|
||||
"@nestjs/core": "^11.0.1",
|
||||
"@nestjs/platform-express": "^11.0.1",
|
||||
"@nestjs/swagger": "^11.2.5",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.3",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import { Module } from '@nestjs/common'
|
||||
import { ConfigModule } from '@nestjs/config'
|
||||
|
||||
import { AuthModule } from '../modules/auth/auth.module'
|
||||
|
||||
import { AppController } from './app.controller'
|
||||
import { AppService } from './app.service'
|
||||
|
||||
@Module({
|
||||
imports: [ConfigModule.forRoot({ isGlobal: true })],
|
||||
imports: [ConfigModule.forRoot({ isGlobal: true }), AuthModule],
|
||||
controllers: [AppController],
|
||||
providers: [AppService]
|
||||
})
|
||||
|
||||
9
src/core/config/cors.config.ts
Normal file
9
src/core/config/cors.config.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface'
|
||||
import { ConfigService } from '@nestjs/config'
|
||||
|
||||
export function getCorsConfig(configService: ConfigService): CorsOptions {
|
||||
return {
|
||||
origin: configService.getOrThrow<string>('HTTP_CORS').split(','),
|
||||
credentials: true
|
||||
}
|
||||
}
|
||||
3
src/core/config/index.ts
Normal file
3
src/core/config/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './cors.config'
|
||||
export * from './swagger.config'
|
||||
export * from './validation-pipe.config'
|
||||
8
src/core/config/swagger.config.ts
Normal file
8
src/core/config/swagger.config.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { DocumentBuilder } from '@nestjs/swagger'
|
||||
|
||||
export const swaggerConfig = new DocumentBuilder()
|
||||
.setTitle('Teacinema API')
|
||||
.setDescription('API Gateway for Teacinema microservices')
|
||||
.setVersion('1.0.0')
|
||||
.addBearerAuth()
|
||||
.build()
|
||||
6
src/core/config/validation-pipe.config.ts
Normal file
6
src/core/config/validation-pipe.config.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { ValidationPipe } from '@nestjs/common'
|
||||
|
||||
export const validationPipe = new ValidationPipe({
|
||||
transform: true,
|
||||
whitelist: true
|
||||
})
|
||||
15
src/main.ts
15
src/main.ts
@ -1,9 +1,10 @@
|
||||
import { Logger } from '@nestjs/common'
|
||||
import { ConfigService } from '@nestjs/config'
|
||||
import { NestFactory } from '@nestjs/core'
|
||||
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'
|
||||
import { SwaggerModule } from '@nestjs/swagger'
|
||||
|
||||
import { AppModule } from './core/app.module'
|
||||
import { getCorsConfig, swaggerConfig, validationPipe } from './core/config'
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule)
|
||||
@ -11,17 +12,9 @@ async function bootstrap() {
|
||||
const logger = new Logger()
|
||||
const config = app.get(ConfigService)
|
||||
|
||||
app.enableCors({
|
||||
origin: config.getOrThrow<string>('HTTP_CORS').split(','),
|
||||
credentials: true
|
||||
})
|
||||
app.useGlobalPipes(validationPipe)
|
||||
|
||||
const swaggerConfig = new DocumentBuilder()
|
||||
.setTitle('Teacinema API')
|
||||
.setDescription('API Gateway for Teacinema microservices')
|
||||
.setVersion('1.0.0')
|
||||
.addBearerAuth()
|
||||
.build()
|
||||
app.enableCors(getCorsConfig(config))
|
||||
|
||||
const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig)
|
||||
SwaggerModule.setup('docs', app, swaggerDocument, {
|
||||
|
||||
19
src/modules/auth/auth.controller.ts
Normal file
19
src/modules/auth/auth.controller.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common'
|
||||
import { ApiOperation } from '@nestjs/swagger'
|
||||
|
||||
import { SendOtpRequestDto } from './dto'
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
@ApiOperation({
|
||||
summary: 'Send OTP',
|
||||
description: 'Send verification code to the user phone or email'
|
||||
})
|
||||
@Post('otp/send')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
public sendOtp(@Body() dto: SendOtpRequestDto) {
|
||||
console.log('data', dto)
|
||||
|
||||
return { ok: true }
|
||||
}
|
||||
}
|
||||
7
src/modules/auth/auth.module.ts
Normal file
7
src/modules/auth/auth.module.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { AuthController } from './auth.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [AuthController]
|
||||
})
|
||||
export class AuthModule {}
|
||||
1
src/modules/auth/dto/index.ts
Normal file
1
src/modules/auth/dto/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './rq'
|
||||
1
src/modules/auth/dto/rq/index.ts
Normal file
1
src/modules/auth/dto/rq/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './send-otp.request.dto'
|
||||
22
src/modules/auth/dto/rq/send-otp.request.dto.ts
Normal file
22
src/modules/auth/dto/rq/send-otp.request.dto.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { ApiProperty } from '@nestjs/swagger'
|
||||
import { IsEnum, IsString, Validate } from 'class-validator'
|
||||
|
||||
import { IdentifierValidator } from '../../../../shared/validators'
|
||||
|
||||
export class SendOtpRequestDto {
|
||||
@ApiProperty({
|
||||
description: 'User phone or email',
|
||||
example: '+791234567890'
|
||||
})
|
||||
@Validate(IdentifierValidator)
|
||||
@IsString()
|
||||
public identifier: string
|
||||
|
||||
@ApiProperty({
|
||||
description: 'Type of identifier',
|
||||
example: 'phone',
|
||||
enum: ['phone', 'email']
|
||||
})
|
||||
@IsEnum(['phone', 'email'])
|
||||
public type: 'phone' | 'email'
|
||||
}
|
||||
35
src/shared/validators/identifier.validator.ts
Normal file
35
src/shared/validators/identifier.validator.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import {
|
||||
isEmail,
|
||||
isPhoneNumber,
|
||||
ValidationArguments,
|
||||
ValidatorConstraint,
|
||||
ValidatorConstraintInterface
|
||||
} from 'class-validator'
|
||||
|
||||
import { SendOtpRequestDto } from '../../modules/auth/dto'
|
||||
|
||||
@ValidatorConstraint({ name: 'IdentifierValidator', async: false })
|
||||
export class IdentifierValidator implements ValidatorConstraintInterface {
|
||||
public validate(value: string, args: ValidationArguments) {
|
||||
const object = args.object as SendOtpRequestDto
|
||||
if (object.type === 'email') {
|
||||
return typeof value === 'string' && isEmail(value)
|
||||
} else if (object.type === 'phone') {
|
||||
return typeof value === 'string' && isPhoneNumber(value)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
public defaultMessage(args: ValidationArguments) {
|
||||
const object = args.object as SendOtpRequestDto
|
||||
|
||||
if (object.type === 'email') {
|
||||
return 'identifier must be a valid email'
|
||||
} else if (object.type === 'phone') {
|
||||
return 'identifier must be a valid phone number'
|
||||
}
|
||||
|
||||
return 'Invalid identifier'
|
||||
}
|
||||
}
|
||||
1
src/shared/validators/index.ts
Normal file
1
src/shared/validators/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './identifier.validator'
|
||||
29
yarn.lock
29
yarn.lock
@ -1359,6 +1359,11 @@
|
||||
"@types/methods" "^1.1.4"
|
||||
"@types/superagent" "^8.1.0"
|
||||
|
||||
"@types/validator@^13.15.3":
|
||||
version "13.15.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.15.10.tgz#742b77ec34d58554b94a76a14cef30d59e3c16b9"
|
||||
integrity sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==
|
||||
|
||||
"@types/yargs-parser@*":
|
||||
version "21.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15"
|
||||
@ -2112,6 +2117,20 @@ cjs-module-lexer@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-2.2.0.tgz#b3ca5101843389259ade7d88c77bd06ce55849ca"
|
||||
integrity sha512-4bHTS2YuzUvtoLjdy+98ykbNB5jS0+07EvFNXerqZQJ89F7DI6ET7OQo/HJuW6K0aVsKA9hj9/RVb2kQVOrPDQ==
|
||||
|
||||
class-transformer@^0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/class-transformer/-/class-transformer-0.5.1.tgz#24147d5dffd2a6cea930a3250a677addf96ab336"
|
||||
integrity sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==
|
||||
|
||||
class-validator@^0.14.3:
|
||||
version "0.14.3"
|
||||
resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.14.3.tgz#834a4caafa8359aed73d7708badb4cf271be50fe"
|
||||
integrity sha512-rXXekcjofVN1LTOSw+u4u9WXVEUvNBVjORW154q/IdmYWy1nMbOU9aNtZB0t8m+FJQ9q91jlr2f9CwwUFdFMRA==
|
||||
dependencies:
|
||||
"@types/validator" "^13.15.3"
|
||||
libphonenumber-js "^1.11.1"
|
||||
validator "^13.15.20"
|
||||
|
||||
cli-cursor@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
|
||||
@ -3666,6 +3685,11 @@ levn@^0.4.1:
|
||||
prelude-ls "^1.2.1"
|
||||
type-check "~0.4.0"
|
||||
|
||||
libphonenumber-js@^1.11.1:
|
||||
version "1.12.34"
|
||||
resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.12.34.tgz#20ed9da39e930e98eff4b6e24a8d8480303658af"
|
||||
integrity sha512-v/Ip8k8eYdp7bINpzqDh46V/PaQ8sK+qi97nMQgjZzFlb166YFqlR/HVI+MzsI9JqcyyVWCOipmmretiaSyQyw==
|
||||
|
||||
lines-and-columns@^1.1.6:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
@ -4953,6 +4977,11 @@ v8-to-istanbul@^9.0.1:
|
||||
"@types/istanbul-lib-coverage" "^2.0.1"
|
||||
convert-source-map "^2.0.0"
|
||||
|
||||
validator@^13.15.20:
|
||||
version "13.15.26"
|
||||
resolved "https://registry.yarnpkg.com/validator/-/validator-13.15.26.tgz#36c3deeab30e97806a658728a155c66fcaa5b944"
|
||||
integrity sha512-spH26xU080ydGggxRyR1Yhcbgx+j3y5jbNXk/8L+iRvdIEQ4uTRH2Sgf2dokud6Q4oAtsbNvJ1Ft+9xmm6IZcA==
|
||||
|
||||
vary@^1, vary@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user