Skip to content

Commit 4d92f09

Browse files
committed
Allow batch updating notifications
1 parent 4f0fd67 commit 4d92f09

9 files changed

Lines changed: 93 additions & 22 deletions

File tree

src/Share/Notifications/API.hs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module Share.Notifications.API
1111
WebhookRoutes (..),
1212
GetHubEntriesResponse (..),
1313
StatusFilter (..),
14-
UpdateHubEntryRequest (..),
14+
UpdateHubEntriesRequest (..),
1515
GetSubscriptionsResponse (..),
1616
CreateSubscriptionRequest (..),
1717
CreateSubscriptionResponse (..),
@@ -53,7 +53,7 @@ data Routes mode
5353
data HubEntriesRoutes mode
5454
= HubEntriesRoutes
5555
{ getHubEntriesEndpoint :: mode :- GetHubEntriesEndpoint,
56-
updateHubEntryEndpoint :: mode :- UpdateHubEntryEndpoint
56+
updateHubEntriesEndpoint :: mode :- UpdateHubEntriesEndpoint
5757
}
5858
deriving stock (Generic)
5959

@@ -200,21 +200,22 @@ instance ToJSON GetHubEntriesResponse where
200200
toJSON GetHubEntriesResponse {notifications} =
201201
object ["notifications" .= notifications]
202202

203-
type UpdateHubEntryEndpoint =
203+
type UpdateHubEntriesEndpoint =
204204
AuthenticatedUserId
205-
:> Capture "hubEntryId" NotificationHubEntryId
206-
:> ReqBody '[JSON] UpdateHubEntryRequest
205+
:> ReqBody '[JSON] UpdateHubEntriesRequest
207206
:> Patch '[JSON] NoContent
208207

209-
data UpdateHubEntryRequest
210-
= UpdateHubEntryRequest
211-
{ notificationStatus :: NotificationStatus
208+
data UpdateHubEntriesRequest
209+
= UpdateHubEntriesRequest
210+
{ notificationStatus :: NotificationStatus,
211+
notificationIds :: NESet NotificationHubEntryId
212212
}
213213

214-
instance FromJSON UpdateHubEntryRequest where
215-
parseJSON = withObject "UpdateHubEntryRequest" $ \o -> do
214+
instance FromJSON UpdateHubEntriesRequest where
215+
parseJSON = withObject "UpdateHubEntriesRequest" $ \o -> do
216216
notificationStatus <- o .: "status"
217-
pure UpdateHubEntryRequest {notificationStatus}
217+
notificationIds <- o .: "notificationIds"
218+
pure UpdateHubEntriesRequest {notificationStatus, notificationIds}
218219

219220
type CreateEmailDeliveryMethodEndpoint =
220221
AuthenticatedUserId

src/Share/Notifications/Impl.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ hubRoutes :: UserHandle -> API.HubEntriesRoutes (AsServerT WebApp)
1717
hubRoutes userHandle =
1818
API.HubEntriesRoutes
1919
{ getHubEntriesEndpoint = getHubEntriesEndpoint userHandle,
20-
updateHubEntryEndpoint = updateHubEntryEndpoint userHandle
20+
updateHubEntriesEndpoint = updateHubEntriesEndpoint userHandle
2121
}
2222

2323
deliveryMethodRoutes :: UserHandle -> API.DeliveryMethodRoutes (AsServerT WebApp)
@@ -68,11 +68,11 @@ getHubEntriesEndpoint userHandle callerUserId limit afterTime mayStatusFilter =
6868
notifications <- PG.runTransaction $ NotificationQ.listNotificationHubEntries notificationUserId limit afterTime (API.getStatusFilter <$> mayStatusFilter)
6969
pure $ API.GetHubEntriesResponse {notifications}
7070

71-
updateHubEntryEndpoint :: UserHandle -> UserId -> NotificationHubEntryId -> API.UpdateHubEntryRequest -> WebApp NoContent
72-
updateHubEntryEndpoint userHandle callerUserId hubEntryId API.UpdateHubEntryRequest {notificationStatus} = do
71+
updateHubEntriesEndpoint :: UserHandle -> UserId -> API.UpdateHubEntriesRequest -> WebApp NoContent
72+
updateHubEntriesEndpoint userHandle callerUserId API.UpdateHubEntriesRequest {notificationStatus, notificationIds} = do
7373
User {user_id = notificationUserId} <- UserQ.expectUserByHandle userHandle
7474
_authZReceipt <- AuthZ.permissionGuard $ AuthZ.checkNotificationsUpdate callerUserId notificationUserId
75-
PG.runTransaction $ NotificationQ.updateNotificationHubEntry hubEntryId notificationStatus
75+
PG.runTransaction $ NotificationQ.updateNotificationHubEntries notificationIds notificationStatus
7676
pure NoContent
7777

7878
getDeliveryMethodsEndpoint :: UserHandle -> UserId -> WebApp API.GetDeliveryMethodsResponse

src/Share/Notifications/Queries.hs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module Share.Notifications.Queries
22
( recordEvent,
33
listNotificationHubEntries,
4-
updateNotificationHubEntry,
4+
updateNotificationHubEntries,
55
listNotificationDeliveryMethods,
66
listEmailDeliveryMethods,
77
listWebhookDeliveryMethods,
@@ -54,13 +54,16 @@ listNotificationHubEntries notificationUserId mayLimit afterTime statusFilter =
5454
LIMIT #{limit}
5555
|]
5656

57-
updateNotificationHubEntry :: (QueryA m) => NotificationHubEntryId -> NotificationStatus -> m ()
58-
updateNotificationHubEntry hubEntryId status = do
57+
updateNotificationHubEntries :: (QueryA m) => NESet NotificationHubEntryId -> NotificationStatus -> m ()
58+
updateNotificationHubEntries hubEntryIds status = do
5959
execute_
6060
[sql|
61+
WITH to_update(notification_id) AS (
62+
SELECT * FROM ^{singleColumnTable $ Foldable.toList hubEntryIds}
63+
)
6164
UPDATE notification_hub_entries
62-
SET status = #{status}
63-
WHERE id = #{hubEntryId}
65+
SET status = #{status}::notification_status
66+
WHERE id IN (SELECT notification_id FROM to_update)
6467
|]
6568

6669
listNotificationDeliveryMethods :: UserId -> Transaction e [NotificationDeliveryMethod]

transcripts/share-apis/notifications/list-notifications-test.json renamed to transcripts/share-apis/notifications/list-notifications-read-transcripts.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"scope": "U-<UUID>"
1919
},
2020
"id": "NOT-<UUID>",
21-
"status": "unread"
21+
"status": "read"
2222
}
2323
]
2424
},
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"body": {
3+
"notifications": []
4+
},
5+
"status": [
6+
{
7+
"status_code": 200
8+
}
9+
]
10+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"body": null,
3+
"status": [
4+
{
5+
"status_code": 200
6+
}
7+
]
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"body": null,
3+
"status": [
4+
{
5+
"status_code": 200
6+
}
7+
]
8+
}

