huntapi/Controllers/AuthController.cs
Finn Skov Henriksen d7479db902
Some checks failed
Build / Restore, build and publish (push) Failing after 2m7s
first commit
2026-08-31 12:29:23 +02:00

91 lines
4.0 KiB
C#

using HuntingAppApi.Models;
using HuntingAppApi.Services;
using Microsoft.AspNetCore.Mvc;
using Npgsql;
using NpgsqlTypes;
namespace HuntingAppApi.Controllers;
[ApiController]
[Route("api/auth")]
public sealed class AuthController(NpgsqlDataSource dataSource, ExternalTokenValidator validator, JwtTokenService jwt) : ControllerBase
{
[HttpPost("external-login")]
public async Task<ActionResult<LoginResponse>> ExternalLogin([FromBody] ExternalLoginRequest request, CancellationToken ct)
{
var external = await validator.ValidateAsync(request.Provider, request.IdToken, ct);
await using var conn = await dataSource.OpenConnectionAsync(ct);
await using var tx = await conn.BeginTransactionAsync(ct);
Guid? userId = null;
string displayName = external.DisplayName;
string? email = external.Email;
await using (var find = new NpgsqlCommand("""
SELECT u.id, u.display_name, u.email
FROM user_identity i
JOIN app_user u ON u.id = i.user_id
WHERE i.provider = @provider AND i.provider_subject = @subject
""", conn, tx))
{
find.Parameters.AddWithValue("provider", external.Provider);
find.Parameters.AddWithValue("subject", external.Subject);
await using var r = await find.ExecuteReaderAsync(ct);
if (await r.ReadAsync(ct))
{
userId = r.GetGuid(0);
displayName = r.GetString(1);
email = r.IsDBNull(2) ? null : r.GetString(2);
}
}
if (userId is null)
{
userId = Guid.NewGuid();
await using var createUser = new NpgsqlCommand("""
INSERT INTO app_user (id, display_name, email, avatar_url)
VALUES (@id, @display_name, @email, @avatar_url)
""", conn, tx);
createUser.Parameters.AddWithValue("id", userId.Value);
createUser.Parameters.AddWithValue("display_name", displayName);
createUser.Parameters.AddWithValue("email", (object?)email ?? DBNull.Value);
createUser.Parameters.AddWithValue("avatar_url", (object?)external.AvatarUrl ?? DBNull.Value);
await createUser.ExecuteNonQueryAsync(ct);
await using var createIdentity = new NpgsqlCommand("""
INSERT INTO user_identity (user_id, provider, provider_subject, email, email_verified, display_name, avatar_url)
VALUES (@user_id, @provider, @subject, @email, @email_verified, @display_name, @avatar_url)
""", conn, tx);
createIdentity.Parameters.AddWithValue("user_id", userId.Value);
createIdentity.Parameters.AddWithValue("provider", external.Provider);
createIdentity.Parameters.AddWithValue("subject", external.Subject);
createIdentity.Parameters.AddWithValue("email", (object?)email ?? DBNull.Value);
createIdentity.Parameters.AddWithValue("email_verified", external.EmailVerified);
createIdentity.Parameters.AddWithValue("display_name", displayName);
createIdentity.Parameters.AddWithValue("avatar_url", (object?)external.AvatarUrl ?? DBNull.Value);
await createIdentity.ExecuteNonQueryAsync(ct);
}
else
{
await using var updateLogin = new NpgsqlCommand("""
UPDATE user_identity SET last_login_at = now()
WHERE provider = @provider AND provider_subject = @subject
""", conn, tx);
updateLogin.Parameters.AddWithValue("provider", external.Provider);
updateLogin.Parameters.AddWithValue("subject", external.Subject);
await updateLogin.ExecuteNonQueryAsync(ct);
}
await tx.CommitAsync(ct);
return Ok(new LoginResponse
{
UserId = userId.Value,
DisplayName = displayName,
Email = email,
Token = jwt.CreateToken(userId.Value, displayName, email)
});
}
}