This commit is contained in:
Tizian.Breuch
2025-09-25 15:17:36 +02:00
parent 195d794703
commit 36cc2d97a0
3 changed files with 126 additions and 134 deletions

View File

@@ -23,44 +23,45 @@ namespace Webshop.Api.Controllers.Auth
[HttpPost("register")] [HttpPost("register")]
[AllowAnonymous] [AllowAnonymous]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> Register([FromBody] RegisterRequestDto request) public async Task<IActionResult> Register([FromBody] RegisterRequestDto request)
{ {
if (!ModelState.IsValid) return BadRequest(ModelState); if (!ModelState.IsValid) return BadRequest(ModelState);
var result = await _authService.RegisterUserAsync(request); var result = await _authService.RegisterUserAsync(request);
if (result.Type == ServiceResultType.Success) return result.Type switch
{ {
return Ok(new { Message = "Registrierung erfolgreich. Bitte bestätigen Sie Ihre E-Mail-Adresse." }); ServiceResultType.Success => Ok(new { Message = "Registrierung erfolgreich. Bitte bestätigen Sie Ihre E-Mail-Adresse." }),
} ServiceResultType.InvalidInput => BadRequest(new { Message = result.ErrorMessage }),
ServiceResultType.Failure => BadRequest(new { Message = result.ErrorMessage }),
return BadRequest(new { Message = result.ErrorMessage }); _ => StatusCode(StatusCodes.Status500InternalServerError, new { Message = result.ErrorMessage ?? "Ein unerwarteter Fehler ist aufgetreten." })
};
} }
[HttpPost("login/customer")] [HttpPost("login/customer")]
[AllowAnonymous] [AllowAnonymous]
[ProducesResponseType(typeof(AuthResponseDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AuthResponseDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> LoginCustomer([FromBody] LoginRequestDto request) public async Task<IActionResult> LoginCustomer([FromBody] LoginRequestDto request)
{ {
if (!ModelState.IsValid) return BadRequest(ModelState); if (!ModelState.IsValid) return BadRequest(ModelState);
var result = await _authService.LoginUserAsync(request); var result = await _authService.LoginUserAsync(request);
if (result.Type == ServiceResultType.Success) return result.Type switch
{ {
return Ok(result.Value); ServiceResultType.Success => Ok(result.Value),
} ServiceResultType.Unauthorized => Unauthorized(new { Message = result.ErrorMessage }),
_ => Unauthorized(new { Message = result.ErrorMessage ?? "Ungültige Anmeldeinformationen." })
return Unauthorized(new { Message = result.ErrorMessage }); };
} }
[HttpPost("login/admin")] [HttpPost("login/admin")]
[AllowAnonymous] [AllowAnonymous]
[ProducesResponseType(typeof(AuthResponseDto), StatusCodes.Status200OK)] [ProducesResponseType(typeof(AuthResponseDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status403Forbidden)]
public async Task<IActionResult> LoginAdmin([FromBody] LoginRequestDto request) public async Task<IActionResult> LoginAdmin([FromBody] LoginRequestDto request)
{ {
@@ -72,80 +73,73 @@ namespace Webshop.Api.Controllers.Auth
{ {
ServiceResultType.Success => Ok(result.Value), ServiceResultType.Success => Ok(result.Value),
ServiceResultType.Forbidden => Forbid(), ServiceResultType.Forbidden => Forbid(),
_ => Unauthorized(new { Message = result.ErrorMessage }) ServiceResultType.Unauthorized => Unauthorized(new { Message = result.ErrorMessage }),
_ => Unauthorized(new { Message = result.ErrorMessage ?? "Ungültige Anmeldeinformationen." })
}; };
} }
[HttpGet("confirm-email")] [HttpGet("confirm-email")]
[AllowAnonymous] [AllowAnonymous]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ConfirmEmail([FromQuery] string userId, [FromQuery] string token) public async Task<IActionResult> ConfirmEmail([FromQuery] string userId, [FromQuery] string token)
{ {
var result = await _authService.ConfirmEmailAsync(userId, token); var result = await _authService.ConfirmEmailAsync(userId, token);
if (result.Type == ServiceResultType.Success) return result.Type switch
{ {
return Ok(new { Message = "E-Mail-Adresse erfolgreich bestätigt. Sie können sich jetzt anmelden." }); ServiceResultType.Success => Ok(new { Message = "E-Mail-Adresse erfolgreich bestätigt. Sie können sich jetzt anmelden." }),
} _ => BadRequest(new { Message = result.ErrorMessage ?? "Der Bestätigungslink ist ungültig oder abgelaufen." })
};
return BadRequest(new { Message = result.ErrorMessage });
} }
[HttpPost("resend-email-confirmation")] [HttpPost("resend-email-confirmation")]
[AllowAnonymous] [AllowAnonymous]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ResendEmailConfirmation([FromBody] ResendEmailConfirmationRequestDto request) public async Task<IActionResult> ResendEmailConfirmation([FromBody] ResendEmailConfirmationRequestDto request)
{ {
if (!ModelState.IsValid) return BadRequest(ModelState); if (!ModelState.IsValid) return BadRequest(ModelState);
var result = await _authService.ResendEmailConfirmationAsync(request.Email); var result = await _authService.ResendEmailConfirmationAsync(request.Email);
if (result.Type == ServiceResultType.Success) return result.Type switch
{ {
// << KORREKTUR: Feste Erfolgsmeldung senden >> // Aus Sicherheitsgründen wird immer eine Erfolgsmeldung zurückgegeben, es sei denn, die E-Mail wurde bereits bestätigt.
return Ok(new { Message = "Wenn ein Konto mit dieser E-Mail-Adresse existiert und noch nicht bestätigt wurde, wurde eine neue E-Mail gesendet." }); ServiceResultType.Success => Ok(new { Message = "Wenn ein Konto mit dieser E-Mail-Adresse existiert und noch nicht bestätigt wurde, wurde eine neue E-Mail gesendet." }),
ServiceResultType.InvalidInput => BadRequest(new { Message = result.ErrorMessage }),
_ => Ok(new { Message = "Wenn ein Konto mit dieser E-Mail-Adresse existiert und noch nicht bestätigt wurde, wurde eine neue E-Mail gesendet." })
};
} }
// Wenn die E-Mail bereits bestätigt war, ist dies ein 'BadRequest' aus Sicht des Workflows.
return BadRequest(new { Message = result.ErrorMessage });
}
// << NEUER ENDPUNKT FÜR PASSWORT VERGESSEN >>
[HttpPost("forgot-password")] [HttpPost("forgot-password")]
[AllowAnonymous] [AllowAnonymous]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ForgotPassword([FromBody] ForgotPasswordRequestDto request) public async Task<IActionResult> ForgotPassword([FromBody] ForgotPasswordRequestDto request)
{ {
if (!ModelState.IsValid) return BadRequest(ModelState); if (!ModelState.IsValid) return BadRequest(ModelState);
// Diese Methode gibt bewusst kein Fehlerdetail zurück, um das Vorhandensein von E-Mail-Adressen nicht preiszugeben.
await _authService.ForgotPasswordAsync(request); await _authService.ForgotPasswordAsync(request);
return Ok(new { Message = "Wenn ein Konto mit dieser E-Mail-Adresse existiert, wurde eine E-Mail zum Zurücksetzen des Passworts gesendet." }); return Ok(new { Message = "Wenn ein Konto mit dieser E-Mail-Adresse existiert, wurde eine E-Mail zum Zurücksetzen des Passworts gesendet." });
} }
// << NEUER ENDPUNKT FÜR PASSWORT ZURÜCKSETZEN >>
[HttpPost("reset-password")] [HttpPost("reset-password")]
[AllowAnonymous] [AllowAnonymous]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(typeof(object), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> ResetPassword([FromBody] ResetPasswordDto request) public async Task<IActionResult> ResetPassword([FromBody] ResetPasswordDto request)
{ {
if (!ModelState.IsValid) return BadRequest(ModelState); if (!ModelState.IsValid) return BadRequest(ModelState);
var result = await _authService.ResetPasswordAsync(request); var result = await _authService.ResetPasswordAsync(request);
if (result.Type == ServiceResultType.Success) return result.Type switch
{ {
return Ok(new { Message = "Ihr Passwort wurde erfolgreich zurückgesetzt." }); ServiceResultType.Success => Ok(new { Message = "Ihr Passwort wurde erfolgreich zurückgesetzt." }),
} _ => BadRequest(new { Message = result.ErrorMessage ?? "Das Passwort konnte nicht zurückgesetzt werden. Der Link ist möglicherweise ungültig oder abgelaufen." })
};
return BadRequest(new { Message = result.ErrorMessage }); }
}
// HINWEIS: Der 'change-email-confirm'-Endpunkt gehört logisch eher zum CustomerController,
// da er eine Aktion eines eingeloggten Benutzers ist.
} }
} }

View File

@@ -4,6 +4,7 @@ using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Resend; using Resend;
using System; using System;
using System.IO;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
@@ -14,6 +15,7 @@ using Webshop.Application.DTOs.Auth;
using Webshop.Domain.Identity; using Webshop.Domain.Identity;
using Webshop.Infrastructure.Data; using Webshop.Infrastructure.Data;
using Webshop.Application; using Webshop.Application;
using System.Collections.Generic;
namespace Webshop.Application.Services.Auth namespace Webshop.Application.Services.Auth
{ {
@@ -68,38 +70,86 @@ namespace Webshop.Application.Services.Auth
return ServiceResult.Ok(); return ServiceResult.Ok();
} }
public async Task<ServiceResult<AuthResponseDto>> LoginUserAsync(LoginRequestDto request)
{
var user = await _userManager.FindByEmailAsync(request.Email);
if (user == null || !await _userManager.CheckPasswordAsync(user, request.Password))
{
return ServiceResult.Fail<AuthResponseDto>(ServiceResultType.Unauthorized, "Ungültige Anmeldeinformationen.");
}
if (!await _userManager.IsEmailConfirmedAsync(user))
{
return ServiceResult.Fail<AuthResponseDto>(ServiceResultType.Unauthorized, "E-Mail-Adresse wurde noch nicht bestätigt.");
}
var roles = await _userManager.GetRolesAsync(user);
var token = GenerateJwtToken(user, roles);
var response = new AuthResponseDto
{
IsAuthSuccessful = true,
Token = token,
UserId = user.Id,
Email = user.Email,
Roles = roles.ToList()
};
return ServiceResult.Ok(response);
}
public async Task<ServiceResult<AuthResponseDto>> LoginAdminAsync(LoginRequestDto request)
{
var loginResult = await LoginUserAsync(request);
if (loginResult.Type != ServiceResultType.Success)
{
// Propagate the specific login failure (e.g., Unauthorized)
return ServiceResult.Fail<AuthResponseDto>(loginResult.Type, loginResult.ErrorMessage!);
}
var user = await _userManager.FindByEmailAsync(request.Email);
// This check is belt-and-suspenders, but good practice
if (user == null || !await _userManager.IsInRoleAsync(user, "Admin"))
{
return ServiceResult.Fail<AuthResponseDto>(ServiceResultType.Forbidden, "Keine Berechtigung für den Admin-Zugang.");
}
return loginResult; // Return the successful login result
}
public async Task<ServiceResult> ConfirmEmailAsync(string userId, string token) public async Task<ServiceResult> ConfirmEmailAsync(string userId, string token)
{ {
if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(token))
{
return ServiceResult.Fail(ServiceResultType.InvalidInput, "Benutzer-ID und Token sind erforderlich.");
}
var user = await _userManager.FindByIdAsync(userId); var user = await _userManager.FindByIdAsync(userId);
if (user == null) if (user == null)
{ {
return ServiceResult.Fail(ServiceResultType.NotFound, "Benutzer nicht gefunden."); // Do not reveal that the user does not exist
return ServiceResult.Fail(ServiceResultType.NotFound, "Ungültiger Bestätigungsversuch.");
} }
var result = await _userManager.ConfirmEmailAsync(user, HttpUtility.UrlDecode(token)); var result = await _userManager.ConfirmEmailAsync(user, token); // The token from the URL is already decoded by ASP.NET Core
return result.Succeeded ? ServiceResult.Ok() : ServiceResult.Fail(ServiceResultType.Failure, "E-Mail-Bestätigung fehlgeschlagen."); return result.Succeeded
? ServiceResult.Ok()
: ServiceResult.Fail(ServiceResultType.Failure, "E-Mail-Bestätigung fehlgeschlagen.");
} }
public async Task<ServiceResult> ResendEmailConfirmationAsync(string email) public async Task<ServiceResult> ResendEmailConfirmationAsync(string email)
{ {
var user = await _userManager.FindByEmailAsync(email); var user = await _userManager.FindByEmailAsync(email);
// Fall 1: Benutzer existiert nicht. Aus Sicherheitsgründen trotzdem OK zurückgeben.
if (user == null) if (user == null)
{ {
return ServiceResult.Ok(); return ServiceResult.Ok(); // Do not reveal user existence
} }
// Fall 2: Die E-Mail des Benutzers ist bereits bestätigt.
// Wir prüfen die Eigenschaft direkt auf dem frisch geladenen User-Objekt.
if (user.EmailConfirmed) if (user.EmailConfirmed)
{ {
// In diesem Fall wollen wir einen Fehler an das Frontend geben,
// damit der Benutzer weiß, dass alles in Ordnung ist.
return ServiceResult.Fail(ServiceResultType.InvalidInput, "Diese E-Mail-Adresse ist bereits bestätigt."); return ServiceResult.Fail(ServiceResultType.InvalidInput, "Diese E-Mail-Adresse ist bereits bestätigt.");
} }
// Fall 3: Benutzer existiert, ist aber nicht bestätigt -> E-Mail senden.
await SendEmailConfirmationEmail(user); await SendEmailConfirmationEmail(user);
return ServiceResult.Ok(); return ServiceResult.Ok();
} }
@@ -109,19 +159,19 @@ namespace Webshop.Application.Services.Auth
var user = await _userManager.FindByEmailAsync(request.Email); var user = await _userManager.FindByEmailAsync(request.Email);
if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
{ {
return ServiceResult.Ok(); return ServiceResult.Ok(); // Do not reveal user existence or status
} }
var token = await _userManager.GeneratePasswordResetTokenAsync(user); var token = await _userManager.GeneratePasswordResetTokenAsync(user);
var encodedToken = HttpUtility.UrlEncode(token);
var clientUrl = _configuration["App:ClientUrl"] ?? "http://localhost:3000"; var clientUrl = _configuration["App:ClientUrl"] ?? "http://localhost:3000";
var resetLink = $"{clientUrl}/reset-password?email={HttpUtility.UrlEncode(request.Email)}&token={encodedToken}"; // Important: URL-encode components separately to avoid encoding the whole URL structure
var resetLink = $"{clientUrl}/reset-password?email={HttpUtility.UrlEncode(request.Email)}&token={HttpUtility.UrlEncode(token)}";
var emailHtmlBody = await LoadAndFormatEmailTemplate( var emailHtmlBody = await LoadAndFormatEmailTemplate(
titel: "Setzen Sie Ihr Passwort zurück", "Setzen Sie Ihr Passwort zurück",
haupttext: "Sie haben eine Anfrage zum Zurücksetzen Ihres Passworts gesendet. Klicken Sie auf den Button unten, um ein neues Passwort festzulegen.", "Sie haben eine Anfrage zum Zurücksetzen Ihres Passworts gesendet. Klicken Sie auf den Button unten, um ein neues Passwort festzulegen.",
callToActionText: "Passwort zurücksetzen", "Passwort zurücksetzen",
callToActionLink: resetLink resetLink
); );
var message = new EmailMessage(); var message = new EmailMessage();
@@ -139,18 +189,17 @@ namespace Webshop.Application.Services.Auth
var user = await _userManager.FindByEmailAsync(request.Email); var user = await _userManager.FindByEmailAsync(request.Email);
if (user == null) if (user == null)
{ {
// Don't reveal user non-existence, but the error message will be generic
return ServiceResult.Fail(ServiceResultType.InvalidInput, "Fehler beim Zurücksetzen des Passworts."); return ServiceResult.Fail(ServiceResultType.InvalidInput, "Fehler beim Zurücksetzen des Passworts.");
} }
var result = await _userManager.ResetPasswordAsync(user, HttpUtility.UrlDecode(request.Token), request.NewPassword); var result = await _userManager.ResetPasswordAsync(user, request.Token, request.NewPassword);
return result.Succeeded return result.Succeeded
? ServiceResult.Ok() ? ServiceResult.Ok()
: ServiceResult.Fail(ServiceResultType.InvalidInput, string.Join(" ", result.Errors.Select(e => e.Description))); : ServiceResult.Fail(ServiceResultType.InvalidInput, string.Join(" ", result.Errors.Select(e => e.Description)));
} }
// --- Private Helper-Methoden ---
private async Task SendEmailConfirmationEmail(ApplicationUser user) private async Task SendEmailConfirmationEmail(ApplicationUser user)
{ {
var token = await _userManager.GenerateEmailConfirmationTokenAsync(user); var token = await _userManager.GenerateEmailConfirmationTokenAsync(user);
@@ -159,42 +208,20 @@ namespace Webshop.Application.Services.Auth
var confirmationLink = $"{clientUrl}/confirm-email?userId={user.Id}&token={encodedToken}"; var confirmationLink = $"{clientUrl}/confirm-email?userId={user.Id}&token={encodedToken}";
var emailHtmlBody = await LoadAndFormatEmailTemplate( var emailHtmlBody = await LoadAndFormatEmailTemplate(
titel: "Bestätigen Sie Ihre E-Mail-Adresse", "Bestätigen Sie Ihre E-Mail-Adresse",
haupttext: "Vielen Dank für Ihre Registrierung! Bitte klicken Sie auf den Button unten, um Ihr Konto zu aktivieren.", "Vielen Dank für Ihre Registrierung! Bitte klicken Sie auf den Button unten, um Ihr Konto zu aktivieren.",
callToActionText: "Konto aktivieren", "Konto aktivieren",
callToActionLink: confirmationLink confirmationLink
); );
var message = new EmailMessage(); var message = new EmailMessage();
message.To.Add(user.Email); message.To.Add(user.Email!);
message.From = _configuration["Resend:FromEmail"]!; message.From = _configuration["Resend:FromEmail"]!;
message.Subject = "Willkommen! Bitte bestätigen Sie Ihre E-Mail-Adresse"; message.Subject = "Willkommen! Bitte bestätigen Sie Ihre E-Mail-Adresse";
message.HtmlBody = emailHtmlBody; message.HtmlBody = emailHtmlBody;
await _resend.EmailSendAsync(message); await _resend.EmailSendAsync(message);
} }
private async Task<string> LoadAndFormatEmailTemplate(string titel, string haupttext, string callToActionText, string callToActionLink)
{
var templatePath = Path.Combine(AppContext.BaseDirectory, "Templates", "_EmailTemplate.html");
if (!File.Exists(templatePath))
{
// Fallback, falls die Vorlagendatei nicht gefunden wird
return $"<h1>{titel}</h1><p>{haupttext}</p><a href='{callToActionLink}'>{callToActionText}</a>";
}
var template = await File.ReadAllTextAsync(templatePath);
template = template.Replace("{{ShopName}}", _configuration["ShopInfo:Name"] ?? "Ihr Webshop");
template = template.Replace("{{Titel}}", titel);
template = template.Replace("{{Haupttext}}", haupttext);
template = template.Replace("{{CallToActionText}}", callToActionText);
template = template.Replace("{{CallToActionLink}}", callToActionLink);
template = template.Replace("{{Jahr}}", DateTime.UtcNow.Year.ToString());
return template;
}
private string GenerateJwtToken(ApplicationUser user, IList<string> roles) private string GenerateJwtToken(ApplicationUser user, IList<string> roles)
{ {
var claims = new List<Claim> var claims = new List<Claim>
@@ -225,48 +252,21 @@ namespace Webshop.Application.Services.Auth
return new JwtSecurityTokenHandler().WriteToken(token); return new JwtSecurityTokenHandler().WriteToken(token);
} }
public async Task<ServiceResult<AuthResponseDto>> LoginAdminAsync(LoginRequestDto request) private async Task<string> LoadAndFormatEmailTemplate(string titel, string haupttext, string callToActionText, string callToActionLink)
{ {
var loginResult = await LoginUserAsync(request); var templatePath = Path.Combine(AppContext.BaseDirectory, "Templates", "_EmailTemplate.html");
if (loginResult.Type != ServiceResultType.Success) if (!File.Exists(templatePath))
{ {
return loginResult; return $"<h1>{titel}</h1><p>{haupttext}</p><a href='{callToActionLink}'>{callToActionText}</a>";
} }
var template = await File.ReadAllTextAsync(templatePath);
var user = await _userManager.FindByEmailAsync(request.Email); template = template.Replace("{{ShopName}}", _configuration["ShopInfo:Name"] ?? "Ihr Webshop");
if (user == null || !await _userManager.IsInRoleAsync(user, "Admin")) template = template.Replace("{{Titel}}", titel);
{ template = template.Replace("{{Haupttext}}", haupttext);
return ServiceResult.Fail<AuthResponseDto>(ServiceResultType.Forbidden, "Keine Berechtigung für den Admin-Zugang."); template = template.Replace("{{CallToActionText}}", callToActionText);
} template = template.Replace("{{CallToActionLink}}", callToActionLink);
template = template.Replace("{{Jahr}}", DateTime.UtcNow.Year.ToString());
return loginResult; return template;
}
public async Task<ServiceResult<AuthResponseDto>> LoginUserAsync(LoginRequestDto request)
{
var user = await _userManager.FindByEmailAsync(request.Email);
if (user == null || !await _userManager.CheckPasswordAsync(user, request.Password))
{
return ServiceResult.Fail<AuthResponseDto>(ServiceResultType.Unauthorized, "Ungültige Anmeldeinformationen.");
}
if (!await _userManager.IsEmailConfirmedAsync(user))
{
return ServiceResult.Fail<AuthResponseDto>(ServiceResultType.Unauthorized, "E-Mail-Adresse wurde noch nicht bestätigt.");
}
var roles = await _userManager.GetRolesAsync(user);
var token = GenerateJwtToken(user, roles);
var response = new AuthResponseDto
{
IsAuthSuccessful = true,
Token = token,
UserId = user.Id,
Email = user.Email,
Roles = roles.ToList()
};
return ServiceResult.Ok(response);
} }
} }
} }

