arpakitlib 1.8.19__py3-none-any.whl → 1.8.20__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.
- arpakitlib/_arpakit_project_template_v_5/project/api/auth.py +136 -211
- arpakitlib/_arpakit_project_template_v_5/project/api/exception_handler.py +1 -2
- arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_arpakitlib_project_template_info.py +7 -1
- arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_auth_data.py +6 -8
- arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/main_router.py +17 -0
- arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/raise_fake_error.py +27 -0
- arpakitlib/_arpakit_project_template_v_5/project/api/router/client/get_errors_info.py +4 -8
- arpakitlib/_arpakit_project_template_v_5/project/api/router/client/main_router.py +7 -0
- arpakitlib/_arpakit_project_template_v_5/project/api/router/general/main_router.py +5 -1
- arpakitlib/_arpakit_project_template_v_5/project/api/router/{client → general}/now_utc_datetime.py +1 -1
- arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/admin/user.py +1 -1
- arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/admin/user_token.py +1 -1
- arpakitlib/_arpakit_project_template_v_5/project/core/settings.py +3 -17
- arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/api_key.py +1 -1
- arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/user.py +1 -1
- arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/user_token.py +1 -1
- arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_api_keys.py +35 -0
- arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_1.py +4 -2
- arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_2.py +4 -2
- arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_3.py +4 -2
- arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_4.py +4 -2
- arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_5.py +4 -2
- {arpakitlib-1.8.19.dist-info → arpakitlib-1.8.20.dist-info}/METADATA +1 -1
- {arpakitlib-1.8.19.dist-info → arpakitlib-1.8.20.dist-info}/RECORD +27 -26
- arpakitlib/_arpakit_project_template_v_5/project/api/auth2.py +0 -218
- {arpakitlib-1.8.19.dist-info → arpakitlib-1.8.20.dist-info}/LICENSE +0 -0
- {arpakitlib-1.8.19.dist-info → arpakitlib-1.8.20.dist-info}/WHEEL +0 -0
- {arpakitlib-1.8.19.dist-info → arpakitlib-1.8.20.dist-info}/entry_points.txt +0 -0
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
import functools
|
2
|
+
from typing import Callable, Any
|
2
3
|
|
3
4
|
import fastapi
|
4
5
|
import fastapi.exceptions
|
@@ -8,10 +9,10 @@ import sqlalchemy
|
|
8
9
|
from fastapi import Security
|
9
10
|
from fastapi.security import APIKeyHeader
|
10
11
|
from pydantic import BaseModel, ConfigDict
|
12
|
+
from sqlalchemy.orm import joinedload
|
11
13
|
|
12
14
|
from arpakitlib.ar_func_util import is_async_func, is_sync_func
|
13
15
|
from arpakitlib.ar_json_util import transfer_data_to_json_str_to_data
|
14
|
-
from arpakitlib.ar_type_util import raise_for_type
|
15
16
|
from project.api.const import APIErrorCodes
|
16
17
|
from project.api.exception import APIException
|
17
18
|
from project.core.settings import get_cached_settings
|
@@ -22,70 +23,27 @@ from project.sqlalchemy_db_.sqlalchemy_model import ApiKeyDBM, UserTokenDBM
|
|
22
23
|
class APIAuthData(BaseModel):
|
23
24
|
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True, from_attributes=True)
|
24
25
|
|
25
|
-
require_api_key_string: bool = False
|
26
|
-
require_user_token_string: bool = False
|
27
|
-
|
28
|
-
require_correct_api_key: bool = False
|
29
|
-
require_correct_user_token: bool = False
|
30
|
-
|
31
|
-
require_mode_type: str | None = None
|
32
|
-
require_not_mode_type: str | None = None
|
33
|
-
|
34
|
-
current_mode_type: str | None = None
|
35
|
-
|
36
26
|
api_key_string: str | None = None
|
37
27
|
user_token_string: str | None = None
|
38
28
|
|
39
29
|
is_api_key_correct: bool | None = None
|
40
|
-
is_user_token_correct: bool | None = None
|
41
30
|
|
42
31
|
api_key_dbm: ApiKeyDBM | None = None
|
43
32
|
user_token_dbm: UserTokenDBM | None = None
|
44
33
|
|
34
|
+
prod_mode: bool = False
|
45
35
|
|
46
|
-
|
47
|
-
*,
|
48
|
-
require_api_key_string: bool = False,
|
49
|
-
require_user_token_string: bool = False,
|
50
|
-
|
51
|
-
require_correct_api_key: bool = False,
|
52
|
-
require_correct_user_token: bool = False,
|
36
|
+
extra_data: dict[str, Any] = {}
|
53
37
|
|
54
|
-
require_mode_type: str | None = None,
|
55
|
-
require_not_mode_type: str | None = None,
|
56
38
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
correct_user_tokens: str | list[str] | None = None,
|
39
|
+
def api_auth(
|
40
|
+
*,
|
41
|
+
middlewares: list[Callable] | None = None
|
61
42
|
) -> Callable:
|
62
|
-
if
|
63
|
-
|
64
|
-
if correct_api_keys is not None:
|
65
|
-
raise_for_type(correct_api_keys, list)
|
66
|
-
|
67
|
-
if is_api_key_correct_func is None and correct_api_keys is not None:
|
68
|
-
is_api_key_correct_func = (
|
69
|
-
lambda *args, **kwargs_: kwargs_["api_auth_data"].api_key_string in correct_api_keys
|
70
|
-
)
|
71
|
-
|
72
|
-
if isinstance(correct_user_tokens, str):
|
73
|
-
correct_user_tokens = [correct_user_tokens]
|
74
|
-
if correct_user_tokens is not None:
|
75
|
-
raise_for_type(correct_user_tokens, list)
|
76
|
-
|
77
|
-
if is_user_token_correct_func is None and correct_user_tokens is not None:
|
78
|
-
is_user_token_correct_func = (
|
79
|
-
lambda *args, **kwargs_: kwargs_["api_auth_data"].user_token_string in correct_user_tokens
|
80
|
-
)
|
81
|
-
|
82
|
-
if require_correct_api_key is True:
|
83
|
-
require_api_key_string = True
|
43
|
+
if middlewares is None:
|
44
|
+
middlewares = []
|
84
45
|
|
85
|
-
|
86
|
-
require_user_token_string = True
|
87
|
-
|
88
|
-
async def func(
|
46
|
+
async def async_func(
|
89
47
|
*,
|
90
48
|
ac: fastapi.security.HTTPAuthorizationCredentials | None = fastapi.Security(
|
91
49
|
fastapi.security.HTTPBearer(auto_error=False)
|
@@ -97,16 +55,10 @@ def api_auth(
|
|
97
55
|
) -> APIAuthData:
|
98
56
|
|
99
57
|
api_auth_data = APIAuthData(
|
100
|
-
|
101
|
-
require_user_token_string=require_user_token_string,
|
102
|
-
require_correct_api_key=require_correct_api_key,
|
103
|
-
require_correct_user_token=require_correct_user_token,
|
104
|
-
require_mode_type=require_mode_type,
|
105
|
-
require_not_mode_type=require_not_mode_type,
|
106
|
-
current_mode_type=get_cached_settings().mode_type
|
58
|
+
prod_mode=get_cached_settings().prod_mode
|
107
59
|
)
|
108
60
|
|
109
|
-
# parse
|
61
|
+
# parse api_key_string
|
110
62
|
|
111
63
|
api_auth_data.api_key_string = api_key_string
|
112
64
|
|
@@ -116,6 +68,8 @@ def api_auth(
|
|
116
68
|
api_auth_data.api_key_string = request.headers["api-key"]
|
117
69
|
if not api_auth_data.api_key_string and "apikey" in request.headers.keys():
|
118
70
|
api_auth_data.api_key_string = request.headers["apikey"]
|
71
|
+
if not api_auth_data.api_key_string and "api_key_string" in request.headers.keys():
|
72
|
+
api_auth_data.api_key_string = request.headers["api_key_string"]
|
119
73
|
|
120
74
|
if not api_auth_data.api_key_string and "api_key" in request.query_params.keys():
|
121
75
|
api_auth_data.api_key_string = request.query_params["api_key"]
|
@@ -123,13 +77,15 @@ def api_auth(
|
|
123
77
|
api_auth_data.api_key_string = request.query_params["api-key"]
|
124
78
|
if not api_auth_data.api_key_string and "apikey" in request.query_params.keys():
|
125
79
|
api_auth_data.api_key_string = request.query_params["apikey"]
|
80
|
+
if not api_auth_data.api_key_string and "api_key_string" in request.query_params.keys():
|
81
|
+
api_auth_data.api_key_string = request.query_params["api_key_string"]
|
126
82
|
|
127
83
|
if api_auth_data.api_key_string:
|
128
84
|
api_auth_data.api_key_string = api_auth_data.api_key_string.strip()
|
129
85
|
if not api_auth_data.api_key_string:
|
130
86
|
api_auth_data.api_key_string = None
|
131
87
|
|
132
|
-
# parse
|
88
|
+
# parse user_token_string
|
133
89
|
|
134
90
|
api_auth_data.user_token_string = ac.credentials if ac and ac.credentials and ac.credentials.strip() else None
|
135
91
|
|
@@ -158,196 +114,165 @@ def api_auth(
|
|
158
114
|
if not api_auth_data.user_token_string:
|
159
115
|
api_auth_data.user_token_string = None
|
160
116
|
|
161
|
-
#
|
117
|
+
# is_api_key_correct
|
162
118
|
|
163
|
-
if
|
164
|
-
if get_cached_settings().
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
169
|
-
)
|
119
|
+
if api_auth_data.api_key_string is not None:
|
120
|
+
if get_cached_settings().api_correct_api_keys is None:
|
121
|
+
api_auth_data.is_api_key_correct = None
|
122
|
+
else:
|
123
|
+
api_auth_data.is_api_key_correct = api_auth_data.api_key_string in get_cached_settings().api_correct_api_keys
|
170
124
|
|
171
|
-
#
|
125
|
+
# api_key_dbm
|
172
126
|
|
173
|
-
if
|
174
|
-
if
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
)
|
127
|
+
if api_auth_data.api_key_string is not None:
|
128
|
+
if get_cached_sqlalchemy_db() is not None:
|
129
|
+
async with get_cached_sqlalchemy_db().new_async_session() as async_session:
|
130
|
+
api_auth_data.api_key_dbm = await async_session.scalar(
|
131
|
+
sqlalchemy.select(ApiKeyDBM).where(ApiKeyDBM.value == api_auth_data.api_key_string)
|
132
|
+
)
|
180
133
|
|
181
|
-
#
|
134
|
+
# user_token_dbm
|
182
135
|
|
183
|
-
if
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
136
|
+
if api_auth_data.api_key_string is not None:
|
137
|
+
if get_cached_sqlalchemy_db() is not None:
|
138
|
+
async with get_cached_sqlalchemy_db().new_async_session() as async_session:
|
139
|
+
api_auth_data.user_token_dbm = await async_session.scalar(
|
140
|
+
sqlalchemy.select(UserTokenDBM)
|
141
|
+
.options(joinedload(UserTokenDBM.user))
|
142
|
+
.where(UserTokenDBM.value == api_auth_data.user_token_string)
|
143
|
+
)
|
189
144
|
|
190
|
-
#
|
191
|
-
|
192
|
-
if require_user_token_string and not api_auth_data.user_token_string:
|
193
|
-
raise APIException(
|
194
|
-
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
195
|
-
error_code=APIErrorCodes.cannot_authorize,
|
196
|
-
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
197
|
-
)
|
145
|
+
# middlewares
|
198
146
|
|
199
|
-
|
147
|
+
for middleware in middlewares:
|
148
|
+
api_auth_data.extra_data[middleware.__name__] = True
|
200
149
|
|
201
|
-
|
202
|
-
if is_async_func(
|
203
|
-
await
|
150
|
+
for middleware in middlewares:
|
151
|
+
if is_async_func(middleware):
|
152
|
+
await middleware(
|
204
153
|
api_auth_data=api_auth_data,
|
205
154
|
request=request
|
206
155
|
)
|
207
|
-
elif is_sync_func(
|
208
|
-
|
156
|
+
elif is_sync_func(middleware):
|
157
|
+
middleware(
|
209
158
|
api_auth_data=api_auth_data,
|
210
159
|
request=request
|
211
160
|
)
|
212
161
|
else:
|
213
|
-
raise TypeError("unknown
|
162
|
+
raise TypeError(f"unknown middleware type, {middleware.__name__}")
|
214
163
|
|
215
|
-
|
164
|
+
return api_auth_data
|
216
165
|
|
217
|
-
|
218
|
-
if is_async_func(is_user_token_correct_func):
|
219
|
-
await is_user_token_correct_func(
|
220
|
-
api_auth_data=api_auth_data,
|
221
|
-
request=request
|
222
|
-
)
|
223
|
-
elif is_sync_func(is_user_token_correct_func):
|
224
|
-
is_user_token_correct_func(
|
225
|
-
api_auth_data=api_auth_data,
|
226
|
-
request=request
|
227
|
-
)
|
228
|
-
else:
|
229
|
-
raise TypeError("unknown validate_token_func type")
|
166
|
+
return async_func
|
230
167
|
|
231
|
-
# require_correct_api_key
|
232
168
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
)
|
169
|
+
def require_prod_mode_api_middleware():
|
170
|
+
@functools.wraps(require_prod_mode_api_middleware)
|
171
|
+
def func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
172
|
+
if not get_cached_settings().prod_mode:
|
173
|
+
raise APIException(
|
174
|
+
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
175
|
+
error_code=APIErrorCodes.cannot_authorize,
|
176
|
+
error_description=f"prod_mode={get_cached_settings().prod_mode}",
|
177
|
+
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
178
|
+
)
|
241
179
|
|
242
|
-
|
180
|
+
return func
|
243
181
|
|
244
|
-
if require_correct_user_token:
|
245
|
-
if not api_auth_data.is_user_token_correct:
|
246
|
-
raise APIException(
|
247
|
-
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
248
|
-
error_code=APIErrorCodes.cannot_authorize,
|
249
|
-
error_description="not api_auth_data.is_user_token_correct",
|
250
|
-
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
251
|
-
)
|
252
182
|
|
253
|
-
|
183
|
+
def require_not_prod_mode_api_middleware():
|
184
|
+
@functools.wraps(require_not_prod_mode_api_middleware)
|
185
|
+
def func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
186
|
+
if get_cached_settings().prod_mode:
|
187
|
+
raise APIException(
|
188
|
+
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
189
|
+
error_code=APIErrorCodes.cannot_authorize,
|
190
|
+
error_description=f"prod_mode={get_cached_settings().prod_mode}",
|
191
|
+
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
192
|
+
)
|
254
193
|
|
255
194
|
return func
|
256
195
|
|
257
196
|
|
258
|
-
def
|
259
|
-
|
260
|
-
|
261
|
-
api_auth_data: APIAuthData,
|
262
|
-
request: fastapi.requests.Request,
|
263
|
-
):
|
264
|
-
if get_cached_settings().api_correct_api_keys is None:
|
265
|
-
api_auth_data.is_api_key_correct = False
|
266
|
-
return
|
197
|
+
def require_api_key_string_api_middleware():
|
198
|
+
@functools.wraps(require_api_key_string_api_middleware)
|
199
|
+
def func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
267
200
|
if api_auth_data.api_key_string is None:
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
return
|
201
|
+
raise APIException(
|
202
|
+
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
203
|
+
error_code=APIErrorCodes.cannot_authorize,
|
204
|
+
error_description="api_key_string is required",
|
205
|
+
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
206
|
+
)
|
275
207
|
|
276
|
-
return
|
208
|
+
return func
|
277
209
|
|
278
210
|
|
279
|
-
def
|
280
|
-
|
281
|
-
|
282
|
-
api_auth_data: APIAuthData,
|
283
|
-
request: fastapi.requests.Request,
|
284
|
-
):
|
285
|
-
if get_cached_settings().api_correct_tokens is None:
|
286
|
-
api_auth_data.is_api_key_correct = False
|
287
|
-
return
|
211
|
+
def require_user_token_string_api_middleware():
|
212
|
+
@functools.wraps(require_user_token_string_api_middleware)
|
213
|
+
def func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
288
214
|
if api_auth_data.user_token_string is None:
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
return
|
296
|
-
|
297
|
-
return async_func
|
215
|
+
raise APIException(
|
216
|
+
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
217
|
+
error_code=APIErrorCodes.cannot_authorize,
|
218
|
+
error_description="user_token_string is required",
|
219
|
+
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
220
|
+
)
|
298
221
|
|
222
|
+
return func
|
299
223
|
|
300
|
-
def correct_api_key_from_sqlalchemy_db__is_api_key_correct_func() -> Callable:
|
301
|
-
async def async_func(
|
302
|
-
*,
|
303
|
-
api_auth_data: APIAuthData,
|
304
|
-
request: fastapi.requests.Request,
|
305
|
-
):
|
306
|
-
if api_auth_data.api_key_string is None:
|
307
|
-
api_auth_data.is_api_key_correct = False
|
308
|
-
return
|
309
224
|
|
310
|
-
|
311
|
-
|
312
|
-
|
225
|
+
def require_correct_api_key_dbm_api_middleware():
|
226
|
+
@functools.wraps(require_correct_api_key_dbm_api_middleware)
|
227
|
+
def func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
228
|
+
if not api_auth_data.is_api_key_correct:
|
229
|
+
raise APIException(
|
230
|
+
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
231
|
+
error_code=APIErrorCodes.cannot_authorize,
|
232
|
+
error_description="api_key_string is not correct",
|
233
|
+
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
313
234
|
)
|
314
235
|
|
315
|
-
|
316
|
-
api_auth_data.is_api_key_correct = False
|
317
|
-
return
|
318
|
-
|
319
|
-
api_auth_data.is_api_key_correct = True
|
320
|
-
return True
|
236
|
+
return func
|
321
237
|
|
322
|
-
return async_func
|
323
238
|
|
239
|
+
def require_api_key_dbm_api_middleware(*, require_active: bool = True):
|
240
|
+
@functools.wraps(require_api_key_dbm_api_middleware)
|
241
|
+
async def async_func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
242
|
+
if api_auth_data.api_key_dbm is None:
|
243
|
+
raise APIException(
|
244
|
+
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
245
|
+
error_code=APIErrorCodes.cannot_authorize,
|
246
|
+
error_description="api_key_dbm is required",
|
247
|
+
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
248
|
+
)
|
249
|
+
if require_active and not api_auth_data.api_key_dbm.is_active:
|
250
|
+
raise APIException(
|
251
|
+
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
252
|
+
error_code=APIErrorCodes.cannot_authorize,
|
253
|
+
error_description="api_key_dbm is not active",
|
254
|
+
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
255
|
+
)
|
324
256
|
|
325
|
-
|
326
|
-
*, require_user_roles: list[str] | None = None
|
327
|
-
) -> Callable:
|
328
|
-
async def async_func(
|
329
|
-
*,
|
330
|
-
api_auth_data: APIAuthData,
|
331
|
-
request: fastapi.requests.Request,
|
332
|
-
):
|
333
|
-
if api_auth_data.user_token_string is None:
|
334
|
-
api_auth_data.is_user_token_correct = False
|
335
|
-
return
|
257
|
+
return async_func
|
336
258
|
|
337
|
-
with get_cached_sqlalchemy_db().new_session() as session:
|
338
|
-
api_auth_data.user_token_dbm = session.query(
|
339
|
-
UserTokenDBM
|
340
|
-
).filter(
|
341
|
-
UserTokenDBM.value == api_auth_data.user_token_string
|
342
|
-
).one_or_none()
|
343
259
|
|
260
|
+
def require_user_token_dbm_api_middleware(*, require_active: bool = True):
|
261
|
+
@functools.wraps(require_user_token_dbm_api_middleware)
|
262
|
+
async def async_func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
344
263
|
if api_auth_data.user_token_dbm is None:
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
264
|
+
raise APIException(
|
265
|
+
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
266
|
+
error_code=APIErrorCodes.cannot_authorize,
|
267
|
+
error_description="user_key_dbm is required",
|
268
|
+
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
269
|
+
)
|
270
|
+
if require_active and not api_auth_data.user_token_dbm.is_active:
|
271
|
+
raise APIException(
|
272
|
+
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
273
|
+
error_code=APIErrorCodes.cannot_authorize,
|
274
|
+
error_description="user_key_dbm is not active",
|
275
|
+
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
276
|
+
)
|
352
277
|
|
353
278
|
return async_func
|
@@ -11,7 +11,6 @@ from arpakitlib.ar_datetime_util import now_utc_dt
|
|
11
11
|
from arpakitlib.ar_dict_util import combine_dicts
|
12
12
|
from arpakitlib.ar_exception_util import exception_to_traceback_str
|
13
13
|
from arpakitlib.ar_func_util import raise_if_not_async_func, is_async_func, is_sync_func
|
14
|
-
from arpakitlib.ar_json_util import transfer_data_to_json_str
|
15
14
|
from project.api.const import APIErrorCodes
|
16
15
|
from project.api.exception import APIException
|
17
16
|
from project.api.response import APIJSONResponse
|
@@ -175,7 +174,7 @@ def logging_func_before_in_api_exception_handler(
|
|
175
174
|
):
|
176
175
|
return
|
177
176
|
|
178
|
-
_logger.
|
177
|
+
_logger.exception(exception)
|
179
178
|
|
180
179
|
return func
|
181
180
|
|
@@ -1,6 +1,8 @@
|
|
1
1
|
import fastapi
|
2
2
|
from fastapi import APIRouter
|
3
3
|
|
4
|
+
from project.api.auth import require_user_token_dbm_api_middleware, require_api_key_dbm_api_middleware, APIAuthData, \
|
5
|
+
api_auth
|
4
6
|
from project.api.schema.out.common.error import ErrorCommonSO
|
5
7
|
from project.api.schema.out.common.raw_data import RawDataCommonSO
|
6
8
|
from project.util.arpakitlib_project_template import get_arpakitlib_project_template_info
|
@@ -17,7 +19,11 @@ api_router = APIRouter()
|
|
17
19
|
async def _(
|
18
20
|
*,
|
19
21
|
request: fastapi.requests.Request,
|
20
|
-
response: fastapi.responses.Response
|
22
|
+
response: fastapi.responses.Response,
|
23
|
+
api_auth_data: APIAuthData = fastapi.Depends(api_auth(middlewares=[
|
24
|
+
require_api_key_dbm_api_middleware(require_active=True),
|
25
|
+
require_user_token_dbm_api_middleware(require_active=True)
|
26
|
+
]))
|
21
27
|
):
|
22
28
|
arpakitlib_project_template_data = get_arpakitlib_project_template_info()
|
23
29
|
return RawDataCommonSO(data=arpakitlib_project_template_data)
|
@@ -2,7 +2,8 @@ import fastapi.requests
|
|
2
2
|
from fastapi import APIRouter
|
3
3
|
|
4
4
|
from arpakitlib.ar_json_util import transfer_data_to_json_str_to_data
|
5
|
-
from project.api.auth import APIAuthData, api_auth
|
5
|
+
from project.api.auth import APIAuthData, api_auth, require_user_token_dbm_api_middleware, \
|
6
|
+
require_api_key_dbm_api_middleware
|
6
7
|
from project.api.schema.out.common.error import ErrorCommonSO
|
7
8
|
from project.api.schema.out.common.raw_data import RawDataCommonSO
|
8
9
|
|
@@ -19,12 +20,9 @@ async def _(
|
|
19
20
|
*,
|
20
21
|
request: fastapi.requests.Request,
|
21
22
|
response: fastapi.responses.Response,
|
22
|
-
api_auth_data: APIAuthData = fastapi.Depends(api_auth(
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
require_api_key_dbm_from_sqlalchemy_db=True,
|
27
|
-
require_user_token_dbm_from_sqlalchemy_db=True
|
28
|
-
))
|
23
|
+
api_auth_data: APIAuthData = fastapi.Depends(api_auth(middlewares=[
|
24
|
+
require_api_key_dbm_api_middleware(require_active=True),
|
25
|
+
require_user_token_dbm_api_middleware(require_active=True)
|
26
|
+
]))
|
29
27
|
):
|
30
28
|
return RawDataCommonSO(data=transfer_data_to_json_str_to_data(api_auth_data.model_dump()))
|
@@ -1,3 +1,20 @@
|
|
1
1
|
from fastapi import APIRouter
|
2
2
|
|
3
|
+
from project.api.router.admin import get_auth_data, get_arpakitlib_project_template_info, raise_fake_error
|
4
|
+
|
3
5
|
main_admin_api_router = APIRouter()
|
6
|
+
|
7
|
+
main_admin_api_router.include_router(
|
8
|
+
router=get_arpakitlib_project_template_info.api_router,
|
9
|
+
prefix="/get_arpakitlib_project_template_info"
|
10
|
+
)
|
11
|
+
|
12
|
+
main_admin_api_router.include_router(
|
13
|
+
router=get_auth_data.api_router,
|
14
|
+
prefix="/get_auth_data"
|
15
|
+
)
|
16
|
+
|
17
|
+
main_admin_api_router.include_router(
|
18
|
+
router=raise_fake_error.api_router,
|
19
|
+
prefix="/raise_fake_error"
|
20
|
+
)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import fastapi.requests
|
2
|
+
from fastapi import APIRouter
|
3
|
+
|
4
|
+
from project.api.auth import APIAuthData, api_auth, require_user_token_dbm_api_middleware, \
|
5
|
+
require_api_key_dbm_api_middleware
|
6
|
+
from project.api.schema.out.common.error import ErrorCommonSO
|
7
|
+
from project.api.schema.out.common.raw_data import RawDataCommonSO
|
8
|
+
|
9
|
+
api_router = APIRouter()
|
10
|
+
|
11
|
+
|
12
|
+
@api_router.get(
|
13
|
+
path="",
|
14
|
+
name="Raise fake error",
|
15
|
+
status_code=fastapi.status.HTTP_200_OK,
|
16
|
+
response_model=RawDataCommonSO | ErrorCommonSO,
|
17
|
+
)
|
18
|
+
async def _(
|
19
|
+
*,
|
20
|
+
request: fastapi.requests.Request,
|
21
|
+
response: fastapi.responses.Response,
|
22
|
+
api_auth_data: APIAuthData = fastapi.Depends(api_auth(middlewares=[
|
23
|
+
require_api_key_dbm_api_middleware(require_active=True),
|
24
|
+
require_user_token_dbm_api_middleware(require_active=True)
|
25
|
+
]))
|
26
|
+
):
|
27
|
+
raise Exception("fake error")
|
@@ -1,9 +1,8 @@
|
|
1
1
|
import fastapi.requests
|
2
2
|
from fastapi import APIRouter
|
3
3
|
|
4
|
-
from project.api.
|
5
|
-
|
6
|
-
try_find_user_token_dbm_api_middleware
|
4
|
+
from project.api.auth import APIAuthData, api_auth, require_api_key_dbm_api_middleware, \
|
5
|
+
require_user_token_dbm_api_middleware
|
7
6
|
from project.api.const import APIErrorCodes, APIErrorSpecificationCodes
|
8
7
|
from project.api.schema.out.common.error import ErrorCommonSO
|
9
8
|
from project.api.schema.out.general.errors_info_general import ErrorsInfoGeneralSO
|
@@ -22,11 +21,8 @@ async def _(
|
|
22
21
|
request: fastapi.requests.Request,
|
23
22
|
response: fastapi.responses.Response,
|
24
23
|
api_auth_data: APIAuthData = fastapi.Depends(api_auth(middlewares=[
|
25
|
-
|
26
|
-
|
27
|
-
try_find_api_key_dbm_api_middleware(),
|
28
|
-
try_find_user_token_dbm_api_middleware(),
|
29
|
-
|
24
|
+
require_api_key_dbm_api_middleware(require_active=True),
|
25
|
+
require_user_token_dbm_api_middleware(require_active=True)
|
30
26
|
]))
|
31
27
|
):
|
32
28
|
return ErrorsInfoGeneralSO(
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from fastapi import APIRouter
|
2
2
|
|
3
|
-
from project.api.router.general import healthcheck
|
3
|
+
from project.api.router.general import healthcheck, now_utc_datetime
|
4
4
|
|
5
5
|
main_general_api_router = APIRouter()
|
6
6
|
|
@@ -8,3 +8,7 @@ main_general_api_router.include_router(
|
|
8
8
|
router=healthcheck.api_router,
|
9
9
|
prefix="/healthcheck"
|
10
10
|
)
|
11
|
+
main_general_api_router.include_router(
|
12
|
+
router=now_utc_datetime.api_router,
|
13
|
+
prefix="/now_utc_datetime"
|
14
|
+
)
|
@@ -10,7 +10,7 @@ from project.sqlalchemy_db_.sqlalchemy_model import UserDBM
|
|
10
10
|
class UserDBMSAdminSO(SimpleDBMAdminSO):
|
11
11
|
mail: str | None
|
12
12
|
roles: list[str]
|
13
|
-
|
13
|
+
is_active: bool
|
14
14
|
tg_id: int | None
|
15
15
|
tg_bot_last_action_dt: dt.datetime | None
|
16
16
|
tg_data: dict[str, Any] | None
|
@@ -7,7 +7,7 @@ from project.sqlalchemy_db_.sqlalchemy_model import UserTokenDBM
|
|
7
7
|
class UserTokenDBMSAdminSO(SimpleDBMAdminSO):
|
8
8
|
value: str
|
9
9
|
user_id: int
|
10
|
-
|
10
|
+
is_active: bool
|
11
11
|
|
12
12
|
@classmethod
|
13
13
|
def from_user_token_dbm(cls, *, user_dbm: UserTokenDBM) -> UserTokenDBMSAdminSO:
|
@@ -84,24 +84,10 @@ class Settings(SimpleSettings):
|
|
84
84
|
|
85
85
|
api_init_json_db: bool = False
|
86
86
|
|
87
|
-
|
87
|
+
api_correct_api_keys: list[str] | None = ["1"]
|
88
88
|
|
89
|
-
@field_validator("
|
90
|
-
def
|
91
|
-
if isinstance(v, str):
|
92
|
-
v = [v]
|
93
|
-
if isinstance(v, int):
|
94
|
-
v = [str(v)]
|
95
|
-
if isinstance(v, list):
|
96
|
-
for i, v_ in enumerate(v):
|
97
|
-
if isinstance(v_, int):
|
98
|
-
v[i] = str(v_)
|
99
|
-
return v
|
100
|
-
|
101
|
-
api_user_tokens: list[str] | None = ["1"]
|
102
|
-
|
103
|
-
@field_validator("api_user_tokens", mode="before")
|
104
|
-
def validate_api_tokens(cls, v: Any, validation_info: ValidationInfo, **kwargs) -> list[str] | None:
|
89
|
+
@field_validator("api_correct_api_keys", mode="before")
|
90
|
+
def validate_api_correct_api_keys(cls, v: Any, validation_info: ValidationInfo, **kwargs) -> list[str] | None:
|
105
91
|
if isinstance(v, str):
|
106
92
|
v = [v]
|
107
93
|
if isinstance(v, int):
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import asyncio
|
2
|
+
import logging
|
3
|
+
|
4
|
+
from project.core.settings import get_cached_settings
|
5
|
+
from project.sqlalchemy_db_.sqlalchemy_db import get_cached_sqlalchemy_db
|
6
|
+
from project.sqlalchemy_db_.sqlalchemy_model import ApiKeyDBM
|
7
|
+
|
8
|
+
_logger = logging.getLogger(__name__)
|
9
|
+
|
10
|
+
|
11
|
+
def make_test_data_1():
|
12
|
+
get_cached_settings().raise_if_prod_mode()
|
13
|
+
with get_cached_sqlalchemy_db().new_session() as session:
|
14
|
+
for i in range(10):
|
15
|
+
api_key = ApiKeyDBM(value=str(i))
|
16
|
+
session.add(api_key)
|
17
|
+
_logger.info(api_key)
|
18
|
+
session.commit()
|
19
|
+
|
20
|
+
|
21
|
+
async def async_make_test_data_1():
|
22
|
+
get_cached_settings().raise_if_prod_mode()
|
23
|
+
|
24
|
+
|
25
|
+
def __example():
|
26
|
+
make_test_data_1()
|
27
|
+
|
28
|
+
|
29
|
+
async def __async_example():
|
30
|
+
await async_make_test_data_1()
|
31
|
+
|
32
|
+
|
33
|
+
if __name__ == '__main__':
|
34
|
+
__example()
|
35
|
+
asyncio.run(__async_example())
|
@@ -1,12 +1,14 @@
|
|
1
1
|
import asyncio
|
2
2
|
|
3
|
+
from project.core.settings import get_cached_settings
|
4
|
+
|
3
5
|
|
4
6
|
def make_test_data_1():
|
5
|
-
|
7
|
+
get_cached_settings().raise_if_prod_mode()
|
6
8
|
|
7
9
|
|
8
10
|
async def async_make_test_data_1():
|
9
|
-
|
11
|
+
get_cached_settings().raise_if_prod_mode()
|
10
12
|
|
11
13
|
|
12
14
|
def __example():
|
@@ -1,12 +1,14 @@
|
|
1
1
|
import asyncio
|
2
2
|
|
3
|
+
from project.core.settings import get_cached_settings
|
4
|
+
|
3
5
|
|
4
6
|
def make_test_data_2():
|
5
|
-
|
7
|
+
get_cached_settings().raise_if_prod_mode()
|
6
8
|
|
7
9
|
|
8
10
|
async def async_make_test_data_2():
|
9
|
-
|
11
|
+
get_cached_settings().raise_if_prod_mode()
|
10
12
|
|
11
13
|
|
12
14
|
def __example():
|
@@ -1,12 +1,14 @@
|
|
1
1
|
import asyncio
|
2
2
|
|
3
|
+
from project.core.settings import get_cached_settings
|
4
|
+
|
3
5
|
|
4
6
|
def make_test_data_3():
|
5
|
-
|
7
|
+
get_cached_settings().raise_if_prod_mode()
|
6
8
|
|
7
9
|
|
8
10
|
async def async_make_test_data_3():
|
9
|
-
|
11
|
+
get_cached_settings().raise_if_prod_mode()
|
10
12
|
|
11
13
|
|
12
14
|
def __example():
|
@@ -1,12 +1,14 @@
|
|
1
1
|
import asyncio
|
2
2
|
|
3
|
+
from project.core.settings import get_cached_settings
|
4
|
+
|
3
5
|
|
4
6
|
def make_test_data_4():
|
5
|
-
|
7
|
+
get_cached_settings().raise_if_prod_mode()
|
6
8
|
|
7
9
|
|
8
10
|
async def async_make_test_data_4():
|
9
|
-
|
11
|
+
get_cached_settings().raise_if_prod_mode()
|
10
12
|
|
11
13
|
|
12
14
|
def __example():
|
@@ -1,12 +1,14 @@
|
|
1
1
|
import asyncio
|
2
2
|
|
3
|
+
from project.core.settings import get_cached_settings
|
4
|
+
|
3
5
|
|
4
6
|
def make_test_data_5():
|
5
|
-
|
7
|
+
get_cached_settings().raise_if_prod_mode()
|
6
8
|
|
7
9
|
|
8
10
|
async def async_make_test_data_5():
|
9
|
-
|
11
|
+
get_cached_settings().raise_if_prod_mode()
|
10
12
|
|
11
13
|
|
12
14
|
def __example():
|
@@ -78,27 +78,27 @@ arpakitlib/_arpakit_project_template_v_5/project/additional_model/__init__.py,sh
|
|
78
78
|
arpakitlib/_arpakit_project_template_v_5/project/additional_model/common.py,sha256=XuVbWeesA5fxD0dFPDW8D7NAk0w4RyD5jXPwGOSFchg,233
|
79
79
|
arpakitlib/_arpakit_project_template_v_5/project/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
80
80
|
arpakitlib/_arpakit_project_template_v_5/project/api/asgi.py,sha256=ES3YGwNxWUHVyD6e2ii6QkvTyB-vlVmr8_PhfVIXQ4Y,78
|
81
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/auth.py,sha256=
|
82
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/auth2.py,sha256=OCQ8zifsio7_4Pa7GGl40rkbcAYHcnCkO6ThF0J3aLg,9206
|
81
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/auth.py,sha256=wuiwenDuQ6NFmYbBcui8RJ3Wzgqz85S5Rpnc5ObrZuM,12096
|
83
82
|
arpakitlib/_arpakit_project_template_v_5/project/api/const.py,sha256=J9bqaRRiIc3RLn6SJTvdfDvFrSsM_Ixii9t2M8dA5Jc,433
|
84
83
|
arpakitlib/_arpakit_project_template_v_5/project/api/create_api_app.py,sha256=-taA-OJ69donUlCUIl4tNxjHjRGnjwXl796lThef-uA,2284
|
85
84
|
arpakitlib/_arpakit_project_template_v_5/project/api/event.py,sha256=xKfJ3UnOx_g1s7KNZjWRp0eZbVRTsSlyJhT3wkfwT6k,2414
|
86
85
|
arpakitlib/_arpakit_project_template_v_5/project/api/exception.py,sha256=cNZaI2DacGLl8Hyn1qIfFpVjvQzOQjwXWsVW4auBrCo,1280
|
87
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/exception_handler.py,sha256=
|
86
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/exception_handler.py,sha256=BZ5myTNgruU7q92cM7832PaB4qHa8ooGcZS6CmSaqnQ,11295
|
88
87
|
arpakitlib/_arpakit_project_template_v_5/project/api/openapi_ui.py,sha256=PLhH-W6zDViO-75AGCs8Vq3IoyHChdqwBYAqLvdQN0U,904
|
89
88
|
arpakitlib/_arpakit_project_template_v_5/project/api/response.py,sha256=xZMymP2BuQaRNVWLeIp3UgUUo-MFN8MJnsn9Al4vOb8,1028
|
90
89
|
arpakitlib/_arpakit_project_template_v_5/project/api/router/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
91
90
|
arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
92
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_arpakitlib_project_template_info.py,sha256=
|
93
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_auth_data.py,sha256=
|
94
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/main_router.py,sha256=
|
91
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_arpakitlib_project_template_info.py,sha256=uN2yJN8NpncyvIOc-D6s9nxftDpA5XwP9ZC6wqI9FZw,1084
|
92
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_auth_data.py,sha256=SWh7P4-D1LSTS0anBEbIxnQI6OV9nymBlqFV5P8h8j4,1007
|
93
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/main_router.py,sha256=wzlJlKxj-hontW8ckuyqpQvzRKs0clpSAuwpXpFiaAQ,545
|
94
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/raise_fake_error.py,sha256=DNRWLRCmGoqqdjnm_zjJmFkClwyEzxpZJTT74vH_TrQ,879
|
95
95
|
arpakitlib/_arpakit_project_template_v_5/project/api/router/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
96
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/router/client/get_errors_info.py,sha256=
|
97
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/router/client/main_router.py,sha256=
|
98
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/router/client/now_utc_datetime.py,sha256=II82zoa1LWbSGkn8YMqzZZpkfNgWxEClT2qrrWyzM4Q,590
|
96
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/router/client/get_errors_info.py,sha256=uG5skKLpYbrXAlHu8MO8pjIHI9dIvYaL8kfTPW4iEIU,1101
|
97
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/router/client/main_router.py,sha256=MFYUoxo0lal7__1B7wf1NT5RhJfVtK5rqp7SYix6AaY,234
|
99
98
|
arpakitlib/_arpakit_project_template_v_5/project/api/router/general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
100
99
|
arpakitlib/_arpakit_project_template_v_5/project/api/router/general/healthcheck.py,sha256=xQNMi81IaroNE2H3LvYNUYV6X1dcGSeS2kAUSvGEcWA,523
|
101
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/router/general/main_router.py,sha256=
|
100
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/router/general/main_router.py,sha256=OPKujYKPInDozmfZrffQnMGtdwyxMBQv1k2f-LttMDY,356
|
101
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/router/general/now_utc_datetime.py,sha256=4On6HXmhUuseuijWIIxuuzxZW1iHjnN_WsKQA8qdMsM,591
|
102
102
|
arpakitlib/_arpakit_project_template_v_5/project/api/router/main_router.py,sha256=Y-PPHWbLoICn0O8NRdx49f7ifEw2uN_QIRwfIseo0J0,615
|
103
103
|
arpakitlib/_arpakit_project_template_v_5/project/api/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
104
104
|
arpakitlib/_arpakit_project_template_v_5/project/api/schema/common.py,sha256=DX6Yz63JHoNlgmZnpss2PuRgEtBh3PPlxM6wImYLpXo,718
|
@@ -115,8 +115,8 @@ arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/admin/__init__.p
|
|
115
115
|
arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/admin/common.py,sha256=i_qLlACMT7XKB4liOEG1PTYkGIL0IDNHoP2Ioh_Xugw,181
|
116
116
|
arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/admin/operation.py,sha256=SrRo1HqugMGDYnc0NUTzHzoMfNdtRzd1EleejURsx_M,715
|
117
117
|
arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/admin/story_log.py,sha256=GQ5EDbYCDByKVwSJpdfLLULWvjUUhE3vo5c2FdK0HBY,498
|
118
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/admin/user.py,sha256=
|
119
|
-
arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/admin/user_token.py,sha256=
|
118
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/admin/user.py,sha256=W0g6qHEKqPa4CJvmhzyfUiLzqXLjtTR3OC07UhfdkZc,632
|
119
|
+
arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/admin/user_token.py,sha256=w7LL2q58aG7zgVDW1D_lUhg4zCJLqJcfXQX4geHSPXw,446
|
120
120
|
arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/client/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
121
121
|
arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/client/common.py,sha256=hi0ybvowgARVEQaD0V8JYxUM5f4gqaJ6U7FlLQCxABE,182
|
122
122
|
arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -138,7 +138,7 @@ arpakitlib/_arpakit_project_template_v_5/project/core/const.py,sha256=hgiiPIYL95
|
|
138
138
|
arpakitlib/_arpakit_project_template_v_5/project/core/dump_file_storage_in_dir.py,sha256=u3-vStMGaseMsRLuJmQK04UDhaez9vw6o5jyHb1fwNg,617
|
139
139
|
arpakitlib/_arpakit_project_template_v_5/project/core/jinja2_templates.py,sha256=jCNLaBauGC7YNvZdTLNHuPp7hmRGt94O23Skg6ewo7o,352
|
140
140
|
arpakitlib/_arpakit_project_template_v_5/project/core/media_file_storage_in_dir.py,sha256=fMofTsfJtA8pp5lEUhucEUu3PBsmj-elaRZzExDsdLI,623
|
141
|
-
arpakitlib/_arpakit_project_template_v_5/project/core/settings.py,sha256=
|
141
|
+
arpakitlib/_arpakit_project_template_v_5/project/core/settings.py,sha256=jGZSy5VNfYaoq3tiUywHV8Nlx1_Vsw2Fml22bc3UUiQ,5905
|
142
142
|
arpakitlib/_arpakit_project_template_v_5/project/core/util.py,sha256=1ha9UrguVPsTSjoMHhVZVCD0_mNBfhIDGEvcG1nA4Zw,667
|
143
143
|
arpakitlib/_arpakit_project_template_v_5/project/json_db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
144
144
|
arpakitlib/_arpakit_project_template_v_5/project/json_db/json_db.py,sha256=tBML-z4Y7uY8f_0ggcxvlDNt15Sf93Jr_OUeHwWxqOA,724
|
@@ -203,19 +203,20 @@ arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/__init__.py,sha2
|
|
203
203
|
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/const.py,sha256=dcvj5C9E2F2KCsGZPBBncQf_EvVJAC1qQgnyD8P4ZEw,6
|
204
204
|
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_db.py,sha256=1y3FaMFzm_5UM2poqtBve_UP_mh1vjs--krq6yO8PsA,742
|
205
205
|
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/__init__.py,sha256=btSjCQ7RJqomeXzYs9HePCu1dZHs0z6-RuboYKG89_8,598
|
206
|
-
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/api_key.py,sha256=
|
206
|
+
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/api_key.py,sha256=a-xSHsnE8EkiH9g1ZoxaQQ7Y7q0urIm3SynlGYiSE8E,1038
|
207
207
|
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/common.py,sha256=yK0fFdRYZUpjWl8Vq9S9DKMLBkj9ZT9TXhGyPuR6asU,1876
|
208
208
|
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/operation.py,sha256=ZyK6jRVYM7K_ze2LDaYBwqTP6MkTFjtQMTD-HroX0jg,3293
|
209
209
|
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/story_log.py,sha256=MyXra-PNFrqe9FOjXnDXNYkzX8_A9pbj2uhk1GTPFJ8,1264
|
210
|
-
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/user.py,sha256=
|
211
|
-
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/user_token.py,sha256=
|
210
|
+
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/user.py,sha256=HwFXmlQD9IIFYwGh5wvp0W1RaKqg2nWtjgLFTIsw5ww,2353
|
211
|
+
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model/user_token.py,sha256=9yGVRC4Ns1TgM7IOaZvbQWuiLYpxDTQKzitokpCGRoQ,1013
|
212
212
|
arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/util.py,sha256=QSA_nT6aWdtE412-Uj3VTd7yh3dzS4HugDK9FivjTPo,570
|
213
213
|
arpakitlib/_arpakit_project_template_v_5/project/test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
214
|
-
arpakitlib/_arpakit_project_template_v_5/project/test_data/
|
215
|
-
arpakitlib/_arpakit_project_template_v_5/project/test_data/
|
216
|
-
arpakitlib/_arpakit_project_template_v_5/project/test_data/
|
217
|
-
arpakitlib/_arpakit_project_template_v_5/project/test_data/
|
218
|
-
arpakitlib/_arpakit_project_template_v_5/project/test_data/
|
214
|
+
arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_api_keys.py,sha256=0T2NXyh2Voy8SmtFNMvvD8HSPVz0OXjsQFDWig5pAAs,834
|
215
|
+
arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_1.py,sha256=fioAaw5sWtZdOuHsl1kbVxuU_g0IK8N-gyKlMzVi8FE,416
|
216
|
+
arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_2.py,sha256=VcCvxRLA0XnLaQcsaoZkIVV8rTO3uMyLTYoEsdxKtYE,416
|
217
|
+
arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_3.py,sha256=9QJTgM4qsJXPgFhfVueQ9vObXr_dAldzP_p8dPO42uA,416
|
218
|
+
arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_4.py,sha256=OyU9601WACF7cCpPT33x6CpizNJeQIPDDFezIvEO01A,416
|
219
|
+
arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_5.py,sha256=cew0ndlJspNkeQVOS0UPoceg1ARIm5ZFCzytiDIyvbg,416
|
219
220
|
arpakitlib/_arpakit_project_template_v_5/project/tg_bot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
220
221
|
arpakitlib/_arpakit_project_template_v_5/project/tg_bot/blank/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
221
222
|
arpakitlib/_arpakit_project_template_v_5/project/tg_bot/blank/admin.py,sha256=RG9YRcOJAkS3Z4VNEnwyTnKj8Xb65gCZWta7NdGdxvU,1008
|
@@ -340,8 +341,8 @@ arpakitlib/ar_type_util.py,sha256=Cs_tef-Fc5xeyAF54KgISCsP11NHyzIsglm4S3Xx7iM,40
|
|
340
341
|
arpakitlib/ar_wata_api_client.py,sha256=gdHOqDbuqxhTjVDtRW1DvkRJLdDofCrOq51GTctzLns,242
|
341
342
|
arpakitlib/ar_yookassa_api_client_util.py,sha256=VozuZeCJjmLd1zj2BdC9WfiAQ3XYOrIMsdpNK-AUlm0,5347
|
342
343
|
arpakitlib/ar_zabbix_api_client_util.py,sha256=Q-VR4MvoZ9aHwZeYZr9G3LwN-ANx1T5KFmF6pvPM-9M,6402
|
343
|
-
arpakitlib-1.8.
|
344
|
-
arpakitlib-1.8.
|
345
|
-
arpakitlib-1.8.
|
346
|
-
arpakitlib-1.8.
|
347
|
-
arpakitlib-1.8.
|
344
|
+
arpakitlib-1.8.20.dist-info/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
|
345
|
+
arpakitlib-1.8.20.dist-info/METADATA,sha256=1-ryZ5_8onpKsykVGz1CtFYHmC6CcpHL5Uvx-xLQdLc,3432
|
346
|
+
arpakitlib-1.8.20.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
|
347
|
+
arpakitlib-1.8.20.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
|
348
|
+
arpakitlib-1.8.20.dist-info/RECORD,,
|
@@ -1,218 +0,0 @@
|
|
1
|
-
from typing import Callable
|
2
|
-
|
3
|
-
import fastapi
|
4
|
-
import fastapi.exceptions
|
5
|
-
import fastapi.responses
|
6
|
-
import fastapi.security
|
7
|
-
import sqlalchemy
|
8
|
-
from fastapi import Security
|
9
|
-
from fastapi.security import APIKeyHeader
|
10
|
-
from pydantic import BaseModel, ConfigDict
|
11
|
-
|
12
|
-
from arpakitlib.ar_func_util import is_async_func, is_sync_func
|
13
|
-
from arpakitlib.ar_json_util import transfer_data_to_json_str_to_data
|
14
|
-
from project.api.const import APIErrorCodes
|
15
|
-
from project.api.exception import APIException
|
16
|
-
from project.core.settings import get_cached_settings
|
17
|
-
from project.sqlalchemy_db_.sqlalchemy_db import get_cached_sqlalchemy_db
|
18
|
-
from project.sqlalchemy_db_.sqlalchemy_model import ApiKeyDBM, UserTokenDBM
|
19
|
-
|
20
|
-
|
21
|
-
class APIAuthData(BaseModel):
|
22
|
-
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True, from_attributes=True)
|
23
|
-
|
24
|
-
api_key_string: str | None = None
|
25
|
-
user_token_string: str | None = None
|
26
|
-
|
27
|
-
api_key_dbm: ApiKeyDBM | None = None
|
28
|
-
user_token_dbm: UserTokenDBM | None = None
|
29
|
-
|
30
|
-
prod_mode: bool = False
|
31
|
-
|
32
|
-
|
33
|
-
def api_auth(
|
34
|
-
*,
|
35
|
-
middlewares: list[Callable] | None = None
|
36
|
-
) -> Callable:
|
37
|
-
if middlewares is None:
|
38
|
-
middlewares = []
|
39
|
-
|
40
|
-
async def async_func(
|
41
|
-
*,
|
42
|
-
ac: fastapi.security.HTTPAuthorizationCredentials | None = fastapi.Security(
|
43
|
-
fastapi.security.HTTPBearer(auto_error=False)
|
44
|
-
),
|
45
|
-
api_key_string: str | None = Security(
|
46
|
-
APIKeyHeader(name="apikey", auto_error=False)
|
47
|
-
),
|
48
|
-
request: fastapi.requests.Request
|
49
|
-
) -> APIAuthData:
|
50
|
-
|
51
|
-
api_auth_data = APIAuthData(
|
52
|
-
prod_mode=get_cached_settings().prod_mode
|
53
|
-
)
|
54
|
-
|
55
|
-
# parse api_key_string
|
56
|
-
|
57
|
-
api_auth_data.api_key_string = api_key_string
|
58
|
-
|
59
|
-
if not api_auth_data.api_key_string and "api_key" in request.headers.keys():
|
60
|
-
api_auth_data.api_key_string = request.headers["api_key"]
|
61
|
-
if not api_auth_data.api_key_string and "api-key" in request.headers.keys():
|
62
|
-
api_auth_data.api_key_string = request.headers["api-key"]
|
63
|
-
if not api_auth_data.api_key_string and "apikey" in request.headers.keys():
|
64
|
-
api_auth_data.api_key_string = request.headers["apikey"]
|
65
|
-
if not api_auth_data.api_key_string and "api_key_string" in request.headers.keys():
|
66
|
-
api_auth_data.api_key_string = request.headers["api_key_string"]
|
67
|
-
|
68
|
-
if not api_auth_data.api_key_string and "api_key" in request.query_params.keys():
|
69
|
-
api_auth_data.api_key_string = request.query_params["api_key"]
|
70
|
-
if not api_auth_data.api_key_string and "api-key" in request.query_params.keys():
|
71
|
-
api_auth_data.api_key_string = request.query_params["api-key"]
|
72
|
-
if not api_auth_data.api_key_string and "apikey" in request.query_params.keys():
|
73
|
-
api_auth_data.api_key_string = request.query_params["apikey"]
|
74
|
-
if not api_auth_data.api_key_string and "api_key_string" in request.query_params.keys():
|
75
|
-
api_auth_data.api_key_string = request.query_params["api_key_string"]
|
76
|
-
|
77
|
-
if api_auth_data.api_key_string:
|
78
|
-
api_auth_data.api_key_string = api_auth_data.api_key_string.strip()
|
79
|
-
if not api_auth_data.api_key_string:
|
80
|
-
api_auth_data.api_key_string = None
|
81
|
-
|
82
|
-
# parse user_token_string
|
83
|
-
|
84
|
-
api_auth_data.user_token_string = ac.credentials if ac and ac.credentials and ac.credentials.strip() else None
|
85
|
-
|
86
|
-
if not api_auth_data.user_token_string and "token" in request.headers.keys():
|
87
|
-
api_auth_data.user_token_string = request.headers["token"]
|
88
|
-
|
89
|
-
if not api_auth_data.user_token_string and "user_token" in request.headers.keys():
|
90
|
-
api_auth_data.user_token_string = request.headers["user_token"]
|
91
|
-
if not api_auth_data.user_token_string and "user-token" in request.headers.keys():
|
92
|
-
api_auth_data.user_token_string = request.headers["user-token"]
|
93
|
-
if not api_auth_data.user_token_string and "usertoken" in request.headers.keys():
|
94
|
-
api_auth_data.user_token_string = request.headers["usertoken"]
|
95
|
-
|
96
|
-
if not api_auth_data.user_token_string and "token" in request.query_params.keys():
|
97
|
-
api_auth_data.user_token_string = request.query_params["token"]
|
98
|
-
|
99
|
-
if not api_auth_data.user_token_string and "user_token" in request.query_params.keys():
|
100
|
-
api_auth_data.user_token_string = request.query_params["user_token"]
|
101
|
-
if not api_auth_data.user_token_string and "user-token" in request.query_params.keys():
|
102
|
-
api_auth_data.user_token_string = request.query_params["user-token"]
|
103
|
-
if not api_auth_data.user_token_string and "usertoken" in request.query_params.keys():
|
104
|
-
api_auth_data.user_token_string = request.query_params["usertoken"]
|
105
|
-
|
106
|
-
if api_auth_data.user_token_string:
|
107
|
-
api_auth_data.user_token_string = api_auth_data.user_token_string.strip()
|
108
|
-
if not api_auth_data.user_token_string:
|
109
|
-
api_auth_data.user_token_string = None
|
110
|
-
|
111
|
-
# middlewares
|
112
|
-
|
113
|
-
for middleware in middlewares:
|
114
|
-
if is_async_func(middleware):
|
115
|
-
await middleware(
|
116
|
-
api_auth_data=api_auth_data,
|
117
|
-
request=request
|
118
|
-
)
|
119
|
-
elif is_sync_func(middleware):
|
120
|
-
middleware(
|
121
|
-
api_auth_data=api_auth_data,
|
122
|
-
request=request
|
123
|
-
)
|
124
|
-
else:
|
125
|
-
raise TypeError(f"unknown middleware type, {middleware.__name__}")
|
126
|
-
|
127
|
-
return api_auth_data
|
128
|
-
|
129
|
-
return async_func
|
130
|
-
|
131
|
-
|
132
|
-
def require_prod_mode_api_middleware():
|
133
|
-
def func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
134
|
-
if not get_cached_settings().prod_mode:
|
135
|
-
raise APIException(
|
136
|
-
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
137
|
-
error_code=APIErrorCodes.cannot_authorize,
|
138
|
-
error_description=f"prod_mode={get_cached_settings().prod_mode}",
|
139
|
-
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
140
|
-
)
|
141
|
-
|
142
|
-
return func
|
143
|
-
|
144
|
-
|
145
|
-
def require_not_prod_mode_api_middleware():
|
146
|
-
def func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
147
|
-
if get_cached_settings().prod_mode:
|
148
|
-
raise APIException(
|
149
|
-
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
150
|
-
error_code=APIErrorCodes.cannot_authorize,
|
151
|
-
error_description=f"prod_mode={get_cached_settings().prod_mode}",
|
152
|
-
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
153
|
-
)
|
154
|
-
|
155
|
-
return func
|
156
|
-
|
157
|
-
|
158
|
-
def require_api_key_string_api_middleware():
|
159
|
-
def func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
160
|
-
if api_auth_data.api_key_string is None:
|
161
|
-
raise APIException(
|
162
|
-
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
163
|
-
error_code=APIErrorCodes.cannot_authorize,
|
164
|
-
error_description="api_key_string is required",
|
165
|
-
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
166
|
-
)
|
167
|
-
|
168
|
-
return func
|
169
|
-
|
170
|
-
|
171
|
-
def require_user_token_string_api_middleware():
|
172
|
-
def func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
173
|
-
if api_auth_data.user_token_string is None:
|
174
|
-
raise APIException(
|
175
|
-
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
176
|
-
error_code=APIErrorCodes.cannot_authorize,
|
177
|
-
error_description="user_token_string is required",
|
178
|
-
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
179
|
-
)
|
180
|
-
|
181
|
-
return func
|
182
|
-
|
183
|
-
|
184
|
-
def try_find_api_key_dbm_api_middleware():
|
185
|
-
async def async_func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
186
|
-
if api_auth_data.api_key_dbm is None:
|
187
|
-
return
|
188
|
-
async with get_cached_sqlalchemy_db().new_async_session() as async_session:
|
189
|
-
api_auth_data.api_key_dbm = await async_session.scalar(
|
190
|
-
sqlalchemy.select(ApiKeyDBM).where(ApiKeyDBM.value == api_auth_data.api_key_string)
|
191
|
-
)
|
192
|
-
|
193
|
-
return async_func
|
194
|
-
|
195
|
-
|
196
|
-
def try_find_user_token_dbm_api_middleware():
|
197
|
-
async def async_func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
198
|
-
if api_auth_data.user_token_dbm is None:
|
199
|
-
return
|
200
|
-
async with get_cached_sqlalchemy_db().new_async_session() as async_session:
|
201
|
-
api_auth_data.user_token_dbm = await async_session.scalar(
|
202
|
-
sqlalchemy.select(UserTokenDBM).where(UserTokenDBM.value == api_auth_data.user_token_string)
|
203
|
-
)
|
204
|
-
|
205
|
-
return async_func
|
206
|
-
|
207
|
-
|
208
|
-
def require_api_key_dbm_api_middleware():
|
209
|
-
async def async_func(*, api_auth_data: APIAuthData, request: fastapi.requests.Request):
|
210
|
-
if api_auth_data.api_key_dbm is None:
|
211
|
-
raise APIException(
|
212
|
-
status_code=fastapi.status.HTTP_401_UNAUTHORIZED,
|
213
|
-
error_code=APIErrorCodes.cannot_authorize,
|
214
|
-
error_description="api_key_dbm is required",
|
215
|
-
error_data=transfer_data_to_json_str_to_data(api_auth_data.model_dump())
|
216
|
-
)
|
217
|
-
|
218
|
-
return async_func
|
File without changes
|
File without changes
|
File without changes
|