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);
}
}