86 lines
3.6 KiB
C#
86 lines
3.6 KiB
C#
using System.Security.Claims;
|
|
using FluentResults;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using NexusReader.Application.DTOs.User;
|
|
using NexusReader.Data.Persistence;
|
|
using NexusReader.Domain.Entities;
|
|
using NexusReader.UI.Shared.Services;
|
|
|
|
namespace NexusReader.Web.New.Services;
|
|
|
|
public class ServerIdentityService : IIdentityService
|
|
{
|
|
private readonly UserManager<NexusUser> _userManager;
|
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
private readonly IDbContextFactory<AppDbContext> _dbContextFactory;
|
|
|
|
public event Func<Task>? OnStateInvalidated;
|
|
|
|
public ServerIdentityService(
|
|
UserManager<NexusUser> userManager,
|
|
IHttpContextAccessor httpContextAccessor,
|
|
IDbContextFactory<AppDbContext> dbContextFactory)
|
|
{
|
|
_userManager = userManager;
|
|
_httpContextAccessor = httpContextAccessor;
|
|
_dbContextFactory = dbContextFactory;
|
|
}
|
|
|
|
public Task<Result> LoginAsync(string email, string password, bool rememberMe = false)
|
|
=> throw new NotSupportedException("Use standard Identity endpoints for login on server.");
|
|
|
|
public Task<Result> LogoutAsync()
|
|
=> throw new NotSupportedException("Use standard Identity endpoints for logout on server.");
|
|
|
|
public Task<Result> RegisterAsync(string email, string password)
|
|
=> throw new NotSupportedException("Use standard Identity endpoints for registration on server.");
|
|
|
|
public Task<Result> RefreshTokenAsync() => Task.FromResult(Result.Ok());
|
|
|
|
public async Task<Result<UserProfile>> GetProfileAsync()
|
|
{
|
|
var user = _httpContextAccessor.HttpContext?.User;
|
|
if (user == null || !user.Identity?.IsAuthenticated == true) return Result.Fail("Not authenticated.");
|
|
|
|
var userId = user.FindFirstValue(ClaimTypes.NameIdentifier);
|
|
if (userId == null) return Result.Fail("User ID not found.");
|
|
|
|
using var dbContext = await _dbContextFactory.CreateDbContextAsync();
|
|
|
|
var profile = await dbContext.Users
|
|
.Where(u => u.Id == userId)
|
|
.Select(u => new UserProfile(
|
|
u.Email ?? string.Empty,
|
|
u.AITokensUsed,
|
|
u.TenantId != null && u.TenantId.Length == 36 ? new Guid(u.TenantId) : Guid.Empty,
|
|
u.SubscriptionPlan != null ? new SubscriptionPlanDto
|
|
{
|
|
Id = u.SubscriptionPlan.Id,
|
|
Name = u.SubscriptionPlan.PlanName,
|
|
AITokenLimit = u.SubscriptionPlan.AITokenLimit,
|
|
MonthlyPrice = u.SubscriptionPlan.MonthlyPrice
|
|
} : new SubscriptionPlanDto(),
|
|
u.QuizResults.Any(q => q.TotalQuestions > 0)
|
|
? (int)u.QuizResults.Where(q => q.TotalQuestions > 0).Average(q => (double)q.Score / q.TotalQuestions * 100)
|
|
: 0,
|
|
u.Ebooks.OrderByDescending(e => e.LastReadDate).Select(e => new LastReadBookDto
|
|
{
|
|
Id = e.Id,
|
|
Title = e.Title,
|
|
Author = new AuthorDto
|
|
{
|
|
Id = e.Author.Id,
|
|
Name = e.Author.Name
|
|
},
|
|
CoverUrl = e.CoverUrl,
|
|
Progress = 65, // Hardcoded for now as per design requirements, will link to real segments later
|
|
LastChapter = "Chapter 4: Renaissance in Italy"
|
|
}).FirstOrDefault()
|
|
))
|
|
.FirstOrDefaultAsync();
|
|
|
|
return profile != null ? Result.Ok(profile) : Result.Fail("Profile not found.");
|
|
}
|
|
}
|