qing-client 0.1.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.
- qing_client-0.1.5/PKG-INFO +23 -0
- qing_client-0.1.5/pyproject.toml +53 -0
- qing_client-0.1.5/qing_client.egg-info/PKG-INFO +23 -0
- qing_client-0.1.5/qing_client.egg-info/SOURCES.txt +21 -0
- qing_client-0.1.5/qing_client.egg-info/dependency_links.txt +1 -0
- qing_client-0.1.5/qing_client.egg-info/requires.txt +9 -0
- qing_client-0.1.5/qing_client.egg-info/top_level.txt +1 -0
- qing_client-0.1.5/qingclient/_version.py +34 -0
- qing_client-0.1.5/qingclient/auth_service.py +36 -0
- qing_client-0.1.5/qingclient/base_client.py +176 -0
- qing_client-0.1.5/qingclient/init.py +21 -0
- qing_client-0.1.5/qingclient/msg_service.py +20 -0
- qing_client-0.1.5/qingclient/token_service.py +34 -0
- qing_client-0.1.5/qingclient/user_service.py +51 -0
- qing_client-0.1.5/setup.cfg +4 -0
- qing_client-0.1.5/setup.py +4 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qing-client
|
|
3
|
+
Version: 0.1.5
|
|
4
|
+
Summary: Python client for audit logging services
|
|
5
|
+
Author-email: xiaoyue9527 <xiaoyue9527@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: homepage, https://github.com/yourusername/qing-client
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/yourusername/qing-client/issues
|
|
9
|
+
Project-URL: Documentation, https://github.com/yourusername/qing-client/wiki
|
|
10
|
+
Keywords: audit,logging,security,monitoring
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Requires-Python: >=3.7
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: httpx>=0.23.0
|
|
17
|
+
Requires-Dist: pydantic>=2.0.0
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
20
|
+
Requires-Dist: pytest-asyncio>=0.20.0; extra == "dev"
|
|
21
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
22
|
+
Requires-Dist: build>=0.10.0; extra == "dev"
|
|
23
|
+
Requires-Dist: bumpversion>=0.6.0; extra == "dev"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel", "setuptools-scm"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[tool.setuptools_scm]
|
|
6
|
+
# 从文件读取版本号
|
|
7
|
+
version_file = "version.txt"
|
|
8
|
+
# 可选:将版本写入Python文件供代码使用
|
|
9
|
+
write_to = "qingclient/_version.py"
|
|
10
|
+
# 确保构建时使用文件版本而非Git标签
|
|
11
|
+
local_scheme = "no-local-version"
|
|
12
|
+
# 添加回退机制
|
|
13
|
+
fallback_version = "0.0.0" # 必须存在,但会被version.txt覆盖
|
|
14
|
+
|
|
15
|
+
[tool.setuptools]
|
|
16
|
+
packages = ["qingclient"]
|
|
17
|
+
package-dir = {"" = "."}
|
|
18
|
+
|
|
19
|
+
[project]
|
|
20
|
+
name = "qing-client"
|
|
21
|
+
dynamic = ["version"] # 关键:声明版本为动态获取
|
|
22
|
+
description = "Python client for audit logging services"
|
|
23
|
+
readme = "README.md"
|
|
24
|
+
requires-python = ">=3.7"
|
|
25
|
+
authors = [
|
|
26
|
+
{name = "xiaoyue9527", email = "xiaoyue9527@example.com" },
|
|
27
|
+
]
|
|
28
|
+
license = {text = "MIT"}
|
|
29
|
+
classifiers = [
|
|
30
|
+
"Programming Language :: Python :: 3",
|
|
31
|
+
"License :: OSI Approved :: MIT License",
|
|
32
|
+
"Operating System :: OS Independent",
|
|
33
|
+
]
|
|
34
|
+
keywords = ["audit", "logging", "security", "monitoring"]
|
|
35
|
+
|
|
36
|
+
dependencies = [
|
|
37
|
+
"httpx>=0.23.0",
|
|
38
|
+
"pydantic>=2.0.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
homepage = "https://github.com/yourusername/qing-client"
|
|
43
|
+
"Bug Tracker" = "https://github.com/yourusername/qing-client/issues"
|
|
44
|
+
Documentation = "https://github.com/yourusername/qing-client/wiki"
|
|
45
|
+
|
|
46
|
+
[project.optional-dependencies]
|
|
47
|
+
dev = [
|
|
48
|
+
"pytest>=7.0",
|
|
49
|
+
"pytest-asyncio>=0.20.0",
|
|
50
|
+
"twine>=4.0.0",
|
|
51
|
+
"build>=0.10.0",
|
|
52
|
+
"bumpversion>=0.6.0"
|
|
53
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qing-client
|
|
3
|
+
Version: 0.1.5
|
|
4
|
+
Summary: Python client for audit logging services
|
|
5
|
+
Author-email: xiaoyue9527 <xiaoyue9527@example.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: homepage, https://github.com/yourusername/qing-client
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/yourusername/qing-client/issues
|
|
9
|
+
Project-URL: Documentation, https://github.com/yourusername/qing-client/wiki
|
|
10
|
+
Keywords: audit,logging,security,monitoring
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Requires-Python: >=3.7
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: httpx>=0.23.0
|
|
17
|
+
Requires-Dist: pydantic>=2.0.0
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
20
|
+
Requires-Dist: pytest-asyncio>=0.20.0; extra == "dev"
|
|
21
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
22
|
+
Requires-Dist: build>=0.10.0; extra == "dev"
|
|
23
|
+
Requires-Dist: bumpversion>=0.6.0; extra == "dev"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
pyproject.toml
|
|
2
|
+
setup.py
|
|
3
|
+
./qingclient/_version.py
|
|
4
|
+
./qingclient/auth_service.py
|
|
5
|
+
./qingclient/base_client.py
|
|
6
|
+
./qingclient/init.py
|
|
7
|
+
./qingclient/msg_service.py
|
|
8
|
+
./qingclient/token_service.py
|
|
9
|
+
./qingclient/user_service.py
|
|
10
|
+
qing_client.egg-info/PKG-INFO
|
|
11
|
+
qing_client.egg-info/SOURCES.txt
|
|
12
|
+
qing_client.egg-info/dependency_links.txt
|
|
13
|
+
qing_client.egg-info/requires.txt
|
|
14
|
+
qing_client.egg-info/top_level.txt
|
|
15
|
+
qingclient/_version.py
|
|
16
|
+
qingclient/auth_service.py
|
|
17
|
+
qingclient/base_client.py
|
|
18
|
+
qingclient/init.py
|
|
19
|
+
qingclient/msg_service.py
|
|
20
|
+
qingclient/token_service.py
|
|
21
|
+
qingclient/user_service.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
qingclient
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
17
|
+
|
|
18
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
20
|
+
else:
|
|
21
|
+
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
23
|
+
|
|
24
|
+
version: str
|
|
25
|
+
__version__: str
|
|
26
|
+
__version_tuple__: VERSION_TUPLE
|
|
27
|
+
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
30
|
+
|
|
31
|
+
__version__ = version = '0.1.5'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 1, 5)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from .base_client import BaseClient
|
|
2
|
+
from .types import RequestOptions, LoginResponse
|
|
3
|
+
|
|
4
|
+
class AuthService(BaseClient):
|
|
5
|
+
def __init__(self, config):
|
|
6
|
+
super().__init__(config, 'auth')
|
|
7
|
+
|
|
8
|
+
def login(self, identifier: str, password: str, project_id: int = 0, options: RequestOptions = None) -> LoginResponse:
|
|
9
|
+
body = {
|
|
10
|
+
'grant_type': 'password',
|
|
11
|
+
'username': identifier,
|
|
12
|
+
'password': password
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
headers = {}
|
|
16
|
+
if options and options.headers:
|
|
17
|
+
headers = options.headers.copy()
|
|
18
|
+
headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
19
|
+
|
|
20
|
+
return self.request('/login', RequestOptions(
|
|
21
|
+
method='POST',
|
|
22
|
+
headers=headers,
|
|
23
|
+
params={'project_id': project_id},
|
|
24
|
+
body=body
|
|
25
|
+
))
|
|
26
|
+
|
|
27
|
+
def logout(self, token: str, options: RequestOptions = None):
|
|
28
|
+
headers = {}
|
|
29
|
+
if options and options.headers:
|
|
30
|
+
headers = options.headers.copy()
|
|
31
|
+
headers['Authorization'] = f'Bearer {token}'
|
|
32
|
+
|
|
33
|
+
return self.request('/logout', RequestOptions(
|
|
34
|
+
method='POST',
|
|
35
|
+
headers=headers
|
|
36
|
+
))
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import json
|
|
3
|
+
from typing import Dict, Any, Optional, List
|
|
4
|
+
from .types import UserContext, ClientConfig, RequestOptions, ApiResponse, PaginatedResponse
|
|
5
|
+
|
|
6
|
+
class BaseClient:
|
|
7
|
+
def __init__(self, config: ClientConfig, service_name: str):
|
|
8
|
+
self.config = config
|
|
9
|
+
self.service_name = service_name # 存储为实例变量
|
|
10
|
+
self.user_context = None
|
|
11
|
+
self.token = None
|
|
12
|
+
|
|
13
|
+
# 确定基础URL
|
|
14
|
+
self.base_url = self._get_base_url()
|
|
15
|
+
|
|
16
|
+
# 创建session
|
|
17
|
+
self.session = requests.Session()
|
|
18
|
+
self.session.headers.update({
|
|
19
|
+
'Content-Type': 'application/json',
|
|
20
|
+
'Accept': 'application/json'
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
def _get_base_url(self):
|
|
24
|
+
# 使用 self.service_name 而不是直接访问 service_name
|
|
25
|
+
service_urls = {
|
|
26
|
+
'auth': self.config.auth_service_url,
|
|
27
|
+
'msg': self.config.msg_service_url,
|
|
28
|
+
'users': self.config.user_service_url,
|
|
29
|
+
'file': self.config.file_service_url,
|
|
30
|
+
'survey': self.config.survey_service_url,
|
|
31
|
+
'token': self.config.token_service_url,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# 检查服务名称是否在支持的列表中
|
|
35
|
+
if self.service_name not in service_urls:
|
|
36
|
+
raise ValueError(f"Unsupported service: {self.service_name}")
|
|
37
|
+
|
|
38
|
+
return service_urls[self.service_name]
|
|
39
|
+
|
|
40
|
+
def set_user_context(self, context: UserContext):
|
|
41
|
+
self.user_context = context
|
|
42
|
+
return self
|
|
43
|
+
|
|
44
|
+
def set_token(self, token: str):
|
|
45
|
+
self.token = token
|
|
46
|
+
return self
|
|
47
|
+
|
|
48
|
+
def _init_user_context_headers(self, context: UserContext) -> Dict[str, str]:
|
|
49
|
+
return {
|
|
50
|
+
'v-user-id': context.user_id,
|
|
51
|
+
'v-user-role': context.role,
|
|
52
|
+
'v-project-id': context.project_id
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
def _handle_api_error(self, error, path):
|
|
56
|
+
error_message = f"[{self.service_name}服务] "
|
|
57
|
+
|
|
58
|
+
if hasattr(error, 'response') and error.response is not None:
|
|
59
|
+
response = error.response
|
|
60
|
+
try:
|
|
61
|
+
response_data = response.json()
|
|
62
|
+
if 'message' in response_data:
|
|
63
|
+
error_message += response_data['message']
|
|
64
|
+
elif 'error' in response_data:
|
|
65
|
+
error_message += response_data['error']
|
|
66
|
+
else:
|
|
67
|
+
error_message += f"请求失败,状态码: {response.status_code}"
|
|
68
|
+
except:
|
|
69
|
+
error_message += f"请求失败,状态码: {response.status_code}"
|
|
70
|
+
|
|
71
|
+
# 添加详细错误信息
|
|
72
|
+
error_message += f" | 状态码: {response.status_code}"
|
|
73
|
+
if 'x-request-id' in response.headers:
|
|
74
|
+
error_message += f" | 请求ID: {response.headers['x-request-id']}"
|
|
75
|
+
else:
|
|
76
|
+
error_message += str(error)
|
|
77
|
+
|
|
78
|
+
# 添加路径信息
|
|
79
|
+
error_message += f" (路径: {path})"
|
|
80
|
+
|
|
81
|
+
raise Exception(error_message)
|
|
82
|
+
|
|
83
|
+
def request(self, path: str, options: RequestOptions = None) -> Any:
|
|
84
|
+
if options is None:
|
|
85
|
+
options = RequestOptions(method='GET')
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
url = f"{self.base_url}{path}"
|
|
89
|
+
|
|
90
|
+
# 准备请求参数
|
|
91
|
+
headers = options.headers.copy() if options.headers else {}
|
|
92
|
+
|
|
93
|
+
# 添加用户上下文
|
|
94
|
+
context = options.user_context or self.user_context
|
|
95
|
+
if context:
|
|
96
|
+
headers.update(self._init_user_context_headers(context))
|
|
97
|
+
|
|
98
|
+
# 添加认证令牌
|
|
99
|
+
if self.token:
|
|
100
|
+
headers['Authorization'] = f"Bearer {self.token}"
|
|
101
|
+
|
|
102
|
+
# 发送请求
|
|
103
|
+
response = self.session.request(
|
|
104
|
+
method=options.method,
|
|
105
|
+
url=url,
|
|
106
|
+
headers=headers,
|
|
107
|
+
params=options.params,
|
|
108
|
+
json=options.body,
|
|
109
|
+
timeout=30
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# 检查HTTP状态
|
|
113
|
+
response.raise_for_status()
|
|
114
|
+
|
|
115
|
+
# 解析响应
|
|
116
|
+
response_data = response.json()
|
|
117
|
+
|
|
118
|
+
# 检查业务成功状态
|
|
119
|
+
if not response_data.get('success', False):
|
|
120
|
+
raise Exception(response_data.get('message', '业务请求失败'))
|
|
121
|
+
|
|
122
|
+
# 返回实际数据
|
|
123
|
+
return response_data.get('data')
|
|
124
|
+
|
|
125
|
+
except Exception as error:
|
|
126
|
+
self._handle_api_error(error, path)
|
|
127
|
+
|
|
128
|
+
def paginated_request(self, path: str, options: RequestOptions = None) -> PaginatedResponse:
|
|
129
|
+
if options is None:
|
|
130
|
+
options = RequestOptions(method='GET')
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
url = f"{self.base_url}{path}"
|
|
134
|
+
|
|
135
|
+
# 准备请求参数
|
|
136
|
+
headers = options.headers.copy() if options.headers else {}
|
|
137
|
+
|
|
138
|
+
# 添加用户上下文
|
|
139
|
+
context = options.user_context or self.user_context
|
|
140
|
+
if context:
|
|
141
|
+
headers.update(self._init_user_context_headers(context))
|
|
142
|
+
|
|
143
|
+
# 添加认证令牌
|
|
144
|
+
if self.token:
|
|
145
|
+
headers['Authorization'] = f"Bearer {self.token}"
|
|
146
|
+
|
|
147
|
+
# 发送请求
|
|
148
|
+
response = self.session.request(
|
|
149
|
+
method=options.method,
|
|
150
|
+
url=url,
|
|
151
|
+
headers=headers,
|
|
152
|
+
params=options.params,
|
|
153
|
+
json=options.body,
|
|
154
|
+
timeout=30
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# 检查HTTP状态
|
|
158
|
+
response.raise_for_status()
|
|
159
|
+
|
|
160
|
+
# 解析响应
|
|
161
|
+
response_data = response.json()
|
|
162
|
+
|
|
163
|
+
# 检查业务成功状态
|
|
164
|
+
if not response_data.get('success', False):
|
|
165
|
+
raise Exception(response_data.get('message', '业务请求失败'))
|
|
166
|
+
|
|
167
|
+
# 返回分页响应
|
|
168
|
+
return PaginatedResponse(
|
|
169
|
+
data=response_data.get('data', []),
|
|
170
|
+
success=response_data.get('success', False),
|
|
171
|
+
message=response_data.get('message', ''),
|
|
172
|
+
pagination=response_data.get('pagination', {})
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
except Exception as error:
|
|
176
|
+
self._handle_api_error(error, path)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from .auth_service import AuthService
|
|
2
|
+
from .msg_service import MsgService
|
|
3
|
+
from .token_service import TokenService
|
|
4
|
+
from .user_service import UserService
|
|
5
|
+
from .base_client import BaseClient
|
|
6
|
+
from .types import *
|
|
7
|
+
|
|
8
|
+
class QingClient:
|
|
9
|
+
def __init__(self, config):
|
|
10
|
+
self.config = config
|
|
11
|
+
self.auth = AuthService(config)
|
|
12
|
+
self.msg = MsgService(config)
|
|
13
|
+
self.token = TokenService(config)
|
|
14
|
+
self.user = UserService(config)
|
|
15
|
+
|
|
16
|
+
def set_user_context(self, context):
|
|
17
|
+
self.auth.set_user_context(context)
|
|
18
|
+
self.msg.set_user_context(context)
|
|
19
|
+
self.token.set_user_context(context)
|
|
20
|
+
self.user.set_user_context(context)
|
|
21
|
+
return self
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from .base_client import BaseClient
|
|
2
|
+
from .types import RequestOptions, MailRequest, FeishuMessage
|
|
3
|
+
|
|
4
|
+
class MsgService(BaseClient):
|
|
5
|
+
def __init__(self, config):
|
|
6
|
+
super().__init__(config, 'msg')
|
|
7
|
+
|
|
8
|
+
def send_mail(self, request: MailRequest, options: RequestOptions = None):
|
|
9
|
+
return self.request('/mail/send', RequestOptions(
|
|
10
|
+
method='POST',
|
|
11
|
+
body=request,
|
|
12
|
+
headers=options.headers if options else None
|
|
13
|
+
))
|
|
14
|
+
|
|
15
|
+
def send_feishu_message(self, message: FeishuMessage, options: RequestOptions = None):
|
|
16
|
+
return self.request('/webhook/feishu/send', RequestOptions(
|
|
17
|
+
method='POST',
|
|
18
|
+
body=message,
|
|
19
|
+
headers=options.headers if options else None
|
|
20
|
+
))
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from .base_client import BaseClient
|
|
2
|
+
from .types import RequestOptions, WxOfficialAccountTokenResponse, WxJsapiTicketResponse, WxSignatureRequest, WxSignatureResponse, WxMiniProgramTokenResponse
|
|
3
|
+
|
|
4
|
+
class TokenService(BaseClient):
|
|
5
|
+
def __init__(self, config):
|
|
6
|
+
super().__init__(config, 'token')
|
|
7
|
+
|
|
8
|
+
def get_wx_official_account_token(self, appid: str, options: RequestOptions = None) -> WxOfficialAccountTokenResponse:
|
|
9
|
+
return self.request('/wxh5/accesstoken', RequestOptions(
|
|
10
|
+
method='GET',
|
|
11
|
+
params={'appid': appid},
|
|
12
|
+
headers=options.headers if options else None
|
|
13
|
+
))
|
|
14
|
+
|
|
15
|
+
def get_wx_jsapi_ticket(self, appid: str, options: RequestOptions = None) -> WxJsapiTicketResponse:
|
|
16
|
+
return self.request('/wxh5/jsapi_ticket', RequestOptions(
|
|
17
|
+
method='GET',
|
|
18
|
+
params={'appid': appid},
|
|
19
|
+
headers=options.headers if options else None
|
|
20
|
+
))
|
|
21
|
+
|
|
22
|
+
def get_wx_signature(self, signature_request: WxSignatureRequest, options: RequestOptions = None) -> WxSignatureResponse:
|
|
23
|
+
return self.request('/wxh5/signature', RequestOptions(
|
|
24
|
+
method='POST',
|
|
25
|
+
body=signature_request,
|
|
26
|
+
headers=options.headers if options else None
|
|
27
|
+
))
|
|
28
|
+
|
|
29
|
+
def get_wx_mini_program_token(self, appid: str, options: RequestOptions = None) -> WxMiniProgramTokenResponse:
|
|
30
|
+
return self.request('/wxmp/accesstoken', RequestOptions(
|
|
31
|
+
method='GET',
|
|
32
|
+
params={'appid': appid},
|
|
33
|
+
headers=options.headers if options else None
|
|
34
|
+
))
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from .base_client import BaseClient
|
|
2
|
+
from .types import RequestOptions, PaginatedResponse, User, UserCreateRequest, UserUpdateRequest
|
|
3
|
+
|
|
4
|
+
class UserService(BaseClient):
|
|
5
|
+
def __init__(self, config):
|
|
6
|
+
super().__init__(config, 'users')
|
|
7
|
+
|
|
8
|
+
def get_current_user(self, options: RequestOptions = None) -> User:
|
|
9
|
+
return self.request('/me', RequestOptions(
|
|
10
|
+
method='GET',
|
|
11
|
+
headers=options.headers if options else None
|
|
12
|
+
))
|
|
13
|
+
|
|
14
|
+
def create_user(self, user_data: UserCreateRequest, options: RequestOptions = None) -> User:
|
|
15
|
+
return self.request('', RequestOptions(
|
|
16
|
+
method='POST',
|
|
17
|
+
body={
|
|
18
|
+
'username': user_data.username,
|
|
19
|
+
'email': user_data.email,
|
|
20
|
+
'password': user_data.password,
|
|
21
|
+
'name': user_data.name,
|
|
22
|
+
'role': user_data.role,
|
|
23
|
+
'phone': user_data.phone,
|
|
24
|
+
'project_id': user_data.project_id
|
|
25
|
+
},
|
|
26
|
+
headers=options.headers if options else None
|
|
27
|
+
))
|
|
28
|
+
|
|
29
|
+
def update_user(self, user_id: int, update_data: UserUpdateRequest, options: RequestOptions = None) -> User:
|
|
30
|
+
return self.request(f'/{user_id}', RequestOptions(
|
|
31
|
+
method='PUT',
|
|
32
|
+
body={
|
|
33
|
+
'name': update_data.name,
|
|
34
|
+
'avatar': update_data.avatar,
|
|
35
|
+
'phone': update_data.phone,
|
|
36
|
+
'role': update_data.role,
|
|
37
|
+
'project_id': update_data.project_id
|
|
38
|
+
},
|
|
39
|
+
headers=options.headers if options else None
|
|
40
|
+
))
|
|
41
|
+
|
|
42
|
+
def list_users(self, include_inactive: bool = False, page: int = 1, per_page: int = 10, options: RequestOptions = None) -> PaginatedResponse[User]:
|
|
43
|
+
return self.paginated_request('', RequestOptions(
|
|
44
|
+
method='GET',
|
|
45
|
+
params={
|
|
46
|
+
'include_inactive': include_inactive,
|
|
47
|
+
'page': page,
|
|
48
|
+
'per_page': per_page
|
|
49
|
+
},
|
|
50
|
+
headers=options.headers if options else None
|
|
51
|
+
))
|