@labdigital/commercetools-mock 2.17.0 → 2.18.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 +4219 -3989
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +268 -415
- package/dist/index.d.ts +268 -415
- package/dist/index.js +4219 -3989
- package/dist/index.js.map +1 -1
- package/package.json +44 -46
- package/src/constants.ts +2 -2
- package/src/ctMock.test.ts +11 -11
- package/src/ctMock.ts +141 -127
- package/src/deprecation.ts +8 -0
- package/src/exceptions.ts +17 -15
- package/src/helpers.ts +32 -32
- package/src/index.test.ts +128 -128
- package/src/index.ts +3 -3
- package/src/lib/expandParser.ts +13 -13
- package/src/lib/haversine.test.ts +9 -9
- package/src/lib/haversine.ts +11 -11
- package/src/lib/masking.ts +11 -11
- package/src/lib/parser.ts +2 -2
- package/src/lib/password.ts +23 -3
- package/src/lib/predicateParser.test.ts +185 -183
- package/src/lib/predicateParser.ts +234 -234
- package/src/lib/projectionSearchFilter.test.ts +103 -101
- package/src/lib/projectionSearchFilter.ts +152 -150
- package/src/lib/proxy.ts +5 -5
- package/src/oauth/errors.ts +4 -4
- package/src/oauth/helpers.ts +6 -6
- package/src/oauth/server.test.ts +110 -67
- package/src/oauth/server.ts +161 -141
- package/src/oauth/store.ts +49 -44
- package/src/priceSelector.test.ts +35 -35
- package/src/priceSelector.ts +30 -30
- package/src/product-projection-search.ts +136 -134
- package/src/projectAPI.test.ts +7 -7
- package/src/projectAPI.ts +24 -22
- package/src/repositories/abstract.ts +168 -116
- package/src/repositories/associate-role.ts +90 -77
- package/src/repositories/attribute-group.ts +51 -40
- package/src/repositories/business-unit.ts +168 -148
- package/src/repositories/cart/actions.ts +489 -0
- package/src/repositories/cart/helpers.ts +30 -0
- package/src/repositories/cart/index.ts +180 -0
- package/src/repositories/cart-discount/actions.ts +148 -0
- package/src/repositories/cart-discount/index.ts +86 -0
- package/src/repositories/category/actions.ts +231 -0
- package/src/repositories/category/index.ts +52 -0
- package/src/repositories/channel.ts +88 -90
- package/src/repositories/custom-object.ts +46 -45
- package/src/repositories/customer/actions.ts +165 -0
- package/src/repositories/customer/index.ts +79 -0
- package/src/repositories/customer-group.ts +66 -55
- package/src/repositories/discount-code/actions.ts +149 -0
- package/src/repositories/discount-code/index.ts +50 -0
- package/src/repositories/errors.ts +10 -10
- package/src/repositories/extension.ts +64 -62
- package/src/repositories/helpers.ts +117 -118
- package/src/repositories/index.ts +80 -79
- package/src/repositories/inventory-entry/actions.ts +84 -0
- package/src/repositories/inventory-entry/index.ts +44 -0
- package/src/repositories/my-customer.ts +114 -0
- package/src/repositories/my-order.ts +8 -8
- package/src/repositories/order/actions.ts +281 -0
- package/src/repositories/{order.test.ts → order/index.test.ts} +77 -77
- package/src/repositories/order/index.ts +260 -0
- package/src/repositories/order-edit.ts +10 -23
- package/src/repositories/payment/actions.ts +305 -0
- package/src/repositories/payment/helpers.ts +17 -0
- package/src/repositories/payment/index.ts +56 -0
- package/src/repositories/product/actions.ts +943 -0
- package/src/repositories/product/helpers.ts +98 -0
- package/src/repositories/product/index.ts +130 -0
- package/src/repositories/product-discount.ts +127 -117
- package/src/repositories/product-projection.ts +56 -62
- package/src/repositories/product-selection.ts +31 -28
- package/src/repositories/product-type.ts +136 -134
- package/src/repositories/project.ts +133 -118
- package/src/repositories/quote-request.ts +7 -19
- package/src/repositories/quote.ts +7 -22
- package/src/repositories/review.ts +13 -26
- package/src/repositories/shipping-method/actions.ts +198 -0
- package/src/repositories/shipping-method/helpers.ts +10 -0
- package/src/repositories/shipping-method/index.ts +138 -0
- package/src/repositories/shopping-list/actions.ts +295 -0
- package/src/repositories/shopping-list/index.ts +122 -0
- package/src/repositories/staged-quote.ts +7 -20
- package/src/repositories/standalone-price.ts +57 -44
- package/src/repositories/state.ts +113 -68
- package/src/repositories/store.ts +106 -94
- package/src/repositories/subscription.ts +46 -22
- package/src/repositories/tax-category/actions.ts +94 -0
- package/src/repositories/tax-category/helpers.ts +8 -0
- package/src/repositories/tax-category/index.ts +25 -0
- package/src/repositories/type/actions.ts +162 -0
- package/src/repositories/type/index.ts +24 -0
- package/src/repositories/zone.ts +62 -58
- package/src/server.ts +9 -9
- package/src/services/abstract.ts +75 -72
- package/src/services/associate-roles.test.ts +27 -27
- package/src/services/associate-roles.ts +7 -7
- package/src/services/attribute-group.ts +7 -7
- package/src/services/business-units.test.ts +28 -28
- package/src/services/business-units.ts +7 -7
- package/src/services/cart-discount.test.ts +199 -199
- package/src/services/cart-discount.ts +7 -7
- package/src/services/cart.test.ts +261 -261
- package/src/services/cart.ts +22 -21
- package/src/services/category.test.ts +121 -121
- package/src/services/category.ts +7 -7
- package/src/services/channel.ts +7 -7
- package/src/services/custom-object.test.ts +130 -130
- package/src/services/custom-object.ts +34 -31
- package/src/services/customer-group.ts +7 -7
- package/src/services/customer.test.ts +205 -205
- package/src/services/customer.ts +31 -29
- package/src/services/discount-code.ts +7 -7
- package/src/services/extension.ts +7 -7
- package/src/services/index.ts +85 -81
- package/src/services/inventory-entry.test.ts +106 -106
- package/src/services/inventory-entry.ts +7 -7
- package/src/services/my-cart.test.ts +56 -56
- package/src/services/my-cart.ts +20 -20
- package/src/services/my-customer.test.ts +155 -104
- package/src/services/my-customer.ts +61 -75
- package/src/services/my-order.ts +16 -16
- package/src/services/my-payment.test.ts +40 -40
- package/src/services/my-payment.ts +7 -7
- package/src/services/my-shopping-list.ts +7 -7
- package/src/services/order.test.ts +243 -243
- package/src/services/order.ts +23 -18
- package/src/services/payment.test.ts +40 -40
- package/src/services/payment.ts +7 -7
- package/src/services/product-discount.ts +7 -7
- package/src/services/product-projection.test.ts +190 -190
- package/src/services/product-projection.ts +34 -32
- package/src/services/product-selection.test.ts +19 -19
- package/src/services/product-selection.ts +7 -7
- package/src/services/product-type.test.ts +38 -38
- package/src/services/product-type.ts +7 -7
- package/src/services/product.test.ts +658 -656
- package/src/services/product.ts +7 -7
- package/src/services/project.test.ts +24 -24
- package/src/services/project.ts +17 -17
- package/src/services/reviews.ts +7 -7
- package/src/services/shipping-method.test.ts +78 -78
- package/src/services/shipping-method.ts +16 -16
- package/src/services/shopping-list.test.ts +170 -170
- package/src/services/shopping-list.ts +7 -7
- package/src/services/standalone-price.test.ts +112 -112
- package/src/services/standalone-price.ts +7 -7
- package/src/services/state.test.ts +30 -30
- package/src/services/state.ts +7 -7
- package/src/services/store.test.ts +40 -40
- package/src/services/store.ts +7 -7
- package/src/services/subscription.ts +7 -7
- package/src/services/tax-category.test.ts +43 -43
- package/src/services/tax-category.ts +7 -7
- package/src/services/type.ts +7 -7
- package/src/services/zone.ts +7 -7
- package/src/shippingCalculator.test.ts +43 -43
- package/src/shippingCalculator.ts +23 -23
- package/src/storage/abstract.ts +36 -34
- package/src/storage/in-memory.ts +237 -233
- package/src/storage/index.ts +2 -2
- package/src/types.ts +91 -91
- package/src/repositories/cart-discount.ts +0 -219
- package/src/repositories/cart.ts +0 -659
- package/src/repositories/category.ts +0 -256
- package/src/repositories/customer.ts +0 -228
- package/src/repositories/discount-code.ts +0 -181
- package/src/repositories/inventory-entry.ts +0 -109
- package/src/repositories/order.ts +0 -514
- package/src/repositories/payment.ts +0 -342
- package/src/repositories/product.ts +0 -1106
- package/src/repositories/shipping-method.ts +0 -312
- package/src/repositories/shopping-list.ts +0 -392
- package/src/repositories/tax-category.ts +0 -111
- package/src/repositories/type.ts +0 -172
package/src/oauth/server.test.ts
CHANGED
|
@@ -1,89 +1,132 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import express from "express";
|
|
2
|
+
import supertest from "supertest";
|
|
3
|
+
import { beforeEach, describe, expect, it } from "vitest";
|
|
4
|
+
import { getBaseResourceProperties } from "../helpers";
|
|
5
|
+
import { hashPassword } from "../lib/password";
|
|
6
|
+
import { CustomerRepository } from "../repositories/customer";
|
|
7
|
+
import { AbstractStorage, InMemoryStorage } from "../storage";
|
|
8
|
+
import { OAuth2Server } from "./server";
|
|
9
|
+
|
|
10
|
+
describe("OAuth2Server", () => {
|
|
11
|
+
let app: express.Express;
|
|
12
|
+
let server: OAuth2Server;
|
|
13
|
+
|
|
14
|
+
let storage: AbstractStorage;
|
|
15
|
+
let customerRepository: CustomerRepository;
|
|
9
16
|
|
|
10
17
|
beforeEach(() => {
|
|
11
|
-
server = new OAuth2Server({ enabled: true, validate: false })
|
|
12
|
-
app = express()
|
|
13
|
-
app.use(server.createRouter())
|
|
14
|
-
|
|
18
|
+
server = new OAuth2Server({ enabled: true, validate: false });
|
|
19
|
+
app = express();
|
|
20
|
+
app.use(server.createRouter());
|
|
21
|
+
|
|
22
|
+
storage = new InMemoryStorage();
|
|
23
|
+
customerRepository = new CustomerRepository(storage);
|
|
24
|
+
server.setCustomerRepository(customerRepository);
|
|
25
|
+
});
|
|
15
26
|
|
|
16
|
-
describe(
|
|
17
|
-
it(
|
|
27
|
+
describe("POST /token", () => {
|
|
28
|
+
it("should return a token for valid client credentials", async () => {
|
|
18
29
|
const response = await supertest(app)
|
|
19
|
-
.post(
|
|
20
|
-
.auth(
|
|
21
|
-
.query({ grant_type:
|
|
22
|
-
.send()
|
|
30
|
+
.post("/token")
|
|
31
|
+
.auth("validClientId", "validClientSecret")
|
|
32
|
+
.query({ grant_type: "client_credentials" })
|
|
33
|
+
.send();
|
|
23
34
|
|
|
24
|
-
const body = await response.body
|
|
35
|
+
const body = await response.body;
|
|
25
36
|
|
|
26
|
-
expect(response.status, JSON.stringify(body)).toBe(200)
|
|
27
|
-
expect(body).toHaveProperty(
|
|
28
|
-
})
|
|
37
|
+
expect(response.status, JSON.stringify(body)).toBe(200);
|
|
38
|
+
expect(body).toHaveProperty("access_token");
|
|
39
|
+
});
|
|
29
40
|
|
|
30
|
-
it(
|
|
41
|
+
it("should failed on invalid refresh token", async () => {
|
|
31
42
|
const response = await supertest(app)
|
|
32
|
-
.post(
|
|
33
|
-
.auth(
|
|
34
|
-
.query({ grant_type:
|
|
35
|
-
.send()
|
|
43
|
+
.post("/token")
|
|
44
|
+
.auth("validClientId", "validClientSecret")
|
|
45
|
+
.query({ grant_type: "refresh_token", refresh_token: "invalid" })
|
|
46
|
+
.send();
|
|
36
47
|
|
|
37
|
-
const body = await response.body
|
|
48
|
+
const body = await response.body;
|
|
38
49
|
|
|
39
|
-
expect(response.status, JSON.stringify(body)).toBe(400)
|
|
40
|
-
})
|
|
50
|
+
expect(response.status, JSON.stringify(body)).toBe(400);
|
|
51
|
+
});
|
|
41
52
|
|
|
42
|
-
it(
|
|
53
|
+
it("should refresh a token", async () => {
|
|
43
54
|
const createResponse = await supertest(app)
|
|
44
55
|
.post(`/my-project/anonymous/token`)
|
|
45
|
-
.auth(
|
|
46
|
-
.query({ grant_type:
|
|
47
|
-
.send()
|
|
56
|
+
.auth("validClientId", "validClientSecret")
|
|
57
|
+
.query({ grant_type: "client_credentials" })
|
|
58
|
+
.send();
|
|
48
59
|
|
|
49
|
-
const refreshToken = createResponse.body.refresh_token
|
|
60
|
+
const refreshToken = createResponse.body.refresh_token;
|
|
50
61
|
|
|
51
62
|
const response = await supertest(app)
|
|
52
|
-
.post(
|
|
53
|
-
.auth(
|
|
54
|
-
.query({ grant_type:
|
|
55
|
-
.send()
|
|
63
|
+
.post("/token")
|
|
64
|
+
.auth("validClientId", "validClientSecret")
|
|
65
|
+
.query({ grant_type: "refresh_token", refresh_token: refreshToken })
|
|
66
|
+
.send();
|
|
56
67
|
|
|
57
|
-
const body = await response.body
|
|
68
|
+
const body = await response.body;
|
|
58
69
|
|
|
59
|
-
expect(response.status, JSON.stringify(body)).toBe(200)
|
|
60
|
-
expect(body.access_token).not.toBe(createResponse.body.access_token)
|
|
61
|
-
expect(body.refresh_token).toBeUndefined()
|
|
62
|
-
})
|
|
63
|
-
})
|
|
70
|
+
expect(response.status, JSON.stringify(body)).toBe(200);
|
|
71
|
+
expect(body.access_token).not.toBe(createResponse.body.access_token);
|
|
72
|
+
expect(body.refresh_token).toBeUndefined();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
64
75
|
|
|
65
|
-
describe(
|
|
66
|
-
it(
|
|
67
|
-
const projectKey =
|
|
76
|
+
describe("POST /:projectKey/anonymous/token", () => {
|
|
77
|
+
it("should return a token for anonymous access", async () => {
|
|
78
|
+
const projectKey = "test-project";
|
|
68
79
|
|
|
69
80
|
const response = await supertest(app)
|
|
70
81
|
.post(`/${projectKey}/anonymous/token`)
|
|
71
|
-
.auth(
|
|
72
|
-
.query({ grant_type:
|
|
73
|
-
.send()
|
|
74
|
-
|
|
75
|
-
expect(response.status).toBe(200)
|
|
76
|
-
expect(response.body).toHaveProperty(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
82
|
+
.auth("validClientId", "validClientSecret")
|
|
83
|
+
.query({ grant_type: "client_credentials" })
|
|
84
|
+
.send();
|
|
85
|
+
|
|
86
|
+
expect(response.status).toBe(200);
|
|
87
|
+
expect(response.body).toHaveProperty("access_token");
|
|
88
|
+
expect(response.body).toEqual({
|
|
89
|
+
scope: expect.stringMatching(/anonymous_id:([^\s]+)/),
|
|
90
|
+
access_token: expect.stringMatching(/\S{8,}==$/),
|
|
91
|
+
refresh_token: expect.stringMatching(/test-project:\S{8,}==$/),
|
|
92
|
+
expires_in: 172800,
|
|
93
|
+
token_type: "Bearer",
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe("POST /:projectKey/customers/token", () => {
|
|
99
|
+
it("should return a token for customer access", async () => {
|
|
100
|
+
const projectKey = "test-project";
|
|
101
|
+
|
|
102
|
+
storage.add(projectKey, "customer", {
|
|
103
|
+
...getBaseResourceProperties(),
|
|
104
|
+
email: "j.doe@example.org",
|
|
105
|
+
password: hashPassword("password"),
|
|
106
|
+
addresses: [],
|
|
107
|
+
authenticationMode: "password",
|
|
108
|
+
isEmailVerified: true,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const response = await supertest(app)
|
|
112
|
+
.post(`/${projectKey}/customers/token`)
|
|
113
|
+
.auth("validClientId", "validClientSecret")
|
|
114
|
+
.query({
|
|
115
|
+
grant_type: "password",
|
|
116
|
+
username: "j.doe@example.org",
|
|
117
|
+
password: "password",
|
|
118
|
+
scope: `${projectKey}:manage_my_profile`,
|
|
119
|
+
})
|
|
120
|
+
.send();
|
|
121
|
+
|
|
122
|
+
expect(response.status).toBe(200);
|
|
123
|
+
expect(response.body).toEqual({
|
|
124
|
+
scope: expect.stringMatching(/customer_id:([^\s]+)/),
|
|
125
|
+
access_token: expect.stringMatching(/\S{8,}==$/),
|
|
126
|
+
refresh_token: expect.stringMatching(/test-project:\S{8,}==$/),
|
|
127
|
+
expires_in: 172800,
|
|
128
|
+
token_type: "Bearer",
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
package/src/oauth/server.ts
CHANGED
|
@@ -1,66 +1,67 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { InvalidTokenError } from "@commercetools/platform-sdk";
|
|
2
|
+
import auth from "basic-auth";
|
|
3
|
+
import bodyParser from "body-parser";
|
|
3
4
|
import express, {
|
|
4
5
|
type NextFunction,
|
|
5
6
|
type Request,
|
|
6
7
|
type Response,
|
|
7
|
-
} from
|
|
8
|
-
import { InvalidTokenError } from '@commercetools/platform-sdk'
|
|
8
|
+
} from "express";
|
|
9
9
|
import {
|
|
10
10
|
AuthError,
|
|
11
11
|
CommercetoolsError,
|
|
12
12
|
InvalidRequestError,
|
|
13
|
-
} from
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
13
|
+
} from "~src/exceptions";
|
|
14
|
+
import { hashPassword } from "../lib/password";
|
|
15
|
+
import { CustomerRepository } from "../repositories/customer";
|
|
16
|
+
import { InvalidClientError, UnsupportedGrantType } from "./errors";
|
|
17
|
+
import { getBearerToken } from "./helpers";
|
|
18
|
+
import { OAuth2Store } from "./store";
|
|
19
19
|
|
|
20
20
|
type AuthRequest = Request & {
|
|
21
|
-
credentials
|
|
22
|
-
clientId: string
|
|
23
|
-
clientSecret: string
|
|
24
|
-
}
|
|
25
|
-
}
|
|
21
|
+
credentials?: {
|
|
22
|
+
clientId: string;
|
|
23
|
+
clientSecret: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
26
|
export type Token = {
|
|
27
|
-
access_token: string
|
|
28
|
-
token_type:
|
|
29
|
-
expires_in: number
|
|
30
|
-
scope: string
|
|
31
|
-
refresh_token?: string
|
|
32
|
-
}
|
|
27
|
+
access_token: string;
|
|
28
|
+
token_type: "Bearer";
|
|
29
|
+
expires_in: number;
|
|
30
|
+
scope: string;
|
|
31
|
+
refresh_token?: string;
|
|
32
|
+
};
|
|
33
33
|
|
|
34
34
|
export class OAuth2Server {
|
|
35
|
-
store: OAuth2Store
|
|
36
|
-
|
|
35
|
+
store: OAuth2Store;
|
|
36
|
+
|
|
37
|
+
private customerRepository: CustomerRepository;
|
|
37
38
|
|
|
38
39
|
constructor(private options: { enabled: boolean; validate: boolean }) {
|
|
39
|
-
this.store = new OAuth2Store(options.validate)
|
|
40
|
+
this.store = new OAuth2Store(options.validate);
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
setCustomerRepository(repository: CustomerRepository) {
|
|
43
|
-
this.customerRepository = repository
|
|
44
|
+
this.customerRepository = repository;
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
createRouter() {
|
|
47
|
-
const router = express.Router()
|
|
48
|
-
router.use(bodyParser.urlencoded({ extended: true }))
|
|
49
|
-
router.use(this.validateClientCredentials.bind(this))
|
|
50
|
-
router.post(
|
|
48
|
+
const router = express.Router();
|
|
49
|
+
router.use(bodyParser.urlencoded({ extended: true }));
|
|
50
|
+
router.use(this.validateClientCredentials.bind(this));
|
|
51
|
+
router.post("/token", this.tokenHandler.bind(this));
|
|
51
52
|
router.post(
|
|
52
|
-
|
|
53
|
-
this.customerTokenHandler.bind(this)
|
|
54
|
-
)
|
|
53
|
+
"/:projectKey/customers/token",
|
|
54
|
+
this.customerTokenHandler.bind(this),
|
|
55
|
+
);
|
|
55
56
|
router.post(
|
|
56
|
-
|
|
57
|
-
this.inStoreCustomerTokenHandler.bind(this)
|
|
58
|
-
)
|
|
57
|
+
"/:projectKey/in-store/key=:storeKey/customers/token",
|
|
58
|
+
this.inStoreCustomerTokenHandler.bind(this),
|
|
59
|
+
);
|
|
59
60
|
router.post(
|
|
60
|
-
|
|
61
|
-
this.anonymousTokenHandler.bind(this)
|
|
62
|
-
)
|
|
63
|
-
return router
|
|
61
|
+
"/:projectKey/anonymous/token",
|
|
62
|
+
this.anonymousTokenHandler.bind(this),
|
|
63
|
+
);
|
|
64
|
+
return router;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
createMiddleware() {
|
|
@@ -68,247 +69,266 @@ export class OAuth2Server {
|
|
|
68
69
|
return async (
|
|
69
70
|
request: Request,
|
|
70
71
|
response: Response,
|
|
71
|
-
next: NextFunction
|
|
72
|
+
next: NextFunction,
|
|
72
73
|
) => {
|
|
73
|
-
next()
|
|
74
|
-
}
|
|
74
|
+
next();
|
|
75
|
+
};
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
return async (request: Request, response: Response, next: NextFunction) => {
|
|
78
|
-
const token = getBearerToken(request)
|
|
79
|
+
const token = getBearerToken(request);
|
|
79
80
|
if (!token) {
|
|
80
81
|
next(
|
|
81
82
|
new CommercetoolsError<InvalidTokenError>(
|
|
82
83
|
{
|
|
83
|
-
code:
|
|
84
|
+
code: "invalid_token",
|
|
84
85
|
message:
|
|
85
|
-
|
|
86
|
+
"This endpoint requires an access token. You can get one from the authorization server.",
|
|
86
87
|
},
|
|
87
|
-
401
|
|
88
|
-
)
|
|
89
|
-
)
|
|
88
|
+
401,
|
|
89
|
+
),
|
|
90
|
+
);
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
if (!token || !this.store.validateToken(token)) {
|
|
93
94
|
next(
|
|
94
95
|
new CommercetoolsError<InvalidTokenError>(
|
|
95
96
|
{
|
|
96
|
-
code:
|
|
97
|
-
message:
|
|
97
|
+
code: "invalid_token",
|
|
98
|
+
message: "invalid_token",
|
|
98
99
|
},
|
|
99
|
-
401
|
|
100
|
-
)
|
|
101
|
-
)
|
|
100
|
+
401,
|
|
101
|
+
),
|
|
102
|
+
);
|
|
102
103
|
}
|
|
103
104
|
|
|
104
|
-
next()
|
|
105
|
-
}
|
|
105
|
+
next();
|
|
106
|
+
};
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
async validateClientCredentials(
|
|
109
110
|
request: AuthRequest,
|
|
110
111
|
response: Response,
|
|
111
|
-
next: NextFunction
|
|
112
|
+
next: NextFunction,
|
|
112
113
|
) {
|
|
113
|
-
const authHeader = request.header(
|
|
114
|
+
const authHeader = request.header("Authorization");
|
|
114
115
|
if (!authHeader) {
|
|
115
116
|
return next(
|
|
116
117
|
new CommercetoolsError<InvalidClientError>(
|
|
117
118
|
{
|
|
118
|
-
code:
|
|
119
|
+
code: "invalid_client",
|
|
119
120
|
message:
|
|
120
|
-
|
|
121
|
+
"Please provide valid client credentials using HTTP Basic Authentication.",
|
|
121
122
|
},
|
|
122
|
-
401
|
|
123
|
-
)
|
|
124
|
-
)
|
|
123
|
+
401,
|
|
124
|
+
),
|
|
125
|
+
);
|
|
125
126
|
}
|
|
126
|
-
const credentials = auth.parse(authHeader)
|
|
127
|
+
const credentials = auth.parse(authHeader);
|
|
127
128
|
if (!credentials) {
|
|
128
129
|
return next(
|
|
129
130
|
new CommercetoolsError<InvalidClientError>(
|
|
130
131
|
{
|
|
131
|
-
code:
|
|
132
|
+
code: "invalid_client",
|
|
132
133
|
message:
|
|
133
|
-
|
|
134
|
+
"Please provide valid client credentials using HTTP Basic Authentication.",
|
|
134
135
|
},
|
|
135
|
-
400
|
|
136
|
-
)
|
|
137
|
-
)
|
|
136
|
+
400,
|
|
137
|
+
),
|
|
138
|
+
);
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
request.credentials = {
|
|
141
142
|
clientId: credentials.name,
|
|
142
143
|
clientSecret: credentials.pass,
|
|
143
|
-
}
|
|
144
|
+
};
|
|
144
145
|
|
|
145
|
-
next()
|
|
146
|
+
next();
|
|
146
147
|
}
|
|
147
148
|
|
|
148
149
|
async tokenHandler(
|
|
149
150
|
request: AuthRequest,
|
|
150
151
|
response: Response,
|
|
151
|
-
next: NextFunction
|
|
152
|
+
next: NextFunction,
|
|
152
153
|
) {
|
|
153
|
-
|
|
154
|
+
if (!request.credentials) {
|
|
155
|
+
return next(
|
|
156
|
+
new CommercetoolsError<InvalidClientError>(
|
|
157
|
+
{
|
|
158
|
+
code: "invalid_client",
|
|
159
|
+
message: "Client credentials are missing.",
|
|
160
|
+
},
|
|
161
|
+
401,
|
|
162
|
+
),
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const grantType = request.query.grant_type || request.body.grant_type;
|
|
154
167
|
if (!grantType) {
|
|
155
168
|
return next(
|
|
156
169
|
new CommercetoolsError<InvalidRequestError>(
|
|
157
170
|
{
|
|
158
|
-
code:
|
|
159
|
-
message:
|
|
171
|
+
code: "invalid_request",
|
|
172
|
+
message: "Missing required parameter: grant_type.",
|
|
160
173
|
},
|
|
161
|
-
400
|
|
162
|
-
)
|
|
163
|
-
)
|
|
174
|
+
400,
|
|
175
|
+
),
|
|
176
|
+
);
|
|
164
177
|
}
|
|
165
178
|
|
|
166
|
-
if (grantType ===
|
|
179
|
+
if (grantType === "client_credentials") {
|
|
167
180
|
const token = this.store.getClientToken(
|
|
168
181
|
request.credentials.clientId,
|
|
169
182
|
request.credentials.clientSecret,
|
|
170
|
-
request.query.scope?.toString()
|
|
171
|
-
)
|
|
172
|
-
return response.status(200).send(token)
|
|
173
|
-
} else if (grantType ===
|
|
183
|
+
request.query.scope?.toString(),
|
|
184
|
+
);
|
|
185
|
+
return response.status(200).send(token);
|
|
186
|
+
} else if (grantType === "refresh_token") {
|
|
174
187
|
const refreshToken =
|
|
175
|
-
request.query.refresh_token?.toString() || request.body.refresh_token
|
|
188
|
+
request.query.refresh_token?.toString() || request.body.refresh_token;
|
|
176
189
|
if (!refreshToken) {
|
|
177
190
|
return next(
|
|
178
191
|
new CommercetoolsError<InvalidRequestError>(
|
|
179
192
|
{
|
|
180
|
-
code:
|
|
181
|
-
message:
|
|
193
|
+
code: "invalid_request",
|
|
194
|
+
message: "Missing required parameter: refresh_token.",
|
|
182
195
|
},
|
|
183
|
-
400
|
|
184
|
-
)
|
|
185
|
-
)
|
|
196
|
+
400,
|
|
197
|
+
),
|
|
198
|
+
);
|
|
186
199
|
}
|
|
187
200
|
const token = this.store.refreshToken(
|
|
188
201
|
request.credentials.clientId,
|
|
189
202
|
request.credentials.clientSecret,
|
|
190
|
-
refreshToken
|
|
191
|
-
)
|
|
203
|
+
refreshToken,
|
|
204
|
+
);
|
|
192
205
|
if (!token) {
|
|
193
206
|
return next(
|
|
194
207
|
new CommercetoolsError<AuthError>(
|
|
195
208
|
{
|
|
196
209
|
statusCode: 400,
|
|
197
|
-
message:
|
|
198
|
-
error:
|
|
210
|
+
message: "The refresh token was not found. It may have expired.",
|
|
211
|
+
error: "invalid_grant",
|
|
199
212
|
error_description:
|
|
200
|
-
|
|
213
|
+
"The refresh token was not found. It may have expired.",
|
|
201
214
|
},
|
|
202
|
-
400
|
|
203
|
-
)
|
|
204
|
-
)
|
|
215
|
+
400,
|
|
216
|
+
),
|
|
217
|
+
);
|
|
205
218
|
}
|
|
206
|
-
return response.status(200).send(token)
|
|
219
|
+
return response.status(200).send(token);
|
|
207
220
|
} else {
|
|
208
221
|
return next(
|
|
209
222
|
new CommercetoolsError<UnsupportedGrantType>(
|
|
210
223
|
{
|
|
211
|
-
code:
|
|
224
|
+
code: "unsupported_grant_type",
|
|
212
225
|
message: `Invalid parameter: grant_type: Invalid grant type: ${grantType}`,
|
|
213
226
|
},
|
|
214
|
-
400
|
|
215
|
-
)
|
|
216
|
-
)
|
|
227
|
+
400,
|
|
228
|
+
),
|
|
229
|
+
);
|
|
217
230
|
}
|
|
218
231
|
}
|
|
232
|
+
|
|
219
233
|
async customerTokenHandler(
|
|
220
234
|
request: AuthRequest,
|
|
221
235
|
response: Response,
|
|
222
|
-
next: NextFunction
|
|
236
|
+
next: NextFunction,
|
|
223
237
|
) {
|
|
224
|
-
const
|
|
238
|
+
const projectKey = request.params.projectKey;
|
|
239
|
+
const grantType = request.query.grant_type || request.body.grant_type;
|
|
225
240
|
if (!grantType) {
|
|
226
241
|
return next(
|
|
227
242
|
new CommercetoolsError<InvalidRequestError>(
|
|
228
243
|
{
|
|
229
|
-
code:
|
|
230
|
-
message:
|
|
244
|
+
code: "invalid_request",
|
|
245
|
+
message: "Missing required parameter: grant_type.",
|
|
231
246
|
},
|
|
232
|
-
400
|
|
233
|
-
)
|
|
234
|
-
)
|
|
247
|
+
400,
|
|
248
|
+
),
|
|
249
|
+
);
|
|
235
250
|
}
|
|
236
251
|
|
|
237
|
-
if (grantType ===
|
|
238
|
-
const username = request.query.username || request.body.username
|
|
252
|
+
if (grantType === "password") {
|
|
253
|
+
const username = request.query.username || request.body.username;
|
|
239
254
|
const password = hashPassword(
|
|
240
|
-
request.query.password || request.body.password
|
|
241
|
-
)
|
|
255
|
+
request.query.password || request.body.password,
|
|
256
|
+
);
|
|
242
257
|
const scope =
|
|
243
|
-
request.query.scope?.toString() || request.body.scope?.toString()
|
|
258
|
+
request.query.scope?.toString() || request.body.scope?.toString();
|
|
244
259
|
|
|
245
260
|
const result = this.customerRepository.query(
|
|
246
261
|
{ projectKey: request.params.projectKey },
|
|
247
262
|
{
|
|
248
263
|
where: [`email = "${username}"`, `password = "${password}"`],
|
|
249
|
-
}
|
|
250
|
-
)
|
|
264
|
+
},
|
|
265
|
+
);
|
|
251
266
|
|
|
252
267
|
if (result.count === 0) {
|
|
253
268
|
return next(
|
|
254
269
|
new CommercetoolsError<any>(
|
|
255
270
|
{
|
|
256
|
-
code:
|
|
257
|
-
message:
|
|
271
|
+
code: "invalid_customer_account_credentials",
|
|
272
|
+
message: "Customer account with the given credentials not found.",
|
|
258
273
|
},
|
|
259
|
-
400
|
|
260
|
-
)
|
|
261
|
-
)
|
|
274
|
+
400,
|
|
275
|
+
),
|
|
276
|
+
);
|
|
262
277
|
}
|
|
263
278
|
|
|
264
|
-
const customer = result.results[0]
|
|
265
|
-
const token = this.store.getCustomerToken(
|
|
266
|
-
return response.status(200).send(token)
|
|
279
|
+
const customer = result.results[0];
|
|
280
|
+
const token = this.store.getCustomerToken(projectKey, customer.id, scope);
|
|
281
|
+
return response.status(200).send(token);
|
|
267
282
|
}
|
|
268
283
|
}
|
|
269
284
|
|
|
270
285
|
async inStoreCustomerTokenHandler(
|
|
271
286
|
request: Request,
|
|
272
287
|
response: Response,
|
|
273
|
-
next: NextFunction
|
|
288
|
+
next: NextFunction,
|
|
274
289
|
) {
|
|
275
290
|
return next(
|
|
276
291
|
new CommercetoolsError<InvalidClientError>(
|
|
277
292
|
{
|
|
278
|
-
code:
|
|
279
|
-
message:
|
|
293
|
+
code: "invalid_client",
|
|
294
|
+
message: "Not implemented yet in commercetools-mock",
|
|
280
295
|
},
|
|
281
|
-
401
|
|
282
|
-
)
|
|
283
|
-
)
|
|
296
|
+
401,
|
|
297
|
+
),
|
|
298
|
+
);
|
|
284
299
|
}
|
|
285
300
|
|
|
286
301
|
async anonymousTokenHandler(
|
|
287
302
|
request: Request,
|
|
288
303
|
response: Response,
|
|
289
|
-
next: NextFunction
|
|
304
|
+
next: NextFunction,
|
|
290
305
|
) {
|
|
291
|
-
const
|
|
306
|
+
const projectKey = request.params.projectKey;
|
|
307
|
+
const grantType = request.query.grant_type || request.body.grant_type;
|
|
292
308
|
if (!grantType) {
|
|
293
309
|
return next(
|
|
294
310
|
new CommercetoolsError<InvalidRequestError>(
|
|
295
311
|
{
|
|
296
|
-
code:
|
|
297
|
-
message:
|
|
312
|
+
code: "invalid_request",
|
|
313
|
+
message: "Missing required parameter: grant_type.",
|
|
298
314
|
},
|
|
299
|
-
400
|
|
300
|
-
)
|
|
301
|
-
)
|
|
315
|
+
400,
|
|
316
|
+
),
|
|
317
|
+
);
|
|
302
318
|
}
|
|
303
319
|
|
|
304
|
-
if (grantType ===
|
|
320
|
+
if (grantType === "client_credentials") {
|
|
305
321
|
const scope =
|
|
306
|
-
request.query.scope?.toString() || request.body.scope?.toString()
|
|
322
|
+
request.query.scope?.toString() || request.body.scope?.toString();
|
|
307
323
|
|
|
308
|
-
const anonymous_id = undefined
|
|
324
|
+
const anonymous_id = undefined;
|
|
309
325
|
|
|
310
|
-
const token = this.store.getAnonymousToken(
|
|
311
|
-
|
|
326
|
+
const token = this.store.getAnonymousToken(
|
|
327
|
+
projectKey,
|
|
328
|
+
anonymous_id,
|
|
329
|
+
scope,
|
|
330
|
+
);
|
|
331
|
+
return response.status(200).send(token);
|
|
312
332
|
}
|
|
313
333
|
}
|
|
314
334
|
}
|