@toa.io/extensions.exposition 0.20.0-dev.9 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/components/context.toa.yaml +15 -0
  2. package/components/identity.bans/manifest.toa.yaml +18 -0
  3. package/components/identity.basic/events/principal.js +9 -0
  4. package/components/identity.basic/manifest.toa.yaml +50 -0
  5. package/components/identity.basic/source/authenticate.ts +29 -0
  6. package/components/identity.basic/source/create.ts +19 -0
  7. package/components/identity.basic/source/transit.ts +64 -0
  8. package/components/identity.basic/source/types.ts +42 -0
  9. package/components/identity.basic/tsconfig.json +9 -0
  10. package/components/identity.roles/manifest.toa.yaml +31 -0
  11. package/components/identity.roles/source/list.ts +7 -0
  12. package/components/identity.roles/source/principal.ts +20 -0
  13. package/components/identity.roles/tsconfig.json +9 -0
  14. package/components/identity.tokens/manifest.toa.yaml +39 -0
  15. package/components/identity.tokens/receivers/identity.bans.updated.js +3 -0
  16. package/components/identity.tokens/source/authenticate.test.ts +56 -0
  17. package/components/identity.tokens/source/authenticate.ts +38 -0
  18. package/components/identity.tokens/source/decrypt.test.ts +59 -0
  19. package/components/identity.tokens/source/decrypt.ts +25 -0
  20. package/components/identity.tokens/source/encrypt.test.ts +35 -0
  21. package/components/identity.tokens/source/encrypt.ts +25 -0
  22. package/components/identity.tokens/source/revoke.ts +5 -0
  23. package/components/identity.tokens/source/types.ts +48 -0
  24. package/components/identity.tokens/tsconfig.json +9 -0
  25. package/cucumber.js +9 -0
  26. package/documentation/.assets/ia3-dark.jpg +0 -0
  27. package/documentation/.assets/ia3-light.jpg +0 -0
  28. package/documentation/.assets/overview-dark.jpg +0 -0
  29. package/documentation/.assets/overview-light.jpg +0 -0
  30. package/documentation/.assets/role-scopes-dark.jpg +0 -0
  31. package/documentation/.assets/role-scopes-light.jpg +0 -0
  32. package/documentation/.assets/rtd-dark.jpg +0 -0
  33. package/documentation/.assets/rtd-light.jpg +0 -0
  34. package/documentation/access.md +256 -0
  35. package/documentation/components.md +276 -0
  36. package/documentation/identity.md +156 -0
  37. package/documentation/notes/sse.md +71 -0
  38. package/documentation/protocol.md +18 -0
  39. package/documentation/query.md +226 -0
  40. package/documentation/tree.md +169 -0
  41. package/features/access.feature +448 -0
  42. package/features/annotation.feature +30 -0
  43. package/features/body.feature +45 -0
  44. package/features/directives.feature +56 -0
  45. package/features/dynamic.feature +99 -0
  46. package/features/errors.feature +193 -0
  47. package/features/identity.basic.feature +276 -0
  48. package/features/identity.feature +61 -0
  49. package/features/identity.roles.feature +51 -0
  50. package/features/identity.tokens.feature +119 -0
  51. package/features/queries.feature +214 -0
  52. package/features/routes.feature +49 -0
  53. package/features/steps/Common.ts +10 -0
  54. package/features/steps/Components.ts +43 -0
  55. package/features/steps/Database.ts +58 -0
  56. package/features/steps/Gateway.ts +113 -0
  57. package/features/steps/HTTP.ts +71 -0
  58. package/features/steps/Parameters.ts +12 -0
  59. package/features/steps/Workspace.ts +40 -0
  60. package/features/steps/components/echo/manifest.toa.yaml +9 -0
  61. package/features/steps/components/echo/operations/affect.js +7 -0
  62. package/features/steps/components/echo/operations/compute.js +7 -0
  63. package/features/steps/components/greeter/manifest.toa.yaml +5 -0
  64. package/features/steps/components/greeter/operations/greet.js +7 -0
  65. package/features/steps/components/pots/manifest.toa.yaml +20 -0
  66. package/features/steps/components/sequences/manifest.toa.yaml +10 -0
  67. package/features/steps/components/sequences/operations/numbers.js +7 -0
  68. package/features/steps/components/sequences/operations/tokens.js +16 -0
  69. package/features/steps/components/users/manifest.toa.yaml +11 -0
  70. package/features/steps/tsconfig.json +9 -0
  71. package/features/streams.feature +26 -0
  72. package/package.json +32 -17
  73. package/readme.md +183 -0
  74. package/schemas/annotation.cos.yaml +5 -0
  75. package/schemas/directive.cos.yaml +3 -0
  76. package/schemas/method.cos.yaml +8 -0
  77. package/schemas/node.cos.yaml +5 -0
  78. package/schemas/query.cos.yaml +17 -0
  79. package/schemas/querystring.cos.yaml +5 -0
  80. package/schemas/range.cos.yaml +2 -0
  81. package/schemas/route.cos.yaml +2 -0
  82. package/source/Annotation.ts +7 -0
  83. package/source/Branch.ts +8 -0
  84. package/source/Composition.ts +57 -0
  85. package/source/Context.ts +6 -0
  86. package/source/Directive.test.ts +91 -0
  87. package/source/Directive.ts +120 -0
  88. package/source/Endpoint.ts +59 -0
  89. package/source/Factory.ts +51 -0
  90. package/source/Gateway.ts +93 -0
  91. package/source/HTTP/Server.fixtures.ts +45 -0
  92. package/source/HTTP/Server.test.ts +221 -0
  93. package/source/HTTP/Server.ts +135 -0
  94. package/source/HTTP/exceptions.ts +77 -0
  95. package/source/HTTP/formats/index.ts +19 -0
  96. package/source/HTTP/formats/json.ts +13 -0
  97. package/source/HTTP/formats/msgpack.ts +10 -0
  98. package/source/HTTP/formats/text.ts +9 -0
  99. package/source/HTTP/formats/yaml.ts +14 -0
  100. package/source/HTTP/index.ts +3 -0
  101. package/source/HTTP/messages.test.ts +116 -0
  102. package/source/HTTP/messages.ts +89 -0
  103. package/source/Mapping.ts +51 -0
  104. package/source/Query.test.ts +37 -0
  105. package/source/Query.ts +105 -0
  106. package/source/RTD/Context.ts +16 -0
  107. package/source/RTD/Directives.ts +9 -0
  108. package/source/RTD/Endpoint.ts +11 -0
  109. package/source/RTD/Match.ts +16 -0
  110. package/source/RTD/Method.ts +24 -0
  111. package/source/RTD/Node.ts +85 -0
  112. package/source/RTD/Route.ts +59 -0
  113. package/source/RTD/Tree.ts +54 -0
  114. package/source/RTD/factory.ts +47 -0
  115. package/source/RTD/index.ts +8 -0
  116. package/source/RTD/segment.test.ts +32 -0
  117. package/source/RTD/segment.ts +25 -0
  118. package/source/RTD/syntax/index.ts +2 -0
  119. package/source/RTD/syntax/parse.test.ts +188 -0
  120. package/source/RTD/syntax/parse.ts +153 -0
  121. package/source/RTD/syntax/types.ts +48 -0
  122. package/source/Remotes.test.ts +42 -0
  123. package/source/Remotes.ts +22 -0
  124. package/source/Tenant.ts +38 -0
  125. package/source/deployment.ts +49 -0
  126. package/source/directives/auth/Anonymous.ts +14 -0
  127. package/source/directives/auth/Echo.ts +12 -0
  128. package/source/directives/auth/Family.ts +145 -0
  129. package/source/directives/auth/Id.ts +19 -0
  130. package/source/directives/auth/Incept.ts +42 -0
  131. package/source/directives/auth/Role.test.ts +62 -0
  132. package/source/directives/auth/Role.ts +56 -0
  133. package/source/directives/auth/Rule.ts +28 -0
  134. package/source/directives/auth/Scheme.ts +26 -0
  135. package/source/directives/auth/index.ts +3 -0
  136. package/source/directives/auth/schemes.ts +8 -0
  137. package/source/directives/auth/split.ts +15 -0
  138. package/source/directives/auth/types.ts +37 -0
  139. package/source/directives/dev/Family.ts +36 -0
  140. package/source/directives/dev/Stub.ts +14 -0
  141. package/source/directives/dev/Throw.ts +14 -0
  142. package/source/directives/dev/index.ts +3 -0
  143. package/source/directives/dev/types.ts +5 -0
  144. package/source/directives/index.ts +5 -0
  145. package/source/discovery.ts +1 -0
  146. package/source/exceptions.ts +17 -0
  147. package/source/index.test.ts +9 -0
  148. package/source/index.ts +6 -0
  149. package/source/manifest.test.ts +59 -0
  150. package/source/manifest.ts +48 -0
  151. package/source/root.ts +38 -0
  152. package/source/schemas.ts +9 -0
  153. package/tsconfig.json +12 -0
  154. package/src/.manifest/index.js +0 -7
  155. package/src/.manifest/normalize.js +0 -58
  156. package/src/.manifest/schema.yaml +0 -71
  157. package/src/.manifest/validate.js +0 -17
  158. package/src/constants.js +0 -3
  159. package/src/deployment.js +0 -23
  160. package/src/exposition.js +0 -68
  161. package/src/factory.js +0 -76
  162. package/src/index.js +0 -9
  163. package/src/manifest.js +0 -12
  164. package/src/query/criteria.js +0 -55
  165. package/src/query/enum.js +0 -35
  166. package/src/query/index.js +0 -17
  167. package/src/query/query.js +0 -60
  168. package/src/query/range.js +0 -28
  169. package/src/query/sort.js +0 -19
  170. package/src/remote.js +0 -88
  171. package/src/server.js +0 -83
  172. package/src/tenant.js +0 -29
  173. package/src/translate/etag.js +0 -14
  174. package/src/translate/index.js +0 -7
  175. package/src/translate/request.js +0 -68
  176. package/src/translate/response.js +0 -62
  177. package/src/tree.js +0 -109
  178. package/test/manifest.normalize.fixtures.js +0 -37
  179. package/test/manifest.normalize.test.js +0 -37
  180. package/test/manifest.validate.test.js +0 -40
  181. package/test/query.range.test.js +0 -18
  182. package/test/tree.fixtures.js +0 -21
  183. package/test/tree.test.js +0 -44
  184. package/types/annotations.d.ts +0 -10
  185. package/types/declarations.d.ts +0 -31
  186. package/types/exposition.d.ts +0 -13
  187. package/types/http.d.ts +0 -13
  188. package/types/query.d.ts +0 -16
  189. package/types/remote.d.ts +0 -19
  190. package/types/server.d.ts +0 -13
  191. package/types/tree.d.ts +0 -33
