♻️ Refactor ohmyapi_auth

- remove Group and UserGroups
  (should be handled by dedicated app, if even)
- enforce User.Schema() include-fields
This commit is contained in:
Brian Wiborg 2025-10-28 14:37:45 +01:00
parent 458ffc6b2c
commit 7163fe778e
No known key found for this signature in database
3 changed files with 19 additions and 46 deletions

View file

@ -1,7 +1,7 @@
# Apps # Apps
Apps are a way to group database models and API routes that contextually belong together. Apps are a way to group database models and API routes that contextually belong together.
For example, OhMyAPI comes bundled with an `auth` app that carries a `User` and `Group` model and provides API endpoints for JWT authentication. For example, OhMyAPI comes bundled with an `auth` app that carries a `User` model and provides API endpoints for JWT authentication.
Apps help organizing projects by isolating individual components (or "features") from one another. Apps help organizing projects by isolating individual components (or "features") from one another.

View file

@ -1,27 +1,16 @@
from functools import wraps
from secrets import token_bytes
from typing import List, Optional
from uuid import UUID
from passlib.context import CryptContext
from tortoise.contrib.pydantic import pydantic_queryset_creator
from ohmyapi.db import Model, field, Q from ohmyapi.db import Model, field, Q
from ohmyapi.router import HTTPException from ohmyapi.router import HTTPException
from .utils import hmac_hash from .utils import hmac_hash
from datetime import datetime
from passlib.context import CryptContext
from typing import Optional
from uuid import UUID
pwd_context = CryptContext(schemes=["argon2"], deprecated="auto") pwd_context = CryptContext(schemes=["argon2"], deprecated="auto")
class Group(Model):
id: UUID = field.data.UUIDField(pk=True)
name: str = field.CharField(max_length=42, index=True)
def __str__(self):
return self.name if self.name else ""
class User(Model): class User(Model):
id: UUID = field.data.UUIDField(pk=True) id: UUID = field.data.UUIDField(pk=True)
username: str = field.CharField(max_length=150, unique=True) username: str = field.CharField(max_length=150, unique=True)
@ -29,20 +18,22 @@ class User(Model):
password_hash: str = field.CharField(max_length=128) password_hash: str = field.CharField(max_length=128)
is_admin: bool = field.BooleanField(default=False) is_admin: bool = field.BooleanField(default=False)
is_staff: bool = field.BooleanField(default=False) is_staff: bool = field.BooleanField(default=False)
groups: field.ManyToManyRelation[Group] = field.ManyToManyField( created_at: datetime = field.DatetimeField(auto_now_add=True)
"ohmyapi_auth.Group", updated_at: datetime = field.DatetimeField(auto_now=True)
related_name="users",
through="ohmyapi_auth.UserGroups",
forward_key="user_id",
backward_key="group_id",
)
class Schema: class Schema:
exclude = ["password_hash", "email_hash"] include = {
"id",
"username",
"is_admin",
"is_staff"
"created_at",
"updated_at",
}
def __str__(self): def __str__(self):
fields = { fields = {
'username': self.username if self.username else "-", 'username': self.username,
'is_admin': 'y' if self.is_admin else 'n', 'is_admin': 'y' if self.is_admin else 'n',
'is_staff': 'y' if self.is_staff else 'n', 'is_staff': 'y' if self.is_staff else 'n',
} }
@ -67,20 +58,3 @@ class User(Model):
if user and user.verify_password(password): if user and user.verify_password(password):
return user return user
return None return None
class UserGroups(Model):
user: field.ForeignKeyRelation[User] = field.ForeignKeyField(
"ohmyapi_auth.User",
related_name="user_groups",
index=True,
)
group: field.ForeignKeyRelation[Group] = field.ForeignKeyField(
"ohmyapi_auth.Group",
related_name="group_users",
index=True,
)
class Meta:
table = "ohmyapi_auth_user_groups"
constraints = [("UNIQUE", ("user_id", "group_id"))]

View file

@ -8,7 +8,7 @@ from fastapi.security.utils import get_authorization_scheme_param
from pydantic import BaseModel from pydantic import BaseModel
from tortoise.exceptions import DoesNotExist from tortoise.exceptions import DoesNotExist
from ohmyapi.builtin.auth.models import Group, User from ohmyapi.builtin.auth.models import User
import jwt import jwt
import settings import settings
@ -80,7 +80,7 @@ class TokenType(str, Enum):
refresh = "refresh" refresh = "refresh"
def claims(token_type: TokenType, user: User, groups: List[Group] = []) -> Claims: def claims(token_type: TokenType, user: User = []) -> Claims:
return Claims( return Claims(
type=token_type, type=token_type,
sub=str(user.id), sub=str(user.id),
@ -89,7 +89,6 @@ def claims(token_type: TokenType, user: User, groups: List[Group] = []) -> Claim
is_admin=user.is_admin, is_admin=user.is_admin,
is_staff=user.is_staff, is_staff=user.is_staff,
), ),
roles=[g.name for g in groups],
exp="", exp="",
) )