From 0fc00be0cb3c58591b175daf7e255f2cee81894f Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Wed, 13 Aug 2025 06:45:36 +0300 Subject: [PATCH] [backend]: add minio, rename methods --- backend/compose.yaml | 16 ++++++++++++++ backend/src/core/graphql/schema.gql | 4 ++-- backend/src/core/prisma/prisma.seed.ts | 3 ++- .../module/auth/account/account.service.ts | 5 +++++ .../module/auth/account/models/user.model.ts | 2 +- .../auth/deactivate/deactivate.service.ts | 21 ++++++++++++++++++- .../module/auth/profile/profile.service.ts | 2 +- .../module/auth/session/session.service.ts | 2 +- .../module/libs/storage/storage.service.ts | 11 +++++----- .../notification/notification.resolver.ts | 6 +++--- .../notification/notification.service.ts | 12 +++++------ backend/src/shared/types/env.d.ts | 8 +++++++ 12 files changed, 71 insertions(+), 21 deletions(-) diff --git a/backend/compose.yaml b/backend/compose.yaml index bada66c..5e7189c 100644 --- a/backend/compose.yaml +++ b/backend/compose.yaml @@ -25,10 +25,26 @@ services: networks: - teastream-backend + minio: + image: minio/minio:latest + container_name: teastream-minio + ports: + - "9000:9000" + - "9001:9001" + environment: + MINIO_ROOT_USER: ${MINIO_ROOT_USER} + MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} + command: server /data --console-address ":9001" + volumes: + - minio_data:/data + networks: + - teastream-backend + volumes: postgres_data: redis_data: + minio_data: networks: teastream-backend: diff --git a/backend/src/core/graphql/schema.gql b/backend/src/core/graphql/schema.gql index 32ee9d0..7cfe9d0 100644 --- a/backend/src/core/graphql/schema.gql +++ b/backend/src/core/graphql/schema.gql @@ -142,7 +142,7 @@ type MakePaymentModel { type Mutation { changeChatSettings(data: ChangeChatSettingsInput!): StreamModel! changeEmail(data: ChangeEmailInput!): UserModel! - changeNotificationSettigs(data: ChangeNotificationSettingsInput!): ChangeNotificationsSettingsResponse! + changeNotificationSettings(data: ChangeNotificationSettingsInput!): ChangeNotificationsSettingsResponse! changePassword(data: ChangePasswordInput!): UserModel! changeProfileAvatar(avatar: Upload!): Boolean! changeProfileInfo(data: ChangeProfileInfoInput!): UserModel! @@ -370,7 +370,7 @@ type UserModel { isVerified: Boolean! name: String! notification: [NotificationModel!]! - notificationSettings: NotificationSettingsModel! + notificationSettings: NotificationSettingsModel password: String! socialLink: [SocialLinkModel!]! stream: StreamModel! diff --git a/backend/src/core/prisma/prisma.seed.ts b/backend/src/core/prisma/prisma.seed.ts index 98f8962..d35cbe7 100644 --- a/backend/src/core/prisma/prisma.seed.ts +++ b/backend/src/core/prisma/prisma.seed.ts @@ -1,7 +1,8 @@ import { BadRequestException, Logger } from '@nestjs/common'; import { hash } from 'argon2'; -import { Prisma, PrismaClient } from '@/prisma/generated'; +// eslint-disable-next-line +import { Prisma, PrismaClient } from '../../../prisma/generated'; import { CATEGORIES } from './data/categories.data'; import { STREAMS } from './data/streams.data'; diff --git a/backend/src/module/auth/account/account.service.ts b/backend/src/module/auth/account/account.service.ts index ea16935..e5653a1 100644 --- a/backend/src/module/auth/account/account.service.ts +++ b/backend/src/module/auth/account/account.service.ts @@ -21,6 +21,11 @@ export class AccountService { where: { id, }, + include: { + socialLink: true, + stream: true, + notificationSettings: true, + }, }); } diff --git a/backend/src/module/auth/account/models/user.model.ts b/backend/src/module/auth/account/models/user.model.ts index 4a593e6..93d6c7c 100644 --- a/backend/src/module/auth/account/models/user.model.ts +++ b/backend/src/module/auth/account/models/user.model.ts @@ -66,7 +66,7 @@ export class UserModel implements User { @Field(() => [NotificationModel]) notification: NotificationModel[]; - @Field(() => NotificationSettingsModel) + @Field(() => NotificationSettingsModel, { nullable: true }) notificationSettings: NotificationSettingsModel; @Field(() => Date) diff --git a/backend/src/module/auth/deactivate/deactivate.service.ts b/backend/src/module/auth/deactivate/deactivate.service.ts index 605ae3e..d9b5234 100644 --- a/backend/src/module/auth/deactivate/deactivate.service.ts +++ b/backend/src/module/auth/deactivate/deactivate.service.ts @@ -3,6 +3,7 @@ import { ConfigService } from '@nestjs/config'; import { verify } from 'argon2'; import { PrismaService } from '@/src/core/prisma/prisma.service'; +import { RedisService } from '@/src/core/redis/redis.service'; import { DeactivateAccountInput } from '@/src/module/auth/deactivate/inputs/deactivate-account.input'; import { MailService } from '@/src/module/libs/mail/mail.service'; import { TelegramService } from '@/src/module/libs/telegram/telegram.service'; @@ -19,6 +20,7 @@ import type { Request } from 'express'; export class DeactivateService { constructor( private readonly prismaService: PrismaService, + private readonly redisService: RedisService, private readonly configService: ConfigService, private readonly mailService: MailService, private readonly telegramService: TelegramService, @@ -82,7 +84,7 @@ export class DeactivateService { throw new BadRequestException('Токен истек'); } - await this.prismaService.user.update({ + const user = await this.prismaService.user.update({ where: { id: existingToken.userId }, data: { isDeactivated: true, @@ -96,7 +98,24 @@ export class DeactivateService { type: TokenType.DEACTIVATE_ACCOUNT, }, }); + await this.clearSessions(user.id); return destroySession(req, this.configService); } + + private async clearSessions(userId: string) { + const keys = await this.redisService.keys('*'); + + for (const key of keys) { + const sessionData = await this.redisService.get(key); + + if (sessionData) { + const session = JSON.parse(sessionData); + + if (session.userId === userId) { + await this.redisService.del(key); + } + } + } + } } diff --git a/backend/src/module/auth/profile/profile.service.ts b/backend/src/module/auth/profile/profile.service.ts index 5714a10..c9bae67 100644 --- a/backend/src/module/auth/profile/profile.service.ts +++ b/backend/src/module/auth/profile/profile.service.ts @@ -1,6 +1,6 @@ import { ConflictException, Injectable } from '@nestjs/common'; import * as Upload from 'graphql-upload/Upload.js'; -import sharp from 'sharp'; +import * as sharp from 'sharp'; import { SocialLink, User } from '@/prisma/generated'; import { PrismaService } from '@/src/core/prisma/prisma.service'; diff --git a/backend/src/module/auth/session/session.service.ts b/backend/src/module/auth/session/session.service.ts index c0acda7..68865ff 100644 --- a/backend/src/module/auth/session/session.service.ts +++ b/backend/src/module/auth/session/session.service.ts @@ -89,7 +89,7 @@ export class SessionService { }, }); - if (!user) { + if (!user || user.isDeactivated) { throw new NotFoundException('Пользователь не найден'); } diff --git a/backend/src/module/libs/storage/storage.service.ts b/backend/src/module/libs/storage/storage.service.ts index 456c9ad..d16db9b 100644 --- a/backend/src/module/libs/storage/storage.service.ts +++ b/backend/src/module/libs/storage/storage.service.ts @@ -20,15 +20,16 @@ export class StorageService { private readonly configService: ConfigService, ) { this.client = new S3Client({ - endpoint: this.configService.getOrThrow('S3_ENDPOINT'), - region: this.configService.getOrThrow('S3_REGION'), + endpoint: this.configService.getOrThrow('MINIO_ENDPOINT'), + region: this.configService.getOrThrow('MINIO_REGION'), credentials: { - accessKeyId: this.configService.getOrThrow('S3_ACCESS_KEY_ID'), - secretAccessKey: this.configService.getOrThrow('S3_SECRET_KEY_ID'), + accessKeyId: this.configService.getOrThrow('MINIO_ACCESS_KEY'), + secretAccessKey: this.configService.getOrThrow('MINIO_SECRET_KEY'), }, + forcePathStyle: true, }); - this.bucket = this.configService.getOrThrow('S3_BUCKET_NAME'); + this.bucket = this.configService.getOrThrow('MINIO_BUCKET_NAME'); } public async upload(buffer: Buffer, key: string, mimetype: string) { diff --git a/backend/src/module/notification/notification.resolver.ts b/backend/src/module/notification/notification.resolver.ts index 6fe6a40..c65cf7f 100644 --- a/backend/src/module/notification/notification.resolver.ts +++ b/backend/src/module/notification/notification.resolver.ts @@ -2,12 +2,12 @@ import { Args, Mutation, Query, Resolver, } from '@nestjs/graphql'; -import { ChangeNotificationSettingsInput } from '@/src/module/notification/inputs/change-notification-settings.input'; -import { ChangeNotificationsSettingsResponse } from '@/src/module/notification/models/notification-settings.model'; import { Authorization } from '@/src/shared/decorators/auth.decorator'; import { Authorized } from '@/src/shared/decorators/authorized.decorator'; import { User } from '@prisma/generated'; +import { ChangeNotificationSettingsInput } from './inputs/change-notification-settings.input'; +import { ChangeNotificationsSettingsResponse } from './models/notification-settings.model'; import { NotificationModel } from './models/notification.model'; import { NotificationService } from './notification.service'; @@ -28,7 +28,7 @@ export class NotificationResolver { } @Authorization() - @Mutation(() => ChangeNotificationsSettingsResponse, { name: 'changeNotificationSettigs' }) + @Mutation(() => ChangeNotificationsSettingsResponse, { name: 'changeNotificationSettings' }) public async changeSettings( @Authorized() user: User, @Args('data') input: ChangeNotificationSettingsInput, diff --git a/backend/src/module/notification/notification.service.ts b/backend/src/module/notification/notification.service.ts index 3153d82..27e5590 100644 --- a/backend/src/module/notification/notification.service.ts +++ b/backend/src/module/notification/notification.service.ts @@ -42,7 +42,7 @@ export class NotificationService { public async changeSettings(user: User, input: ChangeNotificationSettingsInput) { const { siteNotifications, telegramNotifications } = input; - const notificationSetting = await this.prismaService.notificationSettings.upsert({ + const notificationSettings = await this.prismaService.notificationSettings.upsert({ where: { userId: user.id }, create: { siteNotifications, @@ -53,7 +53,7 @@ export class NotificationService { include: { user: true }, }); - if (notificationSetting.telegramNotifications && !notificationSetting.user.telegramId) { + if (notificationSettings.telegramNotifications && !notificationSettings.user.telegramId) { const telegramAuthToken = await generateToken( this.prismaService, user, @@ -61,21 +61,21 @@ export class NotificationService { ); return { - notificationSetting, + notificationSettings, telegramAuthToken: telegramAuthToken.token, }; } - if (!notificationSetting.telegramNotifications && notificationSetting.user.telegramId) { + if (!notificationSettings.telegramNotifications && notificationSettings.user.telegramId) { await this.prismaService.user.update({ where: { id: user.id }, data: { telegramId: null }, }); - return { notificationSetting }; + return { notificationSettings }; } - return { notificationSetting }; + return { notificationSettings }; } public async createStreamStart(userId: string, channel: User) { diff --git a/backend/src/shared/types/env.d.ts b/backend/src/shared/types/env.d.ts index 83215eb..398f8a6 100644 --- a/backend/src/shared/types/env.d.ts +++ b/backend/src/shared/types/env.d.ts @@ -42,6 +42,14 @@ export type ProcessEnv = { S3_SECRET_KEY_ID: string; S3_BUCKET_NAME: string; + MINIO_ROOT_USER: string; + MINIO_ROOT_PASSWORD: string; + MINIO_ENDPOINT: string; + MINIO_ACCESS_KEY: string; + MINIO_SECRET_KEY: string; + MINIO_BUCKET_NAME: string; + MINIO_REGION: string; + LIVEKIT_URL: string; LIVEKIT_API_KEY: string; LIVEKIT_API_SECRET: string;