stoobly-agent 0.30.0__py3-none-any.whl → 0.30.1__py3-none-any.whl
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.
- stoobly_agent/__init__.py +1 -1
- stoobly_agent/app/cli/helpers/openapi_endpoint_adapter.py +60 -5
- stoobly_agent/app/proxy/handle_mock_service.py +1 -1
- stoobly_agent/app/proxy/mitmproxy/request_facade.py +1 -1
- stoobly_agent/app/proxy/record/join_request_service.py +1 -1
- {stoobly_agent-0.30.0.dist-info → stoobly_agent-0.30.1.dist-info}/METADATA +1 -1
- {stoobly_agent-0.30.0.dist-info → stoobly_agent-0.30.1.dist-info}/RECORD +11 -11
- {stoobly_agent-0.30.0.dist-info → stoobly_agent-0.30.1.dist-info}/LICENSE +0 -0
- {stoobly_agent-0.30.0.dist-info → stoobly_agent-0.30.1.dist-info}/WHEEL +0 -0
- {stoobly_agent-0.30.0.dist-info → stoobly_agent-0.30.1.dist-info}/entry_points.txt +0 -0
- {stoobly_agent-0.30.0.dist-info → stoobly_agent-0.30.1.dist-info}/top_level.txt +0 -0
stoobly_agent/__init__.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
COMMAND = 'stoobly-agent'
|
2
|
-
VERSION = '0.30.
|
2
|
+
VERSION = '0.30.1'
|
@@ -27,8 +27,14 @@ class OpenApiEndpointAdapter():
|
|
27
27
|
|
28
28
|
with open(file_path, "r") as stream:
|
29
29
|
file_data: Dict = yaml.safe_load(stream)
|
30
|
+
|
30
31
|
if 'info' not in file_data:
|
31
32
|
self.__add_info(file_data)
|
33
|
+
|
34
|
+
missing_oauth2_scopes = self.__is_missing_oauth2_scopes(file_data)
|
35
|
+
if missing_oauth2_scopes:
|
36
|
+
self.__add_oauth2_default_scopes(file_data)
|
37
|
+
|
32
38
|
spec = Spec.from_dict(file_data)
|
33
39
|
|
34
40
|
return self.adapt(spec)
|
@@ -36,7 +42,7 @@ class OpenApiEndpointAdapter():
|
|
36
42
|
def adapt(self, spec: Spec) -> List[EndpointShowResponse]:
|
37
43
|
endpoints = []
|
38
44
|
endpoint_counter = 0
|
39
|
-
components = spec.get("components")
|
45
|
+
components = spec.get("components", {})
|
40
46
|
schemas = components.get("schemas", {})
|
41
47
|
paths = spec.getkey('paths')
|
42
48
|
|
@@ -184,12 +190,12 @@ class OpenApiEndpointAdapter():
|
|
184
190
|
request_body = operation.get("requestBody", {})
|
185
191
|
required_request_body = request_body.get("required")
|
186
192
|
required_body_params = []
|
187
|
-
param_properties = {}
|
188
193
|
literal_body_params = {}
|
189
194
|
request_body_array = False
|
190
195
|
|
191
196
|
content = request_body.get("content", {})
|
192
197
|
for mimetype, media_type in content.items():
|
198
|
+
param_properties = {}
|
193
199
|
schema = media_type['schema']
|
194
200
|
|
195
201
|
# If Spec Component reference, look it up in components
|
@@ -202,12 +208,10 @@ class OpenApiEndpointAdapter():
|
|
202
208
|
schema_type = schema.get('type')
|
203
209
|
if schema_type:
|
204
210
|
if schema_type == 'object':
|
205
|
-
param_properties = schema
|
211
|
+
param_properties = schema.get('properties', {})
|
206
212
|
elif schema_type == 'array':
|
207
213
|
request_body_array = True
|
208
214
|
param_properties = {'tmp': schema['items']}
|
209
|
-
else:
|
210
|
-
param_properties = {}
|
211
215
|
|
212
216
|
for property_key, property_value in param_properties.items():
|
213
217
|
if property_key in required_body_params:
|
@@ -247,6 +251,57 @@ class OpenApiEndpointAdapter():
|
|
247
251
|
'title': ''
|
248
252
|
}
|
249
253
|
|
254
|
+
def __is_missing_oauth2_scopes(self, file_data: Dict):
|
255
|
+
is_missing = False
|
256
|
+
if 'components' in file_data:
|
257
|
+
components = file_data['components']
|
258
|
+
|
259
|
+
if 'securitySchemes' in components:
|
260
|
+
security_schemes = components['securitySchemes']
|
261
|
+
|
262
|
+
for scheme_name, scheme in security_schemes.items():
|
263
|
+
if scheme.get('type') == 'oauth2':
|
264
|
+
flows = scheme.get('flows')
|
265
|
+
|
266
|
+
if flows and flows.get('clientCredentials'):
|
267
|
+
scopes = flows.get('clientCredentials').get('scopes')
|
268
|
+
|
269
|
+
if scopes is None:
|
270
|
+
return True
|
271
|
+
|
272
|
+
break
|
273
|
+
|
274
|
+
return is_missing
|
275
|
+
|
276
|
+
def __add_oauth2_default_scopes(self, file_data: Dict):
|
277
|
+
if 'components' not in file_data:
|
278
|
+
return
|
279
|
+
components = file_data['components']
|
280
|
+
|
281
|
+
if 'securitySchemes' not in components:
|
282
|
+
return
|
283
|
+
security_schemes = components['securitySchemes']
|
284
|
+
|
285
|
+
oauth_security_scheme = {}
|
286
|
+
for scheme_name, scheme in security_schemes.items():
|
287
|
+
if scheme.get('type') == 'oauth2':
|
288
|
+
oauth_security_scheme = scheme
|
289
|
+
break
|
290
|
+
|
291
|
+
# If empty dict or None
|
292
|
+
if not oauth_security_scheme:
|
293
|
+
return
|
294
|
+
|
295
|
+
flows = oauth_security_scheme['flows']
|
296
|
+
if not flows:
|
297
|
+
return
|
298
|
+
|
299
|
+
client_credentials = flows['clientCredentials']
|
300
|
+
if not client_credentials:
|
301
|
+
return
|
302
|
+
|
303
|
+
client_credentials['scopes'] = {}
|
304
|
+
|
250
305
|
def __get_most_recent_param(self, literal_params: dict):
|
251
306
|
return list(literal_params)[-1] if literal_params else None
|
252
307
|
|
@@ -41,7 +41,7 @@ def handle_request_mock_generic(context: MockContext, **options: MockOptions):
|
|
41
41
|
# Rewrite request with paramter rules for mock
|
42
42
|
request: MitmproxyRequest = context.flow.request
|
43
43
|
request_facade = MitmproxyRequestFacade(request)
|
44
|
-
request_facade.with_parameter_rules(rewrite_rules).rewrite()
|
44
|
+
request_facade.with_parameter_rules(rewrite_rules).with_url_rules(rewrite_rules).rewrite()
|
45
45
|
|
46
46
|
__mock_hook(lifecycle_hooks.BEFORE_MOCK, context)
|
47
47
|
|
@@ -185,7 +185,7 @@ class MitmproxyRequestFacade(Request):
|
|
185
185
|
self.request.host = rewrite.host
|
186
186
|
|
187
187
|
if rewrite.port:
|
188
|
-
self.request.port = rewrite.port
|
188
|
+
self.request.port = int(rewrite.port)
|
189
189
|
|
190
190
|
def __rewrite_headers(self, rewrites: List[ParameterRule]):
|
191
191
|
self.__apply_headers(rewrites, self.__rewrite_handler)
|
@@ -26,7 +26,7 @@ def join_rewritten_request(flow: MitmproxyHTTPFlow, intercept_settings: Intercep
|
|
26
26
|
response = MitmproxyResponseFacade(flow.response)
|
27
27
|
rewrite_rules = intercept_settings.record_rewrite_rules
|
28
28
|
|
29
|
-
request.with_parameter_rules(rewrite_rules).rewrite()
|
29
|
+
request.with_parameter_rules(rewrite_rules).with_url_rules(rewrite_rules).rewrite()
|
30
30
|
response.with_rewrite_rules(rewrite_rules).rewrite()
|
31
31
|
|
32
32
|
return join_request(request, response, intercept_settings)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
stoobly_agent/__init__.py,sha256=
|
1
|
+
stoobly_agent/__init__.py,sha256=ERtaDwMrq3L1TiLsgj7017T43LEdDMO9MX7tpGaf4AA,45
|
2
2
|
stoobly_agent/cli.py,sha256=4ZAnhcjY1a9RA3YZy-RkkUFx4DKw6KpGZq1ZoJZ7akM,7439
|
3
3
|
stoobly_agent/mock.py,sha256=P9cr9yW8PF1XolPfNSftcJVn1xEqcD-SEyIROsFxY20,2549
|
4
4
|
stoobly_agent/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -44,7 +44,7 @@ stoobly_agent/app/cli/helpers/handle_mock_service.py,sha256=OkOaTgCd9ZqYle4_F8jv
|
|
44
44
|
stoobly_agent/app/cli/helpers/handle_replay_service.py,sha256=EmFNISE-e-NzdlCCS_Nx89B2NHjxUXJtUXDe4Caxc7Y,3886
|
45
45
|
stoobly_agent/app/cli/helpers/handle_test_service.py,sha256=4g94uexoAvMPis-fB027TmkZNp4qpj0AO7DZtcHSm5E,6007
|
46
46
|
stoobly_agent/app/cli/helpers/iterate_group_by.py,sha256=oN9JC58LHLiElQC0M6JdjBAVlqIEwoBmNJuSJyIs-cI,3099
|
47
|
-
stoobly_agent/app/cli/helpers/openapi_endpoint_adapter.py,sha256=
|
47
|
+
stoobly_agent/app/cli/helpers/openapi_endpoint_adapter.py,sha256=7p0hlvXie7DYVMgnSMA28p4KBWxLY1qpXSr8TFvR1Jk,19744
|
48
48
|
stoobly_agent/app/cli/helpers/print_service.py,sha256=SQ5vt5DrGbm7syQNCXy6UzHCelMdGBtzEDZllpQ-1zk,1612
|
49
49
|
stoobly_agent/app/cli/helpers/project_facade.py,sha256=rThwVur2clCCBcHa-U4_vGynj0miKv78B3uF6ZRmBSQ,1905
|
50
50
|
stoobly_agent/app/cli/helpers/replay_facade.py,sha256=e-g1gidt6-1zdFYQOJEtz8BHAv0tYHgMFz52DPVgspk,3441
|
@@ -150,7 +150,7 @@ stoobly_agent/app/models/types/response.py,sha256=OQNvHnyLvRSJF3E4A1GaROlZekKvfl
|
|
150
150
|
stoobly_agent/app/models/types/scenario.py,sha256=fcO2rhrFNNDsEd02Mt4TXlVrdAvtkF7I5tIpoR_dkN0,172
|
151
151
|
stoobly_agent/app/proxy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
152
152
|
stoobly_agent/app/proxy/context.py,sha256=XLteUEP8T8aT0hHI_jHDaL2382OaC7QyVwlni5_FS9U,456
|
153
|
-
stoobly_agent/app/proxy/handle_mock_service.py,sha256=
|
153
|
+
stoobly_agent/app/proxy/handle_mock_service.py,sha256=4q0brrNcgiClS02Hx6HKbRzO1glvQUUXrEwsslwZQQE,6043
|
154
154
|
stoobly_agent/app/proxy/handle_record_service.py,sha256=n43FJKGvwgS25QexhfRKBtl3OBMbBN3Trb-R4hqQ3Yc,3362
|
155
155
|
stoobly_agent/app/proxy/handle_replay_service.py,sha256=tJlzRZxu50QGd49MKXoXMiX4UT6GudZbonK7sNFWHHQ,1797
|
156
156
|
stoobly_agent/app/proxy/handle_test_service.py,sha256=F4in8KNyLL8nA30dbmYdRJMCkFV9hc3xJPPYgCUKA0E,3806
|
@@ -166,7 +166,7 @@ stoobly_agent/app/proxy/mitmproxy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
|
|
166
166
|
stoobly_agent/app/proxy/mitmproxy/flow_mock.py,sha256=YxQV3pXIzicvLOCFn7zmnSoAstAmR8fzONYOXAkYbT4,1153
|
167
167
|
stoobly_agent/app/proxy/mitmproxy/request.py,sha256=niy38718CAe4Li4k40GXnWDDmUTCPkXesDZTaC8BeLc,878
|
168
168
|
stoobly_agent/app/proxy/mitmproxy/request_body_facade.py,sha256=kMJ8YH2FKW9qV68QcUbOCLfiGgKrFV5krzt7usGf0as,649
|
169
|
-
stoobly_agent/app/proxy/mitmproxy/request_facade.py,sha256=
|
169
|
+
stoobly_agent/app/proxy/mitmproxy/request_facade.py,sha256=Hq7l6JNDZll3DWqFzAAlkXvLyqGM7jOK7GjcXUIwgLQ,7603
|
170
170
|
stoobly_agent/app/proxy/mitmproxy/response.py,sha256=BFaJlB1D98EOjrc-kUmunUCTUuiZsPDqq2QgAHDocQI,339
|
171
171
|
stoobly_agent/app/proxy/mitmproxy/response_facade.py,sha256=NsNH0aW-mMfLcUXB-Wt9wH5cDyw_4ezdddtCWPHr5hQ,1209
|
172
172
|
stoobly_agent/app/proxy/mock/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -177,7 +177,7 @@ stoobly_agent/app/proxy/mock/hashed_request_decorator.py,sha256=8SnIplrK7VocpvAF
|
|
177
177
|
stoobly_agent/app/proxy/mock/request_hasher.py,sha256=91RLNk163digRaMd1Kg88RLzXrXkpvoNKDQxB_NeiNo,3723
|
178
178
|
stoobly_agent/app/proxy/record/__init__.py,sha256=lbW-G6DZ8IrRpRzvgt-1tn2cRuyLT744u9ERIrZ2dFI,233
|
179
179
|
stoobly_agent/app/proxy/record/context.py,sha256=L9tykwoB35hOPHft3IHSPjuJ2v3TSj9SQAJ9E1q-U_4,343
|
180
|
-
stoobly_agent/app/proxy/record/join_request_service.py,sha256=
|
180
|
+
stoobly_agent/app/proxy/record/join_request_service.py,sha256=Cz34NWBHBIRhHGtfdgnuhTYLPfWPWx6R_mSqljPGr7k,1307
|
181
181
|
stoobly_agent/app/proxy/record/joined_request.py,sha256=va79Pkz5RWACJn07ipV_FtVmGUzjSlqhfUu_amw9bX8,1553
|
182
182
|
stoobly_agent/app/proxy/record/overwrite_scenario_service.py,sha256=3em2a2ry4MrE30XlAukat-l3L9cu4o13Cxhi6BBUgkc,940
|
183
183
|
stoobly_agent/app/proxy/record/proxy_request.py,sha256=6DqQ2KH7AtfvXg5HNDWwvwgjO7x1QrWDYgJOBMWPKqs,418
|
@@ -480,9 +480,9 @@ stoobly_agent/test/app/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
|
|
480
480
|
stoobly_agent/test/mock_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
481
481
|
stoobly_agent/test/mock_data/endpoint_show_response.py,sha256=JFEkceHI6nH38zitCbFMozE1lODahxmvj70N5eM_sec,5901
|
482
482
|
stoobly_agent/test/mock_data/request_show_response.py,sha256=K_a0fP0QT58T8sX9PaM6hqtX1A1depZsqg_GsNPf--k,707
|
483
|
-
stoobly_agent-0.30.
|
484
|
-
stoobly_agent-0.30.
|
485
|
-
stoobly_agent-0.30.
|
486
|
-
stoobly_agent-0.30.
|
487
|
-
stoobly_agent-0.30.
|
488
|
-
stoobly_agent-0.30.
|
483
|
+
stoobly_agent-0.30.1.dist-info/LICENSE,sha256=8WuxPI7sA6w_Yhwqn6v6Ch2Kvu6fo0cwMNIgxSE7oq8,548
|
484
|
+
stoobly_agent-0.30.1.dist-info/METADATA,sha256=wnM9LNhjZn2xLx-iKYvYj-8_2IcjaNiUIP4ohAbsmoo,807
|
485
|
+
stoobly_agent-0.30.1.dist-info/WHEEL,sha256=5sUXSg9e4bi7lTLOHcm6QEYwO5TIF1TNbTSVFVjcJcc,92
|
486
|
+
stoobly_agent-0.30.1.dist-info/entry_points.txt,sha256=4fpF9D1sN3q8Z6d0MmNAKUy0dz-ZxoH9mqfYMhErRCg,57
|
487
|
+
stoobly_agent-0.30.1.dist-info/top_level.txt,sha256=fTxn372sBnUMXVSJxpaVAMBWB3HU3_Mq-WXJCM6mMj8,14
|
488
|
+
stoobly_agent-0.30.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|