robot-wrapper-sdk 0.2.1__tar.gz → 0.2.5__tar.gz
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.
- robot_wrapper_sdk-0.2.5/PKG-INFO +171 -0
- robot_wrapper_sdk-0.2.5/README.md +161 -0
- {robot_wrapper_sdk-0.2.1 → robot_wrapper_sdk-0.2.5}/pyproject.toml +2 -2
- robot_wrapper_sdk-0.2.5/robot_sdk/__init__.py +84 -0
- robot_wrapper_sdk-0.2.5/robot_sdk/application/usecases.py +78 -0
- robot_wrapper_sdk-0.2.5/robot_sdk/domain/entities.py +51 -0
- robot_wrapper_sdk-0.2.5/robot_sdk/domain/repositories.py +77 -0
- {robot_wrapper_sdk-0.2.1 → robot_wrapper_sdk-0.2.5}/robot_sdk/infrastructure/api_client.py +62 -26
- robot_wrapper_sdk-0.2.5/robot_sdk/infrastructure/robot_api_repository.py +126 -0
- robot_wrapper_sdk-0.2.5/robot_wrapper_sdk.egg-info/PKG-INFO +171 -0
- robot_wrapper_sdk-0.2.5/robot_wrapper_sdk.egg-info/requires.txt +1 -0
- robot_wrapper_sdk-0.2.1/PKG-INFO +0 -95
- robot_wrapper_sdk-0.2.1/README.md +0 -85
- robot_wrapper_sdk-0.2.1/robot_sdk/__init__.py +0 -27
- robot_wrapper_sdk-0.2.1/robot_sdk/application/usecases.py +0 -66
- robot_wrapper_sdk-0.2.1/robot_sdk/domain/entities.py +0 -23
- robot_wrapper_sdk-0.2.1/robot_sdk/domain/repositories.py +0 -77
- robot_wrapper_sdk-0.2.1/robot_sdk/infrastructure/robot_api_repository.py +0 -108
- robot_wrapper_sdk-0.2.1/robot_wrapper_sdk.egg-info/PKG-INFO +0 -95
- robot_wrapper_sdk-0.2.1/robot_wrapper_sdk.egg-info/requires.txt +0 -1
- {robot_wrapper_sdk-0.2.1 → robot_wrapper_sdk-0.2.5}/examples/main.py +0 -0
- {robot_wrapper_sdk-0.2.1 → robot_wrapper_sdk-0.2.5}/robot_sdk/application/__init__.py +0 -0
- {robot_wrapper_sdk-0.2.1 → robot_wrapper_sdk-0.2.5}/robot_sdk/domain/__init__.py +0 -0
- {robot_wrapper_sdk-0.2.1 → robot_wrapper_sdk-0.2.5}/robot_sdk/infrastructure/__init__.py +0 -0
- {robot_wrapper_sdk-0.2.1 → robot_wrapper_sdk-0.2.5}/robot_wrapper_sdk.egg-info/SOURCES.txt +0 -0
- {robot_wrapper_sdk-0.2.1 → robot_wrapper_sdk-0.2.5}/robot_wrapper_sdk.egg-info/dependency_links.txt +0 -0
- {robot_wrapper_sdk-0.2.1 → robot_wrapper_sdk-0.2.5}/robot_wrapper_sdk.egg-info/top_level.txt +0 -0
- {robot_wrapper_sdk-0.2.1 → robot_wrapper_sdk-0.2.5}/setup.cfg +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: robot-wrapper-sdk
|
|
3
|
+
Version: 0.2.5
|
|
4
|
+
Summary: Robot Platform API SDK
|
|
5
|
+
Author-email: GH Robot Platform Team <team@ghrobot.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: httpx[socks]>=0.24.1
|
|
10
|
+
|
|
11
|
+
# Robot Platform SDK (Python)
|
|
12
|
+
|
|
13
|
+
Python SDK for Robot Platform with:
|
|
14
|
+
- develop-app authentication (`app_id`/`app_secret`),
|
|
15
|
+
- sync + async clients,
|
|
16
|
+
- auto token refresh,
|
|
17
|
+
- robot operations and login/hardening task flow.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install robot-wrapper-sdk
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Configuration
|
|
26
|
+
|
|
27
|
+
Set environment variables (recommended):
|
|
28
|
+
|
|
29
|
+
- `ROBOT_PLATFORM_BASE_URL`
|
|
30
|
+
- `ROBOT_PLATFORM_APP_ID`
|
|
31
|
+
- `ROBOT_PLATFORM_APP_SECRET`
|
|
32
|
+
- `ROBOT_PLATFORM_PROXY_URL` (optional)
|
|
33
|
+
|
|
34
|
+
Or pass values directly when creating the module.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Quick Start (Sync)
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from robot_sdk import RobotPlatformModule
|
|
42
|
+
|
|
43
|
+
sdk = RobotPlatformModule(
|
|
44
|
+
base_url="http://localhost:8085",
|
|
45
|
+
app_id="your_app_id",
|
|
46
|
+
app_secret="your_app_secret",
|
|
47
|
+
# proxy_url="socks5h://192.168.3.100:1080", # optional
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Read robot
|
|
51
|
+
robot = sdk.get_robot("2047631542552334336")
|
|
52
|
+
print(robot.platform if robot else "not found")
|
|
53
|
+
|
|
54
|
+
# Update lifecycle status
|
|
55
|
+
sdk.update_status("2047631542552334336", "live")
|
|
56
|
+
|
|
57
|
+
# Acquire login tasks
|
|
58
|
+
login_tasks = sdk.acquire_need_login(limit=20, lock_minutes=30)
|
|
59
|
+
|
|
60
|
+
# Update auth status after worker result
|
|
61
|
+
sdk.update_auth_status("2047631542552334336", "authorized")
|
|
62
|
+
# allowed values: authorized | unauthorized | logged_out
|
|
63
|
+
|
|
64
|
+
# Acquire hardening tasks
|
|
65
|
+
hardening_tasks = sdk.acquire_unhardened(limit=20, lock_minutes=30, min_age_days=0)
|
|
66
|
+
|
|
67
|
+
# Update hardening status after worker result
|
|
68
|
+
sdk.update_security_hardened("2047631542552334336", True)
|
|
69
|
+
|
|
70
|
+
sdk.close()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Quick Start (Async)
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import asyncio
|
|
77
|
+
from robot_sdk import AsyncRobotPlatformModule
|
|
78
|
+
|
|
79
|
+
async def main():
|
|
80
|
+
sdk = AsyncRobotPlatformModule(
|
|
81
|
+
base_url="http://localhost:8085",
|
|
82
|
+
app_id="your_app_id",
|
|
83
|
+
app_secret="your_app_secret",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
robot = await sdk.get_robot("2047631542552334336")
|
|
87
|
+
print(robot.platform if robot else "not found")
|
|
88
|
+
|
|
89
|
+
await sdk.update_auth_status("2047631542552334336", "authorized")
|
|
90
|
+
await sdk.update_security_hardened("2047631542552334336", True)
|
|
91
|
+
|
|
92
|
+
await sdk.close()
|
|
93
|
+
|
|
94
|
+
asyncio.run(main())
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Response Shape (Placeholder)
|
|
100
|
+
|
|
101
|
+
Acquire endpoints return:
|
|
102
|
+
|
|
103
|
+
```json
|
|
104
|
+
{
|
|
105
|
+
"status": "success",
|
|
106
|
+
"code": 200,
|
|
107
|
+
"message": "OK",
|
|
108
|
+
"data": [
|
|
109
|
+
{
|
|
110
|
+
"id": "2047631542552334336",
|
|
111
|
+
"username": "example_user_1",
|
|
112
|
+
"platform": "facebook",
|
|
113
|
+
"status": "live",
|
|
114
|
+
"auth_status": "unauthorized",
|
|
115
|
+
"metadata": {
|
|
116
|
+
"security_hardened": false
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Update endpoints return:
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"status": "success",
|
|
128
|
+
"code": 200,
|
|
129
|
+
"message": "OK",
|
|
130
|
+
"data": null
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Main API
|
|
137
|
+
|
|
138
|
+
### `RobotPlatformModule` (sync)
|
|
139
|
+
- `list_robots(platform=None, status=None, project_id=None, page=1, limit=20)`
|
|
140
|
+
- `get_robot(robot_id)`
|
|
141
|
+
- `delete_robot(robot_id)`
|
|
142
|
+
- `get_secrets(robot_id)`
|
|
143
|
+
- `update_status(robot_id, status)`
|
|
144
|
+
- `acquire_need_login(limit=20, lock_minutes=30)`
|
|
145
|
+
- `acquire_unhardened(limit=20, lock_minutes=30, min_age_days=0)`
|
|
146
|
+
- `update_auth_status(robot_id, auth_status)`
|
|
147
|
+
- `update_security_hardened(robot_id, security_hardened)`
|
|
148
|
+
- `close()`
|
|
149
|
+
|
|
150
|
+
### `AsyncRobotPlatformModule` (async)
|
|
151
|
+
Async equivalents of all methods above, plus `await close()`.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Documentation
|
|
156
|
+
|
|
157
|
+
- Usage guide: [`docs/guide.md`](docs/guide.md)
|
|
158
|
+
- Package code: `robot_sdk/`
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Build & Publish (Maintainers)
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
make venv
|
|
166
|
+
make install
|
|
167
|
+
make build
|
|
168
|
+
make publish
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Requires valid PyPI credentials (Twine).
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Robot Platform SDK (Python)
|
|
2
|
+
|
|
3
|
+
Python SDK for Robot Platform with:
|
|
4
|
+
- develop-app authentication (`app_id`/`app_secret`),
|
|
5
|
+
- sync + async clients,
|
|
6
|
+
- auto token refresh,
|
|
7
|
+
- robot operations and login/hardening task flow.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install robot-wrapper-sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
Set environment variables (recommended):
|
|
18
|
+
|
|
19
|
+
- `ROBOT_PLATFORM_BASE_URL`
|
|
20
|
+
- `ROBOT_PLATFORM_APP_ID`
|
|
21
|
+
- `ROBOT_PLATFORM_APP_SECRET`
|
|
22
|
+
- `ROBOT_PLATFORM_PROXY_URL` (optional)
|
|
23
|
+
|
|
24
|
+
Or pass values directly when creating the module.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Quick Start (Sync)
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from robot_sdk import RobotPlatformModule
|
|
32
|
+
|
|
33
|
+
sdk = RobotPlatformModule(
|
|
34
|
+
base_url="http://localhost:8085",
|
|
35
|
+
app_id="your_app_id",
|
|
36
|
+
app_secret="your_app_secret",
|
|
37
|
+
# proxy_url="socks5h://192.168.3.100:1080", # optional
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Read robot
|
|
41
|
+
robot = sdk.get_robot("2047631542552334336")
|
|
42
|
+
print(robot.platform if robot else "not found")
|
|
43
|
+
|
|
44
|
+
# Update lifecycle status
|
|
45
|
+
sdk.update_status("2047631542552334336", "live")
|
|
46
|
+
|
|
47
|
+
# Acquire login tasks
|
|
48
|
+
login_tasks = sdk.acquire_need_login(limit=20, lock_minutes=30)
|
|
49
|
+
|
|
50
|
+
# Update auth status after worker result
|
|
51
|
+
sdk.update_auth_status("2047631542552334336", "authorized")
|
|
52
|
+
# allowed values: authorized | unauthorized | logged_out
|
|
53
|
+
|
|
54
|
+
# Acquire hardening tasks
|
|
55
|
+
hardening_tasks = sdk.acquire_unhardened(limit=20, lock_minutes=30, min_age_days=0)
|
|
56
|
+
|
|
57
|
+
# Update hardening status after worker result
|
|
58
|
+
sdk.update_security_hardened("2047631542552334336", True)
|
|
59
|
+
|
|
60
|
+
sdk.close()
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Quick Start (Async)
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
import asyncio
|
|
67
|
+
from robot_sdk import AsyncRobotPlatformModule
|
|
68
|
+
|
|
69
|
+
async def main():
|
|
70
|
+
sdk = AsyncRobotPlatformModule(
|
|
71
|
+
base_url="http://localhost:8085",
|
|
72
|
+
app_id="your_app_id",
|
|
73
|
+
app_secret="your_app_secret",
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
robot = await sdk.get_robot("2047631542552334336")
|
|
77
|
+
print(robot.platform if robot else "not found")
|
|
78
|
+
|
|
79
|
+
await sdk.update_auth_status("2047631542552334336", "authorized")
|
|
80
|
+
await sdk.update_security_hardened("2047631542552334336", True)
|
|
81
|
+
|
|
82
|
+
await sdk.close()
|
|
83
|
+
|
|
84
|
+
asyncio.run(main())
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Response Shape (Placeholder)
|
|
90
|
+
|
|
91
|
+
Acquire endpoints return:
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"status": "success",
|
|
96
|
+
"code": 200,
|
|
97
|
+
"message": "OK",
|
|
98
|
+
"data": [
|
|
99
|
+
{
|
|
100
|
+
"id": "2047631542552334336",
|
|
101
|
+
"username": "example_user_1",
|
|
102
|
+
"platform": "facebook",
|
|
103
|
+
"status": "live",
|
|
104
|
+
"auth_status": "unauthorized",
|
|
105
|
+
"metadata": {
|
|
106
|
+
"security_hardened": false
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Update endpoints return:
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"status": "success",
|
|
118
|
+
"code": 200,
|
|
119
|
+
"message": "OK",
|
|
120
|
+
"data": null
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Main API
|
|
127
|
+
|
|
128
|
+
### `RobotPlatformModule` (sync)
|
|
129
|
+
- `list_robots(platform=None, status=None, project_id=None, page=1, limit=20)`
|
|
130
|
+
- `get_robot(robot_id)`
|
|
131
|
+
- `delete_robot(robot_id)`
|
|
132
|
+
- `get_secrets(robot_id)`
|
|
133
|
+
- `update_status(robot_id, status)`
|
|
134
|
+
- `acquire_need_login(limit=20, lock_minutes=30)`
|
|
135
|
+
- `acquire_unhardened(limit=20, lock_minutes=30, min_age_days=0)`
|
|
136
|
+
- `update_auth_status(robot_id, auth_status)`
|
|
137
|
+
- `update_security_hardened(robot_id, security_hardened)`
|
|
138
|
+
- `close()`
|
|
139
|
+
|
|
140
|
+
### `AsyncRobotPlatformModule` (async)
|
|
141
|
+
Async equivalents of all methods above, plus `await close()`.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Documentation
|
|
146
|
+
|
|
147
|
+
- Usage guide: [`docs/guide.md`](docs/guide.md)
|
|
148
|
+
- Package code: `robot_sdk/`
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Build & Publish (Maintainers)
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
make venv
|
|
156
|
+
make install
|
|
157
|
+
make build
|
|
158
|
+
make publish
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Requires valid PyPI credentials (Twine).
|
|
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
|
|
|
8
8
|
|
|
9
9
|
[project]
|
|
10
10
|
name = "robot-wrapper-sdk"
|
|
11
|
-
version = "0.2.
|
|
11
|
+
version = "0.2.5"
|
|
12
12
|
description = "Robot Platform API SDK"
|
|
13
13
|
readme = "README.md"
|
|
14
14
|
requires-python = ">=3.10"
|
|
@@ -16,7 +16,7 @@ authors = [
|
|
|
16
16
|
{ name = "GH Robot Platform Team", email = "team@ghrobot.com" },
|
|
17
17
|
]
|
|
18
18
|
dependencies = [
|
|
19
|
-
"httpx>=0.24.1",
|
|
19
|
+
"httpx[socks]>=0.24.1",
|
|
20
20
|
]
|
|
21
21
|
|
|
22
22
|
[project.license]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
from typing import Optional, List, Dict, Any, Tuple
|
|
2
|
+
from .infrastructure.api_client import HTTPClient, AsyncHTTPClient
|
|
3
|
+
from .infrastructure.robot_api_repository import RobotAPIRepository, AsyncRobotAPIRepository
|
|
4
|
+
from .application.usecases import RobotUsecase, AsyncRobotUsecase
|
|
5
|
+
from .domain.entities import Robot, RobotSecrets
|
|
6
|
+
|
|
7
|
+
__version__ = "0.2.1"
|
|
8
|
+
|
|
9
|
+
class RobotPlatformModule:
|
|
10
|
+
"""Synchronous Facade for the Robot Platform SDK."""
|
|
11
|
+
def __init__(self, base_url=None, app_id=None, app_secret=None, proxy_url=None):
|
|
12
|
+
self.client = HTTPClient(base_url, app_id, app_secret, proxy_url)
|
|
13
|
+
self.repo = RobotAPIRepository(self.client)
|
|
14
|
+
self.robot_usecase = RobotUsecase(self.repo)
|
|
15
|
+
|
|
16
|
+
def close(self):
|
|
17
|
+
self.client.close()
|
|
18
|
+
|
|
19
|
+
def list_robots(self, platform: Optional[str] = None, status: Optional[str] = None, project_id: Optional[int] = None, page: int = 1, limit: int = 20) -> Dict[str, Any]:
|
|
20
|
+
return self.robot_usecase.list_robots(platform, status, project_id, page, limit)
|
|
21
|
+
|
|
22
|
+
def get_robot(self, robot_id: str) -> Optional[Robot]:
|
|
23
|
+
return self.robot_usecase.get_robot(robot_id)
|
|
24
|
+
|
|
25
|
+
def delete_robot(self, robot_id: str) -> None:
|
|
26
|
+
self.robot_usecase.delete_robot(robot_id)
|
|
27
|
+
|
|
28
|
+
def get_secrets(self, robot_id: str) -> Optional[RobotSecrets]:
|
|
29
|
+
return self.robot_usecase.get_secrets(robot_id)
|
|
30
|
+
|
|
31
|
+
def update_status(self, robot_id: str, status: str) -> None:
|
|
32
|
+
self.robot_usecase.update_status(robot_id, status)
|
|
33
|
+
|
|
34
|
+
def acquire_need_login(self, limit: int = 20, lock_minutes: int = 30):
|
|
35
|
+
return self.robot_usecase.acquire_need_login(limit, lock_minutes)
|
|
36
|
+
|
|
37
|
+
def acquire_unhardened(self, limit: int = 20, lock_minutes: int = 30, min_age_days: int = 0):
|
|
38
|
+
return self.robot_usecase.acquire_unhardened(limit, lock_minutes, min_age_days)
|
|
39
|
+
|
|
40
|
+
def update_auth_status(self, robot_id: str, auth_status: str) -> None:
|
|
41
|
+
self.robot_usecase.update_auth_status(robot_id, auth_status)
|
|
42
|
+
|
|
43
|
+
def update_security_hardened(self, robot_id: str, security_hardened: bool) -> None:
|
|
44
|
+
self.robot_usecase.update_security_hardened(robot_id, security_hardened)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class AsyncRobotPlatformModule:
|
|
48
|
+
"""Asynchronous Facade for the Robot Platform SDK."""
|
|
49
|
+
def __init__(self, base_url=None, app_id=None, app_secret=None, proxy_url=None):
|
|
50
|
+
self.client = AsyncHTTPClient(base_url, app_id, app_secret, proxy_url)
|
|
51
|
+
self.repo = AsyncRobotAPIRepository(self.client)
|
|
52
|
+
self.robot_usecase = AsyncRobotUsecase(self.repo)
|
|
53
|
+
|
|
54
|
+
async def close(self):
|
|
55
|
+
await self.client.close()
|
|
56
|
+
|
|
57
|
+
async def list_robots(self, platform: Optional[str] = None, status: Optional[str] = None, project_id: Optional[int] = None, page: int = 1, limit: int = 20) -> Dict[str, Any]:
|
|
58
|
+
return await self.robot_usecase.list_robots(platform, status, project_id, page, limit)
|
|
59
|
+
|
|
60
|
+
async def get_robot(self, robot_id: str) -> Optional[Robot]:
|
|
61
|
+
return await self.robot_usecase.get_robot(robot_id)
|
|
62
|
+
|
|
63
|
+
async def delete_robot(self, robot_id: str) -> None:
|
|
64
|
+
await self.robot_usecase.delete_robot(robot_id)
|
|
65
|
+
|
|
66
|
+
async def get_secrets(self, robot_id: str) -> Optional[RobotSecrets]:
|
|
67
|
+
return await self.robot_usecase.get_secrets(robot_id)
|
|
68
|
+
|
|
69
|
+
async def update_status(self, robot_id: str, status: str) -> None:
|
|
70
|
+
await self.robot_usecase.update_status(robot_id, status)
|
|
71
|
+
|
|
72
|
+
async def acquire_need_login(self, limit: int = 20, lock_minutes: int = 30):
|
|
73
|
+
return await self.robot_usecase.acquire_need_login(limit, lock_minutes)
|
|
74
|
+
|
|
75
|
+
async def acquire_unhardened(self, limit: int = 20, lock_minutes: int = 30, min_age_days: int = 0):
|
|
76
|
+
return await self.robot_usecase.acquire_unhardened(limit, lock_minutes, min_age_days)
|
|
77
|
+
|
|
78
|
+
async def update_auth_status(self, robot_id: str, auth_status: str) -> None:
|
|
79
|
+
await self.robot_usecase.update_auth_status(robot_id, auth_status)
|
|
80
|
+
|
|
81
|
+
async def update_security_hardened(self, robot_id: str, security_hardened: bool) -> None:
|
|
82
|
+
await self.robot_usecase.update_security_hardened(robot_id, security_hardened)
|
|
83
|
+
|
|
84
|
+
__all__ = ["RobotPlatformModule", "AsyncRobotPlatformModule", "Robot", "RobotSecrets"]
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
from typing import Optional, List, Tuple, Any, Dict
|
|
2
|
+
from ..domain.repositories import RobotRepository, AsyncRobotRepository
|
|
3
|
+
from ..domain.entities import Robot, RobotSecrets
|
|
4
|
+
|
|
5
|
+
class RobotUsecase:
|
|
6
|
+
def __init__(self, repo: RobotRepository):
|
|
7
|
+
self.repo = repo
|
|
8
|
+
|
|
9
|
+
def get_robot(self, robot_id: str) -> Optional[Robot]:
|
|
10
|
+
return self.repo.find_by_id(robot_id)
|
|
11
|
+
|
|
12
|
+
def delete_robot(self, robot_id: str) -> None:
|
|
13
|
+
self.repo.delete_robot(robot_id)
|
|
14
|
+
|
|
15
|
+
def get_secrets(self, robot_id: str) -> Optional[RobotSecrets]:
|
|
16
|
+
return self.repo.get_secrets(robot_id)
|
|
17
|
+
|
|
18
|
+
def update_status(self, robot_id: str, status: str) -> None:
|
|
19
|
+
self.repo.update_status(robot_id, status)
|
|
20
|
+
|
|
21
|
+
def list_robots(self, platform: Optional[str] = None, status: Optional[str] = None, project_id: Optional[int] = None, page: int = 1, limit: int = 20) -> Dict[str, Any]:
|
|
22
|
+
items, total = self.repo.list_robots(platform, status, project_id, page, limit)
|
|
23
|
+
return {
|
|
24
|
+
"data": [r.__dict__ for r in items],
|
|
25
|
+
"total": total,
|
|
26
|
+
"page": page,
|
|
27
|
+
"limit": limit
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
def acquire_need_login(self, limit: int = 20, lock_minutes: int = 30) -> List[Robot]:
|
|
31
|
+
return self.repo.acquire_need_login(limit, lock_minutes)
|
|
32
|
+
|
|
33
|
+
def acquire_unhardened(self, limit: int = 20, lock_minutes: int = 30, min_age_days: int = 0) -> List[Robot]:
|
|
34
|
+
return self.repo.acquire_unhardened(limit, lock_minutes, min_age_days)
|
|
35
|
+
|
|
36
|
+
def update_auth_status(self, robot_id: str, auth_status: str) -> None:
|
|
37
|
+
self.repo.update_auth_status(robot_id, auth_status)
|
|
38
|
+
|
|
39
|
+
def update_security_hardened(self, robot_id: str, security_hardened: bool) -> None:
|
|
40
|
+
self.repo.update_security_hardened(robot_id, security_hardened)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class AsyncRobotUsecase:
|
|
44
|
+
def __init__(self, repo: AsyncRobotRepository):
|
|
45
|
+
self.repo = repo
|
|
46
|
+
|
|
47
|
+
async def get_robot(self, robot_id: str) -> Optional[Robot]:
|
|
48
|
+
return await self.repo.find_by_id(robot_id)
|
|
49
|
+
|
|
50
|
+
async def delete_robot(self, robot_id: str) -> None:
|
|
51
|
+
await self.repo.delete_robot(robot_id)
|
|
52
|
+
|
|
53
|
+
async def get_secrets(self, robot_id: str) -> Optional[RobotSecrets]:
|
|
54
|
+
return await self.repo.get_secrets(robot_id)
|
|
55
|
+
|
|
56
|
+
async def update_status(self, robot_id: str, status: str) -> None:
|
|
57
|
+
await self.repo.update_status(robot_id, status)
|
|
58
|
+
|
|
59
|
+
async def list_robots(self, platform: Optional[str] = None, status: Optional[str] = None, project_id: Optional[int] = None, page: int = 1, limit: int = 20) -> Dict[str, Any]:
|
|
60
|
+
items, total = await self.repo.list_robots(platform, status, project_id, page, limit)
|
|
61
|
+
return {
|
|
62
|
+
"data": [r.__dict__ for r in items],
|
|
63
|
+
"total": total,
|
|
64
|
+
"page": page,
|
|
65
|
+
"limit": limit
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async def acquire_need_login(self, limit: int = 20, lock_minutes: int = 30) -> List[Robot]:
|
|
69
|
+
return await self.repo.acquire_need_login(limit, lock_minutes)
|
|
70
|
+
|
|
71
|
+
async def acquire_unhardened(self, limit: int = 20, lock_minutes: int = 30, min_age_days: int = 0) -> List[Robot]:
|
|
72
|
+
return await self.repo.acquire_unhardened(limit, lock_minutes, min_age_days)
|
|
73
|
+
|
|
74
|
+
async def update_auth_status(self, robot_id: str, auth_status: str) -> None:
|
|
75
|
+
await self.repo.update_auth_status(robot_id, auth_status)
|
|
76
|
+
|
|
77
|
+
async def update_security_hardened(self, robot_id: str, security_hardened: bool) -> None:
|
|
78
|
+
await self.repo.update_security_hardened(robot_id, security_hardened)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Optional, Any, Dict
|
|
3
|
+
|
|
4
|
+
@dataclass
|
|
5
|
+
class Robot:
|
|
6
|
+
id: str
|
|
7
|
+
username: str
|
|
8
|
+
platform: str
|
|
9
|
+
status: str
|
|
10
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
11
|
+
project_id: Optional[str] = None
|
|
12
|
+
primary_environment: Optional[str] = None
|
|
13
|
+
created_at: Optional[str] = None
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class RobotSecrets:
|
|
17
|
+
password: str
|
|
18
|
+
two_fa_secret: str
|
|
19
|
+
|
|
20
|
+
@dataclass
|
|
21
|
+
class RobotActivity:
|
|
22
|
+
id: str
|
|
23
|
+
activity_type: str
|
|
24
|
+
status: str
|
|
25
|
+
message: str
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class AcquireNeedLoginRequest:
|
|
29
|
+
limit: int = 20
|
|
30
|
+
lock_minutes: int = 30
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class AcquireUnhardenedRequest:
|
|
34
|
+
limit: int = 20
|
|
35
|
+
lock_minutes: int = 30
|
|
36
|
+
min_age_days: int = 0
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class UpdateAuthStatusRequest:
|
|
40
|
+
auth_status: str
|
|
41
|
+
|
|
42
|
+
@dataclass
|
|
43
|
+
class UpdateSecurityHardenedRequest:
|
|
44
|
+
security_hardened: bool
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class StandardResponse:
|
|
48
|
+
status: str
|
|
49
|
+
code: int
|
|
50
|
+
message: str
|
|
51
|
+
data: Any = None
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Optional, List, Tuple
|
|
3
|
+
from .entities import Robot, RobotSecrets
|
|
4
|
+
|
|
5
|
+
class RobotRepository(ABC):
|
|
6
|
+
@abstractmethod
|
|
7
|
+
def find_by_id(self, robot_id: str) -> Optional[Robot]:
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
@abstractmethod
|
|
11
|
+
def update_status(self, robot_id: str, status: str) -> None:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
@abstractmethod
|
|
15
|
+
def delete_robot(self, robot_id: str) -> None:
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def get_secrets(self, robot_id: str) -> Optional[RobotSecrets]:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def list_robots(self, platform: Optional[str] = None, status: Optional[str] = None, project_id: Optional[int] = None, page: int = 1, limit: int = 20) -> Tuple[List[Robot], int]:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def acquire_need_login(self, limit: int = 20, lock_minutes: int = 30) -> List[Robot]:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def acquire_unhardened(self, limit: int = 20, lock_minutes: int = 30, min_age_days: int = 0) -> List[Robot]:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def update_auth_status(self, robot_id: str, auth_status: str) -> None:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
@abstractmethod
|
|
39
|
+
def update_security_hardened(self, robot_id: str, security_hardened: bool) -> None:
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
class AsyncRobotRepository(ABC):
|
|
43
|
+
@abstractmethod
|
|
44
|
+
async def find_by_id(self, robot_id: str) -> Optional[Robot]:
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
@abstractmethod
|
|
48
|
+
async def update_status(self, robot_id: str, status: str) -> None:
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
@abstractmethod
|
|
52
|
+
async def delete_robot(self, robot_id: str) -> None:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
@abstractmethod
|
|
56
|
+
async def get_secrets(self, robot_id: str) -> Optional[RobotSecrets]:
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
@abstractmethod
|
|
60
|
+
async def list_robots(self, platform: Optional[str] = None, status: Optional[str] = None, project_id: Optional[int] = None, page: int = 1, limit: int = 20) -> Tuple[List[Robot], int]:
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
@abstractmethod
|
|
64
|
+
async def acquire_need_login(self, limit: int = 20, lock_minutes: int = 30) -> List[Robot]:
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
@abstractmethod
|
|
68
|
+
async def acquire_unhardened(self, limit: int = 20, lock_minutes: int = 30, min_age_days: int = 0) -> List[Robot]:
|
|
69
|
+
pass
|
|
70
|
+
|
|
71
|
+
@abstractmethod
|
|
72
|
+
async def update_auth_status(self, robot_id: str, auth_status: str) -> None:
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
@abstractmethod
|
|
76
|
+
async def update_security_hardened(self, robot_id: str, security_hardened: bool) -> None:
|
|
77
|
+
pass
|