first commit

This commit is contained in:
Oscar
2026-06-02 15:52:22 +03:00
commit dc44cdd639
105 changed files with 14674 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
import { ApiPropertyOptional } from '@nestjs/swagger';
import { IsOptional, IsString } from 'class-validator';
export class UpdateUserDto {
@ApiPropertyOptional()
@IsOptional()
@IsString()
fcmToken?: string;
}

View File

@@ -0,0 +1,43 @@
import { Controller, Get, Param, Patch, UseGuards } from '@nestjs/common';
import { ApiBearerAuth, ApiOperation, ApiTags } from '@nestjs/swagger';
import { CurrentUser } from '../../common/decorators/current-user.decorator';
import { Roles } from '../../common/decorators/roles.decorator';
import { JwtAuthGuard } from '../../common/guards/jwt-auth.guard';
import { RolesGuard } from '../../common/guards/roles.guard';
import { UsersService } from './users.service';
@ApiTags('users')
@ApiBearerAuth()
@UseGuards(JwtAuthGuard)
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get('me')
@ApiOperation({ summary: 'Get current user profile' })
getMe(@CurrentUser('id') userId: string) {
return this.usersService.getMyProfile(userId);
}
@Get(':id')
@ApiOperation({ summary: 'Get user by ID' })
findOne(@Param('id') id: string) {
return this.usersService.findById(id);
}
@Patch(':id/ban')
@Roles('admin', 'moderator')
@UseGuards(RolesGuard)
@ApiOperation({ summary: 'Ban user (admin/moderator only)' })
ban(@Param('id') id: string) {
return this.usersService.banUser(id);
}
@Patch(':id/activate')
@Roles('admin', 'moderator')
@UseGuards(RolesGuard)
@ApiOperation({ summary: 'Activate user (admin/moderator only)' })
activate(@Param('id') id: string) {
return this.usersService.activateUser(id);
}
}

View File

@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
@Module({
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}

View File

@@ -0,0 +1,71 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { eq } from 'drizzle-orm';
import { DrizzleService } from '../../database/drizzle.service';
import { user, profile, media, role } from '../../database/schema';
@Injectable()
export class UsersService {
constructor(private readonly drizzleService: DrizzleService) {}
async findById(id: string) {
const [found] = await this.drizzleService.db
.select()
.from(user)
.where(eq(user.id, id))
.limit(1);
if (!found) throw new NotFoundException('User not found');
const { password, ...rest } = found;
return rest;
}
async findByIdWithProfile(id: string) {
const [found] = await this.drizzleService.db
.select()
.from(user)
.leftJoin(profile, eq(profile.userId, user.id))
.where(eq(user.id, id))
.limit(1);
if (!found) throw new NotFoundException('User not found');
return found;
}
async getMyProfile(userId: string) {
const result = await this.drizzleService.db
.select()
.from(user)
.leftJoin(profile, eq(profile.userId, user.id))
.leftJoin(role, eq(role.id, user.roleId))
.where(eq(user.id, userId))
.limit(1);
if (!result.length) throw new NotFoundException('User not found');
const row = result[0];
const { password, ...userFields } = row.user;
return { ...userFields, profile: row.profile, role: row.role };
}
async getMediaByUserId(userId: string) {
return this.drizzleService.db
.select()
.from(media)
.where(eq(media.userId, userId));
}
async banUser(userId: string) {
await this.drizzleService.db
.update(user)
.set({ status: 'banned' } as any)
.where(eq(user.id, userId));
return { message: 'User banned' };
}
async activateUser(userId: string) {
await this.drizzleService.db
.update(user)
.set({ status: 'active' } as any)
.where(eq(user.id, userId));
return { message: 'User activated' };
}
}