feat: add user service

This commit is contained in:
Sergey Krylov 2026-03-04 06:17:03 +03:00
parent e7292e7f74
commit 4b24ffc373
11 changed files with 84 additions and 7 deletions

View File

@ -17,6 +17,7 @@ import { AuthModule } from './modules/auth/auth.module'
import { OtpModule } from './modules/otp/otp.module' import { OtpModule } from './modules/otp/otp.module'
import { TelegramModule } from './modules/telegram/telegram.module' import { TelegramModule } from './modules/telegram/telegram.module'
import { TokenModule } from './modules/token/token.module' import { TokenModule } from './modules/token/token.module'
import { UsersModule } from './modules/users/users.module'
@Module({ @Module({
imports: [ imports: [
@ -28,10 +29,11 @@ import { TokenModule } from './modules/token/token.module'
RedisModule, RedisModule,
AuthModule, AuthModule,
OtpModule, OtpModule,
UsersModule,
AccountModule, AccountModule,
TelegramModule, TelegramModule,
TokenModule, TokenModule,
MessagingModule MessagingModule,
] ]
}) })
export class AppModule {} export class AppModule {}

View File

@ -10,6 +10,9 @@ export const grpcEnv = registerAs<GrpcConfig>('grpc', () => {
return { return {
host: process.env.GRPC_HOST, host: process.env.GRPC_HOST,
port: parseInt(process.env.GRPC_PORT) port: parseInt(process.env.GRPC_PORT),
clients: {
users: process.env.USERS_GRPC_URL
}
} }
}) })

View File

@ -1,4 +1,7 @@
export interface GrpcConfig { export interface GrpcConfig {
host: string host: string
port: number port: number
clients: {
users: string
}
} }

View File

@ -6,4 +6,7 @@ export class GrpcValidator {
@IsInt() @IsInt()
public GRPC_PORT: number public GRPC_PORT: number
@IsString()
public USERS_GRPC_URL: string
} }

View File

@ -2,12 +2,14 @@ import { Module } from '@nestjs/common'
import { OtpService } from '@/modules/otp/otp.service' import { OtpService } from '@/modules/otp/otp.service'
import { TokenService } from '@/modules/token/token.service' import { TokenService } from '@/modules/token/token.service'
import { UsersModule } from '@/modules/users/users.module'
import { UserRepository } from '@/shared/utils/repositories' import { UserRepository } from '@/shared/utils/repositories'
import { AuthController } from './auth.controller' import { AuthController } from './auth.controller'
import { AuthService } from './auth.service' import { AuthService } from './auth.service'
@Module({ @Module({
imports: [UsersModule],
controllers: [AuthController], controllers: [AuthController],
providers: [AuthService, UserRepository, OtpService, TokenService] providers: [AuthService, UserRepository, OtpService, TokenService]
}) })

View File

@ -1,4 +1,5 @@
import { Injectable } from '@nestjs/common' import { Injectable } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { RpcException } from '@nestjs/microservices' import { RpcException } from '@nestjs/microservices'
import { Account } from '@prisma/generated/client' import { Account } from '@prisma/generated/client'
import { RpcStatus } from '@teacinema/common' import { RpcStatus } from '@teacinema/common'
@ -16,6 +17,7 @@ import { OtpService } from '@/modules/otp/otp.service'
import { UserRepository } from '@/shared/utils/repositories' import { UserRepository } from '@/shared/utils/repositories'
import { TokenService } from '../token/token.service' import { TokenService } from '../token/token.service'
import { UsersClientGrpc } from '../users/users.grpc'
@Injectable() @Injectable()
export class AuthService { export class AuthService {
@ -23,7 +25,9 @@ export class AuthService {
private readonly userRepository: UserRepository, private readonly userRepository: UserRepository,
private readonly otpService: OtpService, private readonly otpService: OtpService,
private readonly tokenService: TokenService, private readonly tokenService: TokenService,
private readonly messagingService: MessagingService private readonly messagingService: MessagingService,
private readonly usersClient: UsersClientGrpc,
private readonly configService: ConfigService
) {} ) {}
public async sendOtp(data: SendOtpRequest): Promise<SendOtpResponse> { public async sendOtp(data: SendOtpRequest): Promise<SendOtpResponse> {
@ -90,6 +94,8 @@ export class AuthService {
}) })
} }
this.usersClient.create({ id: account.id }).subscribe()
return this.tokenService.generateTokens(account.id) return this.tokenService.generateTokens(account.id)
} }

View File

@ -2,12 +2,14 @@ import { Module } from '@nestjs/common'
import { TelegramRepository } from '@/modules/telegram/telegram.repository' import { TelegramRepository } from '@/modules/telegram/telegram.repository'
import { TokenService } from '@/modules/token/token.service' import { TokenService } from '@/modules/token/token.service'
import { UsersModule } from '@/modules/users/users.module'
import { UserRepository } from '@/shared/utils/repositories' import { UserRepository } from '@/shared/utils/repositories'
import { TelegramController } from './telegram.controller' import { TelegramController } from './telegram.controller'
import { TelegramService } from './telegram.service' import { TelegramService } from './telegram.service'
@Module({ @Module({
imports: [UsersModule],
controllers: [TelegramController], controllers: [TelegramController],
providers: [TelegramService, TelegramRepository, TokenService, UserRepository] providers: [TelegramService, TelegramRepository, TokenService, UserRepository]
}) })

