@labdigital/commercetools-mock 2.66.0 → 3.0.0-beta.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.
Files changed (281) hide show
  1. package/README.md +31 -8
  2. package/dist/abstract-BKFcva6S.mjs +1044 -0
  3. package/dist/abstract-BKFcva6S.mjs.map +1 -0
  4. package/dist/config-BcNSzPZz.d.mts +1718 -0
  5. package/dist/index.d.mts +50 -1633
  6. package/dist/index.mjs +3769 -2653
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/storage/sqlite.d.mts +59 -0
  9. package/dist/storage/sqlite.mjs +234 -0
  10. package/dist/storage/sqlite.mjs.map +1 -0
  11. package/package.json +26 -29
  12. package/src/ctMock.ts +125 -136
  13. package/src/helpers.ts +14 -6
  14. package/src/index.ts +5 -0
  15. package/src/lib/masking.ts +4 -5
  16. package/src/lib/product-review-statistics.test.ts +257 -294
  17. package/src/lib/review-statistics.ts +17 -4
  18. package/src/oauth/helpers.ts +7 -4
  19. package/src/oauth/server.test.ts +102 -62
  20. package/src/oauth/server.ts +215 -213
  21. package/src/oauth/store.ts +20 -6
  22. package/src/orderSearch.ts +3 -3
  23. package/src/product-projection-search.ts +38 -20
  24. package/src/product-search-availability.test.ts +31 -52
  25. package/src/product-search.ts +19 -10
  26. package/src/projectAPI.ts +6 -22
  27. package/src/repositories/abstract.ts +182 -48
  28. package/src/repositories/as-associate.test.ts +19 -19
  29. package/src/repositories/associate-role.ts +12 -23
  30. package/src/repositories/attribute-group.test.ts +23 -23
  31. package/src/repositories/attribute-group.ts +6 -4
  32. package/src/repositories/business-unit.test.ts +63 -57
  33. package/src/repositories/business-unit.ts +107 -55
  34. package/src/repositories/cart/actions.ts +96 -65
  35. package/src/repositories/cart/helpers.ts +15 -11
  36. package/src/repositories/cart/index.test.ts +136 -30
  37. package/src/repositories/cart/index.ts +76 -59
  38. package/src/repositories/cart-discount/actions.ts +12 -44
  39. package/src/repositories/cart-discount/index.ts +20 -8
  40. package/src/repositories/category/actions.ts +27 -27
  41. package/src/repositories/category/index.test.ts +13 -9
  42. package/src/repositories/category/index.ts +40 -23
  43. package/src/repositories/channel.test.ts +53 -51
  44. package/src/repositories/channel.ts +12 -22
  45. package/src/repositories/custom-object.ts +34 -25
  46. package/src/repositories/customer/actions.ts +47 -25
  47. package/src/repositories/customer/index.test.ts +11 -11
  48. package/src/repositories/customer/index.ts +65 -35
  49. package/src/repositories/customer-group.test.ts +44 -42
  50. package/src/repositories/customer-group.ts +12 -22
  51. package/src/repositories/discount-code/actions.ts +3 -19
  52. package/src/repositories/discount-code/index.ts +9 -4
  53. package/src/repositories/discount-group/index.ts +8 -3
  54. package/src/repositories/extension.test.ts +27 -27
  55. package/src/repositories/extension.ts +10 -5
  56. package/src/repositories/helpers.ts +126 -47
  57. package/src/repositories/inventory-entry/actions.ts +3 -24
  58. package/src/repositories/inventory-entry/index.ts +19 -11
  59. package/src/repositories/my-customer.ts +13 -12
  60. package/src/repositories/my-order.ts +5 -2
  61. package/src/repositories/order/actions.ts +84 -56
  62. package/src/repositories/order/index.test.ts +36 -31
  63. package/src/repositories/order/index.ts +83 -49
  64. package/src/repositories/order-edit.ts +8 -3
  65. package/src/repositories/payment/actions.ts +64 -44
  66. package/src/repositories/payment/helpers.ts +3 -3
  67. package/src/repositories/payment/index.ts +28 -12
  68. package/src/repositories/product/actions.ts +133 -98
  69. package/src/repositories/product/helpers.ts +29 -16
  70. package/src/repositories/product/index.ts +42 -25
  71. package/src/repositories/product-discount.ts +6 -4
  72. package/src/repositories/product-projection.ts +41 -21
  73. package/src/repositories/product-selection.ts +8 -15
  74. package/src/repositories/product-tailoring.ts +22 -3
  75. package/src/repositories/product-type.ts +45 -4
  76. package/src/repositories/project.ts +57 -13
  77. package/src/repositories/quote/actions.ts +5 -28
  78. package/src/repositories/quote/index.ts +29 -6
  79. package/src/repositories/quote-request/actions.ts +5 -28
  80. package/src/repositories/quote-request/index.test.ts +3 -3
  81. package/src/repositories/quote-request/index.ts +31 -11
  82. package/src/repositories/quote-staged/actions.ts +5 -28
  83. package/src/repositories/quote-staged/index.ts +22 -8
  84. package/src/repositories/recurrence-policy/index.ts +6 -4
  85. package/src/repositories/recurring-order/actions.ts +7 -32
  86. package/src/repositories/recurring-order/index.ts +8 -6
  87. package/src/repositories/review.test.ts +147 -142
  88. package/src/repositories/review.ts +31 -37
  89. package/src/repositories/shipping-method/actions.ts +11 -28
  90. package/src/repositories/shipping-method/index.ts +26 -15
  91. package/src/repositories/shopping-list/actions.ts +21 -31
  92. package/src/repositories/shopping-list/index.ts +44 -22
  93. package/src/repositories/standalone-price.ts +6 -4
  94. package/src/repositories/state.ts +15 -9
  95. package/src/repositories/store.ts +21 -32
  96. package/src/repositories/subscription.test.ts +22 -22
  97. package/src/repositories/subscription.ts +8 -3
  98. package/src/repositories/tax-category/index.ts +8 -3
  99. package/src/repositories/type/actions.ts +21 -3
  100. package/src/repositories/type/index.ts +5 -3
  101. package/src/repositories/zone.test.ts +112 -77
  102. package/src/repositories/zone.ts +5 -3
  103. package/src/schemas/generated/associate-role.ts +13 -0
  104. package/src/schemas/generated/attribute-group.ts +12 -0
  105. package/src/schemas/generated/business-unit.ts +38 -0
  106. package/src/schemas/generated/cart-discount.ts +33 -0
  107. package/src/schemas/generated/cart.ts +61 -0
  108. package/src/schemas/generated/category.ts +25 -0
  109. package/src/schemas/generated/channel.ts +21 -0
  110. package/src/schemas/generated/common.ts +1372 -0
  111. package/src/schemas/generated/custom-object.ts +11 -0
  112. package/src/schemas/generated/customer-group.ts +11 -0
  113. package/src/schemas/generated/customer.ts +47 -0
  114. package/src/schemas/generated/discount-code.ts +25 -0
  115. package/src/schemas/generated/discount-group.ts +13 -0
  116. package/src/schemas/generated/extension.ts +15 -0
  117. package/src/schemas/generated/index.ts +42 -0
  118. package/src/schemas/generated/inventory-entry.ts +20 -0
  119. package/src/schemas/generated/my-quote-request.ts +10 -0
  120. package/src/schemas/generated/order-edit.ts +18 -0
  121. package/src/schemas/generated/order-from-cart.ts +25 -0
  122. package/src/schemas/generated/payment.ts +30 -0
  123. package/src/schemas/generated/product-discount.ts +20 -0
  124. package/src/schemas/generated/product-selection.ts +18 -0
  125. package/src/schemas/generated/product-tailoring.ts +26 -0
  126. package/src/schemas/generated/product-type.ts +12 -0
  127. package/src/schemas/generated/product.ts +37 -0
  128. package/src/schemas/generated/quote-request.ts +19 -0
  129. package/src/schemas/generated/quote.ts +18 -0
  130. package/src/schemas/generated/recurrence-policy.ts +15 -0
  131. package/src/schemas/generated/recurring-order.ts +19 -0
  132. package/src/schemas/generated/review.ts +24 -0
  133. package/src/schemas/generated/shipping-method.ts +24 -0
  134. package/src/schemas/generated/shopping-list.ts +28 -0
  135. package/src/schemas/generated/staged-quote.ts +18 -0
  136. package/src/schemas/generated/standalone-price.ts +32 -0
  137. package/src/schemas/generated/state.ts +20 -0
  138. package/src/schemas/generated/store.ts +23 -0
  139. package/src/schemas/generated/subscription.ts +20 -0
  140. package/src/schemas/generated/tax-category.ts +12 -0
  141. package/src/schemas/generated/type.ts +17 -0
  142. package/src/schemas/generated/zone.ts +12 -0
  143. package/src/schemas/update-request.ts +3 -5
  144. package/src/server.ts +32 -4
  145. package/src/services/abstract.ts +207 -101
  146. package/src/services/as-associate-cart.test.ts +28 -36
  147. package/src/services/as-associate-cart.ts +15 -12
  148. package/src/services/as-associate-order.test.ts +33 -40
  149. package/src/services/as-associate-order.ts +15 -12
  150. package/src/services/as-associate-quote-request.ts +15 -12
  151. package/src/services/as-associate-shopping-list.test.ts +25 -35
  152. package/src/services/as-associate-shopping-list.ts +15 -12
  153. package/src/services/as-associate.test.ts +21 -15
  154. package/src/services/as-associate.ts +23 -22
  155. package/src/services/associate-roles.test.ts +16 -22
  156. package/src/services/associate-roles.ts +2 -2
  157. package/src/services/attribute-group.test.ts +40 -44
  158. package/src/services/attribute-group.ts +2 -2
  159. package/src/services/business-units.test.ts +227 -163
  160. package/src/services/business-units.ts +2 -2
  161. package/src/services/cart-discount.test.ts +253 -187
  162. package/src/services/cart-discount.ts +2 -2
  163. package/src/services/cart.test.ts +833 -832
  164. package/src/services/cart.ts +31 -12
  165. package/src/services/category.test.ts +208 -130
  166. package/src/services/category.ts +2 -2
  167. package/src/services/channel.test.ts +39 -44
  168. package/src/services/channel.ts +2 -2
  169. package/src/services/custom-object.test.ts +103 -79
  170. package/src/services/custom-object.ts +106 -38
  171. package/src/services/customer-group.test.ts +39 -44
  172. package/src/services/customer-group.ts +2 -2
  173. package/src/services/customer.test.ts +357 -292
  174. package/src/services/customer.ts +70 -23
  175. package/src/services/discount-code.test.ts +57 -68
  176. package/src/services/discount-code.ts +2 -2
  177. package/src/services/discount-group.test.ts +111 -134
  178. package/src/services/discount-group.ts +2 -2
  179. package/src/services/draft-validation.test.ts +255 -0
  180. package/src/services/extension.test.ts +39 -44
  181. package/src/services/extension.ts +2 -2
  182. package/src/services/inventory-entry.test.ts +106 -87
  183. package/src/services/inventory-entry.ts +2 -2
  184. package/src/services/my-business-unit.test.ts +82 -112
  185. package/src/services/my-business-unit.ts +25 -19
  186. package/src/services/my-cart.test.ts +46 -41
  187. package/src/services/my-cart.ts +32 -28
  188. package/src/services/my-customer.test.ts +153 -88
  189. package/src/services/my-customer.ts +130 -61
  190. package/src/services/my-order.ts +15 -12
  191. package/src/services/my-payment.test.ts +30 -24
  192. package/src/services/my-payment.ts +2 -2
  193. package/src/services/my-shopping-list.ts +2 -2
  194. package/src/services/order.test.ts +332 -276
  195. package/src/services/order.ts +45 -27
  196. package/src/services/payment.test.ts +31 -29
  197. package/src/services/payment.ts +2 -2
  198. package/src/services/product-discount.test.ts +39 -46
  199. package/src/services/product-discount.ts +2 -2
  200. package/src/services/product-projection.test.ts +176 -166
  201. package/src/services/product-projection.ts +31 -15
  202. package/src/services/product-selection.test.ts +17 -9
  203. package/src/services/product-selection.ts +2 -2
  204. package/src/services/product-type.test.ts +80 -21
  205. package/src/services/product-type.ts +2 -2
  206. package/src/services/product.test.ts +569 -534
  207. package/src/services/product.ts +14 -7
  208. package/src/services/project.test.ts +22 -12
  209. package/src/services/project.ts +28 -13
  210. package/src/services/quote-request.test.ts +36 -39
  211. package/src/services/quote-request.ts +2 -2
  212. package/src/services/quote-staged.ts +2 -2
  213. package/src/services/quote.ts +2 -2
  214. package/src/services/recurrence-policy.test.ts +114 -139
  215. package/src/services/recurrence-policy.ts +2 -2
  216. package/src/services/recurring-order.test.ts +149 -194
  217. package/src/services/recurring-order.ts +2 -2
  218. package/src/services/reviews.test.ts +127 -106
  219. package/src/services/reviews.ts +2 -2
  220. package/src/services/shipping-method.test.ts +96 -125
  221. package/src/services/shipping-method.ts +24 -12
  222. package/src/services/shopping-list.test.ts +183 -141
  223. package/src/services/shopping-list.ts +2 -2
  224. package/src/services/standalone-price.test.ts +60 -46
  225. package/src/services/standalone-price.ts +2 -2
  226. package/src/services/state.test.ts +20 -25
  227. package/src/services/state.ts +2 -2
  228. package/src/services/store.test.ts +26 -45
  229. package/src/services/store.ts +2 -2
  230. package/src/services/subscription.test.ts +39 -44
  231. package/src/services/subscription.ts +2 -2
  232. package/src/services/tax-category.test.ts +33 -36
  233. package/src/services/tax-category.ts +2 -2
  234. package/src/services/type.test.ts +45 -44
  235. package/src/services/type.ts +2 -2
  236. package/src/services/zone.test.ts +40 -44
  237. package/src/services/zone.ts +2 -2
  238. package/src/shipping.ts +41 -11
  239. package/src/storage/abstract.ts +248 -17
  240. package/src/storage/in-memory.ts +147 -290
  241. package/src/storage/sqlite.ts +429 -0
  242. package/src/storage/storage-map.ts +75 -0
  243. package/src/storage/storage.test-helpers.ts +97 -0
  244. package/src/storage/storage.test.ts +802 -0
  245. package/src/testing/associate-role.ts +28 -0
  246. package/src/testing/attribute-group.ts +27 -0
  247. package/src/testing/business-unit.ts +9 -8
  248. package/src/testing/cart-discount.ts +34 -0
  249. package/src/testing/cart.ts +20 -0
  250. package/src/testing/category.ts +25 -0
  251. package/src/testing/channel.ts +23 -0
  252. package/src/testing/custom-object.ts +27 -0
  253. package/src/testing/customer-group.ts +26 -0
  254. package/src/testing/customer.ts +36 -33
  255. package/src/testing/discount-code.ts +29 -0
  256. package/src/testing/discount-group.ts +27 -0
  257. package/src/testing/extension.ts +32 -0
  258. package/src/testing/index.ts +33 -0
  259. package/src/testing/inventory-entry.ts +26 -0
  260. package/src/testing/order.ts +27 -0
  261. package/src/testing/payment.ts +23 -0
  262. package/src/testing/product-discount.ts +33 -0
  263. package/src/testing/product-selection.ts +28 -0
  264. package/src/testing/product-type.ts +27 -0
  265. package/src/testing/product.ts +38 -0
  266. package/src/testing/quote-request.ts +29 -0
  267. package/src/testing/recurrence-policy.ts +33 -0
  268. package/src/testing/recurring-order.ts +32 -0
  269. package/src/testing/review.ts +24 -0
  270. package/src/testing/shipping-method.ts +31 -0
  271. package/src/testing/shopping-list.ts +25 -0
  272. package/src/testing/standalone-price.ts +31 -0
  273. package/src/testing/state.ts +21 -0
  274. package/src/testing/store.ts +26 -0
  275. package/src/testing/subscription.ts +38 -0
  276. package/src/testing/tax-category.ts +27 -0
  277. package/src/testing/type.ts +9 -6
  278. package/src/testing/zone.ts +22 -0
  279. package/src/validate.test.ts +122 -0
  280. package/src/validate.ts +78 -7
  281. package/src/.env +0 -0
