pachifast 0.15.0__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.
- pachifast-0.15.0/.gitignore +17 -0
- pachifast-0.15.0/CHANGELOG.md +25 -0
- pachifast-0.15.0/LICENSE +21 -0
- pachifast-0.15.0/PKG-INFO +158 -0
- pachifast-0.15.0/README.it.md +95 -0
- pachifast-0.15.0/README.md +103 -0
- pachifast-0.15.0/examples/demo/.env.example +3 -0
- pachifast-0.15.0/examples/demo/.gitignore +12 -0
- pachifast-0.15.0/examples/demo/README.md +36 -0
- pachifast-0.15.0/examples/demo/apps/__init__.py +0 -0
- pachifast-0.15.0/examples/demo/apps/demo/__init__.py +0 -0
- pachifast-0.15.0/examples/demo/apps/demo/admin.py +42 -0
- pachifast-0.15.0/examples/demo/apps/demo/data.py +62 -0
- pachifast-0.15.0/examples/demo/apps/demo/files.py +116 -0
- pachifast-0.15.0/examples/demo/apps/demo/items.py +137 -0
- pachifast-0.15.0/examples/demo/apps/demo/lab.py +110 -0
- pachifast-0.15.0/examples/demo/apps/demo/locale/__init__.py +0 -0
- pachifast-0.15.0/examples/demo/apps/demo/locale/en.py +20 -0
- pachifast-0.15.0/examples/demo/apps/demo/locale/it.py +20 -0
- pachifast-0.15.0/examples/demo/apps/demo/lookups.py +38 -0
- pachifast-0.15.0/examples/demo/apps/demo/models.py +41 -0
- pachifast-0.15.0/examples/demo/apps/demo/module.py +18 -0
- pachifast-0.15.0/examples/demo/apps/demo/seed.py +39 -0
- pachifast-0.15.0/examples/demo/apps/demo/settings.py +32 -0
- pachifast-0.15.0/examples/demo/apps/demo/user_settings.py +16 -0
- pachifast-0.15.0/examples/demo/common/__init__.py +0 -0
- pachifast-0.15.0/examples/demo/main.py +11 -0
- pachifast-0.15.0/examples/demo/migrations/auth/env.py +11 -0
- pachifast-0.15.0/examples/demo/migrations/auth/script.py.mako +20 -0
- pachifast-0.15.0/examples/demo/migrations/auth/versions/.gitkeep +0 -0
- pachifast-0.15.0/examples/demo/migrations/auth/versions/5b4eb75fc01a_init.py +88 -0
- pachifast-0.15.0/examples/demo/migrations/auth/versions/762aa2acf6e7_foreign_keys_of_the_association_tables.py +55 -0
- pachifast-0.15.0/examples/demo/migrations/auth/versions/90c0a092913c_totp_last_step.py +28 -0
- pachifast-0.15.0/examples/demo/migrations/auth/versions/92c7372f20a8_activity_log_and_mfa_tables.py +69 -0
- pachifast-0.15.0/examples/demo/migrations/auth/versions/c41d7e2a9b10_totp_secret_encrypted.py +26 -0
- pachifast-0.15.0/examples/demo/migrations/auth/versions/e48e7d24fc99_refresh_tokens.py +43 -0
- pachifast-0.15.0/examples/demo/migrations/auth/versions/e7d9031f255a_ws_tickets.py +32 -0
- pachifast-0.15.0/examples/demo/migrations/demo/env.py +11 -0
- pachifast-0.15.0/examples/demo/migrations/demo/script.py.mako +20 -0
- pachifast-0.15.0/examples/demo/migrations/demo/versions/.gitkeep +0 -0
- pachifast-0.15.0/examples/demo/migrations/demo/versions/fe109b1b386b_demo_tables.py +53 -0
- pachifast-0.15.0/examples/demo/pachifast.schema.json +450 -0
- pachifast-0.15.0/examples/demo/pachifast.yaml +6 -0
- pachifast-0.15.0/examples/demo/project_modules.py +12 -0
- pachifast-0.15.0/examples/demo/pyproject.toml +13 -0
- pachifast-0.15.0/pyproject.toml +109 -0
- pachifast-0.15.0/src/pachifast/__init__.py +13 -0
- pachifast-0.15.0/src/pachifast/admin/__init__.py +28 -0
- pachifast-0.15.0/src/pachifast/admin/fields.py +293 -0
- pachifast-0.15.0/src/pachifast/admin/generic.py +436 -0
- pachifast-0.15.0/src/pachifast/admin/history.py +43 -0
- pachifast-0.15.0/src/pachifast/admin/models.py +35 -0
- pachifast-0.15.0/src/pachifast/admin/permissions.py +157 -0
- pachifast-0.15.0/src/pachifast/admin/permissions_sync.py +58 -0
- pachifast-0.15.0/src/pachifast/admin/registry.py +178 -0
- pachifast-0.15.0/src/pachifast/admin/schema.py +196 -0
- pachifast-0.15.0/src/pachifast/admin/schemas.py +18 -0
- pachifast-0.15.0/src/pachifast/admin/user.py +116 -0
- pachifast-0.15.0/src/pachifast/app_factory.py +187 -0
- pachifast-0.15.0/src/pachifast/audit/__init__.py +0 -0
- pachifast-0.15.0/src/pachifast/audit/middleware.py +207 -0
- pachifast-0.15.0/src/pachifast/audit/models.py +33 -0
- pachifast-0.15.0/src/pachifast/audit/root.py +128 -0
- pachifast-0.15.0/src/pachifast/auth/__init__.py +1 -0
- pachifast-0.15.0/src/pachifast/auth/cruds.py +507 -0
- pachifast-0.15.0/src/pachifast/auth/dependencies.py +240 -0
- pachifast-0.15.0/src/pachifast/auth/labels.py +73 -0
- pachifast-0.15.0/src/pachifast/auth/models.py +142 -0
- pachifast-0.15.0/src/pachifast/auth/permission_provider.py +43 -0
- pachifast-0.15.0/src/pachifast/auth/profile.py +116 -0
- pachifast-0.15.0/src/pachifast/auth/root.py +173 -0
- pachifast-0.15.0/src/pachifast/auth/schemas.py +146 -0
- pachifast-0.15.0/src/pachifast/auth/security.py +474 -0
- pachifast-0.15.0/src/pachifast/auth/user.py +157 -0
- pachifast-0.15.0/src/pachifast/auth/user_settings.py +0 -0
- pachifast-0.15.0/src/pachifast/auth/user_settings_discover.py +491 -0
- pachifast-0.15.0/src/pachifast/cache/__init__.py +8 -0
- pachifast-0.15.0/src/pachifast/cache/base.py +35 -0
- pachifast-0.15.0/src/pachifast/cache/factory.py +27 -0
- pachifast-0.15.0/src/pachifast/cache/memory.py +70 -0
- pachifast-0.15.0/src/pachifast/cache/redis_backend.py +59 -0
- pachifast-0.15.0/src/pachifast/cli/__init__.py +5 -0
- pachifast-0.15.0/src/pachifast/cli/app.py +51 -0
- pachifast-0.15.0/src/pachifast/cli/commands/__init__.py +1 -0
- pachifast-0.15.0/src/pachifast/cli/commands/audit.py +29 -0
- pachifast-0.15.0/src/pachifast/cli/commands/completion.py +5 -0
- pachifast-0.15.0/src/pachifast/cli/commands/config.py +30 -0
- pachifast-0.15.0/src/pachifast/cli/commands/dev.py +20 -0
- pachifast-0.15.0/src/pachifast/cli/commands/init.py +56 -0
- pachifast-0.15.0/src/pachifast/cli/commands/locale.py +201 -0
- pachifast-0.15.0/src/pachifast/cli/commands/migrations.py +87 -0
- pachifast-0.15.0/src/pachifast/cli/commands/new.py +298 -0
- pachifast-0.15.0/src/pachifast/cli/commands/serve.py +51 -0
- pachifast-0.15.0/src/pachifast/cli/commands/users.py +137 -0
- pachifast-0.15.0/src/pachifast/cli/helpers/__init__.py +21 -0
- pachifast-0.15.0/src/pachifast/cli/helpers/console.py +32 -0
- pachifast-0.15.0/src/pachifast/cli/helpers/git.py +72 -0
- pachifast-0.15.0/src/pachifast/cli/helpers/project.py +55 -0
- pachifast-0.15.0/src/pachifast/cli/helpers/prompt.py +18 -0
- pachifast-0.15.0/src/pachifast/cli/helpers/version.py +11 -0
- pachifast-0.15.0/src/pachifast/cli/services/__init__.py +1 -0
- pachifast-0.15.0/src/pachifast/cli/services/audit.py +46 -0
- pachifast-0.15.0/src/pachifast/cli/services/dev.py +75 -0
- pachifast-0.15.0/src/pachifast/cli/services/init.py +239 -0
- pachifast-0.15.0/src/pachifast/cli/services/locale.py +117 -0
- pachifast-0.15.0/src/pachifast/cli/services/serve.py +85 -0
- pachifast-0.15.0/src/pachifast/cli/services/users.py +264 -0
- pachifast-0.15.0/src/pachifast/config/__init__.py +19 -0
- pachifast-0.15.0/src/pachifast/config/helpers.py +26 -0
- pachifast-0.15.0/src/pachifast/config/schema.py +126 -0
- pachifast-0.15.0/src/pachifast/config/settings.py +307 -0
- pachifast-0.15.0/src/pachifast/config/settings_discovery.py +44 -0
- pachifast-0.15.0/src/pachifast/config/yaml_source.py +92 -0
- pachifast-0.15.0/src/pachifast/database/__init__.py +55 -0
- pachifast-0.15.0/src/pachifast/database/aliased_models.py +5 -0
- pachifast-0.15.0/src/pachifast/database/base.py +23 -0
- pachifast-0.15.0/src/pachifast/database/encrypted.py +79 -0
- pachifast-0.15.0/src/pachifast/database/engine.py +198 -0
- pachifast-0.15.0/src/pachifast/database/helpers.py +80 -0
- pachifast-0.15.0/src/pachifast/database/model_discovery.py +53 -0
- pachifast-0.15.0/src/pachifast/database/pagination.py +137 -0
- pachifast-0.15.0/src/pachifast/database/sync.py +76 -0
- pachifast-0.15.0/src/pachifast/database/types.py +11 -0
- pachifast-0.15.0/src/pachifast/database/utils.py +51 -0
- pachifast-0.15.0/src/pachifast/dependencies.py +31 -0
- pachifast-0.15.0/src/pachifast/errors.py +87 -0
- pachifast-0.15.0/src/pachifast/events/__init__.py +3 -0
- pachifast-0.15.0/src/pachifast/events/broadcaster.py +137 -0
- pachifast-0.15.0/src/pachifast/events/models.py +26 -0
- pachifast-0.15.0/src/pachifast/events/root.py +224 -0
- pachifast-0.15.0/src/pachifast/events/tickets.py +94 -0
- pachifast-0.15.0/src/pachifast/health/__init__.py +0 -0
- pachifast-0.15.0/src/pachifast/health/health.py +70 -0
- pachifast-0.15.0/src/pachifast/health/schemas.py +12 -0
- pachifast-0.15.0/src/pachifast/i18n/__init__.py +29 -0
- pachifast-0.15.0/src/pachifast/i18n/catalogs.py +40 -0
- pachifast-0.15.0/src/pachifast/i18n/exporter.py +156 -0
- pachifast-0.15.0/src/pachifast/i18n/loader.py +202 -0
- pachifast-0.15.0/src/pachifast/i18n/locale/__init__.py +1 -0
- pachifast-0.15.0/src/pachifast/i18n/locale/en.py +94 -0
- pachifast-0.15.0/src/pachifast/i18n/locale/it.py +94 -0
- pachifast-0.15.0/src/pachifast/i18n/middleware.py +30 -0
- pachifast-0.15.0/src/pachifast/i18n/translator.py +156 -0
- pachifast-0.15.0/src/pachifast/infos/__init__.py +1 -0
- pachifast-0.15.0/src/pachifast/infos/engine/__init__.py +4 -0
- pachifast-0.15.0/src/pachifast/infos/engine/engine_helper.py +58 -0
- pachifast-0.15.0/src/pachifast/infos/engine/schemas.py +17 -0
- pachifast-0.15.0/src/pachifast/infos/root.py +16 -0
- pachifast-0.15.0/src/pachifast/logging/__init__.py +0 -0
- pachifast-0.15.0/src/pachifast/logging/customformatter.py +31 -0
- pachifast-0.15.0/src/pachifast/logging/jsonformatter.py +22 -0
- pachifast-0.15.0/src/pachifast/logging/request_id.py +61 -0
- pachifast-0.15.0/src/pachifast/mfa/__init__.py +47 -0
- pachifast-0.15.0/src/pachifast/mfa/cruds.py +210 -0
- pachifast-0.15.0/src/pachifast/mfa/models.py +54 -0
- pachifast-0.15.0/src/pachifast/mfa/root.py +435 -0
- pachifast-0.15.0/src/pachifast/mfa/schemas.py +89 -0
- pachifast-0.15.0/src/pachifast/mfa/security.py +218 -0
- pachifast-0.15.0/src/pachifast/mfa/sender.py +58 -0
- pachifast-0.15.0/src/pachifast/migrations/__init__.py +21 -0
- pachifast-0.15.0/src/pachifast/migrations/manager.py +165 -0
- pachifast-0.15.0/src/pachifast/migrations/runtime.py +285 -0
- pachifast-0.15.0/src/pachifast/module.py +30 -0
- pachifast-0.15.0/src/pachifast/modules.py +276 -0
- pachifast-0.15.0/src/pachifast/openapi/__init__.py +1 -0
- pachifast-0.15.0/src/pachifast/openapi/openapi_setup.py +162 -0
- pachifast-0.15.0/src/pachifast/presets.py +5 -0
- pachifast-0.15.0/src/pachifast/py.typed +0 -0
- pachifast-0.15.0/src/pachifast/ratelimit.py +61 -0
- pachifast-0.15.0/src/pachifast/router_factory.py +5 -0
- pachifast-0.15.0/src/pachifast/routing/__init__.py +0 -0
- pachifast-0.15.0/src/pachifast/routing/auto_response_router.py +16 -0
- pachifast-0.15.0/src/pachifast/routing/core_filters.py +160 -0
- pachifast-0.15.0/src/pachifast/routing/discover.py +46 -0
- pachifast-0.15.0/src/pachifast/routing/envelope_route.py +73 -0
- pachifast-0.15.0/src/pachifast/routing/file_discover.py +44 -0
- pachifast-0.15.0/src/pachifast/routing/permissioned_router.py +238 -0
- pachifast-0.15.0/src/pachifast/routing/router_factory.py +81 -0
- pachifast-0.15.0/src/pachifast/scaffold/__init__.py +21 -0
- pachifast-0.15.0/src/pachifast/scaffold/generators.py +262 -0
- pachifast-0.15.0/src/pachifast/scaffold/helpers.py +35 -0
- pachifast-0.15.0/src/pachifast/scaffold/metadata.py +132 -0
- pachifast-0.15.0/src/pachifast/scaffold/pipelines.py +365 -0
- pachifast-0.15.0/src/pachifast/scaffold/templates.py +309 -0
- pachifast-0.15.0/src/pachifast/schemas/__init__.py +1 -0
- pachifast-0.15.0/src/pachifast/schemas/aliased.py +16 -0
- pachifast-0.15.0/src/pachifast/schemas/responses.py +123 -0
- pachifast-0.15.0/src/pachifast/signals.py +85 -0
- pachifast-0.15.0/src/pachifast/startup.py +41 -0
- pachifast-0.15.0/src/pachifast/udp/__init__.py +13 -0
- pachifast-0.15.0/src/pachifast/udp/protocol.py +49 -0
- pachifast-0.15.0/src/pachifast/udp/registry.py +98 -0
- pachifast-0.15.0/src/pachifast/utils/__init__.py +3 -0
- pachifast-0.15.0/src/pachifast/utils/commands.py +48 -0
- pachifast-0.15.0/src/pachifast/utils/helpers.py +44 -0
- pachifast-0.15.0/src/pachifast/utils/tasks.py +21 -0
- pachifast-0.15.0/src/pachifast/version/__init__.py +1 -0
- pachifast-0.15.0/src/pachifast/version/root.py +13 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to pachifast are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses [semantic versioning](https://semver.org/)
|
|
5
|
+
(while the major version is 0, minor releases may contain breaking changes).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
## [0.15.0] - 2026-10-14
|
|
10
|
+
|
|
11
|
+
First public release. pachifast is alpha software: see [Stability and support](https://pachifast.ilpachi.it/guides/stability/).
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Application factory and modules**: `create_app`, an explicit module registry (`project_modules.py`) and `AppModule`, with routers, settings, migrations, startup and setup hooks, message catalogs, and `requires_pachifast` to declare the pachifast versions a module works with.
|
|
16
|
+
- **Authentication and authorization**: JWT access and refresh tokens, Argon2id passwords, login lockout and rate limiting, users, groups and permissions, a pluggable permission provider, optional MFA (TOTP, email and SMS codes), per-user settings with a UI schema, and a one-to-one user profile for your own columns (`register_profile`).
|
|
17
|
+
- **A uniform API contract**: the response envelope `{success, message, data}`, errors as `{"detail": [{loc, msg, type, code, params?}]}` with stable message codes, camelCase JSON and built-in pagination.
|
|
18
|
+
- **Localized messages**: catalogs per module and per project, and an exporter that produces the JSON files a vue-i18n frontend needs, with a check-only mode for CI.
|
|
19
|
+
- **Generic model admin**, an **activity log** with an index and a retention command (`pachifast audit purge`), lifecycle **signals** (`pachifast.signals`), and live **events** over an authenticated WebSocket with one-time tickets.
|
|
20
|
+
- **Database and migrations**: SQLAlchemy 2.0 with SQLite and PostgreSQL, one Alembic target per database declared by the modules, and a configurable connection pool (`db_pool_*`).
|
|
21
|
+
- **Operations**: `serve` for production, health endpoints (`/`, `/live`, `/ready`), request ids, JSON logs, an optional Redis cache, UDP listeners, and a generated Dockerfile and CI/CD pipelines for GitHub, GitLab and Gitea.
|
|
22
|
+
- **Scaffolding CLI**: `pachifast new` for projects, modules and pipelines, plus commands for migrations, users, settings, i18n and the audit log.
|
|
23
|
+
- **Configuration**: environment variables, `.env` and a `pachifast.yaml` with a JSON Schema.
|
|
24
|
+
- **Extensions**: separate packages named `pachifast-<name>` that export an `AppModule` (for example `pachifast-metrics`).
|
|
25
|
+
- Documentation site with generated reference pages for the CLI, the settings and the message codes.
|
pachifast-0.15.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ilPachi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pachifast
|
|
3
|
+
Version: 0.15.0
|
|
4
|
+
Summary: Modular FastAPI core and scaffolding CLI: projects, apps, auth, migrations.
|
|
5
|
+
Project-URL: Homepage, https://pachifast.ilpachi.it/
|
|
6
|
+
Project-URL: Documentation, https://pachifast.ilpachi.it/
|
|
7
|
+
Project-URL: Repository, https://github.com/ellethee/pachifast
|
|
8
|
+
Project-URL: Source, https://github.com/ellethee/pachifast
|
|
9
|
+
Project-URL: Issues, https://github.com/ellethee/pachifast/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md
|
|
11
|
+
Author: ilPachi
|
|
12
|
+
Maintainer: ilPachi
|
|
13
|
+
License-Expression: MIT
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Keywords: alembic,cli,fastapi,framework,scaffolding,sqlalchemy
|
|
16
|
+
Classifier: Development Status :: 3 - Alpha
|
|
17
|
+
Classifier: Environment :: Web Environment
|
|
18
|
+
Classifier: Framework :: FastAPI
|
|
19
|
+
Classifier: Intended Audience :: Developers
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Classifier: Programming Language :: Python :: 3
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
26
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
27
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
28
|
+
Classifier: Typing :: Typed
|
|
29
|
+
Requires-Python: >=3.11
|
|
30
|
+
Requires-Dist: aiosqlite>=0.20.0
|
|
31
|
+
Requires-Dist: alembic<2.0.0,>=1.14.1
|
|
32
|
+
Requires-Dist: cryptography>=43.0.0
|
|
33
|
+
Requires-Dist: fastapi-pagination<1.0.0,>=0.13.0
|
|
34
|
+
Requires-Dist: fastapi[standard]<1.0.0,>=0.133.0
|
|
35
|
+
Requires-Dist: packaging>=23.0
|
|
36
|
+
Requires-Dist: pwdlib[argon2]>=0.2.1
|
|
37
|
+
Requires-Dist: pydantic-settings<3.0.0,>=2.7.1
|
|
38
|
+
Requires-Dist: pydantic<3.0.0,>=2.11.0
|
|
39
|
+
Requires-Dist: pyjwt<3.0.0,>=2.15.0
|
|
40
|
+
Requires-Dist: pyotp<3.0.0,>=2.9.0
|
|
41
|
+
Requires-Dist: python-multipart>=0.0.31
|
|
42
|
+
Requires-Dist: pyyaml>=6.0
|
|
43
|
+
Requires-Dist: rich>=13.0.0
|
|
44
|
+
Requires-Dist: sqlalchemy[asyncio]<3.0.0,>=2.0.40
|
|
45
|
+
Requires-Dist: starlette<2.0.0,>=1.3.1
|
|
46
|
+
Requires-Dist: typer<1.0.0,>=0.15.0
|
|
47
|
+
Requires-Dist: uvicorn<1.0.0,>=0.34.0
|
|
48
|
+
Provides-Extra: postgres
|
|
49
|
+
Requires-Dist: asyncpg<0.32.0,>=0.30.0; extra == 'postgres'
|
|
50
|
+
Provides-Extra: postgres-sync
|
|
51
|
+
Requires-Dist: psycopg[binary]>=3.2; extra == 'postgres-sync'
|
|
52
|
+
Provides-Extra: redis
|
|
53
|
+
Requires-Dist: redis>=5.0.0; extra == 'redis'
|
|
54
|
+
Description-Content-Type: text/markdown
|
|
55
|
+
|
|
56
|
+
<p align="center"><img src="https://raw.githubusercontent.com/ellethee/pachifast/main/docs/assets/logo.svg" alt="pachifast" width="160"></p>
|
|
57
|
+
|
|
58
|
+
# pachifast
|
|
59
|
+
|
|
60
|
+
[Italiano](https://github.com/ellethee/pachifast/blob/main/README.it.md)
|
|
61
|
+
|
|
62
|
+
An open-source framework for building [FastAPI](https://fastapi.tiangolo.com/) services with a modular structure, a CLI
|
|
63
|
+
that scaffolds projects and modules, built-in authentication with roles and permissions, and multi-database Alembic
|
|
64
|
+
migrations.
|
|
65
|
+
|
|
66
|
+
Version: **<!-- version -->0.15.0<!-- /version -->** - Author: **ilPachi** - License: **MIT** - Status: **alpha** (0.x: minor releases may contain breaking changes).
|
|
67
|
+
|
|
68
|
+
## Features
|
|
69
|
+
|
|
70
|
+
- **Modular by design**: an explicit registry of modules (`project_modules.py`), `apps/` for application modules and
|
|
71
|
+
`common/` for shared ones; each module brings its routers, settings, migrations, hooks and message catalogs.
|
|
72
|
+
- **Authentication and authorization**: JWT access and refresh tokens, Argon2id passwords, login lockout, users, groups
|
|
73
|
+
and permissions, optional MFA (TOTP, email and SMS codes), per-user settings with a UI schema.
|
|
74
|
+
- **A uniform API contract**: every success is `{success, message, data}`, every error is a non-2xx response with
|
|
75
|
+
`{"detail": [{loc, msg, type, code, params?}]}` and a stable `code`; camelCase JSON; pagination built in.
|
|
76
|
+
- **Localized messages**: stable message codes, catalogs per module and per project, and an exporter that produces the
|
|
77
|
+
JSON files a vue-i18n frontend needs (with a check-only mode for CI).
|
|
78
|
+
- **Live events**: an authenticated WebSocket with one-time tickets, an activity log, and automatic disconnection of
|
|
79
|
+
users who are deleted, deactivated or demoted.
|
|
80
|
+
- **Migrations**: one Alembic target per database declared by the modules.
|
|
81
|
+
- **Operations**: `serve` for production, generated Dockerfile and CI/CD pipelines (GitHub, GitLab, Gitea), health and
|
|
82
|
+
version endpoints, optional Redis cache.
|
|
83
|
+
- **Editor-friendly configuration**: environment variables, `.env` and a `pachifast.yaml` with a JSON Schema.
|
|
84
|
+
|
|
85
|
+
## Install
|
|
86
|
+
|
|
87
|
+
Python 3.11 or later and [uv](https://docs.astral.sh/uv/) are required:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
uv tool install pachifast
|
|
91
|
+
pachifast --version
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
In a project, `uv add pachifast` does the same. To install a specific version from PyPI (replace `X.Y.Z`):
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
uv tool install pachifast==X.Y.Z
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Redis cache support is an extra: `pachifast[redis]`; PostgreSQL is `pachifast[postgres]`. Supported databases: SQLite and
|
|
101
|
+
PostgreSQL. See [Getting started](https://pachifast.ilpachi.it/getting-started/) for more installation options.
|
|
102
|
+
|
|
103
|
+
## Stability
|
|
104
|
+
|
|
105
|
+
pachifast is **alpha**: the API contract (response envelope, message codes) is protected by tests, but settings, CLI and
|
|
106
|
+
the database schema of the core may change in any 0.x minor release, always announced in the [changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md)
|
|
107
|
+
and in [Upgrading](https://pachifast.ilpachi.it/guides/upgrading/). Details and the deprecation policy: [Stability](https://pachifast.ilpachi.it/guides/stability/).
|
|
108
|
+
|
|
109
|
+
## Quick start
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
pachifast new project demo && cd demo # scaffold a project
|
|
113
|
+
pachifast new app hello # add an application module
|
|
114
|
+
pachifast init # .env with a secret key, SQLite database, migrations, first superuser
|
|
115
|
+
pachifast dev # run with auto-reload
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Then open <http://127.0.0.1:8000/docs> (application endpoints) or <http://127.0.0.1:8000/docs/core> (authentication,
|
|
119
|
+
administration, health, version). Application routes require a bearer token by default: log in at
|
|
120
|
+
`POST /api/auth/token`.
|
|
121
|
+
|
|
122
|
+
Want to see a complete project first? [`examples/demo`](https://github.com/ellethee/pachifast/tree/main/examples/demo) is a working backend (MFA, model admin, a module with
|
|
123
|
+
tables, uploads, bulk actions and per-user settings) that runs on SQLite with no external services.
|
|
124
|
+
|
|
125
|
+
A project looks like this:
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
demo/
|
|
129
|
+
apps/ # application modules
|
|
130
|
+
common/ # shared modules
|
|
131
|
+
main.py # the ASGI app
|
|
132
|
+
project_modules.py
|
|
133
|
+
pachifast.yaml # optional configuration (with a JSON Schema for editors)
|
|
134
|
+
pyproject.toml
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Documentation
|
|
138
|
+
|
|
139
|
+
The documentation is published at <https://pachifast.ilpachi.it/> and lives in [`docs/`](https://github.com/ellethee/pachifast/tree/main/docs):
|
|
140
|
+
|
|
141
|
+
- [Getting started](https://pachifast.ilpachi.it/getting-started/)
|
|
142
|
+
- Guides: [configuration](https://pachifast.ilpachi.it/guides/configuration/), [modules](https://pachifast.ilpachi.it/guides/modules/),
|
|
143
|
+
[authentication](https://pachifast.ilpachi.it/guides/authentication/), [routing and responses](https://pachifast.ilpachi.it/guides/routing-and-responses/),
|
|
144
|
+
[errors and i18n](https://pachifast.ilpachi.it/guides/errors-and-i18n/), [events](https://pachifast.ilpachi.it/guides/events/), [cache](https://pachifast.ilpachi.it/guides/cache/),
|
|
145
|
+
[database and migrations](https://pachifast.ilpachi.it/guides/database-and-migrations/), [operations](https://pachifast.ilpachi.it/guides/operations/),
|
|
146
|
+
[deployment](https://pachifast.ilpachi.it/guides/deployment/), [publishing](https://pachifast.ilpachi.it/guides/publishing/),
|
|
147
|
+
[frontend integration](https://pachifast.ilpachi.it/guides/frontend-integration/)
|
|
148
|
+
- Reference: [CLI](https://pachifast.ilpachi.it/reference/cli/), [settings](https://pachifast.ilpachi.it/reference/settings/),
|
|
149
|
+
[message codes](https://pachifast.ilpachi.it/reference/error-codes/)
|
|
150
|
+
- [Changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md) and [contributing](https://pachifast.ilpachi.it/contributing/)
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
MIT, see [LICENSE](https://github.com/ellethee/pachifast/blob/main/LICENSE).
|
|
155
|
+
|
|
156
|
+
**Disclaimer.** pachifast is provided "as is", without warranty of any kind. It is alpha software: it can contain bugs
|
|
157
|
+
and change incompatibly between minor releases. You are responsible for reviewing, testing and securing the
|
|
158
|
+
applications you build with it before using them in production. See the [stability policy](https://pachifast.ilpachi.it/guides/stability/).
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<p align="center"><img src="https://raw.githubusercontent.com/ellethee/pachifast/main/docs/assets/logo.svg" alt="pachifast" width="160"></p>
|
|
2
|
+
|
|
3
|
+
# pachifast
|
|
4
|
+
|
|
5
|
+
[English](https://github.com/ellethee/pachifast/blob/main/README.md)
|
|
6
|
+
|
|
7
|
+
Framework open source per costruire servizi [FastAPI](https://fastapi.tiangolo.com/) con una struttura modulare, una CLI
|
|
8
|
+
che genera progetti e moduli, autenticazione integrata con ruoli e permessi e migrazioni Alembic su più database.
|
|
9
|
+
|
|
10
|
+
Versione: **<!-- version -->0.15.0<!-- /version -->** - Autore: **ilPachi** - Licenza: **MIT** - Stato: **alpha** (0.x: le versioni minori possono contenere modifiche incompatibili).
|
|
11
|
+
|
|
12
|
+
## Cosa offre
|
|
13
|
+
|
|
14
|
+
- **Modulare**: registro esplicito dei moduli (`project_modules.py`), `apps/` per i moduli applicativi e `common/` per
|
|
15
|
+
quelli condivisi; ogni modulo porta router, impostazioni, migrazioni, hook e cataloghi di messaggi.
|
|
16
|
+
- **Autenticazione e autorizzazione**: token JWT di accesso e refresh, password Argon2id, blocco dopo tentativi falliti,
|
|
17
|
+
utenti, gruppi e permessi, MFA opzionale (TOTP, codici via email e SMS), impostazioni per utente con schema UI.
|
|
18
|
+
- **Un contratto API uniforme**: ogni successo è `{success, message, data}`, ogni errore è una risposta non-2xx con
|
|
19
|
+
`{"detail": [{loc, msg, type, code, params?}]}` e un `code` stabile; JSON in camelCase; paginazione integrata.
|
|
20
|
+
- **Messaggi localizzati**: codici stabili, cataloghi per modulo e per progetto, ed esportazione dei file JSON per un
|
|
21
|
+
frontend vue-i18n (con modalità di sola verifica per la CI).
|
|
22
|
+
- **Eventi in tempo reale**: WebSocket autenticato con ticket monouso, activity log e disconnessione automatica degli
|
|
23
|
+
utenti eliminati, disattivati o declassati.
|
|
24
|
+
- **Migrazioni**: un target Alembic per ogni database dichiarato dai moduli.
|
|
25
|
+
- **Operatività**: `serve` per la produzione, Dockerfile e pipeline CI/CD generati (GitHub, GitLab, Gitea), endpoint di
|
|
26
|
+
health e versione, cache Redis opzionale.
|
|
27
|
+
- **Configurazione comoda da editor**: variabili d'ambiente, `.env` e un `pachifast.yaml` con JSON Schema.
|
|
28
|
+
|
|
29
|
+
## Installazione
|
|
30
|
+
|
|
31
|
+
Servono Python 3.11 o successivo e [uv](https://docs.astral.sh/uv/):
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv tool install pachifast
|
|
35
|
+
pachifast --version
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
In un progetto, `uv add pachifast` fa lo stesso. Per installare una versione specifica da PyPI (sostituisci `X.Y.Z`):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uv tool install pachifast==X.Y.Z
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
La cache Redis è un extra: `pachifast[redis]`; PostgreSQL è `pachifast[postgres]`. Database supportati: SQLite e
|
|
45
|
+
PostgreSQL. Per altre opzioni di installazione vedi [Getting started](https://pachifast.ilpachi.it/getting-started/)
|
|
46
|
+
(in inglese).
|
|
47
|
+
|
|
48
|
+
## Stabilità
|
|
49
|
+
|
|
50
|
+
pachifast è in **alpha**: il contratto dell'API (envelope di risposta, codici dei messaggi) è protetto da test, ma
|
|
51
|
+
impostazioni, CLI e schema del database del core possono cambiare in ogni versione minore 0.x, sempre annunciate nel
|
|
52
|
+
[changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md) e in [Upgrading](https://pachifast.ilpachi.it/guides/upgrading/). Dettagli e politica di deprecazione:
|
|
53
|
+
[Stability](https://pachifast.ilpachi.it/guides/stability/) (in inglese).
|
|
54
|
+
|
|
55
|
+
## Avvio rapido
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pachifast new project demo && cd demo # crea un progetto
|
|
59
|
+
pachifast new app hello # aggiunge un modulo applicativo
|
|
60
|
+
pachifast init # .env con chiave segreta, database SQLite, migrazioni, primo superuser
|
|
61
|
+
pachifast dev # avvio con ricarica automatica
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Poi apri <http://127.0.0.1:8000/docs> (endpoint dell'applicazione) o <http://127.0.0.1:8000/docs/core> (autenticazione,
|
|
65
|
+
amministrazione, health, versione). Le rotte dell'applicazione richiedono un token: accedi con `POST /api/auth/token`.
|
|
66
|
+
|
|
67
|
+
Vuoi vedere prima un progetto completo? [`examples/demo`](https://github.com/ellethee/pachifast/tree/main/examples/demo) è un backend funzionante (MFA, model admin, un modulo con
|
|
68
|
+
tabelle, upload, azioni di massa e impostazioni per utente) che gira su SQLite, senza servizi esterni.
|
|
69
|
+
|
|
70
|
+
Un progetto ha questa struttura:
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
demo/
|
|
74
|
+
apps/ # moduli applicativi
|
|
75
|
+
common/ # moduli condivisi
|
|
76
|
+
main.py # l'app ASGI
|
|
77
|
+
project_modules.py
|
|
78
|
+
pachifast.yaml # configurazione opzionale (con JSON Schema per gli editor)
|
|
79
|
+
pyproject.toml
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Documentazione
|
|
83
|
+
|
|
84
|
+
La documentazione completa (in inglese) è pubblicata su <https://pachifast.ilpachi.it/> e si trova in [`docs/`](https://github.com/ellethee/pachifast/tree/main/docs): guida introduttiva, guide per argomento,
|
|
85
|
+
riferimenti generati dal codice (CLI, impostazioni, codici dei messaggi), [changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md) e
|
|
86
|
+
[contributi](https://pachifast.ilpachi.it/contributing/).
|
|
87
|
+
|
|
88
|
+
## Licenza
|
|
89
|
+
|
|
90
|
+
MIT, vedi [LICENSE](https://github.com/ellethee/pachifast/blob/main/LICENSE).
|
|
91
|
+
|
|
92
|
+
**Esclusione di garanzia.** pachifast è fornito "così com'è" ("as is"), senza garanzie di alcun tipo. È software alpha:
|
|
93
|
+
può contenere errori e cambiare in modo incompatibile tra versioni minori. Sei responsabile di verificare, testare e
|
|
94
|
+
mettere in sicurezza le applicazioni che costruisci con pachifast prima di usarle in produzione. Vedi la
|
|
95
|
+
[politica di stabilità](https://pachifast.ilpachi.it/guides/stability/).
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
<p align="center"><img src="https://raw.githubusercontent.com/ellethee/pachifast/main/docs/assets/logo.svg" alt="pachifast" width="160"></p>
|
|
2
|
+
|
|
3
|
+
# pachifast
|
|
4
|
+
|
|
5
|
+
[Italiano](https://github.com/ellethee/pachifast/blob/main/README.it.md)
|
|
6
|
+
|
|
7
|
+
An open-source framework for building [FastAPI](https://fastapi.tiangolo.com/) services with a modular structure, a CLI
|
|
8
|
+
that scaffolds projects and modules, built-in authentication with roles and permissions, and multi-database Alembic
|
|
9
|
+
migrations.
|
|
10
|
+
|
|
11
|
+
Version: **<!-- version -->0.15.0<!-- /version -->** - Author: **ilPachi** - License: **MIT** - Status: **alpha** (0.x: minor releases may contain breaking changes).
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Modular by design**: an explicit registry of modules (`project_modules.py`), `apps/` for application modules and
|
|
16
|
+
`common/` for shared ones; each module brings its routers, settings, migrations, hooks and message catalogs.
|
|
17
|
+
- **Authentication and authorization**: JWT access and refresh tokens, Argon2id passwords, login lockout, users, groups
|
|
18
|
+
and permissions, optional MFA (TOTP, email and SMS codes), per-user settings with a UI schema.
|
|
19
|
+
- **A uniform API contract**: every success is `{success, message, data}`, every error is a non-2xx response with
|
|
20
|
+
`{"detail": [{loc, msg, type, code, params?}]}` and a stable `code`; camelCase JSON; pagination built in.
|
|
21
|
+
- **Localized messages**: stable message codes, catalogs per module and per project, and an exporter that produces the
|
|
22
|
+
JSON files a vue-i18n frontend needs (with a check-only mode for CI).
|
|
23
|
+
- **Live events**: an authenticated WebSocket with one-time tickets, an activity log, and automatic disconnection of
|
|
24
|
+
users who are deleted, deactivated or demoted.
|
|
25
|
+
- **Migrations**: one Alembic target per database declared by the modules.
|
|
26
|
+
- **Operations**: `serve` for production, generated Dockerfile and CI/CD pipelines (GitHub, GitLab, Gitea), health and
|
|
27
|
+
version endpoints, optional Redis cache.
|
|
28
|
+
- **Editor-friendly configuration**: environment variables, `.env` and a `pachifast.yaml` with a JSON Schema.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
Python 3.11 or later and [uv](https://docs.astral.sh/uv/) are required:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
uv tool install pachifast
|
|
36
|
+
pachifast --version
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
In a project, `uv add pachifast` does the same. To install a specific version from PyPI (replace `X.Y.Z`):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
uv tool install pachifast==X.Y.Z
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Redis cache support is an extra: `pachifast[redis]`; PostgreSQL is `pachifast[postgres]`. Supported databases: SQLite and
|
|
46
|
+
PostgreSQL. See [Getting started](https://pachifast.ilpachi.it/getting-started/) for more installation options.
|
|
47
|
+
|
|
48
|
+
## Stability
|
|
49
|
+
|
|
50
|
+
pachifast is **alpha**: the API contract (response envelope, message codes) is protected by tests, but settings, CLI and
|
|
51
|
+
the database schema of the core may change in any 0.x minor release, always announced in the [changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md)
|
|
52
|
+
and in [Upgrading](https://pachifast.ilpachi.it/guides/upgrading/). Details and the deprecation policy: [Stability](https://pachifast.ilpachi.it/guides/stability/).
|
|
53
|
+
|
|
54
|
+
## Quick start
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pachifast new project demo && cd demo # scaffold a project
|
|
58
|
+
pachifast new app hello # add an application module
|
|
59
|
+
pachifast init # .env with a secret key, SQLite database, migrations, first superuser
|
|
60
|
+
pachifast dev # run with auto-reload
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then open <http://127.0.0.1:8000/docs> (application endpoints) or <http://127.0.0.1:8000/docs/core> (authentication,
|
|
64
|
+
administration, health, version). Application routes require a bearer token by default: log in at
|
|
65
|
+
`POST /api/auth/token`.
|
|
66
|
+
|
|
67
|
+
Want to see a complete project first? [`examples/demo`](https://github.com/ellethee/pachifast/tree/main/examples/demo) is a working backend (MFA, model admin, a module with
|
|
68
|
+
tables, uploads, bulk actions and per-user settings) that runs on SQLite with no external services.
|
|
69
|
+
|
|
70
|
+
A project looks like this:
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
demo/
|
|
74
|
+
apps/ # application modules
|
|
75
|
+
common/ # shared modules
|
|
76
|
+
main.py # the ASGI app
|
|
77
|
+
project_modules.py
|
|
78
|
+
pachifast.yaml # optional configuration (with a JSON Schema for editors)
|
|
79
|
+
pyproject.toml
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Documentation
|
|
83
|
+
|
|
84
|
+
The documentation is published at <https://pachifast.ilpachi.it/> and lives in [`docs/`](https://github.com/ellethee/pachifast/tree/main/docs):
|
|
85
|
+
|
|
86
|
+
- [Getting started](https://pachifast.ilpachi.it/getting-started/)
|
|
87
|
+
- Guides: [configuration](https://pachifast.ilpachi.it/guides/configuration/), [modules](https://pachifast.ilpachi.it/guides/modules/),
|
|
88
|
+
[authentication](https://pachifast.ilpachi.it/guides/authentication/), [routing and responses](https://pachifast.ilpachi.it/guides/routing-and-responses/),
|
|
89
|
+
[errors and i18n](https://pachifast.ilpachi.it/guides/errors-and-i18n/), [events](https://pachifast.ilpachi.it/guides/events/), [cache](https://pachifast.ilpachi.it/guides/cache/),
|
|
90
|
+
[database and migrations](https://pachifast.ilpachi.it/guides/database-and-migrations/), [operations](https://pachifast.ilpachi.it/guides/operations/),
|
|
91
|
+
[deployment](https://pachifast.ilpachi.it/guides/deployment/), [publishing](https://pachifast.ilpachi.it/guides/publishing/),
|
|
92
|
+
[frontend integration](https://pachifast.ilpachi.it/guides/frontend-integration/)
|
|
93
|
+
- Reference: [CLI](https://pachifast.ilpachi.it/reference/cli/), [settings](https://pachifast.ilpachi.it/reference/settings/),
|
|
94
|
+
[message codes](https://pachifast.ilpachi.it/reference/error-codes/)
|
|
95
|
+
- [Changelog](https://github.com/ellethee/pachifast/blob/main/CHANGELOG.md) and [contributing](https://pachifast.ilpachi.it/contributing/)
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT, see [LICENSE](https://github.com/ellethee/pachifast/blob/main/LICENSE).
|
|
100
|
+
|
|
101
|
+
**Disclaimer.** pachifast is provided "as is", without warranty of any kind. It is alpha software: it can contain bugs
|
|
102
|
+
and change incompatibly between minor releases. You are responsible for reviewing, testing and securing the
|
|
103
|
+
applications you build with it before using them in production. See the [stability policy](https://pachifast.ilpachi.it/guides/stability/).
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# pachifast demo
|
|
2
|
+
|
|
3
|
+
A complete, self-contained backend built on pachifast. It needs no frontend, and no external database: everything runs on SQLite from this folder.
|
|
4
|
+
|
|
5
|
+
It shows:
|
|
6
|
+
|
|
7
|
+
- the core (authentication, users, permissions, refresh tokens), MFA and the generic model admin;
|
|
8
|
+
- an app module (`apps/demo`) with its own tables and migration target, a startup seed, lookups, a paginated and filterable items API with bulk actions, file upload and download, per-user settings and message catalogs in English and Italian.
|
|
9
|
+
|
|
10
|
+
## Run it
|
|
11
|
+
|
|
12
|
+
From the repository root:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
cd examples/demo
|
|
16
|
+
uv sync
|
|
17
|
+
uv run pachifast init --username admin --password change-me-please # .env, auth migrations, first superuser
|
|
18
|
+
uv run pachifast migrations upgrade --target-name demo # tables of the demo app
|
|
19
|
+
uv run pachifast dev
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Open <http://127.0.0.1:8000/docs> for the API of the demo app and <http://127.0.0.1:8000/docs/core> for the built-in routes. Log in with the superuser you just created:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
curl -X POST http://127.0.0.1:8000/api/auth/token -d "username=admin" -d "password=change-me-please"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`init` prepares the auth database only; every other migration target (here `demo`) is applied with `migrations upgrade`. Both are safe to run again. The sample records are inserted at startup, only when the table is empty.
|
|
29
|
+
|
|
30
|
+
## Use a published release
|
|
31
|
+
|
|
32
|
+
The `pyproject.toml` points at the local sources so the demo always matches the repository. To try a released version from PyPI, delete the `[tool.uv.sources]` section; `uv sync` then installs `pachifast` from PyPI.
|
|
33
|
+
|
|
34
|
+
## A frontend
|
|
35
|
+
|
|
36
|
+
Any frontend that follows the pachifast contract (response envelope, errors, token refresh, server-side tables) works against this backend: see the [frontend integration guide](../../docs/guides/frontend-integration.md).
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Model admin of the demo: the generic CRUD screens for items and files (see the pachifast guide "Model admin")."""
|
|
2
|
+
|
|
3
|
+
from pachifast.admin import ModelAdmin, admin_action, register_admin
|
|
4
|
+
|
|
5
|
+
from .models import DemoFile, DemoItem
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@register_admin(DemoItem)
|
|
9
|
+
class ItemAdmin(ModelAdmin):
|
|
10
|
+
"""Items: searchable by name and notes, filterable by status, category and active flag."""
|
|
11
|
+
|
|
12
|
+
name = "item"
|
|
13
|
+
title = "Item"
|
|
14
|
+
list_display = ["name", "category", "status", "price", "quantity", "active", "created_at"]
|
|
15
|
+
search_fields = ["name", "notes"]
|
|
16
|
+
list_filter = ["status", "category", "active"]
|
|
17
|
+
readonly_fields = ["created_at"]
|
|
18
|
+
actions = ["archive", "activate"]
|
|
19
|
+
|
|
20
|
+
@admin_action(label="Archive selected")
|
|
21
|
+
async def archive(self, session, rows) -> str:
|
|
22
|
+
"""Set the status of the selected items to archived."""
|
|
23
|
+
for row in rows:
|
|
24
|
+
row.status = "archived"
|
|
25
|
+
return f"{len(rows)} archived"
|
|
26
|
+
|
|
27
|
+
@admin_action(label="Activate selected", confirm=False)
|
|
28
|
+
async def activate(self, session, rows) -> str:
|
|
29
|
+
"""Set the status of the selected items to active."""
|
|
30
|
+
for row in rows:
|
|
31
|
+
row.status = "active"
|
|
32
|
+
return f"{len(rows)} activated"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@register_admin(DemoFile)
|
|
36
|
+
class FileAdmin(ModelAdmin):
|
|
37
|
+
"""Files: metadata only, read-only (the content is managed by the upload routes)."""
|
|
38
|
+
|
|
39
|
+
name = "file"
|
|
40
|
+
title = "File"
|
|
41
|
+
search_fields = ["name"]
|
|
42
|
+
readonly_fields = ["name", "content_type", "size", "created_at"]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""Static data of the demo: lookups (countries, cities, categories) and the seed of the sample records."""
|
|
2
|
+
|
|
3
|
+
import random
|
|
4
|
+
|
|
5
|
+
COUNTRIES: list[dict] = [
|
|
6
|
+
{"value": 1, "label": "Italia"},
|
|
7
|
+
{"value": 2, "label": "Francia"},
|
|
8
|
+
{"value": 3, "label": "Germania"},
|
|
9
|
+
{"value": 4, "label": "Spagna"},
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
CITIES: list[dict] = [
|
|
13
|
+
{"value": 1, "label": "Roma", "countryId": 1},
|
|
14
|
+
{"value": 2, "label": "Milano", "countryId": 1},
|
|
15
|
+
{"value": 3, "label": "Napoli", "countryId": 1},
|
|
16
|
+
{"value": 4, "label": "Parigi", "countryId": 2},
|
|
17
|
+
{"value": 5, "label": "Lione", "countryId": 2},
|
|
18
|
+
{"value": 6, "label": "Berlino", "countryId": 3},
|
|
19
|
+
{"value": 7, "label": "Monaco", "countryId": 3},
|
|
20
|
+
{"value": 8, "label": "Amburgo", "countryId": 3},
|
|
21
|
+
{"value": 9, "label": "Madrid", "countryId": 4},
|
|
22
|
+
{"value": 10, "label": "Barcellona", "countryId": 4},
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
CATEGORIES: list[dict] = [
|
|
26
|
+
{"value": "tools", "label": "Strumenti"},
|
|
27
|
+
{"value": "books", "label": "Libri"},
|
|
28
|
+
{"value": "toys", "label": "Giochi"},
|
|
29
|
+
{"value": "food", "label": "Alimentari"},
|
|
30
|
+
{"value": "clothes", "label": "Abbigliamento"},
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
STATUSES: list[dict] = [
|
|
34
|
+
{"value": "draft", "label": "Bozza"},
|
|
35
|
+
{"value": "active", "label": "Attivo"},
|
|
36
|
+
{"value": "archived", "label": "Archiviato"},
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
_ADJECTIVES = ["Piccolo", "Grande", "Rapido", "Antico", "Moderno", "Verde", "Rosso", "Leggero", "Robusto", "Elegante"]
|
|
40
|
+
_NOUNS = ["martello", "libro", "robot", "pane", "giacca", "puzzle", "cacciavite", "romanzo", "casco", "formaggio"]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def sample_items(count: int = 120) -> list[dict]:
|
|
44
|
+
"""``count`` reproducible sample records (fixed seed): same data on every database."""
|
|
45
|
+
rng = random.Random(42)
|
|
46
|
+
items = []
|
|
47
|
+
for number in range(1, count + 1):
|
|
48
|
+
city = rng.choice(CITIES)
|
|
49
|
+
items.append(
|
|
50
|
+
{
|
|
51
|
+
"name": f"{rng.choice(_ADJECTIVES)} {rng.choice(_NOUNS)} {number}",
|
|
52
|
+
"category": rng.choice(CATEGORIES)["value"],
|
|
53
|
+
"status": rng.choice(STATUSES)["value"],
|
|
54
|
+
"price": round(rng.uniform(1, 500), 2),
|
|
55
|
+
"quantity": rng.randint(0, 200),
|
|
56
|
+
"active": rng.random() > 0.2,
|
|
57
|
+
"country_id": city["countryId"],
|
|
58
|
+
"city_id": city["value"],
|
|
59
|
+
"notes": None if rng.random() > 0.3 else f"Nota di prova {number}",
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
return items
|