@labdigital/commercetools-mock 2.17.0 → 2.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@labdigital/commercetools-mock",
3
3
  "author": "Michael van Tellingen",
4
- "version": "2.17.0",
4
+ "version": "2.17.1",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.js",
@@ -2,15 +2,26 @@ import { describe, it, expect, beforeEach } from 'vitest'
2
2
  import express from 'express'
3
3
  import supertest from 'supertest'
4
4
  import { OAuth2Server } from './server'
5
+ import { CustomerRepository } from '../repositories/customer'
6
+ import { AbstractStorage, InMemoryStorage } from '../storage'
7
+ import { getBaseResourceProperties } from '../helpers'
8
+ import { hashPassword } from '../lib/password'
5
9
 
6
10
  describe('OAuth2Server', () => {
7
11
  let app: express.Express
8
12
  let server: OAuth2Server
9
13
 
14
+ let storage: AbstractStorage
15
+ let customerRepository: CustomerRepository
16
+
10
17
  beforeEach(() => {
11
18
  server = new OAuth2Server({ enabled: true, validate: false })
12
19
  app = express()
13
20
  app.use(server.createRouter())
21
+
22
+ storage = new InMemoryStorage()
23
+ customerRepository = new CustomerRepository(storage)
24
+ server.setCustomerRepository(customerRepository)
14
25
  })
15
26
 
16
27
  describe('POST /token', () => {
@@ -74,16 +85,48 @@ describe('OAuth2Server', () => {
74
85
 
75
86
  expect(response.status).toBe(200)
76
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'
77
101
 
78
- const matches = response.body.scope?.match(
79
- /(customer_id|anonymous_id):([^\s]+)/
80
- )
81
- if (matches) {
82
- expect(matches[1]).toBe('anonymous_id')
83
- expect(matches[2]).toBeDefined()
84
- } else {
85
- expect(response.body.scope).toBe('')
86
- }
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
+ })
87
130
  })
88
131
  })
89
132
  })
@@ -221,6 +221,7 @@ export class OAuth2Server {
221
221
  response: Response,
222
222
  next: NextFunction
223
223
  ) {
224
+ const projectKey = request.params.projectKey
224
225
  const grantType = request.query.grant_type || request.body.grant_type
225
226
  if (!grantType) {
226
227
  return next(
@@ -262,7 +263,7 @@ export class OAuth2Server {
262
263
  }
263
264
 
264
265
  const customer = result.results[0]
265
- const token = this.store.getCustomerToken(scope, customer.id)
266
+ const token = this.store.getCustomerToken(projectKey, customer.id, scope)
266
267
  return response.status(200).send(token)
267
268
  }
268
269
  }
@@ -288,6 +289,7 @@ export class OAuth2Server {
288
289
  response: Response,
289
290
  next: NextFunction
290
291
  ) {
292
+ const projectKey = request.params.projectKey
291
293
  const grantType = request.query.grant_type || request.body.grant_type
292
294
  if (!grantType) {
293
295
  return next(
@@ -307,7 +309,11 @@ export class OAuth2Server {
307
309
 
308
310
  const anonymous_id = undefined
309
311
 
310
- const token = this.store.getAnonymousToken(scope, anonymous_id)
312
+ const token = this.store.getAnonymousToken(
313
+ projectKey,
314
+ anonymous_id,
315
+ scope
316
+ )
311
317
  return response.status(200).send(token)
312
318
  }
313
319
  }
@@ -33,7 +33,11 @@ export class OAuth2Store {
33
33
  return token
34
34
  }
35
35
 
36
- getAnonymousToken(scope: string, anonymousId: string | undefined) {
36
+ getAnonymousToken(
37
+ projectKey: string,
38
+ anonymousId: string | undefined,
39
+ scope: string
40
+ ) {
37
41
  if (!anonymousId) {
38
42
  anonymousId = uuidv4()
39
43
  }
@@ -44,13 +48,13 @@ export class OAuth2Store {
44
48
  scope: scope
45
49
  ? `${scope} anonymous_id:${anonymousId}`
46
50
  : `anonymous_id:${anonymousId}`,
47
- refresh_token: `my-project-${randomBytes(16).toString('base64')}`,
51
+ refresh_token: `${projectKey}:${randomBytes(16).toString('base64')}`,
48
52
  }
49
53
  this.addToken(token)
50
54
  return token
51
55
  }
52
56
 
53
- getCustomerToken(scope: string, customerId: string) {
57
+ getCustomerToken(projectKey: string, customerId: string, scope: string) {
54
58
  const token: Token = {
55
59
  access_token: randomBytes(16).toString('base64'),
56
60
  token_type: 'Bearer',
@@ -58,7 +62,7 @@ export class OAuth2Store {
58
62
  scope: scope
59
63
  ? `${scope} customer_id:${customerId}`
60
64
  : `customer_id:${customerId}`,
61
- refresh_token: `my-project-${randomBytes(16).toString('base64')}`,
65
+ refresh_token: `${projectKey}:${randomBytes(16).toString('base64')}`,
62
66
  }
63
67
  this.addToken(token)
64
68
  return token
@@ -1,9 +1,10 @@
1
- import { Router } from 'express'
1
+ import { type Request, type Response, Router } from 'express'
2
2
  import { v4 as uuidv4 } from 'uuid'
3
3
  import { getBaseResourceProperties } from '../helpers.js'
4
4
  import { CustomerRepository } from '../repositories/customer.js'
5
5
  import { getRepositoryContext } from '../repositories/helpers.js'
6
6
  import AbstractService from './abstract.js'
7
+ import { CustomerSignInResult } from '@commercetools/platform-sdk'
7
8
 
8
9
  export class CustomerService extends AbstractService {
9
10
  public repository: CustomerRepository
@@ -17,6 +18,20 @@ export class CustomerService extends AbstractService {
17
18
  return 'customers'
18
19
  }
19
20
 
21
+ post(request: Request, response: Response) {
22
+ const draft = request.body
23
+ const resource = this.repository.create(
24
+ getRepositoryContext(request),
25
+ draft
26
+ )
27
+ const expanded = this._expandWithId(request, resource.id)
28
+
29
+ const result: CustomerSignInResult = {
30
+ customer: expanded,
31
+ }
32
+ return response.status(this.createStatusCode).send(result)
33
+ }
34
+
20
35
  extraRoutes(parent: Router) {
21
36
  parent.post('/password-token', (request, response) => {
22
37
  const customer = this.repository.query(getRepositoryContext(request), {