Skip to content

feat: user management feature (C# API + React frontend) — interview code review exercise - #1

Draft
hashcode-adrien with Copilot wants to merge 2 commits into
mainfrom
copilot/featureuser-management
Draft

hashcode-adrien with Copilot wants to merge 2 commits into
mainfrom
copilot/featureuser-management

Conversation

Copilot AI commented Apr 17, 2026 •

Copy link
Copy Markdown

Adds a complete but intentionally flawed user management feature (list, search, create) to serve as a technical interview code review exercise for a Senior Fullstack C# / React candidate.

Backend — backend/UserManagement.Api/

  • Program.cs — DbContext as Singleton, wildcard CORS, hardcoded secrets duplicated from appsettings.json
  • appsettings.json — connection string + JWT key in plaintext
  • UsersController.cs — [AllowAnonymous] on entire controller, blocking .Result call, DELETE routed as HttpGet, inconsistent routing, domain entity returned directly, no ModelState.IsValid check
  • UserService.cs — raw string-concatenated SQL (FromSqlRaw), async void CreateUser, N+1 loop loading orders, silent catch (Exception) {}, Console.WriteLine logging, undisposed SqlConnection, plaintext password storage
  • CreateUserRequest.cs — no [Required] / [EmailAddress] / [StringLength] annotations
  • User.cs — Password and InternalNotes serialized without [JsonIgnore]

Frontend — frontend/src/

  • usersApi.ts — API_KEY hardcoded client-side, hardcoded localhost base URL, no error handling, any types throughout
  • useUsers.ts — useEffect missing searchTerm dependency (stale closure), setInterval with no clearInterval cleanup
  • UserList.tsx — 200+ line monolith mixing API calls / logic / render, N+1 per-user fetch via OrdersLoader, key={index}, direct state mutation (users.splice + setUsers), no useMemo on filter().sort(), no loading/error states, <div onClick> instead of <button>
  • UserCard.tsx — dangerouslySetInnerHTML on user.bio (XSS), <img> without alt, password field rendered in plaintext
  • UserForm.tsx — uncontrolled form via document.getElementById, type="text" on password input, inputs without <label htmlFor>
  • package.json — moment imported for trivial date formatting, wide ^ version ranges
Original prompt

Contexte

Ce dépôt sert de support à un entretien technique pour un poste de Développeur Fullstack Senior C# / React.

Le but de cette Pull Request est de proposer une petite fonctionnalité de gestion d'utilisateurs (listing, recherche, création) avec un backend en C# / ASP.NET Core et un frontend en React + TypeScript.

⚠️ TRÈS IMPORTANT ⚠️ : cette PR doit contenir volontairement un certain nombre de défauts (bugs, mauvaises pratiques, failles de sécurité, problèmes de performance, d'accessibilité, de tests, etc.). Il ne faut PAS les corriger. Le code doit compiler / être cohérent (pas d'erreurs de syntaxe grossières) mais contenir les problèmes listés ci-dessous pour que le candidat puisse les identifier en revue de code.

Structure à créer

Créer une nouvelle branche feature/user-management et y ajouter l'arborescence suivante :

/backend
  /UserManagement.Api
    UserManagement.Api.csproj
    Program.cs
    appsettings.json
    /Controllers
      UsersController.cs
    /Models
      User.cs
      CreateUserRequest.cs
    /Services
      IUserService.cs
      UserService.cs
    /Data
      AppDbContext.cs
/frontend
  package.json
  tsconfig.json
  /src
    index.tsx
    App.tsx
    /components
      UserList.tsx
      UserForm.tsx
      UserCard.tsx
    /api
      usersApi.ts
    /hooks
      useUsers.ts
README.md

Ouvrir une Pull Request de feature/user-management vers main avec un titre clair (ex: feat: user management (API C# + Front React)) et une description listant succinctement les fichiers ajoutés.

Défauts à introduire (OBLIGATOIRE — ne pas corriger)

Côté C# / ASP.NET Core

  1. Injection SQL : dans UserService.GetByName, construire la requête avec une concaténation de chaîne : context.Database.ExecuteSqlRaw("SELECT * FROM Users WHERE Name = '" + name + "'") ou équivalent avec FromSqlRaw.
  2. Mot de passe en clair : User.Password stocké et renvoyé en clair (pas de hash, pas de [JsonIgnore]), et renvoyé dans les réponses API.
  3. Exposition de l'entité de domaine : le contrôleur renvoie directement l'entité User (avec Password, dates internes, etc.) au lieu d'un DTO.
  4. async void : la méthode CreateUser du service est déclarée async void au lieu de async Task.
  5. Appel bloquant : dans le contrôleur, appel .Result ou .Wait() sur une méthode async (ex: var users = _service.GetAllAsync().Result;).
  6. Pas d'annulation : aucune méthode async n'accepte de CancellationToken.
  7. Validation manquante : CreateUserRequest n'a aucune DataAnnotation ([Required], [EmailAddress], [StringLength]) et le contrôleur ne vérifie pas ModelState.IsValid.
  8. DbContext enregistré en Singleton : dans Program.cs, services.AddSingleton<AppDbContext>(...) au lieu de AddDbContext / Scoped.
  9. Secrets en dur : la chaîne de connexion et une clé JWT ("SuperSecretKey123") sont en dur dans appsettings.json ET également dupliquées en constantes dans le code.
  10. CORS trop permissif : app.UseCors(p => p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); sans restriction.
  11. Pas de pagination : GetAll renvoie toute la table Users sans Skip/Take.
  12. N+1 : dans GetAllAsync, boucler sur les utilisateurs et charger les Orders dans la boucle (foreach (var u in users) { u.Orders = _context.Orders.Where(o => o.UserId == u.Id).ToList(); }) au lieu d'un Include.
  13. Exceptions avalées : un try/catch qui fait catch (Exception) { } silencieusement dans UserService.
  14. Logs inexistants / Console.WriteLine : utiliser Console.WriteLine au lieu de ILogger<T>.
  15. Routes incohérentes : mélanger [HttpGet("users")] et [Route("api/[controller]")], avec un endpoint DELETE en HttpGet (ex: [HttpGet("delete/{id}")] qui supprime un utilisateur).
  16. Nom de champ sensible renvoyé : la liste renvoyée inclut Email, Password, InternalNotes.
  17. Pas de using : un SqlConnection (ou équivalent) instancié sans using, jamais disposé.
  18. Attribut [AllowAnonymous] sur le contrôleur entier alors qu'il manipule des utilisateurs.
  19. Aucun test unitaire.

Côté React / TypeScript

  1. any partout : types any sur les props, states et retours de fetch.
  2. useEffect avec dépendances manquantes : fetch des users dans useEffect(() => { fetchUsers(); }, []) alors que fetchUsers dépend de props/state (ex: searchTerm) — pas dans les deps.
  3. Clé key={index} dans le .map() de UserList.
  4. Mutation directe du state : users.push(newUser); setUsers(users); au lieu de setUsers([...users, newUser]).
  5. Pas de gestion d'erreur / loading : fetch sans try/catch, pas d'état loading, pas d'état error affiché à l'utilisateur.
  6. URL d'API en dur : fetch("http://localhost:5000/api/users") directement dans les composants au lieu d'une variable d'environnement.
  7. XSS : `<di...

This pull request was created from Copilot chat.

Agent-Logs-Url: https://github.com/hashcode-adrien/tests/sessions/58958061-f8af-481e-a042-b9300e7cf8cb

Co-authored-by: hashcode-adrien <137324736+hashcode-adrien@users.noreply.github.com>
Copilot AI changed the title [WIP] Add user management functionality with known issues feat: user management feature (C# API + React frontend) — interview code review exercise Apr 17, 2026
Copilot AI requested a review from hashcode-adrien April 17, 2026 12:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants