-
Notifications
You must be signed in to change notification settings - Fork 170
Expand file tree
/
Copy pathuseConnect.ts
More file actions
114 lines (100 loc) · 4.35 KB
/
Copy pathuseConnect.ts
File metadata and controls
114 lines (100 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { useCallback, useContext, useEffect } from 'react';
import { ConnectedWorkspace, useWorkspaceStore, WorkspaceState } from './workspace.store';
import { apiClient, slackClient } from './requests';
import { openPopup } from './helpers';
import { makeOAuthURL } from './constants';
import { getEnvironmentName } from './utils';
import { SDKContext, useCMA, useSDK } from '@contentful/react-apps-toolkit';
import { AppExtensionSDK } from '@contentful/app-sdk';
import { v4 as uuidv4 } from 'uuid';
import { useAuthStore } from './auth.store';
export const useConnect = () => {
const sdk = useSDK<AppExtensionSDK>();
const cma = useCMA();
const { temporaryRefreshToken } = useAuthStore((state) => ({
temporaryRefreshToken: state.temporaryRefreshToken,
}));
// @ts-expect-error private api not typed
const { api } = useContext(SDKContext);
const [setInstallationUuid] = useAuthStore((state) => [state.setInstallationUuid]);
const saveWorkspace = useCallback(
async (workspace, token) => {
const genericErrorMessage =
'Unable to store configuration. Please try connecting Slack again.';
if (token) {
try {
const installationUuid = uuidv4();
await api.install({ workspaces: [workspace.id], installationUuid });
setInstallationUuid(installationUuid);
await apiClient.createAuthToken(sdk, cma, token, installationUuid);
} catch (e) {
const error = e as Error;
// this 'AppInstallation does not exist error' is a race condition that occurs when instantiating the eventsService within the lambda.
// it is not a valid error to show to the user.
const errorMessage = JSON.parse(error.message);
if (errorMessage && errorMessage.details !== 'AppInstallation does not exist.') {
console.error(e);
sdk.notifier.error(genericErrorMessage);
}
}
}
},
// added during migration to new linting rules, ideally we can remove it
// eslint-disable-next-line react-hooks/exhaustive-deps
[cma, sdk, temporaryRefreshToken]
);
const { addConnectedWorkspace, setWorkspaceState, setNotificationsLoading, setChannels } =
useWorkspaceStore((state) => ({
addConnectedWorkspace: state.addConnectedWorkspace,
setWorkspaceState: state.setWorkspaceState,
notificationsLoading: state.notificationsLoading,
setNotificationsLoading: state.setNotificationsLoading,
setChannels: state.setChannels,
}));
const [setTemporaryRefreshToken] = useAuthStore((state) => [state.setTemporaryRefreshToken]);
const onMessage = async (message: MessageEvent) => {
if (message.origin !== window.location.origin) {
return;
}
if (message.data.result === 'error') {
sdk.notifier.error('Something went wrong while authenticating with Slack. Please try again.');
}
if (message.data.errorMessage) {
console.error(message.data.errorMessage);
}
if (message.data.state && message.data.accessToken) {
setWorkspaceState(WorkspaceState.LOADING);
setNotificationsLoading(true);
try {
const token = message.data.accessToken;
setTemporaryRefreshToken(message.data.refreshToken);
const workspace = await slackClient.getWorkspace(token);
const channels = await slackClient.getChannels(token, workspace.id);
setChannels(channels);
await saveWorkspace(workspace, message.data.refreshToken);
addConnectedWorkspace({ ...(workspace as ConnectedWorkspace) });
sdk.notifier.success('Connected to the Slack workspace successfully.');
} catch (e) {
sdk.notifier.error(
'Something went wrong while authenticating with Slack. Please try again.'
);
} finally {
setNotificationsLoading(false);
}
if (message.data) {
window.removeEventListener('message', onMessage);
}
setWorkspaceState(WorkspaceState.SUCCESS);
}
};
useEffect(() => {
return () => window.removeEventListener('message', onMessage);
// added during migration to new linting rules, ideally we can remove it
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const startOAuth = () => {
window.addEventListener('message', onMessage);
openPopup(makeOAuthURL(sdk.ids.space, getEnvironmentName(sdk.ids)), 700, 900);
};
return { startOAuth };
};