View File

@@ -7,13 +7,11 @@ namespace Webshop.Application.Services.Auth
{ {
public interface IAuthService public interface IAuthService
{ {
Task<ServiceResult> RegisterUserAsync(RegisterRequestDto request); // << Gibt kein DTO mehr zurück >> Task<ServiceResult> RegisterUserAsync(RegisterRequestDto request);
Task<ServiceResult<AuthResponseDto>> LoginUserAsync(LoginRequestDto request); Task<ServiceResult<AuthResponseDto>> LoginUserAsync(LoginRequestDto request);
Task<ServiceResult<AuthResponseDto>> LoginAdminAsync(LoginRequestDto request); Task<ServiceResult<AuthResponseDto>> LoginAdminAsync(LoginRequestDto request);
Task<ServiceResult> ConfirmEmailAsync(string userId, string token); Task<ServiceResult> ConfirmEmailAsync(string userId, string token);
Task<ServiceResult> ResendEmailConfirmationAsync(string email); Task<ServiceResult> ResendEmailConfirmationAsync(string email);
// << NEUE METHODEN >>
Task<ServiceResult> ForgotPasswordAsync(ForgotPasswordRequestDto request); Task<ServiceResult> ForgotPasswordAsync(ForgotPasswordRequestDto request);
Task<ServiceResult> ResetPasswordAsync(ResetPasswordDto request); Task<ServiceResult> ResetPasswordAsync(ResetPasswordDto request);
} }