mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2025-01-18 13:26:47 +01:00
Greenfield: Manage notifications (#6058)
Prerequisite for btcpayserver/app#12.
This commit is contained in:
parent
e0c5ac5271
commit
feffbbd980
@ -33,6 +33,16 @@ public partial class BTCPayServerClient
|
||||
return await SendHttpRequest<NotificationData>($"api/v1/users/me/notifications/{notificationId}", new UpdateNotification { Seen = seen }, HttpMethod.Put, token);
|
||||
}
|
||||
|
||||
public virtual async Task<NotificationSettingsData> GetNotificationSettings(CancellationToken token = default)
|
||||
{
|
||||
return await SendHttpRequest<NotificationSettingsData>("api/v1/users/me/notification-settings", null, HttpMethod.Get, token);
|
||||
}
|
||||
|
||||
public virtual async Task<NotificationSettingsData> UpdateNotificationSettings(UpdateNotificationSettingsRequest request, CancellationToken token = default)
|
||||
{
|
||||
return await SendHttpRequest<NotificationSettingsData>("api/v1/users/me/notification-settings", request, HttpMethod.Put, token);
|
||||
}
|
||||
|
||||
public virtual async Task RemoveNotification(string notificationId, CancellationToken token = default)
|
||||
{
|
||||
await SendHttpRequest($"api/v1/users/me/notifications/{notificationId}", null, HttpMethod.Delete, token);
|
||||
|
15
BTCPayServer.Client/Models/NotificationSettingsData.cs
Normal file
15
BTCPayServer.Client/Models/NotificationSettingsData.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class NotificationSettingsData
|
||||
{
|
||||
public List<NotificationSettingsItemData> Notifications { get; set; }
|
||||
}
|
||||
|
||||
public class NotificationSettingsItemData
|
||||
{
|
||||
public string Identifier { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class UpdateNotificationSettingsRequest
|
||||
{
|
||||
public List<string> Disabled { get; set; }
|
||||
}
|
@ -2851,6 +2851,30 @@ namespace BTCPayServer.Tests
|
||||
await client.RemoveNotification(notification.Id);
|
||||
Assert.Empty(await viewOnlyClient.GetNotifications(true));
|
||||
Assert.Empty(await viewOnlyClient.GetNotifications(false));
|
||||
|
||||
// Settings
|
||||
var settings = await client.GetNotificationSettings();
|
||||
Assert.True(settings.Notifications.Find(n => n.Identifier == "newversion").Enabled);
|
||||
Assert.True(settings.Notifications.Find(n => n.Identifier == "pluginupdate").Enabled);
|
||||
Assert.True(settings.Notifications.Find(n => n.Identifier == "inviteaccepted").Enabled);
|
||||
|
||||
var request = new UpdateNotificationSettingsRequest { Disabled = ["newversion", "pluginupdate"] };
|
||||
settings = await client.UpdateNotificationSettings(request);
|
||||
Assert.False(settings.Notifications.Find(n => n.Identifier == "newversion").Enabled);
|
||||
Assert.False(settings.Notifications.Find(n => n.Identifier == "pluginupdate").Enabled);
|
||||
Assert.True(settings.Notifications.Find(n => n.Identifier == "inviteaccepted").Enabled);
|
||||
|
||||
request = new UpdateNotificationSettingsRequest { Disabled = ["all"] };
|
||||
settings = await client.UpdateNotificationSettings(request);
|
||||
Assert.False(settings.Notifications.Find(n => n.Identifier == "newversion").Enabled);
|
||||
Assert.False(settings.Notifications.Find(n => n.Identifier == "pluginupdate").Enabled);
|
||||
Assert.False(settings.Notifications.Find(n => n.Identifier == "inviteaccepted").Enabled);
|
||||
|
||||
request = new UpdateNotificationSettingsRequest { Disabled = [] };
|
||||
settings = await client.UpdateNotificationSettings(request);
|
||||
Assert.True(settings.Notifications.Find(n => n.Identifier == "newversion").Enabled);
|
||||
Assert.True(settings.Notifications.Find(n => n.Identifier == "pluginupdate").Enabled);
|
||||
Assert.True(settings.Notifications.Find(n => n.Identifier == "inviteaccepted").Enabled);
|
||||
}
|
||||
|
||||
[Fact(Timeout = TestTimeout)]
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using BTCPayServer.Abstractions.Constants;
|
||||
@ -23,12 +24,16 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly NotificationManager _notificationManager;
|
||||
private readonly IEnumerable<INotificationHandler> _notificationHandlers;
|
||||
|
||||
public GreenfieldNotificationsController(UserManager<ApplicationUser> userManager,
|
||||
NotificationManager notificationManager)
|
||||
public GreenfieldNotificationsController(
|
||||
UserManager<ApplicationUser> userManager,
|
||||
NotificationManager notificationManager,
|
||||
IEnumerable<INotificationHandler> notificationHandlers)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_notificationManager = notificationManager;
|
||||
_notificationHandlers = notificationHandlers;
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanViewNotificationsForUser,
|
||||
@ -95,6 +100,37 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanManageNotificationsForUser, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
[HttpGet("~/api/v1/users/me/notification-settings")]
|
||||
public async Task<IActionResult> GetNotificationSettings()
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
var model = GetNotificationSettingsData(user);
|
||||
return Ok(model);
|
||||
}
|
||||
|
||||
[Authorize(Policy = Policies.CanManageNotificationsForUser, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
|
||||
[HttpPut("~/api/v1/users/me/notification-settings")]
|
||||
public async Task<IActionResult> UpdateNotificationSettings(UpdateNotificationSettingsRequest request)
|
||||
{
|
||||
var user = await _userManager.GetUserAsync(User);
|
||||
if (request.Disabled.Contains("all"))
|
||||
{
|
||||
user.DisabledNotifications = "all";
|
||||
}
|
||||
else
|
||||
{
|
||||
var disabled = _notificationHandlers
|
||||
.SelectMany(handler => handler.Meta.Select(tuple => tuple.identifier))
|
||||
.Where(id => request.Disabled.Contains(id)).ToList();
|
||||
user.DisabledNotifications = disabled.Any() ? string.Join(';', disabled) + ";" : string.Empty;
|
||||
}
|
||||
await _userManager.UpdateAsync(user);
|
||||
|
||||
var model = GetNotificationSettingsData(user);
|
||||
return Ok(model);
|
||||
}
|
||||
|
||||
private NotificationData ToModel(NotificationViewModel entity)
|
||||
{
|
||||
@ -113,5 +149,19 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
{
|
||||
return this.CreateAPIError(404, "notification-not-found", "The notification was not found");
|
||||
}
|
||||
|
||||
private NotificationSettingsData GetNotificationSettingsData(ApplicationUser user)
|
||||
{
|
||||
var disabledAll = user.DisabledNotifications == "all";
|
||||
var disabledNotifications = user.DisabledNotifications?.Split(';', StringSplitOptions.RemoveEmptyEntries).ToList() ?? [];
|
||||
var notifications = _notificationHandlers.SelectMany(handler => handler.Meta.Select(tuple =>
|
||||
new NotificationSettingsItemData
|
||||
{
|
||||
Identifier = tuple.identifier,
|
||||
Name = tuple.name,
|
||||
Enabled = !disabledAll && !disabledNotifications.Contains(tuple.identifier, StringComparer.InvariantCultureIgnoreCase)
|
||||
})).ToList();
|
||||
return new NotificationSettingsData { Notifications = notifications };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using NBitcoin;
|
||||
using NBXplorer.DerivationStrategy;
|
||||
using NBXplorer.Models;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using InvoiceData = BTCPayServer.Client.Models.InvoiceData;
|
||||
@ -644,6 +643,18 @@ namespace BTCPayServer.Controllers.Greenfield
|
||||
HandleActionResult(await GetController<GreenfieldApiKeysController>().RevokeAPIKey(apikey));
|
||||
}
|
||||
|
||||
public override async Task<NotificationSettingsData> GetNotificationSettings(CancellationToken token = default)
|
||||
{
|
||||
return GetFromActionResult<NotificationSettingsData>(
|
||||
await GetController<GreenfieldNotificationsController>().GetNotificationSettings());
|
||||
}
|
||||
|
||||
public override async Task<NotificationSettingsData> UpdateNotificationSettings(UpdateNotificationSettingsRequest request, CancellationToken token = default)
|
||||
{
|
||||
return GetFromActionResult<NotificationSettingsData>(
|
||||
await GetController<GreenfieldNotificationsController>().UpdateNotificationSettings(request));
|
||||
}
|
||||
|
||||
public override async Task<IEnumerable<NotificationData>> GetNotifications(bool? seen = null,
|
||||
int? skip = null, int? take = null, CancellationToken token = default)
|
||||
{
|
||||
|
@ -203,6 +203,80 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"/api/v1/users/me/notification-settings": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Notifications (Current User)"
|
||||
],
|
||||
"summary": "Get notification settings",
|
||||
"description": "View information about your notification settings",
|
||||
"operationId": "Notifications_GetNotificationSettings",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The current user's notification settings",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/NotificationSettingsData"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "If you are authenticated but forbidden to view the notification settings"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"API_Key": [
|
||||
"btcpay.user.canmanagenotificationsforuser"
|
||||
],
|
||||
"Basic": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"put": {
|
||||
"tags": [
|
||||
"Notifications (Current User)"
|
||||
],
|
||||
"summary": "Update notification settings",
|
||||
"description": "Updates the current user's notification settings",
|
||||
"operationId": "Notifications_UpdateNotification",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "The current user's notification settings",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/NotificationSettingsData"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"403": {
|
||||
"description": "If you are authenticated but forbidden to update the notification settings"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"API_Key": [
|
||||
"btcpay.user.canmanagenotificationsforuser"
|
||||
],
|
||||
"Basic": []
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UpdateNotificationSettingsRequest"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
@ -254,6 +328,117 @@
|
||||
"description": "If the notification has been seen by the user"
|
||||
}
|
||||
}
|
||||
},
|
||||
"UpdateNotificationSettingsRequest": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"disabled": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "List of the notification type identifiers, which should be disabled. Can also be a single item 'all'.",
|
||||
"example": ["newversion", "pluginupdate"],
|
||||
"nullable": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"NotificationSettingsData": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"notifications": {
|
||||
"type": "array",
|
||||
"description": "The notification types",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/NotificationSettingsItemData"
|
||||
}
|
||||
}
|
||||
},
|
||||
"example": [
|
||||
{
|
||||
"identifier": "newversion",
|
||||
"name": "New version",
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"identifier": "newuserrequiresapproval",
|
||||
"name": "New user requires approval",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"identifier": "inviteaccepted",
|
||||
"name": "User accepted invitation",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"identifier": "pluginupdate",
|
||||
"name": "Plugin update",
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"identifier": "invoicestate",
|
||||
"name": "All invoice updates",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"identifier": "invoicestate_invoice_paidAfterExpiration",
|
||||
"name": "Invoice was paid after expiration",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"identifier": "invoicestate_invoice_expiredPaidPartial",
|
||||
"name": "Invoice expired with partial payments",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"identifier": "invoicestate_invoice_failedToConfirm",
|
||||
"name": "Invoice has payments that failed to confirm on time",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"identifier": "invoicestate_invoice_confirmed",
|
||||
"name": "Invoice is settled",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"identifier": "payout",
|
||||
"name": "Payouts",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"identifier": "external-payout-transaction",
|
||||
"name": "External payout approval",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"NotificationSettingsItemData": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"identifier": {
|
||||
"type": "string",
|
||||
"description": "The identifier of the notification type",
|
||||
"nullable": false
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"description": "The description of the notification type",
|
||||
"nullable": false
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "If the notification type is enabled",
|
||||
"nullable": false
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"identifier": "newversion",
|
||||
"name": "New version",
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user