@@ -0,0 +1,193 @@
1
+ Feature: Errors
2
+
3
+ Scenario Outline: Missing routes
4
+ Given the `greeter` is running with the following manifest:
5
+ """yaml
6
+ namespace: basic
7
+ """
8
+ When the following request is received:
9
+ """
10
+ GET <path> HTTP/1.1
11
+ accept: application/yaml
12
+ """
13
+ Then the following reply is sent:
14
+ """
15
+ 404 Not Found
16
+ """
17
+ Examples:
18
+ | path |
19
+ | /basic/greeter/non-existent-segment/ |
20
+ | /basic/non-existent-component/ |
21
+ | /non-existent-namespace/ |
22
+
23
+ Scenario: Missing trailing slash
24
+ Given the `greeter` is running with the following manifest:
25
+ """yaml
26
+ namespace: basic
27
+ """
28
+ When the following request is received:
29
+ """
30
+ GET /basic/greeter HTTP/1.1
31
+ accept: application/json
32
+ """
33
+ Then the following reply is sent:
34
+ """
35
+ 404 Not Found
36
+ content-type: application/json
37
+
38
+ "Trailing slash is required."
39
+ """
40
+
41
+ Scenario: Missing method
42
+ Given the `greeter` is running
43
+ When the following request is received:
44
+ """
45
+ PATCH /greeter/ HTTP/1.1
46
+ accept: application/yaml
47
+ """
48
+ Then the following reply is sent:
49
+ """http
50
+ 405 Method Not Allowed
51
+ """
52
+
53
+ Scenario: Unsupported method
54
+ When the following request is received:
55
+ """
56
+ COPY /basic/greeter/ HTTP/1.1
57
+ accept: application/yaml
58
+ """
59
+ Then the following reply is sent:
60
+ """http
61
+ 501 Not Implemented
62
+ """
63
+
64
+ Scenario: Request body does not match input schema
65
+ Given the `pots` is running with the following manifest:
66
+ """yaml
67
+ exposition:
68
+ /:
69
+ POST: transit
70
+ """
71
+ When the following request is received:
72
+ """
73
+ POST /pots/ HTTP/1.1
74
+ accept: application/yaml
75
+ content-type: application/yaml
76
+
77
+ foo: Hello
78
+ bar: 1.5
79
+ """
80
+ Then the following reply is sent:
81
+ """
82
+ 400 Bad Request
83
+ content-type: application/yaml
84
+
85
+ must have required property 'title'
86
+ """
87
+
88
+ Scenario: Query limit out of range
89
+ Given the `pots` is running with the following manifest:
90
+ """yaml
91
+ exposition:
92
+ /:
93
+ GET: enumerate
94
+ """
95
+ When the following request is received:
96
+ """
97
+ GET /pots/?limit=1001 HTTP/1.1
98
+ accept: text/plain
99
+ """
100
+ Then the following reply is sent:
101
+ """
102
+ 400 Bad Request
103
+ content-type: text/plain
104
+
105
+ Query limit must be between 1 and 1000 inclusive.
106
+ """
107
+
108
+ Scenario: Closed query criteria
109
+ Given the `pots` is running with the following manifest:
110
+ """yaml
111
+ exposition:
112
+ /hot:
113
+ GET:
114
+ endpoint: enumerate
115
+ query:
116
+ criteria: temerature>60
117
+ """
118
+ When the following request is received:
119
+ """
120
+ GET /pots/hot/?criteria=volume>500 HTTP/1.1
121
+ accept: text/plain
122
+ """
123
+ Then the following reply is sent:
124
+ """
125
+ 400 Bad Request
126
+ content-type: text/plain
127
+
128
+ Query criteria is closed.
129
+ """
130
+
131
+ Scenario: Additional query parameters
132
+ Given the `pots` is running with the following manifest:
133
+ """yaml
134
+ exposition:
135
+ /:
136
+ GET:
137
+ endpoint: enumerate
138
+ """
139
+ When the following request is received:
140
+ """
141
+ GET /pots/?foo=bar HTTP/1.1
142
+ accept: text/plain
143
+ """
144
+ Then the following reply is sent:
145
+ """
146
+ 400 Bad Request
147
+ content-type: text/plain
148
+
149
+ Query must NOT have additional properties
150
+ """
151
+
152
+ Scenario: Malformed authorization header
153
+ Given the annotation:
154
+ """yaml
155
+ /:
156
+ GET: {}
157
+ """
158
+ When the following request is received:
159
+ """
160
+ GET / HTTP/1.1
161
+ authorization: Basic
162
+ accept: text/plain
163
+ """
164
+ Then the following reply is sent:
165
+ """
166
+ 401 Unauthorized
167
+
168
+ Malformed authorization header.
169
+ """
170
+
171
+ Scenario Outline: Exception is thrown (debug: <debug>)
172
+ Given the annotation:
173
+ """yaml
174
+ debug: <debug>
175
+ /:
176
+ GET:
177
+ anonymous: true
178
+ dev:throw: Broken!
179
+ """
180
+ When the following request is received:
181
+ """
182
+ GET / HTTP/1.1
183
+ accept: text/plain
184
+ """
185
+ Then the following reply is sent:
186
+ """
187
+ 500 Internal Server Error
188
+ <response>
189
+ """
190
+ Examples:
191
+ | debug | response |
192
+ | false | content-length: 0 |
193
+ | true | Error: Broken! |
@@ -0,0 +1,276 @@
1
+ Feature: Basic authentication
2
+
3
+ Background:
4
+ Given the `identity.basic` database is empty
5
+
6
+ Scenario: Creating new Identity with basic credentials
7
+ When the following request is received:
8
+ """
9
+ POST /identity/basic/ HTTP/1.1
10
+ content-type: application/yaml
11
+
12
+ username: developer
13
+ password: secret#1234
14
+ """
15
+ Then the following reply is sent:
16
+ """
17
+ 201 Created
18
+ """
19
+
20
+ Scenario: Creating new Identity using inception
21
+ Given the `users` is running with the following manifest:
22
+ """yaml
23
+ exposition:
24
+ /:
25
+ anonymous: true # checking compatibility with anonymous access
26
+ POST:
27
+ incept: id
28
+ endpoint: transit
29
+ query: ~
30
+ /:id: # credential testing route
31
+ id: id
32
+ GET: observe
33
+ """
34
+ When the following request is received:
35
+ """
36
+ POST /users/ HTTP/1.1
37
+ authorization: Basic dXNlcjpwYXNzMTIzNA==
38
+ accept: application/yaml
39
+ content-type: application/yaml
40
+
41
+ name: Bill Smith
42
+ """
43
+ Then the following reply is sent:
44
+ """
45
+ 201 Created
46
+ authorization: Token ${{ token }}
47
+
48
+ id: ${{ id }}
49
+ """
50
+ When the following request is received:
51
+ # basic credentials have been created
52
+ """
53
+ GET /users/${{ id }}/ HTTP/1.1
54
+ authorization: Basic dXNlcjpwYXNzMTIzNA==
55
+ """
56
+ Then the following reply is sent:
57
+ """
58
+ 200 OK
59
+ """
60
+ When the following request is received:
61
+ # valid token has been issued
62
+ """
63
+ GET /users/${{ id }}/ HTTP/1.1
64
+ authorization: Token ${{ token }}
65
+ """
66
+ Then the following reply is sent:
67
+ """
68
+ 200 OK
69
+ """
70
+
71
+ Scenario: Changing the password
72
+ Given the annotation:
73
+ """yaml
74
+ /:
75
+ /:id:
76
+ id: id
77
+ GET:
78
+ dev:stub:
79
+ access: granted!
80
+ """
81
+ And the `identity.basic` database contains:
82
+ | _id | _version | username | password |
83
+ | efe3a65ebbee47ed95a73edd911ea328 | 1 | developer | $2b$10$ZRSKkgZoGnrcTNA5w5eCcu3pxDzdTduhteVYXcp56AaNcilNkwJ.O |
84
+ When the following request is received:
85
+ """
86
+ PATCH /identity/basic/efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
87
+ authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
88
+ accept: application/yaml
89
+ content-type: application/yaml
90
+
91
+ password: new-secret
92
+ """
93
+ Then the following reply is sent:
94
+ """
95
+ 200 OK
96
+ """
97
+ When the following request is received:
98
+ # old password
99
+ """
100
+ GET /efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
101
+ authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
102
+ """
103
+ Then the following reply is sent:
104
+ """
105
+ 401 Unauthorized
106
+ """
107
+ When the following request is received:
108
+ # new password
109
+ """
110
+ GET /efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
111
+ authorization: Basic ZGV2ZWxvcGVyOm5ldy1zZWNyZXQ=
112
+ """
113
+ Then the following reply is sent:
114
+ """
115
+ 200 OK
116
+ """
117
+
118
+ Scenario Outline: <problem> not meeting the requirements
119
+ When the following request is received:
120
+ """
121
+ POST /identity/basic/ HTTP/1.1
122
+ accept: application/yaml
123
+ content-type: application/yaml
124
+
125
+ username: <username>
126
+ password: <password>
127
+ """
128
+ Then the following reply is sent:
129
+ """
130
+ 409 Conflict
131
+
132
+ code: <code>
133
+ message: <problem> is not meeting the requirements.
134
+ """
135
+ Examples:
136
+ | username | password | problem | code |
137
+ | with whitespace | secret#1234 | Username | INVALID_USERNAME |
138
+ | root | short | Password | INVALID_PASSWORD |
139
+
140
+ Scenario Outline: Given <property> is not meeting one of requirements
141
+ Given the `identity.basic` configuration:
142
+ """yaml
143
+ <property>:
144
+ - ^\S{1,16}$
145
+ - ^[^A]{1,16}$ # should not contain 'A'
146
+ """
147
+ And the `identity.basic` database contains:
148
+ | _id | _version | username | password |
149
+ | efe3a65ebbee47ed95a73edd911ea328 | 1 | developer | $2b$10$ZRSKkgZoGnrcTNA5w5eCcu3pxDzdTduhteVYXcp56AaNcilNkwJ.O |
150
+ When the following request is received:
151
+ """
152
+ PATCH /identity/basic/efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
153
+ authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
154
+ accept: application/yaml
155
+ content-type: application/yaml
156
+
157
+ <property>: hasAinside
158
+ """
159
+ Then the following reply is sent:
160
+ """
161
+ 409 Conflict
162
+ """
163
+ Examples:
164
+ | property |
165
+ | username |
166
+ | password |
167
+
168
+ Scenario: Granting a `system` role to a Principal
169
+ Given the `identity.basic` configuration:
170
+ """yaml
171
+ principal: root
172
+ """
173
+ And the annotation:
174
+ """yaml
175
+ /:
176
+ GET:
177
+ auth:role: system:stub
178
+ dev:stub:
179
+ access: granted!
180
+ """
181
+ When the following request is received:
182
+ """
183
+ POST /identity/basic/ HTTP/1.1
184
+ content-type: application/yaml
185
+
186
+ username: root
187
+ password: secret#1234
188
+ """
189
+ Then the following reply is sent:
190
+ """
191
+ 201 Created
192
+
193
+ id: ${{ id }}
194
+ """
195
+ # role granting is eventual
196
+ Then after 0.1 seconds
197
+ When the following request is received:
198
+ """
199
+ GET /identity/roles/${{ id }}/ HTTP/1.1
200
+ authorization: Basic cm9vdDpzZWNyZXQjMTIzNA==
201
+ accept: application/yaml
202
+ """
203
+ Then the following reply is sent:
204
+ """
205
+ 200 OK
206
+ authorization: Token ${{ token }}
207
+
208
+ - system
209
+ """
210
+ When the following request is received:
211
+ """
212
+ GET / HTTP/1.1
213
+ authorization: Token ${{ token }}
214
+ accept: application/yaml
215
+ """
216
+ Then the following reply is sent:
217
+ """
218
+ 200 OK
219
+
220
+ access: granted!
221
+ """
222
+ # Principal username cannot be changed
223
+ When the following request is received:
224
+ """
225
+ PATCH /identity/basic/${{ id }}/ HTTP/1.1
226
+ authorization: Token ${{ token }}
227
+ content-type: application/yaml
228
+
229
+ username: admin
230
+ """
231
+ Then the following reply is sent:
232
+ """
233
+ 409 Conflict
234
+
235
+ code: PRINCIPAL_LOCKED
236
+ message: Principal username cannot be changed.
237
+ """
238
+
239
+ Scenario: Creating an Identity using inception with existing credentials
240
+ Given the `identity.basic` database is empty
241
+ And the `users` is running with the following manifest:
242
+ """yaml
243
+ exposition:
244
+ /:
245
+ anonymous: true
246
+ POST:
247
+ incept: id
248
+ endpoint: transit
249
+ """
250
+ When the following request is received:
251
+ # identity inception
252
+ """
253
+ POST /users/ HTTP/1.1
254
+ authorization: Basic dXNlcjpwYXNzMTIzNA==
255
+ accept: application/yaml
256
+ content-type: application/yaml
257
+
258
+ name: Bill Smith
259
+ """
260
+ Then the following reply is sent:
261
+ """
262
+ 201 Created
263
+ """
264
+ And the following request is received:
265
+ # same credentials
266
+ """
267
+ POST /users/ HTTP/1.1
268
+ authorization: Basic dXNlcjpwYXNzMTIzNA==
269
+ content-type: text/plain
270
+
271
+ name: Mary Louis
272
+ """
273
+ Then the following reply is sent:
274
+ """
275
+ 403 Forbidden
276
+ """
@@ -0,0 +1,61 @@
1
+ Feature: Identity resource
2
+
3
+ Scenario: Requesting own Identity
4
+ Given the `identity.basic` database contains:
5
+ | _id | username | password |
6
+ | efe3a65ebbee47ed95a73edd911ea328 | developer | $2b$10$ZRSKkgZoGnrcTNA5w5eCcu3pxDzdTduhteVYXcp56AaNcilNkwJ.O |
7
+ And the `identity.roles` database contains:
8
+ | _id | identity | role |
9
+ | 9c4702490ff84f2a9e1b1da2ab64bdd4 | efe3a65ebbee47ed95a73edd911ea328 | developer |
10
+ | 88ec8e348a5c48aaa2d25faa904cd9ff | efe3a65ebbee47ed95a73edd911ea328 | system:identity |
11
+ When the following request is received:
12
+ """
13
+ GET /identity/ HTTP/1.1
14
+ authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
15
+ accept: application/yaml
16
+ """
17
+ Then the following reply is sent:
18
+ """
19
+ 200 OK
20
+ authorization: Token ${{ token }}
21
+
22
+ id: efe3a65ebbee47ed95a73edd911ea328
23
+ roles:
24
+ - developer
25
+ - system:identity
26
+ """
27
+ When the following request is received:
28
+ """
29
+ GET /identity/ HTTP/1.1
30
+ authorization: Token ${{ token }}
31
+ accept: application/yaml
32
+ """
33
+ Then the following reply is sent:
34
+ """
35
+ 200 OK
36
+
37
+ id: efe3a65ebbee47ed95a73edd911ea328
38
+ roles:
39
+ - developer
40
+ - system:identity
41
+ """
42
+
43
+ Scenario: Requesting Identity with non-existent credentials
44
+ Given the `identity.basic` database is empty
45
+ When the following request is received:
46
+ """
47
+ GET /identity/ HTTP/1.1
48
+ authorization: Basic dXNlcjpwYXNzMTIzNA==
49
+ """
50
+ Then the following reply is sent:
51
+ """
52
+ 401 Unauthorized
53
+ """
54
+ When the following request is received:
55
+ """
56
+ GET /identity/ HTTP/1.1
57
+ """
58
+ Then the following reply is sent:
59
+ """
60
+ 401 Unauthorized
61
+ """
@@ -0,0 +1,51 @@
1
+ Feature: Roles management
2
+
3
+ Scenario: Adding a role to an Identity
4
+ Given the `identity.basic` database contains:
5
+ | _id | username | password |
6
+ | 72cf9b0ab0ac4ab2b8036e4e940ddcae | root | $2b$10$Qq/qnyyU5wjrbDXyWok14OnqAZv/z.pLhz.UddatjI6eHU/rFof4i |
7
+ | 4344518184ad44228baffce7a44fd0b1 | user | $2b$10$JoiAQUS7tzobDAFIDBWhWeEIJv933dQetyjRzSmfQGaJE5ZlJbmYy |
8
+ And the `identity.roles` database contains:
9
+ | _id | identity | role |
10
+ | 9c4702490ff84f2a9e1b1da2ab64bdd4 | 72cf9b0ab0ac4ab2b8036e4e940ddcae | system:identity:roles |
11
+ And the annotation:
12
+ """yaml
13
+ /:
14
+ auth:role: test
15
+ GET:
16
+ dev:stub:
17
+ access: granted!
18
+ """
19
+ When the following request is received:
20
+ # user doesn't have the required role
21
+ """
22
+ GET / HTTP/1.1
23
+ authorization: Basic dXNlcjpwYXNz
24
+ """
25
+ Then the following reply is sent:
26
+ """
27
+ 403 Forbidden
28
+ """
29
+ When the following request is received:
30
+ # root adds a role to a user
31
+ """
32
+ POST /identity/roles/4344518184ad44228baffce7a44fd0b1/ HTTP/1.1
33
+ authorization: Basic cm9vdDpzZWNyZXQ=
34
+ content-type: application/yaml
35
+
36
+ role: test
37
+ """
38
+ Then the following reply is sent:
39
+ """
40
+ 201 Created
41
+ """
42
+ When the following request is received:
43
+ # user now have the role
44
+ """
45
+ GET / HTTP/1.1
46
+ authorization: Basic dXNlcjpwYXNz
47
+ """
48
+ Then the following reply is sent:
49
+ """
50
+ 200 OK
51
+ """
@@ -0,0 +1,119 @@
1
+ Feature: Tokens lifecycle
2
+
3
+ Scenario: Switching to Token authentication scheme
4
+ Given the `identity.basic` database contains:
5
+ | _id | username | password |
6
+ | efe3a65ebbee47ed95a73edd911ea328 | developer | $2b$10$ZRSKkgZoGnrcTNA5w5eCcu3pxDzdTduhteVYXcp56AaNcilNkwJ.O |
7
+ Given the annotation:
8
+ """yaml
9
+ /:
10
+ /hello/:id:
11
+ auth:id: id
12
+ GET:
13
+ dev:stub: Hello
14
+ """
15
+ When the following request is received:
16
+ """
17
+ GET /hello/efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
18
+ authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
19
+ accept: text/plain
20
+ """
21
+ Then the following reply is sent:
22
+ """
23
+ 200 OK
24
+ content-type: text/plain
25
+ authorization: Token ${{ token }}
26
+
27
+ Hello
28
+ """
29
+
30
+ Scenario: Refreshing stale token
31
+ Given the `identity.tokens` configuration:
32
+ """yaml
33
+ refresh: 1
34
+ """
35
+ And the annotation:
36
+ """yaml
37
+ /:
38
+ /hello/:id:
39
+ auth:id: id
40
+ GET:
41
+ dev:stub: Hello
42
+ """
43
+ When the following request is received:
44
+ """
45
+ GET /hello/efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
46
+ authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
47
+ accept: text/plain
48
+ """
49
+ Then the following reply is sent:
50
+ """
51
+ 200 OK
52
+ authorization: Token ${{ token }}
53
+
54
+ Hello
55
+ """
56
+ Then after 1 second
57
+ When the following request is received:
58
+ """
59
+ GET /hello/efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
60
+ authorization: Token ${{ token }}
61
+ accept: text/plain
62
+ """
63
+ Then the following reply is sent:
64
+ """
65
+ 200 OK
66
+ authorization: Token
67
+
68
+ Hello
69
+ """
70
+
71
+ Scenario: Token revocation on password change
72
+ Given the annotation:
73
+ """yaml
74
+ /:
75
+ /:id:
76
+ id: id
77
+ GET:
78
+ dev:stub:
79
+ access: granted!
80
+ """
81
+ And the `identity.tokens` configuration:
82
+ """yaml
83
+ refresh: 0.1
84
+ """
85
+ And the `identity.basic` database contains:
86
+ | _id | _version | username | password |
87
+ | efe3a65ebbee47ed95a73edd911ea328 | 1 | developer | $2b$10$ZRSKkgZoGnrcTNA5w5eCcu3pxDzdTduhteVYXcp56AaNcilNkwJ.O |
88
+ When the following request is received:
89
+ """
90
+ GET /efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
91
+ authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
92
+ """
93
+ Then the following reply is sent:
94
+ """
95
+ 200 OK
96
+ authorization: Token ${{ token }}
97
+ """
98
+ When the following request is received:
99
+ """
100
+ PATCH /identity/basic/efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
101
+ authorization: Basic ZGV2ZWxvcGVyOnNlY3JldA==
102
+ content-type: application/yaml
103
+
104
+ password: new-secret
105
+ """
106
+ Then the following reply is sent:
107
+ """
108
+ 200 OK
109
+ """
110
+ Then after 0.2 seconds
111
+ When the following request is received:
112
+ """
113
+ GET /efe3a65ebbee47ed95a73edd911ea328/ HTTP/1.1
114
+ authorization: Token ${{ token }}
115
+ """
116
+ Then the following reply is sent:
117
+ """
118
+ 401 Unauthorized
119
+ """