feat: Sprint 1 — backend fondations TetaRdPG

Auth SuperOAuth (JWT validation + httpOnly cookie), entités users/characters/level_thresholds,
lazy calculation endurance, seed 100 niveaux, config prod-ready (trust proxy, helmet, CORS, rate limit).
Validé : health 200, auth flow, character CRUD, endurance lazy, 401 sans cookie.
This commit is contained in:
2026-03-15 05:51:02 +01:00
commit da3237bf3f
29 changed files with 7249 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '../../user/user.entity';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const userId: string | false = request.signedCookies?.session;
if (!userId) {
throw new UnauthorizedException('Session manquante ou invalide');
}
// Validation UUID basique avant la requête DB
const uuidRegex =
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (!uuidRegex.test(userId)) {
throw new UnauthorizedException('Session invalide');
}
const user = await this.userRepository.findOne({ where: { id: userId } });
if (!user) {
throw new UnauthorizedException('Utilisateur introuvable');
}
request.user = user;
return true;
}
}