< Summary

Information
Class: Api.Auth.Endpoints.LoginEndpoints.LoginDTO
Assembly: Api
File(s): /home/runner/work/ProjectRead.ing/ProjectRead.ing/Api/Auth/Endpoints/LoginEndpoints.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 1
Coverable lines: 1
Total lines: 65
Line coverage: 0%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%

File(s)

/home/runner/work/ProjectRead.ing/ProjectRead.ing/Api/Auth/Endpoints/LoginEndpoints.cs

#LineLine coverage
 1// SPDX-FileCopyrightText: 2026 Alper Çelik <[email protected]>
 2//
 3// SPDX-License-Identifier: AGPL-3.0-or-later
 4
 5using System.Text;
 6
 7using Api.Auth.Utils;
 8using Api.Database;
 9
 10using FluentValidation;
 11
 12using Geralt;
 13
 14using Microsoft.AspNetCore.Http.HttpResults;
 15using Microsoft.AspNetCore.Mvc;
 16using Microsoft.EntityFrameworkCore;
 17
 18namespace Api.Auth.Endpoints;
 19
 20public static class LoginEndpoints
 21{
 22    public static void Map(IEndpointRouteBuilder route)
 23    {
 24        route.MapPost("login", Login);
 25    }
 26
 27    public static async Task<
 28    Results<
 29        Ok<LoginUtils.LoginResultDTO>,
 30        ForbidHttpResult
 31    >> Login(
 32            [FromServices] HttpContext ctx,
 33            [FromServices] PGContext db,
 34            [FromHeader(Name = "user-agent")] string userAgent,
 35            [FromBody] LoginDTO loginDTO
 36            )
 37    {
 38        Guid? userId = null;
 39        string hash = string.Empty;
 40
 41        if (loginDTO.UserEmail is not null)
 42        {
 43            var user = await db.Users
 44                .Where(u => u.Email == loginDTO.UserEmail)
 45                .Select(u => new { u.Id, u.PasswordHash })
 46                .FirstAsync();
 47            userId = user.Id;
 48            hash = user.PasswordHash;
 49        }
 50
 51        var password = Encoding.UTF8.GetBytes(loginDTO.Password.Normalize());
 52        if (userId is not null &&
 53                Argon2id.VerifyHash(hash, password))
 54        {
 55            var token = await LoginUtils.CreateUserSession(userId.Value, userAgent, db);
 56            await db.SaveChangesAsync();
 57
 58            return LoginUtils.LogUserIn(ctx, token);
 59        }
 60        return TypedResults.Forbid();
 61    }
 62
 63
 064    public record LoginDTO(string UserEmail, string Password);
 65}

Methods/Properties

.ctor(string, string)