@labdigital/commercetools-mock 2.36.0 → 2.37.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@labdigital/commercetools-mock",
3
- "version": "2.36.0",
3
+ "version": "2.37.0",
4
4
  "license": "MIT",
5
5
  "author": "Michael van Tellingen",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  "devDependencies": {
36
36
  "@changesets/changelog-github": "^0.5.0",
37
37
  "@changesets/cli": "^2.27.1",
38
- "@commercetools/platform-sdk": "7.11.0",
38
+ "@commercetools/platform-sdk": "7.17.0",
39
39
  "@stylistic/eslint-plugin": "^1.6.2",
40
40
  "@types/basic-auth": "^1.1.8",
41
41
  "@types/body-parser": "^1.19.5",
@@ -130,4 +130,46 @@ describe("OAuth2Server", () => {
130
130
  });
131
131
  });
132
132
  });
133
+
134
+ describe("POST /:projectKey/in-store/key=:storeKey/customers/token", () => {
135
+ it("should return a token for in-store customer access", async () => {
136
+ const projectKey = "test-project";
137
+ const storeKey = "test-store";
138
+
139
+ storage.add(projectKey, "customer", {
140
+ ...getBaseResourceProperties(),
141
+ email: "j.doe@example.org",
142
+ password: hashPassword("password"),
143
+ addresses: [],
144
+ authenticationMode: "password",
145
+ isEmailVerified: true,
146
+ stores: [
147
+ {
148
+ typeId: "store",
149
+ key: storeKey,
150
+ },
151
+ ],
152
+ });
153
+
154
+ const response = await supertest(app)
155
+ .post(`/${projectKey}/in-store/key=${storeKey}/customers/token`)
156
+ .auth("validClientId", "validClientSecret")
157
+ .query({
158
+ grant_type: "password",
159
+ username: "j.doe@example.org",
160
+ password: "password",
161
+ scope: `${projectKey}:manage_my_profile`,
162
+ })
163
+ .send();
164
+
165
+ expect(response.status).toBe(200);
166
+ expect(response.body).toEqual({
167
+ scope: expect.stringMatching(/customer_id:([^\s]+)/),
168
+ access_token: expect.stringMatching(/\S{8,}==$/),
169
+ refresh_token: expect.stringMatching(/test-project:\S{8,}==$/),
170
+ expires_in: 172800,
171
+ token_type: "Bearer",
172
+ });
173
+ });
174
+ });
133
175
  });
@@ -287,15 +287,52 @@ export class OAuth2Server {
287
287
  response: Response,
288
288
  next: NextFunction,
289
289
  ) {
290
- return next(
291
- new CommercetoolsError<InvalidClientError>(
290
+ const projectKey = request.params.projectKey;
291
+ const storeKey = request.params.storeKey;
292
+ const grantType = request.query.grant_type || request.body.grant_type;
293
+ if (!grantType) {
294
+ return next(
295
+ new CommercetoolsError<InvalidRequestError>(
296
+ {
297
+ code: "invalid_request",
298
+ message: "Missing required parameter: grant_type.",
299
+ },
300
+ 400,
301
+ ),
302
+ );
303
+ }
304
+
305
+ if (grantType === "password") {
306
+ const username = request.query.username || request.body.username;
307
+ const password = hashPassword(
308
+ request.query.password || request.body.password,
309
+ );
310
+ const scope =
311
+ request.query.scope?.toString() || request.body.scope?.toString();
312
+
313
+ const result = this.customerRepository.query(
314
+ { projectKey, storeKey },
292
315
  {
293
- code: "invalid_client",
294
- message: "Not implemented yet in commercetools-mock",
316
+ where: [`email = "${username}"`, `password = "${password}"`],
295
317
  },
296
- 401,
297
- ),
298
- );
318
+ );
319
+
320
+ if (result.count === 0) {
321
+ return next(
322
+ new CommercetoolsError<any>(
323
+ {
324
+ code: "invalid_customer_account_credentials",
325
+ message: "Customer account with the given credentials not found.",
326
+ },
327
+ 400,
328
+ ),
329
+ );
330
+ }
331
+
332
+ const customer = result.results[0];
333
+ const token = this.store.getCustomerToken(projectKey, customer.id, scope);
334
+ return response.status(200).send(token);
335
+ }
299
336
  }
300
337
 
301
338
  async anonymousTokenHandler(
@@ -5,6 +5,7 @@ import type {
5
5
  ProjectChangeCountriesAction,
6
6
  ProjectChangeCountryTaxRateFallbackEnabledAction,
7
7
  ProjectChangeCurrenciesAction,
8
+ ProjectChangeCustomerSearchStatusAction,
8
9
  ProjectChangeLanguagesAction,
9
10
  ProjectChangeMessagesConfigurationAction,
10
11
  ProjectChangeNameAction,
@@ -95,6 +96,18 @@ class ProjectUpdateHandler
95
96
  resource.currencies = currencies;
96
97
  }
97
98
 
99
+ changeCustomerSearchStatus(
100
+ context: RepositoryContext,
101
+ resource: Writable<Project>,
102
+ { status }: ProjectChangeCustomerSearchStatusAction,
103
+ ) {
104
+ if (!resource.searchIndexing?.customers) {
105
+ throw new Error("Invalid project state");
106
+ }
107
+ resource.searchIndexing.customers.status = status;
108
+ resource.searchIndexing.customers.lastModifiedAt = new Date().toISOString();
109
+ }
110
+
98
111
  changeLanguages(
99
112
  context: RepositoryContext,
100
113
  resource: Writable<Project>,
@@ -150,8 +163,20 @@ class ProjectUpdateHandler
150
163
  changeProductSearchIndexingEnabled(
151
164
  context: RepositoryContext,
152
165
  resource: Writable<Project>,
153
- { enabled }: ProjectChangeProductSearchIndexingEnabledAction,
166
+ { enabled, mode }: ProjectChangeProductSearchIndexingEnabledAction,
154
167
  ) {
168
+ if (mode === "ProductsSearch") {
169
+ if (!resource.searchIndexing?.productsSearch) {
170
+ throw new Error("Invalid project state");
171
+ }
172
+ resource.searchIndexing.productsSearch.status = enabled
173
+ ? "Activated"
174
+ : "Deactivated";
175
+ resource.searchIndexing.productsSearch.lastModifiedAt =
176
+ new Date().toISOString();
177
+ return;
178
+ }
179
+
155
180
  if (!resource.searchIndexing?.products) {
156
181
  throw new Error("Invalid project state");
157
182
  }
@@ -39,12 +39,18 @@ describe("Project", () => {
39
39
  },
40
40
  name: "",
41
41
  searchIndexing: {
42
+ customers: {
43
+ status: "Deactivated",
44
+ },
42
45
  orders: {
43
46
  status: "Deactivated",
44
47
  },
45
48
  products: {
46
49
  status: "Deactivated",
47
50
  },
51
+ productsSearch: {
52
+ status: "Deactivated",
53
+ },
48
54
  },
49
55
  trialUntil: "2018-12",
50
56
  } as Project);
@@ -87,9 +87,15 @@ export class InMemoryStorage extends AbstractStorage {
87
87
  products: {
88
88
  status: "Deactivated",
89
89
  },
90
+ productsSearch: {
91
+ status: "Deactivated",
92
+ },
90
93
  orders: {
91
94
  status: "Deactivated",
92
95
  },
96
+ customers: {
97
+ status: "Deactivated",
98
+ },
93
99
  },
94
100
  version: 1,
95
101
  };