@toa.io/extensions.exposition 1.0.0-alpha.13 → 1.0.0-alpha.14
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/components/identity.bans/manifest.toa.yaml +13 -5
- package/components/identity.bans/operations/transit.d.ts +14 -0
- package/components/identity.bans/operations/transit.js +11 -0
- package/components/identity.bans/operations/transit.js.map +1 -0
- package/components/identity.bans/operations/tsconfig.tsbuildinfo +1 -0
- package/components/identity.bans/source/transit.ts +21 -0
- package/components/identity.bans/tsconfig.json +9 -0
- package/components/identity.roles/manifest.toa.yaml +4 -4
- package/components/identity.roles/operations/grant.d.ts +1 -1
- package/components/identity.roles/operations/grant.js +6 -5
- package/components/identity.roles/operations/grant.js.map +1 -1
- package/components/identity.roles/operations/lib/Entity.d.ts +1 -1
- package/components/identity.roles/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/source/grant.ts +7 -6
- package/components/identity.roles/source/lib/Entity.ts +1 -1
- package/components/identity.tokens/manifest.toa.yaml +1 -0
- package/components/identity.tokens/operations/authenticate.js +5 -2
- package/components/identity.tokens/operations/authenticate.js.map +1 -1
- package/components/identity.tokens/operations/encrypt.js +4 -1
- package/components/identity.tokens/operations/encrypt.js.map +1 -1
- package/components/identity.tokens/operations/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/operations/types.d.ts +1 -2
- package/components/identity.tokens/receivers/identity.bans.created.js +3 -0
- package/components/identity.tokens/source/authenticate.ts +5 -2
- package/components/identity.tokens/source/encrypt.ts +4 -1
- package/components/identity.tokens/source/types.ts +1 -2
- package/documentation/access.md +13 -3
- package/documentation/components.md +17 -3
- package/features/access.feature +16 -48
- package/features/errors.feature +3 -1
- package/features/identity.bans.feature +128 -0
- package/features/identity.basic.feature +4 -7
- package/features/identity.federation.feature +1 -0
- package/features/identity.roles.feature +54 -1
- package/features/identity.tokens.feature +1 -0
- package/features/io.feature +29 -0
- package/features/steps/Database.ts +16 -10
- package/features/steps/IdP.ts +28 -23
- package/features/steps/components/echo/manifest.toa.yaml +5 -1
- package/features/steps/components/echo/operations/identity.js +7 -0
- package/features/steps/components/users/manifest.toa.yaml +0 -1
- package/package.json +11 -9
- package/source/Directive.ts +3 -1
- package/source/Gateway.ts +1 -1
- package/source/HTTP/exceptions.ts +1 -1
- package/source/RTD/factory.ts +1 -1
- package/source/Tenant.ts +0 -8
- package/source/directives/auth/Authorization.ts +1 -1
- package/source/directives/auth/Delegate.ts +4 -1
- package/source/directives/auth/Role.test.ts +53 -6
- package/source/directives/auth/Role.ts +23 -5
- package/source/directives/auth/types.ts +1 -1
- package/source/directives/cache/Cache.ts +1 -1
- package/source/directives/dev/Development.ts +1 -1
- package/source/directives/octets/Octets.ts +1 -1
- package/source/directives/vary/Vary.ts +1 -1
- package/source/exceptions.ts +13 -6
- package/transpiled/Directive.js +3 -1
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Gateway.js +1 -1
- package/transpiled/Gateway.js.map +1 -1
- package/transpiled/HTTP/exceptions.d.ts +1 -1
- package/transpiled/HTTP/exceptions.js.map +1 -1
- package/transpiled/RTD/factory.js +1 -1
- package/transpiled/RTD/factory.js.map +1 -1
- package/transpiled/Tenant.d.ts +0 -1
- package/transpiled/Tenant.js +0 -6
- package/transpiled/Tenant.js.map +1 -1
- package/transpiled/directives/auth/Authorization.js +1 -1
- package/transpiled/directives/auth/Authorization.js.map +1 -1
- package/transpiled/directives/auth/Delegate.js +3 -1
- package/transpiled/directives/auth/Delegate.js.map +1 -1
- package/transpiled/directives/auth/Role.d.ts +4 -1
- package/transpiled/directives/auth/Role.js +19 -5
- package/transpiled/directives/auth/Role.js.map +1 -1
- package/transpiled/directives/cache/Cache.js +1 -1
- package/transpiled/directives/cache/Cache.js.map +1 -1
- package/transpiled/directives/dev/Development.js +1 -1
- package/transpiled/directives/dev/Development.js.map +1 -1
- package/transpiled/directives/octets/Octets.js +1 -1
- package/transpiled/directives/octets/Octets.js.map +1 -1
- package/transpiled/directives/vary/Vary.js +1 -1
- package/transpiled/directives/vary/Vary.js.map +1 -1
- package/transpiled/exceptions.d.ts +3 -2
- package/transpiled/exceptions.js +7 -1
- package/transpiled/exceptions.js.map +1 -1
- package/transpiled/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
@security
|
|
2
|
+
Feature: Bans
|
|
3
|
+
|
|
4
|
+
Background:
|
|
5
|
+
Given the `identity.basic` database contains:
|
|
6
|
+
# developer:secret
|
|
7
|
+
# user:12345
|
|
8
|
+
| _id | username | password | _deleted |
|
|
9
|
+
| efe3a65ebbee47ed95a73edd911ea328 | developer | $2b$10$ZRSKkgZoGnrcTNA5w5eCcu3pxDzdTduhteVYXcp56AaNcilNkwJ.O | null |
|
|
10
|
+
| e8e4f9c2a68d419b861403d71fabc915 | user | $2b$10$Frszmrmsz9iwSXzBbRRMKeDVKsNxozkrLNSsN.SnVC.KPxLtQr/bK | null |
|
|
11
|
+
And the `identity.bans` database is empty
|
|
12
|
+
|
|
13
|
+
Scenario: Banning an Identity
|
|
14
|
+
Given the `identity.roles` database contains:
|
|
15
|
+
| _id | identity | role |
|
|
16
|
+
| 775a648d054e4ce1a65f8f17e5b51803 | efe3a65ebbee47ed95a73edd911ea328 | system:identity:bans |
|
|
17
|
+
And the annotation:
|
|
18
|
+
"""yaml
|
|
19
|
+
/:
|
|
20
|
+
/:id:
|
|
21
|
+
io:output: true
|
|
22
|
+
auth:id: id
|
|
23
|
+
GET:
|
|
24
|
+
dev:stub:
|
|
25
|
+
access: granted!
|
|
26
|
+
"""
|
|
27
|
+
And the `identity.tokens` configuration:
|
|
28
|
+
"""yaml
|
|
29
|
+
refresh: 1
|
|
30
|
+
"""
|
|
31
|
+
When the following request is received:
|
|
32
|
+
"""
|
|
33
|
+
GET /e8e4f9c2a68d419b861403d71fabc915/ HTTP/1.1
|
|
34
|
+
authorization: Basic dXNlcjoxMjM0NQ==
|
|
35
|
+
"""
|
|
36
|
+
Then the following reply is sent:
|
|
37
|
+
"""
|
|
38
|
+
200 OK
|
|
39
|
+
authorization: Token ${{ token }}
|
|
40
|
+
"""
|
|
41
|
+
When the following request is received:
|
|
42
|
+
"""
|
|
43
|
+
PUT /identity/bans/e8e4f9c2a68d419b861403d71fabc915/ HTTP/1.1
|
|
44
|
+
authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
|
|
45
|
+
content-type: application/yaml
|
|
46
|
+
|
|
47
|
+
banned: true
|
|
48
|
+
comment: Bye bye
|
|
49
|
+
"""
|
|
50
|
+
Then the following reply is sent:
|
|
51
|
+
"""
|
|
52
|
+
200 OK
|
|
53
|
+
"""
|
|
54
|
+
# accessing a resource with a banned Identity
|
|
55
|
+
When the following request is received:
|
|
56
|
+
"""
|
|
57
|
+
GET /e8e4f9c2a68d419b861403d71fabc915/ HTTP/1.1
|
|
58
|
+
authorization: Basic dXNlcjoxMjM0NQ==
|
|
59
|
+
"""
|
|
60
|
+
Then the following reply is sent:
|
|
61
|
+
"""
|
|
62
|
+
401 Unauthorized
|
|
63
|
+
"""
|
|
64
|
+
Then after 1 second
|
|
65
|
+
When the following request is received:
|
|
66
|
+
"""
|
|
67
|
+
GET /e8e4f9c2a68d419b861403d71fabc915/ HTTP/1.1
|
|
68
|
+
authorization: Token ${{ token }}
|
|
69
|
+
"""
|
|
70
|
+
Then the following reply is sent:
|
|
71
|
+
"""
|
|
72
|
+
401 Unauthorized
|
|
73
|
+
"""
|
|
74
|
+
When the following request is received:
|
|
75
|
+
"""
|
|
76
|
+
PUT /identity/bans/e8e4f9c2a68d419b861403d71fabc915/ HTTP/1.1
|
|
77
|
+
authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
|
|
78
|
+
content-type: application/yaml
|
|
79
|
+
|
|
80
|
+
banned: false
|
|
81
|
+
"""
|
|
82
|
+
Then the following reply is sent:
|
|
83
|
+
"""
|
|
84
|
+
200 OK
|
|
85
|
+
"""
|
|
86
|
+
When the following request is received:
|
|
87
|
+
"""
|
|
88
|
+
GET /e8e4f9c2a68d419b861403d71fabc915/ HTTP/1.1
|
|
89
|
+
authorization: Basic dXNlcjoxMjM0NQ==
|
|
90
|
+
"""
|
|
91
|
+
Then the following reply is sent:
|
|
92
|
+
"""
|
|
93
|
+
200 OK
|
|
94
|
+
|
|
95
|
+
authorization: Token ${{ new_token }}
|
|
96
|
+
"""
|
|
97
|
+
# re-ban
|
|
98
|
+
When the following request is received:
|
|
99
|
+
"""
|
|
100
|
+
PUT /identity/bans/e8e4f9c2a68d419b861403d71fabc915/ HTTP/1.1
|
|
101
|
+
authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
|
|
102
|
+
content-type: application/yaml
|
|
103
|
+
|
|
104
|
+
banned: true
|
|
105
|
+
"""
|
|
106
|
+
Then the following reply is sent:
|
|
107
|
+
"""
|
|
108
|
+
200 OK
|
|
109
|
+
"""
|
|
110
|
+
When the following request is received:
|
|
111
|
+
"""
|
|
112
|
+
GET /e8e4f9c2a68d419b861403d71fabc915/ HTTP/1.1
|
|
113
|
+
authorization: Basic dXNlcjoxMjM0NQ==
|
|
114
|
+
"""
|
|
115
|
+
Then the following reply is sent:
|
|
116
|
+
"""
|
|
117
|
+
401 Unauthorized
|
|
118
|
+
"""
|
|
119
|
+
Then after 1 second
|
|
120
|
+
When the following request is received:
|
|
121
|
+
"""
|
|
122
|
+
GET /e8e4f9c2a68d419b861403d71fabc915/ HTTP/1.1
|
|
123
|
+
authorization: Token ${{ new_token }}
|
|
124
|
+
"""
|
|
125
|
+
Then the following reply is sent:
|
|
126
|
+
"""
|
|
127
|
+
401 Unauthorized
|
|
128
|
+
"""
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
@security
|
|
1
2
|
Feature: Basic authentication
|
|
2
3
|
|
|
3
4
|
Background:
|
|
@@ -28,8 +29,6 @@ Feature: Basic authentication
|
|
|
28
29
|
Then the following reply is sent:
|
|
29
30
|
"""
|
|
30
31
|
409 Conflict
|
|
31
|
-
|
|
32
|
-
- username
|
|
33
32
|
"""
|
|
34
33
|
|
|
35
34
|
Scenario: Creating new Identity using inception
|
|
@@ -43,9 +42,9 @@ Feature: Basic authentication
|
|
|
43
42
|
incept: id
|
|
44
43
|
endpoint: transit
|
|
45
44
|
query: ~
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
/:id: # credential testing route
|
|
46
|
+
id: id
|
|
47
|
+
GET: observe
|
|
49
48
|
"""
|
|
50
49
|
When the following request is received:
|
|
51
50
|
"""
|
|
@@ -96,8 +95,6 @@ Feature: Basic authentication
|
|
|
96
95
|
Then the following reply is sent:
|
|
97
96
|
"""
|
|
98
97
|
409 Conflict
|
|
99
|
-
|
|
100
|
-
- username
|
|
101
98
|
"""
|
|
102
99
|
# credentials already exists
|
|
103
100
|
When the following request is received:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
@security
|
|
1
2
|
Feature: Roles management
|
|
2
3
|
|
|
3
|
-
Scenario:
|
|
4
|
+
Scenario: Granting a role to an Identity
|
|
4
5
|
# root:secret
|
|
5
6
|
# user:pass
|
|
6
7
|
Given the `identity.basic` database contains:
|
|
@@ -34,6 +35,7 @@ Feature: Roles management
|
|
|
34
35
|
"""
|
|
35
36
|
POST /identity/roles/4344518184ad44228baffce7a44fd0b1/ HTTP/1.1
|
|
36
37
|
authorization: Basic cm9vdDpzZWNyZXQ=
|
|
38
|
+
accept: application/yaml
|
|
37
39
|
content-type: application/yaml
|
|
38
40
|
|
|
39
41
|
role: test
|
|
@@ -41,6 +43,8 @@ Feature: Roles management
|
|
|
41
43
|
Then the following reply is sent:
|
|
42
44
|
"""
|
|
43
45
|
201 Created
|
|
46
|
+
|
|
47
|
+
grantor: 72cf9b0ab0ac4ab2b8036e4e940ddcae
|
|
44
48
|
"""
|
|
45
49
|
When the following request is received:
|
|
46
50
|
# user now have the role
|
|
@@ -200,3 +204,52 @@ Feature: Roles management
|
|
|
200
204
|
| app! |
|
|
201
205
|
| app: |
|
|
202
206
|
| app:no spaces |
|
|
207
|
+
|
|
208
|
+
Scenario: Dynamic roles
|
|
209
|
+
Given the `identity.basic` database contains:
|
|
210
|
+
| _id | username | password |
|
|
211
|
+
| 72cf9b0ab0ac4ab2b8036e4e940ddcae | moderator | $2b$10$Qq/qnyyU5wjrbDXyWok14OnqAZv/z.pLhz.UddatjI6eHU/rFof4i |
|
|
212
|
+
And the `identity.roles` database contains:
|
|
213
|
+
| _id | identity | role |
|
|
214
|
+
| 30c969e05ff6437097ed5f07fc52358e | 72cf9b0ab0ac4ab2b8036e4e940ddcae | app:29e54ae1:moderation |
|
|
215
|
+
And the annotation:
|
|
216
|
+
"""yaml
|
|
217
|
+
/:
|
|
218
|
+
/broken:
|
|
219
|
+
auth:role: app:{org}:moderation
|
|
220
|
+
GET:
|
|
221
|
+
dev:stub: never
|
|
222
|
+
/:org:
|
|
223
|
+
io:output: true
|
|
224
|
+
auth:role: app:{org}:moderation
|
|
225
|
+
GET:
|
|
226
|
+
dev:stub:
|
|
227
|
+
access: granted!
|
|
228
|
+
"""
|
|
229
|
+
When the following request is received:
|
|
230
|
+
"""
|
|
231
|
+
GET /29e54ae1/ HTTP/1.1
|
|
232
|
+
authorization: Basic bW9kZXJhdG9yOnNlY3JldA==
|
|
233
|
+
"""
|
|
234
|
+
Then the following reply is sent:
|
|
235
|
+
"""
|
|
236
|
+
200 OK
|
|
237
|
+
"""
|
|
238
|
+
When the following request is received:
|
|
239
|
+
"""
|
|
240
|
+
GET /88584c9b/ HTTP/1.1
|
|
241
|
+
authorization: Basic bW9kZXJhdG9yOnNlY3JldA==
|
|
242
|
+
"""
|
|
243
|
+
Then the following reply is sent:
|
|
244
|
+
"""
|
|
245
|
+
403 Forbidden
|
|
246
|
+
"""
|
|
247
|
+
When the following request is received:
|
|
248
|
+
"""
|
|
249
|
+
GET /broken/ HTTP/1.1
|
|
250
|
+
authorization: Basic bW9kZXJhdG9yOnNlY3JldA==
|
|
251
|
+
"""
|
|
252
|
+
Then the following reply is sent:
|
|
253
|
+
"""
|
|
254
|
+
500 Internal Server Error
|
|
255
|
+
"""
|
package/features/io.feature
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
@security
|
|
1
2
|
Feature: IO restrictions
|
|
2
3
|
|
|
3
4
|
Background:
|
|
@@ -135,6 +136,7 @@ Feature: IO restrictions
|
|
|
135
136
|
exposition:
|
|
136
137
|
/:
|
|
137
138
|
io:input: [title, volume]
|
|
139
|
+
io:output: [id]
|
|
138
140
|
POST: create
|
|
139
141
|
"""
|
|
140
142
|
When the following request is received:
|
|
@@ -165,3 +167,30 @@ Feature: IO restrictions
|
|
|
165
167
|
"""
|
|
166
168
|
201 Created
|
|
167
169
|
"""
|
|
170
|
+
|
|
171
|
+
Scenario: IO shortcuts
|
|
172
|
+
Given the `pots` is running with the following manifest:
|
|
173
|
+
"""yaml
|
|
174
|
+
exposition:
|
|
175
|
+
/:
|
|
176
|
+
input: [title, volume]
|
|
177
|
+
output: [id, title, volume]
|
|
178
|
+
POST: create
|
|
179
|
+
"""
|
|
180
|
+
When the following request is received:
|
|
181
|
+
"""
|
|
182
|
+
POST /pots/ HTTP/1.1
|
|
183
|
+
accept: application/yaml
|
|
184
|
+
content-type: application/yaml
|
|
185
|
+
|
|
186
|
+
title: Hello
|
|
187
|
+
volume: 1.5
|
|
188
|
+
"""
|
|
189
|
+
Then the following reply is sent:
|
|
190
|
+
"""
|
|
191
|
+
201 Created
|
|
192
|
+
|
|
193
|
+
id:
|
|
194
|
+
title: Hello
|
|
195
|
+
volume: 1.5
|
|
196
|
+
"""
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { afterAll, beforeAll, binding, given } from 'cucumber-tsflow'
|
|
2
2
|
import { MongoClient } from 'mongodb'
|
|
3
|
+
import type { Collection } from 'mongodb'
|
|
3
4
|
import type { DataTable } from '@cucumber/cucumber'
|
|
4
5
|
|
|
5
6
|
@binding()
|
|
@@ -8,10 +9,7 @@ export class Database {
|
|
|
8
9
|
|
|
9
10
|
@given('the `{word}` database contains:')
|
|
10
11
|
public async upsert (id: string, table: DataTable): Promise<void> {
|
|
11
|
-
const
|
|
12
|
-
const col = `${namespace}_${name}`.toLowerCase()
|
|
13
|
-
const collection = Database.client.db('toa-dev').collection(col)
|
|
14
|
-
|
|
12
|
+
const collection = this.collection(id)
|
|
15
13
|
const columns = table.raw()[0]
|
|
16
14
|
const rows = table.rows()
|
|
17
15
|
const documents: Document[] = []
|
|
@@ -23,7 +21,11 @@ export class Database {
|
|
|
23
21
|
const str = rows[r][c]
|
|
24
22
|
const int = parseInt(str)
|
|
25
23
|
|
|
26
|
-
document[columns[c]] = int.toString() === str
|
|
24
|
+
document[columns[c]] = int.toString() === str
|
|
25
|
+
? int
|
|
26
|
+
: str === 'null'
|
|
27
|
+
? null
|
|
28
|
+
: str
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
documents.push(document)
|
|
@@ -37,10 +39,7 @@ export class Database {
|
|
|
37
39
|
|
|
38
40
|
@given('the `{word}` database is empty')
|
|
39
41
|
public async truncate (id: string): Promise<void> {
|
|
40
|
-
|
|
41
|
-
const collection = Database.client.db(namespace).collection(name)
|
|
42
|
-
|
|
43
|
-
await collection.deleteMany({})
|
|
42
|
+
await this.collection(id).deleteMany({})
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
@beforeAll()
|
|
@@ -54,6 +53,13 @@ export class Database {
|
|
|
54
53
|
public static async disconnect (): Promise<void> {
|
|
55
54
|
await this.client.close()
|
|
56
55
|
}
|
|
56
|
+
|
|
57
|
+
private collection (id: string): Collection {
|
|
58
|
+
const [name, namespace = 'default'] = id.split('.').reverse()
|
|
59
|
+
const collection = `${namespace}_${name}`.toLowerCase()
|
|
60
|
+
|
|
61
|
+
return Database.client.db('toa-dev').collection(collection)
|
|
62
|
+
}
|
|
57
63
|
}
|
|
58
64
|
|
|
59
|
-
type Document = Record<string, string | number>
|
|
65
|
+
type Document = Record<string, string | number | null>
|
package/features/steps/IdP.ts
CHANGED
|
@@ -14,7 +14,8 @@ export class IdP {
|
|
|
14
14
|
private static privateKey?: crypto.KeyObject
|
|
15
15
|
private static issuer?: string
|
|
16
16
|
|
|
17
|
-
public constructor (private readonly captures: Captures) {
|
|
17
|
+
public constructor (private readonly captures: Captures) {
|
|
18
|
+
}
|
|
18
19
|
|
|
19
20
|
@afterAll()
|
|
20
21
|
public static async stop (): Promise<void> {
|
|
@@ -29,14 +30,21 @@ export class IdP {
|
|
|
29
30
|
if (IdP.server instanceof http.Server) return
|
|
30
31
|
|
|
31
32
|
// creating the key
|
|
32
|
-
const {
|
|
33
|
+
const {
|
|
34
|
+
publicKey,
|
|
35
|
+
privateKey
|
|
36
|
+
} = await util.promisify(crypto.generateKeyPair)('rsa', {
|
|
33
37
|
modulusLength: 2048
|
|
34
38
|
})
|
|
35
39
|
|
|
36
40
|
IdP.privateKey = privateKey
|
|
37
41
|
|
|
38
42
|
const jwk = JSON.stringify({
|
|
39
|
-
keys: [{
|
|
43
|
+
keys: [{
|
|
44
|
+
use: 'sig',
|
|
45
|
+
alg: 'RS256',
|
|
46
|
+
...publicKey.export({ format: 'jwk' })
|
|
47
|
+
}]
|
|
40
48
|
})
|
|
41
49
|
|
|
42
50
|
const JWK_URL = '/.well-known/jwks'
|
|
@@ -54,24 +62,23 @@ export class IdP {
|
|
|
54
62
|
response.end(jwk)
|
|
55
63
|
break
|
|
56
64
|
|
|
57
|
-
case '/.well-known/openid-configuration':
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
65
|
+
case '/.well-known/openid-configuration': {
|
|
66
|
+
const openIdConfiguration = JSON.stringify({
|
|
67
|
+
issuer: IdP.issuer,
|
|
68
|
+
jwks_uri: IdP.issuer + JWK_URL,
|
|
69
|
+
response_types_supported: ['id_token'],
|
|
70
|
+
subject_types_supported: ['public'],
|
|
71
|
+
id_token_signing_alg_values_supported: ['RS256'],
|
|
72
|
+
scopes_supported: ['openid']
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
response.writeHead(200, {
|
|
76
|
+
'Content-Type': 'application/json',
|
|
77
|
+
'Cache-Control': 'public, max-age=3600',
|
|
78
|
+
'Content-Length': openIdConfiguration.length
|
|
79
|
+
})
|
|
80
|
+
response.end(openIdConfiguration)
|
|
81
|
+
}
|
|
75
82
|
|
|
76
83
|
break
|
|
77
84
|
|
|
@@ -120,8 +127,6 @@ export class IdP {
|
|
|
120
127
|
|
|
121
128
|
@given('the IDP {word} token for {word} is issued with following secret:')
|
|
122
129
|
public async issueSymmetricToken (alg: string, user: string, secret: string): Promise<void> {
|
|
123
|
-
console.log('Sym token for %s with secret "%s"', user, secret)
|
|
124
|
-
|
|
125
130
|
const jwt = [
|
|
126
131
|
{
|
|
127
132
|
typ: 'JWT',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/extensions.exposition",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.14",
|
|
4
4
|
"description": "Toa Exposition",
|
|
5
5
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
6
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@toa.io/core": "1.0.0-alpha.
|
|
21
|
-
"@toa.io/generic": "1.0.0-alpha.
|
|
22
|
-
"@toa.io/schemas": "1.0.0-alpha.
|
|
20
|
+
"@toa.io/core": "1.0.0-alpha.14",
|
|
21
|
+
"@toa.io/generic": "1.0.0-alpha.14",
|
|
22
|
+
"@toa.io/schemas": "1.0.0-alpha.14",
|
|
23
23
|
"bcryptjs": "2.4.3",
|
|
24
24
|
"error-value": "0.3.0",
|
|
25
25
|
"js-yaml": "4.1.0",
|
|
@@ -34,20 +34,22 @@
|
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
36
36
|
"test": "jest",
|
|
37
|
-
"transpile": "tsc && npm run transpile:basic && npm run transpile:tokens && npm run transpile:roles && npm run transpile:federation",
|
|
37
|
+
"transpile": "tsc && npm run transpile:bans && npm run transpile:basic && npm run transpile:tokens && npm run transpile:roles && npm run transpile:federation",
|
|
38
|
+
"transpile:bans": "tsc -p ./components/identity.bans",
|
|
38
39
|
"transpile:basic": "tsc -p ./components/identity.basic",
|
|
39
40
|
"transpile:tokens": "tsc -p ./components/identity.tokens",
|
|
40
41
|
"transpile:roles": "tsc -p ./components/identity.roles",
|
|
41
42
|
"pretranspile:federation": "js-yaml components/identity.federation/manifest.toa.yaml | jq -M '{ type: \"object\", properties: {configuration: .configuration.schema, entity: .entity.schema }, additionalProperties: false}' > schemas.json && json2ts -i schemas.json -o components/identity.federation/source/schemas.ts && rm schemas.json",
|
|
42
43
|
"transpile:federation": "tsc -p ./components/identity.federation",
|
|
43
|
-
"features": "cucumber-js"
|
|
44
|
+
"features": "cucumber-js",
|
|
45
|
+
"features:security": "cucumber-js --tags @security"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
|
-
"@toa.io/agent": "1.0.0-alpha.
|
|
47
|
-
"@toa.io/extensions.storages": "1.0.0-alpha.
|
|
48
|
+
"@toa.io/agent": "1.0.0-alpha.14",
|
|
49
|
+
"@toa.io/extensions.storages": "1.0.0-alpha.14",
|
|
48
50
|
"@types/bcryptjs": "2.4.3",
|
|
49
51
|
"@types/cors": "2.8.13",
|
|
50
52
|
"@types/negotiator": "0.6.1"
|
|
51
53
|
},
|
|
52
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "8aa52cb97021695885c8dbe64beca26c9665fc8f"
|
|
53
55
|
}
|
package/source/Directive.ts
CHANGED
package/source/Gateway.ts
CHANGED
package/source/RTD/factory.ts
CHANGED
|
@@ -33,7 +33,7 @@ function createRoute (route: syntax.Route, context: Context): Route {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function createMethod (method: syntax.Method, context: Context): Method {
|
|
36
|
-
const stack =
|
|
36
|
+
const stack = method.directives.concat(context.directives.stack)
|
|
37
37
|
const directives = context.directives.factory.create(stack)
|
|
38
38
|
|
|
39
39
|
const endpoint = method.mapping?.endpoint === undefined
|
package/source/Tenant.ts
CHANGED
|
@@ -25,14 +25,6 @@ export class Tenant extends Connector {
|
|
|
25
25
|
public override async open (): Promise<void> {
|
|
26
26
|
await this.expose()
|
|
27
27
|
await this.broadcast.receive('ping', this.expose.bind(this))
|
|
28
|
-
|
|
29
|
-
console.info('Exposition Tenant for ' +
|
|
30
|
-
`'${this.branch.namespace}.${this.branch.component}' has started.`)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
public override async dispose (): Promise<void> {
|
|
34
|
-
console.info('Exposition Tenant for ' +
|
|
35
|
-
`'${this.branch.namespace}.${this.branch.component}' has been stopped.`)
|
|
36
28
|
}
|
|
37
29
|
|
|
38
30
|
private async expose (): Promise<void> {
|
|
@@ -39,7 +39,7 @@ export class Authorization implements DirectiveFamily<Directive, Extension> {
|
|
|
39
39
|
|
|
40
40
|
public create (name: string, value: any, remotes: Remotes): Directive {
|
|
41
41
|
assert.ok(name in constructors,
|
|
42
|
-
`Directive '
|
|
42
|
+
`Directive 'auth:${name}' is not implemented.`)
|
|
43
43
|
|
|
44
44
|
const Class = constructors[name]
|
|
45
45
|
|
|
@@ -19,6 +19,9 @@ export class Delegate implements Directive {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
private embed (body: unknown, identity: Identity): Record<string, unknown> {
|
|
22
|
+
if (body === undefined)
|
|
23
|
+
body = {}
|
|
24
|
+
|
|
22
25
|
check(body)
|
|
23
26
|
body[this.property] = identity
|
|
24
27
|
|
|
@@ -28,5 +31,5 @@ export class Delegate implements Directive {
|
|
|
28
31
|
|
|
29
32
|
function check (body: unknown): asserts body is Record<string, unknown> {
|
|
30
33
|
if (typeof body !== 'object' || body === null)
|
|
31
|
-
throw new BadRequest('Invalid request body
|
|
34
|
+
throw new BadRequest('Invalid request body')
|
|
32
35
|
}
|