- Added EmailBlacklist service and controller for managing blacklisted emails. - Created EmailBlacklistDto for data transfer and EmailBlacklistFormViewModel for form handling. - Implemented views for listing and adding emails to the blacklist. - Updated database schema with new EmailBlacklist entity and related migrations. - Enhanced OAuthClientFormViewModel to include ClientId and ClientSecret properties. - Added EmailBlacklistService to handle email blacklisting logic. - Integrated email blacklist service into the application with necessary dependencies.
179 lines
5.4 KiB
C#
179 lines
5.4 KiB
C#
using MemberCenter.Api.Contracts;
|
|
using MemberCenter.Application.Abstractions;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using OpenIddict.Abstractions;
|
|
|
|
namespace MemberCenter.Api.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("newsletter")]
|
|
public class NewsletterController : ControllerBase
|
|
{
|
|
private readonly INewsletterService _newsletterService;
|
|
|
|
public NewsletterController(INewsletterService newsletterService)
|
|
{
|
|
_newsletterService = newsletterService;
|
|
}
|
|
|
|
[HttpPost("subscribe")]
|
|
public async Task<IActionResult> Subscribe([FromBody] SubscribeRequest request)
|
|
{
|
|
var result = await _newsletterService.SubscribeAsync(request.ListId, request.Email, request.Preferences);
|
|
if (result is null)
|
|
{
|
|
return NotFound("List not found.");
|
|
}
|
|
|
|
return Ok(new
|
|
{
|
|
id = result.Subscription.Id,
|
|
list_id = result.Subscription.ListId,
|
|
email = result.Subscription.Email,
|
|
status = result.Subscription.Status,
|
|
created_at = result.Subscription.CreatedAt,
|
|
confirm_token = result.ConfirmToken
|
|
});
|
|
}
|
|
|
|
[HttpGet("confirm")]
|
|
public async Task<IActionResult> Confirm([FromQuery] string token)
|
|
{
|
|
var subscription = await _newsletterService.ConfirmAsync(token);
|
|
if (subscription is null)
|
|
{
|
|
return NotFound("Invalid token.");
|
|
}
|
|
|
|
return Ok(new
|
|
{
|
|
id = subscription.Id,
|
|
list_id = subscription.ListId,
|
|
email = subscription.Email,
|
|
status = subscription.Status,
|
|
created_at = subscription.CreatedAt
|
|
});
|
|
}
|
|
|
|
[HttpPost("unsubscribe")]
|
|
public async Task<IActionResult> Unsubscribe([FromBody] UnsubscribeRequest request)
|
|
{
|
|
var subscription = await _newsletterService.UnsubscribeAsync(request.Token);
|
|
if (subscription is null)
|
|
{
|
|
return NotFound("Invalid token.");
|
|
}
|
|
|
|
return Ok(new
|
|
{
|
|
id = subscription.Id,
|
|
list_id = subscription.ListId,
|
|
email = subscription.Email,
|
|
status = subscription.Status,
|
|
created_at = subscription.CreatedAt
|
|
});
|
|
}
|
|
|
|
[HttpPost("unsubscribe-token")]
|
|
public async Task<IActionResult> IssueUnsubscribeToken([FromBody] IssueUnsubscribeTokenRequest request)
|
|
{
|
|
if (request.ListId == Guid.Empty || string.IsNullOrWhiteSpace(request.Email))
|
|
{
|
|
return BadRequest("Both list_id and email are required.");
|
|
}
|
|
|
|
var token = await _newsletterService.IssueUnsubscribeTokenAsync(request.ListId, request.Email);
|
|
if (token is null)
|
|
{
|
|
return NotFound("Subscription not found.");
|
|
}
|
|
|
|
return Ok(new
|
|
{
|
|
unsubscribe_token = token
|
|
});
|
|
}
|
|
|
|
[HttpGet("preferences")]
|
|
public async Task<IActionResult> Preferences([FromQuery(Name = "list_id")] Guid? listId, [FromQuery] string? email)
|
|
{
|
|
if (!listId.HasValue || listId.Value == Guid.Empty || string.IsNullOrWhiteSpace(email))
|
|
{
|
|
return BadRequest("Both list_id and email are required.");
|
|
}
|
|
|
|
var subscription = await _newsletterService.GetPreferencesAsync(listId.Value, email);
|
|
if (subscription is null)
|
|
{
|
|
return NotFound("Subscription not found.");
|
|
}
|
|
|
|
return Ok(new
|
|
{
|
|
id = subscription.Id,
|
|
list_id = subscription.ListId,
|
|
email = subscription.Email,
|
|
status = subscription.Status,
|
|
preferences = subscription.Preferences
|
|
});
|
|
}
|
|
|
|
[HttpPost("preferences")]
|
|
public async Task<IActionResult> UpdatePreferences([FromBody] UpdatePreferencesRequest request)
|
|
{
|
|
if (request.ListId == Guid.Empty || string.IsNullOrWhiteSpace(request.Email))
|
|
{
|
|
return BadRequest("Both list_id and email are required.");
|
|
}
|
|
|
|
var subscription = await _newsletterService.UpdatePreferencesAsync(request.ListId, request.Email, request.Preferences);
|
|
if (subscription is null)
|
|
{
|
|
return NotFound("Subscription not found.");
|
|
}
|
|
|
|
return Ok(new
|
|
{
|
|
id = subscription.Id,
|
|
list_id = subscription.ListId,
|
|
email = subscription.Email,
|
|
status = subscription.Status,
|
|
preferences = subscription.Preferences
|
|
});
|
|
}
|
|
|
|
[Authorize]
|
|
[HttpGet("subscriptions")]
|
|
public async Task<IActionResult> ListSubscriptions([FromQuery(Name = "list_id")] Guid listId)
|
|
{
|
|
if (!HasScope(User, "newsletter:list.read"))
|
|
{
|
|
return Forbid();
|
|
}
|
|
|
|
if (listId == Guid.Empty)
|
|
{
|
|
return BadRequest("list_id is required.");
|
|
}
|
|
|
|
var subscriptions = await _newsletterService.ListSubscriptionsAsync(listId);
|
|
return Ok(subscriptions.Select(s => new
|
|
{
|
|
id = s.Id,
|
|
list_id = s.ListId,
|
|
email = s.Email,
|
|
status = s.Status,
|
|
preferences = s.Preferences,
|
|
created_at = s.CreatedAt
|
|
}));
|
|
}
|
|
|
|
private static bool HasScope(System.Security.Claims.ClaimsPrincipal user, string scope)
|
|
{
|
|
var values = user.FindAll(OpenIddictConstants.Claims.Scope)
|
|
.SelectMany(c => c.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries));
|
|
return values.Contains(scope, StringComparer.Ordinal);
|
|
}
|
|
}
|