@treatwell/moleculer-essentials 1.0.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/LICENSE +21 -0
- package/README.md +1 -0
- package/dist/context-factory-BWO3xPWE.d.cts +520 -0
- package/dist/context-factory-BWO3xPWE.d.mts +520 -0
- package/dist/index-82e1CXJX.cjs +11 -0
- package/dist/index-BV1ZqQrU.mjs +351 -0
- package/dist/index-DNJWwcZu.mjs +8 -0
- package/dist/index-rZl77S1z.cjs +375 -0
- package/dist/index.cjs +1570 -0
- package/dist/index.d.cts +373 -0
- package/dist/index.d.mts +373 -0
- package/dist/index.mjs +1535 -0
- package/dist/mixins/database.mixin.cjs +1673 -0
- package/dist/mixins/database.mixin.d.cts +958 -0
- package/dist/mixins/database.mixin.d.mts +958 -0
- package/dist/mixins/database.mixin.mjs +1645 -0
- package/dist/mixins/encryptor.mixin.cjs +84 -0
- package/dist/mixins/encryptor.mixin.d.cts +31 -0
- package/dist/mixins/encryptor.mixin.d.mts +31 -0
- package/dist/mixins/encryptor.mixin.mjs +81 -0
- package/dist/mixins/global-store.mixin.cjs +56 -0
- package/dist/mixins/global-store.mixin.d.cts +39 -0
- package/dist/mixins/global-store.mixin.d.mts +39 -0
- package/dist/mixins/global-store.mixin.mjs +54 -0
- package/dist/mixins/jwt.mixin.cjs +118 -0
- package/dist/mixins/jwt.mixin.d.cts +43 -0
- package/dist/mixins/jwt.mixin.d.mts +43 -0
- package/dist/mixins/jwt.mixin.mjs +115 -0
- package/dist/mixins/queue.mixin.cjs +420 -0
- package/dist/mixins/queue.mixin.d.cts +150 -0
- package/dist/mixins/queue.mixin.d.mts +150 -0
- package/dist/mixins/queue.mixin.mjs +414 -0
- package/dist/mixins/redis.mixin.cjs +50 -0
- package/dist/mixins/redis.mixin.d.cts +27 -0
- package/dist/mixins/redis.mixin.d.mts +27 -0
- package/dist/mixins/redis.mixin.mjs +48 -0
- package/dist/mixins/redlock.mixin.cjs +76 -0
- package/dist/mixins/redlock.mixin.d.cts +30 -0
- package/dist/mixins/redlock.mixin.d.mts +30 -0
- package/dist/mixins/redlock.mixin.mjs +74 -0
- package/package.json +181 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var clientNode = require('@aws-crypto/client-node');
|
|
4
|
+
var index = require('../index-82e1CXJX.cjs');
|
|
5
|
+
|
|
6
|
+
const kCmm = Symbol("AWS KMS CMM");
|
|
7
|
+
const kClient = Symbol("AWS KMS client");
|
|
8
|
+
function EncryptorMixin({
|
|
9
|
+
keyId,
|
|
10
|
+
cacheMaxMessagesEncrypted,
|
|
11
|
+
cacheMaxAge,
|
|
12
|
+
cacheCapacity,
|
|
13
|
+
cacheMaxBytesEncrypted,
|
|
14
|
+
localMasterKey = process.env.LOCAL_KMS_MASTER_KEY
|
|
15
|
+
}) {
|
|
16
|
+
return index.wrapMixin({
|
|
17
|
+
methods: {
|
|
18
|
+
getEncryptorClient() {
|
|
19
|
+
return this[kClient];
|
|
20
|
+
},
|
|
21
|
+
/**
|
|
22
|
+
* Get a keyring for a specific key ID
|
|
23
|
+
* This keyring is wrapped in a caching manager in order to reduce KMS calls.
|
|
24
|
+
*
|
|
25
|
+
* More info: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/data-key-caching.html
|
|
26
|
+
*/
|
|
27
|
+
getEncryptorCmm() {
|
|
28
|
+
let cmm = this[kCmm];
|
|
29
|
+
if (!cmm) {
|
|
30
|
+
let keyring;
|
|
31
|
+
if (keyId) {
|
|
32
|
+
keyring = new clientNode.KmsKeyringNode({ generatorKeyId: keyId });
|
|
33
|
+
} else if (localMasterKey) {
|
|
34
|
+
const buffer = Buffer.from(localMasterKey, "base64");
|
|
35
|
+
const unencryptedMasterKey = Buffer.alloc(
|
|
36
|
+
buffer.byteLength,
|
|
37
|
+
buffer
|
|
38
|
+
);
|
|
39
|
+
keyring = new clientNode.RawAesKeyringNode({
|
|
40
|
+
keyName: "aes-local-keyring",
|
|
41
|
+
keyNamespace: "aes-local-keyring-namespace",
|
|
42
|
+
wrappingSuite: clientNode.RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING,
|
|
43
|
+
unencryptedMasterKey
|
|
44
|
+
});
|
|
45
|
+
} else {
|
|
46
|
+
throw new Error("Missing KMS key ID in EncryptorMixin");
|
|
47
|
+
}
|
|
48
|
+
cmm = new clientNode.NodeCachingMaterialsManager({
|
|
49
|
+
backingMaterials: keyring,
|
|
50
|
+
cache: clientNode.getLocalCryptographicMaterialsCache(cacheCapacity),
|
|
51
|
+
maxAge: cacheMaxAge,
|
|
52
|
+
maxMessagesEncrypted: cacheMaxMessagesEncrypted || 1,
|
|
53
|
+
maxBytesEncrypted: cacheMaxBytesEncrypted
|
|
54
|
+
});
|
|
55
|
+
this[kCmm] = cmm;
|
|
56
|
+
}
|
|
57
|
+
return cmm;
|
|
58
|
+
},
|
|
59
|
+
async encrypt(plainData) {
|
|
60
|
+
const { encrypt } = this.getEncryptorClient();
|
|
61
|
+
const { result } = await encrypt(this.getEncryptorCmm(), plainData, {});
|
|
62
|
+
return result;
|
|
63
|
+
},
|
|
64
|
+
async decrypt(encryptedData) {
|
|
65
|
+
const { decrypt } = this.getEncryptorClient();
|
|
66
|
+
const { plaintext } = await decrypt(
|
|
67
|
+
this.getEncryptorCmm(),
|
|
68
|
+
encryptedData,
|
|
69
|
+
{}
|
|
70
|
+
);
|
|
71
|
+
return plaintext;
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
created() {
|
|
75
|
+
this[kClient] = clientNode.buildClient({
|
|
76
|
+
commitmentPolicy: clientNode.CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
|
|
77
|
+
maxEncryptedDataKeys: false
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
exports.EncryptorMixin = EncryptorMixin;
|
|
84
|
+
exports.kCmm = kCmm;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { a as CustomServiceSchema } from '../context-factory-BWO3xPWE.cjs';
|
|
2
|
+
import { buildClient, NodeCachingMaterialsManager } from '@aws-crypto/client-node';
|
|
3
|
+
import 'moleculer';
|
|
4
|
+
import 'bson';
|
|
5
|
+
import 'zod/v4';
|
|
6
|
+
import 'ajv/dist/2019.js';
|
|
7
|
+
|
|
8
|
+
declare const kCmm: unique symbol;
|
|
9
|
+
type EncryptorMixinSettings = {
|
|
10
|
+
keyId: string | undefined;
|
|
11
|
+
cacheMaxAge: number;
|
|
12
|
+
cacheCapacity: number;
|
|
13
|
+
cacheMaxBytesEncrypted?: number;
|
|
14
|
+
cacheMaxMessagesEncrypted?: number;
|
|
15
|
+
localMasterKey?: string;
|
|
16
|
+
};
|
|
17
|
+
declare function EncryptorMixin({ keyId, cacheMaxMessagesEncrypted, cacheMaxAge, cacheCapacity, cacheMaxBytesEncrypted, localMasterKey, }: EncryptorMixinSettings): Partial<CustomServiceSchema<unknown, {
|
|
18
|
+
getEncryptorClient(): ReturnType<typeof buildClient>;
|
|
19
|
+
/**
|
|
20
|
+
* Get a keyring for a specific key ID
|
|
21
|
+
* This keyring is wrapped in a caching manager in order to reduce KMS calls.
|
|
22
|
+
*
|
|
23
|
+
* More info: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/data-key-caching.html
|
|
24
|
+
*/
|
|
25
|
+
getEncryptorCmm(): NodeCachingMaterialsManager;
|
|
26
|
+
encrypt(plainData: Buffer | string): Promise<Buffer>;
|
|
27
|
+
decrypt(encryptedData: Uint8Array | string): Promise<Buffer>;
|
|
28
|
+
}, unknown, unknown>>;
|
|
29
|
+
|
|
30
|
+
export { EncryptorMixin, kCmm };
|
|
31
|
+
export type { EncryptorMixinSettings };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { a as CustomServiceSchema } from '../context-factory-BWO3xPWE.mjs';
|
|
2
|
+
import { buildClient, NodeCachingMaterialsManager } from '@aws-crypto/client-node';
|
|
3
|
+
import 'moleculer';
|
|
4
|
+
import 'bson';
|
|
5
|
+
import 'zod/v4';
|
|
6
|
+
import 'ajv/dist/2019.js';
|
|
7
|
+
|
|
8
|
+
declare const kCmm: unique symbol;
|
|
9
|
+
type EncryptorMixinSettings = {
|
|
10
|
+
keyId: string | undefined;
|
|
11
|
+
cacheMaxAge: number;
|
|
12
|
+
cacheCapacity: number;
|
|
13
|
+
cacheMaxBytesEncrypted?: number;
|
|
14
|
+
cacheMaxMessagesEncrypted?: number;
|
|
15
|
+
localMasterKey?: string;
|
|
16
|
+
};
|
|
17
|
+
declare function EncryptorMixin({ keyId, cacheMaxMessagesEncrypted, cacheMaxAge, cacheCapacity, cacheMaxBytesEncrypted, localMasterKey, }: EncryptorMixinSettings): Partial<CustomServiceSchema<unknown, {
|
|
18
|
+
getEncryptorClient(): ReturnType<typeof buildClient>;
|
|
19
|
+
/**
|
|
20
|
+
* Get a keyring for a specific key ID
|
|
21
|
+
* This keyring is wrapped in a caching manager in order to reduce KMS calls.
|
|
22
|
+
*
|
|
23
|
+
* More info: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/data-key-caching.html
|
|
24
|
+
*/
|
|
25
|
+
getEncryptorCmm(): NodeCachingMaterialsManager;
|
|
26
|
+
encrypt(plainData: Buffer | string): Promise<Buffer>;
|
|
27
|
+
decrypt(encryptedData: Uint8Array | string): Promise<Buffer>;
|
|
28
|
+
}, unknown, unknown>>;
|
|
29
|
+
|
|
30
|
+
export { EncryptorMixin, kCmm };
|
|
31
|
+
export type { EncryptorMixinSettings };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { buildClient, CommitmentPolicy, KmsKeyringNode, RawAesKeyringNode, RawAesWrappingSuiteIdentifier, NodeCachingMaterialsManager, getLocalCryptographicMaterialsCache } from '@aws-crypto/client-node';
|
|
2
|
+
import { w as wrapMixin } from '../index-DNJWwcZu.mjs';
|
|
3
|
+
|
|
4
|
+
const kCmm = Symbol("AWS KMS CMM");
|
|
5
|
+
const kClient = Symbol("AWS KMS client");
|
|
6
|
+
function EncryptorMixin({
|
|
7
|
+
keyId,
|
|
8
|
+
cacheMaxMessagesEncrypted,
|
|
9
|
+
cacheMaxAge,
|
|
10
|
+
cacheCapacity,
|
|
11
|
+
cacheMaxBytesEncrypted,
|
|
12
|
+
localMasterKey = process.env.LOCAL_KMS_MASTER_KEY
|
|
13
|
+
}) {
|
|
14
|
+
return wrapMixin({
|
|
15
|
+
methods: {
|
|
16
|
+
getEncryptorClient() {
|
|
17
|
+
return this[kClient];
|
|
18
|
+
},
|
|
19
|
+
/**
|
|
20
|
+
* Get a keyring for a specific key ID
|
|
21
|
+
* This keyring is wrapped in a caching manager in order to reduce KMS calls.
|
|
22
|
+
*
|
|
23
|
+
* More info: https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/data-key-caching.html
|
|
24
|
+
*/
|
|
25
|
+
getEncryptorCmm() {
|
|
26
|
+
let cmm = this[kCmm];
|
|
27
|
+
if (!cmm) {
|
|
28
|
+
let keyring;
|
|
29
|
+
if (keyId) {
|
|
30
|
+
keyring = new KmsKeyringNode({ generatorKeyId: keyId });
|
|
31
|
+
} else if (localMasterKey) {
|
|
32
|
+
const buffer = Buffer.from(localMasterKey, "base64");
|
|
33
|
+
const unencryptedMasterKey = Buffer.alloc(
|
|
34
|
+
buffer.byteLength,
|
|
35
|
+
buffer
|
|
36
|
+
);
|
|
37
|
+
keyring = new RawAesKeyringNode({
|
|
38
|
+
keyName: "aes-local-keyring",
|
|
39
|
+
keyNamespace: "aes-local-keyring-namespace",
|
|
40
|
+
wrappingSuite: RawAesWrappingSuiteIdentifier.AES256_GCM_IV12_TAG16_NO_PADDING,
|
|
41
|
+
unencryptedMasterKey
|
|
42
|
+
});
|
|
43
|
+
} else {
|
|
44
|
+
throw new Error("Missing KMS key ID in EncryptorMixin");
|
|
45
|
+
}
|
|
46
|
+
cmm = new NodeCachingMaterialsManager({
|
|
47
|
+
backingMaterials: keyring,
|
|
48
|
+
cache: getLocalCryptographicMaterialsCache(cacheCapacity),
|
|
49
|
+
maxAge: cacheMaxAge,
|
|
50
|
+
maxMessagesEncrypted: cacheMaxMessagesEncrypted || 1,
|
|
51
|
+
maxBytesEncrypted: cacheMaxBytesEncrypted
|
|
52
|
+
});
|
|
53
|
+
this[kCmm] = cmm;
|
|
54
|
+
}
|
|
55
|
+
return cmm;
|
|
56
|
+
},
|
|
57
|
+
async encrypt(plainData) {
|
|
58
|
+
const { encrypt } = this.getEncryptorClient();
|
|
59
|
+
const { result } = await encrypt(this.getEncryptorCmm(), plainData, {});
|
|
60
|
+
return result;
|
|
61
|
+
},
|
|
62
|
+
async decrypt(encryptedData) {
|
|
63
|
+
const { decrypt } = this.getEncryptorClient();
|
|
64
|
+
const { plaintext } = await decrypt(
|
|
65
|
+
this.getEncryptorCmm(),
|
|
66
|
+
encryptedData,
|
|
67
|
+
{}
|
|
68
|
+
);
|
|
69
|
+
return plaintext;
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
created() {
|
|
73
|
+
this[kClient] = buildClient({
|
|
74
|
+
commitmentPolicy: CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT,
|
|
75
|
+
maxEncryptedDataKeys: false
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export { EncryptorMixin, kCmm };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var index = require('../index-82e1CXJX.cjs');
|
|
4
|
+
|
|
5
|
+
function GlobalStoreMixin() {
|
|
6
|
+
return index.wrapMixin({
|
|
7
|
+
methods: {
|
|
8
|
+
/**
|
|
9
|
+
* Global store to share the adapters between services on the same broker.
|
|
10
|
+
*/
|
|
11
|
+
getStore(storeName) {
|
|
12
|
+
const symbol = Symbol.for(storeName);
|
|
13
|
+
if (!this.broker[symbol]) {
|
|
14
|
+
this.broker[symbol] = /* @__PURE__ */ new Map();
|
|
15
|
+
}
|
|
16
|
+
return this.broker[symbol];
|
|
17
|
+
},
|
|
18
|
+
/**
|
|
19
|
+
* Return the client from the global store
|
|
20
|
+
* and add the adapter to the list of adapters.
|
|
21
|
+
*/
|
|
22
|
+
getFromStore(storeName, key) {
|
|
23
|
+
const res = this.getStore(storeName).get(key);
|
|
24
|
+
if (res) {
|
|
25
|
+
res.services.add(this);
|
|
26
|
+
}
|
|
27
|
+
return res ? res.client : null;
|
|
28
|
+
},
|
|
29
|
+
/**
|
|
30
|
+
* Service MUST call this when they deregister.
|
|
31
|
+
* This function will close the client if it's the last adapter.
|
|
32
|
+
*/
|
|
33
|
+
async removeServiceFromStore(storeName, key) {
|
|
34
|
+
const res = this.getStore(storeName).get(key);
|
|
35
|
+
if (res) {
|
|
36
|
+
res.services.delete(this);
|
|
37
|
+
if (res.services.size > 0) {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
this.getStore(storeName).delete(key);
|
|
41
|
+
await res.onClose();
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
},
|
|
45
|
+
/**
|
|
46
|
+
* Set the client in global store.
|
|
47
|
+
*/
|
|
48
|
+
setClientToStore(storeName, key, client, onClose) {
|
|
49
|
+
const services = (/* @__PURE__ */ new Set()).add(this);
|
|
50
|
+
this.getStore(storeName).set(key, { client, services, onClose });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
exports.GlobalStoreMixin = GlobalStoreMixin;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { a as CustomServiceSchema } from '../context-factory-BWO3xPWE.cjs';
|
|
2
|
+
import 'moleculer';
|
|
3
|
+
import 'bson';
|
|
4
|
+
import 'zod/v4';
|
|
5
|
+
import 'ajv/dist/2019.js';
|
|
6
|
+
|
|
7
|
+
type Wrapper<T> = {
|
|
8
|
+
services: Set<unknown>;
|
|
9
|
+
client: T;
|
|
10
|
+
onClose: () => Promise<void> | void;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Global store mixin to share instances between services on the same broker.
|
|
14
|
+
* To reuse an instance, it must match both:
|
|
15
|
+
* - `storeName`, the name of the store (e.g. `mongodb`, `redis`, etc.)
|
|
16
|
+
* - `key`, the key of the instance (e.g. `mongodb://localhost:27017`)
|
|
17
|
+
*/
|
|
18
|
+
declare function GlobalStoreMixin<T = unknown>(): Partial<CustomServiceSchema<unknown, {
|
|
19
|
+
/**
|
|
20
|
+
* Global store to share the adapters between services on the same broker.
|
|
21
|
+
*/
|
|
22
|
+
getStore(storeName: string): Map<string, Wrapper<T>>;
|
|
23
|
+
/**
|
|
24
|
+
* Return the client from the global store
|
|
25
|
+
* and add the adapter to the list of adapters.
|
|
26
|
+
*/
|
|
27
|
+
getFromStore(storeName: string, key: string): null | T;
|
|
28
|
+
/**
|
|
29
|
+
* Service MUST call this when they deregister.
|
|
30
|
+
* This function will close the client if it's the last adapter.
|
|
31
|
+
*/
|
|
32
|
+
removeServiceFromStore(storeName: string, key: string): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Set the client in global store.
|
|
35
|
+
*/
|
|
36
|
+
setClientToStore(storeName: string, key: string, client: T, onClose: Wrapper<T>["onClose"]): void;
|
|
37
|
+
}, unknown, unknown>>;
|
|
38
|
+
|
|
39
|
+
export { GlobalStoreMixin };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { a as CustomServiceSchema } from '../context-factory-BWO3xPWE.mjs';
|
|
2
|
+
import 'moleculer';
|
|
3
|
+
import 'bson';
|
|
4
|
+
import 'zod/v4';
|
|
5
|
+
import 'ajv/dist/2019.js';
|
|
6
|
+
|
|
7
|
+
type Wrapper<T> = {
|
|
8
|
+
services: Set<unknown>;
|
|
9
|
+
client: T;
|
|
10
|
+
onClose: () => Promise<void> | void;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Global store mixin to share instances between services on the same broker.
|
|
14
|
+
* To reuse an instance, it must match both:
|
|
15
|
+
* - `storeName`, the name of the store (e.g. `mongodb`, `redis`, etc.)
|
|
16
|
+
* - `key`, the key of the instance (e.g. `mongodb://localhost:27017`)
|
|
17
|
+
*/
|
|
18
|
+
declare function GlobalStoreMixin<T = unknown>(): Partial<CustomServiceSchema<unknown, {
|
|
19
|
+
/**
|
|
20
|
+
* Global store to share the adapters between services on the same broker.
|
|
21
|
+
*/
|
|
22
|
+
getStore(storeName: string): Map<string, Wrapper<T>>;
|
|
23
|
+
/**
|
|
24
|
+
* Return the client from the global store
|
|
25
|
+
* and add the adapter to the list of adapters.
|
|
26
|
+
*/
|
|
27
|
+
getFromStore(storeName: string, key: string): null | T;
|
|
28
|
+
/**
|
|
29
|
+
* Service MUST call this when they deregister.
|
|
30
|
+
* This function will close the client if it's the last adapter.
|
|
31
|
+
*/
|
|
32
|
+
removeServiceFromStore(storeName: string, key: string): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Set the client in global store.
|
|
35
|
+
*/
|
|
36
|
+
setClientToStore(storeName: string, key: string, client: T, onClose: Wrapper<T>["onClose"]): void;
|
|
37
|
+
}, unknown, unknown>>;
|
|
38
|
+
|
|
39
|
+
export { GlobalStoreMixin };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { w as wrapMixin } from '../index-DNJWwcZu.mjs';
|
|
2
|
+
|
|
3
|
+
function GlobalStoreMixin() {
|
|
4
|
+
return wrapMixin({
|
|
5
|
+
methods: {
|
|
6
|
+
/**
|
|
7
|
+
* Global store to share the adapters between services on the same broker.
|
|
8
|
+
*/
|
|
9
|
+
getStore(storeName) {
|
|
10
|
+
const symbol = Symbol.for(storeName);
|
|
11
|
+
if (!this.broker[symbol]) {
|
|
12
|
+
this.broker[symbol] = /* @__PURE__ */ new Map();
|
|
13
|
+
}
|
|
14
|
+
return this.broker[symbol];
|
|
15
|
+
},
|
|
16
|
+
/**
|
|
17
|
+
* Return the client from the global store
|
|
18
|
+
* and add the adapter to the list of adapters.
|
|
19
|
+
*/
|
|
20
|
+
getFromStore(storeName, key) {
|
|
21
|
+
const res = this.getStore(storeName).get(key);
|
|
22
|
+
if (res) {
|
|
23
|
+
res.services.add(this);
|
|
24
|
+
}
|
|
25
|
+
return res ? res.client : null;
|
|
26
|
+
},
|
|
27
|
+
/**
|
|
28
|
+
* Service MUST call this when they deregister.
|
|
29
|
+
* This function will close the client if it's the last adapter.
|
|
30
|
+
*/
|
|
31
|
+
async removeServiceFromStore(storeName, key) {
|
|
32
|
+
const res = this.getStore(storeName).get(key);
|
|
33
|
+
if (res) {
|
|
34
|
+
res.services.delete(this);
|
|
35
|
+
if (res.services.size > 0) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
this.getStore(storeName).delete(key);
|
|
39
|
+
await res.onClose();
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
},
|
|
43
|
+
/**
|
|
44
|
+
* Set the client in global store.
|
|
45
|
+
*/
|
|
46
|
+
setClientToStore(storeName, key, client, onClose) {
|
|
47
|
+
const services = (/* @__PURE__ */ new Set()).add(this);
|
|
48
|
+
this.getStore(storeName).set(key, { client, services, onClose });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export { GlobalStoreMixin };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var jsonwebtoken = require('jsonwebtoken');
|
|
4
|
+
var jwksRsa = require('jwks-rsa');
|
|
5
|
+
var moleculer = require('moleculer');
|
|
6
|
+
var index = require('../index-82e1CXJX.cjs');
|
|
7
|
+
|
|
8
|
+
function JwtSignerMixin(opts) {
|
|
9
|
+
const { privateKey, signOptions, renewBefore, disableAction } = opts;
|
|
10
|
+
let jwt = null;
|
|
11
|
+
let expiryDate = null;
|
|
12
|
+
return index.wrapMixin({
|
|
13
|
+
methods: {
|
|
14
|
+
generateJwt(payload = {}) {
|
|
15
|
+
const options = {
|
|
16
|
+
algorithm: "ES512",
|
|
17
|
+
notBefore: "-2s",
|
|
18
|
+
...signOptions
|
|
19
|
+
};
|
|
20
|
+
return new Promise(
|
|
21
|
+
(resolve, reject) => jsonwebtoken.sign(
|
|
22
|
+
payload,
|
|
23
|
+
privateKey,
|
|
24
|
+
options,
|
|
25
|
+
(err, token) => err || !token ? reject(err) : resolve(token)
|
|
26
|
+
)
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
actions: {
|
|
31
|
+
getToken: disableAction ? false : {
|
|
32
|
+
visibility: "public",
|
|
33
|
+
params: {
|
|
34
|
+
type: "object",
|
|
35
|
+
additionalProperties: false,
|
|
36
|
+
required: [],
|
|
37
|
+
properties: {}
|
|
38
|
+
},
|
|
39
|
+
async handler() {
|
|
40
|
+
if (renewBefore && jwt && expiryDate && expiryDate - Date.now() > renewBefore) {
|
|
41
|
+
return jwt;
|
|
42
|
+
}
|
|
43
|
+
jwt = await this.generateJwt();
|
|
44
|
+
if (typeof signOptions.expiresIn === "number") {
|
|
45
|
+
expiryDate = Date.now() + signOptions.expiresIn * 1e3;
|
|
46
|
+
}
|
|
47
|
+
return jwt;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
function JwtVerifierMixin(opts) {
|
|
54
|
+
const { jwksOptions, validClaim } = opts;
|
|
55
|
+
const jwksClient = new jwksRsa.JwksClient(jwksOptions);
|
|
56
|
+
return index.wrapMixin({
|
|
57
|
+
methods: {
|
|
58
|
+
getJwksClient() {
|
|
59
|
+
return jwksClient;
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* Used with jsonwebtoken verify function. Retrieves the signing public key
|
|
63
|
+
* from the kid defined in the JWT header.
|
|
64
|
+
*/
|
|
65
|
+
async getVerifyPublicKey(header, callback) {
|
|
66
|
+
try {
|
|
67
|
+
const key = await this.getJwksClient().getSigningKey(header.kid);
|
|
68
|
+
callback(null, key.getPublicKey());
|
|
69
|
+
} catch (err) {
|
|
70
|
+
callback(err);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* Will validate the JWT token signature but also some claims like the issuer.
|
|
75
|
+
*/
|
|
76
|
+
verifyJwt(token) {
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
jsonwebtoken.verify(
|
|
79
|
+
token,
|
|
80
|
+
(header, callback) => this.getVerifyPublicKey(header, callback),
|
|
81
|
+
validClaim,
|
|
82
|
+
(err) => err ? reject(err) : resolve()
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
async verifyAuthorizationHeader(ctx, value) {
|
|
87
|
+
if (!value || typeof value !== "string" || !value.startsWith("Bearer ")) {
|
|
88
|
+
throw new moleculer.Errors.MoleculerError(
|
|
89
|
+
"Incorrect bearer format authorization",
|
|
90
|
+
401,
|
|
91
|
+
"Unauthorized"
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
const token = value.slice(7);
|
|
95
|
+
if (!token) {
|
|
96
|
+
throw new moleculer.Errors.MoleculerError(
|
|
97
|
+
"Incorrect token",
|
|
98
|
+
401,
|
|
99
|
+
"Unauthorized"
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
await this.verifyJwt(token);
|
|
104
|
+
} catch (err) {
|
|
105
|
+
ctx.logger.warn("Unable to verify JWT", { err });
|
|
106
|
+
throw new moleculer.Errors.MoleculerError(
|
|
107
|
+
"Unable to verify JWT",
|
|
108
|
+
401,
|
|
109
|
+
"Unauthorized"
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
exports.JwtSignerMixin = JwtSignerMixin;
|
|
118
|
+
exports.JwtVerifierMixin = JwtVerifierMixin;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { a as CustomServiceSchema } from '../context-factory-BWO3xPWE.cjs';
|
|
2
|
+
import { SignOptions, PrivateKey, VerifyOptions, JwtHeader, SigningKeyCallback } from 'jsonwebtoken';
|
|
3
|
+
import { Options, JwksClient } from 'jwks-rsa';
|
|
4
|
+
import { Context } from 'moleculer';
|
|
5
|
+
import 'bson';
|
|
6
|
+
import 'zod/v4';
|
|
7
|
+
import 'ajv/dist/2019.js';
|
|
8
|
+
|
|
9
|
+
type JwtSignerMixinSettings = {
|
|
10
|
+
signOptions: SignOptions;
|
|
11
|
+
privateKey: PrivateKey;
|
|
12
|
+
/**
|
|
13
|
+
* Set to false to disable caching of the JWT token.
|
|
14
|
+
*/
|
|
15
|
+
renewBefore: number | false;
|
|
16
|
+
/**
|
|
17
|
+
* Set to true to disable the getToken action.
|
|
18
|
+
*/
|
|
19
|
+
disableAction?: boolean;
|
|
20
|
+
};
|
|
21
|
+
declare function JwtSignerMixin(opts: JwtSignerMixinSettings): Partial<CustomServiceSchema<unknown, {
|
|
22
|
+
generateJwt(payload?: string | Buffer | object): Promise<string>;
|
|
23
|
+
}, unknown, unknown>>;
|
|
24
|
+
type JwtVerifierMixinSettings = {
|
|
25
|
+
jwksOptions: Options;
|
|
26
|
+
validClaim: VerifyOptions;
|
|
27
|
+
};
|
|
28
|
+
declare function JwtVerifierMixin(opts: JwtVerifierMixinSettings): Partial<CustomServiceSchema<unknown, {
|
|
29
|
+
getJwksClient(): JwksClient;
|
|
30
|
+
/**
|
|
31
|
+
* Used with jsonwebtoken verify function. Retrieves the signing public key
|
|
32
|
+
* from the kid defined in the JWT header.
|
|
33
|
+
*/
|
|
34
|
+
getVerifyPublicKey(header: JwtHeader, callback: SigningKeyCallback): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Will validate the JWT token signature but also some claims like the issuer.
|
|
37
|
+
*/
|
|
38
|
+
verifyJwt(token: string): Promise<void>;
|
|
39
|
+
verifyAuthorizationHeader(ctx: Context, value: string | undefined): Promise<void>;
|
|
40
|
+
}, unknown, unknown>>;
|
|
41
|
+
|
|
42
|
+
export { JwtSignerMixin, JwtVerifierMixin };
|
|
43
|
+
export type { JwtSignerMixinSettings, JwtVerifierMixinSettings };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { a as CustomServiceSchema } from '../context-factory-BWO3xPWE.mjs';
|
|
2
|
+
import { SignOptions, PrivateKey, VerifyOptions, JwtHeader, SigningKeyCallback } from 'jsonwebtoken';
|
|
3
|
+
import { Options, JwksClient } from 'jwks-rsa';
|
|
4
|
+
import { Context } from 'moleculer';
|
|
5
|
+
import 'bson';
|
|
6
|
+
import 'zod/v4';
|
|
7
|
+
import 'ajv/dist/2019.js';
|
|
8
|
+
|
|
9
|
+
type JwtSignerMixinSettings = {
|
|
10
|
+
signOptions: SignOptions;
|
|
11
|
+
privateKey: PrivateKey;
|
|
12
|
+
/**
|
|
13
|
+
* Set to false to disable caching of the JWT token.
|
|
14
|
+
*/
|
|
15
|
+
renewBefore: number | false;
|
|
16
|
+
/**
|
|
17
|
+
* Set to true to disable the getToken action.
|
|
18
|
+
*/
|
|
19
|
+
disableAction?: boolean;
|
|
20
|
+
};
|
|
21
|
+
declare function JwtSignerMixin(opts: JwtSignerMixinSettings): Partial<CustomServiceSchema<unknown, {
|
|
22
|
+
generateJwt(payload?: string | Buffer | object): Promise<string>;
|
|
23
|
+
}, unknown, unknown>>;
|
|
24
|
+
type JwtVerifierMixinSettings = {
|
|
25
|
+
jwksOptions: Options;
|
|
26
|
+
validClaim: VerifyOptions;
|
|
27
|
+
};
|
|
28
|
+
declare function JwtVerifierMixin(opts: JwtVerifierMixinSettings): Partial<CustomServiceSchema<unknown, {
|
|
29
|
+
getJwksClient(): JwksClient;
|
|
30
|
+
/**
|
|
31
|
+
* Used with jsonwebtoken verify function. Retrieves the signing public key
|
|
32
|
+
* from the kid defined in the JWT header.
|
|
33
|
+
*/
|
|
34
|
+
getVerifyPublicKey(header: JwtHeader, callback: SigningKeyCallback): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Will validate the JWT token signature but also some claims like the issuer.
|
|
37
|
+
*/
|
|
38
|
+
verifyJwt(token: string): Promise<void>;
|
|
39
|
+
verifyAuthorizationHeader(ctx: Context, value: string | undefined): Promise<void>;
|
|
40
|
+
}, unknown, unknown>>;
|
|
41
|
+
|
|
42
|
+
export { JwtSignerMixin, JwtVerifierMixin };
|
|
43
|
+
export type { JwtSignerMixinSettings, JwtVerifierMixinSettings };
|