Skip to content

Commit f8c5234

Browse files
committed
Add 'actor' to events
1 parent 439b6a4 commit f8c5234

6 files changed

Lines changed: 85 additions & 15 deletions

File tree

src/Share/BackgroundJobs/Webhooks/Worker.hs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import Share.JWT (JWTParam (..))
2525
import Share.JWT qualified as JWT
2626
import Share.Metrics qualified as Metrics
2727
import Share.Notifications.Queries qualified as NQ
28-
import Share.Notifications.Types (HydratedEventPayload, NotificationEvent (..), NotificationTopic, eventData_, hydratedEventTopic)
28+
import Share.Notifications.Types (HydratedEventPayload, NotificationEvent (..), NotificationTopic, eventData_, eventUserInfo_, hydratedEventTopic)
2929
import Share.Notifications.Webhooks.Secrets (WebhookConfig (..), WebhookSecretError)
3030
import Share.Notifications.Webhooks.Secrets qualified as Webhooks
3131
import Share.Postgres qualified as PG
@@ -34,7 +34,8 @@ import Share.Prelude
3434
import Share.Utils.Logging qualified as Logging
3535
import Share.Utils.URI (URIParam (..))
3636
import Share.Web.Authorization qualified as AuthZ
37-
import Share.Web.Share.DisplayInfo.Types (UserDisplayInfo)
37+
import Share.Web.Share.DisplayInfo.Queries qualified as DisplayInfoQ
38+
import Share.Web.Share.DisplayInfo.Types (UnifiedDisplayInfo)
3839
import UnliftIO qualified
3940

4041
data WebhookSendFailure
@@ -163,7 +164,7 @@ instance FromJSON (WebhookEventPayload ()) where
163164
<*> pure ()
164165

