@serve.zone/dcrouter 17.7.0 → 17.8.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/deno.json +1 -1
- package/dist_serve/bundle.js +410 -410
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.d.ts +2 -0
- package/dist_ts/classes.dcrouter.js +23 -1
- package/dist_ts/config/classes.gateway-client-manager.js +3 -1
- package/dist_ts/db/documents/classes.cached.email.d.ts +16 -1
- package/dist_ts/db/documents/classes.cached.email.js +67 -4
- package/dist_ts/db/documents/classes.webpush-admission.doc.d.ts +19 -0
- package/dist_ts/db/documents/classes.webpush-admission.doc.js +124 -0
- package/dist_ts/db/documents/classes.webpush-binding.doc.d.ts +65 -0
- package/dist_ts/db/documents/classes.webpush-binding.doc.js +205 -0
- package/dist_ts/db/documents/classes.webpush-spool.doc.d.ts +44 -0
- package/dist_ts/db/documents/classes.webpush-spool.doc.js +277 -0
- package/dist_ts/db/documents/index.d.ts +3 -0
- package/dist_ts/db/documents/index.js +5 -1
- package/dist_ts/email/classes.accepted-email-spool.d.ts +5 -0
- package/dist_ts/email/classes.accepted-email-spool.js +31 -3
- package/dist_ts/email/classes.workapp-mail-manager.d.ts +5 -1
- package/dist_ts/email/classes.workapp-mail-manager.js +87 -12
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +3 -1
- package/dist_ts/opsserver/classes.opsserver.d.ts +2 -0
- package/dist_ts/opsserver/classes.opsserver.js +5 -1
- package/dist_ts/opsserver/handlers/email-ops.handler.js +5 -3
- package/dist_ts/opsserver/handlers/gatewayclient.handler.js +11 -5
- package/dist_ts/opsserver/handlers/index.d.ts +2 -0
- package/dist_ts/opsserver/handlers/index.js +3 -1
- package/dist_ts/opsserver/handlers/webpush-app.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/webpush-app.handler.js +66 -0
- package/dist_ts/opsserver/handlers/webpush-control.handler.d.ts +14 -0
- package/dist_ts/opsserver/handlers/webpush-control.handler.js +163 -0
- package/dist_ts/plugins.d.ts +5 -2
- package/dist_ts/plugins.js +6 -3
- package/dist_ts/webpush/classes.webpush-crypto.d.ts +38 -0
- package/dist_ts/webpush/classes.webpush-crypto.js +231 -0
- package/dist_ts/webpush/classes.webpush-manager.d.ts +153 -0
- package/dist_ts/webpush/classes.webpush-manager.js +2374 -0
- package/dist_ts/webpush/classes.webpush-transport.d.ts +45 -0
- package/dist_ts/webpush/classes.webpush-transport.js +161 -0
- package/dist_ts/webpush/helpers.webpush-endpoint.d.ts +21 -0
- package/dist_ts/webpush/helpers.webpush-endpoint.js +111 -0
- package/dist_ts/webpush/index.d.ts +4 -0
- package/dist_ts/webpush/index.js +5 -0
- package/dist_ts/webpush/webpush-indexes.d.ts +11 -0
- package/dist_ts/webpush/webpush-indexes.js +123 -0
- package/dist_ts_interfaces/data/route-management.d.ts +2 -0
- package/dist_ts_interfaces/data/route-management.js +1 -1
- package/dist_ts_migrations/index.js +221 -11
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/package.json +13 -9
- package/readme.md +27 -0
- package/third-party-notices.md +37 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +29 -0
- package/ts/config/classes.gateway-client-manager.ts +2 -0
- package/ts/db/documents/classes.cached.email.ts +58 -1
- package/ts/db/documents/classes.webpush-admission.doc.ts +48 -0
- package/ts/db/documents/classes.webpush-binding.doc.ts +147 -0
- package/ts/db/documents/classes.webpush-spool.doc.ts +136 -0
- package/ts/db/documents/index.ts +5 -0
- package/ts/email/classes.accepted-email-spool.ts +44 -2
- package/ts/email/classes.workapp-mail-manager.ts +97 -10
- package/ts/index.ts +3 -0
- package/ts/opsserver/classes.opsserver.ts +4 -0
- package/ts/opsserver/handlers/email-ops.handler.ts +4 -2
- package/ts/opsserver/handlers/gatewayclient.handler.ts +10 -3
- package/ts/opsserver/handlers/index.ts +2 -0
- package/ts/opsserver/handlers/webpush-app.handler.ts +105 -0
- package/ts/opsserver/handlers/webpush-control.handler.ts +257 -0
- package/ts/plugins.ts +6 -0
- package/ts/webpush/classes.webpush-crypto.ts +306 -0
- package/ts/webpush/classes.webpush-manager.ts +3173 -0
- package/ts/webpush/classes.webpush-transport.ts +241 -0
- package/ts/webpush/helpers.webpush-endpoint.ts +150 -0
- package/ts/webpush/index.ts +4 -0
- package/ts/webpush/webpush-indexes.ts +141 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/readme.plan.md +0 -22
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
export class WebPushAppHandler {
|
|
3
|
+
opsServerRef;
|
|
4
|
+
typedrouter = new plugins.typedrequest.TypedRouter();
|
|
5
|
+
constructor(opsServerRef) {
|
|
6
|
+
this.opsServerRef = opsServerRef;
|
|
7
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
8
|
+
this.registerHandlers();
|
|
9
|
+
}
|
|
10
|
+
registerHandlers() {
|
|
11
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getWebPushServiceStatus', async (dataArg) => {
|
|
12
|
+
const manager = this.opsServerRef.dcRouterRef.webPushManager;
|
|
13
|
+
if (!manager.isReady)
|
|
14
|
+
return manager.getUnavailableServiceStatus();
|
|
15
|
+
return await manager.getServiceStatus(dataArg.auth);
|
|
16
|
+
}));
|
|
17
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('enqueueWebPush', async (dataArg) => {
|
|
18
|
+
try {
|
|
19
|
+
return await this.opsServerRef.dcRouterRef.webPushManager.enqueue(dataArg.auth, {
|
|
20
|
+
idempotencyKey: dataArg.idempotencyKey,
|
|
21
|
+
subscriptionId: dataArg.subscriptionId,
|
|
22
|
+
subscription: dataArg.subscription,
|
|
23
|
+
vapidKeyId: dataArg.vapidKeyId,
|
|
24
|
+
payload: dataArg.payload,
|
|
25
|
+
ttlSeconds: dataArg.ttlSeconds,
|
|
26
|
+
urgency: dataArg.urgency,
|
|
27
|
+
collapseKey: dataArg.collapseKey,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
return {
|
|
32
|
+
accepted: false,
|
|
33
|
+
message: this.safeMessage(error),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}));
|
|
37
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('cancelWebPush', async (dataArg) => {
|
|
38
|
+
try {
|
|
39
|
+
const result = await this.opsServerRef.dcRouterRef.webPushManager.cancel(dataArg.auth, dataArg.target);
|
|
40
|
+
return {
|
|
41
|
+
success: true,
|
|
42
|
+
...result,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
return {
|
|
47
|
+
success: false,
|
|
48
|
+
cancelledCount: 0,
|
|
49
|
+
alreadyTerminalCount: 0,
|
|
50
|
+
message: this.safeMessage(error),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}));
|
|
54
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getWebPushDeliveryStatus', async (dataArg) => {
|
|
55
|
+
return {
|
|
56
|
+
delivery: await this.opsServerRef.dcRouterRef.webPushManager.getDeliveryStatus(dataArg.auth, dataArg.spoolItemId),
|
|
57
|
+
};
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
safeMessage(errorArg) {
|
|
61
|
+
return errorArg instanceof plugins.typedrequest.TypedResponseError
|
|
62
|
+
? errorArg.message
|
|
63
|
+
: 'Web Push delivery operation failed';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2VicHVzaC1hcHAuaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL29wc3NlcnZlci9oYW5kbGVycy93ZWJwdXNoLWFwcC5oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFHNUMsTUFBTSxPQUFPLGlCQUFpQjtJQUdRO0lBRjdCLFdBQVcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFNUQsWUFBb0MsWUFBdUI7UUFBdkIsaUJBQVksR0FBWixZQUFZLENBQVc7UUFDekQsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRU8sZ0JBQWdCO1FBQ3RCLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUM5QixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUduQyx5QkFBeUIsRUFDekIsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQ2hCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQztZQUM3RCxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU87Z0JBQUUsT0FBTyxPQUFPLENBQUMsMkJBQTJCLEVBQUUsQ0FBQztZQUNuRSxPQUFPLE1BQU0sT0FBTyxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0RCxDQUFDLENBQ0YsQ0FDRixDQUFDO1FBRUYsSUFBSSxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQzlCLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBR25DLGdCQUFnQixFQUNoQixLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7WUFDaEIsSUFBSSxDQUFDO2dCQUNILE9BQU8sTUFBTSxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUMvRCxPQUFPLENBQUMsSUFBSSxFQUNaO29CQUNFLGNBQWMsRUFBRSxPQUFPLENBQUMsY0FBYztvQkFDdEMsY0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjO29CQUN0QyxZQUFZLEVBQUUsT0FBTyxDQUFDLFlBQVk7b0JBQ2xDLFVBQVUsRUFBRSxPQUFPLENBQUMsVUFBVTtvQkFDOUIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPO29CQUN4QixVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVU7b0JBQzlCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztvQkFDeEIsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXO2lCQUNqQyxDQUNGLENBQUM7WUFDSixDQUFDO1lBQUMsT0FBTyxLQUFjLEVBQUUsQ0FBQztnQkFDeEIsT0FBTztvQkFDTCxRQUFRLEVBQUUsS0FBSztvQkFDZixPQUFPLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUM7aUJBQ2pDLENBQUM7WUFDSixDQUFDO1FBQ0gsQ0FBQyxDQUNGLENBQ0YsQ0FBQztRQUVGLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUM5QixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUduQyxlQUFlLEVBQ2YsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQ2hCLElBQUksQ0FBQztnQkFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQ3RFLE9BQU8sQ0FBQyxJQUFJLEVBQ1osT0FBTyxDQUFDLE1BQU0sQ0FDZixDQUFDO2dCQUNGLE9BQU87b0JBQ0wsT0FBTyxFQUFFLElBQUk7b0JBQ2IsR0FBRyxNQUFNO2lCQUNWLENBQUM7WUFDSixDQUFDO1lBQUMsT0FBTyxLQUFjLEVBQUUsQ0FBQztnQkFDeEIsT0FBTztvQkFDTCxPQUFPLEVBQUUsS0FBSztvQkFDZCxjQUFjLEVBQUUsQ0FBQztvQkFDakIsb0JBQW9CLEVBQUUsQ0FBQztvQkFDdkIsT0FBTyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDO2lCQUNqQyxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUMsQ0FDRixDQUNGLENBQUM7UUFFRixJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FDOUIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FHbkMsMEJBQTBCLEVBQzFCLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtZQUNoQixPQUFPO2dCQUNMLFFBQVEsRUFBRSxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxpQkFBaUIsQ0FDNUUsT0FBTyxDQUFDLElBQUksRUFDWixPQUFPLENBQUMsV0FBVyxDQUNwQjthQUNGLENBQUM7UUFDSixDQUFDLENBQ0YsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVPLFdBQVcsQ0FBQyxRQUFpQjtRQUNuQyxPQUFPLFFBQVEsWUFBWSxPQUFPLENBQUMsWUFBWSxDQUFDLGtCQUFrQjtZQUNoRSxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU87WUFDbEIsQ0FBQyxDQUFDLG9DQUFvQyxDQUFDO0lBQzNDLENBQUM7Q0FDRiJ9
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
export declare class WebPushControlHandler {
|
|
4
|
+
private readonly opsServerRef;
|
|
5
|
+
typedrouter: plugins.typedrequest.TypedRouter<import("@api.global/typedrequest-interfaces").ITypedRequest>;
|
|
6
|
+
constructor(opsServerRef: OpsServer);
|
|
7
|
+
private registerHandlers;
|
|
8
|
+
private requireControlAuth;
|
|
9
|
+
private scopeOwnerFilter;
|
|
10
|
+
private assertExactOwner;
|
|
11
|
+
private requireAuthorizedBinding;
|
|
12
|
+
private bindingOwner;
|
|
13
|
+
private safeMessage;
|
|
14
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { requireGatewayMachineAuth, } from '../helpers/gateway-client-auth.js';
|
|
3
|
+
export class WebPushControlHandler {
|
|
4
|
+
opsServerRef;
|
|
5
|
+
typedrouter = new plugins.typedrequest.TypedRouter();
|
|
6
|
+
constructor(opsServerRef) {
|
|
7
|
+
this.opsServerRef = opsServerRef;
|
|
8
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
9
|
+
this.registerHandlers();
|
|
10
|
+
}
|
|
11
|
+
registerHandlers() {
|
|
12
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('listWebPushBindings', async (dataArg) => {
|
|
13
|
+
const auth = await this.requireControlAuth(dataArg.auth, 'readWebPush');
|
|
14
|
+
const owner = this.scopeOwnerFilter(auth, dataArg.owner);
|
|
15
|
+
const manager = this.opsServerRef.dcRouterRef.webPushManager;
|
|
16
|
+
return {
|
|
17
|
+
bindings: await manager.listBindings(owner),
|
|
18
|
+
};
|
|
19
|
+
}));
|
|
20
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('syncWebPushBinding', async (dataArg) => {
|
|
21
|
+
try {
|
|
22
|
+
const request = dataArg;
|
|
23
|
+
const auth = await this.requireControlAuth(dataArg.auth, 'manageWebPush');
|
|
24
|
+
this.assertExactOwner(auth, dataArg.binding.owner);
|
|
25
|
+
const result = await this.opsServerRef.dcRouterRef.webPushManager.syncBinding(dataArg.binding, request.controller, auth.userId);
|
|
26
|
+
return {
|
|
27
|
+
success: true,
|
|
28
|
+
binding: result.binding,
|
|
29
|
+
credential: result.credential,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return {
|
|
34
|
+
success: false,
|
|
35
|
+
message: this.safeMessage(error),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}));
|
|
39
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('deleteWebPushBinding', async (dataArg) => {
|
|
40
|
+
try {
|
|
41
|
+
const request = dataArg;
|
|
42
|
+
const auth = await this.requireControlAuth(dataArg.auth, 'manageWebPush');
|
|
43
|
+
this.assertExactOwner(auth, request.owner);
|
|
44
|
+
return {
|
|
45
|
+
success: await this.opsServerRef.dcRouterRef.webPushManager.deleteBinding({
|
|
46
|
+
...(request.id !== undefined ? { id: request.id } : {}),
|
|
47
|
+
owner: request.owner,
|
|
48
|
+
controller: request.controller,
|
|
49
|
+
}, auth.userId),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
message: this.safeMessage(error),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}));
|
|
59
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('rotateWebPushCredential', async (dataArg) => {
|
|
60
|
+
try {
|
|
61
|
+
const auth = await this.requireControlAuth(dataArg.auth, 'manageWebPush');
|
|
62
|
+
const manager = this.opsServerRef.dcRouterRef.webPushManager;
|
|
63
|
+
const binding = await manager.getBindingByCredentialId(dataArg.credentialId);
|
|
64
|
+
if (!binding) {
|
|
65
|
+
throw new plugins.typedrequest.TypedResponseError('Web Push binding not found');
|
|
66
|
+
}
|
|
67
|
+
this.assertExactOwner(auth, this.bindingOwner(binding));
|
|
68
|
+
return {
|
|
69
|
+
success: true,
|
|
70
|
+
credential: await manager.rotateCredential(dataArg.credentialId),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
return {
|
|
75
|
+
success: false,
|
|
76
|
+
message: this.safeMessage(error),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}));
|
|
80
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('rotateWebPushVapidKey', async (dataArg) => {
|
|
81
|
+
try {
|
|
82
|
+
const auth = await this.requireControlAuth(dataArg.auth, 'manageWebPush');
|
|
83
|
+
const binding = await this.requireAuthorizedBinding(auth, dataArg.bindingId);
|
|
84
|
+
return {
|
|
85
|
+
success: true,
|
|
86
|
+
binding: await this.opsServerRef.dcRouterRef.webPushManager.rotateVapidKey(binding.id),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
return {
|
|
91
|
+
success: false,
|
|
92
|
+
message: this.safeMessage(error),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
async requireControlAuth(authArg, capabilityArg) {
|
|
98
|
+
const auth = await requireGatewayMachineAuth(this.opsServerRef, authArg, capabilityArg === 'manageWebPush'
|
|
99
|
+
? 'gateway-clients:write'
|
|
100
|
+
: 'gateway-clients:read');
|
|
101
|
+
if (auth.isAdmin)
|
|
102
|
+
return auth;
|
|
103
|
+
if (auth.policy?.role !== 'gatewayClient'
|
|
104
|
+
|| auth.policy.capabilities?.[capabilityArg] !== true) {
|
|
105
|
+
throw new plugins.typedrequest.TypedResponseError(`token capability missing: ${capabilityArg}`);
|
|
106
|
+
}
|
|
107
|
+
return auth;
|
|
108
|
+
}
|
|
109
|
+
scopeOwnerFilter(authArg, requestedArg) {
|
|
110
|
+
if (authArg.isAdmin)
|
|
111
|
+
return requestedArg || {};
|
|
112
|
+
const gatewayClient = authArg.gatewayClient;
|
|
113
|
+
if (!gatewayClient) {
|
|
114
|
+
throw new plugins.typedrequest.TypedResponseError('gateway-client credential required');
|
|
115
|
+
}
|
|
116
|
+
if (requestedArg?.gatewayClientType !== undefined
|
|
117
|
+
&& requestedArg.gatewayClientType !== gatewayClient.type) {
|
|
118
|
+
throw new plugins.typedrequest.TypedResponseError('gateway-client credential cannot access another Web Push owner');
|
|
119
|
+
}
|
|
120
|
+
if (requestedArg?.gatewayClientId !== undefined
|
|
121
|
+
&& requestedArg.gatewayClientId !== gatewayClient.id) {
|
|
122
|
+
throw new plugins.typedrequest.TypedResponseError('gateway-client credential cannot access another Web Push owner');
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
gatewayClientType: gatewayClient.type,
|
|
126
|
+
gatewayClientId: gatewayClient.id,
|
|
127
|
+
...(requestedArg?.appInstanceId !== undefined
|
|
128
|
+
? { appInstanceId: requestedArg.appInstanceId }
|
|
129
|
+
: {}),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
assertExactOwner(authArg, ownerArg) {
|
|
133
|
+
if (authArg.isAdmin)
|
|
134
|
+
return;
|
|
135
|
+
const gatewayClient = authArg.gatewayClient;
|
|
136
|
+
if (!gatewayClient
|
|
137
|
+
|| ownerArg.gatewayClientType !== gatewayClient.type
|
|
138
|
+
|| ownerArg.gatewayClientId !== gatewayClient.id) {
|
|
139
|
+
throw new plugins.typedrequest.TypedResponseError('gateway-client credential cannot access another Web Push owner');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async requireAuthorizedBinding(authArg, bindingIdArg) {
|
|
143
|
+
const binding = await this.opsServerRef.dcRouterRef.webPushManager.getBindingById(bindingIdArg);
|
|
144
|
+
if (!binding) {
|
|
145
|
+
throw new plugins.typedrequest.TypedResponseError('Web Push binding not found');
|
|
146
|
+
}
|
|
147
|
+
this.assertExactOwner(authArg, this.bindingOwner(binding));
|
|
148
|
+
return binding;
|
|
149
|
+
}
|
|
150
|
+
bindingOwner(bindingArg) {
|
|
151
|
+
return {
|
|
152
|
+
gatewayClientType: bindingArg.ownerGatewayClientType,
|
|
153
|
+
gatewayClientId: bindingArg.ownerGatewayClientId,
|
|
154
|
+
appInstanceId: bindingArg.ownerAppInstanceId,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
safeMessage(errorArg) {
|
|
158
|
+
return errorArg instanceof plugins.typedrequest.TypedResponseError
|
|
159
|
+
? errorArg.message
|
|
160
|
+
: 'Web Push control operation failed';
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2VicHVzaC1jb250cm9sLmhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9vcHNzZXJ2ZXIvaGFuZGxlcnMvd2VicHVzaC1jb250cm9sLmhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUk1QyxPQUFPLEVBQ0wseUJBQXlCLEdBRTFCLE1BQU0sbUNBQW1DLENBQUM7QUFJM0MsTUFBTSxPQUFPLHFCQUFxQjtJQUdJO0lBRjdCLFdBQVcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFNUQsWUFBb0MsWUFBdUI7UUFBdkIsaUJBQVksR0FBWixZQUFZLENBQVc7UUFDekQsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRU8sZ0JBQWdCO1FBQ3RCLElBQUksQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUM5QixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUduQyxxQkFBcUIsRUFDckIsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQ2hCLE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDeEUsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDekQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDO1lBQzdELE9BQU87Z0JBQ0wsUUFBUSxFQUFFLE1BQU0sT0FBTyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUM7YUFD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
|
package/dist_ts/plugins.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import * as dns from 'node:dns';
|
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
3
|
import * as crypto from 'node:crypto';
|
|
4
4
|
import * as http from 'node:http';
|
|
5
|
+
import * as https from 'node:https';
|
|
5
6
|
import * as net from 'node:net';
|
|
6
7
|
import * as buffer from 'node:buffer';
|
|
7
8
|
import * as os from 'node:os';
|
|
@@ -9,7 +10,7 @@ import * as path from 'node:path';
|
|
|
9
10
|
import * as tls from 'node:tls';
|
|
10
11
|
import * as util from 'node:util';
|
|
11
12
|
import * as url from 'node:url';
|
|
12
|
-
export { dns, fs, crypto, http, net, buffer, os, path, tls, util, url, };
|
|
13
|
+
export { dns, fs, crypto, http, https, net, buffer, os, path, tls, util, url, };
|
|
13
14
|
import * as servezoneInterfaces from '@serve.zone/interfaces';
|
|
14
15
|
import * as remoteingress from '@serve.zone/remoteingress';
|
|
15
16
|
export { servezoneInterfaces, remoteingress, };
|
|
@@ -50,5 +51,7 @@ import * as cloudflare from '@apiclient.xyz/cloudflare';
|
|
|
50
51
|
export { cloudflare, };
|
|
51
52
|
import * as tsclass from '@tsclass/tsclass';
|
|
52
53
|
export { tsclass, };
|
|
54
|
+
import ipaddr from 'ipaddr.js';
|
|
53
55
|
import * as uuid from 'uuid';
|
|
54
|
-
|
|
56
|
+
import webpush from 'web-push';
|
|
57
|
+
export { ipaddr, uuid, webpush, };
|
package/dist_ts/plugins.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as dns from 'node:dns';
|
|
|
3
3
|
import * as fs from 'node:fs';
|
|
4
4
|
import * as crypto from 'node:crypto';
|
|
5
5
|
import * as http from 'node:http';
|
|
6
|
+
import * as https from 'node:https';
|
|
6
7
|
import * as net from 'node:net';
|
|
7
8
|
import * as buffer from 'node:buffer';
|
|
8
9
|
import * as os from 'node:os';
|
|
@@ -10,7 +11,7 @@ import * as path from 'node:path';
|
|
|
10
11
|
import * as tls from 'node:tls';
|
|
11
12
|
import * as util from 'node:util';
|
|
12
13
|
import * as url from 'node:url';
|
|
13
|
-
export { dns, fs, crypto, http, net, buffer, os, path, tls, util, url, };
|
|
14
|
+
export { dns, fs, crypto, http, https, net, buffer, os, path, tls, util, url, };
|
|
14
15
|
// @serve.zone scope
|
|
15
16
|
import * as servezoneInterfaces from '@serve.zone/interfaces';
|
|
16
17
|
import * as remoteingress from '@serve.zone/remoteingress';
|
|
@@ -57,6 +58,8 @@ export { cloudflare, };
|
|
|
57
58
|
import * as tsclass from '@tsclass/tsclass';
|
|
58
59
|
export { tsclass, };
|
|
59
60
|
// third party
|
|
61
|
+
import ipaddr from 'ipaddr.js';
|
|
60
62
|
import * as uuid from 'uuid';
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
import webpush from 'web-push';
|
|
64
|
+
export { ipaddr, uuid, webpush, };
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsY0FBYztBQUNkLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxLQUFLLE1BQU0sWUFBWSxDQUFDO0FBQ3BDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxNQUFNLE1BQU0sYUFBYSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQzlCLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBQ2hDLE9BQU8sS0FBSyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sS0FBSyxHQUFHLE1BQU0sVUFBVSxDQUFDO0FBRWhDLE9BQU8sRUFDTCxHQUFHLEVBQ0gsRUFBRSxFQUNGLE1BQU0sRUFDTixJQUFJLEVBQ0osS0FBSyxFQUNMLEdBQUcsRUFDSCxNQUFNLEVBQ04sRUFBRSxFQUNGLElBQUksRUFDSixHQUFHLEVBQ0gsSUFBSSxFQUNKLEdBQUcsR0FDSixDQUFBO0FBRUQsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxtQkFBbUIsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEtBQUssYUFBYSxNQUFNLDJCQUEyQixDQUFDO0FBRTNELE9BQU8sRUFDTCxtQkFBbUIsRUFDbkIsYUFBYSxHQUNkLENBQUE7QUFFRCxvQkFBb0I7QUFDcEIsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUN6RCxPQUFPLEtBQUssV0FBVyxNQUFNLHlC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
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface IWebPushKeyRing {
|
|
2
|
+
currentKeyId: string;
|
|
3
|
+
keys: ReadonlyMap<string, Buffer>;
|
|
4
|
+
}
|
|
5
|
+
export interface IWebPushEncryptedEnvelope {
|
|
6
|
+
version: 1;
|
|
7
|
+
algorithm: 'aes-256-gcm';
|
|
8
|
+
keyId: string;
|
|
9
|
+
nonce: string;
|
|
10
|
+
ciphertext: string;
|
|
11
|
+
tag: string;
|
|
12
|
+
}
|
|
13
|
+
export interface IWebPushAadContext {
|
|
14
|
+
gatewayClientId: string;
|
|
15
|
+
appInstanceId: string;
|
|
16
|
+
bindingId: string;
|
|
17
|
+
documentType: string;
|
|
18
|
+
documentId: string;
|
|
19
|
+
}
|
|
20
|
+
export type TWebPushHmacDomain = 'credential' | 'idempotency-key' | 'request' | 'endpoint' | 'topic';
|
|
21
|
+
export declare function parseWebPushKeyRing(rawValueArg: unknown, labelArg: string): IWebPushKeyRing;
|
|
22
|
+
export declare function assertDistinctWebPushKeyRings(encryptionRingArg: IWebPushKeyRing, hmacRingArg: IWebPushKeyRing): void;
|
|
23
|
+
export declare function buildWebPushAad(contextArg: IWebPushAadContext): Buffer;
|
|
24
|
+
export declare function canonicalJson(valueArg: unknown): string;
|
|
25
|
+
export declare class WebPushCrypto {
|
|
26
|
+
private readonly encryptionRing;
|
|
27
|
+
private readonly hmacRing;
|
|
28
|
+
constructor(encryptionRing: IWebPushKeyRing, hmacRing: IWebPushKeyRing);
|
|
29
|
+
get currentEncryptionKeyId(): string;
|
|
30
|
+
get currentHmacKeyId(): string;
|
|
31
|
+
encryptJson(valueArg: unknown, aadContextArg: IWebPushAadContext): IWebPushEncryptedEnvelope;
|
|
32
|
+
decryptJson<T>(envelopeArg: IWebPushEncryptedEnvelope, aadContextArg: IWebPushAadContext): T;
|
|
33
|
+
hmac(domainArg: TWebPushHmacDomain, valueArg: string, keyIdArg?: string): {
|
|
34
|
+
keyId: string;
|
|
35
|
+
digest: string;
|
|
36
|
+
};
|
|
37
|
+
verifyHmac(domainArg: TWebPushHmacDomain, valueArg: string, keyIdArg: string, expectedDigestArg: string): boolean;
|
|
38
|
+
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
const KEY_ID_PATTERN = /^[A-Za-z0-9._-]{1,64}$/;
|
|
3
|
+
const BASE64URL_KEY_PATTERN = /^[A-Za-z0-9_-]{43}$/;
|
|
4
|
+
const BASE64URL_VALUE_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
5
|
+
const KEY_RING_LIMIT = 8;
|
|
6
|
+
const AAD_SCHEMA_VERSION = 1;
|
|
7
|
+
function requirePlainObject(valueArg, labelArg) {
|
|
8
|
+
if (valueArg === null
|
|
9
|
+
|| typeof valueArg !== 'object'
|
|
10
|
+
|| Array.isArray(valueArg)
|
|
11
|
+
|| Object.getPrototypeOf(valueArg) !== Object.prototype) {
|
|
12
|
+
throw new Error(`${labelArg} must be a plain object`);
|
|
13
|
+
}
|
|
14
|
+
return valueArg;
|
|
15
|
+
}
|
|
16
|
+
function decodeBase64UrlExact(valueArg, lengthArg, labelArg) {
|
|
17
|
+
if (typeof valueArg !== 'string' || !BASE64URL_VALUE_PATTERN.test(valueArg)) {
|
|
18
|
+
throw new Error(`${labelArg} must be unpadded base64url`);
|
|
19
|
+
}
|
|
20
|
+
const decoded = Buffer.from(valueArg, 'base64url');
|
|
21
|
+
if (decoded.length !== lengthArg || decoded.toString('base64url') !== valueArg) {
|
|
22
|
+
throw new Error(`${labelArg} has an invalid encoded length`);
|
|
23
|
+
}
|
|
24
|
+
return decoded;
|
|
25
|
+
}
|
|
26
|
+
function parseKeyRingSource(rawValueArg, labelArg) {
|
|
27
|
+
if (typeof rawValueArg === 'string') {
|
|
28
|
+
const trimmed = rawValueArg.trim();
|
|
29
|
+
if (!trimmed) {
|
|
30
|
+
throw new Error(`${labelArg} is empty`);
|
|
31
|
+
}
|
|
32
|
+
const jsonText = trimmed.startsWith('base64Object:')
|
|
33
|
+
? Buffer.from(trimmed.slice('base64Object:'.length), 'base64').toString('utf8')
|
|
34
|
+
: trimmed;
|
|
35
|
+
try {
|
|
36
|
+
return requirePlainObject(JSON.parse(jsonText), labelArg);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (error.message.startsWith(`${labelArg} `))
|
|
40
|
+
throw error;
|
|
41
|
+
throw new Error(`${labelArg} must be valid JSON`, { cause: error });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return requirePlainObject(rawValueArg, labelArg);
|
|
45
|
+
}
|
|
46
|
+
export function parseWebPushKeyRing(rawValueArg, labelArg) {
|
|
47
|
+
const source = parseKeyRingSource(rawValueArg, labelArg);
|
|
48
|
+
const currentKeyId = source.currentKeyId;
|
|
49
|
+
if (typeof currentKeyId !== 'string' || !KEY_ID_PATTERN.test(currentKeyId)) {
|
|
50
|
+
throw new Error(`${labelArg}.currentKeyId is invalid`);
|
|
51
|
+
}
|
|
52
|
+
const rawKeys = requirePlainObject(source.keys, `${labelArg}.keys`);
|
|
53
|
+
const entries = Object.entries(rawKeys);
|
|
54
|
+
if (entries.length === 0 || entries.length > KEY_RING_LIMIT) {
|
|
55
|
+
throw new Error(`${labelArg}.keys must contain 1 to ${KEY_RING_LIMIT} keys`);
|
|
56
|
+
}
|
|
57
|
+
const keys = new Map();
|
|
58
|
+
const fingerprints = new Set();
|
|
59
|
+
for (const [keyId, encodedKey] of entries) {
|
|
60
|
+
if (!KEY_ID_PATTERN.test(keyId)) {
|
|
61
|
+
throw new Error(`${labelArg}.keys contains an invalid key id`);
|
|
62
|
+
}
|
|
63
|
+
if (typeof encodedKey !== 'string' || !BASE64URL_KEY_PATTERN.test(encodedKey)) {
|
|
64
|
+
throw new Error(`${labelArg}.keys.${keyId} must be a 32-byte unpadded base64url key`);
|
|
65
|
+
}
|
|
66
|
+
const key = decodeBase64UrlExact(encodedKey, 32, `${labelArg}.keys.${keyId}`);
|
|
67
|
+
const fingerprint = key.toString('hex');
|
|
68
|
+
if (fingerprints.has(fingerprint)) {
|
|
69
|
+
throw new Error(`${labelArg}.keys must not contain duplicate key material`);
|
|
70
|
+
}
|
|
71
|
+
fingerprints.add(fingerprint);
|
|
72
|
+
keys.set(keyId, key);
|
|
73
|
+
}
|
|
74
|
+
if (!keys.has(currentKeyId)) {
|
|
75
|
+
throw new Error(`${labelArg}.currentKeyId does not name a configured key`);
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
currentKeyId,
|
|
79
|
+
keys,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export function assertDistinctWebPushKeyRings(encryptionRingArg, hmacRingArg) {
|
|
83
|
+
const encryptionFingerprints = new Set([...encryptionRingArg.keys.values()].map((keyArg) => keyArg.toString('hex')));
|
|
84
|
+
if ([...hmacRingArg.keys.values()]
|
|
85
|
+
.some((keyArg) => encryptionFingerprints.has(keyArg.toString('hex')))) {
|
|
86
|
+
throw new Error('Web Push encryption and HMAC key rings must use distinct key material');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export function buildWebPushAad(contextArg) {
|
|
90
|
+
for (const [name, value] of Object.entries(contextArg)) {
|
|
91
|
+
if (typeof value !== 'string' || !value.trim()) {
|
|
92
|
+
throw new Error(`Web Push AAD ${name} is missing`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return Buffer.from(canonicalJson({
|
|
96
|
+
schemaVersion: AAD_SCHEMA_VERSION,
|
|
97
|
+
gatewayClientId: contextArg.gatewayClientId,
|
|
98
|
+
appInstanceId: contextArg.appInstanceId,
|
|
99
|
+
bindingId: contextArg.bindingId,
|
|
100
|
+
documentType: contextArg.documentType,
|
|
101
|
+
documentId: contextArg.documentId,
|
|
102
|
+
}), 'utf8');
|
|
103
|
+
}
|
|
104
|
+
function canonicalize(valueArg) {
|
|
105
|
+
if (valueArg === null
|
|
106
|
+
|| typeof valueArg === 'string'
|
|
107
|
+
|| typeof valueArg === 'boolean') {
|
|
108
|
+
return valueArg;
|
|
109
|
+
}
|
|
110
|
+
if (typeof valueArg === 'number') {
|
|
111
|
+
if (!Number.isFinite(valueArg))
|
|
112
|
+
throw new Error('Canonical JSON does not support non-finite numbers');
|
|
113
|
+
return valueArg;
|
|
114
|
+
}
|
|
115
|
+
if (Array.isArray(valueArg)) {
|
|
116
|
+
return valueArg.map((entryArg) => canonicalize(entryArg));
|
|
117
|
+
}
|
|
118
|
+
const value = requirePlainObject(valueArg, 'Canonical JSON value');
|
|
119
|
+
const result = {};
|
|
120
|
+
for (const key of Object.keys(value).sort()) {
|
|
121
|
+
if (value[key] === undefined) {
|
|
122
|
+
throw new Error('Canonical JSON does not support undefined values');
|
|
123
|
+
}
|
|
124
|
+
result[key] = canonicalize(value[key]);
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
export function canonicalJson(valueArg) {
|
|
129
|
+
return JSON.stringify(canonicalize(valueArg));
|
|
130
|
+
}
|
|
131
|
+
export class WebPushCrypto {
|
|
132
|
+
encryptionRing;
|
|
133
|
+
hmacRing;
|
|
134
|
+
constructor(encryptionRing, hmacRing) {
|
|
135
|
+
this.encryptionRing = encryptionRing;
|
|
136
|
+
this.hmacRing = hmacRing;
|
|
137
|
+
assertDistinctWebPushKeyRings(encryptionRing, hmacRing);
|
|
138
|
+
}
|
|
139
|
+
get currentEncryptionKeyId() {
|
|
140
|
+
return this.encryptionRing.currentKeyId;
|
|
141
|
+
}
|
|
142
|
+
get currentHmacKeyId() {
|
|
143
|
+
return this.hmacRing.currentKeyId;
|
|
144
|
+
}
|
|
145
|
+
encryptJson(valueArg, aadContextArg) {
|
|
146
|
+
const keyId = this.encryptionRing.currentKeyId;
|
|
147
|
+
const key = this.encryptionRing.keys.get(keyId);
|
|
148
|
+
if (!key)
|
|
149
|
+
throw new Error('Current Web Push encryption key is unavailable');
|
|
150
|
+
const nonce = plugins.crypto.randomBytes(12);
|
|
151
|
+
const cipher = plugins.crypto.createCipheriv('aes-256-gcm', key, nonce);
|
|
152
|
+
cipher.setAAD(buildWebPushAad(aadContextArg));
|
|
153
|
+
const ciphertext = Buffer.concat([
|
|
154
|
+
cipher.update(canonicalJson(valueArg), 'utf8'),
|
|
155
|
+
cipher.final(),
|
|
156
|
+
]);
|
|
157
|
+
const tag = cipher.getAuthTag();
|
|
158
|
+
return {
|
|
159
|
+
version: 1,
|
|
160
|
+
algorithm: 'aes-256-gcm',
|
|
161
|
+
keyId,
|
|
162
|
+
nonce: nonce.toString('base64url'),
|
|
163
|
+
ciphertext: ciphertext.toString('base64url'),
|
|
164
|
+
tag: tag.toString('base64url'),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
decryptJson(envelopeArg, aadContextArg) {
|
|
168
|
+
if (envelopeArg?.version !== 1
|
|
169
|
+
|| envelopeArg.algorithm !== 'aes-256-gcm'
|
|
170
|
+
|| typeof envelopeArg.keyId !== 'string'
|
|
171
|
+
|| !KEY_ID_PATTERN.test(envelopeArg.keyId)) {
|
|
172
|
+
throw new Error('Web Push encrypted envelope is malformed');
|
|
173
|
+
}
|
|
174
|
+
const key = this.encryptionRing.keys.get(envelopeArg.keyId);
|
|
175
|
+
if (!key)
|
|
176
|
+
throw new Error('Web Push encrypted envelope references an unavailable key');
|
|
177
|
+
const nonce = decodeBase64UrlExact(envelopeArg.nonce, 12, 'Web Push envelope nonce');
|
|
178
|
+
const tag = decodeBase64UrlExact(envelopeArg.tag, 16, 'Web Push envelope tag');
|
|
179
|
+
if (typeof envelopeArg.ciphertext !== 'string'
|
|
180
|
+
|| !envelopeArg.ciphertext
|
|
181
|
+
|| !BASE64URL_VALUE_PATTERN.test(envelopeArg.ciphertext)) {
|
|
182
|
+
throw new Error('Web Push envelope ciphertext is malformed');
|
|
183
|
+
}
|
|
184
|
+
const ciphertext = Buffer.from(envelopeArg.ciphertext, 'base64url');
|
|
185
|
+
if (ciphertext.toString('base64url') !== envelopeArg.ciphertext) {
|
|
186
|
+
throw new Error('Web Push envelope ciphertext is malformed');
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
const decipher = plugins.crypto.createDecipheriv('aes-256-gcm', key, nonce);
|
|
190
|
+
decipher.setAAD(buildWebPushAad(aadContextArg));
|
|
191
|
+
decipher.setAuthTag(tag);
|
|
192
|
+
const plaintext = Buffer.concat([
|
|
193
|
+
decipher.update(ciphertext),
|
|
194
|
+
decipher.final(),
|
|
195
|
+
]).toString('utf8');
|
|
196
|
+
return JSON.parse(plaintext);
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
throw new Error('Web Push encrypted envelope authentication failed', { cause: error });
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
hmac(domainArg, valueArg, keyIdArg = this.hmacRing.currentKeyId) {
|
|
203
|
+
const key = this.hmacRing.keys.get(keyIdArg);
|
|
204
|
+
if (!key)
|
|
205
|
+
throw new Error('Web Push HMAC key is unavailable');
|
|
206
|
+
const digest = plugins.crypto
|
|
207
|
+
.createHmac('sha256', key)
|
|
208
|
+
.update(`dcrouter:webpush:v1:${domainArg}\0`, 'utf8')
|
|
209
|
+
.update(valueArg, 'utf8')
|
|
210
|
+
.digest('base64url');
|
|
211
|
+
return {
|
|
212
|
+
keyId: keyIdArg,
|
|
213
|
+
digest,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
verifyHmac(domainArg, valueArg, keyIdArg, expectedDigestArg) {
|
|
217
|
+
let actualDigest;
|
|
218
|
+
try {
|
|
219
|
+
actualDigest = this.hmac(domainArg, valueArg, keyIdArg).digest;
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
const actual = Buffer.from(actualDigest, 'base64url');
|
|
225
|
+
const expected = Buffer.from(expectedDigestArg, 'base64url');
|
|
226
|
+
return actual.length === expected.length
|
|
227
|
+
&& actual.length > 0
|
|
228
|
+
&& plugins.crypto.timingSafeEqual(actual, expected);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy53ZWJwdXNoLWNyeXB0by5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL3dlYnB1c2gvY2xhc3Nlcy53ZWJwdXNoLWNyeXB0by50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQStCekMsTUFBTSxjQUFjLEdBQUcsd0JBQXdCLENBQUM7QUFDaEQsTUFBTSxxQkFBcUIsR0FBRyxxQkFBcUIsQ0FBQztBQUNwRCxNQUFNLHVCQUF1QixHQUFHLGtCQUFrQixDQUFDO0FBQ25ELE1BQU0sY0FBYyxHQUFHLENBQUMsQ0FBQztBQUN6QixNQUFNLGtCQUFrQixHQUFHLENBQUMsQ0FBQztBQUU3QixTQUFTLGtCQUFrQixDQUN6QixRQUFpQixFQUNqQixRQUFnQjtJQUVoQixJQUNFLFFBQVEsS0FBSyxJQUFJO1dBQ2QsT0FBTyxRQUFRLEtBQUssUUFBUTtXQUM1QixLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztXQUN2QixNQUFNLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxLQUFLLE1BQU0sQ0FBQyxTQUFTLEVBQ3ZELENBQUM7UUFDRCxNQUFNLElBQUksS0FBSyxDQUFDLEdBQUcsUUFBUSx5QkFBeUIsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFDRCxPQUFPLFFBQW1DLENBQUM7QUFDN0MsQ0FBQztBQUVELFNBQVMsb0JBQW9CLENBQzNCLFFBQWlCLEVBQ2pCLFNBQWlCLEVBQ2pCLFFBQWdCO0lBRWhCLElBQUksT0FBTyxRQUFRLEtBQUssUUFBUSxJQUFJLENBQUMsdUJBQXVCLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDNUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxHQUFHLFFBQVEsNkJBQTZCLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBQ0QsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFD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
|