Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.

Commit 767ecf8

Browse files
committed
feat(oas3): warn when auth schemes are used but not declared
1 parent e6cb222 commit 767ecf8

14 files changed

+670
-31
lines changed

packages/fury-adapter-oas3-parser/STATUS.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Key:
2020
| servers | [](https://github.com/apiaryio/api-elements.js/issues/76) |
2121
| paths | [~](#paths-object) |
2222
| components | ~ |
23-
| security | [](https://github.com/apiaryio/api-elements.js/issues/77) |
23+
| security | |
2424
| tags | [](https://github.com/apiaryio/api-elements.js/issues/75) |
2525
| externalDocs | [](https://github.com/apiaryio/api-elements.js/issues/82) |
2626

@@ -72,7 +72,7 @@ Key:
7272
| responses | [~](#responses-object) |
7373
| callbacks | [](https://github.com/apiaryio/api-elements.js/issues/74) |
7474
| deprecated ||
75-
| security | [](https://github.com/apiaryio/api-elements.js/issues/329) |
75+
| security | |
7676
| servers | [](https://github.com/apiaryio/api-elements.js/issues/76) |
7777

7878
## Parameter Object
@@ -211,15 +211,17 @@ support.
211211

212212
## Security Scheme Object
213213

214+
See https://github.com/apiaryio/api-elements.js/issues/329 to track things left to do.
215+
214216
| Field Name | Support |
215217
|:--|:--|
216218
| type | [~](#security-scheme-type) |
217219
| description ||
218220
| name ||
219-
| in | ~ |
221+
| in | |
220222
| scheme | ~ |
221223
| bearerFormat ||
222-
| flows | |
224+
| flows | |
223225
| openIdConnectUrl ||
224226

225227
## Security Scheme Type
@@ -228,7 +230,7 @@ support.
228230
|:--|:--|
229231
| apiKey ||
230232
| http ||
231-
| oauth2 | |
233+
| oauth2 | |
232234
| openIdConnect ||
233235

234236
## Example Object

packages/fury-adapter-oas3-parser/lib/context.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ class Context {
1616
registerId(id) {
1717
return this.state.registerId(id);
1818
}
19+
20+
oauthFlow(id, flow) {
21+
return this.state.oauthFlow(id, flow);
22+
}
23+
24+
registerScheme(id) {
25+
return this.state.registerScheme(id);
26+
}
27+
28+
hasScheme(id) {
29+
return this.state.hasScheme(id);
30+
}
1931
}
2032

2133
module.exports = Context;

packages/fury-adapter-oas3-parser/lib/parser/oas/parseComponentsObject.js

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -152,28 +152,47 @@ function parseComponentsObject(context, element) {
152152
const parseSecuritySchemes = pipeParseResult(namespace,
153153
parseComponentObjectMember(parseSecuritySchemeObject),
154154
(object) => {
155+
const parseResult = new namespace.elements.ParseResult([]);
155156
const array = new namespace.elements.Array([]);
156157

157158
object.forEach((value, key) => {
159+
const keyValue = key.toValue();
160+
158161
if (value) {
159162
if (value instanceof namespace.elements.AuthScheme) {
160-
// eslint-disable-next-line no-param-reassign
161-
value.id = key.clone();
162-
array.push(value);
163+
if (!context.registerScheme(keyValue)) {
164+
parseResult.push(createWarning(namespace,
165+
`'${keyValue}' security scheme is already defined`, key));
166+
} else {
167+
// eslint-disable-next-line no-param-reassign
168+
value.id = key.clone();
169+
array.push(value);
170+
}
163171

164172
return;
165173
}
166174

167175
// append oauth2 flow names
168176
value.forEach((flow) => {
169-
// eslint-disable-next-line no-param-reassign
170-
flow.id = `${key.toValue()} ${flow.grantTypeValue}`;
171-
array.push(flow);
177+
const flowSchemeName = `${keyValue} ${flow.grantTypeValue}`;
178+
179+
if (!context.oauthFlow(keyValue, flowSchemeName)) {
180+
parseResult.push(createWarning(namespace,
181+
`'${flowSchemeName}' security scheme can't be created from '${keyValue}' security scheme because it is already defined`, key));
182+
} else {
183+
// eslint-disable-next-line no-param-reassign
184+
flow.id = flowSchemeName;
185+
array.push(flow);
186+
}
172187
});
173188
}
174189
});
175190

176-
return array;
191+
if (!array.isEmpty) {
192+
parseResult.push(array);
193+
}
194+
195+
return parseResult;
177196
});
178197

179198
const parseMember = R.cond([

packages/fury-adapter-oas3-parser/lib/parser/oas/parseOpenAPIObject.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,8 @@ function parseOASObject(context, object) {
110110
const parseMember = R.cond([
111111
[hasKey('openapi'), parseOpenAPI(context)],
112112
[hasKey('info'), R.compose(parseInfoObject(context), getValue)],
113-
[hasKey('paths'), R.compose(asArray, parsePathsObject(context), getValue)],
114113
[hasKey('components'), R.compose(parseComponentsObject(context), getValue)],
114+
[hasKey('paths'), R.compose(asArray, parsePathsObject(context), getValue)],
115115
[hasKey('security'), R.compose(parseSecurityRequirementsArray(context), getValue)],
116116

117117
// FIXME Support exposing extensions into parse result

packages/fury-adapter-oas3-parser/lib/parser/oas/parseSecurityRequirementObject.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,34 @@ function parseSecurityRequirementObject(context, object) {
4040
const parseSecurityRequirement = pipeParseResult(namespace,
4141
parseObject(context, name, parseMember),
4242
(securityRequirement) => {
43-
// TODO: expand oauth requirements into multiples depending on flows
44-
const arr = new namespace.elements.Array([]);
43+
const parseResult = new namespace.elements.ParseResult([]);
44+
const array = new namespace.elements.Array([]);
4545

4646
securityRequirement.forEach((value, key) => {
4747
let e;
48-
const scopes = value.map(scope => scope.toValue());
48+
const schemeName = key.toValue();
4949

50-
if (scopes.length) {
51-
e = new namespace.elements.AuthScheme({ scopes });
50+
if (!context.hasScheme(schemeName)) {
51+
parseResult.push(createWarning(namespace, `'${schemeName}' security scheme not found`, key));
5252
} else {
53-
e = new namespace.elements.AuthScheme({});
54-
}
53+
const scopes = value.map(scope => scope.toValue());
54+
55+
if (scopes.length) {
56+
e = new namespace.elements.AuthScheme({ scopes });
57+
} else {
58+
e = new namespace.elements.AuthScheme({});
59+
}
5560

56-
e.element = key.toValue();
57-
arr.push(e);
61+
e.element = schemeName;
62+
array.push(e);
63+
}
5864
});
5965

60-
return arr;
66+
if (!array.isEmpty) {
67+
parseResult.push(array);
68+
}
69+
70+
return parseResult;
6171
});
6272

6373
return parseSecurityRequirement(object);

packages/fury-adapter-oas3-parser/lib/state.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
class State {
22
constructor() {
33
this.registeredIds = new Set();
4+
5+
this.registeredSchemes = new Set();
6+
this.oauthFlows = {};
47
}
58

69
registerId(id) {
@@ -11,6 +14,26 @@ class State {
1114
this.registeredIds.add(id);
1215
return true;
1316
}
17+
18+
oauthFlow(id, flow) {
19+
this.oauthFlows[id] = this.oauthFlows[id] || [];
20+
this.oauthFlows[id].push(flow);
21+
22+
return this.registerScheme(flow);
23+
}
24+
25+
registerScheme(id) {
26+
if (this.registeredSchemes.has(id)) {
27+
return false;
28+
}
29+
30+
this.registeredSchemes.add(id);
31+
return true;
32+
}
33+
34+
hasScheme(id) {
35+
return this.registeredSchemes.has(id);
36+
}
1437
}
1538

1639
module.exports = State;
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
{
2+
"element": "parseResult",
3+
"content": [
4+
{
5+
"element": "category",
6+
"meta": {
7+
"classes": {
8+
"element": "array",
9+
"content": [
10+
{
11+
"element": "string",
12+
"content": "api"
13+
}
14+
]
15+
},
16+
"title": {
17+
"element": "string",
18+
"content": "Auth Scheme"
19+
}
20+
},
21+
"attributes": {
22+
"version": {
23+
"element": "string",
24+
"content": "1.0.0"
25+
}
26+
},
27+
"content": [
28+
{
29+
"element": "resource",
30+
"attributes": {
31+
"href": {
32+
"element": "string",
33+
"content": "/user"
34+
}
35+
},
36+
"content": [
37+
{
38+
"element": "transition",
39+
"meta": {
40+
"title": {
41+
"element": "string",
42+
"content": "View the current User"
43+
}
44+
},
45+
"content": [
46+
{
47+
"element": "httpTransaction",
48+
"content": [
49+
{
50+
"element": "httpRequest",
51+
"attributes": {
52+
"method": {
53+
"element": "string",
54+
"content": "GET"
55+
}
56+
}
57+
},
58+
{
59+
"element": "httpResponse",
60+
"attributes": {
61+
"headers": {
62+
"element": "httpHeaders",
63+
"content": [
64+
{
65+
"element": "member",
66+
"content": {
67+
"key": {
68+
"element": "string",
69+
"content": "Content-Type"
70+
},
71+
"value": {
72+
"element": "string",
73+
"content": "application/json"
74+
}
75+
}
76+
}
77+
]
78+
},
79+
"statusCode": {
80+
"element": "string",
81+
"content": "200"
82+
}
83+
},
84+
"content": [
85+
{
86+
"element": "dataStructure",
87+
"content": {
88+
"element": "string"
89+
}
90+
},
91+
{
92+
"element": "copy",
93+
"content": "An user"
94+
}
95+
]
96+
}
97+
]
98+
}
99+
]
100+
}
101+
]
102+
}
103+
]
104+
},
105+
{
106+
"element": "annotation",
107+
"meta": {
108+
"classes": {
109+
"element": "array",
110+
"content": [
111+
{
112+
"element": "string",
113+
"content": "warning"
114+
}
115+
]
116+
}
117+
},
118+
"attributes": {
119+
"sourceMap": {
120+
"element": "array",
121+
"content": [
122+
{
123+
"element": "sourceMap",
124+
"content": [
125+
{
126+
"element": "array",
127+
"content": [
128+
{
129+
"element": "number",
130+
"attributes": {
131+
"line": {
132+
"element": "number",
133+
"content": 10
134+
},
135+
"column": {
136+
"element": "number",
137+
"content": 11
138+
}
139+
},
140+
"content": 149
141+
},
142+
{
143+
"element": "number",
144+
"attributes": {
145+
"line": {
146+
"element": "number",
147+
"content": 10
148+
},
149+
"column": {
150+
"element": "number",
151+
"content": 16
152+
}
153+
},
154+
"content": 5
155+
}
156+
]
157+
}
158+
]
159+
}
160+
]
161+
}
162+
},
163+
"content": "'basic' security scheme not found"
164+
}
165+
]
166+
}

0 commit comments

Comments
 (0)