@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.
- package/README.md +31 -8
- package/dist/abstract-BKFcva6S.mjs +1044 -0
- package/dist/abstract-BKFcva6S.mjs.map +1 -0
- package/dist/config-BcNSzPZz.d.mts +1718 -0
- package/dist/index.d.mts +50 -1633
- package/dist/index.mjs +3769 -2653
- package/dist/index.mjs.map +1 -1
- package/dist/storage/sqlite.d.mts +59 -0
- package/dist/storage/sqlite.mjs +234 -0
- package/dist/storage/sqlite.mjs.map +1 -0
- package/package.json +26 -29
- package/src/ctMock.ts +125 -136
- package/src/helpers.ts +14 -6
- package/src/index.ts +5 -0
- package/src/lib/masking.ts +4 -5
- package/src/lib/product-review-statistics.test.ts +257 -294
- package/src/lib/review-statistics.ts +17 -4
- package/src/oauth/helpers.ts +7 -4
- package/src/oauth/server.test.ts +102 -62
- package/src/oauth/server.ts +215 -213
- package/src/oauth/store.ts +20 -6
- package/src/orderSearch.ts +3 -3
- package/src/product-projection-search.ts +38 -20
- package/src/product-search-availability.test.ts +31 -52
- package/src/product-search.ts +19 -10
- package/src/projectAPI.ts +6 -22
- package/src/repositories/abstract.ts +182 -48
- package/src/repositories/as-associate.test.ts +19 -19
- package/src/repositories/associate-role.ts +12 -23
- package/src/repositories/attribute-group.test.ts +23 -23
- package/src/repositories/attribute-group.ts +6 -4
- package/src/repositories/business-unit.test.ts +63 -57
- package/src/repositories/business-unit.ts +107 -55
- package/src/repositories/cart/actions.ts +96 -65
- package/src/repositories/cart/helpers.ts +15 -11
- package/src/repositories/cart/index.test.ts +136 -30
- package/src/repositories/cart/index.ts +76 -59
- package/src/repositories/cart-discount/actions.ts +12 -44
- package/src/repositories/cart-discount/index.ts +20 -8
- package/src/repositories/category/actions.ts +27 -27
- package/src/repositories/category/index.test.ts +13 -9
- package/src/repositories/category/index.ts +40 -23
- package/src/repositories/channel.test.ts +53 -51
- package/src/repositories/channel.ts +12 -22
- package/src/repositories/custom-object.ts +34 -25
- package/src/repositories/customer/actions.ts +47 -25
- package/src/repositories/customer/index.test.ts +11 -11
- package/src/repositories/customer/index.ts +65 -35
- package/src/repositories/customer-group.test.ts +44 -42
- package/src/repositories/customer-group.ts +12 -22
- package/src/repositories/discount-code/actions.ts +3 -19
- package/src/repositories/discount-code/index.ts +9 -4
- package/src/repositories/discount-group/index.ts +8 -3
- package/src/repositories/extension.test.ts +27 -27
- package/src/repositories/extension.ts +10 -5
- package/src/repositories/helpers.ts +126 -47
- package/src/repositories/inventory-entry/actions.ts +3 -24
- package/src/repositories/inventory-entry/index.ts +19 -11
- package/src/repositories/my-customer.ts +13 -12
- package/src/repositories/my-order.ts +5 -2
- package/src/repositories/order/actions.ts +84 -56
- package/src/repositories/order/index.test.ts +36 -31
- package/src/repositories/order/index.ts +83 -49
- package/src/repositories/order-edit.ts +8 -3
- package/src/repositories/payment/actions.ts +64 -44
- package/src/repositories/payment/helpers.ts +3 -3
- package/src/repositories/payment/index.ts +28 -12
- package/src/repositories/product/actions.ts +133 -98
- package/src/repositories/product/helpers.ts +29 -16
- package/src/repositories/product/index.ts +42 -25
- package/src/repositories/product-discount.ts +6 -4
- package/src/repositories/product-projection.ts +41 -21
- package/src/repositories/product-selection.ts +8 -15
- package/src/repositories/product-tailoring.ts +22 -3
- package/src/repositories/product-type.ts +45 -4
- package/src/repositories/project.ts +57 -13
- package/src/repositories/quote/actions.ts +5 -28
- package/src/repositories/quote/index.ts +29 -6
- package/src/repositories/quote-request/actions.ts +5 -28
- package/src/repositories/quote-request/index.test.ts +3 -3
- package/src/repositories/quote-request/index.ts +31 -11
- package/src/repositories/quote-staged/actions.ts +5 -28
- package/src/repositories/quote-staged/index.ts +22 -8
- package/src/repositories/recurrence-policy/index.ts +6 -4
- package/src/repositories/recurring-order/actions.ts +7 -32
- package/src/repositories/recurring-order/index.ts +8 -6
- package/src/repositories/review.test.ts +147 -142
- package/src/repositories/review.ts +31 -37
- package/src/repositories/shipping-method/actions.ts +11 -28
- package/src/repositories/shipping-method/index.ts +26 -15
- package/src/repositories/shopping-list/actions.ts +21 -31
- package/src/repositories/shopping-list/index.ts +44 -22
- package/src/repositories/standalone-price.ts +6 -4
- package/src/repositories/state.ts +15 -9
- package/src/repositories/store.ts +21 -32
- package/src/repositories/subscription.test.ts +22 -22
- package/src/repositories/subscription.ts +8 -3
- package/src/repositories/tax-category/index.ts +8 -3
- package/src/repositories/type/actions.ts +21 -3
- package/src/repositories/type/index.ts +5 -3
- package/src/repositories/zone.test.ts +112 -77
- package/src/repositories/zone.ts +5 -3
- package/src/schemas/generated/associate-role.ts +13 -0
- package/src/schemas/generated/attribute-group.ts +12 -0
- package/src/schemas/generated/business-unit.ts +38 -0
- package/src/schemas/generated/cart-discount.ts +33 -0
- package/src/schemas/generated/cart.ts +61 -0
- package/src/schemas/generated/category.ts +25 -0
- package/src/schemas/generated/channel.ts +21 -0
- package/src/schemas/generated/common.ts +1372 -0
- package/src/schemas/generated/custom-object.ts +11 -0
- package/src/schemas/generated/customer-group.ts +11 -0
- package/src/schemas/generated/customer.ts +47 -0
- package/src/schemas/generated/discount-code.ts +25 -0
- package/src/schemas/generated/discount-group.ts +13 -0
- package/src/schemas/generated/extension.ts +15 -0
- package/src/schemas/generated/index.ts +42 -0
- package/src/schemas/generated/inventory-entry.ts +20 -0
- package/src/schemas/generated/my-quote-request.ts +10 -0
- package/src/schemas/generated/order-edit.ts +18 -0
- package/src/schemas/generated/order-from-cart.ts +25 -0
- package/src/schemas/generated/payment.ts +30 -0
- package/src/schemas/generated/product-discount.ts +20 -0
- package/src/schemas/generated/product-selection.ts +18 -0
- package/src/schemas/generated/product-tailoring.ts +26 -0
- package/src/schemas/generated/product-type.ts +12 -0
- package/src/schemas/generated/product.ts +37 -0
- package/src/schemas/generated/quote-request.ts +19 -0
- package/src/schemas/generated/quote.ts +18 -0
- package/src/schemas/generated/recurrence-policy.ts +15 -0
- package/src/schemas/generated/recurring-order.ts +19 -0
- package/src/schemas/generated/review.ts +24 -0
- package/src/schemas/generated/shipping-method.ts +24 -0
- package/src/schemas/generated/shopping-list.ts +28 -0
- package/src/schemas/generated/staged-quote.ts +18 -0
- package/src/schemas/generated/standalone-price.ts +32 -0
- package/src/schemas/generated/state.ts +20 -0
- package/src/schemas/generated/store.ts +23 -0
- package/src/schemas/generated/subscription.ts +20 -0
- package/src/schemas/generated/tax-category.ts +12 -0
- package/src/schemas/generated/type.ts +17 -0
- package/src/schemas/generated/zone.ts +12 -0
- package/src/schemas/update-request.ts +3 -5
- package/src/server.ts +32 -4
- package/src/services/abstract.ts +207 -101
- package/src/services/as-associate-cart.test.ts +28 -36
- package/src/services/as-associate-cart.ts +15 -12
- package/src/services/as-associate-order.test.ts +33 -40
- package/src/services/as-associate-order.ts +15 -12
- package/src/services/as-associate-quote-request.ts +15 -12
- package/src/services/as-associate-shopping-list.test.ts +25 -35
- package/src/services/as-associate-shopping-list.ts +15 -12
- package/src/services/as-associate.test.ts +21 -15
- package/src/services/as-associate.ts +23 -22
- package/src/services/associate-roles.test.ts +16 -22
- package/src/services/associate-roles.ts +2 -2
- package/src/services/attribute-group.test.ts +40 -44
- package/src/services/attribute-group.ts +2 -2
- package/src/services/business-units.test.ts +227 -163
- package/src/services/business-units.ts +2 -2
- package/src/services/cart-discount.test.ts +253 -187
- package/src/services/cart-discount.ts +2 -2
- package/src/services/cart.test.ts +833 -832
- package/src/services/cart.ts +31 -12
- package/src/services/category.test.ts +208 -130
- package/src/services/category.ts +2 -2
- package/src/services/channel.test.ts +39 -44
- package/src/services/channel.ts +2 -2
- package/src/services/custom-object.test.ts +103 -79
- package/src/services/custom-object.ts +106 -38
- package/src/services/customer-group.test.ts +39 -44
- package/src/services/customer-group.ts +2 -2
- package/src/services/customer.test.ts +357 -292
- package/src/services/customer.ts +70 -23
- package/src/services/discount-code.test.ts +57 -68
- package/src/services/discount-code.ts +2 -2
- package/src/services/discount-group.test.ts +111 -134
- package/src/services/discount-group.ts +2 -2
- package/src/services/draft-validation.test.ts +255 -0
- package/src/services/extension.test.ts +39 -44
- package/src/services/extension.ts +2 -2
- package/src/services/inventory-entry.test.ts +106 -87
- package/src/services/inventory-entry.ts +2 -2
- package/src/services/my-business-unit.test.ts +82 -112
- package/src/services/my-business-unit.ts +25 -19
- package/src/services/my-cart.test.ts +46 -41
- package/src/services/my-cart.ts +32 -28
- package/src/services/my-customer.test.ts +153 -88
- package/src/services/my-customer.ts +130 -61
- package/src/services/my-order.ts +15 -12
- package/src/services/my-payment.test.ts +30 -24
- package/src/services/my-payment.ts +2 -2
- package/src/services/my-shopping-list.ts +2 -2
- package/src/services/order.test.ts +332 -276
- package/src/services/order.ts +45 -27
- package/src/services/payment.test.ts +31 -29
- package/src/services/payment.ts +2 -2
- package/src/services/product-discount.test.ts +39 -46
- package/src/services/product-discount.ts +2 -2
- package/src/services/product-projection.test.ts +176 -166
- package/src/services/product-projection.ts +31 -15
- package/src/services/product-selection.test.ts +17 -9
- package/src/services/product-selection.ts +2 -2
- package/src/services/product-type.test.ts +80 -21
- package/src/services/product-type.ts +2 -2
- package/src/services/product.test.ts +569 -534
- package/src/services/product.ts +14 -7
- package/src/services/project.test.ts +22 -12
- package/src/services/project.ts +28 -13
- package/src/services/quote-request.test.ts +36 -39
- package/src/services/quote-request.ts +2 -2
- package/src/services/quote-staged.ts +2 -2
- package/src/services/quote.ts +2 -2
- package/src/services/recurrence-policy.test.ts +114 -139
- package/src/services/recurrence-policy.ts +2 -2
- package/src/services/recurring-order.test.ts +149 -194
- package/src/services/recurring-order.ts +2 -2
- package/src/services/reviews.test.ts +127 -106
- package/src/services/reviews.ts +2 -2
- package/src/services/shipping-method.test.ts +96 -125
- package/src/services/shipping-method.ts +24 -12
- package/src/services/shopping-list.test.ts +183 -141
- package/src/services/shopping-list.ts +2 -2
- package/src/services/standalone-price.test.ts +60 -46
- package/src/services/standalone-price.ts +2 -2
- package/src/services/state.test.ts +20 -25
- package/src/services/state.ts +2 -2
- package/src/services/store.test.ts +26 -45
- package/src/services/store.ts +2 -2
- package/src/services/subscription.test.ts +39 -44
- package/src/services/subscription.ts +2 -2
- package/src/services/tax-category.test.ts +33 -36
- package/src/services/tax-category.ts +2 -2
- package/src/services/type.test.ts +45 -44
- package/src/services/type.ts +2 -2
- package/src/services/zone.test.ts +40 -44
- package/src/services/zone.ts +2 -2
- package/src/shipping.ts +41 -11
- package/src/storage/abstract.ts +248 -17
- package/src/storage/in-memory.ts +147 -290
- package/src/storage/sqlite.ts +429 -0
- package/src/storage/storage-map.ts +75 -0
- package/src/storage/storage.test-helpers.ts +97 -0
- package/src/storage/storage.test.ts +802 -0
- package/src/testing/associate-role.ts +28 -0
- package/src/testing/attribute-group.ts +27 -0
- package/src/testing/business-unit.ts +9 -8
- package/src/testing/cart-discount.ts +34 -0
- package/src/testing/cart.ts +20 -0
- package/src/testing/category.ts +25 -0
- package/src/testing/channel.ts +23 -0
- package/src/testing/custom-object.ts +27 -0
- package/src/testing/customer-group.ts +26 -0
- package/src/testing/customer.ts +36 -33
- package/src/testing/discount-code.ts +29 -0
- package/src/testing/discount-group.ts +27 -0
- package/src/testing/extension.ts +32 -0
- package/src/testing/index.ts +33 -0
- package/src/testing/inventory-entry.ts +26 -0
- package/src/testing/order.ts +27 -0
- package/src/testing/payment.ts +23 -0
- package/src/testing/product-discount.ts +33 -0
- package/src/testing/product-selection.ts +28 -0
- package/src/testing/product-type.ts +27 -0
- package/src/testing/product.ts +38 -0
- package/src/testing/quote-request.ts +29 -0
- package/src/testing/recurrence-policy.ts +33 -0
- package/src/testing/recurring-order.ts +32 -0
- package/src/testing/review.ts +24 -0
- package/src/testing/shipping-method.ts +31 -0
- package/src/testing/shopping-list.ts +25 -0
- package/src/testing/standalone-price.ts +31 -0
- package/src/testing/state.ts +21 -0
- package/src/testing/store.ts +26 -0
- package/src/testing/subscription.ts +38 -0
- package/src/testing/tax-category.ts +27 -0
- package/src/testing/type.ts +9 -6
- package/src/testing/zone.ts +22 -0
- package/src/validate.test.ts +122 -0
- package/src/validate.ts +78 -7
- package/src/.env +0 -0
package/src/oauth/server.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import type { InvalidTokenError } from "@commercetools/platform-sdk";
|
|
2
2
|
import auth from "basic-auth";
|
|
3
|
-
import
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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(
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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:
|
|
81
|
+
return async (request: FastifyRequest, reply: FastifyReply) => {
|
|
76
82
|
const token = getBearerToken(request);
|
|
77
83
|
if (!token) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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
|
-
|
|
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:
|
|
108
|
-
|
|
109
|
-
next: NextFunction,
|
|
114
|
+
request: FastifyRequest,
|
|
115
|
+
reply: FastifyReply,
|
|
110
116
|
) {
|
|
111
|
-
const authHeader = request.
|
|
117
|
+
const authHeader = request.headers.authorization;
|
|
112
118
|
if (!authHeader) {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
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
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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:
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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
|
|
163
|
+
const query = request.query;
|
|
164
|
+
const body = request.body;
|
|
165
|
+
const grantType = query.grant_type || body?.grant_type;
|
|
164
166
|
if (!grantType) {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
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
|
-
|
|
180
|
+
query.scope?.toString(),
|
|
181
181
|
);
|
|
182
|
-
|
|
183
|
-
return;
|
|
182
|
+
return reply.status(200).send(token);
|
|
184
183
|
}
|
|
185
184
|
if (grantType === "refresh_token") {
|
|
186
185
|
const refreshToken =
|
|
187
|
-
|
|
186
|
+
query.refresh_token?.toString() || body?.refresh_token;
|
|
188
187
|
if (!refreshToken) {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|
-
|
|
219
|
-
return;
|
|
213
|
+
return reply.status(200).send(token);
|
|
220
214
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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:
|
|
234
|
-
|
|
235
|
-
|
|
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
|
|
238
|
-
const
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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 =
|
|
253
|
-
const password = hashPassword(
|
|
254
|
-
|
|
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:
|
|
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
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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(
|
|
280
|
-
|
|
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:
|
|
286
|
-
|
|
287
|
-
|
|
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
|
|
290
|
-
const
|
|
291
|
-
const
|
|
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
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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 =
|
|
306
|
-
const password = hashPassword(
|
|
307
|
-
|
|
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
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
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(
|
|
333
|
-
|
|
334
|
-
|
|
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:
|
|
340
|
-
|
|
341
|
-
|
|
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
|
|
344
|
-
const
|
|
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
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
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
|
-
|
|
369
|
-
return;
|
|
371
|
+
return reply.status(200).send(token);
|
|
370
372
|
}
|
|
371
373
|
}
|
|
372
374
|
}
|
package/src/oauth/store.ts
CHANGED
|
@@ -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(
|
|
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 {
|
package/src/orderSearch.ts
CHANGED
|
@@ -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;
|