View File

@ -15,6 +15,7 @@ import { createHash, createHmac, randomBytes } from 'node:crypto'
import { AllConfigs } from '@/config' import { AllConfigs } from '@/config'
import { RedisService } from '@/infra/redis/redis.service' import { RedisService } from '@/infra/redis/redis.service'
import { TokenService } from '@/modules/token/token.service' import { TokenService } from '@/modules/token/token.service'
import { UsersClientGrpc } from '@/modules/users/users.grpc'
import { UserRepository } from '@/shared/utils/repositories' import { UserRepository } from '@/shared/utils/repositories'
import { TelegramRepository } from './telegram.repository' import { TelegramRepository } from './telegram.repository'
@ -31,7 +32,8 @@ export class TelegramService {
private readonly configService: ConfigService<AllConfigs>, private readonly configService: ConfigService<AllConfigs>,
private readonly telegramRepository: TelegramRepository, private readonly telegramRepository: TelegramRepository,
private readonly tokenService: TokenService, private readonly tokenService: TokenService,
private readonly userRepository: UserRepository private readonly userRepository: UserRepository,
private readonly usersClient: UsersClientGrpc
) { ) {
this.BOT_ID = configService.get('telegram.telegramBotId', { infer: true }) this.BOT_ID = configService.get('telegram.telegramBotId', { infer: true })
this.BOT_TOKEN = configService.get('telegram.telegramBotToken', { this.BOT_TOKEN = configService.get('telegram.telegramBotToken', {
@ -73,6 +75,8 @@ export class TelegramService {
return this.tokenService.generateTokens(exists.id) return this.tokenService.generateTokens(exists.id)
} }
this.usersClient.create({ id: exists.id }).subscribe()
const sessionId = randomBytes(16).toString('hex') const sessionId = randomBytes(16).toString('hex')
await this.redisService.set( await this.redisService.set(

View File

@ -0,0 +1,22 @@
import { Inject, Injectable, OnModuleInit } from '@nestjs/common'
import type { ClientGrpc } from '@nestjs/microservices'
import {
CreateUserRequest,
UsersServiceClient
} from '@teacinema/contracts/gen/users'
@Injectable()
export class UsersClientGrpc implements OnModuleInit {
private usersService: UsersServiceClient
constructor(@Inject('USERS_PACKAGE') private readonly client: ClientGrpc) {}
onModuleInit() {
this.usersService =
this.client.getService<UsersServiceClient>('UsersService')
}
public create(request: CreateUserRequest) {
return this.usersService.createUser(request)
}
}

View File

@ -0,0 +1,30 @@
import { Module } from '@nestjs/common'
import { ConfigService } from '@nestjs/config'
import { ClientsModule, Transport } from '@nestjs/microservices'
import { PROTO_PATHS } from '@teacinema/contracts'
import { AllConfigs } from '@/config'
import { UsersClientGrpc } from './users.grpc'
@Module({
imports: [
ClientsModule.registerAsync([
{
name: 'USERS_PACKAGE',
useFactory: (configService: ConfigService<AllConfigs>) => ({
transport: Transport.GRPC,
options: {
package: 'users.v1',
protoPath: PROTO_PATHS.USERS,
url: configService.get('grpc.clients.users', { infer: true })
}
}),
inject: [ConfigService]
}
])
],
providers: [UsersClientGrpc],
exports: [UsersClientGrpc]
})
export class UsersModule {}

View File

@ -1383,9 +1383,9 @@
integrity sha512-q3DURJbSk3k8MNWFIYaSM4LEcBgPbWa+HJmBz/nzYT4kuYitJVSXxpZ97kr0Ea+81AZwAU3JhQKlkK0SBWUi0A== integrity sha512-q3DURJbSk3k8MNWFIYaSM4LEcBgPbWa+HJmBz/nzYT4kuYitJVSXxpZ97kr0Ea+81AZwAU3JhQKlkK0SBWUi0A==
"@teacinema/contracts@^1.0.0": "@teacinema/contracts@^1.0.0":
version "1.1.1" version "1.1.2"
resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcontracts/-/1.1.1/contracts-1.1.1.tgz#69fc54e0e096cad5ecc5d8bb654d982b6c70996b" resolved "https://git.ksv741.keenetic.pro/api/packages/teacinema/npm/%40teacinema%2Fcontracts/-/1.1.2/contracts-1.1.2.tgz#74e5ce7c95515983fd299332ef095a882dbe6665"
integrity sha512-yK3Th430sWumcnm2/jyEx8dtaA59hmCvCAnul+q/JbW+C2s/AyhBEBoxToDVxx/KKTDixDePJ3O3EnNnIHGgRw== integrity sha512-LL9UqmjIX0C9kHVtyoAoNUrp0zk1u/JzNTfnU+gqTXHJhejHOSa3blVtQBO4cjTt+yYDaN89fjm5fRbL/V0dDw==
dependencies: dependencies:
"@nestjs/microservices" "^11.1.12" "@nestjs/microservices" "^11.1.12"
protoc "33.4.0" protoc "33.4.0"