crypticorn 2.17.0rc7__py3-none-any.whl → 2.18.0__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.
- crypticorn/auth/client/api/admin_api.py +2 -0
- crypticorn/auth/client/api/auth_api.py +1417 -545
- crypticorn/auth/client/api/service_api.py +4 -0
- crypticorn/auth/client/api/user_api.py +4 -0
- crypticorn/auth/client/api/wallet_api.py +4 -0
- crypticorn/auth/client/api_client.py +5 -0
- crypticorn/auth/client/configuration.py +2 -2
- crypticorn/auth/client/models/add_wallet_request.py +1 -1
- crypticorn/auth/client/models/authorize_user_request.py +1 -1
- crypticorn/auth/client/models/create_api_key_request.py +3 -3
- crypticorn/auth/client/models/create_user_request.py +1 -1
- crypticorn/auth/client/models/get_api_keys200_response_inner.py +3 -3
- crypticorn/auth/client/models/list_wallets200_response_balances_inner_sale_round.py +1 -1
- crypticorn/auth/client/models/list_wallets200_response_balances_inner_wallet.py +1 -1
- crypticorn/auth/client/models/list_wallets200_response_balances_inner_wallet_vesting_wallets_inner.py +1 -1
- crypticorn/auth/client/models/list_wallets200_response_data_inner.py +1 -1
- crypticorn/auth/client/models/logout_default_response.py +1 -1
- crypticorn/auth/client/models/oauth_callback200_response_user.py +1 -1
- crypticorn/auth/client/models/refresh_token_info200_response_user_session.py +1 -1
- crypticorn/auth/client/models/rotate_tokens200_response.py +1 -1
- crypticorn/auth/client/models/token_info200_response.py +1 -1
- crypticorn/auth/client/models/update_user_request.py +1 -1
- crypticorn/auth/client/models/user_by_username200_response.py +1 -1
- crypticorn/auth/client/models/verify200_response.py +1 -1
- crypticorn/auth/client/models/verify_email200_response_auth.py +1 -1
- crypticorn/auth/client/models/verify_email200_response_auth_auth.py +1 -1
- crypticorn/auth/client/models/whoami200_response.py +1 -1
- crypticorn/common/__init__.py +11 -11
- crypticorn/common/auth.py +109 -57
- crypticorn/common/decorators.py +1 -1
- crypticorn/common/enums.py +1 -0
- crypticorn/common/errors.py +7 -21
- crypticorn/common/exceptions.py +33 -17
- crypticorn/common/logging.py +5 -4
- crypticorn/common/metrics.py +17 -5
- crypticorn/common/middleware.py +61 -12
- crypticorn/common/mixins.py +2 -1
- crypticorn/common/pagination.py +3 -2
- crypticorn/common/router/admin_router.py +17 -6
- crypticorn/common/router/status_router.py +3 -26
- crypticorn/common/utils.py +6 -6
- crypticorn/common/warnings.py +1 -0
- crypticorn/dex/client/api/admin_api.py +3 -0
- crypticorn/dex/client/api/signals_api.py +27 -23
- crypticorn/dex/client/api/status_api.py +3 -0
- crypticorn/dex/client/api_client.py +5 -0
- crypticorn/dex/client/configuration.py +2 -2
- crypticorn/dex/client/models/exception_detail.py +1 -1
- crypticorn/dex/client/models/paginated_response_signal_with_token.py +1 -1
- crypticorn/dex/client/models/signal_overview_stats.py +4 -2
- crypticorn/dex/client/models/signal_volume.py +4 -4
- crypticorn/dex/client/models/signal_with_token.py +2 -2
- crypticorn/dex/client/models/token_detail.py +1 -1
- crypticorn/klines/main.py +1 -1
- crypticorn/metrics/main.py +1 -1
- crypticorn/trade/client/__init__.py +1 -7
- crypticorn/trade/client/api/admin_api.py +0 -402
- crypticorn/trade/client/api/trading_actions_api.py +86 -315
- crypticorn/trade/client/models/__init__.py +1 -7
- crypticorn/trade/client/models/actions_count.py +88 -0
- crypticorn/trade/client/models/api_error_identifier.py +1 -0
- crypticorn/trade/client/models/exchange_key.py +1 -1
- crypticorn/trade/client/models/exchange_key_balance.py +1 -1
- crypticorn/trade/client/models/execution_ids.py +1 -1
- crypticorn/trade/client/models/notification_create.py +1 -1
- crypticorn/trade/client/models/post_futures_action.py +1 -1
- crypticorn/trade/client/models/spot_balance.py +6 -7
- crypticorn/trade/client/models/tpsl.py +4 -19
- crypticorn/trade/client/models/tpsl_create.py +6 -19
- {crypticorn-2.17.0rc7.dist-info → crypticorn-2.18.0.dist-info}/METADATA +1 -1
- {crypticorn-2.17.0rc7.dist-info → crypticorn-2.18.0.dist-info}/RECORD +75 -77
- crypticorn/trade/client/models/paginated_response_union_futures_trading_action_spot_trading_action.py +0 -141
- crypticorn/trade/client/models/paginated_response_union_futures_trading_action_spot_trading_action_data_inner.py +0 -165
- crypticorn/trade/client/models/spot_trading_action.py +0 -207
- {crypticorn-2.17.0rc7.dist-info → crypticorn-2.18.0.dist-info}/WHEEL +0 -0
- {crypticorn-2.17.0rc7.dist-info → crypticorn-2.18.0.dist-info}/entry_points.txt +0 -0
- {crypticorn-2.17.0rc7.dist-info → crypticorn-2.18.0.dist-info}/licenses/LICENSE +0 -0
- {crypticorn-2.17.0rc7.dist-info → crypticorn-2.18.0.dist-info}/top_level.txt +0 -0
@@ -11,10 +11,14 @@ Generated by OpenAPI Generator (https://openapi-generator.tech)
|
|
11
11
|
Do not edit the class manually.
|
12
12
|
""" # noqa: E501
|
13
13
|
|
14
|
+
import warnings
|
14
15
|
from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt
|
15
16
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
16
17
|
from typing_extensions import Annotated
|
17
18
|
|
19
|
+
from pydantic import Field, StrictStr
|
20
|
+
from typing import Optional
|
21
|
+
from typing_extensions import Annotated
|
18
22
|
from crypticorn.auth.client.models.list_wallets200_response_user_value import (
|
19
23
|
ListWallets200ResponseUserValue,
|
20
24
|
)
|
@@ -11,10 +11,14 @@ Generated by OpenAPI Generator (https://openapi-generator.tech)
|
|
11
11
|
Do not edit the class manually.
|
12
12
|
""" # noqa: E501
|
13
13
|
|
14
|
+
import warnings
|
14
15
|
from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt
|
15
16
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
16
17
|
from typing_extensions import Annotated
|
17
18
|
|
19
|
+
from pydantic import Field, StrictStr
|
20
|
+
from typing import Any, Optional
|
21
|
+
from typing_extensions import Annotated
|
18
22
|
from crypticorn.auth.client.models.create_user_request import CreateUserRequest
|
19
23
|
from crypticorn.auth.client.models.resend_verification_email_request import (
|
20
24
|
ResendVerificationEmailRequest,
|
@@ -11,10 +11,14 @@ Generated by OpenAPI Generator (https://openapi-generator.tech)
|
|
11
11
|
Do not edit the class manually.
|
12
12
|
""" # noqa: E501
|
13
13
|
|
14
|
+
import warnings
|
14
15
|
from pydantic import validate_call, Field, StrictFloat, StrictStr, StrictInt
|
15
16
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
16
17
|
from typing_extensions import Annotated
|
17
18
|
|
19
|
+
from pydantic import Field, StrictFloat, StrictInt, StrictStr
|
20
|
+
from typing import Any, Optional, Union
|
21
|
+
from typing_extensions import Annotated
|
18
22
|
from crypticorn.auth.client.models.add_wallet200_response import AddWallet200Response
|
19
23
|
from crypticorn.auth.client.models.add_wallet_request import AddWalletRequest
|
20
24
|
from crypticorn.auth.client.models.list_wallets200_response import (
|
@@ -33,6 +33,11 @@ from crypticorn.auth.client import rest
|
|
33
33
|
from crypticorn.auth.client.exceptions import (
|
34
34
|
ApiValueError,
|
35
35
|
ApiException,
|
36
|
+
BadRequestException,
|
37
|
+
UnauthorizedException,
|
38
|
+
ForbiddenException,
|
39
|
+
NotFoundException,
|
40
|
+
ServiceException,
|
36
41
|
)
|
37
42
|
|
38
43
|
RequestSerialized = Tuple[str, str, Dict[str, str], Optional[str], List[str]]
|
@@ -195,7 +195,7 @@ class Configuration:
|
|
195
195
|
debug: Optional[bool] = None,
|
196
196
|
) -> None:
|
197
197
|
"""Constructor"""
|
198
|
-
self._base_path = "
|
198
|
+
self._base_path = "http://localhost/v1/auth" if host is None else host
|
199
199
|
"""Default Base url
|
200
200
|
"""
|
201
201
|
self.server_index = 0 if server_index is None and host is None else server_index
|
@@ -528,7 +528,7 @@ class Configuration:
|
|
528
528
|
"""
|
529
529
|
return [
|
530
530
|
{
|
531
|
-
"url": "
|
531
|
+
"url": "http://localhost/v1/auth",
|
532
532
|
"description": "No description provided",
|
533
533
|
}
|
534
534
|
]
|
@@ -19,7 +19,7 @@ import json
|
|
19
19
|
|
20
20
|
from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr
|
21
21
|
from typing import Any, ClassVar, Dict, List, Optional, Union
|
22
|
-
from typing import Set
|
22
|
+
from typing import Optional, Set
|
23
23
|
from typing_extensions import Self
|
24
24
|
|
25
25
|
|
@@ -20,7 +20,7 @@ import json
|
|
20
20
|
from pydantic import BaseModel, ConfigDict, Field, StrictBool
|
21
21
|
from typing import Any, ClassVar, Dict, List, Optional
|
22
22
|
from typing_extensions import Annotated
|
23
|
-
from typing import Set
|
23
|
+
from typing import Optional, Set
|
24
24
|
from typing_extensions import Self
|
25
25
|
|
26
26
|
|
@@ -21,7 +21,7 @@ from datetime import datetime
|
|
21
21
|
from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
|
22
22
|
from typing import Any, ClassVar, Dict, List, Optional
|
23
23
|
from typing_extensions import Annotated
|
24
|
-
from typing import Set
|
24
|
+
from typing import Optional, Set
|
25
25
|
from typing_extensions import Self
|
26
26
|
|
27
27
|
|
@@ -50,7 +50,7 @@ class CreateApiKeyRequest(BaseModel):
|
|
50
50
|
if i not in set(
|
51
51
|
[
|
52
52
|
"read:predictions",
|
53
|
-
"read:
|
53
|
+
"read:dex:signals",
|
54
54
|
"read:hive:model",
|
55
55
|
"read:hive:data",
|
56
56
|
"write:hive:model",
|
@@ -85,7 +85,7 @@ class CreateApiKeyRequest(BaseModel):
|
|
85
85
|
]
|
86
86
|
):
|
87
87
|
raise ValueError(
|
88
|
-
"each list item must be one of ('read:predictions', 'read:
|
88
|
+
"each list item must be one of ('read:predictions', 'read:dex:signals', 'read:hive:model', 'read:hive:data', 'write:hive:model', 'read:trade:bots', 'write:trade:bots', 'read:trade:exchangekeys', 'write:trade:exchangekeys', 'read:trade:orders', 'read:trade:actions', 'write:trade:actions', 'read:trade:exchanges', 'read:trade:futures', 'write:trade:futures', 'read:trade:notifications', 'write:trade:notifications', 'read:trade:strategies', 'write:trade:strategies', 'read:pay:payments', 'read:pay:products', 'write:pay:products', 'read:pay:now', 'write:pay:now', 'read:metrics:marketcap', 'read:metrics:indicators', 'read:metrics:exchanges', 'read:metrics:tokens', 'read:metrics:markets', 'read:sentiment', 'read:klines', 'read:admin', 'write:admin')"
|
89
89
|
)
|
90
90
|
return value
|
91
91
|
|
@@ -20,7 +20,7 @@ import json
|
|
20
20
|
from pydantic import BaseModel, ConfigDict, Field, StrictStr
|
21
21
|
from typing import Any, ClassVar, Dict, List, Optional
|
22
22
|
from typing_extensions import Annotated
|
23
|
-
from typing import Set
|
23
|
+
from typing import Optional, Set
|
24
24
|
from typing_extensions import Self
|
25
25
|
|
26
26
|
|
@@ -20,7 +20,7 @@ import json
|
|
20
20
|
from datetime import datetime
|
21
21
|
from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator
|
22
22
|
from typing import Any, ClassVar, Dict, List, Optional
|
23
|
-
from typing import Set
|
23
|
+
from typing import Optional, Set
|
24
24
|
from typing_extensions import Self
|
25
25
|
|
26
26
|
|
@@ -58,7 +58,7 @@ class GetApiKeys200ResponseInner(BaseModel):
|
|
58
58
|
if i not in set(
|
59
59
|
[
|
60
60
|
"read:predictions",
|
61
|
-
"read:
|
61
|
+
"read:dex:signals",
|
62
62
|
"read:hive:model",
|
63
63
|
"read:hive:data",
|
64
64
|
"write:hive:model",
|
@@ -93,7 +93,7 @@ class GetApiKeys200ResponseInner(BaseModel):
|
|
93
93
|
]
|
94
94
|
):
|
95
95
|
raise ValueError(
|
96
|
-
"each list item must be one of ('read:predictions', 'read:
|
96
|
+
"each list item must be one of ('read:predictions', 'read:dex:signals', 'read:hive:model', 'read:hive:data', 'write:hive:model', 'read:trade:bots', 'write:trade:bots', 'read:trade:exchangekeys', 'write:trade:exchangekeys', 'read:trade:orders', 'read:trade:actions', 'write:trade:actions', 'read:trade:exchanges', 'read:trade:futures', 'write:trade:futures', 'read:trade:notifications', 'write:trade:notifications', 'read:trade:strategies', 'write:trade:strategies', 'read:pay:payments', 'read:pay:products', 'write:pay:products', 'read:pay:now', 'write:pay:now', 'read:metrics:marketcap', 'read:metrics:indicators', 'read:metrics:exchanges', 'read:metrics:tokens', 'read:metrics:markets', 'read:sentiment', 'read:klines', 'read:admin', 'write:admin')"
|
97
97
|
)
|
98
98
|
return value
|
99
99
|
|
@@ -20,7 +20,7 @@ import json
|
|
20
20
|
from datetime import datetime
|
21
21
|
from pydantic import BaseModel, ConfigDict, Field, StrictFloat, StrictInt, StrictStr
|
22
22
|
from typing import Any, ClassVar, Dict, List, Optional, Union
|
23
|
-
from typing import Set
|
23
|
+
from typing import Optional, Set
|
24
24
|
from typing_extensions import Self
|
25
25
|
|
26
26
|
|
@@ -22,7 +22,7 @@ from typing import Any, ClassVar, Dict, List, Optional, Union
|
|
22
22
|
from crypticorn.auth.client.models.list_wallets200_response_balances_inner_wallet_vesting_wallets_inner import (
|
23
23
|
ListWallets200ResponseBalancesInnerWalletVestingWalletsInner,
|
24
24
|
)
|
25
|
-
from typing import Set
|
25
|
+
from typing import Optional, Set
|
26
26
|
from typing_extensions import Self
|
27
27
|
|
28
28
|
|
@@ -20,7 +20,7 @@ import json
|
|
20
20
|
from datetime import datetime
|
21
21
|
from pydantic import BaseModel, ConfigDict, StrictStr
|
22
22
|
from typing import Any, ClassVar, Dict, List, Optional
|
23
|
-
from typing import Set
|
23
|
+
from typing import Optional, Set
|
24
24
|
from typing_extensions import Self
|
25
25
|
|
26
26
|
|
@@ -22,7 +22,7 @@ from typing import Any, ClassVar, Dict, List, Optional
|
|
22
22
|
from crypticorn.auth.client.models.logout_default_response_issues_inner import (
|
23
23
|
LogoutDefaultResponseIssuesInner,
|
24
24
|
)
|
25
|
-
from typing import Set
|
25
|
+
from typing import Optional, Set
|
26
26
|
from typing_extensions import Self
|
27
27
|
|
28
28
|
|
@@ -20,7 +20,7 @@ import json
|
|
20
20
|
from datetime import datetime
|
21
21
|
from pydantic import BaseModel, ConfigDict, Field, StrictStr
|
22
22
|
from typing import Any, ClassVar, Dict, List, Optional
|
23
|
-
from typing import Set
|
23
|
+
from typing import Optional, Set
|
24
24
|
from typing_extensions import Self
|
25
25
|
|
26
26
|
|
@@ -22,7 +22,7 @@ from typing import Any, ClassVar, Dict, List, Optional, Union
|
|
22
22
|
from crypticorn.auth.client.models.verify_email200_response_auth_auth import (
|
23
23
|
VerifyEmail200ResponseAuthAuth,
|
24
24
|
)
|
25
|
-
from typing import Set
|
25
|
+
from typing import Optional, Set
|
26
26
|
from typing_extensions import Self
|
27
27
|
|
28
28
|
|
@@ -22,7 +22,7 @@ from typing import Any, ClassVar, Dict, List, Optional
|
|
22
22
|
from crypticorn.auth.client.models.verify_email200_response_auth_auth import (
|
23
23
|
VerifyEmail200ResponseAuthAuth,
|
24
24
|
)
|
25
|
-
from typing import Set
|
25
|
+
from typing import Optional, Set
|
26
26
|
from typing_extensions import Self
|
27
27
|
|
28
28
|
|
@@ -22,7 +22,7 @@ from typing import Any, ClassVar, Dict, List, Optional
|
|
22
22
|
from crypticorn.auth.client.models.verify_email200_response_auth_auth import (
|
23
23
|
VerifyEmail200ResponseAuthAuth,
|
24
24
|
)
|
25
|
-
from typing import Set
|
25
|
+
from typing import Optional, Set
|
26
26
|
from typing_extensions import Self
|
27
27
|
|
28
28
|
|
crypticorn/common/__init__.py
CHANGED
@@ -1,18 +1,18 @@
|
|
1
|
-
from crypticorn.common.
|
2
|
-
from crypticorn.common.scopes import *
|
3
|
-
from crypticorn.common.urls import *
|
4
|
-
from crypticorn.common.decorators import *
|
5
|
-
from crypticorn.common.mixins import *
|
1
|
+
from crypticorn.common.ansi_colors import *
|
6
2
|
from crypticorn.common.auth import *
|
3
|
+
from crypticorn.common.decorators import *
|
7
4
|
from crypticorn.common.enums import *
|
8
|
-
from crypticorn.common.
|
5
|
+
from crypticorn.common.errors import *
|
9
6
|
from crypticorn.common.exceptions import *
|
10
|
-
from crypticorn.common.pagination import *
|
11
7
|
from crypticorn.common.logging import *
|
12
|
-
from crypticorn.common.
|
8
|
+
from crypticorn.common.metrics import *
|
13
9
|
from crypticorn.common.middleware import *
|
14
|
-
from crypticorn.common.
|
10
|
+
from crypticorn.common.mixins import *
|
15
11
|
from crypticorn.common.openapi import *
|
16
|
-
from crypticorn.common.
|
17
|
-
from crypticorn.common.router.status_router import router as status_router
|
12
|
+
from crypticorn.common.pagination import *
|
18
13
|
from crypticorn.common.router.admin_router import router as admin_router
|
14
|
+
from crypticorn.common.router.status_router import router as status_router
|
15
|
+
from crypticorn.common.scopes import *
|
16
|
+
from crypticorn.common.urls import *
|
17
|
+
from crypticorn.common.utils import *
|
18
|
+
from crypticorn.common.warnings import *
|
crypticorn/common/auth.py
CHANGED
@@ -1,25 +1,30 @@
|
|
1
1
|
import json
|
2
|
+
from typing import Union
|
2
3
|
|
3
|
-
from crypticorn.auth import
|
4
|
+
from crypticorn.auth import AuthClient, Configuration, Verify200Response
|
4
5
|
from crypticorn.auth.client.exceptions import ApiException
|
5
|
-
from crypticorn.common.scopes import Scope
|
6
6
|
from crypticorn.common.exceptions import (
|
7
7
|
ApiError,
|
8
|
-
HTTPException,
|
9
8
|
ExceptionContent,
|
9
|
+
HTTPException,
|
10
10
|
)
|
11
|
-
from crypticorn.common.
|
11
|
+
from crypticorn.common.scopes import Scope
|
12
|
+
from crypticorn.common.urls import ApiVersion, BaseUrl, Service
|
12
13
|
from fastapi import Depends, Query
|
13
14
|
from fastapi.security import (
|
14
|
-
HTTPAuthorizationCredentials,
|
15
|
-
SecurityScopes,
|
16
|
-
HTTPBearer,
|
17
15
|
APIKeyHeader,
|
16
|
+
HTTPAuthorizationCredentials,
|
18
17
|
HTTPBasic,
|
18
|
+
HTTPBasicCredentials,
|
19
|
+
HTTPBearer,
|
20
|
+
SecurityScopes,
|
19
21
|
)
|
20
22
|
from typing_extensions import Annotated
|
21
|
-
|
22
|
-
|
23
|
+
|
24
|
+
AUTHENTICATE_HEADER = "WWW-Authenticate"
|
25
|
+
BEARER_AUTH_SCHEME = "Bearer"
|
26
|
+
APIKEY_AUTH_SCHEME = "X-API-Key"
|
27
|
+
BASIC_AUTH_SCHEME = "Basic"
|
23
28
|
|
24
29
|
# Auth Schemes
|
25
30
|
http_bearer = HTTPBearer(
|
@@ -29,15 +34,15 @@ http_bearer = HTTPBearer(
|
|
29
34
|
)
|
30
35
|
|
31
36
|
apikey_header = APIKeyHeader(
|
32
|
-
name=
|
37
|
+
name=APIKEY_AUTH_SCHEME,
|
33
38
|
auto_error=False,
|
34
39
|
description="The API key to use for authentication.",
|
35
40
|
)
|
36
41
|
|
37
|
-
|
38
|
-
scheme_name=
|
42
|
+
http_basic = HTTPBasic(
|
43
|
+
scheme_name=BASIC_AUTH_SCHEME,
|
39
44
|
auto_error=False,
|
40
|
-
description="The username and password to use for authentication.
|
45
|
+
description="The username and password to use for authentication.",
|
41
46
|
)
|
42
47
|
|
43
48
|
|
@@ -55,7 +60,7 @@ class AuthHandler:
|
|
55
60
|
base_url: BaseUrl = BaseUrl.PROD,
|
56
61
|
):
|
57
62
|
self.url = f"{base_url}/{ApiVersion.V1}/{Service.AUTH}"
|
58
|
-
self.client = AuthClient(Configuration(host=self.url))
|
63
|
+
self.client = AuthClient(Configuration(host=self.url), is_sync=False)
|
59
64
|
|
60
65
|
async def _verify_api_key(self, api_key: str) -> Verify200Response:
|
61
66
|
"""
|
@@ -73,6 +78,12 @@ class AuthHandler:
|
|
73
78
|
self.client.config.access_token = bearer.credentials
|
74
79
|
return await self.client.login.verify()
|
75
80
|
|
81
|
+
async def _verify_basic(self, basic: HTTPBasicCredentials) -> Verify200Response:
|
82
|
+
"""
|
83
|
+
Verifies the basic authentication credentials.
|
84
|
+
"""
|
85
|
+
return await self.client.login.verify_basic_auth(basic.username, basic.password)
|
86
|
+
|
76
87
|
async def _validate_scopes(
|
77
88
|
self, api_scopes: list[Scope], user_scopes: list[Scope]
|
78
89
|
) -> bool:
|
@@ -118,6 +129,8 @@ class AuthHandler:
|
|
118
129
|
error = ApiError.EXPIRED_API_KEY
|
119
130
|
elif message == "jwt expired":
|
120
131
|
error = ApiError.EXPIRED_BEARER
|
132
|
+
elif message == "Invalid basic authentication credentials":
|
133
|
+
error = ApiError.INVALID_BASIC_AUTH
|
121
134
|
else:
|
122
135
|
message = "Invalid bearer token"
|
123
136
|
error = (
|
@@ -150,17 +163,17 @@ class AuthHandler:
|
|
150
163
|
This function is used for HTTP connections.
|
151
164
|
"""
|
152
165
|
try:
|
153
|
-
return await self.
|
166
|
+
return await self.full_auth(
|
167
|
+
bearer=None, api_key=api_key, basic=None, sec=sec
|
168
|
+
)
|
154
169
|
except HTTPException as e:
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
)
|
163
|
-
raise e
|
170
|
+
raise HTTPException(
|
171
|
+
content=ExceptionContent(
|
172
|
+
error=ApiError.from_json(e.detail),
|
173
|
+
message=e.detail.get("message"),
|
174
|
+
),
|
175
|
+
headers={AUTHENTICATE_HEADER: APIKEY_AUTH_SCHEME},
|
176
|
+
)
|
164
177
|
|
165
178
|
async def bearer_auth(
|
166
179
|
self,
|
@@ -176,17 +189,37 @@ class AuthHandler:
|
|
176
189
|
This function is used for HTTP connections.
|
177
190
|
"""
|
178
191
|
try:
|
179
|
-
return await self.
|
192
|
+
return await self.full_auth(
|
193
|
+
bearer=bearer, api_key=None, basic=None, sec=sec
|
194
|
+
)
|
195
|
+
except HTTPException as e:
|
196
|
+
raise HTTPException(
|
197
|
+
content=ExceptionContent(
|
198
|
+
error=ApiError.from_json(e.detail),
|
199
|
+
message=e.detail.get("message"),
|
200
|
+
),
|
201
|
+
headers={AUTHENTICATE_HEADER: BEARER_AUTH_SCHEME},
|
202
|
+
)
|
203
|
+
|
204
|
+
async def basic_auth(
|
205
|
+
self,
|
206
|
+
credentials: Annotated[Union[HTTPBasicCredentials, None], Depends(http_basic)],
|
207
|
+
) -> Verify200Response:
|
208
|
+
"""
|
209
|
+
Verifies the basic authentication credentials. This authentication method should just be used for special cases like /admin/metrics, where JWT and API key authentication are not desired or not possible.
|
210
|
+
"""
|
211
|
+
try:
|
212
|
+
return await self.full_auth(
|
213
|
+
basic=credentials, bearer=None, api_key=None, sec=None
|
214
|
+
)
|
180
215
|
except HTTPException as e:
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
)
|
189
|
-
raise e
|
216
|
+
raise HTTPException(
|
217
|
+
content=ExceptionContent(
|
218
|
+
error=ApiError.from_json(e.detail),
|
219
|
+
message=e.detail.get("message"),
|
220
|
+
),
|
221
|
+
headers={AUTHENTICATE_HEADER: BASIC_AUTH_SCHEME},
|
222
|
+
)
|
190
223
|
|
191
224
|
async def combined_auth(
|
192
225
|
self,
|
@@ -202,8 +235,38 @@ class AuthHandler:
|
|
202
235
|
Use this function if you want to allow access via either the bearer token or the API key.
|
203
236
|
This function is used for HTTP connections.
|
204
237
|
"""
|
205
|
-
|
238
|
+
try:
|
239
|
+
return await self.full_auth(
|
240
|
+
basic=None, bearer=bearer, api_key=api_key, sec=sec
|
241
|
+
)
|
242
|
+
except HTTPException as e:
|
243
|
+
raise HTTPException(
|
244
|
+
content=ExceptionContent(
|
245
|
+
error=ApiError.from_json(e.detail),
|
246
|
+
message=e.detail.get("message"),
|
247
|
+
),
|
248
|
+
headers={
|
249
|
+
AUTHENTICATE_HEADER: f"{BEARER_AUTH_SCHEME}, {APIKEY_AUTH_SCHEME}"
|
250
|
+
},
|
251
|
+
)
|
206
252
|
|
253
|
+
async def full_auth(
|
254
|
+
self,
|
255
|
+
basic: Annotated[Union[HTTPBasicCredentials, None], Depends(http_basic)] = None,
|
256
|
+
bearer: Annotated[
|
257
|
+
Union[HTTPAuthorizationCredentials, None], Depends(http_bearer)
|
258
|
+
] = None,
|
259
|
+
api_key: Annotated[Union[str, None], Depends(apikey_header)] = None,
|
260
|
+
sec: SecurityScopes = SecurityScopes(),
|
261
|
+
) -> Verify200Response:
|
262
|
+
"""
|
263
|
+
IMPORTANT: combined_auth is sufficient for most use cases. This function adds basic auth to the mix, which is needed for external services like prometheus, but is not recommended for internal use.
|
264
|
+
Verifies the bearer token, API key and basic authentication credentials and checks the scopes.
|
265
|
+
Returns early on the first successful verification, otherwise tries all available tokens.
|
266
|
+
Use this function if you want to allow access via either the bearer token, the API key or the basic authentication credentials.
|
267
|
+
This function is used for HTTP connections.
|
268
|
+
"""
|
269
|
+
tokens = [bearer, api_key, basic]
|
207
270
|
last_error = None
|
208
271
|
for token in tokens:
|
209
272
|
try:
|
@@ -214,6 +277,8 @@ class AuthHandler:
|
|
214
277
|
res = await self._verify_api_key(token)
|
215
278
|
elif isinstance(token, HTTPAuthorizationCredentials):
|
216
279
|
res = await self._verify_bearer(token)
|
280
|
+
elif isinstance(token, HTTPBasicCredentials):
|
281
|
+
res = await self._verify_basic(token)
|
217
282
|
if res is None:
|
218
283
|
continue
|
219
284
|
if sec:
|
@@ -230,9 +295,11 @@ class AuthHandler:
|
|
230
295
|
raise HTTPException(
|
231
296
|
content=ExceptionContent(
|
232
297
|
error=ApiError.NO_CREDENTIALS,
|
233
|
-
message="No credentials provided.
|
298
|
+
message="No credentials provided. Check the WWW-Authenticate header for the available authentication methods.",
|
234
299
|
),
|
235
|
-
headers={
|
300
|
+
headers={
|
301
|
+
AUTHENTICATE_HEADER: f"{BEARER_AUTH_SCHEME}, {APIKEY_AUTH_SCHEME}, {BASIC_AUTH_SCHEME}"
|
302
|
+
},
|
236
303
|
)
|
237
304
|
|
238
305
|
async def ws_api_key_auth(
|
@@ -257,7 +324,11 @@ class AuthHandler:
|
|
257
324
|
Use this function if you only want to allow access via the bearer token.
|
258
325
|
This function is used for WebSocket connections.
|
259
326
|
"""
|
260
|
-
credentials =
|
327
|
+
credentials = (
|
328
|
+
HTTPAuthorizationCredentials(scheme="Bearer", credentials=bearer)
|
329
|
+
if bearer
|
330
|
+
else None
|
331
|
+
)
|
261
332
|
return await self.bearer_auth(bearer=credentials, sec=sec)
|
262
333
|
|
263
334
|
async def ws_combined_auth(
|
@@ -277,22 +348,3 @@ class AuthHandler:
|
|
277
348
|
else None
|
278
349
|
)
|
279
350
|
return await self.combined_auth(bearer=credentials, api_key=api_key, sec=sec)
|
280
|
-
|
281
|
-
async def basic_auth(
|
282
|
-
self,
|
283
|
-
credentials: Annotated[HTTPBasicCredentials, Depends(basic_auth)],
|
284
|
-
):
|
285
|
-
"""
|
286
|
-
Verifies the basic authentication credentials. This authentication method should just be used for special cases like /admin/metrics, where JWT and API key authentication are not desired or not possible.
|
287
|
-
"""
|
288
|
-
try:
|
289
|
-
await self.client.login.verify_basic_auth(credentials.username, credentials.password)
|
290
|
-
except ApiException as e:
|
291
|
-
raise HTTPException(
|
292
|
-
content=ExceptionContent(
|
293
|
-
error=ApiError.INVALID_BASIC_AUTH,
|
294
|
-
message="Invalid basic authentication credentials",
|
295
|
-
),
|
296
|
-
headers={"WWW-Authenticate": "Basic"},
|
297
|
-
)
|
298
|
-
return credentials.username
|
crypticorn/common/decorators.py
CHANGED