@labdigital/commercetools-mock 2.0.0 → 2.1.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.js CHANGED
@@ -16,10 +16,12 @@ import assert from "assert";
16
16
  var CommercetoolsError = class extends Error {
17
17
  info;
18
18
  statusCode;
19
+ errors;
19
20
  constructor(info, statusCode = 400) {
20
21
  super(info.message);
21
22
  this.info = info;
22
23
  this.statusCode = statusCode || 500;
24
+ this.errors = info.errors ?? [];
23
25
  }
24
26
  };
25
27
 
@@ -1219,6 +1221,16 @@ var OAuth2Store = class {
1219
1221
  this.tokens.push(token);
1220
1222
  return token;
1221
1223
  }
1224
+ getCustomerToken(scope, customerId) {
1225
+ const token = {
1226
+ access_token: randomBytes(16).toString("base64"),
1227
+ token_type: "Bearer",
1228
+ expires_in: 172800,
1229
+ scope: scope ? `${scope} custome_id:${customerId}` : `customer_id: ${customerId}`
1230
+ };
1231
+ this.tokens.push(token);
1232
+ return token;
1233
+ }
1222
1234
  validateToken(token) {
1223
1235
  if (!this.validate)
1224
1236
  return true;
@@ -1240,16 +1252,36 @@ var getBearerToken = (request) => {
1240
1252
  return void 0;
1241
1253
  };
1242
1254
 
1255
+ // src/lib/password.ts
1256
+ var hashPassword = (clearPassword) => Buffer.from(clearPassword).toString("base64");
1257
+
1243
1258
  // src/oauth/server.ts
1244
1259
  var OAuth2Server = class {
1245
1260
  store;
1261
+ customerRepository;
1246
1262
  constructor(options) {
1247
1263
  this.store = new OAuth2Store(options.validate);
1248
1264
  }
1265
+ setCustomerRepository(repository) {
1266
+ this.customerRepository = repository;
1267
+ }
1249
1268
  createRouter() {
1250
1269
  const router = express.Router();
1251
1270
  router.use(bodyParser.urlencoded({ extended: true }));
1271
+ router.use(this.validateClientCredentials.bind(this));
1252
1272
  router.post("/token", this.tokenHandler.bind(this));
1273
+ router.post(
1274
+ "/:projectKey/customers/token",
1275
+ this.customerTokenHandler.bind(this)
1276
+ );
1277
+ router.post(
1278
+ "/:projectKey/in-store/key=:storeKey/customers/token",
1279
+ this.inStoreCustomerTokenHandler.bind(this)
1280
+ );
1281
+ router.post(
1282
+ "/:projectKey/anonymous/token",
1283
+ this.anonymousTokenHandler.bind(this)
1284
+ );
1253
1285
  return router;
1254
1286
  }
1255
1287
  createMiddleware() {
@@ -1280,7 +1312,7 @@ var OAuth2Server = class {
1280
1312
  next();
1281
1313
  };
1282
1314
  }
1283
- async tokenHandler(request, response, next) {
1315
+ async validateClientCredentials(request, response, next) {
1284
1316
  const authHeader = request.header("Authorization");
1285
1317
  if (!authHeader) {
1286
1318
  return next(
@@ -1305,6 +1337,13 @@ var OAuth2Server = class {
1305
1337
  )
1306
1338
  );
1307
1339
  }
1340
+ request.credentials = {
1341
+ clientId: credentials.name,
1342
+ clientSecret: credentials.pass
1343
+ };
1344
+ next();
1345
+ }
1346
+ async tokenHandler(request, response, next) {
1308
1347
  const grantType = request.query.grant_type || request.body.grant_type;
1309
1348
  if (!grantType) {
1310
1349
  return next(
@@ -1319,8 +1358,15 @@ var OAuth2Server = class {
1319
1358
  }
1320
1359
  if (grantType === "client_credentials") {
1321
1360
  const token = this.store.getClientToken(
1322
- credentials.name,
1323
- credentials.pass,
1361
+ request.credentials.clientId,
1362
+ request.credentials.clientSecret,
1363
+ request.query.scope?.toString()
1364
+ );
1365
+ return response.status(200).send(token);
1366
+ } else if (grantType === "refresh_token") {
1367
+ const token = this.store.getClientToken(
1368
+ request.credentials.clientId,
1369
+ request.credentials.clientSecret,
1324
1370
  request.query.scope?.toString()
1325
1371
  );
1326
1372
  return response.status(200).send(token);
@@ -1336,6 +1382,69 @@ var OAuth2Server = class {
1336
1382
  );
1337
1383
  }
1338
1384
  }
1385
+ async customerTokenHandler(request, response, next) {
1386
+ const grantType = request.query.grant_type || request.body.grant_type;
1387
+ if (!grantType) {
1388
+ return next(
1389
+ new CommercetoolsError(
1390
+ {
1391
+ code: "invalid_request",
1392
+ message: "Missing required parameter: grant_type."
1393
+ },
1394
+ 400
1395
+ )
1396
+ );
1397
+ }
1398
+ if (grantType === "password") {
1399
+ const username = request.query.username || request.body.username;
1400
+ const password = hashPassword(
1401
+ request.query.password || request.body.password
1402
+ );
1403
+ const scope = request.query.scope?.toString() || request.body.scope?.toString();
1404
+ const result = this.customerRepository.query(
1405
+ { projectKey: request.params.projectKey },
1406
+ {
1407
+ where: [`email = "${username}"`, `password = "${password}"`]
1408
+ }
1409
+ );
1410
+ if (result.count === 0) {
1411
+ return next(
1412
+ new CommercetoolsError(
1413
+ {
1414
+ code: "invalid_customer_account_credentials",
1415
+ message: "Customer account with the given credentials not found."
1416
+ },
1417
+ 400
1418
+ )
1419
+ );
1420
+ }
1421
+ const customer = result.results[0];
1422
+ const token = this.store.getCustomerToken(scope, customer.id);
1423
+ return response.status(200).send(token);
1424
+ }
1425
+ }
1426
+ async inStoreCustomerTokenHandler(request, response, next) {
1427
+ return next(
1428
+ new CommercetoolsError(
1429
+ {
1430
+ code: "invalid_client",
1431
+ message: "Not implemented yet in commercetools-mock"
1432
+ },
1433
+ 401
1434
+ )
1435
+ );
1436
+ }
1437
+ async anonymousTokenHandler(request, response, next) {
1438
+ return next(
1439
+ new CommercetoolsError(
1440
+ {
1441
+ code: "invalid_client",
1442
+ message: "Not implemented yet in commercetools-mock"
1443
+ },
1444
+ 401
1445
+ )
1446
+ );
1447
+ }
1339
1448
  };
1340
1449
 
1341
1450
  // src/projectAPI.ts
@@ -2812,11 +2921,29 @@ var CustomerRepository = class extends AbstractResourceRepository {
2812
2921
  return "customer";
2813
2922
  }
2814
2923
  create(context, draft) {
2924
+ const results = this._storage.query(context.projectKey, this.getTypeId(), {
2925
+ where: [`email="${draft.email.toLocaleLowerCase()}"`]
2926
+ });
2927
+ if (results.count > 0) {
2928
+ throw new CommercetoolsError({
2929
+ code: "CustomerAlreadyExists",
2930
+ statusCode: 400,
2931
+ message: "There is already an existing customer with the provided email.",
2932
+ errors: [
2933
+ {
2934
+ code: "DuplicateField",
2935
+ message: `Customer with email '${draft.email}' already exists.`,
2936
+ duplicateValue: draft.email,
2937
+ field: "email"
2938
+ }
2939
+ ]
2940
+ });
2941
+ }
2815
2942
  const resource = {
2816
2943
  ...getBaseResourceProperties(),
2817
2944
  authenticationMode: draft.authenticationMode || "Password",
2818
- email: draft.email,
2819
- password: draft.password ? Buffer.from(draft.password).toString("base64") : void 0,
2945
+ email: draft.email.toLowerCase(),
2946
+ password: draft.password ? hashPassword(draft.password) : void 0,
2820
2947
  isEmailVerified: draft.isEmailVerified || false,
2821
2948
  addresses: []
2822
2949
  };
@@ -2854,7 +2981,7 @@ var CustomerRepository = class extends AbstractResourceRepository {
2854
2981
  return;
2855
2982
  }
2856
2983
  if (authMode === "Password") {
2857
- resource.password = password ? Buffer.from(password).toString("base64") : void 0;
2984
+ resource.password = password ? hashPassword(password) : void 0;
2858
2985
  return;
2859
2986
  }
2860
2987
  throw new CommercetoolsError(
@@ -5984,7 +6111,7 @@ var MyCustomerService = class extends AbstractService {
5984
6111
  }
5985
6112
  signIn(request, response) {
5986
6113
  const { email, password } = request.body;
5987
- const encodedPassword = Buffer.from(password).toString("base64");
6114
+ const encodedPassword = hashPassword(password);
5988
6115
  const result = this.repository.query(getRepositoryContext(request), {
5989
6116
  where: [`email = "${email}"`, `password = "${encodedPassword}"`]
5990
6117
  });
@@ -6421,6 +6548,7 @@ var CommercetoolsMock = class {
6421
6548
  }
6422
6549
  createApp(options) {
6423
6550
  this._repositories = createRepositories(this._storage);
6551
+ this._oauth2.setCustomerRepository(this._repositories.customer);
6424
6552
  const app = express2();
6425
6553
  const projectRouter = express2.Router({ mergeParams: true });
6426
6554
  projectRouter.use(express2.json());
@@ -6446,6 +6574,13 @@ var CommercetoolsMock = class {
6446
6574
  );
6447
6575
  app.use((err, req, resp, next) => {
6448
6576
  if (err instanceof CommercetoolsError) {
6577
+ if (err.errors?.length > 0) {
6578
+ return resp.status(err.statusCode).send({
6579
+ statusCode: err.statusCode,
6580
+ message: err.message,
6581
+ errors: err.errors
6582
+ });
6583
+ }
6449
6584
  return resp.status(err.statusCode).send({
6450
6585
  statusCode: err.statusCode,
6451
6586
  message: err.message,