Skip to content

Commit 1ef99b5

Browse files
committed
notification working with prod web sockets (beta)
1 parent c0847e7 commit 1ef99b5

File tree

1 file changed

+39
-21
lines changed

1 file changed

+39
-21
lines changed

packages/mgt-chat/src/statefulClient/GraphNotificationClient.ts

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,13 @@
88
import { BetaGraph, IGraph, Providers, error, log } from '@microsoft/mgt-element';
99
import * as signalR from '@microsoft/signalr';
1010
import { ThreadEventEmitter } from './ThreadEventEmitter';
11-
import type { Subscription, ChatMessage, Chat, AadUserConversationMember } from '@microsoft/microsoft-graph-types';
12-
import {} from '@microsoft/microsoft-graph-types-beta';
11+
import type {
12+
Entity,
13+
Subscription,
14+
ChatMessage,
15+
Chat,
16+
AadUserConversationMember
17+
} from '@microsoft/microsoft-graph-types';
1318
import { GraphConfig } from './GraphConfig';
1419
import { SubscriptionsCache } from './Caching/SubscriptionCache';
1520

@@ -21,18 +26,25 @@ export const appSettings = {
2126

2227
type ChangeTypes = 'created' | 'updated' | 'deleted';
2328

24-
type Notification = {
29+
type Notification<T extends Entity> = {
2530
subscriptionId: string;
2631
changeType: ChangeTypes;
2732
resource: string;
28-
resourceData: {
33+
resourceData: T & {
2934
id: string;
3035
'@odata.type': string;
3136
'@odata.id': string;
3237
};
33-
encryptedContent: string;
38+
EncryptedContent: string;
3439
};
3540

41+
type ReceivedNotification = Notification<Chat> | Notification<ChatMessage> | Notification<AadUserConversationMember>;
42+
43+
const isMessageNotification = (o: Notification<Entity>): o is Notification<ChatMessage> =>
44+
o.resource.includes('/messages(');
45+
const isMembershipNotification = (o: Notification<Entity>): o is Notification<AadUserConversationMember> =>
46+
o.resource.includes('/members');
47+
3648
const stripWssScheme = (notificationUrl: string): string => notificationUrl.replace('wss:', '');
3749

3850
export class GraphNotificationClient {
@@ -70,22 +82,27 @@ export class GraphNotificationClient {
7082
return (await Promise.resolve(encryptedData)) as T;
7183
}
7284

73-
private readonly receiveNotificationMessage = async (notification: Notification) => {
85+
private readonly receiveNotificationMessage = (message: string) => {
86+
if (typeof message !== 'string') throw new Error('Expected string from receivenotificationmessageasync');
87+
88+
const notification: ReceivedNotification = JSON.parse(message) as ReceivedNotification;
7489
log('received notification message', notification);
7590
const emitter: ThreadEventEmitter | undefined = this.emitter;
76-
if (!notification.encryptedContent) throw new Error('Message did not contain encrypted content');
77-
if (notification.resource.indexOf('/messages') !== -1) {
78-
await this.processMessageNotification(notification, emitter);
79-
} else if (notification.resource.indexOf('/members') !== -1) {
80-
await this.processMembershipNotification(notification, emitter);
91+
if (!notification.resourceData) throw new Error('Message did not contain resourceData');
92+
if (isMessageNotification(notification)) {
93+
this.processMessageNotification(notification, emitter);
94+
} else if (isMembershipNotification(notification)) {
95+
this.processMembershipNotification(notification, emitter);
8196
} else {
82-
await this.processChatPropertiesNotification(notification, emitter);
97+
this.processChatPropertiesNotification(notification, emitter);
8398
}
99+
return { StatusCode: '200' };
100+
84101
return new signalR.HttpResponse(200);
85102
};
86103

87-
private async processMessageNotification(notification: Notification, emitter: ThreadEventEmitter | undefined) {
88-
const message = await this.decryptMessage<ChatMessage>(notification.encryptedContent);
104+
private processMessageNotification(notification: Notification<ChatMessage>, emitter: ThreadEventEmitter | undefined) {
105+
const message = notification.resourceData;
89106

90107
switch (notification.changeType) {
91108
case 'created':
@@ -102,8 +119,11 @@ export class GraphNotificationClient {
102119
}
103120
}
104121

105-
private async processMembershipNotification(notification: Notification, emitter: ThreadEventEmitter | undefined) {
106-
const member = await this.decryptMessage<AadUserConversationMember>(notification.encryptedContent);
122+
private processMembershipNotification(
123+
notification: Notification<AadUserConversationMember>,
124+
emitter: ThreadEventEmitter | undefined
125+
) {
126+
const member = notification.resourceData;
107127
switch (notification.changeType) {
108128
case 'created':
109129
emitter?.participantAdded(member);
@@ -116,8 +136,8 @@ export class GraphNotificationClient {
116136
}
117137
}
118138

119-
private async processChatPropertiesNotification(notification: Notification, emitter: ThreadEventEmitter | undefined) {
120-
const chat = await this.decryptMessage<Chat>(notification.encryptedContent);
139+
private processChatPropertiesNotification(notification: Notification<Chat>, emitter: ThreadEventEmitter | undefined) {
140+
const chat = notification.resourceData;
121141
switch (notification.changeType) {
122142
case 'updated':
123143
emitter?.chatThreadPropertiesUpdated(chat);
@@ -135,7 +155,7 @@ export class GraphNotificationClient {
135155

136156
await this.subscriptionCache.cacheSubscription(this.chatId, subscriptionRecord);
137157

138-
// only start timer once. -1 for renewaltimer is semaphore it has stopped.
158+
// only start timer once. -1 for renewalInterval is semaphore it has stopped.
139159
if (this.renewalInterval === -1) this.startRenewalTimer();
140160
};
141161

@@ -150,8 +170,6 @@ export class GraphNotificationClient {
150170
resource: resourcePath,
151171
expirationDateTime,
152172
includeResourceData: true,
153-
// encryptionCertificate: this._publicKey,
154-
// encryptionCertificateId: 'not-a-cert-id',
155173
clientState: 'wsssecret'
156174
};
157175

0 commit comments

Comments
 (0)