implement Clean Architecture and user authentication
- Add LoopFit.Domain with entities (ApplicationUser, Workout, CalorieEntry, VitalData), enums (WorkoutType), and interfaces (IJwtTokenGenerator, IUserRepository, IWorkoutRepository) - Add LoopFit.Application with auth DTOs, service interfaces, and DI setup - Add LoopFit.Infrastructure with EF Core DbContext (PostgreSQL), ASP.NET Core Identity, JWT token generation, and repository implementations - Add AuthController with register/login/me endpoints and JWT Bearer auth - Add MAUI auth services (AuthService, TokenStorageService) and Login/Register Blazor pages
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using LoopFit.Application.DTOs.Auth;
|
||||
using LoopFit.Application.Interfaces;
|
||||
using LoopFit.Domain.Entities;
|
||||
using LoopFit.Domain.Interfaces;
|
||||
using LoopFit.Infrastructure.Data;
|
||||
|
||||
namespace LoopFit.Infrastructure.Identity;
|
||||
|
||||
public class AuthService : IAuthService
|
||||
{
|
||||
private readonly UserManager<IdentityUser> _userManager;
|
||||
private readonly IJwtTokenGenerator _jwtTokenGenerator;
|
||||
private readonly AppDbContext _dbContext;
|
||||
|
||||
public AuthService(
|
||||
UserManager<IdentityUser> userManager,
|
||||
IJwtTokenGenerator jwtTokenGenerator,
|
||||
AppDbContext dbContext)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_jwtTokenGenerator = jwtTokenGenerator;
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
public async Task<AuthResponse?> RegisterAsync(RegisterRequest request)
|
||||
{
|
||||
var identityUser = new IdentityUser
|
||||
{
|
||||
UserName = request.Email,
|
||||
Email = request.Email
|
||||
};
|
||||
|
||||
var result = await _userManager.CreateAsync(identityUser, request.Password);
|
||||
|
||||
if (!result.Succeeded)
|
||||
return null;
|
||||
|
||||
var appUser = new ApplicationUser
|
||||
{
|
||||
Id = Guid.Parse(identityUser.Id),
|
||||
Email = request.Email,
|
||||
FirstName = request.FirstName,
|
||||
LastName = request.LastName
|
||||
};
|
||||
|
||||
_dbContext.ApplicationUsers.Add(appUser);
|
||||
await _dbContext.SaveChangesAsync();
|
||||
|
||||
var token = _jwtTokenGenerator.GenerateToken(appUser.Id, appUser.Email);
|
||||
|
||||
return new AuthResponse
|
||||
{
|
||||
Token = token,
|
||||
Expiration = DateTime.UtcNow.AddMinutes(60),
|
||||
UserName = $"{appUser.FirstName} {appUser.LastName}"
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<AuthResponse?> LoginAsync(LoginRequest request)
|
||||
{
|
||||
var identityUser = await _userManager.FindByEmailAsync(request.Email);
|
||||
|
||||
if (identityUser is null)
|
||||
return null;
|
||||
|
||||
var isValidPassword = await _userManager.CheckPasswordAsync(identityUser, request.Password);
|
||||
|
||||
if (!isValidPassword)
|
||||
return null;
|
||||
|
||||
var appUser = await _dbContext.ApplicationUsers
|
||||
.FirstOrDefaultAsync(u => u.Id == Guid.Parse(identityUser.Id));
|
||||
|
||||
var userId = Guid.Parse(identityUser.Id);
|
||||
var token = _jwtTokenGenerator.GenerateToken(userId, identityUser.Email!);
|
||||
|
||||
return new AuthResponse
|
||||
{
|
||||
Token = token,
|
||||
Expiration = DateTime.UtcNow.AddMinutes(60),
|
||||
UserName = appUser != null ? $"{appUser.FirstName} {appUser.LastName}" : identityUser.Email!
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<AuthResponse?> GetCurrentUserAsync(Guid userId)
|
||||
{
|
||||
var appUser = await _dbContext.ApplicationUsers
|
||||
.FirstOrDefaultAsync(u => u.Id == userId);
|
||||
|
||||
if (appUser is null)
|
||||
return null;
|
||||
|
||||
var token = _jwtTokenGenerator.GenerateToken(appUser.Id, appUser.Email);
|
||||
|
||||
return new AuthResponse
|
||||
{
|
||||
Token = token,
|
||||
Expiration = DateTime.UtcNow.AddMinutes(60),
|
||||
UserName = $"{appUser.FirstName} {appUser.LastName}"
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user