From f9aecaf7bdd9f5cd63f20c6bf096a92bac6326bd Mon Sep 17 00:00:00 2001
From: LUCCA DUKIC <109136188+LuccaBitfly@users.noreply.github.com>
Date: Thu, 19 Sep 2024 10:58:52 +0200
Subject: [PATCH 1/5] (BEDS-452) move clients in notification settings
---
backend/pkg/api/types/notifications.go | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
diff --git a/backend/pkg/api/types/notifications.go b/backend/pkg/api/types/notifications.go
index 27bf585be..5d80efc89 100644
--- a/backend/pkg/api/types/notifications.go
+++ b/backend/pkg/api/types/notifications.go
@@ -162,6 +162,12 @@ type NotificationPairedDevice struct {
}
type InternalPutUserNotificationSettingsPairedDevicesResponse ApiDataResponse[NotificationPairedDevice]
+type NotificationSettingsClients struct {
+ Id uint64 `json:"id"`
+ Name string `json:"name"`
+ Category string `json:"category"`
+ IsSubscribed bool `json:"is_subscribed"`
+}
type NotificationSettingsGeneral struct {
DoNotDisturbTimestamp int64 `json:"do_not_disturb_timestamp"` // notifications are disabled until this timestamp
IsEmailNotificationsEnabled bool `json:"is_email_notifications_enabled"`
@@ -175,18 +181,18 @@ type NotificationSettingsGeneral struct {
IsMachineMemoryUsageSubscribed bool `json:"is_machine_memory_usage_subscribed"`
MachineMemoryUsageThreshold float64 `json:"machine_memory_usage_threshold" faker:"boundary_start=0, boundary_end=1"`
- SubscribedClients []string `json:"subscribed_clients"`
- IsRocketPoolNewRewardRoundSubscribed bool `json:"is_rocket_pool_new_reward_round_subscribed"`
- IsRocketPoolMaxCollateralSubscribed bool `json:"is_rocket_pool_max_collateral_subscribed"`
- RocketPoolMaxCollateralThreshold float64 `json:"rocket_pool_max_collateral_threshold" faker:"boundary_start=0, boundary_end=1"`
- IsRocketPoolMinCollateralSubscribed bool `json:"is_rocket_pool_min_collateral_subscribed"`
- RocketPoolMinCollateralThreshold float64 `json:"rocket_pool_min_collateral_threshold" faker:"boundary_start=0, boundary_end=1"`
+ IsRocketPoolNewRewardRoundSubscribed bool `json:"is_rocket_pool_new_reward_round_subscribed"`
+ IsRocketPoolMaxCollateralSubscribed bool `json:"is_rocket_pool_max_collateral_subscribed"`
+ RocketPoolMaxCollateralThreshold float64 `json:"rocket_pool_max_collateral_threshold" faker:"boundary_start=0, boundary_end=1"`
+ IsRocketPoolMinCollateralSubscribed bool `json:"is_rocket_pool_min_collateral_subscribed"`
+ RocketPoolMinCollateralThreshold float64 `json:"rocket_pool_min_collateral_threshold" faker:"boundary_start=0, boundary_end=1"`
}
type InternalPutUserNotificationSettingsGeneralResponse ApiDataResponse[NotificationSettingsGeneral]
type NotificationSettings struct {
- GeneralSettings NotificationSettingsGeneral `json:"general_settings"`
- Networks []NotificationNetwork `json:"networks"`
- PairedDevices []NotificationPairedDevice `json:"paired_devices"`
+ GeneralSettings NotificationSettingsGeneral `json:"general_settings"`
+ Networks []NotificationNetwork `json:"networks"`
+ PairedDevices []NotificationPairedDevice `json:"paired_devices"`
+ Clients []NotificationSettingsClients `json:"clients"`
}
type InternalGetUserNotificationSettingsResponse ApiDataResponse[NotificationSettings]
From d0a011c6dc740ce3673464078e94cfc3afedb0dc Mon Sep 17 00:00:00 2001
From: LUCCA DUKIC <109136188+LuccaBitfly@users.noreply.github.com>
Date: Thu, 19 Sep 2024 12:29:45 +0200
Subject: [PATCH 2/5] (BEDS-452) add new client notification settings endpoint
---
backend/pkg/api/data_access/dummy.go | 5 +
backend/pkg/api/data_access/notifications.go | 4 +
backend/pkg/api/handlers/internal.go | 4 +
backend/pkg/api/handlers/public.go | 122 +++++++++++++------
backend/pkg/api/router.go | 1 +
backend/pkg/api/types/notifications.go | 13 +-
6 files changed, 104 insertions(+), 45 deletions(-)
diff --git a/backend/pkg/api/data_access/dummy.go b/backend/pkg/api/data_access/dummy.go
index 7bee9a38c..38fb693ab 100644
--- a/backend/pkg/api/data_access/dummy.go
+++ b/backend/pkg/api/data_access/dummy.go
@@ -488,6 +488,11 @@ func (d *DummyService) UpdateNotificationSettingsPairedDevice(ctx context.Contex
func (d *DummyService) DeleteNotificationSettingsPairedDevice(ctx context.Context, userId uint64, pairedDeviceId string) error {
return nil
}
+
+func (d *DummyService) UpdateNotificationSettingsClients(ctx context.Context, userId uint64, clientId uint64, IsSubscribed bool) (*t.NotificationSettingsClient, error) {
+ return getDummyStruct[t.NotificationSettingsClient]()
+}
+
func (d *DummyService) GetNotificationSettingsDashboards(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationSettingsDashboardColumn], search string, limit uint64) ([]t.NotificationSettingsDashboardsTableRow, *t.Paging, error) {
r, p, err := getDummyWithPaging[t.NotificationSettingsDashboardsTableRow]()
for i, n := range r {
diff --git a/backend/pkg/api/data_access/notifications.go b/backend/pkg/api/data_access/notifications.go
index 5389847db..44f7ca4a5 100644
--- a/backend/pkg/api/data_access/notifications.go
+++ b/backend/pkg/api/data_access/notifications.go
@@ -25,6 +25,7 @@ type NotificationsRepository interface {
UpdateNotificationSettingsNetworks(ctx context.Context, userId uint64, chainId uint64, settings t.NotificationSettingsNetwork) error
UpdateNotificationSettingsPairedDevice(ctx context.Context, userId uint64, pairedDeviceId string, name string, IsNotificationsEnabled bool) error
DeleteNotificationSettingsPairedDevice(ctx context.Context, userId uint64, pairedDeviceId string) error
+ UpdateNotificationSettingsClients(ctx context.Context, userId uint64, clientId uint64, IsSubscribed bool) (*t.NotificationSettingsClient, error)
GetNotificationSettingsDashboards(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationSettingsDashboardColumn], search string, limit uint64) ([]t.NotificationSettingsDashboardsTableRow, *t.Paging, error)
UpdateNotificationSettingsValidatorDashboard(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, settings t.NotificationSettingsValidatorDashboard) error
UpdateNotificationSettingsAccountDashboard(ctx context.Context, dashboardId t.VDBIdPrimary, groupId uint64, settings t.NotificationSettingsAccountDashboard) error
@@ -72,6 +73,9 @@ func (d *DataAccessService) UpdateNotificationSettingsPairedDevice(ctx context.C
func (d *DataAccessService) DeleteNotificationSettingsPairedDevice(ctx context.Context, userId uint64, pairedDeviceId string) error {
return d.dummy.DeleteNotificationSettingsPairedDevice(ctx, userId, pairedDeviceId)
}
+func (d *DataAccessService) UpdateNotificationSettingsClients(ctx context.Context, userId uint64, clientId uint64, IsSubscribed bool) (*t.NotificationSettingsClient, error) {
+ return d.dummy.UpdateNotificationSettingsClients(ctx, userId, clientId, IsSubscribed)
+}
func (d *DataAccessService) GetNotificationSettingsDashboards(ctx context.Context, userId uint64, cursor string, colSort t.Sort[enums.NotificationSettingsDashboardColumn], search string, limit uint64) ([]t.NotificationSettingsDashboardsTableRow, *t.Paging, error) {
return d.dummy.GetNotificationSettingsDashboards(ctx, userId, cursor, colSort, search, limit)
}
diff --git a/backend/pkg/api/handlers/internal.go b/backend/pkg/api/handlers/internal.go
index 78d998856..bf3e347fe 100644
--- a/backend/pkg/api/handlers/internal.go
+++ b/backend/pkg/api/handlers/internal.go
@@ -609,6 +609,10 @@ func (h *HandlerService) InternalDeleteUserNotificationSettingsPairedDevices(w h
h.PublicDeleteUserNotificationSettingsPairedDevices(w, r)
}
+func (h *HandlerService) InternalPutUserNotificationSettingsClient(w http.ResponseWriter, r *http.Request) {
+ h.PublicPutUserNotificationSettingsClient(w, r)
+}
+
func (h *HandlerService) InternalGetUserNotificationSettingsDashboards(w http.ResponseWriter, r *http.Request) {
h.PublicGetUserNotificationSettingsDashboards(w, r)
}
diff --git a/backend/pkg/api/handlers/public.go b/backend/pkg/api/handlers/public.go
index e0e560b8c..d160582df 100644
--- a/backend/pkg/api/handlers/public.go
+++ b/backend/pkg/api/handlers/public.go
@@ -271,7 +271,7 @@ func (h *HandlerService) PublicGetValidatorDashboard(w http.ResponseWriter, r *h
// @Security ApiKeyInHeader || ApiKeyInQuery
// @Tags Validator Dashboard Management
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
+// @Param dashboard_id path integer true "The ID of the dashboard."
// @Success 204 "Dashboard deleted successfully."
// @Failure 400 {object} types.ApiErrorResponse "Bad Request"
// @Router /validator-dashboards/{dashboard_id} [delete]
@@ -297,7 +297,7 @@ func (h *HandlerService) PublicDeleteValidatorDashboard(w http.ResponseWriter, r
// @Tags Validator Dashboard Management
// @Accept json
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
+// @Param dashboard_id path integer true "The ID of the dashboard."
// @Param request body handlers.PublicPutValidatorDashboardName.request true "request"
// @Success 200 {object} types.ApiDataResponse[types.VDBPostReturnData]
// @Failure 400 {object} types.ApiErrorResponse
@@ -336,7 +336,7 @@ func (h *HandlerService) PublicPutValidatorDashboardName(w http.ResponseWriter,
// @Tags Validator Dashboard Management
// @Accept json
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
+// @Param dashboard_id path integer true "The ID of the dashboard."
// @Param request body handlers.PublicPostValidatorDashboardGroups.request true "request"
// @Success 201 {object} types.ApiDataResponse[types.VDBPostCreateGroupData]
// @Failure 400 {object} types.ApiErrorResponse
@@ -400,8 +400,8 @@ func (h *HandlerService) PublicPostValidatorDashboardGroups(w http.ResponseWrite
// @Tags Validator Dashboard Management
// @Accept json
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id path string true "The ID of the group."
+// @Param dashboard_id path integer true "The ID of the dashboard."
+// @Param group_id path integer true "The ID of the group."
// @Param request body handlers.PublicPutValidatorDashboardGroups.request true "request"
// @Success 200 {object} types.ApiDataResponse[types.VDBPostCreateGroupData]
// @Failure 400 {object} types.ApiErrorResponse
@@ -453,8 +453,8 @@ func (h *HandlerService) PublicPutValidatorDashboardGroups(w http.ResponseWriter
// @Security ApiKeyInHeader || ApiKeyInQuery
// @Accept json
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id path string true "The ID of the group."
+// @Param dashboard_id path integer true "The ID of the dashboard."
+// @Param group_id path integer true "The ID of the group."
// @Success 204 "Group deleted successfully."
// @Failure 400 {object} types.ApiErrorResponse
// @Router /validator-dashboards/{dashboard_id}/groups/{group_id} [delete]
@@ -496,7 +496,7 @@ func (h *HandlerService) PublicDeleteValidatorDashboardGroup(w http.ResponseWrit
// @Tags Validator Dashboard Management
// @Accept json
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
+// @Param dashboard_id path integer true "The ID of the dashboard."
// @Param request body handlers.PublicPostValidatorDashboardValidators.request true "`group_id`: (optional) Provide a single group id, to which all validators get added to. If omitted, the default group will be used.
To add validators, only one of the following fields can be set:
- `validators`: Provide a list of validator indices or public keys to add to the dashboard.
- `deposit_address`: (limited to subscription tiers with 'Bulk adding') Provide a deposit address from which as many validators as possible will be added to the dashboard.
- `withdrawal_address`: (limited to subscription tiers with 'Bulk adding') Provide a withdrawal address from which as many validators as possible will be added to the dashboard.
- `graffiti`: (limited to subscription tiers with 'Bulk adding') Provide a graffiti string from which as many validators as possible will be added to the dashboard.
"
// @Success 201 {object} types.ApiDataResponse[[]types.VDBPostValidatorsData] "Returns a list of added validators."
// @Failure 400 {object} types.ApiErrorResponse
@@ -631,7 +631,7 @@ func (h *HandlerService) PublicPostValidatorDashboardValidators(w http.ResponseW
// @Tags Validator Dashboard
// @Produce json
// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id query string false "The ID of the group."
+// @Param group_id query integer false "The ID of the group."
// @Param limit query string false "The maximum number of results that may be returned."
// @Param sort query string false "The field you want to sort by. Append with `:desc` for descending order." Enums(index, public_key, balance, status, withdrawal_credentials)
// @Param search query string false "Search for Address, ENS."
@@ -672,7 +672,7 @@ func (h *HandlerService) PublicGetValidatorDashboardValidators(w http.ResponseWr
// @Tags Validator Dashboard Management
// @Accept json
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
+// @Param dashboard_id path integer true "The ID of the dashboard."
// @Param request body handlers.PublicDeleteValidatorDashboardValidators.request true "`validators`: Provide an array of validator indices or public keys that should get removed from the dashboard."
// @Success 204 "Validators removed successfully."
// @Failure 400 {object} types.ApiErrorResponse
@@ -714,7 +714,7 @@ func (h *HandlerService) PublicDeleteValidatorDashboardValidators(w http.Respons
// @Tags Validator Dashboard Management
// @Accept json
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
+// @Param dashboard_id path integer true "The ID of the dashboard."
// @Param request body handlers.PublicPostValidatorDashboardPublicIds.request true "`name`: Provide a public name for the dashboard
`share_settings`:- `share_groups`: If set to `true`, accessing the dashboard through the public ID will not reveal any group information.
"
// @Success 201 {object} types.ApiDataResponse[types.VDBPublicId]
// @Failure 400 {object} types.ApiErrorResponse
@@ -768,7 +768,7 @@ func (h *HandlerService) PublicPostValidatorDashboardPublicIds(w http.ResponseWr
// @Tags Validator Dashboard Management
// @Accept json
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
+// @Param dashboard_id path integer true "The ID of the dashboard."
// @Param public_id path string true "The ID of the public ID."
// @Param request body handlers.PublicPutValidatorDashboardPublicId.request true "`name`: Provide a public name for the dashboard
`share_settings`:- `share_groups`: If set to `true`, accessing the dashboard through the public ID will not reveal any group information.
"
// @Success 200 {object} types.ApiDataResponse[types.VDBPublicId]
@@ -823,7 +823,7 @@ func (h *HandlerService) PublicPutValidatorDashboardPublicId(w http.ResponseWrit
// @Security ApiKeyInHeader || ApiKeyInQuery
// @Tags Validator Dashboard Management
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
+// @Param dashboard_id path integer true "The ID of the dashboard."
// @Param public_id path string true "The ID of the public ID."
// @Success 204 "Public ID deleted successfully."
// @Failure 400 {object} types.ApiErrorResponse
@@ -863,8 +863,8 @@ func (h *HandlerService) PublicDeleteValidatorDashboardPublicId(w http.ResponseW
// @Tags Validator Dashboard Management
// @Accept json
// @Produce json
-// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param request body handlers.PublicPutValidatorDashboardArchiving.request true "request"
+// @Param dashboard_id path integer true "The ID of the dashboard."
+// @Param request body handlers.PublicPutValidatorDashboardArchiving.request true "`is_archived`: Set to `true` to archive the dashboard, or `false` to unarchive it."
// @Success 200 {object} types.ApiDataResponse[types.VDBPostArchivingReturnData]
// @Failure 400 {object} types.ApiErrorResponse
// @Failure 409 {object} types.ApiErrorResponse "Conflict. The request could not be performed by the server because the authenticated user has already reached their subscription limit."
@@ -1043,7 +1043,7 @@ func (h *HandlerService) PublicGetValidatorDashboardSummary(w http.ResponseWrite
// @Tags Validator Dashboard
// @Produce json
// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id path string true "The ID of the group."
+// @Param group_id path integer true "The ID of the group."
// @Param period query string true "Time period to get data for." Enums(all_time, last_30d, last_7d, last_24h, last_1h)
// @Param modes query string false "Provide a comma separated list of protocol modes which should be respected for validator calculations. Possible values are `rocket_pool``."
// @Success 200 {object} types.GetValidatorDashboardGroupSummaryResponse
@@ -1142,7 +1142,7 @@ func (h *HandlerService) PublicGetValidatorDashboardSummaryChart(w http.Response
// @Tags Validator Dashboard
// @Produce json
// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id query string false "The ID of the group."
+// @Param group_id query integer false "The ID of the group."
// @Param duty query string false "Validator duty to get data for." Enums(none, sync, slashed, proposal) Default(none)
// @Param period query string true "Time period to get data for." Enums(all_time, last_30d, last_7d, last_24h, last_1h)
// @Success 200 {object} types.GetValidatorDashboardSummaryValidatorsResponse
@@ -1246,8 +1246,8 @@ func (h *HandlerService) PublicGetValidatorDashboardRewards(w http.ResponseWrite
// @Tags Validator Dashboard
// @Produce json
// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id path string true "The ID of the group."
-// @Param epoch path string true "The epoch to get data for."
+// @Param group_id path integer true "The ID of the group."
+// @Param epoch path integer true "The epoch to get data for."
// @Param modes query string false "Provide a comma separated list of protocol modes which should be respected for validator calculations. Possible values are `rocket_pool``."
// @Success 200 {object} types.GetValidatorDashboardGroupRewardsResponse
// @Failure 400 {object} types.ApiErrorResponse
@@ -1322,8 +1322,8 @@ func (h *HandlerService) PublicGetValidatorDashboardRewardsChart(w http.Response
// @Tags Validator Dashboard
// @Produce json
// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param epoch path string true "The epoch to get data for."
-// @Param group_id query string false "The ID of the group."
+// @Param epoch path integer true "The epoch to get data for."
+// @Param group_id query integer false "The ID of the group."
// @Param cursor query string false "Return data for the given cursor value. Pass the `paging.next_cursor`` value of the previous response to navigate to forward, or pass the `paging.prev_cursor`` value of the previous response to navigate to backward."
// @Param limit query string false "The maximum number of results that may be returned."
// @Param sort query string false "The field you want to sort by. Append with `:desc` for descending order." Enums(validator, reward)
@@ -1460,8 +1460,8 @@ func (h *HandlerService) PublicGetValidatorDashboardHeatmap(w http.ResponseWrite
// @Tags Validator Dashboard
// @Produce json
// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id path string true "The ID of the group."
-// @Param timestamp path string true "The timestamp to get data for."
+// @Param group_id path integer true "The ID of the group."
+// @Param timestamp path integer true "The timestamp to get data for."
// @Param modes query string false "Provide a comma separated list of protocol modes which should be respected for validator calculations. Possible values are `rocket_pool``."
// @Param aggregation query string false "Aggregation type to get data for." Enums(epoch, hourly, daily, weekly) Default(hourly)
// @Success 200 {object} types.GetValidatorDashboardGroupHeatmapResponse
@@ -1903,7 +1903,7 @@ func (h *HandlerService) PublicGetUserNotifications(w http.ResponseWriter, r *ht
// @Produce json
// @Param network query string false "If set, results will be filtered to only include networks given. Provide a comma separated list."
// @Param cursor query string false "Return data for the given cursor value. Pass the `paging.next_cursor`` value of the previous response to navigate to forward, or pass the `paging.prev_cursor`` value of the previous response to navigate to backward."
-// @Param limit query string false "The maximum number of results that may be returned."
+// @Param limit query integer false "The maximum number of results that may be returned."
// @Param sort query string false "The field you want to sort by. Append with `:desc` for descending order." " Enums(chain_id, timestamp, dashboard_id)
// @Param search query string false "Search for Dashboard, Group"
// @Success 200 {object} types.InternalGetUserNotificationDashboardsResponse
@@ -1931,7 +1931,7 @@ func (h *HandlerService) PublicGetUserNotificationDashboards(w http.ResponseWrit
}
response := types.InternalGetUserNotificationDashboardsResponse{
Data: data,
- Paging: *paging,
+ Paging: *paging, // @Param epoch path strings
}
returnOk(w, r, response)
}
@@ -1943,8 +1943,8 @@ func (h *HandlerService) PublicGetUserNotificationDashboards(w http.ResponseWrit
// @Tags Notifications
// @Produce json
// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id path string true "The ID of the group."
-// @Param epoch path string true "The epoch of the notification."
+// @Param group_id path integer true "The ID of the group."
+// @Param epoch path integer true "The epoch of the notification."
// @Success 200 {object} types.InternalGetUserNotificationsValidatorDashboardResponse
// @Failure 400 {object} types.ApiErrorResponse
// @Router /users/me/notifications/validator-dashboards/{dashboard_id}/groups/{group_id}/epochs/{epoch} [get]
@@ -1976,8 +1976,8 @@ func (h *HandlerService) PublicGetUserNotificationsValidatorDashboard(w http.Res
// @Tags Notifications
// @Produce json
// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id path string true "The ID of the group."
-// @Param epoch path string true "The epoch of the notification."
+// @Param group_id path integer true "The ID of the group."
+// @Param epoch path integer true "The epoch of the notification."
// @Success 200 {object} types.InternalGetUserNotificationsAccountDashboardResponse
// @Failure 400 {object} types.ApiErrorResponse
// @Router /users/me/notifications/account-dashboards/{dashboard_id}/groups/{group_id}/epochs/{epoch} [get]
@@ -2009,7 +2009,7 @@ func (h *HandlerService) PublicGetUserNotificationsAccountDashboard(w http.Respo
// @Tags Notifications
// @Produce json
// @Param cursor query string false "Return data for the given cursor value. Pass the `paging.next_cursor`` value of the previous response to navigate to forward, or pass the `paging.prev_cursor`` value of the previous response to navigate to backward."
-// @Param limit query string false "The maximum number of results that may be returned."
+// @Param limit query integer false "The maximum number of results that may be returned."
// @Param sort query string false "The field you want to sort by. Append with `:desc` for descending order." Enums(machine_name, threshold, event_type, timestamp)
// @Param search query string false "Search for Machine"
// @Success 200 {object} types.InternalGetUserNotificationMachinesResponse
@@ -2048,7 +2048,7 @@ func (h *HandlerService) PublicGetUserNotificationMachines(w http.ResponseWriter
// @Tags Notifications
// @Produce json
// @Param cursor query string false "Return data for the given cursor value. Pass the `paging.next_cursor`` value of the previous response to navigate to forward, or pass the `paging.prev_cursor`` value of the previous response to navigate to backward."
-// @Param limit query string false "The maximum number of results that may be returned."
+// @Param limit query integer false "The maximum number of results that may be returned."
// @Param sort query string false "The field you want to sort by. Append with `:desc` for descending order." Enums(client_name, timestamp)
// @Param search query string false "Search for Client"
// @Success 200 {object} types.InternalGetUserNotificationClientsResponse
@@ -2087,7 +2087,7 @@ func (h *HandlerService) PublicGetUserNotificationClients(w http.ResponseWriter,
// @Tags Notifications
// @Produce json
// @Param cursor query string false "Return data for the given cursor value. Pass the `paging.next_cursor`` value of the previous response to navigate to forward, or pass the `paging.prev_cursor`` value of the previous response to navigate to backward."
-// @Param limit query string false "The maximum number of results that may be returned."
+// @Param limit query integer false "The maximum number of results that may be returned."
// @Param sort query string false "The field you want to sort by. Append with `:desc` for descending order." Enums(timestamp, event_type, node_address)
// @Param search query string false "Search for TODO"
// @Success 200 {object} types.InternalGetUserNotificationRocketPoolResponse
@@ -2126,7 +2126,7 @@ func (h *HandlerService) PublicGetUserNotificationRocketPool(w http.ResponseWrit
// @Tags Notifications
// @Produce json
// @Param cursor query string false "Return data for the given cursor value. Pass the `paging.next_cursor`` value of the previous response to navigate to forward, or pass the `paging.prev_cursor`` value of the previous response to navigate to backward."
-// @Param limit query string false "The maximum number of results that may be returned."
+// @Param limit query integer false "The maximum number of results that may be returned."
// @Param sort query string false "The field you want to sort by. Append with `:desc` for descending order." Enums(timestamp, event_type)
// @Param search query string false "Search for TODO"
// @Success 200 {object} types.InternalGetUserNotificationNetworksResponse
@@ -2190,7 +2190,7 @@ func (h *HandlerService) PublicGetUserNotificationSettings(w http.ResponseWriter
// @Tags Notification Settings
// @Accept json
// @Produce json
-// @Param request body types.NotificationSettingsGeneral true "Notification settings"
+// @Param request body types.NotificationSettingsGeneral true "Description TODO"
// @Success 200 {object} types.InternalPutUserNotificationSettingsGeneralResponse
// @Failure 400 {object} types.ApiErrorResponse
// @Router /users/me/notifications/settings/general [put]
@@ -2211,7 +2211,6 @@ func (h *HandlerService) PublicPutUserNotificationSettingsGeneral(w http.Respons
checkMinMax(&v, req.MachineMemoryUsageThreshold, 0, 1, "machine_memory_usage_threshold")
checkMinMax(&v, req.RocketPoolMaxCollateralThreshold, 0, 1, "rocket_pool_max_collateral_threshold")
checkMinMax(&v, req.RocketPoolMinCollateralThreshold, 0, 1, "rocket_pool_min_collateral_threshold")
- // TODO: check validity of clients
if v.hasErrors() {
handleErr(w, r, v)
return
@@ -2235,7 +2234,7 @@ func (h *HandlerService) PublicPutUserNotificationSettingsGeneral(w http.Respons
// @Accept json
// @Produce json
// @Param network path string true "The networks name or chain ID."
-// @Param request body types.NotificationSettingsNetwork true "Notification settings"
+// @Param request body types.NotificationSettingsNetwork true "Description Todo"
// @Success 200 {object} types.InternalPutUserNotificationSettingsNetworksResponse
// @Failure 400 {object} types.ApiErrorResponse
// @Router /users/me/notifications/settings/networks/{network} [put]
@@ -2280,7 +2279,7 @@ func (h *HandlerService) PublicPutUserNotificationSettingsNetworks(w http.Respon
// @Accept json
// @Produce json
// @Param paired_device_id path string true "The paired device ID."
-// @Param request body handlers.PublicPutUserNotificationSettingsPairedDevices.request true "Notification settings"
+// @Param request body handlers.PublicPutUserNotificationSettingsPairedDevices.request true "Description TODO"
// @Success 200 {object} types.InternalPutUserNotificationSettingsPairedDevicesResponse
// @Failure 400 {object} types.ApiErrorResponse
// @Router /users/me/notifications/settings/paired-devices/{paired_device_id} [put]
@@ -2355,6 +2354,49 @@ func (h *HandlerService) PublicDeleteUserNotificationSettingsPairedDevices(w htt
returnNoContent(w, r)
}
+// PublicPutUserNotificationSettingsClient godoc
+//
+// @Description Update client notification settings for the authenticated user. When a client is subscribed, notifications will be sent when a new version is available.
+// @Security ApiKeyInHeader || ApiKeyInQuery
+// @Tags Notification Settings
+// @Accept json
+// @Produce json
+// @Param client_id path integer true "The ID of the client."
+// @Param request body handlers.PublicPutUserNotificationSettingsClient.request true "`is_subscribed`: Set to `true` to subscribe to notifications; set to `false` to unsubscribe."
+// @Success 200 {object} types.InternalPutUserNotificationSettingsClientResponse
+// @Failure 400 {object} types.ApiErrorResponse
+// @Router /users/me/notifications/settings/clients/{client_id} [put]
+func (h *HandlerService) PublicPutUserNotificationSettingsClient(w http.ResponseWriter, r *http.Request) {
+ var v validationError
+ userId, err := GetUserIdByContext(r)
+ if err != nil {
+ handleErr(w, r, err)
+ return
+ }
+ type request struct {
+ IsSubscribed bool `json:"is_subscribed"`
+ }
+ var req request
+ if err := v.checkBody(&req, r); err != nil {
+ handleErr(w, r, err)
+ return
+ }
+ clientId := v.checkUint(mux.Vars(r)["client_id"], "client_id")
+ if v.hasErrors() {
+ handleErr(w, r, v)
+ return
+ }
+ data, err := h.dai.UpdateNotificationSettingsClients(r.Context(), userId, clientId, req.IsSubscribed)
+ if err != nil {
+ handleErr(w, r, err)
+ return
+ }
+ response := types.InternalPutUserNotificationSettingsClientResponse{
+ Data: *data,
+ }
+ returnOk(w, r, response)
+}
+
// PublicGetUserNotificationSettingsDashboards godoc
//
// @Description Get a list of notification settings for the dashboards of the authenticated user.
@@ -2362,7 +2404,7 @@ func (h *HandlerService) PublicDeleteUserNotificationSettingsPairedDevices(w htt
// @Tags Notification Settings
// @Produce json
// @Param cursor query string false "Return data for the given cursor value. Pass the `paging.next_cursor`` value of the previous response to navigate to forward, or pass the `paging.prev_cursor`` value of the previous response to navigate to backward."
-// @Param limit query string false "The maximum number of results that may be returned."
+// @Param limit query integer false "The maximum number of results that may be returned."
// @Param sort query string false "The field you want to sort by. Append with `:desc` for descending order." Enums (dashboard_id, group_name)
// @Param search query string false "Search for Dashboard, Group"
// @Success 200 {object} types.InternalGetUserNotificationSettingsDashboardsResponse
@@ -2402,7 +2444,7 @@ func (h *HandlerService) PublicGetUserNotificationSettingsDashboards(w http.Resp
// @Accept json
// @Produce json
// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id path string true "The ID of the group."
+// @Param group_id path integer true "The ID of the group."
// @Param request body types.NotificationSettingsValidatorDashboard true "Notification settings"
// @Success 200 {object} types.InternalPutUserNotificationSettingsValidatorDashboardResponse
// @Failure 400 {object} types.ApiErrorResponse
@@ -2441,7 +2483,7 @@ func (h *HandlerService) PublicPutUserNotificationSettingsValidatorDashboard(w h
// @Accept json
// @Produce json
// @Param dashboard_id path string true "The ID of the dashboard."
-// @Param group_id path string true "The ID of the group."
+// @Param group_id path integer true "The ID of the group."
// @Param request body handlers.PublicPutUserNotificationSettingsAccountDashboard.request true "Notification settings"
// @Success 200 {object} types.InternalPutUserNotificationSettingsAccountDashboardResponse
// @Failure 400 {object} types.ApiErrorResponse
diff --git a/backend/pkg/api/router.go b/backend/pkg/api/router.go
index 16ab4c0b2..864cb69d8 100644
--- a/backend/pkg/api/router.go
+++ b/backend/pkg/api/router.go
@@ -329,6 +329,7 @@ func addNotificationRoutes(hs *handlers.HandlerService, publicRouter, internalRo
{http.MethodPut, "/settings/networks/{network}", hs.PublicPutUserNotificationSettingsNetworks, hs.InternalPutUserNotificationSettingsNetworks},
{http.MethodPut, "/settings/paired-devices/{paired_device_id}", hs.PublicPutUserNotificationSettingsPairedDevices, hs.InternalPutUserNotificationSettingsPairedDevices},
{http.MethodDelete, "/settings/paired-devices/{paired_device_id}", hs.PublicDeleteUserNotificationSettingsPairedDevices, hs.InternalDeleteUserNotificationSettingsPairedDevices},
+ {http.MethodPut, "/settings/clients/{client_id}", hs.PublicPutUserNotificationSettingsClient, hs.InternalPutUserNotificationSettingsClient},
{http.MethodGet, "/settings/dashboards", hs.PublicGetUserNotificationSettingsDashboards, hs.InternalGetUserNotificationSettingsDashboards},
{http.MethodPost, "/test-email", hs.PublicPostUserNotificationsTestEmail, hs.InternalPostUserNotificationsTestEmail},
{http.MethodPost, "/test-push", hs.PublicPostUserNotificationsTestPush, hs.InternalPostUserNotificationsTestPush},
diff --git a/backend/pkg/api/types/notifications.go b/backend/pkg/api/types/notifications.go
index 5d80efc89..4d512ff5a 100644
--- a/backend/pkg/api/types/notifications.go
+++ b/backend/pkg/api/types/notifications.go
@@ -162,12 +162,15 @@ type NotificationPairedDevice struct {
}
type InternalPutUserNotificationSettingsPairedDevicesResponse ApiDataResponse[NotificationPairedDevice]
-type NotificationSettingsClients struct {
+type NotificationSettingsClient struct {
Id uint64 `json:"id"`
Name string `json:"name"`
Category string `json:"category"`
IsSubscribed bool `json:"is_subscribed"`
}
+
+type InternalPutUserNotificationSettingsClientResponse ApiDataResponse[NotificationSettingsClient]
+
type NotificationSettingsGeneral struct {
DoNotDisturbTimestamp int64 `json:"do_not_disturb_timestamp"` // notifications are disabled until this timestamp
IsEmailNotificationsEnabled bool `json:"is_email_notifications_enabled"`
@@ -189,10 +192,10 @@ type NotificationSettingsGeneral struct {
}
type InternalPutUserNotificationSettingsGeneralResponse ApiDataResponse[NotificationSettingsGeneral]
type NotificationSettings struct {
- GeneralSettings NotificationSettingsGeneral `json:"general_settings"`
- Networks []NotificationNetwork `json:"networks"`
- PairedDevices []NotificationPairedDevice `json:"paired_devices"`
- Clients []NotificationSettingsClients `json:"clients"`
+ GeneralSettings NotificationSettingsGeneral `json:"general_settings"`
+ Networks []NotificationNetwork `json:"networks"`
+ PairedDevices []NotificationPairedDevice `json:"paired_devices"`
+ Clients []NotificationSettingsClient `json:"clients"`
}
type InternalGetUserNotificationSettingsResponse ApiDataResponse[NotificationSettings]
From 1b7d591b99887e569067d4080006ffb59ed28022 Mon Sep 17 00:00:00 2001
From: LUCCA DUKIC <109136188+LuccaBitfly@users.noreply.github.com>
Date: Thu, 19 Sep 2024 12:30:19 +0200
Subject: [PATCH 3/5] (BEDS-452) typescript conversion
---
frontend/types/api/notifications.ts | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/frontend/types/api/notifications.ts b/frontend/types/api/notifications.ts
index 0d9f53898..57a2900d4 100644
--- a/frontend/types/api/notifications.ts
+++ b/frontend/types/api/notifications.ts
@@ -156,6 +156,13 @@ export interface NotificationPairedDevice {
is_notifications_enabled: boolean;
}
export type InternalPutUserNotificationSettingsPairedDevicesResponse = ApiDataResponse;
+export interface NotificationSettingsClient {
+ id: number /* uint64 */;
+ name: string;
+ category: string;
+ is_subscribed: boolean;
+}
+export type InternalPutUserNotificationSettingsClientResponse = ApiDataResponse;
export interface NotificationSettingsGeneral {
do_not_disturb_timestamp: number /* int64 */; // notifications are disabled until this timestamp
is_email_notifications_enabled: boolean;
@@ -167,7 +174,6 @@ export interface NotificationSettingsGeneral {
machine_cpu_usage_threshold: number /* float64 */;
is_machine_memory_usage_subscribed: boolean;
machine_memory_usage_threshold: number /* float64 */;
- subscribed_clients: string[];
is_rocket_pool_new_reward_round_subscribed: boolean;
is_rocket_pool_max_collateral_subscribed: boolean;
rocket_pool_max_collateral_threshold: number /* float64 */;
@@ -179,6 +185,7 @@ export interface NotificationSettings {
general_settings: NotificationSettingsGeneral;
networks: NotificationNetwork[];
paired_devices: NotificationPairedDevice[];
+ clients: NotificationSettingsClient[];
}
export type InternalGetUserNotificationSettingsResponse = ApiDataResponse;
export interface NotificationSettingsValidatorDashboard {
From f29cd091cd21b671a4ba63d7b94b83e10e5322ad Mon Sep 17 00:00:00 2001
From: LUCCA DUKIC <109136188+LuccaBitfly@users.noreply.github.com>
Date: Thu, 19 Sep 2024 12:48:14 +0200
Subject: [PATCH 4/5] (BEDS-452) defeat frontend typecheck
---
frontend/utils/mock.ts | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/frontend/utils/mock.ts b/frontend/utils/mock.ts
index f942d8fbb..0f5e8bc6e 100644
--- a/frontend/utils/mock.ts
+++ b/frontend/utils/mock.ts
@@ -443,6 +443,32 @@ export function simulateAPIresponseAboutNetworkList(): ApiDataResponse<
export function mockManageNotificationsGeneral(): InternalGetUserNotificationSettingsResponse {
return {
data: {
+ clients: [
+ {
+ category: 'EL',
+ id: 1,
+ is_subscribed: true,
+ name: 'EL Client 1',
+ },
+ {
+ category: 'CL',
+ id: 2,
+ is_subscribed: false,
+ name: 'CL Client 1',
+ },
+ {
+ category: 'other',
+ id: 3,
+ is_subscribed: true,
+ name: 'Other Clien 1',
+ },
+ {
+ category: 'other',
+ id: 4,
+ is_subscribed: false,
+ name: 'Other Clien 2',
+ },
+ ],
general_settings: {
do_not_disturb_timestamp: 9000,
is_email_notifications_enabled: false,
@@ -459,7 +485,6 @@ export function mockManageNotificationsGeneral(): InternalGetUserNotificationSet
machine_storage_usage_threshold: 80,
rocket_pool_max_collateral_threshold: 29823,
rocket_pool_min_collateral_threshold: 123,
- subscribed_clients: [],
},
networks: [],
paired_devices: [
From 434ccfc33e98c2e1075fe7d08d4a9c27cc943e61 Mon Sep 17 00:00:00 2001
From: marcel-bitfly <174338434+marcel-bitfly@users.noreply.github.com>
Date: Fri, 27 Sep 2024 11:09:32 +0200
Subject: [PATCH 5/5] refactor: resolve `type errors`
---
.../useNotificationsManagementStore.ts | 2 +-
frontend/utils/mock.ts | 65 -------------------
2 files changed, 1 insertion(+), 66 deletions(-)
diff --git a/frontend/stores/notifications/useNotificationsManagementStore.ts b/frontend/stores/notifications/useNotificationsManagementStore.ts
index ad08472d8..2b7c060b7 100644
--- a/frontend/stores/notifications/useNotificationsManagementStore.ts
+++ b/frontend/stores/notifications/useNotificationsManagementStore.ts
@@ -10,6 +10,7 @@ export const useNotificationsManagementStore = defineStore('notifications-manage
const { fetch } = useCustomFetch()
const settings = ref(
{
+ clients: [],
general_settings: {
do_not_disturb_timestamp: 0,
is_email_notifications_enabled: false,
@@ -26,7 +27,6 @@ export const useNotificationsManagementStore = defineStore('notifications-manage
machine_storage_usage_threshold: 0.0,
rocket_pool_max_collateral_threshold: 0,
rocket_pool_min_collateral_threshold: 0,
- subscribed_clients: [],
},
networks: [ {
chain_id: 0,
diff --git a/frontend/utils/mock.ts b/frontend/utils/mock.ts
index bc1f3d08a..23a2b3184 100644
--- a/frontend/utils/mock.ts
+++ b/frontend/utils/mock.ts
@@ -438,68 +438,3 @@ export function simulateAPIresponseAboutNetworkList(): ApiDataResponse<
}
return result
}
-
-export function mockManageNotificationsGeneral(): InternalGetUserNotificationSettingsResponse {
- return {
- data: {
- clients: [
- {
- category: 'EL',
- id: 1,
- is_subscribed: true,
- name: 'EL Client 1',
- },
- {
- category: 'CL',
- id: 2,
- is_subscribed: false,
- name: 'CL Client 1',
- },
- {
- category: 'other',
- id: 3,
- is_subscribed: true,
- name: 'Other Clien 1',
- },
- {
- category: 'other',
- id: 4,
- is_subscribed: false,
- name: 'Other Clien 2',
- },
- ],
- general_settings: {
- do_not_disturb_timestamp: 9000,
- is_email_notifications_enabled: false,
- is_machine_cpu_usage_subscribed: true,
- is_machine_memory_usage_subscribed: true,
- is_machine_offline_subscribed: true,
- is_machine_storage_usage_subscribed: true,
- is_push_notifications_enabled: true,
- is_rocket_pool_max_collateral_subscribed: true,
- is_rocket_pool_min_collateral_subscribed: true,
- is_rocket_pool_new_reward_round_subscribed: true,
- machine_cpu_usage_threshold: 40,
- machine_memory_usage_threshold: 50,
- machine_storage_usage_threshold: 80,
- rocket_pool_max_collateral_threshold: 29823,
- rocket_pool_min_collateral_threshold: 123,
- },
- networks: [],
- paired_devices: [
- {
- id: 'ABC-test',
- is_notifications_enabled: true,
- name: 'My device',
- paired_timestamp: 1620000000,
- },
- {
- id: 'DEF-test',
- is_notifications_enabled: false,
- name: 'My other device',
- paired_timestamp: 1700000000,
- },
- ],
- },
- }
-}