< Summary

Information
Class: Api.Auth.Endpoints.LoginEndpoints
Assembly: Api
File(s): /home/runner/work/ProjectRead.ing/ProjectRead.ing/Api/Auth/Endpoints/LoginEndpoints.cs
Line coverage
12%
Covered lines: 3
Uncovered lines: 22
Coverable lines: 25
Total lines: 65
Line coverage: 12%
Branch coverage
25%
Covered branches: 2
Total branches: 8
Branch coverage: 25%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Map(...)100%22100%
Login()0%4260%
.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)
 123    {
 124        route.MapPost("login", Login);
 125    }
 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            )
 037    {
 038        Guid? userId = null;
 039        string hash = string.Empty;
 40
 041        if (loginDTO.UserEmail is not null)
 042        {
 043            var user = await db.Users
 044                .Where(u => u.Email == loginDTO.UserEmail)
 045                .Select(u => new { u.Id, u.PasswordHash })
 046                .FirstAsync();
 047            userId = user.Id;
 048            hash = user.PasswordHash;
 049        }
 50
 051        var password = Encoding.UTF8.GetBytes(loginDTO.Password.Normalize());
 052        if (userId is not null &&
 053                Argon2id.VerifyHash(hash, password))
 054        {
 055            var token = await LoginUtils.CreateUserSession(userId.Value, userAgent, db);
 056            await db.SaveChangesAsync();
 57
 058            return LoginUtils.LogUserIn(ctx, token);
 59        }
 060        return TypedResults.Forbid();
 061    }
 62
 63
 064    public record LoginDTO(string UserEmail, string Password);
 65}