feat: sprint 3 — profile endpoints + avatar
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 32s
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 32s
- GET /api/auth/me enrichi : avatar, plan actif, subscriptionDate - GET /api/users/me/profile : profil complet (local UUID, sub, rôles) - PATCH /api/users/me : update nickname / avatar (validation URL + longueur) - User entity : champ avatar VARCHAR(500) nullable - Migration 1742000000000-AddUserAvatar (appliquée VPS)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { AppDataSource } from "../config/data-source";
|
||||
import { User } from "../entities/User";
|
||||
import { UserSubscription } from "../entities/UserSubscription";
|
||||
import { requireAuth, AuthenticatedRequest } from "../middleware/auth.middleware";
|
||||
|
||||
const router = Router();
|
||||
@@ -189,17 +190,51 @@ router.post("/logout", (_req: Request, res: Response): void => {
|
||||
|
||||
/**
|
||||
* GET /api/auth/me
|
||||
* Retourne l'utilisateur courant (cookie ou Bearer) + ses rôles locaux.
|
||||
* Retourne l'utilisateur courant + rôles locaux + plan actif + avatar.
|
||||
*/
|
||||
router.get("/me", requireAuth, async (req: Request, res: Response): Promise<void> => {
|
||||
const { user } = req as AuthenticatedRequest;
|
||||
|
||||
const localUser = await AppDataSource.getRepository(User)
|
||||
.findOne({ where: { superOAuthId: user.id }, relations: ["userRoles", "userRoles.role"] });
|
||||
const localUser = await AppDataSource.getRepository(User).findOne({
|
||||
where: { superOAuthId: user.id },
|
||||
relations: ["userRoles", "userRoles.role"],
|
||||
});
|
||||
|
||||
const roles = localUser?.userRoles.map((ur) => ur.role.slug) ?? [];
|
||||
|
||||
res.json({ success: true, data: { user: { ...user, roles } } });
|
||||
let plan: { slug: string; name: string; level: number } | null = null;
|
||||
let subscriptionDate: string | null = null;
|
||||
|
||||
if (localUser) {
|
||||
const now = new Date();
|
||||
const activeSub = await AppDataSource.getRepository(UserSubscription)
|
||||
.createQueryBuilder("sub")
|
||||
.leftJoinAndSelect("sub.plan", "plan")
|
||||
.where("sub.userId = :userId", { userId: localUser.id })
|
||||
.andWhere("sub.status IN (:...statuses)", { statuses: ["active", "trial"] })
|
||||
.andWhere("(sub.endsAt IS NULL OR sub.endsAt > :now)", { now })
|
||||
.orderBy("plan.level", "DESC")
|
||||
.addOrderBy("sub.startsAt", "DESC")
|
||||
.getOne();
|
||||
|
||||
if (activeSub) {
|
||||
plan = { slug: activeSub.plan.slug, name: activeSub.plan.name, level: activeSub.plan.level };
|
||||
subscriptionDate = activeSub.startsAt.toISOString();
|
||||
}
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
user: {
|
||||
...user,
|
||||
avatar: localUser?.avatar ?? null,
|
||||
roles,
|
||||
plan,
|
||||
subscriptionDate,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user