@seeka-labs/cli-apps 1.1.7 → 1.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +6 -6
- package/dist/index.js.map +2 -2
- package/dist/init-templates/aws-lambda/package.json +1 -1
- package/dist/init-templates/aws-lambda/src/routes/seekaAppWebhook.ts +32 -8
- package/dist/init-templates/azure-function/package.json +1 -1
- package/dist/init-templates/azure-function/src/functions/seekaAppWebhook.ts +33 -7
- package/dist/init-templates/netlify-function/package.json +1 -1
- package/dist/init-templates/netlify-function/src/api/seeka-app-webhook/index.ts +34 -8
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
import { webhookLogger } from '../lib/logging';
|
|
15
15
|
import { startServices } from '../lib/services';
|
|
16
16
|
import {
|
|
17
|
-
createOrUpdateInstallation, deleteInstallation, SeekaAppInstallState, tryGetInstallation
|
|
17
|
+
createOrUpdateInstallation, deleteInstallation, SampleAppInstallSettings, SeekaAppInstallState, tryGetInstallation
|
|
18
18
|
} from '../lib/state/seeka/installations';
|
|
19
19
|
|
|
20
20
|
export async function seekaAppWebhook(req: Request, res: Response, context: Context): Promise<void> {
|
|
@@ -64,15 +64,16 @@ export async function seekaAppWebhook(req: Request, res: Response, context: Cont
|
|
|
64
64
|
|
|
65
65
|
// Do something
|
|
66
66
|
try {
|
|
67
|
+
let errorMessage: string | null = null;
|
|
67
68
|
switch (body.type) {
|
|
68
69
|
case SeekaWebhookCallType.AppInstalled:
|
|
69
70
|
{
|
|
70
|
-
await onInstallation(body as SeekaAppInstalledWebhookPayload, logger);
|
|
71
|
+
errorMessage = await onInstallation(body as SeekaAppInstalledWebhookPayload, logger);
|
|
71
72
|
break;
|
|
72
73
|
}
|
|
73
74
|
case SeekaWebhookCallType.AppInstallSettingsUpdated:
|
|
74
75
|
{
|
|
75
|
-
await onInstallationSettingsUpdate(body as SeekaAppInstallSettingsUpdatedWebhookPayload, logger);
|
|
76
|
+
errorMessage = await onInstallationSettingsUpdate(body as SeekaAppInstallSettingsUpdatedWebhookPayload, logger);
|
|
76
77
|
break;
|
|
77
78
|
}
|
|
78
79
|
case SeekaWebhookCallType.AppUninstalled:
|
|
@@ -97,7 +98,13 @@ export async function seekaAppWebhook(req: Request, res: Response, context: Cont
|
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
100
|
|
|
100
|
-
|
|
101
|
+
if (errorMessage) {
|
|
102
|
+
logger.warn('Webhook call failed', { errorMessage });
|
|
103
|
+
res.status(400).json({ error: { message: errorMessage } }).send();
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
res.status(204).send();
|
|
107
|
+
}
|
|
101
108
|
}
|
|
102
109
|
catch (err) {
|
|
103
110
|
logger.error('Failed to handle webhook', { ex: winston.exceptions.getAllInfo(err) });
|
|
@@ -109,8 +116,18 @@ export async function seekaAppWebhook(req: Request, res: Response, context: Cont
|
|
|
109
116
|
}
|
|
110
117
|
}
|
|
111
118
|
|
|
112
|
-
const
|
|
113
|
-
|
|
119
|
+
const validateInstallationSettings = async (installSettings: SampleAppInstallSettings, logger: Logger): Promise<string | null> => {
|
|
120
|
+
// Returning an error message string here will block the installation request or settings update request by the user installing the app
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const onInstallation = async (payload: SeekaAppInstalledWebhookPayload, logger: Logger): Promise<string | null> => {
|
|
127
|
+
if (payload.isTest) return null;
|
|
128
|
+
|
|
129
|
+
const errorMessage = await validateInstallationSettings(payload.content?.installationSettings || {}, logger);
|
|
130
|
+
if (errorMessage) return errorMessage;
|
|
114
131
|
|
|
115
132
|
const installation = await createOrUpdateInstallation({
|
|
116
133
|
...payload.context,
|
|
@@ -123,10 +140,15 @@ const onInstallation = async (payload: SeekaAppInstalledWebhookPayload, logger:
|
|
|
123
140
|
installedAt: new Date().toISOString(),
|
|
124
141
|
installationSettings: payload.content?.installationSettings || {}
|
|
125
142
|
}, logger)
|
|
143
|
+
|
|
144
|
+
return null;
|
|
126
145
|
}
|
|
127
146
|
|
|
128
|
-
const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpdatedWebhookPayload, logger: Logger) => {
|
|
129
|
-
if (payload.isTest) return;
|
|
147
|
+
const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpdatedWebhookPayload, logger: Logger): Promise<string | null> => {
|
|
148
|
+
if (payload.isTest) return null;
|
|
149
|
+
|
|
150
|
+
const errorMessage = await validateInstallationSettings(payload.content?.installationSettings || {}, logger);
|
|
151
|
+
if (errorMessage) return errorMessage;
|
|
130
152
|
|
|
131
153
|
const existingInstallation = await tryGetInstallation(payload.context?.applicationInstallId as string, true, logger) as SeekaAppInstallState;
|
|
132
154
|
const installation = await createOrUpdateInstallation({
|
|
@@ -137,6 +159,8 @@ const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpda
|
|
|
137
159
|
},
|
|
138
160
|
installationSettings: payload.content?.installationSettings || {},
|
|
139
161
|
}, logger)
|
|
162
|
+
|
|
163
|
+
return null;
|
|
140
164
|
}
|
|
141
165
|
|
|
142
166
|
const handleSeekaActivity = async (activity: SeekaActivityAcceptedWebhookPayload, logger: Logger) => {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@azure/functions": "^4.1.0",
|
|
25
25
|
"@azure/storage-queue": "^12.16.0",
|
|
26
26
|
"@datalust/winston-seq": "^2.0.0",
|
|
27
|
-
"@seeka-labs/sdk-apps-server": "^1.
|
|
27
|
+
"@seeka-labs/sdk-apps-server": "^1.1.7",
|
|
28
28
|
"axios": "^1.6.7",
|
|
29
29
|
"lodash-es": "^4.17.21",
|
|
30
30
|
"openid-client": "^5.6.4",
|
|
@@ -16,7 +16,7 @@ import { getSeekaBrowserPlugin } from '../lib/browser'
|
|
|
16
16
|
import { webhookLogger } from '../lib/logging';
|
|
17
17
|
import { startServices } from '../lib/services';
|
|
18
18
|
import {
|
|
19
|
-
createOrUpdateInstallation, deleteInstallation, SeekaAppInstallState, tryGetInstallation
|
|
19
|
+
createOrUpdateInstallation, deleteInstallation, SampleAppInstallSettings, SeekaAppInstallState, tryGetInstallation
|
|
20
20
|
} from '../lib/state/seeka/installations';
|
|
21
21
|
|
|
22
22
|
import type { Logger } from 'winston';
|
|
@@ -85,16 +85,17 @@ export async function seekaAppWebhook(req: HttpRequest, context: InvocationConte
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
// Do something
|
|
88
|
+
let errorMessage: string | null = null;
|
|
88
89
|
try {
|
|
89
90
|
switch (body.type) {
|
|
90
91
|
case SeekaWebhookCallType.AppInstalled:
|
|
91
92
|
{
|
|
92
|
-
await onInstallation(body as SeekaAppInstalledWebhookPayload, logger);
|
|
93
|
+
errorMessage = await onInstallation(body as SeekaAppInstalledWebhookPayload, logger);
|
|
93
94
|
break;
|
|
94
95
|
}
|
|
95
96
|
case SeekaWebhookCallType.AppInstallSettingsUpdated:
|
|
96
97
|
{
|
|
97
|
-
await onInstallationSettingsUpdate(body as SeekaAppInstallSettingsUpdatedWebhookPayload, logger);
|
|
98
|
+
errorMessage = await onInstallationSettingsUpdate(body as SeekaAppInstallSettingsUpdatedWebhookPayload, logger);
|
|
98
99
|
break;
|
|
99
100
|
}
|
|
100
101
|
case SeekaWebhookCallType.AppUninstalled:
|
|
@@ -146,13 +147,31 @@ export async function seekaAppWebhook(req: HttpRequest, context: InvocationConte
|
|
|
146
147
|
logger.verbose('Seeka webhook handled');
|
|
147
148
|
}
|
|
148
149
|
|
|
150
|
+
if (errorMessage) {
|
|
151
|
+
logger.warn('Webhook call failed', { errorMessage });
|
|
152
|
+
return {
|
|
153
|
+
status: 400,
|
|
154
|
+
jsonBody: { error: { message: errorMessage } }
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
149
158
|
return {
|
|
150
159
|
status: 204
|
|
151
160
|
}
|
|
152
161
|
}
|
|
153
162
|
|
|
154
|
-
const
|
|
155
|
-
|
|
163
|
+
const validateInstallationSettings = async (installSettings: SampleAppInstallSettings, logger: Logger): Promise<string | null> => {
|
|
164
|
+
// Returning an error message string here will block the installation request or settings update request by the user installing the app
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const onInstallation = async (payload: SeekaAppInstalledWebhookPayload, logger: Logger): Promise<string | null> => {
|
|
171
|
+
if (payload.isTest) return null;
|
|
172
|
+
|
|
173
|
+
const errorMessage = await validateInstallationSettings(payload.content?.installationSettings || {}, logger);
|
|
174
|
+
if (errorMessage) return errorMessage;
|
|
156
175
|
|
|
157
176
|
const installation = await createOrUpdateInstallation({
|
|
158
177
|
...payload.context,
|
|
@@ -171,10 +190,15 @@ const onInstallation = async (payload: SeekaAppInstalledWebhookPayload, logger:
|
|
|
171
190
|
causationId: payload.causationId,
|
|
172
191
|
correlationId: payload.requestId
|
|
173
192
|
}, logger)
|
|
193
|
+
|
|
194
|
+
return null;
|
|
174
195
|
}
|
|
175
196
|
|
|
176
|
-
const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpdatedWebhookPayload, logger: Logger) => {
|
|
177
|
-
if (payload.isTest) return;
|
|
197
|
+
const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpdatedWebhookPayload, logger: Logger): Promise<string | null> => {
|
|
198
|
+
if (payload.isTest) return null;
|
|
199
|
+
|
|
200
|
+
const errorMessage = await validateInstallationSettings(payload.content?.installationSettings || {}, logger);
|
|
201
|
+
if (errorMessage) return errorMessage;
|
|
178
202
|
|
|
179
203
|
const existingInstallation = await tryGetInstallation(payload.context?.applicationInstallId as string, true, logger) as SeekaAppInstallState;
|
|
180
204
|
const installation = await createOrUpdateInstallation({
|
|
@@ -191,6 +215,8 @@ const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpda
|
|
|
191
215
|
causationId: payload.causationId,
|
|
192
216
|
correlationId: payload.requestId
|
|
193
217
|
}, logger)
|
|
218
|
+
|
|
219
|
+
return null;
|
|
194
220
|
}
|
|
195
221
|
|
|
196
222
|
const handleSeekaActivity = async (activity: SeekaActivityAcceptedWebhookPayload, logger: Logger) => {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@datalust/winston-seq": "^2.0.0",
|
|
21
21
|
"@netlify/functions": "^2.5.1",
|
|
22
|
-
"@seeka-labs/sdk-apps-server": "^1.
|
|
22
|
+
"@seeka-labs/sdk-apps-server": "^1.1.7",
|
|
23
23
|
"axios": "^1.6.7",
|
|
24
24
|
"lodash-es": "^4.17.21",
|
|
25
25
|
"openid-client": "^5.6.4",
|
|
@@ -7,7 +7,7 @@ import { jobNames, triggerBackgroundJob } from '@/lib/jobs';
|
|
|
7
7
|
import { webhookLogger } from '@/lib/logging';
|
|
8
8
|
import { startServices, stopServices } from '@/lib/services';
|
|
9
9
|
import {
|
|
10
|
-
createOrUpdateInstallation, deleteInstallation, SeekaAppInstallState, tryGetInstallation
|
|
10
|
+
createOrUpdateInstallation, deleteInstallation, SampleAppInstallSettings, SeekaAppInstallState, tryGetInstallation
|
|
11
11
|
} from '@/lib/state/seeka/installations';
|
|
12
12
|
import {
|
|
13
13
|
PersonIdentifiers, SeekaActivityAcceptedWebhookPayload, SeekaAppInstalledWebhookPayload,
|
|
@@ -67,16 +67,17 @@ export default async (req: Request, context: Context) => {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
// Do something
|
|
70
|
+
let errorMessage: string | null = null;
|
|
70
71
|
try {
|
|
71
72
|
switch (body.type) {
|
|
72
73
|
case SeekaWebhookCallType.AppInstalled:
|
|
73
74
|
{
|
|
74
|
-
await onInstallation(body as SeekaAppInstalledWebhookPayload, logger);
|
|
75
|
+
errorMessage = await onInstallation(body as SeekaAppInstalledWebhookPayload, logger);
|
|
75
76
|
break;
|
|
76
77
|
}
|
|
77
78
|
case SeekaWebhookCallType.AppInstallSettingsUpdated:
|
|
78
79
|
{
|
|
79
|
-
await onInstallationSettingsUpdate(body as SeekaAppInstallSettingsUpdatedWebhookPayload, logger);
|
|
80
|
+
errorMessage = await onInstallationSettingsUpdate(body as SeekaAppInstallSettingsUpdatedWebhookPayload, logger);
|
|
80
81
|
break;
|
|
81
82
|
}
|
|
82
83
|
case SeekaWebhookCallType.AppUninstalled:
|
|
@@ -114,29 +115,52 @@ export default async (req: Request, context: Context) => {
|
|
|
114
115
|
logger.verbose('Seeka webhook handled');
|
|
115
116
|
}
|
|
116
117
|
|
|
118
|
+
if (errorMessage) {
|
|
119
|
+
logger.warn('Webhook call failed', { errorMessage });
|
|
120
|
+
return Response.json({ error: { message: errorMessage } }, { status: 400 });
|
|
121
|
+
}
|
|
122
|
+
|
|
117
123
|
return new Response(undefined, { status: 204 })
|
|
118
124
|
}
|
|
119
125
|
|
|
126
|
+
const validateInstallationSettings = async (installSettings: SampleAppInstallSettings, logger: Logger): Promise<string | null> => {
|
|
127
|
+
// Returning an error message string here will block the installation request or settings update request by the user installing the app
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const onInstallation = async (payload: SeekaAppInstalledWebhookPayload, logger: Logger): Promise<string | null> => {
|
|
134
|
+
if (payload.isTest) return null;
|
|
120
135
|
|
|
121
|
-
const
|
|
122
|
-
if (
|
|
136
|
+
const errorMessage = await validateInstallationSettings(payload.content?.installationSettings || {}, logger);
|
|
137
|
+
if (errorMessage) return errorMessage;
|
|
123
138
|
|
|
124
139
|
const installation = await createOrUpdateInstallation({
|
|
125
140
|
...payload.context,
|
|
126
141
|
installationState: {
|
|
127
142
|
grantedPermissions: payload.content?.grantedPermissions || []
|
|
128
143
|
},
|
|
144
|
+
applicationInstallId: payload.context?.applicationInstallId as string,
|
|
145
|
+
organisationBrandId: payload.context?.organisationBrandId as string,
|
|
146
|
+
organisationId: payload.context?.organisationId as string,
|
|
147
|
+
installedAt: new Date().toISOString(),
|
|
129
148
|
installationSettings: payload.content?.installationSettings || {}
|
|
130
|
-
}
|
|
149
|
+
}, logger)
|
|
131
150
|
|
|
132
151
|
// Trigger a sync for the installation
|
|
133
152
|
await triggerBackgroundJob(jobNames.exampleBackgroundJob, {
|
|
134
153
|
...payload.context
|
|
135
154
|
}, logger)
|
|
155
|
+
|
|
156
|
+
return null;
|
|
136
157
|
}
|
|
137
158
|
|
|
138
|
-
const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpdatedWebhookPayload, logger: Logger) => {
|
|
139
|
-
if (payload.isTest) return;
|
|
159
|
+
const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpdatedWebhookPayload, logger: Logger): Promise<string | null> => {
|
|
160
|
+
if (payload.isTest) return null;
|
|
161
|
+
|
|
162
|
+
const errorMessage = await validateInstallationSettings(payload.content?.installationSettings || {}, logger);
|
|
163
|
+
if (errorMessage) return errorMessage;
|
|
140
164
|
|
|
141
165
|
const existingInstallation = await tryGetInstallation(payload.context?.applicationInstallId as string, true, logger) as SeekaAppInstallState;
|
|
142
166
|
|
|
@@ -152,6 +176,8 @@ const onInstallationSettingsUpdate = async (payload: SeekaAppInstallSettingsUpda
|
|
|
152
176
|
} as any, logger) // TODO: remove any
|
|
153
177
|
|
|
154
178
|
logger.info('Settings updated')
|
|
179
|
+
|
|
180
|
+
return null;
|
|
155
181
|
}
|
|
156
182
|
|
|
157
183
|
const handleSeekaActivity = async (activity: SeekaActivityAcceptedWebhookPayload, logger: Logger) => {
|