ohmyapi 0.4.5__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 CHANGED
@@ -1 +1 @@
1
- __VERSION__ = "0.4.5"
1
+ __VERSION__ = "0.4.7"
@@ -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 authenticate_username(cls, username: str, password: str) -> Optional["User"]:
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):
@@ -1,6 +1,7 @@
1
1
  from .routes import (
2
2
  get_current_user,
3
3
  get_token,
4
+ maybe_authenticated,
4
5
  require_admin,
5
6
  require_authenticated,
6
7
  require_group,
@@ -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 jwt
6
- import settings
7
- from fastapi import APIRouter, Body, Depends, Header, HTTPException, status
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 optionally_authenticated(token: Optional[str] = Depends(oauth2_scheme)) -> Optional[User]:
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.5
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=HnnSH0gG1g7ATAegc_GYeIjnfe5EsX83POJ_loJ2i_s,22
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=FJ-F7wY5tXBSZl5YZth6UzhBSFISVCZNc2gp2uKvmR0,2602
5
- ohmyapi/builtin/auth/permissions.py,sha256=mxsnhF_UGesTFle7v1JHORkNODtQ0qanAL3FtOcMCEY,145
6
- ohmyapi/builtin/auth/routes.py,sha256=I1WK3iyWcOAYrUIXUk8GAmbxq9sNkZyw4YBw5MCgym0,6500
4
+ ohmyapi/builtin/auth/models.py,sha256=GXYSSdNdKomlcY5jh8sjxXj7HY6FgttusQ9w73usyVA,2593
5
+ ohmyapi/builtin/auth/permissions.py,sha256=jpfiGf7CA8ghy7wI5OBYBafpqDsqM0SQYliCOGh7ZjA,170
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=sXIlbRAzTvDzfJNB1COk0CHaUUfc-Vflmx6cVVoLRRg,13822
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.5.dist-info/METADATA,sha256=Y2MKvxvMoNFdDoUioJY-UHtmJDys9k9VjB4dFgDECBI,2657
30
- ohmyapi-0.4.5.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
31
- ohmyapi-0.4.5.dist-info/entry_points.txt,sha256=wb3lw8-meAlpiv1mqcQ3m25ukL7djagU_w89GkrC37k,43
32
- ohmyapi-0.4.5.dist-info/RECORD,,
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,,