transcripts/share-apis/notifications/run.zsh

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,28 @@ fetch "$test_user" POST private-contribution-create '/users/test/projects/privat
5151

5252
fetch "$unauthorized_user" GET notifications-get-unauthorized '/users/test/notifications/hub'
5353

54-
fetch "$test_user" GET list-notifications-test '/users/test/notifications/hub'
54+
test_notification_id=$(fetch_data_jq "$test_user" GET list-notifications-test '/users/test/notifications/hub' '.notifications[0].id')
55+
transcripts_notification_id=$(fetch_data_jq "$transcripts_user" GET list-notifications-transcripts '/users/transcripts/notifications/hub' '.notifications[0].id')
5556

5657
fetch "$transcripts_user" GET list-notifications-transcripts '/users/transcripts/notifications/hub'
58+
59+
# Mark notifications as read
60+
fetch "$test_user" PATCH mark-notifications-read-test '/users/test/notifications/hub' "{
61+
\"status\": \"read\",
62+
\"notificationIds\": [
63+
\"$test_notification_id\"
64+
]
65+
}"
66+
67+
fetch "$transcripts_user" PATCH mark-notifications-read-transcripts '/users/transcripts/notifications/hub' "{
68+
\"status\": \"read\",
69+
\"notificationIds\": [
70+
\"$transcripts_notification_id\"
71+
]
72+
}"
73+
74+
# Show only unread notifications (none should be unread):
75+
fetch "$test_user" GET list-notifications-unread-test '/users/test/notifications/hub?status=unread'
76+
77+
# Show only read notifications (the one we just marked as read):
78+
fetch "$transcripts_user" GET list-notifications-read-transcripts '/users/transcripts/notifications/hub?status=read'

transcripts/transcript_helpers.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,25 @@ fetch_data() {
155155
esac
156156
}
157157

158+
fetch_data_jq() {
159+
if [ "$#" -lt 5 ]; then
160+
echo "fetch requires at least 5 arguments: user_id, method, testname, api_path, jq_pattern, [data]" >&2
161+
exit 1
162+
fi
163+
if [ -z "$1" ]; then
164+
echo "fetch requires a user id" >&2
165+
exit 1
166+
fi
167+
cookie_jar="$1"
168+
method="$2"
169+
testname="$3"
170+
api_path="$4"
171+
jq_pattern="$5"
172+
data="$6"
173+
fetch_data "$cookie_jar" "$method" "$testname" "$api_path" "$data" 2> /dev/null | \
174+
jq --sort-keys -r "$jq_pattern"
175+
}
176+
158177
# Credentials setup
159178

160179
login_user_for_ucm() {

0 commit comments

Comments
 (0)