@labdigital/commercetools-mock 2.0.0 → 2.2.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/dist/index.cjs +177 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +177 -26
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/ctMock.ts +49 -29
- package/src/exceptions.ts +4 -0
- package/src/helpers.ts +18 -0
- package/src/lib/password.ts +7 -0
- package/src/oauth/server.ts +137 -3
- package/src/oauth/store.ts +13 -0
- package/src/repositories/customer.ts +30 -8
- package/src/services/my-customer.ts +2 -1
package/dist/index.cjs
CHANGED
|
@@ -37,8 +37,8 @@ module.exports = __toCommonJS(src_exports);
|
|
|
37
37
|
|
|
38
38
|
// src/ctMock.ts
|
|
39
39
|
var import_express6 = __toESM(require("express"), 1);
|
|
40
|
-
var import_supertest = __toESM(require("supertest"), 1);
|
|
41
40
|
var import_morgan = __toESM(require("morgan"), 1);
|
|
41
|
+
var import_light_my_request = __toESM(require("light-my-request"), 1);
|
|
42
42
|
var import_node = require("msw/node");
|
|
43
43
|
var import_msw = require("msw");
|
|
44
44
|
|
|
@@ -53,10 +53,12 @@ var import_assert = __toESM(require("assert"), 1);
|
|
|
53
53
|
var CommercetoolsError = class extends Error {
|
|
54
54
|
info;
|
|
55
55
|
statusCode;
|
|
56
|
+
errors;
|
|
56
57
|
constructor(info, statusCode = 400) {
|
|
57
58
|
super(info.message);
|
|
58
59
|
this.info = info;
|
|
59
60
|
this.statusCode = statusCode || 500;
|
|
61
|
+
this.errors = info.errors ?? [];
|
|
60
62
|
}
|
|
61
63
|
};
|
|
62
64
|
|
|
@@ -101,6 +103,18 @@ var queryParamsValue = (value) => {
|
|
|
101
103
|
return void 0;
|
|
102
104
|
};
|
|
103
105
|
var cloneObject = (o) => JSON.parse(JSON.stringify(o));
|
|
106
|
+
var mapHeaderType = (outgoingHttpHeaders) => {
|
|
107
|
+
const headersInit = {};
|
|
108
|
+
for (const key in outgoingHttpHeaders) {
|
|
109
|
+
const value = outgoingHttpHeaders[key];
|
|
110
|
+
if (Array.isArray(value)) {
|
|
111
|
+
headersInit[key] = value.join(", ");
|
|
112
|
+
} else if (value !== void 0) {
|
|
113
|
+
headersInit[key] = value.toString();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return headersInit;
|
|
117
|
+
};
|
|
104
118
|
|
|
105
119
|
// src/lib/expandParser.ts
|
|
106
120
|
var parseExpandClause = (clause) => {
|
|
@@ -1256,6 +1270,16 @@ var OAuth2Store = class {
|
|
|
1256
1270
|
this.tokens.push(token);
|
|
1257
1271
|
return token;
|
|
1258
1272
|
}
|
|
1273
|
+
getCustomerToken(scope, customerId) {
|
|
1274
|
+
const token = {
|
|
1275
|
+
access_token: (0, import_crypto.randomBytes)(16).toString("base64"),
|
|
1276
|
+
token_type: "Bearer",
|
|
1277
|
+
expires_in: 172800,
|
|
1278
|
+
scope: scope ? `${scope} custome_id:${customerId}` : `customer_id: ${customerId}`
|
|
1279
|
+
};
|
|
1280
|
+
this.tokens.push(token);
|
|
1281
|
+
return token;
|
|
1282
|
+
}
|
|
1259
1283
|
validateToken(token) {
|
|
1260
1284
|
if (!this.validate)
|
|
1261
1285
|
return true;
|
|
@@ -1277,16 +1301,36 @@ var getBearerToken = (request) => {
|
|
|
1277
1301
|
return void 0;
|
|
1278
1302
|
};
|
|
1279
1303
|
|
|
1304
|
+
// src/lib/password.ts
|
|
1305
|
+
var hashPassword = (clearPassword) => Buffer.from(clearPassword).toString("base64");
|
|
1306
|
+
|
|
1280
1307
|
// src/oauth/server.ts
|
|
1281
1308
|
var OAuth2Server = class {
|
|
1282
1309
|
store;
|
|
1310
|
+
customerRepository;
|
|
1283
1311
|
constructor(options) {
|
|
1284
1312
|
this.store = new OAuth2Store(options.validate);
|
|
1285
1313
|
}
|
|
1314
|
+
setCustomerRepository(repository) {
|
|
1315
|
+
this.customerRepository = repository;
|
|
1316
|
+
}
|
|
1286
1317
|
createRouter() {
|
|
1287
1318
|
const router = import_express.default.Router();
|
|
1288
1319
|
router.use(import_body_parser.default.urlencoded({ extended: true }));
|
|
1320
|
+
router.use(this.validateClientCredentials.bind(this));
|
|
1289
1321
|
router.post("/token", this.tokenHandler.bind(this));
|
|
1322
|
+
router.post(
|
|
1323
|
+
"/:projectKey/customers/token",
|
|
1324
|
+
this.customerTokenHandler.bind(this)
|
|
1325
|
+
);
|
|
1326
|
+
router.post(
|
|
1327
|
+
"/:projectKey/in-store/key=:storeKey/customers/token",
|
|
1328
|
+
this.inStoreCustomerTokenHandler.bind(this)
|
|
1329
|
+
);
|
|
1330
|
+
router.post(
|
|
1331
|
+
"/:projectKey/anonymous/token",
|
|
1332
|
+
this.anonymousTokenHandler.bind(this)
|
|
1333
|
+
);
|
|
1290
1334
|
return router;
|
|
1291
1335
|
}
|
|
1292
1336
|
createMiddleware() {
|
|
@@ -1317,7 +1361,7 @@ var OAuth2Server = class {
|
|
|
1317
1361
|
next();
|
|
1318
1362
|
};
|
|
1319
1363
|
}
|
|
1320
|
-
async
|
|
1364
|
+
async validateClientCredentials(request, response, next) {
|
|
1321
1365
|
const authHeader = request.header("Authorization");
|
|
1322
1366
|
if (!authHeader) {
|
|
1323
1367
|
return next(
|
|
@@ -1342,6 +1386,13 @@ var OAuth2Server = class {
|
|
|
1342
1386
|
)
|
|
1343
1387
|
);
|
|
1344
1388
|
}
|
|
1389
|
+
request.credentials = {
|
|
1390
|
+
clientId: credentials.name,
|
|
1391
|
+
clientSecret: credentials.pass
|
|
1392
|
+
};
|
|
1393
|
+
next();
|
|
1394
|
+
}
|
|
1395
|
+
async tokenHandler(request, response, next) {
|
|
1345
1396
|
const grantType = request.query.grant_type || request.body.grant_type;
|
|
1346
1397
|
if (!grantType) {
|
|
1347
1398
|
return next(
|
|
@@ -1356,8 +1407,15 @@ var OAuth2Server = class {
|
|
|
1356
1407
|
}
|
|
1357
1408
|
if (grantType === "client_credentials") {
|
|
1358
1409
|
const token = this.store.getClientToken(
|
|
1359
|
-
credentials.
|
|
1360
|
-
credentials.
|
|
1410
|
+
request.credentials.clientId,
|
|
1411
|
+
request.credentials.clientSecret,
|
|
1412
|
+
request.query.scope?.toString()
|
|
1413
|
+
);
|
|
1414
|
+
return response.status(200).send(token);
|
|
1415
|
+
} else if (grantType === "refresh_token") {
|
|
1416
|
+
const token = this.store.getClientToken(
|
|
1417
|
+
request.credentials.clientId,
|
|
1418
|
+
request.credentials.clientSecret,
|
|
1361
1419
|
request.query.scope?.toString()
|
|
1362
1420
|
);
|
|
1363
1421
|
return response.status(200).send(token);
|
|
@@ -1373,6 +1431,69 @@ var OAuth2Server = class {
|
|
|
1373
1431
|
);
|
|
1374
1432
|
}
|
|
1375
1433
|
}
|
|
1434
|
+
async customerTokenHandler(request, response, next) {
|
|
1435
|
+
const grantType = request.query.grant_type || request.body.grant_type;
|
|
1436
|
+
if (!grantType) {
|
|
1437
|
+
return next(
|
|
1438
|
+
new CommercetoolsError(
|
|
1439
|
+
{
|
|
1440
|
+
code: "invalid_request",
|
|
1441
|
+
message: "Missing required parameter: grant_type."
|
|
1442
|
+
},
|
|
1443
|
+
400
|
|
1444
|
+
)
|
|
1445
|
+
);
|
|
1446
|
+
}
|
|
1447
|
+
if (grantType === "password") {
|
|
1448
|
+
const username = request.query.username || request.body.username;
|
|
1449
|
+
const password = hashPassword(
|
|
1450
|
+
request.query.password || request.body.password
|
|
1451
|
+
);
|
|
1452
|
+
const scope = request.query.scope?.toString() || request.body.scope?.toString();
|
|
1453
|
+
const result = this.customerRepository.query(
|
|
1454
|
+
{ projectKey: request.params.projectKey },
|
|
1455
|
+
{
|
|
1456
|
+
where: [`email = "${username}"`, `password = "${password}"`]
|
|
1457
|
+
}
|
|
1458
|
+
);
|
|
1459
|
+
if (result.count === 0) {
|
|
1460
|
+
return next(
|
|
1461
|
+
new CommercetoolsError(
|
|
1462
|
+
{
|
|
1463
|
+
code: "invalid_customer_account_credentials",
|
|
1464
|
+
message: "Customer account with the given credentials not found."
|
|
1465
|
+
},
|
|
1466
|
+
400
|
|
1467
|
+
)
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
const customer = result.results[0];
|
|
1471
|
+
const token = this.store.getCustomerToken(scope, customer.id);
|
|
1472
|
+
return response.status(200).send(token);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
async inStoreCustomerTokenHandler(request, response, next) {
|
|
1476
|
+
return next(
|
|
1477
|
+
new CommercetoolsError(
|
|
1478
|
+
{
|
|
1479
|
+
code: "invalid_client",
|
|
1480
|
+
message: "Not implemented yet in commercetools-mock"
|
|
1481
|
+
},
|
|
1482
|
+
401
|
|
1483
|
+
)
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1486
|
+
async anonymousTokenHandler(request, response, next) {
|
|
1487
|
+
return next(
|
|
1488
|
+
new CommercetoolsError(
|
|
1489
|
+
{
|
|
1490
|
+
code: "invalid_client",
|
|
1491
|
+
message: "Not implemented yet in commercetools-mock"
|
|
1492
|
+
},
|
|
1493
|
+
401
|
|
1494
|
+
)
|
|
1495
|
+
);
|
|
1496
|
+
}
|
|
1376
1497
|
};
|
|
1377
1498
|
|
|
1378
1499
|
// src/projectAPI.ts
|
|
@@ -2849,11 +2970,29 @@ var CustomerRepository = class extends AbstractResourceRepository {
|
|
|
2849
2970
|
return "customer";
|
|
2850
2971
|
}
|
|
2851
2972
|
create(context, draft) {
|
|
2973
|
+
const results = this._storage.query(context.projectKey, this.getTypeId(), {
|
|
2974
|
+
where: [`email="${draft.email.toLocaleLowerCase()}"`]
|
|
2975
|
+
});
|
|
2976
|
+
if (results.count > 0) {
|
|
2977
|
+
throw new CommercetoolsError({
|
|
2978
|
+
code: "CustomerAlreadyExists",
|
|
2979
|
+
statusCode: 400,
|
|
2980
|
+
message: "There is already an existing customer with the provided email.",
|
|
2981
|
+
errors: [
|
|
2982
|
+
{
|
|
2983
|
+
code: "DuplicateField",
|
|
2984
|
+
message: `Customer with email '${draft.email}' already exists.`,
|
|
2985
|
+
duplicateValue: draft.email,
|
|
2986
|
+
field: "email"
|
|
2987
|
+
}
|
|
2988
|
+
]
|
|
2989
|
+
});
|
|
2990
|
+
}
|
|
2852
2991
|
const resource = {
|
|
2853
2992
|
...getBaseResourceProperties(),
|
|
2854
2993
|
authenticationMode: draft.authenticationMode || "Password",
|
|
2855
|
-
email: draft.email,
|
|
2856
|
-
password: draft.password ?
|
|
2994
|
+
email: draft.email.toLowerCase(),
|
|
2995
|
+
password: draft.password ? hashPassword(draft.password) : void 0,
|
|
2857
2996
|
isEmailVerified: draft.isEmailVerified || false,
|
|
2858
2997
|
addresses: []
|
|
2859
2998
|
};
|
|
@@ -2891,7 +3030,7 @@ var CustomerRepository = class extends AbstractResourceRepository {
|
|
|
2891
3030
|
return;
|
|
2892
3031
|
}
|
|
2893
3032
|
if (authMode === "Password") {
|
|
2894
|
-
resource.password = password ?
|
|
3033
|
+
resource.password = password ? hashPassword(password) : void 0;
|
|
2895
3034
|
return;
|
|
2896
3035
|
}
|
|
2897
3036
|
throw new CommercetoolsError(
|
|
@@ -6021,7 +6160,7 @@ var MyCustomerService = class extends AbstractService {
|
|
|
6021
6160
|
}
|
|
6022
6161
|
signIn(request, response) {
|
|
6023
6162
|
const { email, password } = request.body;
|
|
6024
|
-
const encodedPassword =
|
|
6163
|
+
const encodedPassword = hashPassword(password);
|
|
6025
6164
|
const result = this.repository.query(getRepositoryContext(request), {
|
|
6026
6165
|
where: [`email = "${email}"`, `password = "${encodedPassword}"`]
|
|
6027
6166
|
});
|
|
@@ -6458,6 +6597,7 @@ var CommercetoolsMock = class {
|
|
|
6458
6597
|
}
|
|
6459
6598
|
createApp(options) {
|
|
6460
6599
|
this._repositories = createRepositories(this._storage);
|
|
6600
|
+
this._oauth2.setCustomerRepository(this._repositories.customer);
|
|
6461
6601
|
const app = (0, import_express6.default)();
|
|
6462
6602
|
const projectRouter = import_express6.default.Router({ mergeParams: true });
|
|
6463
6603
|
projectRouter.use(import_express6.default.json());
|
|
@@ -6483,6 +6623,13 @@ var CommercetoolsMock = class {
|
|
|
6483
6623
|
);
|
|
6484
6624
|
app.use((err, req, resp, next) => {
|
|
6485
6625
|
if (err instanceof CommercetoolsError) {
|
|
6626
|
+
if (err.errors?.length > 0) {
|
|
6627
|
+
return resp.status(err.statusCode).send({
|
|
6628
|
+
statusCode: err.statusCode,
|
|
6629
|
+
message: err.message,
|
|
6630
|
+
errors: err.errors
|
|
6631
|
+
});
|
|
6632
|
+
}
|
|
6486
6633
|
return resp.status(err.statusCode).send({
|
|
6487
6634
|
statusCode: err.statusCode,
|
|
6488
6635
|
message: err.message,
|
|
@@ -6506,42 +6653,46 @@ var CommercetoolsMock = class {
|
|
|
6506
6653
|
_globalListeners.forEach((listener) => listener.close());
|
|
6507
6654
|
}
|
|
6508
6655
|
}
|
|
6509
|
-
const
|
|
6656
|
+
const server = this.app;
|
|
6510
6657
|
this._mswServer = (0, import_node.setupServer)(
|
|
6511
6658
|
import_msw.http.post(`${this.options.authHost}/oauth/*`, async ({ request }) => {
|
|
6512
|
-
const
|
|
6659
|
+
const body = await request.text();
|
|
6513
6660
|
const url = new URL(request.url);
|
|
6514
|
-
const
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6661
|
+
const headers = copyHeaders(request.headers);
|
|
6662
|
+
const res = await (0, import_light_my_request.default)(server).post(url.pathname + "?" + url.searchParams.toString()).body(body).headers(headers).end();
|
|
6663
|
+
return new import_msw.HttpResponse(res.body, {
|
|
6664
|
+
status: res.statusCode,
|
|
6665
|
+
headers: mapHeaderType(res.headers)
|
|
6518
6666
|
});
|
|
6519
6667
|
}),
|
|
6520
6668
|
import_msw.http.get(`${this.options.apiHost}/*`, async ({ request }) => {
|
|
6521
6669
|
const body = await request.text();
|
|
6522
6670
|
const url = new URL(request.url);
|
|
6523
|
-
const
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6671
|
+
const headers = copyHeaders(request.headers);
|
|
6672
|
+
const res = await (0, import_light_my_request.default)(server).get(url.pathname + "?" + url.searchParams.toString()).body(body).headers(headers).end();
|
|
6673
|
+
return new import_msw.HttpResponse(res.body, {
|
|
6674
|
+
status: res.statusCode,
|
|
6675
|
+
headers: mapHeaderType(res.headers)
|
|
6527
6676
|
});
|
|
6528
6677
|
}),
|
|
6529
6678
|
import_msw.http.post(`${this.options.apiHost}/*`, async ({ request }) => {
|
|
6530
6679
|
const body = await request.text();
|
|
6531
6680
|
const url = new URL(request.url);
|
|
6532
|
-
const
|
|
6533
|
-
|
|
6534
|
-
|
|
6535
|
-
|
|
6681
|
+
const headers = copyHeaders(request.headers);
|
|
6682
|
+
const res = await (0, import_light_my_request.default)(server).post(url.pathname + "?" + url.searchParams.toString()).body(body).headers(headers).end();
|
|
6683
|
+
return new import_msw.HttpResponse(res.body, {
|
|
6684
|
+
status: res.statusCode,
|
|
6685
|
+
headers: mapHeaderType(res.headers)
|
|
6536
6686
|
});
|
|
6537
6687
|
}),
|
|
6538
6688
|
import_msw.http.delete(`${this.options.apiHost}/*`, async ({ request }) => {
|
|
6539
6689
|
const body = await request.text();
|
|
6540
6690
|
const url = new URL(request.url);
|
|
6541
|
-
const
|
|
6542
|
-
|
|
6543
|
-
|
|
6544
|
-
|
|
6691
|
+
const headers = copyHeaders(request.headers);
|
|
6692
|
+
const res = await (0, import_light_my_request.default)(server).delete(url.pathname + "?" + url.searchParams.toString()).body(body).headers(headers).end();
|
|
6693
|
+
return new import_msw.HttpResponse(res.body, {
|
|
6694
|
+
status: res.statusCode,
|
|
6695
|
+
headers: mapHeaderType(res.headers)
|
|
6545
6696
|
});
|
|
6546
6697
|
})
|
|
6547
6698
|
);
|