165166
tryWebhook ::
166-
NotificationEvent NotificationEventId UserDisplayInfo UTCTime HydratedEventPayload ->
167+
NotificationEvent NotificationEventId UnifiedDisplayInfo UTCTime HydratedEventPayload ->
167168
NotificationWebhookId ->
168169
Background (Maybe WebhookSendFailure)
169170
tryWebhook event webhookId = UnliftIO.handleAny (\someException -> pure $ Just $ InvalidRequest event.eventId webhookId someException) do
@@ -206,14 +207,15 @@ tryWebhook event webhookId = UnliftIO.handleAny (\someException -> pure $ Just $
206207

207208
attemptWebhookSend ::
208209
AuthZ.AuthZReceipt ->
209-
(NotificationEvent NotificationEventId UserDisplayInfo UTCTime HydratedEventPayload -> NotificationWebhookId -> IO (Maybe WebhookSendFailure)) ->
210+
(NotificationEvent NotificationEventId UnifiedDisplayInfo UTCTime HydratedEventPayload -> NotificationWebhookId -> IO (Maybe WebhookSendFailure)) ->
210211
NotificationEventId ->
211212
NotificationWebhookId ->
212213
PG.Transaction e (Maybe WebhookSendFailure)
213214
attemptWebhookSend _authZReceipt tryWebhookIO eventId webhookId = do
214215
event <- NQ.expectEvent eventId
215216
hydratedEvent <- forOf eventData_ event NQ.hydrateEventData
216-
PG.transactionUnsafeIO (tryWebhookIO hydratedEvent webhookId) >>= \case
217+
populatedEvent <- hydratedEvent & DisplayInfoQ.unifiedDisplayInfoForUserOf eventUserInfo_
218+
PG.transactionUnsafeIO (tryWebhookIO populatedEvent webhookId) >>= \case
217219
Just err -> do
218220
WQ.recordFailedDeliveryAttempt eventId webhookId
219221
pure $ Just err

src/Share/Notifications/API.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import Share.Notifications.Types (DeliveryMethodId, HydratedEventPayload, Notifi
4343
import Share.OAuth.Session (AuthenticatedUserId)
4444
import Share.Prelude
4545
import Share.Utils.URI (URIParam)
46-
import Share.Web.Share.DisplayInfo.Types (UserDisplayInfo)
46+
import Share.Web.Share.DisplayInfo.Types (UnifiedDisplayInfo)
4747

4848
type API = NamedRoutes Routes
4949

@@ -213,7 +213,7 @@ type GetHubEntriesEndpoint =
213213
:> Get '[JSON] GetHubEntriesResponse
214214

215215
data GetHubEntriesResponse = GetHubEntriesResponse
216-
{ notifications :: [NotificationHubEntry UserDisplayInfo HydratedEventPayload]
216+
{ notifications :: [NotificationHubEntry UnifiedDisplayInfo HydratedEventPayload]
217217
}
218218

219219
instance ToJSON GetHubEntriesResponse where

src/Share/Notifications/Queries.hs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,15 @@ import Share.Postgres qualified as PG
3434
import Share.Postgres.Contributions.Queries qualified as ContributionQ
3535
import Share.Postgres.Users.Queries qualified as UsersQ
3636
import Share.Prelude
37-
import Share.Web.Share.DisplayInfo.Types (UserDisplayInfo)
37+
import Share.Web.Share.DisplayInfo.Queries qualified as DisplayInfoQ
38+
import Share.Web.Share.DisplayInfo.Types (UnifiedDisplayInfo)
3839

3940
recordEvent :: (QueryA m) => NewNotificationEvent -> m ()
4041
recordEvent (NotificationEvent {eventScope, eventData, eventResourceId, eventActor}) = do
4142
execute_
4243
[sql|
4344
INSERT INTO notification_events (topic, scope_user_id, actor_user_id, resource_id, data)
44-
VALUES (#{eventTopic eventData}::notification_topic, #{eventScope}, #{eventActor} #{eventResourceId}, #{eventData})
45+
VALUES (#{eventTopic eventData}::notification_topic, #{eventScope}, #{eventActor}, #{eventResourceId}, #{eventData})
4546
|]
4647

4748
expectEvent :: (QueryM m) => NotificationEventId -> m PGNotificationEvent
@@ -53,14 +54,14 @@ expectEvent eventId = do
5354
WHERE id = #{eventId}
5455
|]
5556

56-
listNotificationHubEntries :: UserId -> Maybe Int -> Maybe UTCTime -> Maybe (NESet NotificationStatus) -> Transaction e [NotificationHubEntry UserDisplayInfo HydratedEventPayload]
57+
listNotificationHubEntries :: UserId -> Maybe Int -> Maybe UTCTime -> Maybe (NESet NotificationStatus) -> Transaction e [NotificationHubEntry UnifiedDisplayInfo HydratedEventPayload]
5758
listNotificationHubEntries notificationUserId mayLimit afterTime statusFilter = do
5859
let limit = clamp (0, 1000) . fromIntegral @Int @Int32 . fromMaybe 50 $ mayLimit
5960
let statusFilterList = Foldable.toList <$> statusFilter
6061
dbNotifications <-
6162
queryListRows @(NotificationHubEntry UserId NotificationEventData)
6263
[sql|
63-
SELECT hub.id, hub.status, event.id, event.occurred_at, event.scope_user_id, event.resource_id, event.topic, event.data
64+
SELECT hub.id, hub.status, event.id, event.occurred_at, event.scope_user_id, event.actor_user_id, event.resource_id, event.topic, event.data
6465
FROM notification_hub_entries hub
6566
JOIN notification_events event ON hub.event_id = event.id
6667
WHERE hub.user_id = #{notificationUserId}
@@ -69,7 +70,8 @@ listNotificationHubEntries notificationUserId mayLimit afterTime statusFilter =
6970
ORDER BY hub.created_at DESC
7071
LIMIT #{limit}
7172
|]
72-
PG.pipelined $ forOf (traversed . traversed) dbNotifications hydrateEventData
73+
hydrated <- PG.pipelined $ forOf (traversed . traversed) dbNotifications hydrateEventData
74+
hydrated & DisplayInfoQ.unifiedDisplayInfoForUserOf (traversed . hubEntryUserInfo_)
7375

7476
updateNotificationHubEntries :: (QueryA m) => NESet NotificationHubEntryId -> NotificationStatus -> m ()
7577
updateNotificationHubEntries hubEntryIds status = do

src/Share/Notifications/Types.hs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# LANGUAGE RecordWildCards #-}
2+
13
module Share.Notifications.Types
24
( NotificationTopic (..),
35
NotificationFilter (..),
@@ -23,6 +25,8 @@ module Share.Notifications.Types
2325
eventTopic,
2426
hydratedEventTopic,
2527
eventData_,
28+
eventUserInfo_,
29+
hubEntryUserInfo_,
2630
)
2731
where
2832

@@ -235,6 +239,12 @@ data NotificationEvent id userInfo occurredAt eventPayload = NotificationEvent
235239
eventData_ :: Lens (NotificationEvent id userInfo occurredAt eventPayload) (NotificationEvent id userInfo occurredAt eventPayload') eventPayload eventPayload'
236240
eventData_ f event = (\eventData -> event {eventData}) <$> f (eventData event)
237241

242+
eventUserInfo_ :: Traversal (NotificationEvent id userInfo occurredAt eventPayload) (NotificationEvent id userInfo' occurredAt eventPayload) userInfo userInfo'
243+
eventUserInfo_ f NotificationEvent {eventActor, eventScope, ..} = do
244+
eventActor' <- f eventActor
245+
eventScope' <- f eventScope
246+
pure $ NotificationEvent {eventActor = eventActor', eventScope = eventScope', ..}
247+
238248
instance (Aeson.ToJSON eventPayload, Aeson.ToJSON userInfo) => Aeson.ToJSON (NotificationEvent NotificationEventId userInfo UTCTime eventPayload) where
239249
toJSON NotificationEvent {eventId, eventOccurredAt, eventData, eventScope, eventActor} =
240250
Aeson.object
@@ -366,6 +376,11 @@ instance Hasql.DecodeRow (NotificationHubEntry UserId NotificationEventData) whe
366376
hubEntryEvent <- PG.decodeRow
367377
pure $ NotificationHubEntry {hubEntryId, hubEntryEvent, hubEntryStatus}
368378

379+
hubEntryUserInfo_ :: Traversal (NotificationHubEntry userInfo eventPayload) (NotificationHubEntry userInfo' eventPayload) userInfo userInfo'
380+
hubEntryUserInfo_ f (NotificationHubEntry {hubEntryEvent, ..}) = do
381+
hubEntryEvent' <- hubEntryEvent & eventUserInfo_ %%~ f
382+
pure $ NotificationHubEntry {hubEntryEvent = hubEntryEvent', ..}
383+
369384
newtype SubscriptionFilter = SubscriptionFilter (Aeson.Value)
370385
deriving (Hasql.EncodeValue, Hasql.DecodeValue) via Hasql.Jsonb
371386
deriving newtype (Eq, Show, Aeson.ToJSON, Aeson.FromJSON)

transcripts/share-apis/notifications/list-notifications-read-transcripts.json

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@
33
"notifications": [
44
{
55
"event": {
6+
"actor": {
7+
"info": {
8+
"avatarUrl": null,
9+
"handle": "test",
10+
"name": null,
11+
"userId": "U-<UUID>"
12+
},
13+
"kind": "user"
14+
},
615
"data": {
716
"kind": "projectBranchUpdated",
817
"payload": {
@@ -24,7 +33,15 @@
2433
},
2534
"id": "EVENT-<UUID>",
2635
"occurredAt": "<TIMESTAMP>",
27-
"scope": "U-<UUID>"
36+
"scope": {
37+
"info": {
38+
"avatarUrl": null,
39+
"handle": "test",
40+
"name": null,
41+
"userId": "U-<UUID>"
42+
},
43+
"kind": "user"
44+
}
2845
},
2946
"id": "NOT-<UUID>",
3047
"status": "read"

transcripts/share-apis/notifications/list-notifications-transcripts.json

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@
33
"notifications": [
44
{
55
"event": {
6+
"actor": {
7+
"info": {
8+
"avatarUrl": null,
9+
"handle": "test",
10+
"name": null,
11+
"userId": "U-<UUID>"
12+
},
13+
"kind": "user"
14+
},
615
"data": {
716
"kind": "projectBranchUpdated",
817
"payload": {
@@ -24,13 +33,30 @@
2433
},
2534
"id": "EVENT-<UUID>",
2635
"occurredAt": "<TIMESTAMP>",
27-
"scope": "U-<UUID>"
36+
"scope": {
37+
"info": {
38+
"avatarUrl": null,
39+
"handle": "test",
40+
"name": null,
41+
"userId": "U-<UUID>"
42+
},
43+
"kind": "user"
44+
}
2845
},
2946
"id": "NOT-<UUID>",
3047
"status": "unread"
3148
},
3249
{
3350
"event": {
51+
"actor": {
52+
"info": {
53+
"avatarUrl": null,
54+
"handle": "test",
55+
"name": null,
56+
"userId": "U-<UUID>"
57+
},
58+
"kind": "user"
59+
},
3460
"data": {
3561
"kind": "projectContributionCreated",
3662
"payload": {
@@ -69,7 +95,15 @@
6995
},
7096
"id": "EVENT-<UUID>",
7197
"occurredAt": "<TIMESTAMP>",
72-
"scope": "U-<UUID>"
98+
"scope": {
99+
"info": {
100+
"avatarUrl": null,
101+
"handle": "test",
102+
"name": null,
103+
"userId": "U-<UUID>"
104+
},
105+
"kind": "user"
106+
}
73107
},
74108
"id": "NOT-<UUID>",
75109
"status": "unread"

0 commit comments

Comments
 (0)