ohmyapi 0.4.6__py3-none-any.whl → 0.4.7__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.
- ohmyapi/__init__.py +1 -1
- ohmyapi/builtin/auth/models.py +1 -1
- ohmyapi/builtin/auth/routes.py +21 -7
- ohmyapi/core/runtime.py +8 -8
- {ohmyapi-0.4.6.dist-info → ohmyapi-0.4.7.dist-info}/METADATA +1 -1
- {ohmyapi-0.4.6.dist-info → ohmyapi-0.4.7.dist-info}/RECORD +8 -8
- {ohmyapi-0.4.6.dist-info → ohmyapi-0.4.7.dist-info}/WHEEL +0 -0
- {ohmyapi-0.4.6.dist-info → ohmyapi-0.4.7.dist-info}/entry_points.txt +0 -0
ohmyapi/__init__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__VERSION__ = "0.4.
|
1
|
+
__VERSION__ = "0.4.7"
|
ohmyapi/builtin/auth/models.py
CHANGED
@@ -66,7 +66,7 @@ class User(Model):
|
|
66
66
|
return pwd_context.verify(raw_password, self.password_hash)
|
67
67
|
|
68
68
|
@classmethod
|
69
|
-
async def
|
69
|
+
async def authenticate(cls, username: str, password: str) -> Optional["User"]:
|
70
70
|
"""Authenticate a user by username and password."""
|
71
71
|
user = await cls.filter(username=username).first()
|
72
72
|
if user and user.verify_password(password):
|
ohmyapi/builtin/auth/routes.py
CHANGED
@@ -2,14 +2,16 @@ import time
|
|
2
2
|
from enum import Enum
|
3
3
|
from typing import Any, Dict, List, Optional
|
4
4
|
|
5
|
-
import
|
6
|
-
import
|
7
|
-
from fastapi import
|
8
|
-
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
5
|
+
from fastapi import APIRouter, Body, Depends, Header, HTTPException, Request, status
|
6
|
+
from fastapi.security import OAuth2, OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
7
|
+
from fastapi.security.utils import get_authorization_scheme_param
|
9
8
|
from pydantic import BaseModel
|
10
9
|
|
11
10
|
from ohmyapi.builtin.auth.models import Group, User
|
12
11
|
|
12
|
+
import jwt
|
13
|
+
import settings
|
14
|
+
|
13
15
|
# Router
|
14
16
|
router = APIRouter(prefix="/auth", tags=["Auth"])
|
15
17
|
|
@@ -23,12 +25,25 @@ REFRESH_TOKEN_EXPIRE_SECONDS = getattr(
|
|
23
25
|
settings, "JWT_REFRESH_TOKEN_EXPIRE_SECONDS", 7 * 24 * 60 * 60
|
24
26
|
)
|
25
27
|
|
28
|
+
class OptionalOAuth2PasswordBearer(OAuth2):
|
29
|
+
def __init__(self, tokenUrl: str):
|
30
|
+
super().__init__(flows={"password": {"tokenUrl": tokenUrl}}, scheme_name="OAuth2PasswordBearer")
|
31
|
+
|
32
|
+
async def __call__(self, request: Request) -> Optional[str]:
|
33
|
+
authorization: str = request.headers.get("Authorization")
|
34
|
+
scheme, param = get_authorization_scheme_param(authorization)
|
35
|
+
if not authorization or scheme.lower() != "bearer":
|
36
|
+
# No token provided — just return None
|
37
|
+
return None
|
38
|
+
return param
|
39
|
+
|
40
|
+
|
26
41
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login")
|
42
|
+
oauth2_optional_scheme = OptionalOAuth2PasswordBearer(tokenUrl="/auth/login")
|
27
43
|
|
28
44
|
|
29
45
|
class ClaimsUser(BaseModel):
|
30
46
|
username: str
|
31
|
-
email: str
|
32
47
|
is_admin: bool
|
33
48
|
is_staff: bool
|
34
49
|
|
@@ -70,7 +85,6 @@ def claims(token_type: TokenType, user: User, groups: List[Group] = []) -> Claim
|
|
70
85
|
sub=str(user.id),
|
71
86
|
user=ClaimsUser(
|
72
87
|
username=user.username,
|
73
|
-
email=user.email,
|
74
88
|
is_admin=user.is_admin,
|
75
89
|
is_staff=user.is_staff,
|
76
90
|
),
|
@@ -124,7 +138,7 @@ async def get_current_user(token: str = Depends(oauth2_scheme)) -> User:
|
|
124
138
|
return user
|
125
139
|
|
126
140
|
|
127
|
-
async def maybe_authenticated(token: Optional[str] = Depends(
|
141
|
+
async def maybe_authenticated(token: Optional[str] = Depends(oauth2_optional_scheme)) -> Optional[User]:
|
128
142
|
if token is None:
|
129
143
|
return None
|
130
144
|
return await get_current_user(token)
|
ohmyapi/core/runtime.py
CHANGED
@@ -40,6 +40,14 @@ class Project:
|
|
40
40
|
if str(self.project_path) not in sys.path:
|
41
41
|
sys.path.insert(0, str(self.project_path))
|
42
42
|
|
43
|
+
# Load settings.py
|
44
|
+
try:
|
45
|
+
self.settings = importlib.import_module("settings")
|
46
|
+
except Exception as e:
|
47
|
+
raise RuntimeError(
|
48
|
+
f"Failed to import project settings from {self.project_path}"
|
49
|
+
) from e
|
50
|
+
|
43
51
|
# Alias builtin apps as ohmyapi_<name>.
|
44
52
|
# We need this, because Tortoise app-names may not include dots `.`.
|
45
53
|
spec = importlib.util.find_spec("ohmyapi.builtin")
|
@@ -57,14 +65,6 @@ class Project:
|
|
57
65
|
except ModuleNotFoundError:
|
58
66
|
pass
|
59
67
|
|
60
|
-
# Load settings.py
|
61
|
-
try:
|
62
|
-
self.settings = importlib.import_module("settings")
|
63
|
-
except Exception as e:
|
64
|
-
raise RuntimeError(
|
65
|
-
f"Failed to import project settings from {self.project_path}"
|
66
|
-
) from e
|
67
|
-
|
68
68
|
# Load installed apps
|
69
69
|
for app_name in getattr(self.settings, "INSTALLED_APPS", []):
|
70
70
|
self._apps[app_name] = App(self, name=app_name)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: ohmyapi
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.7
|
4
4
|
Summary: Django-flavored scaffolding and management layer around FastAPI, Pydantic, TortoiseORM and Aerich migrations
|
5
5
|
License-Expression: MIT
|
6
6
|
Keywords: fastapi,tortoise,orm,pydantic,async,web-framework
|
@@ -1,16 +1,16 @@
|
|
1
|
-
ohmyapi/__init__.py,sha256=
|
1
|
+
ohmyapi/__init__.py,sha256=3dsUOCvM16TDxvcoMYe1SuKxNaZ9jZXHay8N798iVaQ,22
|
2
2
|
ohmyapi/__main__.py,sha256=wcCrL4PjG51r5wVKqJhcoJPTLfHW0wNbD31DrUN0MWI,28
|
3
3
|
ohmyapi/builtin/auth/__init__.py,sha256=vOVCSJX8BALzs8h5ZW9507bjoscP37bncMjdMmBXcMM,42
|
4
|
-
ohmyapi/builtin/auth/models.py,sha256=
|
4
|
+
ohmyapi/builtin/auth/models.py,sha256=GXYSSdNdKomlcY5jh8sjxXj7HY6FgttusQ9w73usyVA,2593
|
5
5
|
ohmyapi/builtin/auth/permissions.py,sha256=jpfiGf7CA8ghy7wI5OBYBafpqDsqM0SQYliCOGh7ZjA,170
|
6
|
-
ohmyapi/builtin/auth/routes.py,sha256=
|
6
|
+
ohmyapi/builtin/auth/routes.py,sha256=LKN79_rllymkObguR8ooS8JVZLBdH37TR2CnJ1fI4lA,7171
|
7
7
|
ohmyapi/builtin/demo/__init__.py,sha256=44Yo3mYmlKSKEwVp6O9urr-C_3qDQzCYLMn6B9i6wew,29
|
8
8
|
ohmyapi/builtin/demo/models.py,sha256=r06rfuhPJaI2fYsQ24L1JCOd67f2GQNfGnkgKAptOX8,1404
|
9
9
|
ohmyapi/builtin/demo/routes.py,sha256=1VTlEttrez6Qnhrz_9sTA-emtfXem0s0BkPVcLvg3k0,1801
|
10
10
|
ohmyapi/cli.py,sha256=iWP0vPkodC_Y3MenNs9AH8FR_d-XpoXliGtz4inWkR4,5114
|
11
11
|
ohmyapi/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
12
|
ohmyapi/core/logging.py,sha256=YHN-I2--WP1uXy4W3Q1aD1XLiG9-CrVWvyCYe8HsD9E,1094
|
13
|
-
ohmyapi/core/runtime.py,sha256=
|
13
|
+
ohmyapi/core/runtime.py,sha256=n1OLGlPSks6V67MBX7ZTUuNneLRg_qAD2lVumHPZb3I,13822
|
14
14
|
ohmyapi/core/scaffolding.py,sha256=EehJesfDBB8vcMvc_T351QYdyJuyMGBA__BpLT33oVA,3122
|
15
15
|
ohmyapi/core/templates/app/__init__.py.j2,sha256=QwVIQVUGZVhdH1d4NrvL7NTsK4-T4cihzYs8UVX2dt4,43
|
16
16
|
ohmyapi/core/templates/app/models.py.j2,sha256=_3w-vFJ5fgsmncsCv34k_wyCMF78jufbSSglns4gbb0,119
|
@@ -26,7 +26,7 @@ ohmyapi/db/model/__init__.py,sha256=k3StTNuKatpwZo_Z5JBFa-927eJrzibFE8U4SA82asc,
|
|
26
26
|
ohmyapi/db/model/model.py,sha256=ui4g78c5xoS06Dj8Cdk7QgTjRnE68zKeL-AdmeYYPuQ,2776
|
27
27
|
ohmyapi/middleware/cors.py,sha256=p8HlKsZLM6jKLEa2-q22cIEZUKawirMQB9ajfxaM4xw,818
|
28
28
|
ohmyapi/router.py,sha256=5g0U59glu4hxxnIoTSFzb2S2offkOT3eE39aprzVxwo,83
|
29
|
-
ohmyapi-0.4.
|
30
|
-
ohmyapi-0.4.
|
31
|
-
ohmyapi-0.4.
|
32
|
-
ohmyapi-0.4.
|
29
|
+
ohmyapi-0.4.7.dist-info/METADATA,sha256=9DxryMIXrrCWLaGGOkehOcq3BaC1a8ea6-fVs1p2YLA,2657
|
30
|
+
ohmyapi-0.4.7.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
31
|
+
ohmyapi-0.4.7.dist-info/entry_points.txt,sha256=wb3lw8-meAlpiv1mqcQ3m25ukL7djagU_w89GkrC37k,43
|
32
|
+
ohmyapi-0.4.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|