diff options
author | 2025-02-03 02:25:53 -0800 | |
---|---|---|
committer | 2025-02-03 10:25:53 +0000 | |
commit | 27844b7da2567491661f9ddd2d4662f9f1b3ce40 (patch) | |
tree | 1832fe4ec4d3a0fbf6d01bcb5f39acf6885cc1f5 /internal/api | |
parent | [chore]: Bump github.com/tdewolff/minify/v2 from 2.21.2 to 2.21.3 (#3727) (diff) | |
download | gotosocial-27844b7da2567491661f9ddd2d4662f9f1b3ce40.tar.xz |
[feature] Implement Web Push notification policy (#3721)
* Web Push: add policy column to subscriptions
* Web Push: add policy to API
* Web Push: test notification policy
* go-fmt unrelated file (how did this get thru?)
Diffstat (limited to 'internal/api')
-rw-r--r-- | internal/api/client/push/pushsubscriptionpost.go | 11 | ||||
-rw-r--r-- | internal/api/client/push/pushsubscriptionpost_test.go | 22 | ||||
-rw-r--r-- | internal/api/client/push/pushsubscriptionput.go | 22 | ||||
-rw-r--r-- | internal/api/client/push/pushsubscriptionput_test.go | 13 | ||||
-rw-r--r-- | internal/api/model/webpushsubscription.go | 11 |
5 files changed, 76 insertions, 3 deletions
diff --git a/internal/api/client/push/pushsubscriptionpost.go b/internal/api/client/push/pushsubscriptionpost.go index a7e299894..cc1be185f 100644 --- a/internal/api/client/push/pushsubscriptionpost.go +++ b/internal/api/client/push/pushsubscriptionpost.go @@ -147,6 +147,17 @@ import ( // type: boolean // default: false // description: Receive a push notification when a boost is pending? +// - +// name: data[policy] +// in: formData +// type: string +// enum: +// - all +// - followed +// - follower +// - none +// default: all +// description: Which accounts to receive push notifications from. // // security: // - OAuth2 Bearer: diff --git a/internal/api/client/push/pushsubscriptionpost_test.go b/internal/api/client/push/pushsubscriptionpost_test.go index bdd22d729..e7e8582df 100644 --- a/internal/api/client/push/pushsubscriptionpost_test.go +++ b/internal/api/client/push/pushsubscriptionpost_test.go @@ -44,6 +44,7 @@ func (suite *PushTestSuite) postSubscription( p256dh *string, alertsMention *bool, alertsStatus *bool, + policy *string, requestJson *string, expectedHTTPStatus int, ) (*apimodel.WebPushSubscription, error) { @@ -80,6 +81,9 @@ func (suite *PushTestSuite) postSubscription( if alertsStatus != nil { ctx.Request.Form["data[alerts][status]"] = []string{strconv.FormatBool(*alertsStatus)} } + if policy != nil { + ctx.Request.Form["data[policy]"] = []string{*policy} + } } // trigger the handler @@ -119,6 +123,7 @@ func (suite *PushTestSuite) TestPostSubscription() { p256dh := "BMYVItYVOX+AHBdtA62Q0i6c+F7MV2Gia3aoDr8mvHkuPBNIOuTLDfmFcnBqoZcQk6BtLcIONbxhHpy2R+mYIUY=" alertsMention := true alertsStatus := false + policy := "followed" subscription, err := suite.postSubscription( accountFixtureName, tokenFixtureName, @@ -127,6 +132,7 @@ func (suite *PushTestSuite) TestPostSubscription() { &p256dh, &alertsMention, &alertsStatus, + &policy, nil, 200, ) @@ -138,6 +144,7 @@ func (suite *PushTestSuite) TestPostSubscription() { suite.False(subscription.Alerts.Status) // Omitted event types should default to off. suite.False(subscription.Alerts.Favourite) + suite.Equal(apimodel.WebPushNotificationPolicyFollowed, subscription.Policy) } } @@ -159,6 +166,7 @@ func (suite *PushTestSuite) TestPostSubscriptionMinimal() { nil, nil, nil, + nil, 200, ) if suite.NoError(err) { @@ -169,6 +177,8 @@ func (suite *PushTestSuite) TestPostSubscriptionMinimal() { suite.False(subscription.Alerts.Mention) suite.False(subscription.Alerts.Status) suite.False(subscription.Alerts.Favourite) + // Policy should default to all. + suite.Equal(apimodel.WebPushNotificationPolicyAll, subscription.Policy) } } @@ -192,6 +202,7 @@ func (suite *PushTestSuite) TestPostInvalidSubscription() { &alertsMention, &alertsStatus, nil, + nil, 422, ) suite.NoError(err) @@ -215,7 +226,8 @@ func (suite *PushTestSuite) TestPostSubscriptionJSON() { "alerts": { "mention": true, "status": false - } + }, + "policy": "followed" } }` subscription, err := suite.postSubscription( @@ -226,6 +238,7 @@ func (suite *PushTestSuite) TestPostSubscriptionJSON() { nil, nil, nil, + nil, &requestJson, 200, ) @@ -237,6 +250,7 @@ func (suite *PushTestSuite) TestPostSubscriptionJSON() { suite.False(subscription.Alerts.Status) // Omitted event types should default to off. suite.False(subscription.Alerts.Favourite) + suite.Equal(apimodel.WebPushNotificationPolicyFollowed, subscription.Policy) } } @@ -263,6 +277,7 @@ func (suite *PushTestSuite) TestPostSubscriptionJSONMinimal() { nil, nil, nil, + nil, &requestJson, 200, ) @@ -274,6 +289,8 @@ func (suite *PushTestSuite) TestPostSubscriptionJSONMinimal() { suite.False(subscription.Alerts.Mention) suite.False(subscription.Alerts.Status) suite.False(subscription.Alerts.Favourite) + // Policy should default to all. + suite.Equal(apimodel.WebPushNotificationPolicyAll, subscription.Policy) } } @@ -306,6 +323,7 @@ func (suite *PushTestSuite) TestPostInvalidSubscriptionJSON() { nil, nil, nil, + nil, &requestJson, 422, ) @@ -323,6 +341,7 @@ func (suite *PushTestSuite) TestPostExistingSubscription() { p256dh := "BMYVItYVOX+AHBdtA62Q0i6c+F7MV2Gia3aoDr8mvHkuPBNIOuTLDfmFcnBqoZcQk6BtLcIONbxhHpy2R+mYIUY=" alertsMention := true alertsStatus := false + policy := "followed" subscription, err := suite.postSubscription( accountFixtureName, tokenFixtureName, @@ -331,6 +350,7 @@ func (suite *PushTestSuite) TestPostExistingSubscription() { &p256dh, &alertsMention, &alertsStatus, + &policy, nil, 200, ) diff --git a/internal/api/client/push/pushsubscriptionput.go b/internal/api/client/push/pushsubscriptionput.go index 06575f4ee..4d1c5765e 100644 --- a/internal/api/client/push/pushsubscriptionput.go +++ b/internal/api/client/push/pushsubscriptionput.go @@ -25,6 +25,7 @@ import ( apiutil "github.com/superseriousbusiness/gotosocial/internal/api/util" "github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/oauth" + "github.com/superseriousbusiness/gotosocial/internal/util" ) // PushSubscriptionPUTHandler swagger:operation PUT /api/v1/push/subscription pushSubscriptionPut @@ -122,6 +123,17 @@ import ( // type: boolean // default: false // description: Receive a push notification when a boost is pending? +// - +// name: data[policy] +// in: formData +// type: string +// enum: +// - all +// - followed +// - follower +// - none +// default: all +// description: Which accounts to receive push notifications from. // // security: // - OAuth2 Bearer: @@ -181,7 +193,8 @@ func (m *Module) PushSubscriptionPUTHandler(c *gin.Context) { apiutil.JSON(c, http.StatusOK, apiSubscription) } -// validateNormalizeUpdate copies form fields to their canonical JSON equivalents. +// validateNormalizeUpdate copies form fields to their canonical JSON equivalents +// and sets defaults for fields that have them. func validateNormalizeUpdate(request *apimodel.WebPushSubscriptionUpdateRequest) error { if request.Data == nil { request.Data = &apimodel.WebPushSubscriptionRequestData{} @@ -228,5 +241,12 @@ func validateNormalizeUpdate(request *apimodel.WebPushSubscriptionUpdateRequest) request.Data.Alerts.Reblog = *request.DataAlertsPendingReblog } + if request.DataPolicy != nil { + request.Data.Policy = request.DataPolicy + } + if request.Data.Policy == nil { + request.Data.Policy = util.Ptr(apimodel.WebPushNotificationPolicyAll) + } + return nil } diff --git a/internal/api/client/push/pushsubscriptionput_test.go b/internal/api/client/push/pushsubscriptionput_test.go index 924e3d475..d9f0e395e 100644 --- a/internal/api/client/push/pushsubscriptionput_test.go +++ b/internal/api/client/push/pushsubscriptionput_test.go @@ -41,6 +41,7 @@ func (suite *PushTestSuite) putSubscription( tokenFixtureName string, alertsMention *bool, alertsStatus *bool, + policy *string, requestJson *string, expectedHTTPStatus int, ) (*apimodel.WebPushSubscription, error) { @@ -68,6 +69,9 @@ func (suite *PushTestSuite) putSubscription( if alertsStatus != nil { ctx.Request.Form["data[alerts][status]"] = []string{strconv.FormatBool(*alertsStatus)} } + if policy != nil { + ctx.Request.Form["data[policy]"] = []string{*policy} + } } // trigger the handler @@ -104,11 +108,13 @@ func (suite *PushTestSuite) TestPutSubscription() { alertsMention := true alertsStatus := false + policy := "followed" subscription, err := suite.putSubscription( accountFixtureName, tokenFixtureName, &alertsMention, &alertsStatus, + &policy, nil, 200, ) @@ -120,6 +126,7 @@ func (suite *PushTestSuite) TestPutSubscription() { suite.False(subscription.Alerts.Status) // Omitted event types should default to off. suite.False(subscription.Alerts.Favourite) + suite.Equal(apimodel.WebPushNotificationPolicyFollowed, subscription.Policy) } } @@ -134,7 +141,8 @@ func (suite *PushTestSuite) TestPutSubscriptionJSON() { "alerts": { "mention": true, "status": false - } + }, + "policy": "followed" } }` subscription, err := suite.putSubscription( @@ -142,6 +150,7 @@ func (suite *PushTestSuite) TestPutSubscriptionJSON() { tokenFixtureName, nil, nil, + nil, &requestJson, 200, ) @@ -153,6 +162,7 @@ func (suite *PushTestSuite) TestPutSubscriptionJSON() { suite.False(subscription.Alerts.Status) // Omitted event types should default to off. suite.False(subscription.Alerts.Favourite) + suite.Equal(apimodel.WebPushNotificationPolicyFollowed, subscription.Policy) } } @@ -170,6 +180,7 @@ func (suite *PushTestSuite) TestPutMissingSubscription() { &alertsMention, &alertsStatus, nil, + nil, 404, ) suite.NoError(err) diff --git a/internal/api/model/webpushsubscription.go b/internal/api/model/webpushsubscription.go index a28bb7294..38d6cf7ed 100644 --- a/internal/api/model/webpushsubscription.go +++ b/internal/api/model/webpushsubscription.go @@ -138,6 +138,8 @@ type WebPushSubscriptionUpdateRequest struct { DataAlertsPendingFavourite *bool `form:"data[alerts][pending.favourite]" json:"-"` DataAlertsPendingReply *bool `form:"data[alerts][pending.reply]" json:"-"` DataAlertsPendingReblog *bool `form:"data[alerts][pending.reblog]" json:"-"` + + DataPolicy *WebPushNotificationPolicy `form:"data[policy]" json:"-"` } // WebPushSubscriptionRequestData is the part of a Web Push subscription that can be changed after creation. @@ -146,6 +148,9 @@ type WebPushSubscriptionUpdateRequest struct { type WebPushSubscriptionRequestData struct { // Alerts selects the specific events that this Web Push subscription will receive. Alerts *WebPushSubscriptionAlerts `form:"-" json:"alerts"` + + // Policy selects which accounts will trigger Web Push notifications. + Policy *WebPushNotificationPolicy `form:"-" json:"policy"` } // WebPushNotificationPolicy names sets of accounts that can generate notifications. @@ -154,4 +159,10 @@ type WebPushNotificationPolicy string const ( // WebPushNotificationPolicyAll allows all accounts to send notifications to the subscribing user. WebPushNotificationPolicyAll WebPushNotificationPolicy = "all" + // WebPushNotificationPolicyFollowed allows accounts followed by the subscribing user to send notifications. + WebPushNotificationPolicyFollowed WebPushNotificationPolicy = "followed" + // WebPushNotificationPolicyFollower allows accounts following the subscribing user to send notifications. + WebPushNotificationPolicyFollower WebPushNotificationPolicy = "follower" + // WebPushNotificationPolicyNone doesn't allow any acounts to send notifications to the subscribing user. + WebPushNotificationPolicyNone WebPushNotificationPolicy = "none" ) |