gui version

This commit is contained in:
Den Piligrim
2026-01-28 12:05:10 +03:00
parent f574931c25
commit ba6db6edd5
102 changed files with 19151 additions and 2673 deletions
+30
View File
@@ -0,0 +1,30 @@
import { Controller, Post, Body, Request, UseGuards, Get } from '@nestjs/common';
import { AuthService } from './auth.service';
import { Public } from './public.decorator';
@Controller('auth')
export class AuthController {
constructor(private authService: AuthService) {}
@Public()
@Post('login')
async login(@Body() req) {
const user = await this.authService.validateUser(req.login, req.password);
if (!user) {
throw new Error('Invalid credentials');
}
return this.authService.login(user);
}
@Post('change-password')
async changePassword(@Body('password') password: string) {
await this.authService.changePassword(password);
return { success: true };
}
@Post('update-profile')
async updateProfile(@Body() body: { login: string; password?: string }) {
await this.authService.updateAdminProfile(body.login, body.password);
return { success: true };
}
}
+23
View File
@@ -0,0 +1,23 @@
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Setting } from '../settings/entities/setting.entity';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { JwtStrategy } from './jwt.strategy';
@Module({
imports: [
TypeOrmModule.forFeature([Setting]),
PassportModule,
JwtModule.register({
secret: 'SECRET_KEY_CHANGE_ME',
signOptions: { expiresIn: '24h' },
}),
],
providers: [AuthService, JwtStrategy],
controllers: [AuthController],
exports: [AuthService],
})
export class AuthModule {}
+110
View File
@@ -0,0 +1,110 @@
import { Injectable, Logger } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcrypt';
import { Setting } from '../settings/entities/setting.entity';
@Injectable()
export class AuthService {
private readonly logger = new Logger(AuthService.name);
constructor(
@InjectRepository(Setting)
private settingsRepo: Repository<Setting>,
private jwtService: JwtService,
) {}
async validateUser(login: string, pass: string): Promise<any> {
this.logger.log(`Попытка входа с логином: ${login}`);
const dbLogin = await this.settingsRepo.findOne({ where: { key: 'admin_login' } });
const dbPass = await this.settingsRepo.findOne({ where: { key: 'admin_password' } });
if (!dbLogin) {
this.logger.error('Пользователь admin_login не найден в базе данных!');
return null;
}
if (!dbPass) {
this.logger.error('Пароль admin_password не найден в базе данных!');
return null;
}
this.logger.log(`Пользователь найден, проверяем хеш пароля...`);
// Сравниваем пароль
const isMatch = await bcrypt.compare(pass, dbPass.value);
if (isMatch) {
this.logger.log('Пароль верный!');
return { login: dbLogin.value };
} else {
this.logger.warn('Пароль неверный.');
return null;
}
}
async login(user: any) {
const payload = { username: user.login };
return {
access_token: this.jwtService.sign(payload),
};
}
async changePassword(newPass: string) {
const hash = await bcrypt.hash(newPass, 10);
let setting = await this.settingsRepo.findOne({ where: { key: 'admin_password' } });
if (!setting) {
setting = this.settingsRepo.create({ key: 'admin_password' });
}
setting.value = hash;
await this.settingsRepo.save(setting);
this.logger.log('Пароль администратора изменен.');
}
// ... imports
// (Оставьте существующие методы без изменений, добавьте/обновите этот)
async updateAdminProfile(login: string, password?: string) {
let loginSetting = await this.settingsRepo.findOne({ where: { key: 'admin_login' } });
if (!loginSetting) loginSetting = this.settingsRepo.create({ key: 'admin_login' });
loginSetting.value = login;
await this.settingsRepo.save(loginSetting);
if (password && password.trim().length > 0) {
const hash = await bcrypt.hash(password, 10);
let passSetting = await this.settingsRepo.findOne({ where: { key: 'admin_password' } });
if (!passSetting) passSetting = this.settingsRepo.create({ key: 'admin_password' });
passSetting.value = hash;
await this.settingsRepo.save(passSetting);
}
this.logger.log(`Профиль администратора обновлен. Новый логин: ${login}`);
}
// Обновленный метод инициализации
async seedAdmin() {
const login = await this.settingsRepo.findOne({ where: { key: 'admin_login' } });
// Если пользователя нет ИЛИ если нужно принудительно сбросить (для отладки)
if (!login) {
this.logger.log('Инициализация администратора (admin / admin)...');
// 1. Сохраняем логин
const loginSetting = this.settingsRepo.create({ key: 'admin_login', value: 'admin' });
await this.settingsRepo.save(loginSetting);
// 2. Сохраняем пароль
const hash = await bcrypt.hash('admin', 10);
const passSetting = this.settingsRepo.create({ key: 'admin_password', value: hash });
await this.settingsRepo.save(passSetting);
this.logger.log('Администратор успешно создан.');
} else {
this.logger.log('Администратор уже существует в базе.');
}
}
}
+21
View File
@@ -0,0 +1,21 @@
import { Injectable, ExecutionContext, UnauthorizedException } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Reflector } from '@nestjs/core';
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
constructor(private reflector: Reflector) {
super();
}
canActivate(context: ExecutionContext) {
const isPublic = this.reflector.getAllAndOverride<boolean>('isPublic', [
context.getHandler(),
context.getClass(),
]);
if (isPublic) {
return true;
}
return super.canActivate(context);
}
}
+18
View File
@@ -0,0 +1,18 @@
import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor() {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: 'SECRET_KEY_CHANGE_ME',
});
}
async validate(payload: any) {
return { userId: payload.sub, username: payload.username };
}
}
+2
View File
@@ -0,0 +1,2 @@
import { SetMetadata } from '@nestjs/common';
export const Public = () => SetMetadata('isPublic', true);