@serve.zone/gitops 3.1.1 → 32.1.0
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/.smartconfig.json +26 -7
- package/changelog.md +42 -0
- package/deno.json +1 -1
- package/dist_serve/bundle.js +327 -299
- package/dist_serve/bundle.js.map +1 -0
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/cache/classes.cachedb.d.ts +1 -1
- package/dist_ts/cache/classes.cachedb.js +1 -1
- package/dist_ts/classes/connectionmanager.d.ts +41 -0
- package/dist_ts/classes/connectionmanager.js +143 -9
- package/dist_ts/opsserver/handlers/webhook.handler.d.ts +20 -0
- package/dist_ts/opsserver/handlers/webhook.handler.js +132 -14
- package/dist_ts/opsserver/helpers/webhookverification.d.ts +70 -0
- package/dist_ts/opsserver/helpers/webhookverification.js +158 -0
- package/dist_ts/plugins.d.ts +2 -1
- package/dist_ts/plugins.js +3 -2
- package/dist_ts/providers/classes.giteaprovider.d.ts +10 -0
- package/dist_ts/providers/classes.giteaprovider.js +11 -1
- package/dist_ts/providers/classes.gitlabprovider.d.ts +10 -0
- package/dist_ts/providers/classes.gitlabprovider.js +11 -1
- package/dist_ts_interfaces/data/connection.d.ts +27 -0
- package/dist_ts_interfaces/requests/webhook.d.ts +31 -0
- package/package.json +9 -9
- package/readme.md +60 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/cache/classes.cachedb.ts +1 -1
- package/ts/classes/connectionmanager.ts +150 -8
- package/ts/opsserver/handlers/webhook.handler.ts +175 -14
- package/ts/opsserver/helpers/webhookverification.ts +202 -0
- package/ts/plugins.ts +2 -1
- package/ts/providers/classes.giteaprovider.ts +11 -0
- package/ts/providers/classes.gitlabprovider.ts +11 -0
- package/ts_interfaces/data/connection.ts +29 -0
- package/ts_interfaces/requests/webhook.ts +42 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +46 -0
- package/ts_web/elements/views/connections/index.ts +89 -0
- package/readme.todo.md +0 -3
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/gitops',
|
|
6
|
-
version: '
|
|
6
|
+
version: '32.1.0',
|
|
7
7
|
description: 'GitOps management app for Gitea and GitLab - manage secrets, browse projects, view CI pipelines, and stream build logs'
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxvQkFBb0I7SUFDMUIsT0FBTyxFQUFFLFFBQVE7SUFDakIsV0FBVyxFQUFFLHdIQUF3SDtDQUN0SSxDQUFBIn0=
|
|
@@ -5,7 +5,7 @@ export interface ICacheDbOptions {
|
|
|
5
5
|
debug?: boolean;
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
|
-
* Singleton wrapper around
|
|
8
|
+
* Singleton wrapper around SmartMongo's NoSQLDB memory server and SmartData.
|
|
9
9
|
* Provides a managed MongoDB-compatible cache database.
|
|
10
10
|
*/
|
|
11
11
|
export declare class CacheDb {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as plugins from '../plugins.js';
|
|
2
2
|
import { logger } from '../logging.js';
|
|
3
3
|
/**
|
|
4
|
-
* Singleton wrapper around
|
|
4
|
+
* Singleton wrapper around SmartMongo's NoSQLDB memory server and SmartData.
|
|
5
5
|
* Provides a managed MongoDB-compatible cache database.
|
|
6
6
|
*/
|
|
7
7
|
export class CacheDb {
|
|
@@ -30,8 +30,20 @@ export declare class ConnectionManager {
|
|
|
30
30
|
*/
|
|
31
31
|
private migrateTokenToKeychain;
|
|
32
32
|
private migrateRegistryTokenToKeychain;
|
|
33
|
+
/**
|
|
34
|
+
* Connections stored before webhook verification existed carry no secret. Nothing in
|
|
35
|
+
* gitops can create the webhook at the provider (neither provider implementation nor
|
|
36
|
+
* the Gitea/GitLab clients expose a hooks endpoint), so the secret is minted here and
|
|
37
|
+
* the connection is marked 'unverified': its deliveries stay refused until an operator
|
|
38
|
+
* copies the secret into the provider's webhook configuration and confirms it.
|
|
39
|
+
*/
|
|
40
|
+
private backfillWebhookSecret;
|
|
33
41
|
private persistConnection;
|
|
34
42
|
private removeConnection;
|
|
43
|
+
/**
|
|
44
|
+
* The shape handed to API callers: every secret is masked, never the real value.
|
|
45
|
+
*/
|
|
46
|
+
private toPublicConnection;
|
|
35
47
|
getConnections(): interfaces.data.IProviderConnection[];
|
|
36
48
|
getConnection(id: string): interfaces.data.IProviderConnection | undefined;
|
|
37
49
|
createConnection(name: string, providerType: interfaces.data.TProviderType, baseUrl: string, token: string, groupFilter?: string, registryUrl?: string, registryUsername?: string, registryToken?: string): Promise<interfaces.data.IProviderConnection>;
|
|
@@ -46,6 +58,35 @@ export declare class ConnectionManager {
|
|
|
46
58
|
}): Promise<interfaces.data.IProviderConnection>;
|
|
47
59
|
deleteConnection(id: string): Promise<void>;
|
|
48
60
|
pauseConnection(id: string, paused: boolean): Promise<interfaces.data.IProviderConnection>;
|
|
61
|
+
/**
|
|
62
|
+
* Reveals the webhook secret to an already authenticated caller — the operator has to
|
|
63
|
+
* transfer it into the provider's webhook configuration by hand, because no provider
|
|
64
|
+
* API surface in this app creates webhooks.
|
|
65
|
+
*/
|
|
66
|
+
/**
|
|
67
|
+
* A stored-but-unreadable secret is reported as such, so an operator sees a secret-store
|
|
68
|
+
* outage instead of a connection that appears to have lost its secret.
|
|
69
|
+
*/
|
|
70
|
+
private assertWebhookSecretReadable;
|
|
71
|
+
getWebhookSecret(id: string): {
|
|
72
|
+
secret: string;
|
|
73
|
+
status: interfaces.data.TWebhookStatus;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Mints a fresh webhook secret. The provider still holds the previous one, so the
|
|
77
|
+
* connection goes back to 'unverified' until the new secret is confirmed.
|
|
78
|
+
*/
|
|
79
|
+
rotateWebhookSecret(id: string): Promise<{
|
|
80
|
+
secret: string;
|
|
81
|
+
status: interfaces.data.TWebhookStatus;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* Records that the provider side now holds the current secret; deliveries that carry a
|
|
85
|
+
* valid signature are accepted from here on.
|
|
86
|
+
*/
|
|
87
|
+
confirmWebhookSecret(id: string): Promise<{
|
|
88
|
+
status: interfaces.data.TWebhookStatus;
|
|
89
|
+
}>;
|
|
49
90
|
testConnection(id: string): Promise<{
|
|
50
91
|
ok: boolean;
|
|
51
92
|
error?: string;
|
|
@@ -5,6 +5,12 @@ const LEGACY_CONNECTIONS_FILE = './.nogit/connections.json';
|
|
|
5
5
|
const CONNECTIONS_PREFIX = '/connections/';
|
|
6
6
|
const KEYCHAIN_PREFIX = 'keychain:';
|
|
7
7
|
const getRegistryTokenSecretId = (connectionId) => `${connectionId}:registry`;
|
|
8
|
+
const getWebhookSecretId = (connectionId) => `${connectionId}:webhook`;
|
|
9
|
+
/**
|
|
10
|
+
* Mints a webhook secret. 32 random bytes as hex: long enough that a delivery carrying
|
|
11
|
+
* it proves the sender was configured by us, short enough to paste into a provider UI.
|
|
12
|
+
*/
|
|
13
|
+
const mintWebhookSecret = () => plugins.crypto.randomBytes(32).toString('hex');
|
|
8
14
|
/**
|
|
9
15
|
* Manages provider connections — persists each connection as an
|
|
10
16
|
* individual JSON file via StorageManager. Tokens are stored in
|
|
@@ -109,7 +115,25 @@ export class ConnectionManager {
|
|
|
109
115
|
else if (conn.registryToken && conn.registryToken !== '***') {
|
|
110
116
|
await this.migrateRegistryTokenToKeychain(conn);
|
|
111
117
|
}
|
|
118
|
+
if (conn.webhookSecret?.startsWith(KEYCHAIN_PREFIX)) {
|
|
119
|
+
const webhookSecretId = conn.webhookSecret.substring(KEYCHAIN_PREFIX.length);
|
|
120
|
+
const realWebhookSecret = await this.smartSecret.getSecret(webhookSecretId);
|
|
121
|
+
if (realWebhookSecret) {
|
|
122
|
+
conn.webhookSecret = realWebhookSecret;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// The sentinel proves a secret was stored under this id, so an empty read is a
|
|
126
|
+
// keychain failure, not a missing secret. Minting a replacement here would
|
|
127
|
+
// overwrite the operator's confirmed secret under the same id and lose it, so
|
|
128
|
+
// the connection is flagged instead and its deliveries are refused by name.
|
|
129
|
+
logger.warn(`Webhook secret for connection ${conn.id} is stored but unreadable — deliveries are ` +
|
|
130
|
+
'refused until the secret store returns it again; the stored secret is left untouched');
|
|
131
|
+
conn.webhookSecret = undefined;
|
|
132
|
+
conn.webhookSecretUnreadable = true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
112
135
|
this.connections.push(conn);
|
|
136
|
+
await this.backfillWebhookSecret(conn);
|
|
113
137
|
}
|
|
114
138
|
}
|
|
115
139
|
if (this.connections.length > 0) {
|
|
@@ -150,6 +174,29 @@ export class ConnectionManager {
|
|
|
150
174
|
logger.warn(`Failed to migrate registry token for ${conn.id} to keychain: ${err}`);
|
|
151
175
|
}
|
|
152
176
|
}
|
|
177
|
+
/**
|
|
178
|
+
* Connections stored before webhook verification existed carry no secret. Nothing in
|
|
179
|
+
* gitops can create the webhook at the provider (neither provider implementation nor
|
|
180
|
+
* the Gitea/GitLab clients expose a hooks endpoint), so the secret is minted here and
|
|
181
|
+
* the connection is marked 'unverified': its deliveries stay refused until an operator
|
|
182
|
+
* copies the secret into the provider's webhook configuration and confirms it.
|
|
183
|
+
*/
|
|
184
|
+
async backfillWebhookSecret(conn) {
|
|
185
|
+
// A stored-but-unreadable secret is not a missing one. Minting here would write a new
|
|
186
|
+
// secret over the same keychain id and destroy confirmed operator material because of
|
|
187
|
+
// a transient read failure, so this connection is left exactly as it is on disk.
|
|
188
|
+
if (conn.webhookSecretUnreadable)
|
|
189
|
+
return;
|
|
190
|
+
if (conn.webhookSecret && conn.webhookStatus)
|
|
191
|
+
return;
|
|
192
|
+
if (!conn.webhookSecret) {
|
|
193
|
+
conn.webhookSecret = mintWebhookSecret();
|
|
194
|
+
}
|
|
195
|
+
conn.webhookStatus = 'unverified';
|
|
196
|
+
await this.persistConnection(conn);
|
|
197
|
+
logger.warn(`Connection "${conn.name}" had no webhook secret — minted one and marked the webhook unverified. ` +
|
|
198
|
+
'Webhook deliveries are refused until the secret is set at the provider and confirmed.');
|
|
199
|
+
}
|
|
153
200
|
async persistConnection(conn) {
|
|
154
201
|
// Store real token in keychain
|
|
155
202
|
await this.smartSecret.setSecret(conn.id, conn.token);
|
|
@@ -159,25 +206,52 @@ export class ConnectionManager {
|
|
|
159
206
|
else {
|
|
160
207
|
await this.smartSecret.deleteSecret(getRegistryTokenSecretId(conn.id));
|
|
161
208
|
}
|
|
209
|
+
// A connection whose secret is stored but unreadable keeps both its keychain entry and
|
|
210
|
+
// its sentinel: writing would replace material we could not read, deleting would throw
|
|
211
|
+
// it away. Every other persist path (status updates, health checks) runs through here,
|
|
212
|
+
// so this is where the stored secret survives a secret-store outage.
|
|
213
|
+
if (conn.webhookSecretUnreadable) {
|
|
214
|
+
// nothing to write — the stored secret and sentinel stay as they are
|
|
215
|
+
}
|
|
216
|
+
else if (conn.webhookSecret) {
|
|
217
|
+
await this.smartSecret.setSecret(getWebhookSecretId(conn.id), conn.webhookSecret);
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
await this.smartSecret.deleteSecret(getWebhookSecretId(conn.id));
|
|
221
|
+
}
|
|
162
222
|
// Save JSON with sentinel value
|
|
163
223
|
const jsonConn = {
|
|
164
224
|
...conn,
|
|
165
225
|
token: `${KEYCHAIN_PREFIX}${conn.id}`,
|
|
166
226
|
registryToken: conn.registryToken ? `${KEYCHAIN_PREFIX}${getRegistryTokenSecretId(conn.id)}` : undefined,
|
|
227
|
+
webhookSecret: conn.webhookSecret || conn.webhookSecretUnreadable
|
|
228
|
+
? `${KEYCHAIN_PREFIX}${getWebhookSecretId(conn.id)}`
|
|
229
|
+
: undefined,
|
|
230
|
+
// Runtime-only flag: it describes this process's view of the secret store, not the
|
|
231
|
+
// connection, and persisting it would outlive the outage that caused it.
|
|
232
|
+
webhookSecretUnreadable: undefined,
|
|
167
233
|
};
|
|
168
234
|
await this.storageManager.setJSON(`${CONNECTIONS_PREFIX}${conn.id}.json`, jsonConn);
|
|
169
235
|
}
|
|
170
236
|
async removeConnection(id) {
|
|
171
237
|
await this.smartSecret.deleteSecret(id);
|
|
172
238
|
await this.smartSecret.deleteSecret(getRegistryTokenSecretId(id));
|
|
239
|
+
await this.smartSecret.deleteSecret(getWebhookSecretId(id));
|
|
173
240
|
await this.storageManager.delete(`${CONNECTIONS_PREFIX}${id}.json`);
|
|
174
241
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
242
|
+
/**
|
|
243
|
+
* The shape handed to API callers: every secret is masked, never the real value.
|
|
244
|
+
*/
|
|
245
|
+
toPublicConnection(conn) {
|
|
246
|
+
return {
|
|
247
|
+
...conn,
|
|
178
248
|
token: '***',
|
|
179
|
-
registryToken:
|
|
180
|
-
|
|
249
|
+
registryToken: conn.registryToken ? '***' : undefined,
|
|
250
|
+
webhookSecret: conn.webhookSecret ? '***' : undefined,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
getConnections() {
|
|
254
|
+
return this.connections.map((c) => this.toPublicConnection(c));
|
|
181
255
|
}
|
|
182
256
|
getConnection(id) {
|
|
183
257
|
return this.connections.find((c) => c.id === id);
|
|
@@ -195,11 +269,15 @@ export class ConnectionManager {
|
|
|
195
269
|
registryUrl: registryUrl || undefined,
|
|
196
270
|
registryUsername: registryUsername || undefined,
|
|
197
271
|
registryToken: registryToken || undefined,
|
|
272
|
+
// Minted with the connection so the operator can paste it into the provider's
|
|
273
|
+
// webhook form right away; no earlier provider state can hold a stale secret.
|
|
274
|
+
webhookSecret: mintWebhookSecret(),
|
|
275
|
+
webhookStatus: 'active',
|
|
198
276
|
};
|
|
199
277
|
this.connections.push(connection);
|
|
200
278
|
await this.persistConnection(connection);
|
|
201
279
|
logger.success(`Connection created: ${name} (${providerType})`);
|
|
202
|
-
return
|
|
280
|
+
return this.toPublicConnection(connection);
|
|
203
281
|
}
|
|
204
282
|
async updateConnection(id, updates) {
|
|
205
283
|
const conn = this.connections.find((c) => c.id === id);
|
|
@@ -222,7 +300,7 @@ export class ConnectionManager {
|
|
|
222
300
|
if (updates.registryToken !== undefined)
|
|
223
301
|
conn.registryToken = updates.registryToken || undefined;
|
|
224
302
|
await this.persistConnection(conn);
|
|
225
|
-
return
|
|
303
|
+
return this.toPublicConnection(conn);
|
|
226
304
|
}
|
|
227
305
|
async deleteConnection(id) {
|
|
228
306
|
const idx = this.connections.findIndex((c) => c.id === id);
|
|
@@ -239,7 +317,63 @@ export class ConnectionManager {
|
|
|
239
317
|
conn.status = paused ? 'paused' : 'disconnected';
|
|
240
318
|
await this.persistConnection(conn);
|
|
241
319
|
logger.info(`Connection ${paused ? 'paused' : 'resumed'}: ${conn.name}`);
|
|
242
|
-
return
|
|
320
|
+
return this.toPublicConnection(conn);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Reveals the webhook secret to an already authenticated caller — the operator has to
|
|
324
|
+
* transfer it into the provider's webhook configuration by hand, because no provider
|
|
325
|
+
* API surface in this app creates webhooks.
|
|
326
|
+
*/
|
|
327
|
+
/**
|
|
328
|
+
* A stored-but-unreadable secret is reported as such, so an operator sees a secret-store
|
|
329
|
+
* outage instead of a connection that appears to have lost its secret.
|
|
330
|
+
*/
|
|
331
|
+
assertWebhookSecretReadable(conn) {
|
|
332
|
+
if (conn.webhookSecretUnreadable) {
|
|
333
|
+
throw new Error(`Webhook secret for connection ${conn.id} is stored but unreadable — the secret store did not return it`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
getWebhookSecret(id) {
|
|
337
|
+
const conn = this.connections.find((c) => c.id === id);
|
|
338
|
+
if (!conn)
|
|
339
|
+
throw new Error(`Connection not found: ${id}`);
|
|
340
|
+
this.assertWebhookSecretReadable(conn);
|
|
341
|
+
if (!conn.webhookSecret)
|
|
342
|
+
throw new Error(`Connection has no webhook secret: ${id}`);
|
|
343
|
+
return { secret: conn.webhookSecret, status: conn.webhookStatus ?? 'unverified' };
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Mints a fresh webhook secret. The provider still holds the previous one, so the
|
|
347
|
+
* connection goes back to 'unverified' until the new secret is confirmed.
|
|
348
|
+
*/
|
|
349
|
+
async rotateWebhookSecret(id) {
|
|
350
|
+
const conn = this.connections.find((c) => c.id === id);
|
|
351
|
+
if (!conn)
|
|
352
|
+
throw new Error(`Connection not found: ${id}`);
|
|
353
|
+
conn.webhookSecret = mintWebhookSecret();
|
|
354
|
+
conn.webhookStatus = 'unverified';
|
|
355
|
+
// Rotation is the operator's explicit decision to replace the stored secret, which is
|
|
356
|
+
// also the way out of an unreadable one — unlike the automatic backfill.
|
|
357
|
+
conn.webhookSecretUnreadable = undefined;
|
|
358
|
+
await this.persistConnection(conn);
|
|
359
|
+
logger.info(`Webhook secret rotated for connection "${conn.name}" — webhook is unverified again`);
|
|
360
|
+
return { secret: conn.webhookSecret, status: conn.webhookStatus };
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Records that the provider side now holds the current secret; deliveries that carry a
|
|
364
|
+
* valid signature are accepted from here on.
|
|
365
|
+
*/
|
|
366
|
+
async confirmWebhookSecret(id) {
|
|
367
|
+
const conn = this.connections.find((c) => c.id === id);
|
|
368
|
+
if (!conn)
|
|
369
|
+
throw new Error(`Connection not found: ${id}`);
|
|
370
|
+
this.assertWebhookSecretReadable(conn);
|
|
371
|
+
if (!conn.webhookSecret)
|
|
372
|
+
throw new Error(`Connection has no webhook secret: ${id}`);
|
|
373
|
+
conn.webhookStatus = 'active';
|
|
374
|
+
await this.persistConnection(conn);
|
|
375
|
+
logger.success(`Webhook confirmed for connection "${conn.name}"`);
|
|
376
|
+
return { status: conn.webhookStatus };
|
|
243
377
|
}
|
|
244
378
|
async testConnection(id) {
|
|
245
379
|
const conn = this.connections.find((c) => c.id === id);
|
|
@@ -299,4 +433,4 @@ export class ConnectionManager {
|
|
|
299
433
|
}
|
|
300
434
|
}
|
|
301
435
|
}
|
|
302
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdGlvbm1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jbGFzc2VzL2Nvbm5lY3Rpb25tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFdkMsT0FBTyxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFHcEYsTUFBTSx1QkFBdUIsR0FBRywyQkFBMkIsQ0FBQztBQUM1RCxNQUFNLGtCQUFrQixHQUFHLGVBQWUsQ0FBQztBQUMzQyxNQUFNLGVBQWUsR0FBRyxXQUFXLENBQUM7QUFFcEMsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLFlBQW9CLEVBQVUsRUFBRSxDQUFDLEdBQUcsWUFBWSxXQUFXLENBQUM7QUFFOUY7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyxpQkFBaUI7SUFDcEIsV0FBVyxHQUEwQyxFQUFFLENBQUM7SUFDeEQsY0FBYyxDQUFpQjtJQUMvQixXQUFXLENBQWtDO0lBQ3JELGlFQUFpRTtJQUMxRCxlQUFlLEdBQWtCLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUUxRCxZQUFZLGNBQThCLEVBQUUsV0FBNEM7UUFDdEYsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7SUFDakMsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJO1FBQ1IsTUFBTSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUMvQixNQUFNLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUM3Qiw4Q0FBOEM7UUFDOUMsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztJQUNuRCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssS0FBSyxD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
|
|
436
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ubmVjdGlvbm1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jbGFzc2VzL2Nvbm5lY3Rpb25tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFdkMsT0FBTyxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFHcEYsTUFBTSx1QkFBdUIsR0FBRywyQkFBMkIsQ0FBQztBQUM1RCxNQUFNLGtCQUFrQixHQUFHLGVBQWUsQ0FBQztBQUMzQyxNQUFNLGVBQWUsR0FBRyxXQUFXLENBQUM7QUFFcEMsTUFBTSx3QkFBd0IsR0FBRyxDQUFDLFlBQW9CLEVBQVUsRUFBRSxDQUFDLEdBQUcsWUFBWSxXQUFXLENBQUM7QUFDOUYsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLFlBQW9CLEVBQVUsRUFBRSxDQUFDLEdBQUcsWUFBWSxVQUFVLENBQUM7QUFFdkY7OztHQUdHO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxHQUFXLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7QUFFdkY7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyxpQkFBaUI7SUFDcEIsV0FBVyxHQUEwQyxFQUFFLENBQUM7SUFDeEQsY0FBYyxDQUFpQjtJQUMvQixXQUFXLENBQWtDO0lBQ3JELGlFQUFpRTtJQUMxRCxlQUFlLEdBQWtCLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUUxRCxZQUFZLGNBQThCLEVBQUUsV0FBNEM7UUFDdEYsSUFBSSxDQUFDLGNBQWMsR0FBRyxjQUFjLENBQUM7UUFDckMsSUFBSSxDQUFDLFdBQVcsR0FBRyxXQUFXLENBQUM7SUFDakMsQ0FBQztJQUVE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
|
|
@@ -1,7 +1,27 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
2
|
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
4
|
+
/** Route pattern of the delivery endpoint. */
|
|
5
|
+
export declare const webhookRoutePattern = "/webhook/:connectionId";
|
|
6
|
+
/** The concrete delivery path an operator configures at the provider. */
|
|
7
|
+
export declare const webhookDeliveryPath: (connectionIdArg: string) => string;
|
|
3
8
|
export declare class WebhookHandler {
|
|
4
9
|
private opsServerRef;
|
|
10
|
+
typedrouter: plugins.typedrequest.TypedRouter<interfaces.typedrequestInterfaces.ITypedRequest>;
|
|
5
11
|
constructor(opsServerRef: OpsServer);
|
|
12
|
+
private get connectionManager();
|
|
13
|
+
private get actionLog();
|
|
14
|
+
/**
|
|
15
|
+
* Refuses a delivery. The refusal name is the whole answer — no payload is echoed and
|
|
16
|
+
* nothing about the presented or expected secret is logged.
|
|
17
|
+
*/
|
|
18
|
+
private refuse;
|
|
19
|
+
private webhookSettingsFor;
|
|
20
|
+
/**
|
|
21
|
+
* Operator-facing side of the webhook: reveal, rotate and confirm the shared secret.
|
|
22
|
+
* Neither provider implementation creates webhooks through the API, so the secret is
|
|
23
|
+
* transferred into the provider's webhook configuration by hand.
|
|
24
|
+
*/
|
|
25
|
+
private registerHandlers;
|
|
6
26
|
registerRoutes(typedserver: plugins.typedserver.TypedServer): void;
|
|
7
27
|
}
|
|
@@ -1,28 +1,146 @@
|
|
|
1
1
|
import * as plugins from '../../plugins.js';
|
|
2
2
|
import { logger } from '../../logging.js';
|
|
3
3
|
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
4
|
+
import { requireValidIdentity } from '../helpers/guards.js';
|
|
5
|
+
import { checkWebhookConnection, readBoundedWebhookBody, verifyWebhookDelivery, webhookEventHeaderFor, webhookSecretHeaderFor, } from '../helpers/webhookverification.js';
|
|
6
|
+
/** Route pattern of the delivery endpoint. */
|
|
7
|
+
export const webhookRoutePattern = '/webhook/:connectionId';
|
|
8
|
+
/** The concrete delivery path an operator configures at the provider. */
|
|
9
|
+
export const webhookDeliveryPath = (connectionIdArg) => `/webhook/${connectionIdArg}`;
|
|
10
|
+
/**
|
|
11
|
+
* HTTP status per refusal. Everything the caller could fix by presenting the right
|
|
12
|
+
* secret is a 401; the rest describes the request itself — except
|
|
13
|
+
* 'webhook-secret-unreadable', which is our own transient fault and is answered 503 so a
|
|
14
|
+
* provider retries instead of an operator rotating a secret that is still correct.
|
|
15
|
+
*/
|
|
16
|
+
const refusalStatusCodes = {
|
|
17
|
+
'webhook-connection-unknown': 404,
|
|
18
|
+
'webhook-connection-unverified': 401,
|
|
19
|
+
'webhook-secret-missing': 401,
|
|
20
|
+
'webhook-secret-unreadable': 503,
|
|
21
|
+
'webhook-length-missing': 411,
|
|
22
|
+
'webhook-body-too-large': 413,
|
|
23
|
+
'webhook-body-unreadable': 400,
|
|
24
|
+
'webhook-signature-missing': 401,
|
|
25
|
+
'webhook-signature-invalid': 401,
|
|
26
|
+
};
|
|
4
27
|
export class WebhookHandler {
|
|
5
28
|
opsServerRef;
|
|
29
|
+
typedrouter = new plugins.typedrequest.TypedRouter();
|
|
6
30
|
constructor(opsServerRef) {
|
|
7
31
|
this.opsServerRef = opsServerRef;
|
|
32
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
33
|
+
this.registerHandlers();
|
|
34
|
+
}
|
|
35
|
+
get connectionManager() {
|
|
36
|
+
return this.opsServerRef.gitopsAppRef.connectionManager;
|
|
37
|
+
}
|
|
38
|
+
get actionLog() {
|
|
39
|
+
return this.opsServerRef.gitopsAppRef.actionLog;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Refuses a delivery. The refusal name is the whole answer — no payload is echoed and
|
|
43
|
+
* nothing about the presented or expected secret is logged.
|
|
44
|
+
*/
|
|
45
|
+
refuse(refusalArg, connectionIdArg, connectionNameArg) {
|
|
46
|
+
const target = connectionNameArg
|
|
47
|
+
? `connection ${connectionNameArg} (${connectionIdArg})`
|
|
48
|
+
: `connection ${connectionIdArg}`;
|
|
49
|
+
logger.warn(`Webhook refused: ${refusalArg} for ${target}`);
|
|
50
|
+
return new Response(JSON.stringify({ error: refusalArg }), {
|
|
51
|
+
status: refusalStatusCodes[refusalArg],
|
|
52
|
+
headers: { 'Content-Type': 'application/json' },
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
webhookSettingsFor(connectionIdArg) {
|
|
56
|
+
const connection = this.connectionManager.getConnection(connectionIdArg);
|
|
57
|
+
if (!connection) {
|
|
58
|
+
throw new plugins.typedrequest.TypedResponseError(`Connection not found: ${connectionIdArg}`);
|
|
59
|
+
}
|
|
60
|
+
const { secret, status } = this.connectionManager.getWebhookSecret(connectionIdArg);
|
|
61
|
+
return {
|
|
62
|
+
connectionId: connection.id,
|
|
63
|
+
providerType: connection.providerType,
|
|
64
|
+
deliveryPath: webhookDeliveryPath(connection.id),
|
|
65
|
+
headerName: webhookSecretHeaderFor(connection.providerType),
|
|
66
|
+
secret,
|
|
67
|
+
status,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Operator-facing side of the webhook: reveal, rotate and confirm the shared secret.
|
|
72
|
+
* Neither provider implementation creates webhooks through the API, so the secret is
|
|
73
|
+
* transferred into the provider's webhook configuration by hand.
|
|
74
|
+
*/
|
|
75
|
+
registerHandlers() {
|
|
76
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getWebhookSettings', async (dataArg) => {
|
|
77
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
78
|
+
return { webhookSettings: this.webhookSettingsFor(dataArg.connectionId) };
|
|
79
|
+
}));
|
|
80
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('rotateWebhookSecret', async (dataArg) => {
|
|
81
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
82
|
+
await this.connectionManager.rotateWebhookSecret(dataArg.connectionId);
|
|
83
|
+
const webhookSettings = this.webhookSettingsFor(dataArg.connectionId);
|
|
84
|
+
this.actionLog.append({
|
|
85
|
+
actionType: 'update',
|
|
86
|
+
entityType: 'connection',
|
|
87
|
+
entityId: dataArg.connectionId,
|
|
88
|
+
entityName: this.connectionManager.getConnection(dataArg.connectionId)?.name || dataArg.connectionId,
|
|
89
|
+
details: 'Rotated webhook secret — webhook is unverified until the new secret is set at the provider',
|
|
90
|
+
username: dataArg.identity.username,
|
|
91
|
+
});
|
|
92
|
+
return { webhookSettings };
|
|
93
|
+
}));
|
|
94
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('confirmWebhookSecret', async (dataArg) => {
|
|
95
|
+
await requireValidIdentity(this.opsServerRef.adminHandler, dataArg);
|
|
96
|
+
const result = await this.connectionManager.confirmWebhookSecret(dataArg.connectionId);
|
|
97
|
+
this.actionLog.append({
|
|
98
|
+
actionType: 'update',
|
|
99
|
+
entityType: 'connection',
|
|
100
|
+
entityId: dataArg.connectionId,
|
|
101
|
+
entityName: this.connectionManager.getConnection(dataArg.connectionId)?.name || dataArg.connectionId,
|
|
102
|
+
details: 'Confirmed the webhook secret is configured at the provider',
|
|
103
|
+
username: dataArg.identity.username,
|
|
104
|
+
});
|
|
105
|
+
return result;
|
|
106
|
+
}));
|
|
8
107
|
}
|
|
9
108
|
registerRoutes(typedserver) {
|
|
10
|
-
typedserver.addRoute(
|
|
109
|
+
typedserver.addRoute(webhookRoutePattern, 'POST', async (ctx) => {
|
|
11
110
|
const connectionId = ctx.params.connectionId;
|
|
12
|
-
//
|
|
13
|
-
const connection = this.
|
|
111
|
+
// The connection carries the secret, so it is resolved before any body work.
|
|
112
|
+
const connection = this.connectionManager.getConnection(connectionId);
|
|
14
113
|
if (!connection) {
|
|
15
|
-
return
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
114
|
+
return this.refuse('webhook-connection-unknown', connectionId);
|
|
115
|
+
}
|
|
116
|
+
// Everything that does not need the body is decided before buffering it.
|
|
117
|
+
const precondition = checkWebhookConnection(connection);
|
|
118
|
+
if (precondition) {
|
|
119
|
+
return this.refuse(precondition, connectionId, connection.name);
|
|
120
|
+
}
|
|
121
|
+
// The raw bytes are what the provider signed; parsing and re-serializing would
|
|
122
|
+
// change key order and whitespace and invalidate every genuine signature. The body
|
|
123
|
+
// is read through the bounded reader rather than ctx.arrayBuffer(), which buffers
|
|
124
|
+
// whatever an unauthenticated caller sends.
|
|
125
|
+
const body = await readBoundedWebhookBody({
|
|
126
|
+
headers: ctx.headers,
|
|
127
|
+
body: () => ctx.request.body,
|
|
128
|
+
});
|
|
129
|
+
if (!body.ok) {
|
|
130
|
+
return this.refuse(body.refusal, connectionId, connection.name);
|
|
131
|
+
}
|
|
132
|
+
const verification = verifyWebhookDelivery({
|
|
133
|
+
connection,
|
|
134
|
+
headers: ctx.headers,
|
|
135
|
+
rawBody: body.rawBody,
|
|
136
|
+
});
|
|
137
|
+
if (!verification.ok) {
|
|
138
|
+
return this.refuse(verification.refusal, connectionId, connection.name);
|
|
19
139
|
}
|
|
20
|
-
//
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
const provider = giteaEvent ? 'gitea' : gitlabEvent ? 'gitlab' : 'unknown';
|
|
25
|
-
logger.info(`Webhook received: ${provider}/${event} for connection ${connection.name} (${connectionId})`);
|
|
140
|
+
// The provider is the one we have a connection with, never the one the caller claims.
|
|
141
|
+
const provider = connection.providerType;
|
|
142
|
+
const event = ctx.headers.get(webhookEventHeaderFor(provider)) || 'unknown';
|
|
143
|
+
logger.info(`Webhook accepted: ${provider}/${event} for connection ${connection.name} (${connectionId})`);
|
|
26
144
|
// Broadcast to all connected frontends via TypedSocket
|
|
27
145
|
try {
|
|
28
146
|
const typedsocket = this.opsServerRef.server.typedserver.typedsocket;
|
|
@@ -52,4 +170,4 @@ export class WebhookHandler {
|
|
|
52
170
|
logger.info('WebhookHandler routes registered');
|
|
53
171
|
}
|
|
54
172
|
}
|
|
55
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
173
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2ViaG9vay5oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvb3Bzc2VydmVyL2hhbmRsZXJzL3dlYmhvb2suaGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGtCQUFrQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUUxQyxPQUFPLEtBQUssVUFBVSxNQUFNLGlDQUFpQyxDQUFDO0FBQzlELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQzVELE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIsc0JBQXNCLEVBQ3RCLHFCQUFxQixFQUNyQixxQkFBcUIsRUFDckIsc0JBQXNCLEdBRXZCLE1BQU0sbUNBQW1DLENBQUM7QUFFM0MsOENBQThDO0FBQzlDLE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLHdCQUF3QixDQUFDO0FBRTVELHlFQUF5RTtBQUN6RSxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLGVBQXVCLEVBQVUsRUFBRSxDQUNyRSxZQUFZLGVBQWUsRUFBRSxDQUFDO0FBRWhDOzs7OztHQUtHO0FBQ0gsTUFBTSxrQkFBa0IsR0FBb0M7SUFDMUQsNEJBQTRCLEVBQUUsR0FBRztJQUNqQywrQkFBK0IsRUFBRSxHQUFHO0lBQ3BDLHdCQUF3QixFQUFFLEdBQUc7SUFDN0IsMkJBQTJCLEVBQUUsR0FBRztJQUNoQyx3QkFBd0IsRUFBRSxHQUFHO0lBQzdCLHdCQUF3QixFQUFFLEdBQUc7SUFDN0IseUJBQXlCLEVBQUUsR0FBRztJQUM5QiwyQkFBMkIsRUFBRSxHQUFHO0lBQ2hDLDJCQUEyQixFQUFFLEdBQUc7Q0FDakMsQ0FBQztBQUVGLE1BQU0sT0FBTyxjQUFjO0lBR0w7SUFGYixXQUFXLEdBQUcsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBRTVELFlBQW9CLFlBQXVCO1FBQXZCLGlCQUFZLEdBQVosWUFBWSxDQUFXO1FBQ3pDLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDL0QsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVELElBQVksaUJBQWlCO1FBQzNCLE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsaUJBQWlCLENBQUM7SUFDMUQsQ0FBQztJQUVELElBQVksU0FBUztRQUNuQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQztJQUNsRCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssTUFBTSxDQUNaLFVBQTJCLEVBQzNCLGVBQXVCLEVBQ3ZCLGlCQUEwQjtRQUUxQixNQUFNLE1BQU0sR0FBRyxpQkFBaUI7WUFDOUIsQ0FBQyxDQUFDLGNBQWMsaUJBQWlCLEtBQUssZUFBZSxHQUFHO1lBQ3hELENBQUMsQ0FBQyxjQUFjLGVBQWUsRUFBRSxDQUFDO1FBQ3BDLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLFVBQVUsUUFBUSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzVELE9BQU8sSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFO1lBQ3pELE1BQU0sRUFBRSxrQkFBa0IsQ0FBQyxVQUFVLENBQUM7WUFDdEMsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFFO1NBQ2hELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxrQkFBa0IsQ0FDeEIsZUFBdUI7UUFFdkIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUN6RSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDaEIsTUFBTSxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsa0JBQWtCLENBQUMseUJBQXlCLGVBQWUsRUFBRSxDQUFDLENBQUM7UUFDaEcsQ0FBQztRQUNELE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGdCQUFnQixDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3BGLE9BQU87WUFDTCxZQUFZLEVBQUUsVUFBVSxDQUFDLEVBQUU7WUFDM0IsWUFBWSxFQUFFLFVBQVUsQ0FBQyxZQUFZO1lBQ3JDLFlBQVksRUFBRSxtQkFBbUIsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ2hELFVBQVUsRUFBRSxzQkFBc0IsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDO1lBQzNELE1BQU07WUFDTixNQUFNO1NBQ1AsQ0FBQztJQUNKLENBQUM7SUFFRDs7OztPQUlHO0lBQ0ssZ0JBQWdCO1FBQ3RCLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUM5QixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUNuQyxvQkFBb0IsRUFDcEIsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQ2hCLE1BQU0sb0JBQW9CLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDcEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxJQUFJLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7UUFDNUUsQ0FBQyxDQUNGLENBQ0YsQ0FBQztRQUVGLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUM5QixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUNuQyxxQkFBcUIsRUFDckIsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQ2hCLE1BQU0sb0JBQW9CLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDcEUsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsbUJBQW1CLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3ZFLE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDdEUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7Z0JBQ3BCLFVBQVUsRUFBRSxRQUFRO2dCQUNwQixVQUFVLEVBQUUsWUFBWTtnQkFDeEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxZQUFZO2dCQUM5QixVQUFVLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsSUFBSSxJQUFJLE9BQU8sQ0FBQyxZQUFZO2dCQUNwRyxPQUFPLEVBQUUsNEZBQTRGO2dCQUNyRyxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRO2FBQ3BDLENBQUMsQ0FBQztZQUNILE9BQU8sRUFBRSxlQUFlLEVBQUUsQ0FBQztRQUM3QixDQUFDLENBQ0YsQ0FDRixDQUFDO1FBRUYsSUFBSSxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQzlCLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQ25DLHNCQUFzQixFQUN0QixLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7WUFDaEIsTUFBTSxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNwRSxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDdkYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7Z0JBQ3BCLFVBQVUsRUFBRSxRQUFRO2dCQUNwQixVQUFVLEVBQUUsWUFBWTtnQkFDeEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxZQUFZO2dCQUM5QixVQUFVLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsSUFBSSxJQUFJLE9BQU8sQ0FBQyxZQUFZO2dCQUNwRyxPQUFPLEVBQUUsNERBQTREO2dCQUNyRSxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxRQUFRO2FBQ3BDLENBQUMsQ0FBQztZQUNILE9BQU8sTUFBTSxDQUFDO1FBQ2hCLENBQUMsQ0FDRixDQUNGLENBQUM7SUFDSixDQUFDO0lBRU0sY0FBYyxDQUFDLFdBQTRDO1FBQ2hFLFdBQVcsQ0FBQyxRQUFRLENBQUMsbUJBQW1CLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUM5RCxNQUFNLFlBQVksR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQztZQUU3Qyw2RUFBNkU7WUFDN0UsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUN0RSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7Z0JBQ2hCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyw0QkFBNEIsRUFBRSxZQUFZLENBQUMsQ0FBQztZQUNqRSxDQUFDO1lBRUQseUVBQXlFO1lBQ3pFLE1BQU0sWUFBWSxHQUFHLHNCQUFzQixDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3hELElBQUksWUFBWSxFQUFFLENBQUM7Z0JBQ2pCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsWUFBWSxFQUFFLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNsRSxDQUFDO1lBQ0QsK0VBQStFO1lBQy9FLG1GQUFtRjtZQUNuRixrRkFBa0Y7WUFDbEYsNENBQTRDO1lBQzVDLE1BQU0sSUFBSSxHQUFHLE1BQU0sc0JBQXNCLENBQUM7Z0JBQ3hDLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTztnQkFDcEIsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSTthQUM3QixDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRSxDQUFDO2dCQUNiLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbEUsQ0FBQztZQUVELE1BQU0sWUFBWSxHQUFHLHFCQUFxQixDQUFDO2dCQUN6QyxVQUFVO2dCQUNWLE9BQU8sRUFBRSxHQUFHLENBQUMsT0FBTztnQkFDcEIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO2FBQ3RCLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQ3JCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBUSxFQUFFLFlBQVksRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0UsQ0FBQztZQUVELHNGQUFzRjtZQUN0RixNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsWUFBWSxDQUFDO1lBQ3pDLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLHFCQUFxQixDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksU0FBUyxDQUFDO1lBRTVFLE1BQU0sQ0FBQyxJQUFJLENBQUMscUJBQXFCLFFBQVEsSUFBSSxLQUFLLG1CQUFtQixVQUFVLENBQUMsSUFBSSxLQUFLLFlBQVksR0FBRyxDQUFDLENBQUM7WUFFMUcsdURBQXVEO1lBQ3ZELElBQUksQ0FBQztnQkFDSCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDO2dCQUNyRSxJQUFJLFdBQVcsRUFBRSxDQUFDO29CQUNoQixNQUFNLFdBQVcsR0FBRyxNQUFNLFdBQVcsQ0FBQyw2QkFBNkIsQ0FBQyxlQUFlLENBQUMsQ0FBQztvQkFDckYsS0FBSyxNQUFNLElBQUksSUFBSSxXQUFXLEVBQUUsQ0FBQzt3QkFDL0IsTUFBTSxHQUFHLEdBQUcsV0FBVyxDQUFDLGtCQUFrQixDQUN4QyxxQkFBcUIsRUFDckIsSUFBSSxDQUNMLENBQUM7d0JBQ0YsR0FBRyxDQUFDLElBQUksQ0FBQzs0QkFDUCxZQUFZOzRCQUNaLFFBQVE7NEJBQ1IsS0FBSzs0QkFDTCxTQUFTLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRTt5QkFDdEIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQVEsRUFBRSxFQUFFOzRCQUNwQixNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixHQUFHLENBQUMsT0FBTyxJQUFJLEdBQUcsRUFBRSxDQUFDLENBQUM7d0JBQ2hFLENBQUMsQ0FBQyxDQUFDO29CQUNMLENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7WUFBQyxPQUFPLEdBQVEsRUFBRSxDQUFDO2dCQUNsQixNQUFNLENBQUMsSUFBSSxDQUFDLHNDQUFzQyxHQUFHLENBQUMsT0FBTyxJQUFJLEdBQUcsRUFBRSxDQUFDLENBQUM7WUFDMUUsQ0FBQztZQUVELE9BQU8sSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFO2dCQUNoRCxNQUFNLEVBQUUsR0FBRztnQkFDWCxPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUU7YUFDaEQsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7UUFFSCxNQUFNLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLENBQUM7SUFDbEQsQ0FBQztDQUNGIn0=
|