using Domain.Entities; using Domain.Exceptions; using Features.Users.Dtos; using Features.Users.Queries.GetAllUsers; using Features.Users.Queries.GetPublicUserProfileById; using Features.Users.Queries.GetUserById; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Shared.Contracts; namespace Features.Users.Controllers; /// /// Exposes read endpoints for user accounts. /// /// /// Every endpoint requires [Authorize(AuthenticationSchemes = "JWT")] except /// , which is since it /// only returns an allowlisted DTO. also restricts access to the /// caller's own account. Neither nor may expose /// another user's Email or DateOfBirth. /// [ApiController] [Route("api/[controller]")] [Authorize(AuthenticationSchemes = "JWT")] public class UserController(IMediator mediator) : ControllerBase { /// Gets a page of user accounts' public profiles, ordered by creation date descending. /// null for no limit. /// null for no offset. [HttpGet] public async Task>> GetAll( [FromQuery] int? limit, [FromQuery] int? offset ) { IEnumerable users = await mediator.Send( new GetAllUsersQuery(limit, offset) ); return Ok(users); } /// Gets the caller's own user account by ID. /// /// Thrown when is not the caller's own account. The API returns HTTP status 403. /// /// /// Thrown when no user account exists with the given ID, resulting in a 404 response. /// [HttpGet("{id:guid}")] public async Task> GetById(Guid id) { UserAccount user = await mediator.Send( new GetUserByIdQuery(id, User.GetAuthenticatedUserId()) ); return Ok(user); } /// Gets the public profile for the user account with the given ID. /// /// This endpoint is anonymous-accessible and requires no ownership. Anyone can view any /// account's public profile. The response includes only fields that are safe to show publicly. /// Unlike , it never includes Email or DateOfBirth. /// /// /// Thrown when no user account exists with the given ID. The API returns HTTP status 404. /// [HttpGet("{id:guid}/profile")] [AllowAnonymous] public async Task> GetPublicProfile(Guid id) { PublicUserProfileDto profile = await mediator.Send(new GetPublicUserProfileByIdQuery(id)); return Ok(profile); } }