/
viktorphp
/
back-socket
Обзор
Документация
Войти
/
viktorphp
/
back-socket
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/app.module.ts
163 строки
8 KB
Иванов Виктор Евгеньевич
[feat-tree]: добавить функционал для построения дерева предков
13 апр 2026, 21:34
13 апр 2026, 21:34
52b3f3d
Код
Авторство
О чём код?
import { Module, MiddlewareConsumer, NestModule } from '@nestjs/common'; import { UsersModule } from './modules/users/users.module'; import { AuthModule } from './modules/auth/auth.module'; import { MessagesModule } from './modules/messages/messages.module'; import { DiaryModule } from './modules/diary/diary.module'; import { AncestorsModule } from './modules/ancestors/ancestors.module'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './entities/users/user.entity'; import { ConfigModule, ConfigService } from '@nestjs/config'; // Пакет для работы с конфигурациями и переменными окружения import { configuration } from './config/configuration'; import session from 'express-session'; import passport from 'passport'; import { Message } from './entities/messages/message.entity'; import { DiaryEntry } from './entities/diary/diary-entry.entity'; import { DiaryFile } from './entities/diary/diary-file.entity'; import { Ancestor } from './entities/ancestors/ancestor.entity'; import { AncestorContribution } from './entities/ancestors/ancestor-contribution.entity'; import { AncestorMedia } from './entities/ancestors/ancestor-media.entity'; import { AncestorSibling } from './entities/ancestors/ancestor-sibling.entity'; import { FamilyRequest } from './entities/ancestors/family-request.entity'; import { UserTree } from './entities/ancestors/user-tree.entity'; @Module({ imports: [ ConfigModule.forRoot({ load: [configuration], // загружает конфигурацию из файла configuration.ts isGlobal: true, // делает конфигурацию доступной во всем приложении envFilePath: '.env', // ignoreEnvFile: true, }), TypeOrmModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => ({ type: 'postgres', host: configService.get('database.host'), port: configService.get('database.port'), username: configService.get('database.username'), password: configService.get('database.password'), database: configService.get('database.database'), entities: [ User, Message, DiaryEntry, DiaryFile, Ancestor, AncestorContribution, AncestorMedia, AncestorSibling, FamilyRequest, UserTree, ], synchronize: true, }), }), UsersModule, AuthModule, MessagesModule, DiaryModule, AncestorsModule, ], controllers: [], providers: [], }) export class AppModule implements NestModule { constructor(private readonly configService: ConfigService) {} configure(consumer: MiddlewareConsumer) { /* Каждый запрос будет проходить через эти middleware Для каждого запроса создается или проверяется сессия Passport.js будет автоматически пытаться аутентифицировать пользователя на основе сессии */ consumer .apply( // Добавляем новый middleware для логирования куков (req: any, res: any, next: any) => { console.log('=== Middleware логирование ==='); console.log('Метод:', req.method); console.log('URL:', req.url); console.log('Входящие куки:', req.headers.cookie); let bodyForReqLogging = req.body; // Если тело ответа является объектом, удаляем поле avatar для логирования if (req.body && typeof req.body === 'object') { bodyForReqLogging = { ...req.body }; if (bodyForReqLogging.avatar) { delete bodyForReqLogging.avatar; } } console.log('Тело запроса:', bodyForReqLogging); console.log('Сессия:', req.session); // Перехват ответа const originalSend = res.send; res.send = function (body: any) { console.log('=== Исходящий ответ ==='); console.log('Статус:', res.statusCode); // TODO: убрать из тела ответа поле avatar. Напрямую объект не парсится. console.log('Тело ответа:', '??????????'); return originalSend.call(this, body); }; // Перехват json const originalJson = res.json; res.json = function (body: any) { console.log('=== Исходящий JSON ==='); console.log('Статус:', res.statusCode); let bodyForLogging = body; // Если тело ответа является объектом, удаляем поле avatar для логирования if (body && typeof body === 'object') { bodyForLogging = { ...body }; if (bodyForLogging.avatar) { delete bodyForLogging.avatar; } } console.log('Тело ответа:', bodyForLogging); return originalJson.call(this, body); }; next(); }, session({ secret: this.configService.get('session.secret'), // секретный ключ для подписи сессионного cookie // name: 'sessionId', // имя сессионного cookie resave: false, // не сохранять сессию, если она не была изменена saveUninitialized: false, // не создавать сессию до тех пор, пока что-то не сохранено cookie: { maxAge: parseInt(this.configService.get('session.maxAge'), 10), // время жизни cookie secure: this.configService.get('cookie.secure'), // использовать только HTTPS sameSite: this.configService.get('cookie.sameSite'), // защита от CSRF атак httpOnly: this.configService.get('cookie.httpOnly'), // запрет доступа к cookie через JavaScript }, rolling: true, // обновление времени жизни при каждом запросе }), // Логирование после session middleware (req: any, res: any, next: any) => { console.log('=== После session middleware ==='); console.log('Сессия:', req.session); next(); }, passport.initialize(), // инициализирует Passport // Проверка после passport.initialize (req: any, res: any, next: any) => { console.log('=== 3. После passport.initialize ==='); console.log('User:', req.user); next(); }, passport.session(), // позволяет Passport использовать // Проверка после passport.session (req: any, res: any, next: any) => { console.log('=== После passport.session ==='); console.log('User:', req.user); console.log('isAuthenticated:', req.isAuthenticated()); next(); }, ) .exclude('auth/register', 'auth/login', 'auth/loginSession') // исключить пути .forRoutes('*'); // применяет эти middleware ко всем маршрутам } }