stoobly-agent 0.26.11__py3-none-any.whl → 0.27.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/api/configs_controller.py +17 -12
- stoobly_agent/app/cli/helpers/print_service.py +4 -2
- stoobly_agent/app/models/factories/resource/local_db/helpers/create_request_columns_service.py +1 -1
- stoobly_agent/app/models/factories/resource/local_db/request_adapter.py +29 -11
- stoobly_agent/app/proxy/record/overwrite_scenario_service.py +1 -1
- stoobly_agent/lib/api/keys/request_key.py +14 -5
- stoobly_agent/lib/api/keys/scenario_key.py +14 -5
- stoobly_agent/lib/api/keys/uuid_key.py +24 -0
- stoobly_agent/lib/orm/request.py +11 -1
- stoobly_agent/lib/orm/scenario.py +1 -1
- stoobly_agent/public/11-es2015.0d86b95c0db1e55945f4.js +1 -0
- stoobly_agent/public/11-es5.0d86b95c0db1e55945f4.js +1 -0
- stoobly_agent/public/18-es2015.750ef954bde422debcb6.js +1 -0
- stoobly_agent/public/18-es5.750ef954bde422debcb6.js +1 -0
- stoobly_agent/public/dashboard.agent-alpha-0.27.0.tar.gz +0 -0
- stoobly_agent/public/index.html +1 -1
- stoobly_agent/public/{main-es2015.ece107681f10e74540af.js → main-es2015.9aaecf72f47ebb58efdb.js} +1 -1
- stoobly_agent/public/{main-es5.ece107681f10e74540af.js → main-es5.9aaecf72f47ebb58efdb.js} +1 -1
- stoobly_agent/public/runtime-es2015.6d14514e90ffbe7aa697.js +1 -0
- stoobly_agent/public/runtime-es5.6d14514e90ffbe7aa697.js +1 -0
- {stoobly_agent-0.26.11.dist-info → stoobly_agent-0.27.1.dist-info}/METADATA +1 -1
- {stoobly_agent-0.26.11.dist-info → stoobly_agent-0.27.1.dist-info}/RECORD +27 -26
- stoobly_agent/public/11-es2015.8feb8504fdd3e6813e67.js +0 -1
- stoobly_agent/public/11-es5.8feb8504fdd3e6813e67.js +0 -1
- stoobly_agent/public/18-es2015.4b1aafce0739bb8141fd.js +0 -1
- stoobly_agent/public/18-es5.4b1aafce0739bb8141fd.js +0 -1
- stoobly_agent/public/dashboard.agent-alpha-0.26.10.tar.gz +0 -0
- stoobly_agent/public/runtime-es2015.da33ff934331415e9631.js +0 -1
- stoobly_agent/public/runtime-es5.da33ff934331415e9631.js +0 -1
- {stoobly_agent-0.26.11.dist-info → stoobly_agent-0.27.1.dist-info}/LICENSE +0 -0
- {stoobly_agent-0.26.11.dist-info → stoobly_agent-0.27.1.dist-info}/WHEEL +0 -0
- {stoobly_agent-0.26.11.dist-info → stoobly_agent-0.27.1.dist-info}/entry_points.txt +0 -0
- {stoobly_agent-0.26.11.dist-info → stoobly_agent-0.27.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.
|
2
|
+
VERSION = '0.27.1'
|
@@ -2,14 +2,14 @@ import pdb
|
|
2
2
|
|
3
3
|
from mergedeep import merge
|
4
4
|
|
5
|
+
from stoobly_agent.app.api.simple_http_request_handler import SimpleHTTPRequestHandler
|
5
6
|
from stoobly_agent.app.cli.helpers.handle_config_update_service import context as handle_context, handle_project_update, handle_policy_update, handle_scenario_update
|
6
|
-
from stoobly_agent.app.
|
7
|
+
from stoobly_agent.app.models.scenario_model import ScenarioModel
|
7
8
|
from stoobly_agent.app.proxy.intercept_settings import InterceptSettings
|
8
|
-
from stoobly_agent.
|
9
|
-
from stoobly_agent.config.constants import mock_policy, record_policy
|
9
|
+
from stoobly_agent.app.settings import Settings
|
10
|
+
from stoobly_agent.config.constants import mock_policy, mode, record_policy, replay_policy
|
10
11
|
from stoobly_agent.lib.api.keys.project_key import ProjectKey
|
11
12
|
from stoobly_agent.lib.api.keys.scenario_key import ScenarioKey
|
12
|
-
from stoobly_agent.lib.api.scenarios_resource import ScenariosResource
|
13
13
|
|
14
14
|
class ConfigsController:
|
15
15
|
_instance = None
|
@@ -67,17 +67,20 @@ class ConfigsController:
|
|
67
67
|
project_id = ProjectKey(project_key).id if project_key else None
|
68
68
|
|
69
69
|
scenario_key = intercept_settings.scenario_key
|
70
|
-
scenario_id =
|
70
|
+
scenario_id = None
|
71
71
|
|
72
72
|
# Check to make sure the scenario still exists
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
scenario_uuid = ScenarioKey(scenario_key).id if scenario_key else None
|
74
|
+
|
75
|
+
if scenario_uuid:
|
76
|
+
model = self.__scenario_model(context, settings)
|
77
|
+
scenario, status = model.show(scenario_uuid)
|
76
78
|
|
77
|
-
if
|
78
|
-
scenario_id = None
|
79
|
+
if status == 404:
|
79
80
|
intercept_settings.scenario_key = None
|
80
81
|
settings.commit()
|
82
|
+
elif status == 200:
|
83
|
+
scenario_id = scenario['id']
|
81
84
|
|
82
85
|
modes = [mode.RECORD, mode.MOCK, mode.TEST, mode.REPLAY] if not context.params.get('agent') else [mode.RECORD, mode.MOCK, mode.REPLAY]
|
83
86
|
|
@@ -114,5 +117,7 @@ class ConfigsController:
|
|
114
117
|
status = 200
|
115
118
|
)
|
116
119
|
|
117
|
-
def
|
118
|
-
|
120
|
+
def __scenario_model(self, context: SimpleHTTPRequestHandler, settings: Settings = None):
|
121
|
+
scenario_model = ScenarioModel(settings or Settings.instance())
|
122
|
+
scenario_model.as_remote() if context.headers.get('access-token') else scenario_model.as_local()
|
123
|
+
return scenario_model
|
@@ -24,7 +24,9 @@ def print_projects(projects, **kwargs):
|
|
24
24
|
def print_requests(requests, **kwargs):
|
25
25
|
tabulate_print(
|
26
26
|
requests,
|
27
|
-
filter=[
|
27
|
+
filter=[
|
28
|
+
'body_params_hash', 'body_text_hash', 'components' , 'created_at', 'endpoint', 'endpoint_id', 'http_version', 'is_deleted', 'position', 'project_id', 'pushed_at', 'query_params_hash', 'scenario_id', 'scheme', 'starred', 'uuid', 'updated_at', 'url'
|
29
|
+
],
|
28
30
|
headers=not kwargs.get('without_headers'),
|
29
31
|
select=kwargs.get('select') or []
|
30
32
|
)
|
@@ -32,7 +34,7 @@ def print_requests(requests, **kwargs):
|
|
32
34
|
def print_scenarios(scenarios, **kwargs):
|
33
35
|
tabulate_print(
|
34
36
|
scenarios,
|
35
|
-
filter=['created_at', 'priority', 'project_id', 'starred', 'updated_at'],
|
37
|
+
filter=['created_at', 'is_deleted', 'priority', 'project_id', 'starred', 'uuid', 'updated_at'],
|
36
38
|
headers=not kwargs.get('without_headers'),
|
37
39
|
select=kwargs.get('select') or []
|
38
40
|
)
|
stoobly_agent/app/models/factories/resource/local_db/helpers/create_request_columns_service.py
CHANGED
@@ -20,7 +20,7 @@ def build_request_columns(flow: MitmproxyHTTPFlow, joined_request: JoinedRequest
|
|
20
20
|
'is_deleted': params.get('is_deleted') or False,
|
21
21
|
'latency': joined_request.response_string.latency,
|
22
22
|
'raw': joined_request.request_string.get(),
|
23
|
-
'scenario_id':
|
23
|
+
'scenario_id': params['scenario_id'] if params.get('scenario_id') else None,
|
24
24
|
'status': flow.response.status_code,
|
25
25
|
'uuid': joined_request.request_string.request_id,
|
26
26
|
}
|
@@ -13,6 +13,7 @@ from stoobly_agent.app.proxy.record.joined_request import JoinedRequest
|
|
13
13
|
from stoobly_agent.lib.orm import ORM
|
14
14
|
from stoobly_agent.lib.orm.request import Request
|
15
15
|
from stoobly_agent.lib.orm.response import Response
|
16
|
+
from stoobly_agent.lib.orm.scenario import Scenario
|
16
17
|
from stoobly_agent.lib.orm.transformers.orm_to_stoobly_request_transformer import ORMToStooblyRequestTransformer
|
17
18
|
from stoobly_agent.lib.orm.types.request_columns import RequestColumns
|
18
19
|
from stoobly_agent.lib.orm.transformers import ORMToRequestTransformer, ORMToRequestsResponseTransformer
|
@@ -28,16 +29,20 @@ class LocalDBRequestAdapter(LocalDBAdapter):
|
|
28
29
|
__request_orm = None
|
29
30
|
__response_orm = None
|
30
31
|
|
31
|
-
def __init__(self, request_orm: Request.__class__ = Request, response_orm: Response.__class__ = Response):
|
32
|
+
def __init__(self, request_orm: Request.__class__ = Request, response_orm: Response.__class__ = Response, scenario_orm = Scenario.__class__):
|
32
33
|
self.__request_orm: Request = request_orm
|
33
34
|
self.__response_orm: Response = response_orm
|
35
|
+
self.__scenario_orm: Scenario = scenario_orm
|
34
36
|
|
35
37
|
def create(self, **params: RequestCreateParams) -> Tuple[RequestShowResponse, int]:
|
38
|
+
self.__adapt_scenario_id(params)
|
39
|
+
|
36
40
|
flow: MitmproxyHTTPFlow = params['flow']
|
37
41
|
joined_request: JoinedRequest = params['joined_request']
|
42
|
+
scenario_id = params.get('scenario_id')
|
38
43
|
|
39
44
|
with ORM.instance().db.transaction():
|
40
|
-
request_columns = build_request_columns(flow, joined_request, scenario_id=
|
45
|
+
request_columns = build_request_columns(flow, joined_request, scenario_id=scenario_id)
|
41
46
|
request_record = self.__request_orm.create(**request_columns)
|
42
47
|
|
43
48
|
response_columns = {
|
@@ -89,6 +94,8 @@ class LocalDBRequestAdapter(LocalDBAdapter):
|
|
89
94
|
return ORMToRequestsResponseTransformer(response_record).transform()
|
90
95
|
|
91
96
|
def index(self, **query_params: RequestsIndexQueryParams) -> Tuple[RequestsIndexResponse, int]:
|
97
|
+
self.__adapt_scenario_id(query_params)
|
98
|
+
|
92
99
|
scenario_id = query_params.get('scenario_id')
|
93
100
|
page = int(query_params.get('page') or 0)
|
94
101
|
query = query_params.get('q')
|
@@ -105,7 +112,7 @@ class LocalDBRequestAdapter(LocalDBAdapter):
|
|
105
112
|
if unassigned:
|
106
113
|
requests = requests.where('scenario_id', None)
|
107
114
|
elif scenario_id:
|
108
|
-
requests = requests.where('scenario_id',
|
115
|
+
requests = requests.where('scenario_id', scenario_id)
|
109
116
|
sort_order = query_params.get('sort_order') or 'asc'
|
110
117
|
|
111
118
|
if starred:
|
@@ -258,15 +265,30 @@ class LocalDBRequestAdapter(LocalDBAdapter):
|
|
258
265
|
|
259
266
|
return candidates.get()
|
260
267
|
|
268
|
+
def __filter_request_response_columns(self, request_columns: RequestCreateParams):
|
269
|
+
if request_columns.get('project_id'):
|
270
|
+
del request_columns['project_id']
|
271
|
+
|
261
272
|
def __request(self, request_id: str):
|
262
273
|
if self.validate_uuid(request_id):
|
263
274
|
return self.__request_orm.find_by(uuid=request_id)
|
264
275
|
else:
|
265
276
|
return self.__request_orm.find(request_id)
|
266
277
|
|
267
|
-
def
|
268
|
-
|
269
|
-
|
278
|
+
def __request_not_found(self):
|
279
|
+
return self.not_found('Request not found')
|
280
|
+
|
281
|
+
def __adapt_scenario_id(self, params: dict):
|
282
|
+
if not params.get('scenario_id'):
|
283
|
+
return
|
284
|
+
|
285
|
+
scenario_id = params['scenario_id']
|
286
|
+
if not self.validate_uuid(scenario_id):
|
287
|
+
return
|
288
|
+
|
289
|
+
scenario = self.__scenario_orm.find_by(uuid=scenario_id)
|
290
|
+
if scenario:
|
291
|
+
params['scenario_id'] = scenario.id
|
270
292
|
|
271
293
|
def __search(self, base_model: Request, query: str) -> Request:
|
272
294
|
uri = urlparse(query)
|
@@ -275,8 +297,4 @@ class LocalDBRequestAdapter(LocalDBAdapter):
|
|
275
297
|
return base_model.where('host', uri.hostname).where('path', uri.path)
|
276
298
|
else:
|
277
299
|
pattern = f"%{query}%"
|
278
|
-
return base_model.where('path', 'like', pattern).or_where('host', 'like', pattern)
|
279
|
-
|
280
|
-
def __request_not_found(self):
|
281
|
-
return self.not_found('Request not found')
|
282
|
-
|
300
|
+
return base_model.where('path', 'like', pattern).or_where('host', 'like', pattern)
|
@@ -31,7 +31,7 @@ def overwrite_scenario(scenario_key: str):
|
|
31
31
|
return
|
32
32
|
|
33
33
|
requests_model = RequestModel(settings)
|
34
|
-
res, status = requests_model.destroy_all(scenario_id=
|
34
|
+
res, status = requests_model.destroy_all(scenario_id=scenario['id'])
|
35
35
|
|
36
36
|
if status != 200:
|
37
37
|
return
|
@@ -1,14 +1,18 @@
|
|
1
|
-
|
1
|
+
import uuid
|
2
|
+
|
3
|
+
from .uuid_key import UuidKey
|
2
4
|
|
3
5
|
from stoobly_agent.app.settings import Settings
|
4
6
|
|
5
7
|
class InvalidRequestKey(Exception):
|
6
8
|
pass
|
7
9
|
|
8
|
-
class RequestKey(
|
10
|
+
class RequestKey(UuidKey):
|
9
11
|
def __init__(self, key: str):
|
10
12
|
super().__init__(key)
|
11
13
|
|
14
|
+
self.__raw = key
|
15
|
+
|
12
16
|
if not self.id:
|
13
17
|
raise InvalidRequestKey('Missing id')
|
14
18
|
|
@@ -19,15 +23,20 @@ class RequestKey(ResourceKey):
|
|
19
23
|
|
20
24
|
@property
|
21
25
|
def id(self) -> str:
|
22
|
-
|
26
|
+
u = uuid.UUID(self.get('i'))
|
27
|
+
return str(u)
|
23
28
|
|
24
29
|
@property
|
25
30
|
def project_id(self) -> str:
|
26
31
|
return self.get('p')
|
27
32
|
|
33
|
+
@property
|
34
|
+
def raw(self):
|
35
|
+
return self.__raw
|
36
|
+
|
28
37
|
@staticmethod
|
29
38
|
def encode(project_id: str, request_id: str):
|
30
|
-
return
|
39
|
+
return UuidKey.encode({
|
31
40
|
'p': project_id,
|
32
|
-
'i': request_id,
|
41
|
+
'i': request_id.replace('-', ''),
|
33
42
|
})
|
@@ -1,13 +1,17 @@
|
|
1
|
-
|
1
|
+
import uuid
|
2
|
+
|
3
|
+
from .uuid_key import UuidKey
|
2
4
|
|
3
5
|
class InvalidScenarioKey(Exception):
|
4
6
|
pass
|
5
7
|
|
6
|
-
class ScenarioKey(
|
8
|
+
class ScenarioKey(UuidKey):
|
7
9
|
|
8
10
|
def __init__(self, key: str):
|
9
11
|
super().__init__(key)
|
10
12
|
|
13
|
+
self.__raw = key
|
14
|
+
|
11
15
|
if not self.id:
|
12
16
|
raise InvalidScenarioKey('Missing id')
|
13
17
|
|
@@ -20,11 +24,16 @@ class ScenarioKey(ResourceKey):
|
|
20
24
|
|
21
25
|
@property
|
22
26
|
def id(self) -> str:
|
23
|
-
|
27
|
+
u = uuid.UUID(self.get('i'))
|
28
|
+
return str(u)
|
29
|
+
|
30
|
+
@property
|
31
|
+
def raw(self):
|
32
|
+
return self.__raw
|
24
33
|
|
25
34
|
@staticmethod
|
26
35
|
def encode(project_id: str, request_id: str):
|
27
|
-
return
|
36
|
+
return UuidKey.encode({
|
28
37
|
'p': project_id,
|
29
|
-
'i': request_id,
|
38
|
+
'i': request_id.replace('-', ''),
|
30
39
|
})
|
@@ -0,0 +1,24 @@
|
|
1
|
+
from .resource_key import ResourceKey
|
2
|
+
|
3
|
+
DELIMITTER = '.'
|
4
|
+
|
5
|
+
class UuidKey(ResourceKey):
|
6
|
+
def __init__(self, key: str):
|
7
|
+
super().__init__(super().encode(self.__decode(key)))
|
8
|
+
|
9
|
+
@staticmethod
|
10
|
+
def encode(d: dict):
|
11
|
+
toks = []
|
12
|
+
for key in d:
|
13
|
+
toks.append(f"{key}{d[key]}")
|
14
|
+
|
15
|
+
return DELIMITTER.join(toks)
|
16
|
+
|
17
|
+
def __decode(self, key: str):
|
18
|
+
toks = key.split(DELIMITTER)
|
19
|
+
|
20
|
+
d = {}
|
21
|
+
for tok in toks:
|
22
|
+
d[tok[0]] = tok[1:]
|
23
|
+
|
24
|
+
return d
|
stoobly_agent/lib/orm/request.py
CHANGED
@@ -52,7 +52,7 @@ class Request(Base):
|
|
52
52
|
return Scenario
|
53
53
|
|
54
54
|
def key(self):
|
55
|
-
return decode(RequestKey.encode(LOCAL_PROJECT_ID, self.
|
55
|
+
return decode(RequestKey.encode(LOCAL_PROJECT_ID, self.uuid))
|
56
56
|
|
57
57
|
# Override
|
58
58
|
def to_dict(self):
|
@@ -96,6 +96,16 @@ def handle_saving(request):
|
|
96
96
|
if hasattr(request, 'is_deleted') and request.is_deleted:
|
97
97
|
request.scenario_id = None
|
98
98
|
|
99
|
+
if hasattr(request, 'scenario_id') and request.scenario_id:
|
100
|
+
try:
|
101
|
+
# If set as uuid, convert to id
|
102
|
+
uuid.UUID(request.scenario_id)
|
103
|
+
|
104
|
+
scenario = Scenario.find_by(uuid=request.scenario_id)
|
105
|
+
request.scenario_id = scenario.id
|
106
|
+
except Exception:
|
107
|
+
pass
|
108
|
+
|
99
109
|
def handle_saved(request):
|
100
110
|
request_before = request.get_original()
|
101
111
|
|