svc-infra 0.1.176__tar.gz → 0.1.177__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.
- {svc_infra-0.1.176 → svc_infra-0.1.177}/PKG-INFO +1 -1
- {svc_infra-0.1.176 → svc_infra-0.1.177}/pyproject.toml +1 -1
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/add.py +18 -1
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/resource.py +1 -1
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/auth/__init__.py +1 -1
- svc_infra-0.1.176/src/svc_infra/auth/user_service.py → svc_infra-0.1.177/src/svc_infra/auth/user_default.py +6 -10
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/models_schemas/auth/models.py.tmpl +9 -1
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/models_schemas/auth/schemas.py.tmpl +1 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/README.md +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/README.md +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/crud_router.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/health.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/http.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/management.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/repository.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/service.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/service_hooks.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/db/session.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/middleware/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/middleware/errors/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/middleware/errors/catchall.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/middleware/errors/error_handlers.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/middleware/errors/exceptions.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/routers/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/routers/ping.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/settings.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/app/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/app/env.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/app/logging.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/app/root.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/app/settings.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/auth/integration.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/auth/oauth_router.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/auth/providers.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/auth/settings.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/auth/users.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/cli/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/cli/cmds/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/cli/cmds/alembic_cmds.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/cli/cmds/help.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/cli/cmds/scaffold_cmds.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/cli/foundation/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/cli/foundation/runner.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/cli/foundation/typer_bootstrap.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/README.md +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/base.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/constants.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/core.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/scaffold.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/models_schemas/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/models_schemas/entity/models.py.tmpl +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/models_schemas/entity/schemas.py.tmpl +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/setup/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/setup/alembic.ini.tmpl +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/setup/env_async.py.tmpl +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/setup/env_sync.py.tmpl +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/setup/script.py.mako.tmpl +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/utils.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/mcp/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/mcp/svc_infra_mcp.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/README.md +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/metrics/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/metrics/asgi.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/metrics/base.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/metrics/http.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/metrics/sqlalchemy.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/settings.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/templates/grafana_dashboard.json +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/templates/otel-collector.yaml +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/templates/prometheus_rules.yml +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/tracing/__init__.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/tracing/setup.py +0 -0
- {svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/py.typed +0 -0
@@ -4,6 +4,7 @@ from typing import Optional, Sequence
|
|
4
4
|
from contextlib import asynccontextmanager
|
5
5
|
from fastapi import FastAPI
|
6
6
|
|
7
|
+
from svc_infra.auth.user_default import make_default_user_service
|
7
8
|
from .repository import Repository
|
8
9
|
from .service import Service
|
9
10
|
from .crud_router import make_crud_router_plus
|
@@ -12,10 +13,25 @@ from .resource import Resource
|
|
12
13
|
from .session import initialize_session, dispose_session
|
13
14
|
from .health import _make_db_health_router
|
14
15
|
|
16
|
+
def _looks_like_user_model(model: type) -> bool:
|
17
|
+
# minimal/robust: users have email + password_hash.
|
18
|
+
# (You can tighten this with hasattr(model, "extra") / "roles" if you want.)
|
19
|
+
return hasattr(model, "email") and hasattr(model, "password_hash")
|
20
|
+
|
15
21
|
def add_resources(app: FastAPI, resources: Sequence[Resource]) -> None:
|
16
22
|
for r in resources:
|
17
23
|
repo = Repository(model=r.model, id_attr=r.id_attr, soft_delete=r.soft_delete)
|
18
|
-
|
24
|
+
|
25
|
+
# 1) explicit app-provided factory wins
|
26
|
+
if r.service_factory:
|
27
|
+
svc = r.service_factory(repo)
|
28
|
+
# 2) otherwise, auto-apply our default user service if model looks like a user
|
29
|
+
elif _looks_like_user_model(r.model):
|
30
|
+
svc = make_default_user_service(repo)
|
31
|
+
# 3) else, generic service
|
32
|
+
else:
|
33
|
+
svc = Service(repo)
|
34
|
+
|
19
35
|
if r.read_schema and r.create_schema and r.update_schema:
|
20
36
|
Read, Create, Update = r.read_schema, r.create_schema, r.update_schema
|
21
37
|
else:
|
@@ -26,6 +42,7 @@ def add_resources(app: FastAPI, resources: Sequence[Resource]) -> None:
|
|
26
42
|
create_name=r.create_name,
|
27
43
|
update_name=r.update_name,
|
28
44
|
)
|
45
|
+
|
29
46
|
router = make_crud_router_plus(
|
30
47
|
model=r.model,
|
31
48
|
service=svc,
|
@@ -6,26 +6,22 @@ from svc_infra.api.fastapi.db.repository import Repository
|
|
6
6
|
|
7
7
|
_pwd = PasswordHelper()
|
8
8
|
|
9
|
-
def
|
10
|
-
data = dict(data)
|
11
|
-
# map payload fields -> model columns
|
9
|
+
def _pre_create(data: Dict[str, Any]) -> Dict[str, Any]:
|
10
|
+
data = dict(data)
|
12
11
|
if "password" in data:
|
13
12
|
data["password_hash"] = _pwd.hash(data.pop("password"))
|
14
|
-
if "metadata" in data:
|
13
|
+
if "metadata" in data: # pydantic alias -> model column "metadata" (extra)
|
15
14
|
data["extra"] = data.pop("metadata")
|
16
|
-
# roles default if missing
|
17
15
|
data.setdefault("roles", [])
|
18
|
-
# booleans default come from model; fine to ignore if absent
|
19
16
|
return data
|
20
17
|
|
21
|
-
def
|
18
|
+
def _pre_update(data: Dict[str, Any]) -> Dict[str, Any]:
|
22
19
|
data = dict(data)
|
23
|
-
# allow password change via generic update too (optional)
|
24
20
|
if "password" in data:
|
25
21
|
data["password_hash"] = _pwd.hash(data.pop("password"))
|
26
22
|
if "metadata" in data:
|
27
23
|
data["extra"] = data.pop("metadata")
|
28
24
|
return data
|
29
25
|
|
30
|
-
def
|
31
|
-
return ServiceWithHooks(repo, pre_create=
|
26
|
+
def make_default_user_service(repo: Repository):
|
27
|
+
return ServiceWithHooks(repo, pre_create=_pre_create, pre_update=_pre_update)
|
@@ -23,8 +23,16 @@ class User(ModelBase):
|
|
23
23
|
is_superuser: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
|
24
24
|
is_verified: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
|
25
25
|
|
26
|
-
# auth state
|
27
26
|
password_hash: Mapped[str] = mapped_column(String(512), nullable=False)
|
27
|
+
|
28
|
+
@property
|
29
|
+
def password(self) -> str:
|
30
|
+
raise AttributeError("password is write-only")
|
31
|
+
|
32
|
+
@password.setter
|
33
|
+
def password(self, raw: str) -> None:
|
34
|
+
self.password_hash = _pwd.hash(raw)
|
35
|
+
|
28
36
|
last_login: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
|
29
37
|
disabled_reason: Mapped[Optional[str]] = mapped_column(Text)
|
30
38
|
|
@@ -35,6 +35,7 @@ class UserCreate(BaseModel):
|
|
35
35
|
class UserUpdate(BaseModel):
|
36
36
|
email: Optional[EmailStr] = None
|
37
37
|
full_name: Optional[str] = None
|
38
|
+
password: Optional[str] = None
|
38
39
|
is_active: Optional[bool] = None
|
39
40
|
is_superuser: Optional[bool] = None
|
40
41
|
is_verified: Optional[bool] = None
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/middleware/errors/__init__.py
RENAMED
File without changes
|
{svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/middleware/errors/catchall.py
RENAMED
File without changes
|
File without changes
|
{svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/api/fastapi/middleware/errors/exceptions.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/models_schemas/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/db/templates/setup/script.py.mako.tmpl
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/templates/grafana_dashboard.json
RENAMED
File without changes
|
{svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/templates/otel-collector.yaml
RENAMED
File without changes
|
{svc_infra-0.1.176 → svc_infra-0.1.177}/src/svc_infra/observability/templates/prometheus_rules.yml
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|