@creator.co/wapi 1.2.1-beta6 → 1.2.2
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/.github/workflows/npmpublish.yml +11 -19
- package/.github/workflows/prs.yml +13 -0
- package/jest.config.ts +39 -0
- package/package.json +15 -4
- package/src/API/Request.ts +120 -10
- package/src/API/Response.ts +236 -8
- package/src/API/Utils.ts +56 -1
- package/src/BaseEvent/EventProcessor.ts +84 -11
- package/src/BaseEvent/Process.ts +62 -1
- package/src/BaseEvent/Transaction.ts +5 -8
- package/src/Config/Configuration.ts +111 -5
- package/src/Config/EnvironmentVar.ts +90 -1
- package/src/Crypto/Crypto.ts +77 -18
- package/src/Crypto/JWT.ts +49 -3
- package/src/Globals.ts +141 -3
- package/src/Logger/Logger.ts +173 -19
- package/src/Mailer/Mailer.ts +95 -0
- package/src/Publisher/Publisher.ts +50 -4
- package/src/Server/RouteResolver.ts +142 -0
- package/src/Server/Router.ts +77 -0
- package/src/Server/lib/ContainerServer.ts +48 -1
- package/src/Server/lib/Server.ts +78 -38
- package/src/Server/lib/container/GenericHandler.ts +7 -5
- package/src/Server/lib/container/GenericHandlerEvent.ts +59 -17
- package/src/Server/lib/container/HealthHandler.ts +1 -1
- package/src/Server/lib/container/Proxy.ts +92 -11
- package/src/Server/lib/container/Utils.ts +16 -25
- package/src/Validation/Validator.ts +18 -2
- package/tests/API/Request.test.ts +263 -0
- package/tests/API/Response.test.ts +372 -0
- package/tests/API/Utils.test.ts +157 -0
- package/tests/BaseEvent/EventProcessor.test.ts +278 -0
- package/tests/BaseEvent/Process.test.ts +49 -0
- package/tests/BaseEvent/Transaction.test.ts +231 -0
- package/tests/Config/Config.test.ts +193 -0
- package/tests/Config/EnvironmentVar.test.ts +223 -0
- package/tests/Crypto/Crypto.test.ts +90 -0
- package/tests/Crypto/JWT.test.ts +92 -0
- package/tests/Logger/Logger.test.ts +108 -0
- package/tests/Mailer/Mailer.test.ts +67 -0
- package/tests/Publisher/Publisher.test.ts +60 -0
- package/tests/Server/RouteResolver.test.ts +106 -0
- package/tests/Server/Router.test.ts +38 -0
- package/tests/Server/lib/ContainerServer.test.ts +329 -0
- package/tests/Server/lib/Server.test.ts +12 -0
- package/tests/Server/lib/container/GenericHandler.test.ts +141 -0
- package/tests/Server/lib/container/GenericHandlerEvent.test.ts +103 -0
- package/tests/Server/lib/container/HealthHandler.test.ts +30 -0
- package/tests/Server/lib/container/Proxy.test.ts +278 -0
- package/tests/Server/lib/container/Utils.test.ts +48 -0
- package/tests/Test.utils.ts +95 -0
- package/tests/Validation/Validator.test.ts +88 -0
- package/tests/main.test.ts +15 -0
- package/tsconfig.json +1 -0
- package/dist/index.d.ts +0 -11
- package/dist/index.js +0 -24
- package/dist/index.js.map +0 -1
- package/dist/package.json +0 -53
- package/dist/src/API/Request.d.ts +0 -21
- package/dist/src/API/Request.js +0 -86
- package/dist/src/API/Request.js.map +0 -1
- package/dist/src/API/Response.d.ts +0 -39
- package/dist/src/API/Response.js +0 -232
- package/dist/src/API/Response.js.map +0 -1
- package/dist/src/API/Utils.d.ts +0 -8
- package/dist/src/API/Utils.js +0 -49
- package/dist/src/API/Utils.js.map +0 -1
- package/dist/src/BaseEvent/EventProcessor.d.ts +0 -13
- package/dist/src/BaseEvent/EventProcessor.js +0 -151
- package/dist/src/BaseEvent/EventProcessor.js.map +0 -1
- package/dist/src/BaseEvent/Process.d.ts +0 -12
- package/dist/src/BaseEvent/Process.js +0 -114
- package/dist/src/BaseEvent/Process.js.map +0 -1
- package/dist/src/BaseEvent/Transaction.d.ts +0 -29
- package/dist/src/BaseEvent/Transaction.js +0 -248
- package/dist/src/BaseEvent/Transaction.js.map +0 -1
- package/dist/src/Config/Configuration.d.ts +0 -34
- package/dist/src/Config/Configuration.js +0 -93
- package/dist/src/Config/Configuration.js.map +0 -1
- package/dist/src/Config/EnvironmentVar.d.ts +0 -17
- package/dist/src/Config/EnvironmentVar.js +0 -152
- package/dist/src/Config/EnvironmentVar.js.map +0 -1
- package/dist/src/Crypto/Crypto.d.ts +0 -8
- package/dist/src/Crypto/Crypto.js +0 -84
- package/dist/src/Crypto/Crypto.js.map +0 -1
- package/dist/src/Crypto/JWT.d.ts +0 -16
- package/dist/src/Crypto/JWT.js +0 -49
- package/dist/src/Crypto/JWT.js.map +0 -1
- package/dist/src/Globals.d.ts +0 -21
- package/dist/src/Globals.js +0 -35
- package/dist/src/Globals.js.map +0 -1
- package/dist/src/Logger/Logger.d.ts +0 -34
- package/dist/src/Logger/Logger.js +0 -345
- package/dist/src/Logger/Logger.js.map +0 -1
- package/dist/src/Mailer/Mailer.d.ts +0 -12
- package/dist/src/Mailer/Mailer.js +0 -234
- package/dist/src/Mailer/Mailer.js.map +0 -1
- package/dist/src/Publisher/Publisher.d.ts +0 -10
- package/dist/src/Publisher/Publisher.js +0 -109
- package/dist/src/Publisher/Publisher.js.map +0 -1
- package/dist/src/Server/Router.d.ts +0 -27
- package/dist/src/Server/Router.js +0 -22
- package/dist/src/Server/Router.js.map +0 -1
- package/dist/src/Server/lib/ContainerServer.d.ts +0 -11
- package/dist/src/Server/lib/ContainerServer.js +0 -103
- package/dist/src/Server/lib/ContainerServer.js.map +0 -1
- package/dist/src/Server/lib/Server.d.ts +0 -9
- package/dist/src/Server/lib/Server.js +0 -141
- package/dist/src/Server/lib/Server.js.map +0 -1
- package/dist/src/Server/lib/container/GenericHandler.d.ts +0 -4
- package/dist/src/Server/lib/container/GenericHandler.js +0 -136
- package/dist/src/Server/lib/container/GenericHandler.js.map +0 -1
- package/dist/src/Server/lib/container/GenericHandlerEvent.d.ts +0 -14
- package/dist/src/Server/lib/container/GenericHandlerEvent.js +0 -164
- package/dist/src/Server/lib/container/GenericHandlerEvent.js.map +0 -1
- package/dist/src/Server/lib/container/HealthHandler.d.ts +0 -3
- package/dist/src/Server/lib/container/HealthHandler.js +0 -44
- package/dist/src/Server/lib/container/HealthHandler.js.map +0 -1
- package/dist/src/Server/lib/container/Proxy.d.ts +0 -15
- package/dist/src/Server/lib/container/Proxy.js +0 -157
- package/dist/src/Server/lib/container/Proxy.js.map +0 -1
- package/dist/src/Server/lib/container/Utils.d.ts +0 -6
- package/dist/src/Server/lib/container/Utils.js +0 -109
- package/dist/src/Server/lib/container/Utils.js.map +0 -1
- package/dist/src/Validation/Validator.d.ts +0 -5
- package/dist/src/Validation/Validator.js +0 -31
- package/dist/src/Validation/Validator.js.map +0 -1
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm"
|
|
2
|
+
import { mockClient } from "aws-sdk-client-mock"
|
|
3
|
+
import { expect } from "chai"
|
|
4
|
+
|
|
5
|
+
import Configuration from "../../src/Config/Configuration"
|
|
6
|
+
import { SampleConfig, SampleConfigSchema } from "../Test.utils"
|
|
7
|
+
|
|
8
|
+
const SSMMock = mockClient(SSMClient)
|
|
9
|
+
const config = new Configuration<SampleConfigSchema>(SampleConfig, "my-prefix")
|
|
10
|
+
describe(`Optional remote environment`, () => {
|
|
11
|
+
// reset mock
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
SSMMock.reset()
|
|
14
|
+
config["resetCache"]()
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
test("Does not accept sync get", async () => {
|
|
18
|
+
let err = null
|
|
19
|
+
try {
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
config.get("TOKEN_SECRET")
|
|
22
|
+
} catch (e) {
|
|
23
|
+
err = e
|
|
24
|
+
}
|
|
25
|
+
expect(err).is.not.null
|
|
26
|
+
expect(err?.["message"]).is.not.null
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test("Optional value with null value", async () => {
|
|
30
|
+
SSMMock.on(GetParameterCommand).resolves({
|
|
31
|
+
Parameter: {
|
|
32
|
+
Value: undefined,
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
const token = await config.asyncGet("TOKEN_SECRET_FALSY")
|
|
36
|
+
expect(token).is.undefined
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test("Optional value with empty response", async () => {
|
|
40
|
+
SSMMock.on(GetParameterCommand).resolves({})
|
|
41
|
+
const token = await config.asyncGet("TOKEN_SECRET_FALSY")
|
|
42
|
+
expect(token).is.undefined
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test("Optional value with valid response", async () => {
|
|
46
|
+
const value = "abc"
|
|
47
|
+
SSMMock.on(GetParameterCommand).resolves({
|
|
48
|
+
Parameter: {
|
|
49
|
+
Value: value,
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
const token = await config.asyncGet("TOKEN_SECRET_FALSY")
|
|
53
|
+
expect(token).is.not.undefined
|
|
54
|
+
expect(token).to.be.equals(value)
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test("Optional value rejection", async () => {
|
|
58
|
+
SSMMock.on(GetParameterCommand).rejects(new Error("failed!"))
|
|
59
|
+
const token = await config.asyncGet("TOKEN_SECRET_FALSY")
|
|
60
|
+
expect(token).is.undefined
|
|
61
|
+
})
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
describe(`Required remote environment`, () => {
|
|
65
|
+
// reset mock
|
|
66
|
+
beforeEach(() => {
|
|
67
|
+
SSMMock.reset()
|
|
68
|
+
config["resetCache"]()
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test("Does not accept sync get", async () => {
|
|
72
|
+
let err = null
|
|
73
|
+
try {
|
|
74
|
+
// @ts-ignore
|
|
75
|
+
config.get("TOKEN_SECRET")
|
|
76
|
+
} catch (e) {
|
|
77
|
+
err = e
|
|
78
|
+
}
|
|
79
|
+
expect(err).is.not.null
|
|
80
|
+
expect(err?.["message"]).is.not.null
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
test("Required value with null value", async () => {
|
|
84
|
+
SSMMock.on(GetParameterCommand).resolves({
|
|
85
|
+
Parameter: {
|
|
86
|
+
Value: undefined,
|
|
87
|
+
},
|
|
88
|
+
})
|
|
89
|
+
let err = null
|
|
90
|
+
try {
|
|
91
|
+
await config.asyncGet("TOKEN_SECRET")
|
|
92
|
+
} catch (e) {
|
|
93
|
+
err = e
|
|
94
|
+
}
|
|
95
|
+
expect(err).is.not.null
|
|
96
|
+
expect(err?.["message"]).is.not.null
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test("Required value with empty response", async () => {
|
|
100
|
+
SSMMock.on(GetParameterCommand).resolves({})
|
|
101
|
+
let err = null
|
|
102
|
+
try {
|
|
103
|
+
await config.asyncGet("TOKEN_SECRET")
|
|
104
|
+
} catch (e) {
|
|
105
|
+
err = e
|
|
106
|
+
}
|
|
107
|
+
expect(err).is.not.null
|
|
108
|
+
expect(err?.["message"]).is.not.null
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
test("Required value with valid response", async () => {
|
|
112
|
+
const value = "abc"
|
|
113
|
+
SSMMock.on(GetParameterCommand).resolves({
|
|
114
|
+
Parameter: {
|
|
115
|
+
Value: value,
|
|
116
|
+
},
|
|
117
|
+
})
|
|
118
|
+
const token = await config.asyncGet("TOKEN_SECRET")
|
|
119
|
+
expect(token).is.not.undefined
|
|
120
|
+
expect(token).to.be.equals(value)
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
test("Required value rejection", async () => {
|
|
124
|
+
SSMMock.on(GetParameterCommand).rejects(new Error("failed!"))
|
|
125
|
+
let err = null
|
|
126
|
+
try {
|
|
127
|
+
await config.asyncGet("TOKEN_SECRET")
|
|
128
|
+
} catch (e) {
|
|
129
|
+
err = e
|
|
130
|
+
}
|
|
131
|
+
expect(err).is.not.null
|
|
132
|
+
expect(err?.["message"]).is.not.null
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
describe(`Optional local environment`, () => {
|
|
137
|
+
beforeEach(() => {
|
|
138
|
+
config["resetCache"]()
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
test("Optional value with null value", async () => {
|
|
142
|
+
const token = config.get("PATH123")
|
|
143
|
+
expect(token).is.undefined
|
|
144
|
+
})
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
describe(`Required local environment`, () => {
|
|
148
|
+
beforeEach(() => {
|
|
149
|
+
config["resetCache"]()
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test("Required value with null value", async () => {
|
|
153
|
+
let err = null
|
|
154
|
+
try {
|
|
155
|
+
config.get("PATH_FALSY")
|
|
156
|
+
} catch (e) {
|
|
157
|
+
err = e
|
|
158
|
+
}
|
|
159
|
+
expect(err).is.not.null
|
|
160
|
+
expect(err?.["message"]).is.not.null
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
test("Required value with valid response", async () => {
|
|
164
|
+
const key = "PATH"
|
|
165
|
+
const v = config.get(key)
|
|
166
|
+
expect(v).is.not.null
|
|
167
|
+
expect(v).to.be.equals(process.env[key])
|
|
168
|
+
})
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
describe(`Caching test`, () => {
|
|
172
|
+
test("Does cache previous fetched value", async () => {
|
|
173
|
+
const value = "123"
|
|
174
|
+
const key = "TOKEN_SECRET"
|
|
175
|
+
// initial fetch
|
|
176
|
+
SSMMock.on(GetParameterCommand).resolves({
|
|
177
|
+
Parameter: {
|
|
178
|
+
Value: value,
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
const v = await config.asyncGet(key)
|
|
182
|
+
expect(v).is.not.null
|
|
183
|
+
expect(v).to.be.equals(value)
|
|
184
|
+
// subsequent fetch
|
|
185
|
+
SSMMock.reset()
|
|
186
|
+
SSMMock.on(GetParameterCommand).rejects(new Error("failed!"))
|
|
187
|
+
const v2 = await config.asyncGet(key)
|
|
188
|
+
expect(v2).is.not.null
|
|
189
|
+
expect(v2).to.be.equals(value)
|
|
190
|
+
})
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
export {}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SecretsManagerClient,
|
|
3
|
+
GetSecretValueCommand,
|
|
4
|
+
} from "@aws-sdk/client-secrets-manager"
|
|
5
|
+
import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm"
|
|
6
|
+
import { mockClient } from "aws-sdk-client-mock"
|
|
7
|
+
import { expect } from "chai"
|
|
8
|
+
|
|
9
|
+
import EnvironmentVar, {
|
|
10
|
+
EnvironmentType,
|
|
11
|
+
} from "../../src/Config/EnvironmentVar"
|
|
12
|
+
|
|
13
|
+
const SSMMock = mockClient(SSMClient)
|
|
14
|
+
const SecretsManagerMock = mockClient(SecretsManagerClient)
|
|
15
|
+
|
|
16
|
+
function testRemoteEnv(mock, type, command) {
|
|
17
|
+
describe(`Optional ${type} environment`, () => {
|
|
18
|
+
// reset mock
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
mock.reset()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test("Does not accept sync resolve", async () => {
|
|
24
|
+
mock.on(command).resolves({
|
|
25
|
+
Parameter: {
|
|
26
|
+
Value: undefined,
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
let err = null
|
|
30
|
+
try {
|
|
31
|
+
const env = new EnvironmentVar("abc", type, true)
|
|
32
|
+
env.syncResolve()
|
|
33
|
+
} catch (e) {
|
|
34
|
+
err = e
|
|
35
|
+
}
|
|
36
|
+
expect(err).is.not.null
|
|
37
|
+
expect(err?.["message"]).is.not.null
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
test("Optional value with null value", async () => {
|
|
41
|
+
mock.on(command).resolves({
|
|
42
|
+
Parameter: {
|
|
43
|
+
Value: undefined,
|
|
44
|
+
},
|
|
45
|
+
})
|
|
46
|
+
const env = new EnvironmentVar("abc", type, true)
|
|
47
|
+
const token = await env.resolve()
|
|
48
|
+
expect(token).is.undefined
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test("Optional value with empty response", async () => {
|
|
52
|
+
mock.on(command).resolves({})
|
|
53
|
+
const env = new EnvironmentVar("abc", type, true)
|
|
54
|
+
const token = await env.resolve()
|
|
55
|
+
expect(token).is.undefined
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test("Optional value with valid response", async () => {
|
|
59
|
+
const value = "abc"
|
|
60
|
+
mock.on(command).resolves({
|
|
61
|
+
Parameter: {
|
|
62
|
+
Value: value,
|
|
63
|
+
},
|
|
64
|
+
})
|
|
65
|
+
const env = new EnvironmentVar(value, type, true)
|
|
66
|
+
const token = await env.resolve()
|
|
67
|
+
expect(token).is.not.undefined
|
|
68
|
+
expect(token).to.be.equals(value)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test("Optional value rejection", async () => {
|
|
72
|
+
const value = "abc"
|
|
73
|
+
mock.on(command).rejects(new Error("failed!"))
|
|
74
|
+
const env = new EnvironmentVar(value, type, true)
|
|
75
|
+
const token = await env.resolve()
|
|
76
|
+
expect(token).is.undefined
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
describe(`Required ${type} environment`, () => {
|
|
81
|
+
// reset mock
|
|
82
|
+
beforeEach(() => {
|
|
83
|
+
mock.reset()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
test("Does not accept sync resolve", async () => {
|
|
87
|
+
mock.on(command).resolves({
|
|
88
|
+
Parameter: {
|
|
89
|
+
Value: undefined,
|
|
90
|
+
},
|
|
91
|
+
})
|
|
92
|
+
let err = null
|
|
93
|
+
try {
|
|
94
|
+
const env = new EnvironmentVar("abc", type)
|
|
95
|
+
env.syncResolve()
|
|
96
|
+
} catch (e) {
|
|
97
|
+
err = e
|
|
98
|
+
}
|
|
99
|
+
expect(err).is.not.null
|
|
100
|
+
expect(err?.["message"]).is.not.null
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
test("Required fails when null", async () => {
|
|
104
|
+
mock.on(command).resolves({
|
|
105
|
+
Parameter: {
|
|
106
|
+
Value: undefined,
|
|
107
|
+
},
|
|
108
|
+
})
|
|
109
|
+
let err = null
|
|
110
|
+
try {
|
|
111
|
+
const env = new EnvironmentVar("abc", type)
|
|
112
|
+
await env.resolve()
|
|
113
|
+
} catch (e) {
|
|
114
|
+
err = e
|
|
115
|
+
}
|
|
116
|
+
console.log(err)
|
|
117
|
+
expect(err).is.not.null
|
|
118
|
+
expect(err?.["message"]).is.not.null
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
test("Required fails when empty response", async () => {
|
|
122
|
+
mock.on(command).resolves({})
|
|
123
|
+
let err = null
|
|
124
|
+
try {
|
|
125
|
+
const env = new EnvironmentVar("abc", type)
|
|
126
|
+
await env.resolve()
|
|
127
|
+
} catch (e) {
|
|
128
|
+
err = e
|
|
129
|
+
}
|
|
130
|
+
expect(err).is.not.null
|
|
131
|
+
expect(err?.["message"]).is.not.null
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
test("Required value with valid response", async () => {
|
|
135
|
+
const value = "abc"
|
|
136
|
+
mock.on(command).resolves({
|
|
137
|
+
Parameter: {
|
|
138
|
+
Value: value,
|
|
139
|
+
},
|
|
140
|
+
})
|
|
141
|
+
const env = new EnvironmentVar(value, type)
|
|
142
|
+
const token = await env.resolve()
|
|
143
|
+
expect(token).is.not.undefined
|
|
144
|
+
expect(token).to.be.equals(value)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
test("Required value rejection", async () => {
|
|
148
|
+
mock.on(command).rejects(new Error("failed!"))
|
|
149
|
+
let err = null
|
|
150
|
+
try {
|
|
151
|
+
const env = new EnvironmentVar("abc", type)
|
|
152
|
+
await env.resolve()
|
|
153
|
+
} catch (e) {
|
|
154
|
+
err = e
|
|
155
|
+
}
|
|
156
|
+
expect(err).is.not.null
|
|
157
|
+
expect(err?.["message"]).is.not.null
|
|
158
|
+
})
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* Remote envs test */
|
|
163
|
+
testRemoteEnv(SSMMock, EnvironmentType.PlainRemote, GetParameterCommand)
|
|
164
|
+
testRemoteEnv(
|
|
165
|
+
SecretsManagerMock,
|
|
166
|
+
EnvironmentType.SecureRemote,
|
|
167
|
+
GetSecretValueCommand,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
describe("Optional Local environment", () => {
|
|
171
|
+
test("Does accept async resolve", async () => {
|
|
172
|
+
const env = new EnvironmentVar("PATH123", EnvironmentType.Local, true)
|
|
173
|
+
const v = await env.resolve()
|
|
174
|
+
expect(v).is.undefined
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
test("Optional value with null value", async () => {
|
|
178
|
+
const env = new EnvironmentVar("PATH123", EnvironmentType.Local, true)
|
|
179
|
+
const token = env.syncResolve()
|
|
180
|
+
expect(token).is.undefined
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
test("Optional value with valid value", async () => {
|
|
184
|
+
const key = "PATH"
|
|
185
|
+
const env = new EnvironmentVar(key, EnvironmentType.Local, true)
|
|
186
|
+
const token = env.syncResolve()
|
|
187
|
+
expect(token).is.not.undefined
|
|
188
|
+
expect(token).to.be.equals(process.env[key])
|
|
189
|
+
})
|
|
190
|
+
})
|
|
191
|
+
|
|
192
|
+
describe("Required local environment", () => {
|
|
193
|
+
test("Does accept async resolve", async () => {
|
|
194
|
+
const key = "PATH"
|
|
195
|
+
const env = new EnvironmentVar(key, EnvironmentType.Local)
|
|
196
|
+
const v = await env.resolve()
|
|
197
|
+
expect(v).is.not.null
|
|
198
|
+
expect(v).to.be.equals(process.env[key])
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
test("Required fails when null", async () => {
|
|
202
|
+
let err = null
|
|
203
|
+
try {
|
|
204
|
+
const env = new EnvironmentVar("PATH123", EnvironmentType.Local)
|
|
205
|
+
env.syncResolve()
|
|
206
|
+
} catch (e) {
|
|
207
|
+
err = e
|
|
208
|
+
}
|
|
209
|
+
console.log(err)
|
|
210
|
+
expect(err).is.not.null
|
|
211
|
+
expect(err?.["message"]).is.not.null
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
test("Required value with valid value", async () => {
|
|
215
|
+
const key = "PATH"
|
|
216
|
+
const env = new EnvironmentVar(key, EnvironmentType.Local)
|
|
217
|
+
const v = env.syncResolve()
|
|
218
|
+
expect(v).is.not.null
|
|
219
|
+
expect(v).to.be.equals(process.env[key])
|
|
220
|
+
})
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
export {}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { DecryptCommand, EncryptCommand, KMSClient } from "@aws-sdk/client-kms"
|
|
2
|
+
import { mockClient } from "aws-sdk-client-mock"
|
|
3
|
+
import { expect } from "chai"
|
|
4
|
+
|
|
5
|
+
import Crypto from "../../src/Crypto/Crypto"
|
|
6
|
+
|
|
7
|
+
const KMSMock = mockClient(KMSClient)
|
|
8
|
+
|
|
9
|
+
function fakeEncryption(v) {
|
|
10
|
+
const f = new TextEncoder().encode(v)
|
|
11
|
+
return Buffer.from(f as any, "utf8").toString("hex")
|
|
12
|
+
}
|
|
13
|
+
function fakeDecryption(v) {
|
|
14
|
+
return new TextEncoder().encode(v)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
describe("Encryption", () => {
|
|
18
|
+
// reset mock
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
KMSMock.reset()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
const provider = new Crypto("ca-central-1", "abc123")
|
|
24
|
+
test("Encrypts json object", async () => {
|
|
25
|
+
const encryptionObj = { userID: 123 }
|
|
26
|
+
KMSMock.on(EncryptCommand).resolves({
|
|
27
|
+
CiphertextBlob: new TextEncoder().encode(JSON.stringify(encryptionObj)),
|
|
28
|
+
})
|
|
29
|
+
const token = await provider.encryptData(encryptionObj)
|
|
30
|
+
expect(token).is.not.null
|
|
31
|
+
expect(token).to.be.equals(fakeEncryption(JSON.stringify(encryptionObj)))
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test("Encrypts string", async () => {
|
|
35
|
+
const encryptionText = "Hello encryption!"
|
|
36
|
+
KMSMock.on(EncryptCommand).resolves({
|
|
37
|
+
CiphertextBlob: new TextEncoder().encode(encryptionText),
|
|
38
|
+
})
|
|
39
|
+
const token = await provider.encryptData(encryptionText)
|
|
40
|
+
expect(token).is.not.null
|
|
41
|
+
expect(token).to.be.equals(fakeEncryption(encryptionText))
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test("Fails to encrypt a number", async () => {
|
|
45
|
+
const encryptionText = 123
|
|
46
|
+
KMSMock.on(EncryptCommand).rejects(new Error("failed"))
|
|
47
|
+
const token = await provider.encryptData(encryptionText)
|
|
48
|
+
expect(token).is.null
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
describe("Decryption", () => {
|
|
53
|
+
// reset mock
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
KMSMock.reset()
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const provider = new Crypto("ca-central-1", "abc123")
|
|
59
|
+
test("Decrypts json object", async () => {
|
|
60
|
+
const encryptionObj = { userID: 123 }
|
|
61
|
+
KMSMock.on(DecryptCommand).resolves({
|
|
62
|
+
Plaintext: fakeDecryption(JSON.stringify(encryptionObj)),
|
|
63
|
+
})
|
|
64
|
+
const token = await provider.decryptData(
|
|
65
|
+
fakeEncryption(JSON.stringify(encryptionObj)),
|
|
66
|
+
)
|
|
67
|
+
expect(token).is.not.null
|
|
68
|
+
expect(token).to.be.equals(JSON.stringify(encryptionObj))
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test("Decrypts string", async () => {
|
|
72
|
+
const encryptionText = "abc123"
|
|
73
|
+
KMSMock.on(DecryptCommand).resolves({
|
|
74
|
+
Plaintext: fakeDecryption(encryptionText),
|
|
75
|
+
})
|
|
76
|
+
const token = await provider.decryptData(fakeEncryption(encryptionText))
|
|
77
|
+
expect(token).is.not.null
|
|
78
|
+
expect(token).to.be.equals(encryptionText)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test("Fails to decrypt a number", async () => {
|
|
82
|
+
const encryptionText = 123
|
|
83
|
+
KMSMock.on(DecryptCommand).rejects(new Error("failed"))
|
|
84
|
+
// @ts-ignore
|
|
85
|
+
const token = await provider.decryptData(encryptionText)
|
|
86
|
+
expect(token).is.null
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
export {}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { expect } from "chai"
|
|
2
|
+
|
|
3
|
+
import JWT from "../../src/Crypto/JWT"
|
|
4
|
+
import { foreignToken, privateKey } from "../Test.utils"
|
|
5
|
+
|
|
6
|
+
describe("Creates token", () => {
|
|
7
|
+
const provider = new JWT(privateKey, "7d")
|
|
8
|
+
test("Creates token without explicity expiration", () => {
|
|
9
|
+
const token = provider.createToken({ userID: 123 })
|
|
10
|
+
expect(token).to.be.a("string")
|
|
11
|
+
expect(token).is.not.null
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test("Creates token with explicity expiration", () => {
|
|
15
|
+
const token = provider.createToken({ userID: 123 }, "7d")
|
|
16
|
+
expect(token).to.be.a("string")
|
|
17
|
+
expect(token).is.not.null
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test("Creates token with explicity token override", () => {
|
|
21
|
+
const token = provider.createToken({ userID: 123 }, "7d", privateKey)
|
|
22
|
+
expect(token).to.be.a("string")
|
|
23
|
+
expect(token).is.not.null
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
test("Creates token with explicity token options", () => {
|
|
27
|
+
const token = provider.createToken({ userID: 123 }, undefined, undefined, {
|
|
28
|
+
expiresIn: "7d",
|
|
29
|
+
})
|
|
30
|
+
expect(token).to.be.a("string")
|
|
31
|
+
expect(token).is.not.null
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test("Creates token with no expiration", () => {
|
|
35
|
+
const localProvider = new JWT(privateKey)
|
|
36
|
+
const token = localProvider.createToken({ userID: 123 })
|
|
37
|
+
expect(token).to.be.a("string")
|
|
38
|
+
expect(token).is.not.null
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
describe("Validates token", () => {
|
|
43
|
+
const provider = new JWT(privateKey, "7d")
|
|
44
|
+
test("Succeed to validate just created token", () => {
|
|
45
|
+
// Creates token
|
|
46
|
+
const token = provider.createToken({ userID: 123 }, "7d", privateKey)
|
|
47
|
+
expect(token).to.be.a("string")
|
|
48
|
+
expect(token).is.not.null
|
|
49
|
+
// Validates token
|
|
50
|
+
const validationResp = provider.validateToken(token)
|
|
51
|
+
expect(validationResp).is.not.null
|
|
52
|
+
expect(validationResp.isValid).is.true
|
|
53
|
+
expect(validationResp["isExpired"]).is.undefined
|
|
54
|
+
expect(validationResp["decodedToken"]).is.not.null
|
|
55
|
+
expect(validationResp["decodedToken"].userID).to.be.equals(123)
|
|
56
|
+
expect(validationResp["decodedToken"].exp).to.be.a("number")
|
|
57
|
+
expect(validationResp["decodedToken"].exp).to.be.above(Date.now() / 1000)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
test("Fails to validate invalid token", () => {
|
|
61
|
+
// Creates token
|
|
62
|
+
const token = provider.createToken({ userID: 123 }, "7d", privateKey)
|
|
63
|
+
// Validates token
|
|
64
|
+
const validationResp = provider.validateToken(token + "123")
|
|
65
|
+
expect(validationResp).is.not.null
|
|
66
|
+
expect(validationResp.isValid).is.false
|
|
67
|
+
expect(validationResp["isExpired"]).is.undefined
|
|
68
|
+
expect(validationResp["decodedToken"]).to.undefined
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test("Fails to validate expired token", () => {
|
|
72
|
+
// Creates token
|
|
73
|
+
const token = provider.createToken({ userID: 123 }, "-7d", privateKey)
|
|
74
|
+
// Validates token
|
|
75
|
+
const validationResp = provider.validateToken(token)
|
|
76
|
+
expect(validationResp).is.not.null
|
|
77
|
+
expect(validationResp.isValid).is.false
|
|
78
|
+
expect(validationResp["isExpired"]).is.true
|
|
79
|
+
expect(validationResp["decodedToken"]).to.undefined
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
test("Fails to validate foreign token", () => {
|
|
83
|
+
// Validates token
|
|
84
|
+
const validationResp = provider.validateToken(foreignToken)
|
|
85
|
+
expect(validationResp).is.not.null
|
|
86
|
+
expect(validationResp.isValid).is.false
|
|
87
|
+
expect(validationResp["isExpired"]).is.undefined
|
|
88
|
+
expect(validationResp["decodedToken"]).to.undefined
|
|
89
|
+
})
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
export {}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// get console ref and mock before logger import
|
|
2
|
+
const consoleProxy = console
|
|
3
|
+
const mock = jest.spyOn(consoleProxy, "log")
|
|
4
|
+
// import logger after first ref
|
|
5
|
+
import Logger from "../../src/Logger/Logger"
|
|
6
|
+
// get console reference after logger import
|
|
7
|
+
const transactionID = "123-456"
|
|
8
|
+
|
|
9
|
+
function setContainerFlag(isContainer: boolean) {
|
|
10
|
+
if (isContainer) {
|
|
11
|
+
process.env["HYBRIDLESS_RUNTIME"] = "true"
|
|
12
|
+
} else {
|
|
13
|
+
process.env["HYBRIDLESS_RUNTIME"] = undefined
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function fixLogTypePrefix(logType: string) {
|
|
18
|
+
if (logType == "exception") return "error"
|
|
19
|
+
if (logType == "warning") return "warn"
|
|
20
|
+
if (logType == "log") return "info"
|
|
21
|
+
return logType
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function testLogs(isContainer: boolean, provider?: Logger) {
|
|
25
|
+
const type = isContainer ? "container" : "serverless"
|
|
26
|
+
const loggerType = !provider ? "Console" : "Logger"
|
|
27
|
+
const localProvider = provider || console
|
|
28
|
+
|
|
29
|
+
test(`${type} - ${loggerType} Log - Suppress sensitive info`, async () => {
|
|
30
|
+
setContainerFlag(isContainer)
|
|
31
|
+
localProvider.log("TEST", { password: "123" })
|
|
32
|
+
expect(consoleProxy.log).toHaveBeenNthCalledWith(
|
|
33
|
+
1,
|
|
34
|
+
expect.stringContaining(
|
|
35
|
+
(isContainer ? `${transactionID} ` : "") + "[INFO] [Logger.test.ts:",
|
|
36
|
+
),
|
|
37
|
+
)
|
|
38
|
+
expect(consoleProxy.log).toHaveBeenNthCalledWith(
|
|
39
|
+
1,
|
|
40
|
+
expect.stringContaining("] TEST **SUPPRESSED_SENSITIVE_DATA**"),
|
|
41
|
+
)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
test(`${type} - ${loggerType} Log - Suppress sensitive info (array)`, async () => {
|
|
45
|
+
setContainerFlag(isContainer)
|
|
46
|
+
localProvider.log("TEST2", [{ password: "123" }])
|
|
47
|
+
expect(consoleProxy.log).toHaveBeenNthCalledWith(
|
|
48
|
+
1,
|
|
49
|
+
expect.stringContaining(
|
|
50
|
+
(isContainer ? `${transactionID} ` : "") + "[INFO] [Logger.test.ts:",
|
|
51
|
+
),
|
|
52
|
+
)
|
|
53
|
+
expect(consoleProxy.log).toHaveBeenNthCalledWith(
|
|
54
|
+
1,
|
|
55
|
+
expect.stringContaining("] TEST2 **SUPPRESSED_SENSITIVE_DATA**"),
|
|
56
|
+
)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
for (const logType of [
|
|
60
|
+
"log",
|
|
61
|
+
"debug",
|
|
62
|
+
"info",
|
|
63
|
+
"warn",
|
|
64
|
+
"warning",
|
|
65
|
+
"error",
|
|
66
|
+
"exception",
|
|
67
|
+
]) {
|
|
68
|
+
test(`${type} - ${loggerType} ${logType}`, async () => {
|
|
69
|
+
setContainerFlag(isContainer)
|
|
70
|
+
localProvider[logType](logType.toUpperCase())
|
|
71
|
+
// alias
|
|
72
|
+
const logTypePrefix = fixLogTypePrefix(logType)
|
|
73
|
+
expect(consoleProxy.log).toHaveBeenNthCalledWith(
|
|
74
|
+
1,
|
|
75
|
+
expect.stringContaining(
|
|
76
|
+
(isContainer ? `${transactionID} ` : "") +
|
|
77
|
+
`[${logTypePrefix.toUpperCase()}] [Logger.test.ts:`,
|
|
78
|
+
),
|
|
79
|
+
)
|
|
80
|
+
expect(consoleProxy.log).toHaveBeenNthCalledWith(
|
|
81
|
+
1,
|
|
82
|
+
expect.stringContaining(`] ${logType.toUpperCase()}`),
|
|
83
|
+
)
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
describe("Logger", () => {
|
|
89
|
+
beforeEach(() => {
|
|
90
|
+
mock.mockClear()
|
|
91
|
+
})
|
|
92
|
+
const provider = new Logger(
|
|
93
|
+
{
|
|
94
|
+
logLevel: "DEBUG",
|
|
95
|
+
sensitiveFilteringKeywords: true,
|
|
96
|
+
},
|
|
97
|
+
transactionID,
|
|
98
|
+
)
|
|
99
|
+
provider.notGlobalLogger()
|
|
100
|
+
// Test serverless logs
|
|
101
|
+
testLogs(false, provider)
|
|
102
|
+
testLogs(false)
|
|
103
|
+
// Test container logs
|
|
104
|
+
testLogs(true, provider)
|
|
105
|
+
testLogs(true)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
export {}
|