Compare commits
2 Commits
86f6614f56
...
a9650366eb
| Author | SHA1 | Date |
|---|---|---|
|
|
a9650366eb | |
|
|
39c7bc8fc0 |
34
.env
34
.env
|
|
@ -1,19 +1,19 @@
|
|||
# Прометеус
|
||||
#PROMETHEUS_API=http://192.168.2.34:9090/api/v1
|
||||
PROMETHEUS_API=http://192.168.2.34:9090/api/v1
|
||||
|
||||
#FRONTEND_URL=192.168.2.39:5173
|
||||
FRONTEND_URL=localhost:5173
|
||||
|
||||
# Постгресс
|
||||
#DB_HOST=192.168.2.37
|
||||
#DB_PORT=5432
|
||||
#DB_USER=trust
|
||||
#DB_PASSWORD=kaiqolzp2a4aH
|
||||
#DB_NAME=trust-db
|
||||
DB_HOST=192.168.2.37
|
||||
DB_PORT=5432
|
||||
DB_USER=trust
|
||||
DB_PASSWORD=kaiqolzp2a4aH
|
||||
DB_NAME=trust-db
|
||||
|
||||
|
||||
# JWT
|
||||
#JWT_SECRET=x7F!2p9L#q1$z0*8R5vYgMnBk
|
||||
#JWT_SECRET=x7Fcdp9L#q1$z0*8R5vYgMnBk
|
||||
JWT_SECRET=x7Fcdp9Lq1$z0*8R5vYgMnBk
|
||||
|
||||
# COOKIE
|
||||
# Для production
|
||||
|
|
@ -21,18 +21,18 @@
|
|||
#COOKIE_SAME_SITE=strict
|
||||
|
||||
# Для development
|
||||
#COOKIE_SECURE=false
|
||||
#COOKIE_SAME_SITE=lax
|
||||
COOKIE_SECURE=false
|
||||
COOKIE_SAME_SITE=lax
|
||||
|
||||
# Для меню
|
||||
#RANGES_API_URL=http://192.168.2.39:9999
|
||||
#RANGES_API_ENDPOINT=/api/ranges/9999
|
||||
RANGES_API_URL=http://192.168.2.39:9999
|
||||
RANGES_API_ENDPOINT=/api/ranges/9999
|
||||
|
||||
# ClickHouse
|
||||
#CLICKHOUSE_HOST=http://192.168.2.37:8123
|
||||
#CLICKHOUSE_USER=vlad
|
||||
#CLICKHOUSE_PASSWORD=vlad
|
||||
#CLICKHOUSE_DB=zvks
|
||||
CLICKHOUSE_HOST=http://192.168.2.37:8123
|
||||
CLICKHOUSE_USER=vlad
|
||||
CLICKHOUSE_PASSWORD=vlad
|
||||
CLICKHOUSE_DB=zvks
|
||||
|
||||
# Для ai api
|
||||
#AI_SERVICE_URL=http://192.168.2.39:5134
|
||||
AI_SERVICE_URL=http://192.168.2.39:5134
|
||||
|
|
@ -10,4 +10,6 @@ COPY . .
|
|||
|
||||
ENV NODE_ENV=development
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["npm", "run", "start:dev"]
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,8 +1,9 @@
|
|||
import { Controller, Post, Get, Body, Res, Req, UnauthorizedException, UseGuards } from '@nestjs/common';
|
||||
import { Controller, Post, Get, Body, Res, Req, UnauthorizedException, UseGuards, ForbiddenException, Delete, Param } from '@nestjs/common';
|
||||
import { AuthService } from './auth.service';
|
||||
import { Response, Request } from 'express';
|
||||
import { JwtAuthGuard } from './jwt-auth.guard';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { User } from './user.entity';
|
||||
|
||||
@Controller('auth')
|
||||
export class AuthController {
|
||||
|
|
@ -77,4 +78,41 @@ export class AuthController {
|
|||
res.clearCookie('access_token');
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get('users')
|
||||
async getAllUsers(@Req() req: Request) {
|
||||
const user = req.user as User;
|
||||
const isAdmin = await this.authService.isAdmin(user.id);
|
||||
if (!isAdmin) {
|
||||
throw new ForbiddenException('Only admin can access this resource');
|
||||
}
|
||||
return this.authService.getAllUsers();
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('users')
|
||||
async createUser(
|
||||
@Body() body: { login: string; password: string; role?: 'user' | 'admin' },
|
||||
@Req() req: Request
|
||||
) {
|
||||
const user = req.user as User;
|
||||
const isAdmin = await this.authService.isAdmin(user.id);
|
||||
if (!isAdmin) {
|
||||
throw new ForbiddenException('Only admin can create users');
|
||||
}
|
||||
return this.authService.createUser(body.login, body.password, body.role);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Delete('users/:id')
|
||||
async deleteUser(@Param('id') id: string, @Req() req: Request) {
|
||||
const user = req.user as User;
|
||||
const isAdmin = await this.authService.isAdmin(user.id);
|
||||
if (!isAdmin) {
|
||||
throw new ForbiddenException('Only admin can delete users');
|
||||
}
|
||||
await this.authService.deleteUser(parseInt(id));
|
||||
return { message: 'User deleted successfully' };
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { Injectable, ForbiddenException } from '@nestjs/common';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { User } from './user.entity';
|
||||
import * as bcrypt from 'bcrypt';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
|
|
@ -12,6 +13,7 @@ export class AuthService {
|
|||
private jwtService: JwtService,
|
||||
) { }
|
||||
|
||||
|
||||
async validateUser(login: string, password: string): Promise<any> {
|
||||
const user = await this.usersRepository.findOne({ where: { login } });
|
||||
|
||||
|
|
@ -25,6 +27,8 @@ export class AuthService {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
async login(user: any) {
|
||||
const payload = {
|
||||
username: user.login,
|
||||
|
|
@ -35,4 +39,33 @@ export class AuthService {
|
|||
access_token: this.jwtService.sign(payload),
|
||||
};
|
||||
}
|
||||
|
||||
async getAllUsers(): Promise<User[]> {
|
||||
return this.usersRepository.find();
|
||||
}
|
||||
|
||||
async createUser(login: string, password: string, role: 'user' | 'admin' = 'user'): Promise<User> {
|
||||
// const hashedPassword = await bcrypt.hash(password, 10);
|
||||
const user = this.usersRepository.create({
|
||||
login,
|
||||
password, //hashedPassword,
|
||||
role
|
||||
});
|
||||
return this.usersRepository.save(user);
|
||||
}
|
||||
|
||||
async deleteUser(id: number): Promise<void> {
|
||||
const user = await this.usersRepository.findOne({ where: { id } });
|
||||
if (user && user.role === 'admin') {
|
||||
throw new ForbiddenException('Cannot delete admin user');
|
||||
}
|
||||
await this.usersRepository.delete(id);
|
||||
}
|
||||
|
||||
async isAdmin(userId: number): Promise<boolean> {
|
||||
const user = await this.usersRepository.findOne({ where: { id: userId } });
|
||||
return user?.role === 'admin';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,33 +6,33 @@ import { MenuItem } from './menu.interface';
|
|||
export class MenuController {
|
||||
constructor(private readonly menuService: MenuService) { }
|
||||
|
||||
@Get('full')
|
||||
async getFullMenu(@Headers('if-modified-since') ifModifiedSince?: string) {
|
||||
console.log('GET /menu/full requested');
|
||||
try {
|
||||
const result = await this.menuService.getFullMenuWithCache(ifModifiedSince);
|
||||
|
||||
if (!result.fresh && ifModifiedSince) {
|
||||
throw new HttpException('Not Modified', HttpStatus.NOT_MODIFIED);
|
||||
}
|
||||
|
||||
return result.menu;
|
||||
} catch (error) {
|
||||
if (error.status === HttpStatus.NOT_MODIFIED) {
|
||||
throw error;
|
||||
}
|
||||
throw new HttpException(
|
||||
error.message || 'Failed to load menu',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
/*
|
||||
@Get('full')
|
||||
async getFullMenu() {
|
||||
console.log('Simplified endpoint called');
|
||||
return { test: 'OK' }; // Простейший ответ
|
||||
} */
|
||||
async getFullMenu(@Headers('if-modified-since') ifModifiedSince?: string) {
|
||||
console.log('GET /menu/full requested');
|
||||
try {
|
||||
const result = await this.menuService.getFullMenuWithCache(ifModifiedSince);
|
||||
|
||||
if (!result.fresh && ifModifiedSince) {
|
||||
throw new HttpException('Not Modified', HttpStatus.NOT_MODIFIED);
|
||||
}
|
||||
|
||||
return result.menu;
|
||||
} catch (error) {
|
||||
if (error.status === HttpStatus.NOT_MODIFIED) {
|
||||
throw error;
|
||||
}
|
||||
throw new HttpException(
|
||||
error.message || 'Failed to load menu',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
/*
|
||||
@Get('full')
|
||||
async getFullMenu() {
|
||||
console.log('Simplified endpoint called');
|
||||
return { test: 'OK' }; // Простейший ответ
|
||||
} */
|
||||
|
||||
@Get('check-updates')
|
||||
async checkUpdates(@Headers('if-modified-since') ifModifiedSince: string) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue