Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Andrespeerez/porfolio-blog/llms.txt

Use this file to discover all available pages before exploring further.

The Application layer exposes three use cases that represent the core business operations of the CMS. Each use case is a plain C# class registered in the DI container and injected wherever it is needed. They depend exclusively on port interfaces — never on concrete infrastructure — keeping the business logic fully decoupled from EF Core, Identity, or ASP.NET Core internals.

AuthenticateUser

Verifies a user’s credentials and establishes an authenticated session by writing an authentication cookie. Method signature
public async Task<AuthResult> ExecuteAsync(string email, string password)

Parameters

email
string
required
The email address submitted by the user on the login form. Used as the lookup key in IUserRepository.
password
string
required
The plain-text password submitted by the user. It is never stored — it is compared against the stored hash via IPasswordHasher.Verify.

Return value

AuthResult
record

How it works

1

Look up the user by email

Calls IUserRepository.GetByEmailAsync(email). If no record is found, returns AuthResult.Fail("Credenciales incorrectas.") immediately — intentionally avoiding a distinct “user not found” message to prevent user enumeration.
2

Verify the password hash

Passes the stored PasswordHash and the raw input to IPasswordHasher.Verify. A mismatch also returns AuthResult.Fail("Credenciales incorrectas.").
3

Sign in via ISessionManager

On success, calls ISessionManager.SignInAsync(user), which writes an authentication cookie carrying the user’s ID and email as claims.
4

Return success

Returns AuthResult.Ok() — a record with Success = true and Error = null.

Source

Application/UseCases/AuthenticateUser.cs
public class AuthenticateUser
{
    public async Task<AuthResult> ExecuteAsync(string email, string password)
    {
        User? user = await _userRepository.GetByEmailAsync(email);

        if (user == null)
            return AuthResult.Fail("Credenciales incorrectas.");

        if (!_passwordHasher.Verify(user.PasswordHash, password))
            return AuthResult.Fail("Credenciales incorrectas.");

        await _sessionManager.SignInAsync(user); // crea cookie

        return AuthResult.Ok();
    }
}

Error conditions

Both “user not found” and “wrong password” return the same error message — "Credenciales incorrectas." — to prevent attackers from discovering which email addresses are registered.
ConditionSuccessError
User not foundfalse"Credenciales incorrectas."
Password mismatchfalse"Credenciales incorrectas."
Valid credentialstruenull

RegisterUser

Creates a new user account by hashing the provided password, persisting the entity, and returning the new user’s ID. Method signature
public async Task<RegisterResult> ExecuteAsync(string email, string rawPassword)

Parameters

email
string
required
The email address for the new account. Must be unique across all users — a duplicate triggers an early-return failure before any write occurs.
rawPassword
string
required
The plain-text password chosen by the new user. It is hashed by User.Create(...) via IPasswordHasher.Hash before being stored; the raw value is never persisted.

Return value

RegisterResult
record

How it works

1

Check for a duplicate email

Calls IUserRepository.GetByEmailAsync(email). If a record is returned, the use case exits early with RegisterResult.Fail("Ese email ya está registrado."). No write takes place.
2

Create the User entity

Calls the domain factory User.Create(email, rawPassword, _passwordHasher). The factory hashes the password internally via IPasswordHasher.Hash and sets all required fields on the new User instance.
3

Persist the new user

Calls IUserRepository.AddAsync(user), which inserts the record and flushes the EF Core change tracker.
4

Return the new ID

Returns RegisterResult.Ok(user.Id), carrying the auto-generated primary key so the caller can reference the new account immediately.

Source

Application/UseCases/RegisterUser.cs
public class RegisterUser
{
    public async Task<RegisterResult> ExecuteAsync(string email, string rawPassword)
    {
        var existing = await _userRepository.GetByEmailAsync(email);
        if (existing is not null)
        {
            return RegisterResult.Fail("Ese email ya está registrado.");
        }

        var user = User.Create(email, rawPassword, _passwordHasher);

        await _userRepository.AddAsync(user);

        return RegisterResult.Ok(user.Id);
    }
}

