API Test
This commit is contained in:
@@ -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);
|
||||
Reference in New Issue
Block a user