This commit is contained in:
keyhan
2026-04-05 15:22:01 +03:30
commit 33be1649c4
82 changed files with 23956 additions and 0 deletions
+46
View File
@@ -0,0 +1,46 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
OneToMany,
} from 'typeorm';
import { UserRole } from '../../common/enums';
import { Application } from '../../applications/entities/application.entity';
@Entity('users')
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ unique: true })
email: string;
@Column()
password: string;
@Column()
firstName: string;
@Column()
lastName: string;
@Column({ type: 'enum', enum: UserRole, default: UserRole.USER })
role: UserRole;
@Column({ default: true })
isActive: boolean;
@Column({ nullable: true })
namespace: string; // K8s namespace assigned to user
@OneToMany(() => Application, (app: Application) => app.user)
applications: Application[];
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
}
+57
View File
@@ -0,0 +1,57 @@
import {
Controller,
Get,
Patch,
Param,
Body,
UseGuards,
Request,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { UsersService } from './users.service';
import { RolesGuard } from '../common/guards/roles.guard';
import { Roles } from '../common/decorators/roles.decorator';
import { UserRole } from '../common/enums';
@ApiTags('Users')
@ApiBearerAuth()
@Controller('users')
@UseGuards(AuthGuard('jwt'), RolesGuard)
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get('me')
@ApiOperation({ summary: 'Get current user profile' })
async getProfile(@Request() req: any) {
const user = await this.usersService.findById(req.user.id);
if (user) {
const { password, ...result } = user;
return result;
}
return null;
}
@Get()
@Roles(UserRole.ADMIN)
@ApiOperation({ summary: 'List all users (Admin only)' })
async findAll() {
return this.usersService.findAll();
}
@Patch(':id/deactivate')
@Roles(UserRole.ADMIN)
@ApiOperation({ summary: 'Deactivate a user (Admin only)' })
async deactivate(@Param('id') id: string) {
await this.usersService.deactivate(id);
return { message: 'User deactivated' };
}
@Patch(':id/activate')
@Roles(UserRole.ADMIN)
@ApiOperation({ summary: 'Activate a user (Admin only)' })
async activate(@Param('id') id: string) {
await this.usersService.activate(id);
return { message: 'User activated' };
}
}
+13
View File
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
import { User } from './entities/user.entity';
@Module({
imports: [TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}
+52
View File
@@ -0,0 +1,52 @@
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './entities/user.entity';
import { UserRole } from '../common/enums';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {}
async create(data: Partial<User>): Promise<User> {
const user = this.usersRepository.create(data);
// Assign a unique namespace based on user ID
const saved = await this.usersRepository.save(user);
saved.namespace = `user-${saved.id.split('-')[0]}`;
return this.usersRepository.save(saved);
}
async findByEmail(email: string): Promise<User | null> {
return this.usersRepository.findOne({ where: { email } });
}
async findById(id: string): Promise<User | null> {
return this.usersRepository.findOne({ where: { id } });
}
async findAll(): Promise<User[]> {
return this.usersRepository.find({
select: ['id', 'email', 'firstName', 'lastName', 'role', 'isActive', 'namespace', 'createdAt'],
});
}
async update(id: string, data: Partial<User>): Promise<User> {
const user = await this.findById(id);
if (!user) {
throw new NotFoundException('User not found');
}
Object.assign(user, data);
return this.usersRepository.save(user);
}
async deactivate(id: string): Promise<void> {
await this.usersRepository.update(id, { isActive: false });
}
async activate(id: string): Promise<void> {
await this.usersRepository.update(id, { isActive: true });
}
}