Error conditions

ConditionSuccessNewIdError
Email already registeredfalsenull"Ese email ya está registrado."
Registration successfultrue<new id>null
RegisterUser does not sign in the new user automatically. After a successful registration, the caller is responsible for redirecting the user to the login page or explicitly invoking AuthenticateUser.
No HTTP endpoint is currently mapped for RegisterUser. The Api/Auth/Register.cs file exists but is empty, and Program.cs does not call any MapRegister() extension. RegisterUser is available as an Application-layer use case and is registered in the DI container (AddScoped<RegisterUser>()), but it cannot be invoked through a public API request at this time. Wire up an endpoint before exposing this functionality.

LogoutUser

Terminates the current user session by revoking the authentication cookie. Method signature
public async Task ExecuteAsync()

Parameters

This method takes no parameters. It operates exclusively through the ISessionManager abstraction, which reads the current HTTP context internally.

Return value

Task — the method completes when the session has been revoked. It does not return a result object because logout is considered an unconditional operation: if there is no active session, SignOutAsync is a no-op.

How it works

1

Delegate to ISessionManager

Calls ISessionManager.SignOutAsync(), which invokes ASP.NET Core’s HttpContext.SignOutAsync to remove the authentication cookie from the response.

Source

Application/UseCases/LogoutUser.cs
public class LogoutUser
{
    public async Task ExecuteAsync()
    {
        await _sessionManager.SignOutAsync();
    }
}
Because LogoutUser has a single dependency (ISessionManager) and a single line of logic, it is deliberately thin. All cookie-handling details live in the infrastructure adapter CookieSessionManager, keeping this use case easy to unit-test with a mock.

DTOs

Data transfer objects used as inputs and outputs for the use cases above. All three are C# record types — immutable by default, with built-in value equality.

AuthResult

Returned by AuthenticateUser.ExecuteAsync.
Application/DTOs/AuthResult.cs
public record AuthResult(bool Success, string? Error = null)
{
    public static AuthResult Ok() => new(true);
    public static AuthResult Fail(string error) => new(false, error);
}

AuthResult.Ok()

Factory for a successful authentication. Produces { Success: true, Error: null }.

AuthResult.Fail(string error)

Factory for a failed authentication. Produces { Success: false, Error: "<message>" }.
FieldTypeDescription
Successbooltrue when authentication succeeded.
Errorstring?Human-readable error message, or null on success.

RegisterResult

Returned by RegisterUser.ExecuteAsync.
Application/DTOs/RegisterResult.cs
public record RegisterResult(bool Success, int? NewId = null, string? Error = null)
{
    public static RegisterResult Ok(int newId) => new(true, newId);
    public static RegisterResult Fail(string error) => new(false, Error: error);
}

RegisterResult.Ok(int newId)

Factory for a successful registration. Carries the new user’s database ID. Produces { Success: true, NewId: <id>, Error: null }.

RegisterResult.Fail(string error)

Factory for a failed registration. Produces { Success: false, NewId: null, Error: "<message>" }.
FieldTypeDescription
Successbooltrue when the account was created.
NewIdint?The new user’s primary key, or null on failure.
Errorstring?Human-readable error message, or null on success.

LoginRequest

A strongly-typed container for the values submitted on a login form. Not passed directly to AuthenticateUser.ExecuteAsync, but used by the Blazor component layer to bind form fields and carry the RememberMe preference.
Application/DTOs/LoginRequest.cs
public record LoginRequest(string Email, string Password, bool RememberMe = false);
FieldTypeDefaultDescription
EmailstringThe email address entered by the user.
PasswordstringThe plain-text password entered by the user.
RememberMeboolfalseWhen true, signals the session layer to issue a persistent cookie.

Build docs developers (and LLMs) love