Aller au contenu principal

Module Users

Module de gestion des utilisateurs pour la MyTelevision API.


Vue d'ensemble

Le module Users gere :

  • Operations CRUD sur les utilisateurs
  • Systeme de comptes multi-profils (Netflix-grade)
  • Gestion des profils (standard et enfants)
  • Gestion des appareils
  • Sessions actives
  • Preferences utilisateur
  • Controle parental (PIN, restrictions d'age, horaires)
  • Scoring de risque

Architecture


Hierarchie du Systeme

Tenant (white-label brand)
└── Account (email/password)
└── Profile (max 4, dont le profil par defaut)
├── Restrictions (controle parental)
├── Signals (donnees de recommandation)
└── Sessions (connexions actives)
└── Device (suivi par fingerprint)

Structure des Fichiers

src/
├── application/
│ ├── dtos/
│ │ └── users/
│ │ ├── user.dto.ts
│ │ ├── create-user.dto.ts
│ │ ├── update-user.dto.ts
│ │ └── user-response.dto.ts
│ └── services/
│ └── users/
│ ├── users.service.ts
│ └── users.service.spec.ts
└── presentation/
├── controllers/
│ └── api/v2/
│ └── users.controller.ts
└── modules/
└── users.module.ts

Composants Principaux

UserService

@Injectable()
export class UserService {
async findById(id: string): Promise<User>;
async findByEmail(email: string): Promise<User>;
async create(dto: CreateUserDto): Promise<User>;
async update(id: string, dto: UpdateUserDto): Promise<User>;
async delete(id: string): Promise<void>;
async updatePreferences(id: string, prefs: UserPreferencesDto): Promise<User>;
}

Modele de Donnees

User

model User {
id String @id @default(uuid())
email String @unique
password String?
firstName String?
lastName String?
avatarUrl String?
role UserRole @default(USER)
status UserStatus @default(ACTIVE)
emailVerified Boolean @default(false)
firebaseUid String? @unique

// Relations
accounts Account[]
socialAccounts SocialAccount[]

// Timestamps
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

enum UserRole {
USER
MODERATOR
ADMIN
SUPER_ADMIN
}

enum UserStatus {
ACTIVE
SUSPENDED
LOCKED
PENDING_VERIFICATION
}

DTOs

CreateUserDto

export class CreateUserDto {
@IsEmail()
email: string;

@IsString()
@MinLength(8)
password: string;

@IsOptional()
@IsString()
firstName?: string;

@IsOptional()
@IsString()
lastName?: string;
}

UpdateUserDto

export class UpdateUserDto {
@IsOptional()
@IsString()
firstName?: string;

@IsOptional()
@IsString()
lastName?: string;

@IsOptional()
@IsUrl()
avatarUrl?: string;
}

UserResponseDto

export class UserResponseDto {
id: string;
email: string;
firstName: string;
lastName: string;
avatarUrl: string;
role: UserRole;
emailVerified: boolean;
createdAt: Date;
}

Endpoints API

Utilisateurs

MethodeEndpointDescriptionAuth
GET/api/v2/users/meObtenir l'utilisateur courantRequis
PATCH/api/v2/users/meMettre a jour l'utilisateur courantRequis
GET/api/v2/users/:idObtenir un utilisateur par IDAdmin
DELETE/api/v2/users/meSupprimer le compteRequis

Profils

MethodeEndpointDescriptionAuth
GET/api/v2/profilesLister les profils du compteRequis
GET/api/v2/profiles/pickerObtenir les profils pour le selecteur UIRequis
POST/api/v2/profilesCreer un profilRequis
POST/api/v2/profiles/kidsCreer un profil enfantRequis
GET/api/v2/profiles/meObtenir le profil actuelRequis
PATCH/api/v2/profiles/:idMettre a jour un profilRequis
DELETE/api/v2/profiles/:idSupprimer un profil (pas le defaut)Requis
POST/api/v2/profiles/:id/switchChanger de profilRequis
POST/api/v2/profiles/:id/pinDefinir/modifier le PINRequis
POST/api/v2/profiles/:id/verify-pinVerifier le PINRequis

Appareils

MethodeEndpointDescriptionAuth
GET/api/v2/devicesLister les appareilsRequis
POST/api/v2/devicesEnregistrer un appareilRequis
GET/api/v2/devices/currentObtenir l'appareil courantRequis
PATCH/api/v2/devices/:idModifier le nom de l'appareilRequis
DELETE/api/v2/devices/:idRevoquer un appareilRequis

Sessions

MethodeEndpointDescriptionAuth
GET/api/v2/sessionsLister les sessionsRequis
GET/api/v2/sessions/currentObtenir la session couranteRequis
DELETE/api/v2/sessions/:idRevoquer une sessionRequis
DELETE/api/v2/sessionsRevoquer toutes les sessionsRequis
POST/api/v2/sessions/current/heartbeatMettre a jour l'activiteRequis

Cycle de Vie de l'Utilisateur


Controle Parental (Profils Enfants)

RestrictionDescription
Age RatingRestriction du contenu par classification d'age (7+, 13+, 16+)
CategoriesBlocage de categories specifiques (horreur, violence, actualites)
HorairesAutorisation de visionnage uniquement pendant des creneaux definis
Limite quotidienneTemps de visionnage maximum par jour
Types de mediasActivation/desactivation par type (films, series, TV, actualites)
Protection PINPIN a 4-6 chiffres pour l'acces au profil
Anti brute-force5 tentatives echouees = blocage 15 minutes

Scoring de Risque

SignalImpact ScoreDescription
Nouvel appareil+15Connexion depuis un appareil non reconnu
Voyage impossible+40>500 km en moins d'1 heure
Echecs de connexion+255+ tentatives en 10 min
VPN/Proxy+20Connexion depuis un VPN/proxy connu
Sessions simultanees+30Depasse le max de sessions
Rate limit depasse+15Requetes constamment proches du max
Plage de ScoreNiveauAction
0-30LOWALLOW
31-60MEDIUMSTEP_UP
61-85HIGHCHALLENGE
86-100CRITICALBLOCK

Suppression de Compte (RGPD)

Le systeme de suppression implemente la conformite RGPD avec une periode de retractation de 30 jours :

  1. L'utilisateur demande la suppression - statut passe a PENDING_DELETION
  2. Date de suppression planifiee (date actuelle + 30 jours)
  3. L'utilisateur peut annuler a tout moment avant la date
  4. Si l'utilisateur se connecte pendant la retractation, le compte est automatiquement restaure
  5. Avertissement 3 jours avant la suppression (cron a 1h du matin)
  6. Apres 30 jours, le cron effectue la suppression reelle (a 2h du matin)

Actions de suppression

  • Toutes les sessions revoquees
  • Tous les appareils marques comme revoques
  • Tous les profils marques comme supprimes
  • Email anonymise (deleted_<accountId>@deleted.local)
  • Compte soft-delete avec timestamp deletedAt

Strategie de Cache

Donnees utilisateur mises en cache dans Redis :

Pattern de CleTTLDescription
user:{id}5 minUtilisateur par ID
user:email:{email}5 minUtilisateur par email
user:{id}:preferences10 minPreferences utilisateur

L'invalidation du cache se produit lors de :

  • Mise a jour de l'utilisateur
  • Changement de role
  • Changement de statut

Rate Limiting (Par Profil)

TierLimiteFenetre
Short3 requetes1 seconde
Medium20 requetes10 secondes
Long100 requetes1 minute
  • Cle : (tenant_id, profile_id, tier)
  • Distribue : Base sur Redis, compatible cluster
  • Non contournable : Impossible a contourner via changement de profil/appareil/session

Tests

describe('UserService', () => {
it('should find user by id', async () => {
const user = await userService.findById('user-id');
expect(user).toBeDefined();
expect(user.email).toBe('[email protected]');
});

it('should update user profile', async () => {
const updated = await userService.update('user-id', {
firstName: 'John',
lastName: 'Doe',
});
expect(updated.firstName).toBe('John');
});
});

Documentation associee