< Summary

Information
Class: Api.Auth.Mutations.LoginInput
Assembly: Api
File(s): /home/runner/work/ProjectRead.ing/ProjectRead.ing/Api/Auth/Mutations/LoginMutation.cs
Line coverage
100%
Covered lines: 1
Uncovered lines: 0
Coverable lines: 1
Total lines: 65
Line coverage: 100%
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%11100%

File(s)

/home/runner/work/ProjectRead.ing/ProjectRead.ing/Api/Auth/Mutations/LoginMutation.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;
 6using Api.Auth.Models;
 7using Api.Auth.Utils;
 8using Api.Database;
 9using Api.Database.Utils;
 10using FluentValidation;
 11using Geralt;
 12using HotChocolate.Authorization;
 13using Microsoft.EntityFrameworkCore;
 14
 15namespace Api.Auth.Mutations;
 16
 17public record LoginPayload(Queries.User User, string Token);
 18
 119public record LoginInput(string Email, string Password, string ClientName = "unknown");
 20
 21[MutationType]
 22public static partial class LoginMutations
 23{
 24    [AllowAnonymous]
 25    public static async Task<LoginPayload> LoginMutation(
 26        [Service] PGContext db,
 27        [Service] IEFTransactionDIAccessorService txAccessor,
 28        LoginInput input
 29    )
 30    {
 31        var tx = await txAccessor.BeginOrGetTransactionAsync();
 32        UserEF? user = await db
 33            .Users.Where(u => u.Email == input.Email.NormalizeEmail())
 34            .FirstOrDefaultAsync();
 35
 36        var junkHash = new char[Argon2id.HashSize];
 37        Argon2id.ComputeHash(
 38            junkHash,
 39            Encoding.UTF8.GetBytes("123"),
 40            AuthUtils.ARGON2ID_ITER,
 41            AuthUtils.ARGON2ID_MEM_BYTES
 42        );
 43
 44        var passworkdVerified = Argon2id.VerifyHash(
 45            user?.PasswordHash ?? new string(junkHash),
 46            Encoding.UTF8.GetBytes(input.Password.Normalize())
 47        );
 48
 49        if (user is not null && passworkdVerified)
 50        {
 51            var token = await AuthUtils.CreateUserSession(user.Id, input.ClientName, db);
 52            await db.SaveChangesAsync();
 53            await tx.CommitAsync();
 54            return new(Queries.UserMapper.ToDto(user), token);
 55        }
 56
 57        throw new GraphQLException(
 58            ErrorBuilder
 59                .New()
 60                .SetMessage("Invalid Credentials")
 61                .SetCode(ErrorCodes.INVALID_CREDS)
 62                .Build()
 63        );
 64    }
 65}

Methods/Properties

.ctor(string, string, string)