@@ -1,11 +1,6 @@
1
1
  import type { InvalidTokenError } from "@commercetools/platform-sdk";
2
2
  import auth from "basic-auth";
3
- import bodyParser from "body-parser";
4
- import express, {
5
- type NextFunction,
6
- type Request,
7
- type Response,
8
- } from "express";
3
+ import type { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
9
4
  import type { AuthError, InvalidRequestError } from "#src/exceptions.ts";
10
5
  import { CommercetoolsError } from "#src/exceptions.ts";
11
6
  import { hashPassword } from "../lib/password.ts";
@@ -14,12 +9,15 @@ import type { InvalidClientError, UnsupportedGrantType } from "./errors.ts";
14
9
  import { getBearerToken } from "./helpers.ts";
15
10
  import { OAuth2Store } from "./store.ts";
16
11
 
17
- type AuthRequest = Request & {
18
- credentials?: {
19
- clientId: string;
20
- clientSecret: string;
21
- };
22
- };
12
+ declare module "fastify" {
13
+ interface FastifyRequest {
14
+ credentials?: {
15
+ clientId: string;
16
+ clientSecret: string;
17
+ };
18
+ }
19
+ }
20
+
23
21
  export type Token = {
24
22
  access_token: string;
25
23
  token_type: "Bearer";
@@ -32,8 +30,10 @@ export class OAuth2Server {
32
30
  store: OAuth2Store;
33
31
 
34
32
  private customerRepository: CustomerRepository;
33
+ private options: { enabled: boolean; validate: boolean };
35
34
 
36
- constructor(private options: { enabled: boolean; validate: boolean }) {
35
+ constructor(options: { enabled: boolean; validate: boolean }) {
36
+ this.options = options;
37
37
  this.store = new OAuth2Store(options.validate);
38
38
  }
39
39
 
@@ -41,97 +41,99 @@ export class OAuth2Server {
41
41
  this.customerRepository = repository;
42
42
  }
43
43
 
44
- createRouter() {
45
- const router = express.Router();
46
- router.use(bodyParser.urlencoded({ extended: true }));
47
- router.use(this.validateClientCredentials.bind(this));
48
- router.post("/token", this.tokenHandler.bind(this));
49
- router.post(
50
- "/:projectKey/customers/token",
51
- this.customerTokenHandler.bind(this),
52
- );
53
- router.post(
54
- "/:projectKey/in-store/key=:storeKey/customers/token",
55
- this.inStoreCustomerTokenHandler.bind(this),
56
- );
57
- router.post(
58
- "/:projectKey/anonymous/token",
59
- this.anonymousTokenHandler.bind(this),
60
- );
61
- return router;
44
+ createPlugin() {
45
+ return async (instance: FastifyInstance) => {
46
+ await instance.register(import("@fastify/formbody"));
47
+ instance.decorateRequest("credentials", undefined);
48
+ instance.addHook("preHandler", this.validateClientCredentials.bind(this));
49
+ instance.post("/token", this.tokenHandler.bind(this));
50
+ instance.post(
51
+ "/:projectKey/customers/token",
52
+ this.customerTokenHandler.bind(this),
53
+ );
54
+ instance.post(
55
+ "/:projectKey/in-store/key=:storeKey/customers/token",
56
+ this.inStoreCustomerTokenHandler.bind(this),
57
+ );
58
+ instance.post(
59
+ "/:projectKey/anonymous/token",
60
+ this.anonymousTokenHandler.bind(this),
61
+ );
62
+ };
62
63
  }
63
64
 
64
65
  createMiddleware() {
65
66
  if (!this.options.validate) {
66
- return async (
67
- request: Request,
68
- response: Response,
69
- next: NextFunction,
70
- ) => {
71
- next();
67
+ return async (request: FastifyRequest, reply: FastifyReply) => {
68
+ // When validation is disabled, still populate credentials
69
+ // so createdBy/lastModifiedBy can be set on resources
70
+ const token = getBearerToken(request);
71
+ const clientId = token
72
+ ? this.store.getClientIdForToken(token)
73
+ : undefined;
74
+ request.credentials = {
75
+ clientId: clientId ?? "",
76
+ clientSecret: "",
77
+ };
72
78
  };
73
79
  }
74
80
 
75
- return async (request: Request, response: Response, next: NextFunction) => {
81
+ return async (request: FastifyRequest, reply: FastifyReply) => {
76
82
  const token = getBearerToken(request);
77
83
  if (!token) {
78
- return next(
79
- new CommercetoolsError<InvalidTokenError>(
80
- {
81
- code: "invalid_token",
82
- message:
83
- "This endpoint requires an access token. You can get one from the authorization server.",
84
- },
85
- 401,
86
- ),
84
+ throw new CommercetoolsError<InvalidTokenError>(
85
+ {
86
+ code: "invalid_token",
87
+ message:
88
+ "This endpoint requires an access token. You can get one from the authorization server.",
89
+ },
90
+ 401,
87
91
  );
88
92
  }
89
93
 
90
94
  if (!token || !this.store.validateToken(token)) {
91
- return next(
92
- new CommercetoolsError<InvalidTokenError>(
93
- {
94
- code: "invalid_token",
95
- message: "invalid_token",
96
- },
97
- 401,
98
- ),
95
+ throw new CommercetoolsError<InvalidTokenError>(
96
+ {
97
+ code: "invalid_token",
98
+ message: "invalid_token",
99
+ },
100
+ 401,
99
101
  );
100
102
  }
101
103
 
102
- return next();
104
+ // Populate credentials so createdBy/lastModifiedBy can be set
105
+ const clientId = this.store.getClientIdForToken(token);
106
+ request.credentials = {
107
+ clientId: clientId ?? "",
108
+ clientSecret: "",
109
+ };
103
110
  };
104
111
  }
105
112
 
106
113
  async validateClientCredentials(
107
- request: AuthRequest,
108
- response: Response,
109
- next: NextFunction,
114
+ request: FastifyRequest,
115
+ reply: FastifyReply,
110
116
  ) {
111
- const authHeader = request.header("Authorization");
117
+ const authHeader = request.headers.authorization;
112
118
  if (!authHeader) {
113
- return next(
114
- new CommercetoolsError<InvalidClientError>(
115
- {
116
- code: "invalid_client",
117
- message:
118
- "Please provide valid client credentials using HTTP Basic Authentication.",
119
- },
120
- 401,
121
- ),
119
+ throw new CommercetoolsError<InvalidClientError>(
120
+ {
121
+ code: "invalid_client",
122
+ message:
123
+ "Please provide valid client credentials using HTTP Basic Authentication.",
124
+ },
125
+ 401,
122
126
  );
123
127
  }
124
128
  const credentials = auth.parse(authHeader);
125
129
  if (!credentials) {
126
- return next(
127
- new CommercetoolsError<InvalidClientError>(
128
- {
129
- code: "invalid_client",
130
- message:
131
- "Please provide valid client credentials using HTTP Basic Authentication.",
132
- },
133
- 400,
134
- ),
130
+ throw new CommercetoolsError<InvalidClientError>(
131
+ {
132
+ code: "invalid_client",
133
+ message:
134
+ "Please provide valid client credentials using HTTP Basic Authentication.",
135
+ },
136
+ 400,
135
137
  );
136
138
  }
137
139
 
@@ -139,37 +141,35 @@ export class OAuth2Server {
139
141
  clientId: credentials.name,
140
142
  clientSecret: credentials.pass,
141
143
  };
142
-
143
- next();
144
144
  }
145
145
 
146
146
  async tokenHandler(
147
- request: AuthRequest,
148
- response: Response,
149
- next: NextFunction,
147
+ request: FastifyRequest<{
148
+ Querystring: Record<string, any>;
149
+ Body: Record<string, any>;
150
+ }>,
151
+ reply: FastifyReply,
150
152
  ) {
151
153
  if (!request.credentials) {
152
- return next(
153
- new CommercetoolsError<InvalidClientError>(
154
- {
155
- code: "invalid_client",
156
- message: "Client credentials are missing.",
157
- },
158
- 401,
159
- ),
154
+ throw new CommercetoolsError<InvalidClientError>(
155
+ {
156
+ code: "invalid_client",
157
+ message: "Client credentials are missing.",
158
+ },
159
+ 401,
160
160
  );
161
161
  }
162
162
 
163
- const grantType = request.query.grant_type || request.body?.grant_type;
163
+ const query = request.query;
164
+ const body = request.body;
165
+ const grantType = query.grant_type || body?.grant_type;
164
166
  if (!grantType) {
165
- return next(
166
- new CommercetoolsError<InvalidRequestError>(
167
- {
168
- code: "invalid_request",
169
- message: "Missing required parameter: grant_type.",
170
- },
171
- 400,
172
- ),
167
+ throw new CommercetoolsError<InvalidRequestError>(
168
+ {
169
+ code: "invalid_request",
170
+ message: "Missing required parameter: grant_type.",
171
+ },
172
+ 400,
173
173
  );
174
174
  }
175
175
 
@@ -177,23 +177,20 @@ export class OAuth2Server {
177
177
  const token = this.store.getClientToken(
178
178
  request.credentials.clientId,
179
179
  request.credentials.clientSecret,
180
- request.query.scope?.toString(),
180
+ query.scope?.toString(),
181
181
  );
182
- response.status(200).send(token);
183
- return;
182
+ return reply.status(200).send(token);
184
183
  }
185
184
  if (grantType === "refresh_token") {
186
185
  const refreshToken =
187
- request.query.refresh_token?.toString() || request.body?.refresh_token;
186
+ query.refresh_token?.toString() || body?.refresh_token;
188
187
  if (!refreshToken) {
189
- return next(
190
- new CommercetoolsError<InvalidRequestError>(
191
- {
192
- code: "invalid_request",
193
- message: "Missing required parameter: refresh_token.",
194
- },
195
- 400,
196
- ),
188
+ throw new CommercetoolsError<InvalidRequestError>(
189
+ {
190
+ code: "invalid_request",
191
+ message: "Missing required parameter: refresh_token.",
192
+ },
193
+ 400,
197
194
  );
198
195
  }
199
196
  const token = this.store.refreshToken(
@@ -202,114 +199,114 @@ export class OAuth2Server {
202
199
  refreshToken,
203
200
  );
204
201
  if (!token) {
205
- return next(
206
- new CommercetoolsError<AuthError>(
207
- {
208
- statusCode: 400,
209
- message: "The refresh token was not found. It may have expired.",
210
- error: "invalid_grant",
211
- error_description:
212
- "The refresh token was not found. It may have expired.",
213
- },
214
- 400,
215
- ),
202
+ throw new CommercetoolsError<AuthError>(
203
+ {
204
+ statusCode: 400,
205
+ message: "The refresh token was not found. It may have expired.",
206
+ error: "invalid_grant",
207
+ error_description:
208
+ "The refresh token was not found. It may have expired.",
209
+ },
210
+ 400,
216
211
  );
217
212
  }
218
- response.status(200).send(token);
219
- return;
213
+ return reply.status(200).send(token);
220
214
  }
221
- return next(
222
- new CommercetoolsError<UnsupportedGrantType>(
223
- {
224
- code: "unsupported_grant_type",
225
- message: `Invalid parameter: grant_type: Invalid grant type: ${grantType}`,
226
- },
227
- 400,
228
- ),
215
+ throw new CommercetoolsError<UnsupportedGrantType>(
216
+ {
217
+ code: "unsupported_grant_type",
218
+ message: `Invalid parameter: grant_type: Invalid grant type: ${grantType}`,
219
+ },
220
+ 400,
229
221
  );
230
222
  }
231
223
 
232
224
  async customerTokenHandler(
233
- request: AuthRequest,
234
- response: Response,
235
- next: NextFunction,
225
+ request: FastifyRequest<{
226
+ Params: Record<string, string>;
227
+ Querystring: Record<string, any>;
228
+ Body: Record<string, any>;
229
+ }>,
230
+ reply: FastifyReply,
236
231
  ) {
237
- const projectKey = request.params.projectKey;
238
- const grantType = request.query.grant_type || request.body?.grant_type;
232
+ const params = request.params;
233
+ const query = request.query;
234
+ const body = request.body;
235
+ const projectKey = params.projectKey;
236
+ const grantType = query.grant_type || body?.grant_type;
239
237
  if (!grantType) {
240
- return next(
241
- new CommercetoolsError<InvalidRequestError>(
242
- {
243
- code: "invalid_request",
244
- message: "Missing required parameter: grant_type.",
245
- },
246
- 400,
247
- ),
238
+ throw new CommercetoolsError<InvalidRequestError>(
239
+ {
240
+ code: "invalid_request",
241
+ message: "Missing required parameter: grant_type.",
242
+ },
243
+ 400,
248
244
  );
249
245
  }
250
246
 
251
247
  if (grantType === "password") {
252
- const username = request.query.username || request.body?.username;
253
- const password = hashPassword(
254
- request.query.password || request.body.password,
255
- );
256
- const scope =
257
- request.query.scope?.toString() || request.body?.scope?.toString();
248
+ const username = query.username || body?.username;
249
+ const password = hashPassword(query.password || body.password);
250
+ const scope = query.scope?.toString() || body?.scope?.toString();
258
251
 
259
- const result = this.customerRepository.query(
260
- { projectKey: request.params.projectKey },
252
+ const result = await this.customerRepository.query(
253
+ { projectKey: params.projectKey },
261
254
  {
262
255
  where: [`email = "${username}"`, `password = "${password}"`],
263
256
  },
264
257
  );
265
258
 
266
259
  if (result.count === 0) {
267
- return next(
268
- new CommercetoolsError<any>(
269
- {
270
- code: "invalid_customer_account_credentials",
271
- message: "Customer account with the given credentials not found.",
272
- },
273
- 400,
274
- ),
260
+ throw new CommercetoolsError<any>(
261
+ {
262
+ code: "invalid_customer_account_credentials",
263
+ message: "Customer account with the given credentials not found.",
264
+ },
265
+ 400,
275
266
  );
276
267
  }
277
268
 
278
269
  const customer = result.results[0];
279
- const token = this.store.getCustomerToken(projectKey, customer.id, scope);
280
- response.status(200).send(token);
270
+ const token = this.store.getCustomerToken(
271
+ projectKey,
272
+ customer.id,
273
+ scope,
274
+ request.credentials?.clientId,
275
+ );
276
+ return reply.status(200).send(token);
281
277
  }
282
278
  }
283
279
 
284
280
  async inStoreCustomerTokenHandler(
285
- request: Request,
286
- response: Response,
287
- next: NextFunction,
281
+ request: FastifyRequest<{
282
+ Params: Record<string, string>;
283
+ Querystring: Record<string, any>;
284
+ Body: Record<string, any>;
285
+ }>,
286
+ reply: FastifyReply,
288
287
  ) {
289
- const projectKey = request.params.projectKey;
290
- const storeKey = request.params.storeKey;
291
- const grantType = request.query.grant_type || request.body.grant_type;
288
+ const params = request.params;
289
+ const query = request.query;
290
+ const body = request.body;
291
+ const projectKey = params.projectKey;
292
+ const storeKey = params.storeKey;
293
+ const grantType = query.grant_type || body.grant_type;
292
294
  if (!grantType) {
293
- return next(
294
- new CommercetoolsError<InvalidRequestError>(
295
- {
296
- code: "invalid_request",
297
- message: "Missing required parameter: grant_type.",
298
- },
299
- 400,
300
- ),
295
+ throw new CommercetoolsError<InvalidRequestError>(
296
+ {
297
+ code: "invalid_request",
298
+ message: "Missing required parameter: grant_type.",
299
+ },
300
+ 400,
301
301
  );
302
302
  }
303
303
 
304
304
  if (grantType === "password") {
305
- const username = request.query.username || request.body.username;
306
- const password = hashPassword(
307
- request.query.password || request.body.password,
308
- );
309
- const scope =
310
- request.query.scope?.toString() || request.body.scope?.toString();
305
+ const username = query.username || body.username;
306
+ const password = hashPassword(query.password || body.password);
307
+ const scope = query.scope?.toString() || body.scope?.toString();
311
308
 
312
- const result = this.customerRepository.query(
309
+ const result = await this.customerRepository.query(
313
310
  { projectKey, storeKey },
314
311
  {
315
312
  where: [`email = "${username}"`, `password = "${password}"`],
@@ -317,46 +314,51 @@ export class OAuth2Server {
317
314
  );
318
315
 
319
316
  if (result.count === 0) {
320
- return next(
321
- new CommercetoolsError<any>(
322
- {
323
- code: "invalid_customer_account_credentials",
324
- message: "Customer account with the given credentials not found.",
325
- },
326
- 400,
327
- ),
317
+ throw new CommercetoolsError<any>(
318
+ {
319
+ code: "invalid_customer_account_credentials",
320
+ message: "Customer account with the given credentials not found.",
321
+ },
322
+ 400,
328
323
  );
329
324
  }
330
325
 
331
326
  const customer = result.results[0];
332
- const token = this.store.getCustomerToken(projectKey, customer.id, scope);
333
- response.status(200).send(token);
334
- return;
327
+ const token = this.store.getCustomerToken(
328
+ projectKey,
329
+ customer.id,
330
+ scope,
331
+ request.credentials?.clientId,
332
+ );
333
+ return reply.status(200).send(token);
335
334
  }
336
335
  }
337
336
 
338
337
  async anonymousTokenHandler(
339
- request: Request,
340
- response: Response,
341
- next: NextFunction,
338
+ request: FastifyRequest<{
339
+ Params: Record<string, string>;
340
+ Querystring: Record<string, any>;
341
+ Body: Record<string, any>;
342
+ }>,
343
+ reply: FastifyReply,
342
344
  ) {
343
- const projectKey = request.params.projectKey;
344
- const grantType = request.query.grant_type || request.body.grant_type;
345
+ const params = request.params;
346
+ const query = request.query;
347
+ const body = request.body;
348
+ const projectKey = params.projectKey;
349
+ const grantType = query.grant_type || body.grant_type;
345
350
  if (!grantType) {
346
- return next(
347
- new CommercetoolsError<InvalidRequestError>(
348
- {
349
- code: "invalid_request",
350
- message: "Missing required parameter: grant_type.",
351
- },
352
- 400,
353
- ),
351
+ throw new CommercetoolsError<InvalidRequestError>(
352
+ {
353
+ code: "invalid_request",
354
+ message: "Missing required parameter: grant_type.",
355
+ },
356
+ 400,
354
357
  );
355
358
  }
356
359
 
357
360
  if (grantType === "client_credentials") {
358
- const scope =
359
- request.query.scope?.toString() || request.body?.scope?.toString();
361
+ const scope = query.scope?.toString() || body?.scope?.toString();
360
362
 
361
363
  const anonymous_id = undefined;
362
364
 
@@ -364,9 +366,9 @@ export class OAuth2Server {
364
366
  projectKey,
365
367
  anonymous_id,
366
368
  scope,
369
+ request.credentials?.clientId,
367
370
  );
368
- response.status(200).send(token);
369
- return;
371
+ return reply.status(200).send(token);
370
372
  }
371
373
  }
372
374
  }
@@ -11,6 +11,7 @@ type Token = {
11
11
 
12
12
  export class OAuth2Store {
13
13
  tokens: Token[] = [];
14
+ private tokenClientMap: Map<string, string> = new Map();
14
15
 
15
16
  validate = true;
16
17
 
@@ -18,8 +19,15 @@ export class OAuth2Store {
18
19
  this.validate = validate;
19
20
  }
20
21
 
21
- addToken(token: Token) {
22
+ addToken(token: Token, clientId?: string) {
22
23
  this.tokens.push(token);
24
+ if (clientId) {
25
+ this.tokenClientMap.set(token.access_token, clientId);
26
+ }
27
+ }
28
+
29
+ getClientIdForToken(accessToken: string): string | undefined {
30
+ return this.tokenClientMap.get(accessToken);
23
31
  }
24
32
 
25
33
  getClientToken(clientId: string, clientSecret: string, scope?: string) {
@@ -30,7 +38,7 @@ export class OAuth2Store {
30
38
  scope: scope || "todo",
31
39
  refresh_token: `my-project-${randomBytes(16).toString("base64")}`,
32
40
  };
33
- this.addToken(token);
41
+ this.addToken(token, clientId);
34
42
  return token;
35
43
  }
36
44
 
@@ -38,6 +46,7 @@ export class OAuth2Store {
38
46
  projectKey: string,
39
47
  anonymousId: string | undefined,
40
48
  scope: string,
49
+ clientId?: string,
41
50
  ) {
42
51
  if (!anonymousId) {
43
52
  anonymousId = uuidv4();
@@ -51,11 +60,16 @@ export class OAuth2Store {
51
60
  : `anonymous_id:${anonymousId}`,
52
61
  refresh_token: `${projectKey}:${randomBytes(16).toString("base64")}`,
53
62
  };
54
- this.addToken(token);
63
+ this.addToken(token, clientId);
55
64
  return token;
56
65
  }
57
66
 
58
- getCustomerToken(projectKey: string, customerId: string, scope: string) {
67
+ getCustomerToken(
68
+ projectKey: string,
69
+ customerId: string,
70
+ scope: string,
71
+ clientId?: string,
72
+ ) {
59
73
  const token: Token = {
60
74
  access_token: randomBytes(16).toString("base64"),
61
75
  token_type: "Bearer",
@@ -65,7 +79,7 @@ export class OAuth2Store {
65
79
  : `customer_id:${customerId}`,
66
80
  refresh_token: `${projectKey}:${randomBytes(16).toString("base64")}`,
67
81
  };
68
- this.addToken(token);
82
+ this.addToken(token, clientId);
69
83
  return token;
70
84
  }
71
85
 
@@ -78,7 +92,7 @@ export class OAuth2Store {
78
92
  ...existing,
79
93
  access_token: randomBytes(16).toString("base64"),
80
94
  };
81
- this.addToken(token);
95
+ this.addToken(token, clientId);
82
96
 
83
97
  // We don't want to return the refresh_token again
84
98
  return {
@@ -13,11 +13,11 @@ export class OrderSearch {
13
13
  this._storage = config.storage;
14
14
  }
15
15
 
16
- search(
16
+ async search(
17
17
  projectKey: string,
18
18
  params: OrderSearchRequest,
19
- ): OrderPagedSearchResponse {
20
- const orderResources = this._storage.all(projectKey, "order");
19
+ ): Promise<OrderPagedSearchResponse> {
20
+ const orderResources = await this._storage.all(projectKey, "order");
21
21
 
22
22
  // TODO: implement filtering based on params.query
23
23
  const offset = params.offset || 0;