@velocitycareerlabs/aws-clients 1.24.0-dev-build.183959a2c → 1.24.0-dev-build.1bc10e07c
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/package.json +6 -14
- package/src/aws-factory.js +85 -0
- package/src/document-storage.js +7 -27
- package/src/email-notifications.js +26 -33
- package/src/index.js +1 -0
- package/src/kms-client.js +11 -26
- package/src/s3-client.js +19 -42
- package/src/sms-notifications.js +7 -14
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@velocitycareerlabs/aws-clients",
|
3
|
-
"version": "1.24.0-dev-build.
|
3
|
+
"version": "1.24.0-dev-build.1bc10e07c",
|
4
4
|
"description": "Set of aws functions and utils used by Velocity Foundation projects",
|
5
5
|
"repository": "https://github.com/velocitycareerlabs/packages",
|
6
6
|
"main": "index.js",
|
@@ -15,22 +15,14 @@
|
|
15
15
|
"lint:fix": "eslint --fix --ext .js ."
|
16
16
|
},
|
17
17
|
"dependencies": {
|
18
|
-
"
|
19
|
-
"@aws-sdk/client-kms": "^3.731.1",
|
20
|
-
"@aws-sdk/client-s3": "^3.731.1",
|
21
|
-
"@aws-sdk/client-ses": "^3.731.1",
|
22
|
-
"@aws-sdk/client-sesv2": "^3.731.1",
|
23
|
-
"@aws-sdk/client-sns": "^3.731.1",
|
24
|
-
"@aws-sdk/lib-dynamodb": "^3.731.1",
|
25
|
-
"@aws-sdk/s3-request-presigner": "^3.731.1",
|
26
|
-
"aws-sdk": "^2.784.0",
|
18
|
+
"aws-sdk": "2.1692.0",
|
27
19
|
"fastify-plugin": "~4.5.1",
|
28
|
-
"lodash": "
|
20
|
+
"lodash": "^4.17.21",
|
29
21
|
"twilio": "^5.0.0"
|
30
22
|
},
|
31
23
|
"devDependencies": {
|
32
|
-
"@velocitycareerlabs/crypto": "1.24.0-dev-build.
|
33
|
-
"@velocitycareerlabs/jwt": "1.24.0-dev-build.
|
24
|
+
"@velocitycareerlabs/crypto": "1.24.0-dev-build.1bc10e07c",
|
25
|
+
"@velocitycareerlabs/jwt": "1.24.0-dev-build.1bc10e07c",
|
34
26
|
"eslint": "8.57.1",
|
35
27
|
"eslint-config-airbnb-base": "14.2.1",
|
36
28
|
"eslint-config-prettier": "8.10.0",
|
@@ -43,5 +35,5 @@
|
|
43
35
|
"jest": "29.7.0",
|
44
36
|
"prettier": "2.8.8"
|
45
37
|
},
|
46
|
-
"gitHead": "
|
38
|
+
"gitHead": "75caedc95a2a0f92af65851a2c14f3e683599160"
|
47
39
|
}
|
@@ -0,0 +1,85 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2023 Velocity Team
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
const AWS = require('aws-sdk');
|
18
|
+
|
19
|
+
const testsConfig = (awsEndpoint) =>
|
20
|
+
awsEndpoint
|
21
|
+
? {
|
22
|
+
credentials: new AWS.Credentials('tests-kei-id', 'tests-key'),
|
23
|
+
endpoint: awsEndpoint,
|
24
|
+
}
|
25
|
+
: {};
|
26
|
+
|
27
|
+
const createKmsClient = ({ awsRegion, awsEndpoint }) => {
|
28
|
+
return new AWS.KMS({
|
29
|
+
region: awsRegion,
|
30
|
+
...testsConfig(awsEndpoint),
|
31
|
+
});
|
32
|
+
};
|
33
|
+
|
34
|
+
const createSesClient = ({ awsRegion, awsEndpoint }) =>
|
35
|
+
new AWS.SES({
|
36
|
+
apiVersion: '2010-12-01',
|
37
|
+
region: awsRegion,
|
38
|
+
...testsConfig(awsEndpoint),
|
39
|
+
});
|
40
|
+
|
41
|
+
const createSesV2Client = ({ awsRegion }) =>
|
42
|
+
new AWS.SESV2({
|
43
|
+
apiVersion: '2019-09-27',
|
44
|
+
region: awsRegion,
|
45
|
+
});
|
46
|
+
|
47
|
+
const createDynamoDbDocumentClient = ({ awsRegion, awsEndpoint }) =>
|
48
|
+
new AWS.DynamoDB.DocumentClient({
|
49
|
+
apiVersion: '2012-08-10',
|
50
|
+
region: awsRegion,
|
51
|
+
...testsConfig(awsEndpoint),
|
52
|
+
});
|
53
|
+
|
54
|
+
const createS3Client = ({
|
55
|
+
awsRegion,
|
56
|
+
awsEndpoint,
|
57
|
+
accessKeyId,
|
58
|
+
secretAccessKey,
|
59
|
+
isTest,
|
60
|
+
}) =>
|
61
|
+
new AWS.S3({
|
62
|
+
apiVersion: '2006-03-01',
|
63
|
+
region: awsRegion,
|
64
|
+
signatureVersion: 'v4',
|
65
|
+
accessKeyId,
|
66
|
+
secretAccessKey,
|
67
|
+
s3ForcePathStyle: isTest,
|
68
|
+
...testsConfig(awsEndpoint),
|
69
|
+
});
|
70
|
+
|
71
|
+
const createSnsClient = ({ awsRegion, awsEndpoint }) =>
|
72
|
+
new AWS.SNS({
|
73
|
+
apiVersion: '2010-03-31',
|
74
|
+
region: awsRegion,
|
75
|
+
...testsConfig(awsEndpoint),
|
76
|
+
});
|
77
|
+
|
78
|
+
module.exports = {
|
79
|
+
createSnsClient,
|
80
|
+
createSesClient,
|
81
|
+
createSesV2Client,
|
82
|
+
createDynamoDbDocumentClient,
|
83
|
+
createS3Client,
|
84
|
+
createKmsClient,
|
85
|
+
};
|
package/src/document-storage.js
CHANGED
@@ -14,27 +14,7 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
-
const {
|
18
|
-
const {
|
19
|
-
DynamoDBDocumentClient,
|
20
|
-
GetCommand,
|
21
|
-
PutCommand,
|
22
|
-
} = require('@aws-sdk/lib-dynamodb');
|
23
|
-
|
24
|
-
const createDynamoDbDocumentClient = ({ awsRegion, awsEndpoint }) =>
|
25
|
-
DynamoDBDocumentClient.from(
|
26
|
-
new DynamoDB({
|
27
|
-
apiVersion: '2012-08-10',
|
28
|
-
region: awsRegion,
|
29
|
-
credentials: awsEndpoint
|
30
|
-
? {
|
31
|
-
accessKeyId: 'tests-key-id',
|
32
|
-
secretAccessKey: 'tests-key',
|
33
|
-
}
|
34
|
-
: awsEndpoint,
|
35
|
-
endpoint: awsEndpoint,
|
36
|
-
})
|
37
|
-
);
|
17
|
+
const { createDynamoDbDocumentClient } = require('./aws-factory');
|
38
18
|
|
39
19
|
const initReadDocument =
|
40
20
|
({ awsRegion, awsEndpoint }) =>
|
@@ -44,12 +24,12 @@ const initReadDocument =
|
|
44
24
|
awsEndpoint,
|
45
25
|
});
|
46
26
|
|
47
|
-
return dynamoDbDocClient
|
48
|
-
|
27
|
+
return dynamoDbDocClient
|
28
|
+
.get({
|
49
29
|
TableName: table,
|
50
30
|
Key: key,
|
51
31
|
})
|
52
|
-
|
32
|
+
.promise();
|
53
33
|
};
|
54
34
|
|
55
35
|
const initWriteDocument =
|
@@ -60,12 +40,12 @@ const initWriteDocument =
|
|
60
40
|
awsEndpoint,
|
61
41
|
});
|
62
42
|
|
63
|
-
await dynamoDbDocClient
|
64
|
-
|
43
|
+
await dynamoDbDocClient
|
44
|
+
.put({
|
65
45
|
TableName: table,
|
66
46
|
Item: document,
|
67
47
|
})
|
68
|
-
|
48
|
+
.promise();
|
69
49
|
};
|
70
50
|
|
71
51
|
module.exports = {
|
@@ -15,34 +15,28 @@
|
|
15
15
|
*/
|
16
16
|
|
17
17
|
const { isEmpty, join } = require('lodash/fp');
|
18
|
-
const {
|
19
|
-
SESClient,
|
20
|
-
SendEmailCommand: SESSendEmailCommand,
|
21
|
-
} = require('@aws-sdk/client-ses');
|
22
|
-
const {
|
23
|
-
SESv2Client,
|
24
|
-
SendEmailCommand: SESv2SendEmailCommand,
|
25
|
-
} = require('@aws-sdk/client-sesv2');
|
18
|
+
const { createSesClient, createSesV2Client } = require('./aws-factory');
|
26
19
|
|
27
|
-
// 2020-10-20: At the moment
|
28
|
-
// so SES is used for testing when a value is passed for endpoint (local address)
|
20
|
+
// 2020-10-20: At the moment Localstack doesn't support SESv2, so SES is used for testing when a value is passed for endpoint (local address)
|
29
21
|
|
30
|
-
const
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
endpoint: awsEndpoint,
|
39
|
-
});
|
22
|
+
const initVerifyDomain =
|
23
|
+
({ awsRegion, awsEndpoint }) =>
|
24
|
+
async (domain) => {
|
25
|
+
if (awsEndpoint) {
|
26
|
+
const awsSes = createSesClient({
|
27
|
+
awsRegion,
|
28
|
+
awsEndpoint,
|
29
|
+
});
|
40
30
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
31
|
+
await awsSes.verifyDomainDkim({ Domain: domain }).promise();
|
32
|
+
} else {
|
33
|
+
const awsSesV2 = createSesV2Client({
|
34
|
+
awsRegion,
|
35
|
+
});
|
36
|
+
|
37
|
+
await awsSesV2.createEmailIdentity({ EmailIdentity: domain }).promise();
|
38
|
+
}
|
39
|
+
};
|
46
40
|
|
47
41
|
const initSendEmailNotification =
|
48
42
|
({ awsRegion, awsEndpoint }) =>
|
@@ -75,8 +69,8 @@ const initSendEmailNotification =
|
|
75
69
|
awsEndpoint,
|
76
70
|
});
|
77
71
|
|
78
|
-
await awsSes
|
79
|
-
|
72
|
+
await awsSes
|
73
|
+
.sendEmail({
|
80
74
|
Source: sender,
|
81
75
|
Destination: destination,
|
82
76
|
ReplyToAddresses: [replyTo],
|
@@ -108,14 +102,14 @@ const initSendEmailNotification =
|
|
108
102
|
},
|
109
103
|
},
|
110
104
|
})
|
111
|
-
|
105
|
+
.promise();
|
112
106
|
} else {
|
113
107
|
const awsSesV2 = createSesV2Client({
|
114
108
|
awsRegion,
|
115
109
|
});
|
116
110
|
|
117
|
-
await awsSesV2
|
118
|
-
|
111
|
+
await awsSesV2
|
112
|
+
.sendEmail({
|
119
113
|
FromEmailAddress: sender,
|
120
114
|
Destination: destination,
|
121
115
|
ReplyToAddresses: [replyTo],
|
@@ -149,7 +143,7 @@ const initSendEmailNotification =
|
|
149
143
|
}),
|
150
144
|
},
|
151
145
|
})
|
152
|
-
|
146
|
+
.promise();
|
153
147
|
}
|
154
148
|
};
|
155
149
|
|
@@ -192,8 +186,7 @@ const buildRawMessage = ({
|
|
192
186
|
};
|
193
187
|
|
194
188
|
module.exports = {
|
195
|
-
|
196
|
-
createSesV2Client,
|
189
|
+
initVerifyDomain,
|
197
190
|
initSendEmailNotification,
|
198
191
|
buildRawMessage,
|
199
192
|
};
|
package/src/index.js
CHANGED
package/src/kms-client.js
CHANGED
@@ -14,44 +14,29 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
-
const {
|
18
|
-
KMSClient,
|
19
|
-
EncryptCommand,
|
20
|
-
DecryptCommand,
|
21
|
-
} = require('@aws-sdk/client-kms');
|
17
|
+
const { createKmsClient } = require('./aws-factory');
|
22
18
|
|
23
19
|
const initKmsClient = ({ awsRegion, awsEndpoint }) => {
|
24
|
-
const kmsClient =
|
25
|
-
|
26
|
-
|
27
|
-
? {
|
28
|
-
accessKeyId: 'tests-key-id',
|
29
|
-
secretAccessKey: 'tests-key',
|
30
|
-
}
|
31
|
-
: awsEndpoint,
|
32
|
-
endpoint: awsEndpoint,
|
20
|
+
const kmsClient = createKmsClient({
|
21
|
+
awsRegion,
|
22
|
+
awsEndpoint,
|
33
23
|
});
|
34
24
|
|
35
25
|
const encrypt = async (keyId, plaintext) => {
|
36
|
-
const
|
26
|
+
const params = {
|
37
27
|
KeyId: keyId,
|
38
|
-
Plaintext:
|
39
|
-
}
|
28
|
+
Plaintext: plaintext,
|
29
|
+
};
|
40
30
|
|
41
|
-
return kmsClient.
|
31
|
+
return kmsClient.encrypt(params).promise();
|
42
32
|
};
|
43
33
|
|
44
34
|
const decrypt = async (ciphertextBlob) => {
|
45
|
-
const
|
35
|
+
const params = {
|
46
36
|
CiphertextBlob: ciphertextBlob,
|
47
|
-
});
|
48
|
-
|
49
|
-
const result = await kmsClient.send(command);
|
50
|
-
|
51
|
-
return {
|
52
|
-
...result,
|
53
|
-
Plaintext: Buffer.from(result.Plaintext),
|
54
37
|
};
|
38
|
+
|
39
|
+
return kmsClient.decrypt(params).promise();
|
55
40
|
};
|
56
41
|
|
57
42
|
return {
|
package/src/s3-client.js
CHANGED
@@ -14,15 +14,7 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
-
const {
|
18
|
-
S3Client,
|
19
|
-
GetObjectCommand,
|
20
|
-
PutObjectCommand,
|
21
|
-
DeleteObjectCommand,
|
22
|
-
} = require('@aws-sdk/client-s3');
|
23
|
-
const {
|
24
|
-
getSignedUrl: awsGetSignedUrl,
|
25
|
-
} = require('@aws-sdk/s3-request-presigner');
|
17
|
+
const { createS3Client } = require('./aws-factory');
|
26
18
|
|
27
19
|
const initS3Client = ({
|
28
20
|
awsRegion,
|
@@ -33,65 +25,50 @@ const initS3Client = ({
|
|
33
25
|
secretAccessKey,
|
34
26
|
isTest,
|
35
27
|
}) => {
|
36
|
-
const s3Client =
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
secretAccessKey,
|
43
|
-
},
|
44
|
-
forcePathStyle: isTest,
|
45
|
-
endpoint: awsEndpoint,
|
28
|
+
const s3Client = createS3Client({
|
29
|
+
awsRegion,
|
30
|
+
awsEndpoint,
|
31
|
+
accessKeyId,
|
32
|
+
secretAccessKey,
|
33
|
+
isTest,
|
46
34
|
});
|
47
35
|
|
48
|
-
const getSignedUrl = async ({ key, contentType, metadata }) =>
|
49
|
-
|
36
|
+
const getSignedUrl = async ({ key, contentType, metadata }) =>
|
37
|
+
s3Client.getSignedUrlPromise('putObject', {
|
50
38
|
Bucket: s3Bucket,
|
51
39
|
Key: key,
|
40
|
+
Expires: s3PresignedUrlExpiration,
|
52
41
|
ContentType: contentType,
|
53
42
|
Metadata: metadata,
|
54
43
|
});
|
55
44
|
|
56
|
-
return awsGetSignedUrl(s3Client, command, {
|
57
|
-
expiresIn: s3PresignedUrlExpiration,
|
58
|
-
});
|
59
|
-
};
|
60
|
-
|
61
45
|
const getObject = async ({ bucket, key }) => {
|
62
|
-
const
|
46
|
+
const params = {
|
63
47
|
Bucket: bucket,
|
64
48
|
Key: key,
|
65
|
-
});
|
66
|
-
|
67
|
-
const result = await s3Client.send(command);
|
68
|
-
const body = await result.Body.transformToByteArray();
|
69
|
-
|
70
|
-
return {
|
71
|
-
...result,
|
72
|
-
Body: body,
|
73
49
|
};
|
50
|
+
|
51
|
+
return s3Client.getObject(params).promise();
|
74
52
|
};
|
75
53
|
|
76
54
|
const putObject = async ({ bucket, key, body, contentType, metadata }) => {
|
77
|
-
const
|
55
|
+
const params = {
|
78
56
|
Bucket: bucket,
|
79
57
|
Key: key,
|
80
58
|
Body: body,
|
81
59
|
ContentType: contentType,
|
82
60
|
Metadata: metadata,
|
83
|
-
}
|
61
|
+
};
|
84
62
|
|
85
|
-
await s3Client.
|
63
|
+
await s3Client.putObject(params).promise();
|
86
64
|
};
|
87
65
|
|
88
66
|
const deleteObject = async ({ bucket, key }) => {
|
89
|
-
const
|
67
|
+
const params = {
|
90
68
|
Bucket: bucket,
|
91
69
|
Key: key,
|
92
|
-
}
|
93
|
-
|
94
|
-
await s3Client.send(command);
|
70
|
+
};
|
71
|
+
await s3Client.deleteObject(params).promise();
|
95
72
|
};
|
96
73
|
|
97
74
|
return {
|
package/src/sms-notifications.js
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
const { startsWith } = require('lodash/fp');
|
17
|
-
const {
|
17
|
+
const { createSnsClient } = require('./aws-factory');
|
18
18
|
const { createTwilioClient } = require('./twilio-factory');
|
19
19
|
|
20
20
|
const singaporePhoneCode = '+65';
|
@@ -39,16 +39,9 @@ const initSendSmsNotification =
|
|
39
39
|
onlyTwilioSms,
|
40
40
|
}) =>
|
41
41
|
async ({ message, phoneNumber, senderId }) => {
|
42
|
-
const awsSns =
|
43
|
-
|
44
|
-
|
45
|
-
credentials: awsEndpoint
|
46
|
-
? {
|
47
|
-
accessKeyId: 'tests-key-id',
|
48
|
-
secretAccessKey: 'tests-key',
|
49
|
-
}
|
50
|
-
: awsEndpoint,
|
51
|
-
endpoint: awsEndpoint,
|
42
|
+
const awsSns = createSnsClient({
|
43
|
+
awsRegion,
|
44
|
+
awsEndpoint,
|
52
45
|
});
|
53
46
|
const { sendTwilioSms } = createTwilioClient({
|
54
47
|
twilioAccountSid,
|
@@ -61,8 +54,8 @@ const initSendSmsNotification =
|
|
61
54
|
return;
|
62
55
|
}
|
63
56
|
|
64
|
-
await awsSns
|
65
|
-
|
57
|
+
await awsSns
|
58
|
+
.publish({
|
66
59
|
Message: message,
|
67
60
|
PhoneNumber: phoneNumber,
|
68
61
|
MessageAttributes: {
|
@@ -73,7 +66,7 @@ const initSendSmsNotification =
|
|
73
66
|
},
|
74
67
|
},
|
75
68
|
})
|
76
|
-
|
69
|
+
.promise();
|
77
70
|
};
|
78
71
|
|
79
72
|
module.exports = {
|