apexauthlib 0.1.3__tar.gz → 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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: apexauthlib
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: Apex authorization library for services
5
5
  Author: Apex Dev
6
6
  Author-email: dev@apex.ge
@@ -1,7 +1,9 @@
1
1
  from dataclasses import dataclass, field
2
- from typing import Any
2
+ from typing import Any, Generic, TypeVar
3
3
  from uuid import uuid4
4
4
 
5
+ ItemT = TypeVar("ItemT")
6
+
5
7
 
6
8
  @dataclass(frozen=True)
7
9
  class User:
@@ -33,3 +35,16 @@ class ServiceMetadata:
33
35
  class UserMetadata:
34
36
  service: str
35
37
  metadata: dict[str, Any]
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class Client:
42
+ client_id: str
43
+ hashed_secret: str
44
+
45
+
46
+ @dataclass(frozen=True)
47
+ class ServiceUserInfo(Generic[ItemT]):
48
+ user: User
49
+ is_superuser: bool
50
+ metadata: ItemT
@@ -7,10 +7,12 @@ from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
7
7
  from starlette import status
8
8
 
9
9
  from apexauthlib.entities import User
10
- from apexauthlib.integration.api import AuthApiProvider
10
+ from apexauthlib.entities.auth import ServiceUserInfo
11
+ from apexauthlib.integration.api import AuthApiProvider, AuthCodeApi
11
12
 
12
13
  auth_api = APIRouter(tags=["Auth"])
13
14
  AuthApiProviderDependable = Annotated[AuthApiProvider[Any], inject("auth")]
15
+ AuthCodeApiDependable = Annotated[AuthCodeApi, inject("auth_code")]
14
16
 
15
17
 
16
18
  def oauth2() -> OAuth2PasswordBearer:
@@ -66,6 +68,21 @@ def get_user_with_metadata(
66
68
  )
67
69
 
68
70
 
71
+ def get_user_with_full_metadata(
72
+ token: TokenDependable,
73
+ auth: AuthApiProviderDependable,
74
+ ) -> ServiceUserInfo[Any]:
75
+ try:
76
+ api = auth.for_token(token)
77
+ return api.full_metadata_for(api.user().id)
78
+ except Exception as e:
79
+ raise HTTPException(
80
+ status_code=status.HTTP_401_UNAUTHORIZED,
81
+ detail=str(e),
82
+ headers={"WWW-Authenticate": "Bearer"},
83
+ )
84
+
85
+
69
86
  @dataclass
70
87
  class TokenResponse:
71
88
  access_token: str
@@ -90,3 +107,23 @@ def login(
90
107
  status_code=status.HTTP_401_UNAUTHORIZED,
91
108
  detail="Incorrect username or password",
92
109
  )
110
+
111
+
112
+ @auth_api.post(
113
+ "/login/code",
114
+ status_code=200,
115
+ response_model=TokenResponse,
116
+ )
117
+ def login_code(
118
+ code: str,
119
+ auth_code: AuthCodeApiDependable,
120
+ ) -> TokenResponse:
121
+ try:
122
+ return TokenResponse(
123
+ access_token=auth_code.token_for(code),
124
+ )
125
+ except Exception:
126
+ raise HTTPException(
127
+ status_code=status.HTTP_401_UNAUTHORIZED,
128
+ detail="Incorrect username or password",
129
+ )
@@ -1,14 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
- from dataclasses import dataclass
4
- from typing import Any, Generic, Mapping, TypeVar
3
+ from dataclasses import dataclass, field
4
+ from typing import Any, Generic, Mapping
5
5
 
6
6
  from apexdevkit.formatter import DataclassFormatter, Formatter
7
7
  from apexdevkit.http import FluentHttp, JsonDict
8
8
 
9
9
  from apexauthlib.entities import User
10
-
11
- ItemT = TypeVar("ItemT")
10
+ from apexauthlib.entities.auth import ItemT, ServiceUserInfo
12
11
 
13
12
 
14
13
  @dataclass(frozen=True)
@@ -48,6 +47,10 @@ class AuthApi(Generic[ItemT]):
48
47
  formatter: Formatter[Mapping[str, Any], ItemT]
49
48
  token: str
50
49
 
50
+ user_formatter: Formatter[Mapping[str, Any], User] = field(
51
+ default_factory=lambda: DataclassFormatter(User)
52
+ )
53
+
51
54
  def user(self) -> User:
52
55
  return DataclassFormatter(User).load(
53
56
  (
@@ -71,3 +74,47 @@ class AuthApi(Generic[ItemT]):
71
74
  )
72
75
 
73
76
  return self.formatter.load(JsonDict(result["data"]["metadata"]["metadata"]))
77
+
78
+ def full_metadata_for(self, user_id: str) -> ServiceUserInfo[ItemT]:
79
+ result = JsonDict(
80
+ (
81
+ self.http.with_header("Authorization", f"Bearer {self.token}")
82
+ .get()
83
+ .on_endpoint(f"/services/{self.service_name}/users/{user_id}")
84
+ .on_failure(raises=RuntimeError)
85
+ .json()
86
+ )
87
+ )["data"]["user"]
88
+
89
+ user = dict(result["user"])
90
+ user["hashed_password"] = "unknown"
91
+
92
+ return ServiceUserInfo[ItemT](
93
+ user=self.user_formatter.load(user),
94
+ is_superuser=bool(result["is_superuser"]),
95
+ metadata=self.formatter.load(result["metadata"]),
96
+ )
97
+
98
+
99
+ @dataclass
100
+ class AuthCodeApi:
101
+ http: FluentHttp
102
+ client_id: str
103
+ client_secret: str
104
+
105
+ def token_for(self, code: str) -> str:
106
+ data = {
107
+ "code": code,
108
+ "client_id": self.client_id,
109
+ "client_secret": self.client_secret,
110
+ }
111
+
112
+ return str(
113
+ (
114
+ self.http.with_data(JsonDict(data))
115
+ .post()
116
+ .on_endpoint("/auth/oauth/token")
117
+ .on_failure(raises=RuntimeError)
118
+ .json()
119
+ )["access_token"]
120
+ )
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "apexauthlib"
3
- version = "0.1.3"
3
+ version = "0.1.5"
4
4
  description = "Apex authorization library for services"
5
5
  authors = [{ name = "Apex Dev", email = "dev@apex.ge" }]
6
6
  readme = "README.md"
File without changes
File without changes