Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/api/.env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# Переменные среды для приложения API
JWT_SECRET=секретный_ключ_jwt
JWT_ACCESS_TOKEN_TTL=время_жизни_токена_доступа
JWT_REFRESH_TOKEN_TTL=время_жизни_токена_обновления

# PostgreSQL Database URL
# Формат: postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA
DATABASE_URL="postgresql://postgres:password@host:port/mydb?schema=public"
DIRECT_URL="postgresql://postgres:password@host:port/mydb"

# Node Environment
NODE_ENV="development"
4 changes: 3 additions & 1 deletion apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
"@nestjs/common": "^11.1.11",
"@nestjs/config": "^4.0.3",
"@nestjs/core": "^11.1.11",
"@nestjs/jwt": "^11.0.2",
"@nestjs/platform-express": "^11.1.11",
"@nestjs/swagger": "^11.2.6",
"@prisma/adapter-pg": "^7.4.0",
"@prisma/client": "^7.4.0",
"@repo/api": "workspace:*",
"@repo/types": "workspace:*",
"argon2": "^0.44.0",
"dotenv": "^17.3.1",
"escape-html": "^1.0.3",
"nestjs-zod": "^5.1.1",
Expand Down
1 change: 0 additions & 1 deletion apps/api/prisma/prisma.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Pool } from 'pg'
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
constructor() {
console.log('DATABASE_URL in PrismaService:', process.env['DATABASE_URL'])
const pool = new Pool({ connectionString: process.env['DATABASE_URL'] })
const adapter = new PrismaPg(pool)
super({ adapter })
Expand Down
3 changes: 2 additions & 1 deletion apps/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { CustomZodValidationPipe } from './common/providers/zod-validation.provi
AppService,
{ provide: APP_PIPE, useClass: CustomZodValidationPipe },
{ provide: APP_INTERCEPTOR, useClass: ZodSerializerInterceptor },
],
]
})

export class AppModule {}
10 changes: 10 additions & 0 deletions apps/api/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { JwtModule } from '@nestjs/jwt';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { getJwtConfig } from './config/jwt.config';

@Module({
imports: [
JwtModule.registerAsync({
imports: [ConfigModule],
useFactory: getJwtConfig,
inject: [ConfigService],
})
],
controllers: [AuthController],
providers: [AuthService],
})
Expand Down
40 changes: 37 additions & 3 deletions apps/api/src/auth/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,30 @@
import { hash } from 'argon2'
import { ConfigService } from '@nestjs/config'
import { ConflictException, Injectable } from '@nestjs/common'
import { JwtService } from '@nestjs/jwt'

import { RegisterRequestDto } from './dto/register.dto'
import { PrismaService } from '../../prisma/prisma.service'
import { JwtPayload } from './interfaces/jwt.interface'

@Injectable()
export class AuthService {
constructor(private readonly prismaService: PrismaService) {}
private readonly JWT_SECRET: string
private readonly JWT_ACCESS_TOKEN_TTL
private readonly JWT_REFRESH_TOKEN_TTL

constructor(
private readonly prismaService: PrismaService,
private readonly configService: ConfigService,
private readonly jwtService: JwtService,
) {
this.JWT_SECRET = this.configService.getOrThrow<string>('JWT_SECRET')
this.JWT_ACCESS_TOKEN_TTL =
this.configService.getOrThrow<string>('JWT_ACCESS_TOKEN_TTL')
this.JWT_REFRESH_TOKEN_TTL = this.configService.getOrThrow<string>(
'JWT_REFRESH_TOKEN_TTL',
)
}

async register(dto: RegisterRequestDto) {
const { name, email, password } = dto
Expand All @@ -23,10 +43,24 @@
data: {
name,
email,
password,
password: await hash(password),

Check warning on line 46 in apps/api/src/auth/auth.service.ts

View workflow job for this annotation

GitHub Actions / ci

Unsafe argument of type error typed assigned to a parameter of type `string | Buffer<ArrayBufferLike>`
},
})

return user
return this.generateTokens(user.id)

Check warning on line 50 in apps/api/src/auth/auth.service.ts

View workflow job for this annotation

GitHub Actions / ci

Unsafe argument of type error typed assigned to a parameter of type `string`
}

private generateTokens(userId: string) {
const payload: JwtPayload = { id: userId }

const accessToken = this.jwtService.sign(payload, {
expiresIn: this.JWT_ACCESS_TOKEN_TTL,
})

const refreshToken = this.jwtService.sign(payload, {
expiresIn: this.JWT_REFRESH_TOKEN_TTL,
})

return { accessToken, refreshToken }
}
}
13 changes: 13 additions & 0 deletions apps/api/src/auth/config/jwt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ConfigService } from '@nestjs/config'
import type { JwtModuleOptions } from '@nestjs/jwt'

export async function getJwtConfig(
configService: ConfigService,
): Promise<JwtModuleOptions> {
return {
secret: configService.getOrThrow<string>('JWT_SECRET'),
signOptions: {
algorithm: 'HS256',
},
}
}
2 changes: 1 addition & 1 deletion apps/api/src/auth/dto/register.dto.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { createZodDto } from 'nestjs-zod'
import { registerRequestSchema } from '@repo/api'
import { registerRequestSchema } from '@repo/types'

// Создаём DTO класс для NestJS и Swagger из схемы
export class RegisterRequestDto extends createZodDto(registerRequestSchema) {}
3 changes: 3 additions & 0 deletions apps/api/src/auth/interfaces/jwt.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface JwtPayload {
id: string
}
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"zustand": "^5.0.11"
},
"devDependencies": {
"@repo/api": "workspace:*",
"@repo/types": "workspace:*",
"@repo/eslint-config": "workspace:*",
"@repo/typescript-config": "workspace:*",
"@tailwindcss/postcss": "^4.2.0",
Expand Down
2 changes: 1 addition & 1 deletion docs/backend/validation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export type RegisterRequest = z.infer<typeof registerRequestSchema>
// apps/api/src/auth/dto/register.dto.ts
import { createZodDto } from 'nestjs-zod'

import { registerRequestSchema } from '@repo/api'
import { registerRequestSchema } from '@repo/types'

export class RegisterRequestDto extends createZodDto(registerRequestSchema) {}
```
Expand Down
2 changes: 1 addition & 1 deletion docs/validation/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export type { RegisterRequest } from './auth/dto/register.dto'
```typescript
import { createZodDto } from 'nestjs-zod'

import { registerRequestSchema } from '@repo/api'
import { registerRequestSchema } from '@repo/types'

export class RegisterRequestDto extends createZodDto(registerRequestSchema) {}
```
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion packages/api/package.json → packages/types/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@repo/api",
"name": "@repo/types",
"version": "0.0.0",
"private": true,
"license": "MIT",
Expand Down
File renamed without changes.
File renamed without changes.
Loading