This commit is contained in:
6d486f49
2026-08-17 00:45:08 -04:00
parent 3a2f112a73
commit 1d6207fbfe
154 changed files with 126007 additions and 47385 deletions
+208
View File
@@ -0,0 +1,208 @@
using API.Data;
using API.Models;
using API.Services;
using Microsoft.EntityFrameworkCore;
using Model;
namespace API.GraphQL;
public class Mutation
{
private static string EnsureAuthenticated(IHttpContextAccessor? httpContextAccessor, ITokenService tokenService)
{
var httpContext = httpContextAccessor?.HttpContext;
if (httpContext == null)
throw new Exception("Authentication required. Please provide a valid authorization token.");
var authHeader = httpContext.Request.Headers["Authorization"].FirstOrDefault();
if (string.IsNullOrWhiteSpace(authHeader))
throw new Exception("Authentication required. Please login to access this resource.");
var token = authHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)
? authHeader["Bearer ".Length..].Trim()
: authHeader.Trim();
var username = tokenService.ValidateToken(token);
if (string.IsNullOrEmpty(username))
throw new Exception("Invalid or expired authentication token. Please login again.");
return username;
}
public async Task<LoginPayload> Login(
[Service] AppDbContext db,
[Service] ITokenService tokenService,
string username,
string password)
{
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
return new LoginPayload
{
Success = false,
Message = "Username and password are required."
};
try
{
var user = await db.Users.FirstOrDefaultAsync(u => u.Username == username);
if (user == null)
{
user = new User
{
Username = username,
Password = password,
CreatedAt = DateTime.UtcNow
};
db.Users.Add(user);
await db.SaveChangesAsync();
}
else if (user.Password != password)
{
return new LoginPayload
{
Success = false,
Message = "Invalid credentials."
};
}
var token = tokenService.GenerateToken(username);
return new LoginPayload
{
Success = true,
Token = token,
Username = username,
Message = "Login successful."
};
}
catch (Exception ex)
{
return new LoginPayload
{
Success = false,
Message = $"Login failed: {ex.Message}"
};
}
}
public async Task<CardNote> SaveNote(
[Service] AppDbContext db,
[Service] IHttpContextAccessor httpContextAccessor,
[Service] ITokenService tokenService,
string cardName,
string note)
{
var username = EnsureAuthenticated(httpContextAccessor, tokenService);
try
{
var existing =
await db.CardNotes.FirstOrDefaultAsync(n => n.CardName == cardName && n.Username == username);
if (existing == null)
{
var cardNote = new CardNote
{ Username = username, CardName = cardName, Note = note, UpdatedAt = DateTime.UtcNow };
db.CardNotes.Add(cardNote);
await db.SaveChangesAsync();
return cardNote;
}
existing.Note = note;
existing.UpdatedAt = DateTime.UtcNow;
await db.SaveChangesAsync();
return existing;
}
catch (Exception ex)
{
Console.WriteLine($"[WARNING] Could not save note: {ex.Message}");
return new CardNote { Username = username, CardName = cardName, Note = note };
}
}
public async Task<bool> DeleteNote(
[Service] AppDbContext db,
[Service] IHttpContextAccessor httpContextAccessor,
[Service] ITokenService tokenService,
string cardName)
{
var username = EnsureAuthenticated(httpContextAccessor, tokenService);
try
{
var existing =
await db.CardNotes.FirstOrDefaultAsync(n => n.CardName == cardName && n.Username == username);
if (existing != null)
{
db.CardNotes.Remove(existing);
await db.SaveChangesAsync();
return true;
}
return false;
}
catch (Exception ex)
{
Console.WriteLine($"[WARNING] Could not delete note: {ex.Message}");
return false;
}
}
public async Task<UserDeck> SaveDeck(
[Service] AppDbContext db,
[Service] IHttpContextAccessor httpContextAccessor,
[Service] ITokenService tokenService,
UserDeckInput input)
{
EnsureAuthenticated(httpContextAccessor, tokenService);
var id = input.Id ?? Guid.NewGuid();
var existing = await db.UserDecks.FindAsync(id);
if (existing == null)
{
var deck = new UserDeck
{
Id = id,
Name = input.Name,
Cards = input.Cards ?? [],
Divers = input.Divers ?? [],
Notes = input.Notes,
Season = input.Season,
UpdatedAt = DateTime.UtcNow
};
db.UserDecks.Add(deck);
await db.SaveChangesAsync();
return deck;
}
existing.Name = input.Name;
existing.Cards = input.Cards ?? [];
existing.Divers = input.Divers ?? [];
existing.Notes = input.Notes;
existing.Season = input.Season;
existing.UpdatedAt = DateTime.UtcNow;
await db.SaveChangesAsync();
return existing;
}
public async Task<bool> DeleteDeck(
[Service] AppDbContext db,
[Service] IHttpContextAccessor httpContextAccessor,
[Service] ITokenService tokenService,
Guid id)
{
EnsureAuthenticated(httpContextAccessor, tokenService);
var existing = await db.UserDecks.FindAsync(id);
if (existing != null)
{
db.UserDecks.Remove(existing);
await db.SaveChangesAsync();
return true;
}
return false;
}
}
public record UserDeckInput(
Guid? Id,
string Name,
List<string>? Cards,
List<string>? Divers,
string? Notes,
string? Season);