Sube carpetas API, API.Tests, Application y Domain del Backend

This commit is contained in:
FrancoRu
2026-09-18 13:35:59 -03:00
parent bbb09554bb
commit 2eb4eeef03
572 changed files with 56405 additions and 0 deletions
@@ -0,0 +1,23 @@
using Application.Utils.Constants.Validation;
using System.ComponentModel.DataAnnotations;
namespace Application.DTOs.Auth.Request;
/// <summary>
/// Payload the invited user submits from the activation email link to set their first password.
/// </summary>
public sealed class ActivateAccountRequest
{
[Required, EmailAddress]
public string Email { get; set; } = string.Empty;
/// <summary>
/// Activation token received via email, URL-decoded automatically by the framework.
/// </summary>
[Required]
public string Token { get; set; } = string.Empty;
[Required, MinLength(UserFieldLengths.PasswordMinLength)]
public string NewPassword { get; set; } = string.Empty;
}
@@ -0,0 +1,28 @@
using Application.Utils.Constants.Validation;
using System.ComponentModel.DataAnnotations;
namespace Application.DTOs.Auth.Request;
/// <summary>
/// Request to create a user by email only; the system emails a magic activation link to set the password.
/// </summary>
public sealed class InviteUserRequest
{
[Required(ErrorMessage = "Email is required.")]
[EmailAddress(ErrorMessage = "Invalid email format.")]
public required string Email { get; set; }
/// <summary>
/// Optional contact phone number.
/// </summary>
[ArgentinePhoneNumber]
[MaxLength(UserFieldLengths.PhoneMaxLength, ErrorMessage = "Phone number must not exceed 15 characters.")]
public string? Phone { get; set; }
/// <summary>
/// Target role. Accepted values: ADMIN, OWNER.
/// </summary>
[Required(ErrorMessage = "Role is required.")]
public required string Role { get; set; }
}
@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace Application.DTOs.Auth.Request;
/// <summary>
/// Represents a request object for user login.
/// </summary>
public class LogInUserRequest
{
[Required(ErrorMessage = "The Email field is required.")]
public required string Email { get; set; }
[Required(ErrorMessage = "The Password field is required.")]
public required string Password { get; set; }
}
@@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
namespace Application.DTOs.Auth.Request;
/// <summary>
/// Request to login using a magic-link token.
/// </summary>
public sealed class MagicLinkLoginRequest
{
[Required(ErrorMessage = "The Email field is required.")]
[EmailAddress(ErrorMessage = "Invalid email format.")]
public required string Email { get; set; }
[Required(ErrorMessage = "The Token field is required.")]
public required string Token { get; set; }
}
@@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace Application.DTOs.Auth.Request;
/// <summary>
/// Request to generate a magic-link login token.
/// </summary>
public sealed class MagicLinkRequest
{
[Required(ErrorMessage = "The Email field is required.")]
[EmailAddress(ErrorMessage = "Invalid email format.")]
public required string Email { get; set; }
}
@@ -0,0 +1,23 @@
using Application.Utils.Constants.Validation;
using System.ComponentModel.DataAnnotations;
namespace Application.DTOs.Auth.Request;
/// <summary>
/// Payload for confirming a password reset from the email link.
/// </summary>
public sealed class PasswordResetConfirmRequest
{
[Required, EmailAddress]
public string Email { get; set; } = string.Empty;
/// <summary>
/// Token received via email, URL-decoded automatically by the framework.
/// </summary>
[Required]
public string Token { get; set; } = string.Empty;
[Required, MinLength(UserFieldLengths.PasswordMinLength)]
public string NewPassword { get; set; } = string.Empty;
}
@@ -0,0 +1,12 @@
namespace Application.DTOs.Auth.Request;
/// <summary>
/// Represents a request object for refreshing a JWT token.
/// </summary>
public class RefreshTokenRequest
{
/// <summary>
/// The refresh token to use for generating a new JWT token.
/// </summary>
public required string RefreshToken { get; set; }
}
@@ -0,0 +1,36 @@
using Application.Utils.Constants.Validation;
using System.ComponentModel.DataAnnotations;
namespace Application.DTOs.Auth.Request;
/// <summary>
/// Request to register a new user. Password is generated automatically by the system.
/// </summary>
public sealed class RegisterUserRequest
{
[Required(ErrorMessage = "Email is required.")]
[EmailAddress(ErrorMessage = "Invalid email format.")]
public required string Email { get; set; }
/// <summary>
/// Display name for the user; must be unique across all accounts.
/// </summary>
[Required(ErrorMessage = "Username is required.")]
[StringLength(UserFieldLengths.UsernameMaxLength, MinimumLength = UserFieldLengths.UsernameMinLength,
ErrorMessage = "Username must be between 3 and 50 characters.")]
public required string Username { get; set; }
/// <summary>
/// Optional contact phone number.
/// </summary>
[ArgentinePhoneNumber]
[MaxLength(UserFieldLengths.PhoneMaxLength, ErrorMessage = "Phone number must not exceed 15 characters.")]
public string? Phone { get; set; }
/// <summary>
/// Target role. Accepted values: ADMIN, OWNER.
/// </summary>
[Required(ErrorMessage = "Role is required.")]
public required string Role { get; set; }
}
@@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace Application.DTOs.Auth.Request;
/// <summary>
/// Self-service request to receive a password-reset magic link by email.
/// </summary>
public sealed class RequestPasswordResetRequest
{
[Required(ErrorMessage = "The Email field is required.")]
[EmailAddress(ErrorMessage = "Invalid email format.")]
public required string Email { get; set; }
}
@@ -0,0 +1,13 @@
using System;
namespace Application.DTOs.Auth.Response;
/// <summary>
/// Confirmation payload returned after inviting a user by email; the account has no password until activation.
/// </summary>
public sealed class InviteUserResponse(Guid userId, string email, string role)
{
public Guid UserId { get; init; } = userId;
public string Email { get; init; } = email;
public string Role { get; init; } = role;
}
@@ -0,0 +1,10 @@
namespace Application.DTOs.Auth.Response;
/// <summary>
/// Response for magic-link request flow.
/// </summary>
public sealed class MagicLinkResponse(string message, string? magicLink = null)
{
public string Message { get; init; } = message;
public string? MagicLink { get; init; } = magicLink;
}
@@ -0,0 +1,15 @@
using System;
namespace Application.DTOs.Auth.Response;
/// <summary>
/// Confirmation payload returned after successfully registering a new user.
/// </summary>
public sealed class RegisterUserResponse(Guid userId, string email, string username, string role, string? phone)
{
public Guid UserId { get; init; } = userId;
public string Email { get; init; } = email;
public string Username { get; init; } = username;
public string Role { get; init; } = role;
public string? PhoneNumber { get; init; } = phone;
}
@@ -0,0 +1,21 @@
using System;
namespace Application.DTOs.Auth.Response;
/// <summary>
/// Represents the response containing access token, expiration time, and refresh token.
/// </summary>
public sealed class TokenResponse(string accessToken, TimeSpan expiresIn, string? refreshToken)
{
/// <summary>
/// The access token used for authorization.
/// </summary>
public string AccessToken { get; init; } = accessToken;
public TimeSpan ExpiresIn { get; init; } = expiresIn;
/// <summary>
/// The refresh token used to obtain a new access token.
/// </summary>
public string? RefreshToken { get; init; } = refreshToken;
}