hinbert-fastapi 0.1.0__tar.gz → 0.2.1__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.
Files changed (107) hide show
  1. hinbert_fastapi-0.2.1/PKG-INFO +336 -0
  2. hinbert_fastapi-0.2.1/README.md +298 -0
  3. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/deps/auth.py +40 -40
  4. hinbert_fastapi-0.2.1/app/core/middleware/__init__.py +14 -0
  5. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/security/auth.py +15 -8
  6. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/services/auth_service.py +32 -32
  7. hinbert_fastapi-0.2.1/hinbert_cli/__init__.py +0 -0
  8. hinbert_fastapi-0.2.1/hinbert_cli/main.py +984 -0
  9. hinbert_fastapi-0.2.1/hinbert_fastapi.egg-info/PKG-INFO +336 -0
  10. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/hinbert_fastapi.egg-info/SOURCES.txt +2 -0
  11. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/hinbert_fastapi.egg-info/entry_points.txt +1 -1
  12. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/hinbert_fastapi.egg-info/top_level.txt +1 -0
  13. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/pyproject.toml +41 -41
  14. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/setup.cfg +4 -4
  15. hinbert_fastapi-0.1.0/PKG-INFO +0 -0
  16. hinbert_fastapi-0.1.0/README.md +0 -0
  17. hinbert_fastapi-0.1.0/app/core/middleware/__init__.py +0 -1
  18. hinbert_fastapi-0.1.0/hinbert_fastapi.egg-info/PKG-INFO +0 -0
  19. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/LICENSE +0 -0
  20. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/__init__.py +0 -0
  21. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/__init__.py +0 -0
  22. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/deps/__init__.py +0 -0
  23. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/deps/pagination.py +0 -0
  24. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/v1/__init__.py +0 -0
  25. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/v1/endpoints/__init__.py +0 -0
  26. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/v1/endpoints/auth.py +0 -0
  27. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/v1/endpoints/dashboard.py +0 -0
  28. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/v1/endpoints/products.py +0 -0
  29. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/v1/endpoints/users.py +0 -0
  30. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/v1/routers/__init__.py +0 -0
  31. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/api/v1/routers/api_router.py +0 -0
  32. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/__init__.py +0 -0
  33. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/config/__init__.py +0 -0
  34. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/config/database.py +0 -0
  35. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/config/settings.py +0 -0
  36. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/exceptions/__init__.py +0 -0
  37. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/exceptions/base_exception.py +0 -0
  38. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/exceptions/custom_exceptions.py +0 -0
  39. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/middleware/cors.py +0 -0
  40. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/middleware/error_handler.py +0 -0
  41. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/middleware/logging.py +0 -0
  42. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/middleware/rate_limit.py +0 -0
  43. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/security/__init__.py +0 -0
  44. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/security/jwt.py +0 -0
  45. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/security/oauth.py +0 -0
  46. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/security/password.py +0 -0
  47. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/core/security/totp.py +0 -0
  48. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/db/__init__.py +0 -0
  49. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/db/base.py +0 -0
  50. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/db/migrations/env.py +0 -0
  51. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/db/migrations/versions/97ed1bc05f4a_complete_product_and_totp_fields.py +0 -0
  52. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/db/migrations/versions/f8b632aa11da_initial_migration.py +0 -0
  53. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/db/session.py +0 -0
  54. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/main.py +0 -0
  55. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/__init__.py +0 -0
  56. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/domain/__init__.py +0 -0
  57. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/domain/base.py +0 -0
  58. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/domain/email_verification.py +0 -0
  59. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/domain/password_reset.py +0 -0
  60. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/domain/product.py +0 -0
  61. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/domain/refresh_token.py +0 -0
  62. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/domain/totp_secret.py +0 -0
  63. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/domain/user.py +0 -0
  64. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/schemas/__init__.py +0 -0
  65. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/schemas/auth.py +0 -0
  66. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/schemas/password.py +0 -0
  67. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/schemas/product.py +0 -0
  68. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/schemas/response.py +0 -0
  69. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/schemas/token.py +0 -0
  70. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/schemas/totp.py +0 -0
  71. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/models/schemas/user.py +0 -0
  72. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/repositories/__init__.py +0 -0
  73. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/repositories/base/__init__.py +0 -0
  74. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/repositories/base/base_repository.py +0 -0
  75. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/repositories/email_verification_repository.py +0 -0
  76. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/repositories/password_reset_repository.py +0 -0
  77. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/repositories/product_repository.py +0 -0
  78. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/repositories/refresh_token_repository.py +0 -0
  79. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/repositories/totp_secret_repository.py +0 -0
  80. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/repositories/user_repository.py +0 -0
  81. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/services/__init__.py +0 -0
  82. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/services/base/__init__.py +0 -0
  83. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/services/base/base_service.py +0 -0
  84. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/services/email_service.py +0 -0
  85. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/services/product_service.py +0 -0
  86. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/services/social_auth_service.py +0 -0
  87. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/services/totp_service.py +0 -0
  88. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/services/user_service.py +0 -0
  89. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/tests/__init__.py +0 -0
  90. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/tests/conftest.py +0 -0
  91. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/tests/integration/test_auth_api.py +0 -0
  92. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/tests/integration/test_product_api.py +0 -0
  93. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/tests/integration/test_user_api.py +0 -0
  94. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/tests/unit/test_auth_service.py +0 -0
  95. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/tests/unit/test_product_service.py +0 -0
  96. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/tests/unit/test_user_service.py +0 -0
  97. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/utils/__init__.py +0 -0
  98. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/utils/date_utils.py +0 -0
  99. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/utils/file_utils.py +0 -0
  100. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/utils/logger.py +0 -0
  101. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/app/utils/validators.py +0 -0
  102. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/hinbert_fastapi.egg-info/dependency_links.txt +0 -0
  103. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/hinbert_fastapi.egg-info/requires.txt +0 -0
  104. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/scripts/__init__.py +0 -0
  105. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/scripts/create_admin.py +0 -0
  106. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/scripts/run_migrations.py +0 -0
  107. {hinbert_fastapi-0.1.0 → hinbert_fastapi-0.2.1}/scripts/seed_data.py +0 -0
@@ -0,0 +1,336 @@
1
+ Metadata-Version: 2.4
2
+ Name: hinbert-fastapi
3
+ Version: 0.2.1
4
+ Summary: Professional FastAPI boilerplate with JWT auth, 2FA, PostgreSQL, Docker
5
+ Author: Hinbert Engineering
6
+ License: MIT
7
+ Project-URL: Documentation, https://github.com/hinbert/hinbert-fastapi#readme
8
+ Project-URL: Repository, https://github.com/hinbert/hinbert-fastapi
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Framework :: FastAPI
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: fastapi<1,>=0.115
18
+ Requires-Dist: uvicorn[standard]<1,>=0.30
19
+ Requires-Dist: sqlalchemy[asyncio]<3,>=2.0
20
+ Requires-Dist: asyncpg<1,>=0.29
21
+ Requires-Dist: aiosqlite<1,>=0.20
22
+ Requires-Dist: alembic<2,>=1.13
23
+ Requires-Dist: pydantic<3,>=2.8
24
+ Requires-Dist: pydantic-settings<3,>=2.4
25
+ Requires-Dist: python-jose[cryptography]<4,>=3.3
26
+ Requires-Dist: passlib[bcrypt]<2,>=1.7
27
+ Requires-Dist: bcrypt<5,>=4.0
28
+ Requires-Dist: pyotp<3,>=2.9
29
+ Requires-Dist: slowapi<1,>=0.1.9
30
+ Requires-Dist: loguru<1,>=0.7
31
+ Requires-Dist: email-validator<3,>=2.2
32
+ Requires-Dist: python-multipart<1,>=0.0.9
33
+ Requires-Dist: redis<6,>=5
34
+ Requires-Dist: aiosmtplib<4,>=3
35
+ Requires-Dist: cryptography<46,>=42
36
+ Requires-Dist: httpx<1,>=0.27
37
+ Dynamic: license-file
38
+
39
+ [![GitHub stars](https://img.shields.io/github/stars/hinbert-cli-development/hinbert_fastapi)](https://github.com/hinbert-cli-development/hinbert_fastapi/stargazers)
40
+ [![GitHub forks](https://img.shields.io/github/forks/hinbert-cli-development/hinbert_fastapi)](https://github.com/hinbert-cli-development/hinbert_fastapi/forks)
41
+ [![GitHub issues](https://img.shields.io/github/issues/hinbert-cli-development/hinbert_fastapi)](https://github.com/hinbert-cli-development/hinbert_fastapi/issues)
42
+ [![GitHub pull requests](https://img.shields.io/github/issues-pr/hinbert-cli-development/hinbert_fastapi)](https://github.com/hinbert-cli-development/hinbert_fastapi/pulls)
43
+ [![PyPI](https://img.shields.io/pypi/v/hinbert-fastapi)](https://pypi.org/project/hinbert-fastapi/)
44
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
45
+ # Hinbert FastAPI
46
+
47
+ A modern, production-oriented FastAPI backend foundation for secure web applications. Built for teams that want a clean architecture, strong authentication defaults, scalable API design, and quick deployment without starting from scratch.
48
+
49
+ ## Why this project?
50
+
51
+ Hinbert FastAPI combines a pragmatic backend structure with security-first design patterns:
52
+
53
+ - JWT-based authentication with refresh token rotation
54
+ - Password reset and email verification flows
55
+ - Optional TOTP multi-factor authentication
56
+ - OAuth login for Google and Facebook
57
+ - Async SQLAlchemy data layer with PostgreSQL support
58
+ - Rate limiting, request logging, and structured error handling
59
+ - Clean separation between API, services, repositories, and models
60
+ - Docker-ready local environment and deployment support
61
+
62
+ ## Features
63
+
64
+ - Secure user registration and login
65
+ - Email verification and password recovery
66
+ - Access token + refresh token issuance
67
+ - Logout and refresh-token revocation
68
+ - TOTP setup and validation
69
+ - Social authentication hooks
70
+ - Product CRUD endpoints with filtering, sorting, and pagination
71
+ - Redis-backed rate limiting
72
+ - Pydantic-based validation and environment configuration
73
+ - Alembic migrations for database evolution
74
+ - Python testing coverage for core business flows
75
+
76
+
77
+
78
+ ### Available Commands
79
+
80
+ | Command | Description | Example |
81
+ | --- | --- | --- |
82
+ | `hinbert init [PROJECT_NAME]` | Create a new FastAPI project | `hinbert init my_app` |
83
+ | `hinbert init --help` | Show help and available options | `hinbert init --help` |
84
+ | `hinbert init .` | Generate project in current directory | `hinbert init .` |
85
+ | `hinbert init [PROJECT_NAME] --yes` | Skip prompts, use defaults | `hinbert init my_app --yes` |
86
+ | `--db [postgresql|mysql|sqlite]` | Choose database | `--db postgresql` |
87
+ | `--auth [jwt|oauth2|none]` | Choose authentication | `--auth jwt` |
88
+ | `--no-2fa` | Skip two-factor authentication | `--no-2fa` |
89
+ | `--no-email` | Skip email verification | `--no-email` |
90
+ | `--no-rate-limit` | Skip rate limiting | `--no-rate-limit` |
91
+ | `--no-docker` | Skip Docker configuration | `--no-docker` |
92
+ | `--k8s` | Include Kubernetes/Helm | `--k8s` |
93
+ | `--logging [loguru|structlog|none]` | Choose logging library | `--logging structlog` |
94
+ | `-y, --yes` | Skip all confirmation prompts | `-y` |
95
+
96
+ ## Tech Stack
97
+
98
+ - Python 3.12+
99
+ - FastAPI
100
+ - SQLAlchemy 2 with async support
101
+ - PostgreSQL / SQLite compatibility
102
+ - Pydantic v2
103
+ - Redis
104
+ - Alembic
105
+ - JWT + bcrypt + pyotp
106
+ - Docker and Docker Compose
107
+ - pytest
108
+
109
+ ## Architecture
110
+
111
+ ```text
112
+ app/
113
+ ├── api/
114
+ │ ├── deps/
115
+ │ └── v1/
116
+ │ ├── endpoints/
117
+ │ └── routers/
118
+ ├── core/
119
+ │ ├── config/
120
+ │ ├── exceptions/
121
+ │ ├── middleware/
122
+ │ └── security/
123
+ ├── db/
124
+ │ └── migrations/
125
+ ├── models/
126
+ │ ├── domain/
127
+ │ └── schemas/
128
+ ├── repositories/
129
+ ├── services/
130
+ ├── tests/
131
+ ├── main.py
132
+ ├── __init__.py
133
+
134
+ scripts/
135
+ ├── create_admin.py
136
+ ├── run_migrations.py
137
+ ├── seed_data.py
138
+
139
+ docker/
140
+ ├── Dockerfile
141
+ ├── docker-compose.yml
142
+
143
+ alembic.ini
144
+ pyproject.toml
145
+ requirements.txt
146
+ requirements-dev.txt
147
+ .env.example
148
+ README.md
149
+ ```
150
+
151
+ ## Quick Start
152
+
153
+ ### Prerequisites
154
+
155
+ - Python 3.12+
156
+ - PostgreSQL or Docker
157
+ - Redis or Docker
158
+ - Git
159
+
160
+ ### 1. Clone the repository
161
+
162
+ ```bash
163
+ git clone <repository-url>
164
+ cd hinbert_fastapi
165
+ ```
166
+
167
+ ### 2. Create a virtual environment
168
+
169
+ ```bash
170
+ python -m venv .venv
171
+ ```
172
+
173
+ On Windows PowerShell:
174
+
175
+ ```powershell
176
+ .\.venv\Scripts\Activate.ps1
177
+ ```
178
+
179
+ On macOS/Linux:
180
+
181
+ ```bash
182
+ source .venv/bin/activate
183
+ ```
184
+
185
+ ### 3. Install dependencies
186
+
187
+ ```bash
188
+ pip install -r requirements.txt
189
+ pip install -r requirements-dev.txt
190
+ ```
191
+
192
+ ### 4. Configure environment variables
193
+
194
+ ```bash
195
+ copy .env.example .env
196
+ ```
197
+
198
+ or:
199
+
200
+ ```bash
201
+ cp .env.example .env
202
+ ```
203
+
204
+ Update the values in `.env` for your database, Redis, JWT secret, SMTP settings, and OAuth credentials.
205
+
206
+ ### 5. Run database migrations
207
+
208
+ ```bash
209
+ python -m scripts.run_migrations
210
+ ```
211
+
212
+ ### 6. Start the API
213
+
214
+ ```bash
215
+ uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
216
+ ```
217
+
218
+ Once running, the app is available at:
219
+
220
+ - API: http://localhost:8000
221
+ - Swagger UI: http://localhost:8000/docs
222
+ - ReDoc: http://localhost:8000/redoc
223
+ - Health: http://localhost:8000/health
224
+
225
+ ## Docker Setup
226
+
227
+ This project includes a Docker Compose setup for local development.
228
+
229
+ ```bash
230
+ docker compose -f docker/docker-compose.yml up --build
231
+ ```
232
+
233
+ To stop it:
234
+
235
+ ```bash
236
+ docker compose -f docker/docker-compose.yml down
237
+ ```
238
+
239
+ ## API Highlights
240
+
241
+ The application exposes a versioned API under `/api/v1`.
242
+
243
+ ### Auth endpoints
244
+
245
+ - `/api/v1/auth/signup`
246
+ - `/api/v1/auth/login`
247
+ - `/api/v1/auth/refresh`
248
+ - `/api/v1/auth/logout`
249
+ - `/api/v1/auth/forgot-password`
250
+ - `/api/v1/auth/reset-password`
251
+ - `/api/v1/auth/totp/setup`
252
+ - `/api/v1/auth/totp/verify`
253
+ - `/api/v1/auth/google`
254
+ - `/api/v1/auth/facebook`
255
+
256
+ ### Product endpoints
257
+
258
+ - `/api/v1/products`
259
+ - `/api/v1/products/{product_id}`
260
+
261
+ ### User endpoints
262
+
263
+ - `/api/v1/users/me`
264
+ - admin/user management routes where applicable
265
+
266
+ ## Example Authentication Flow
267
+
268
+ ```json
269
+ {
270
+ "email": "user@example.com",
271
+ "password": "StrongPassword!123"
272
+ }
273
+ ```
274
+
275
+ The login response returns both an access token and refresh token:
276
+
277
+ ```http
278
+ Authorization: Bearer <access_token>
279
+ ```
280
+
281
+ ## Environment Configuration
282
+
283
+ The project reads configuration using Pydantic settings from `.env` and supports values such as:
284
+
285
+ - `DATABASE_URL`
286
+ - `REDIS_URL`
287
+ - `SECRET_KEY`
288
+ - `ALGORITHM`
289
+ - `ACCESS_TOKEN_EXPIRE_MINUTES`
290
+ - `REFRESH_TOKEN_EXPIRE_DAYS`
291
+ - `SMTP_HOST`
292
+ - `SMTP_PORT`
293
+ - `EMAIL_FROM`
294
+ - `GOOGLE_CLIENT_ID`
295
+ - `FACEBOOK_CLIENT_ID`
296
+ - `BACKEND_CORS_ORIGINS`
297
+
298
+ ## Testing
299
+
300
+ Run the test suite with:
301
+
302
+ ```bash
303
+ pytest
304
+ ```
305
+
306
+ Targeted test folders:
307
+
308
+ ```bash
309
+ pytest app/tests/unit
310
+ pytest app/tests/integration
311
+ ```
312
+
313
+ ## Security Notes
314
+
315
+ This project includes strong defaults for a starter backend, but production deployments should still:
316
+
317
+ - replace the default JWT secret with a secure secret manager value
318
+ - restrict CORS origins to trusted domains
319
+ - protect database credentials and infrastructure endpoints
320
+ - use HTTPS behind a reverse proxy or load balancer
321
+ - configure valid SMTP and OAuth provider credentials
322
+ - enable monitoring, backups, and secure deployment policies
323
+
324
+ ## Contributing
325
+
326
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md).
327
+
328
+ ## License
329
+
330
+ MIT License. See [LICENSE](LICENSE) for details.
331
+
332
+ ## Support
333
+
334
+ If you find this useful, please give it a ⭐ on GitHub!
335
+
336
+
@@ -0,0 +1,298 @@
1
+ [![GitHub stars](https://img.shields.io/github/stars/hinbert-cli-development/hinbert_fastapi)](https://github.com/hinbert-cli-development/hinbert_fastapi/stargazers)
2
+ [![GitHub forks](https://img.shields.io/github/forks/hinbert-cli-development/hinbert_fastapi)](https://github.com/hinbert-cli-development/hinbert_fastapi/forks)
3
+ [![GitHub issues](https://img.shields.io/github/issues/hinbert-cli-development/hinbert_fastapi)](https://github.com/hinbert-cli-development/hinbert_fastapi/issues)
4
+ [![GitHub pull requests](https://img.shields.io/github/issues-pr/hinbert-cli-development/hinbert_fastapi)](https://github.com/hinbert-cli-development/hinbert_fastapi/pulls)
5
+ [![PyPI](https://img.shields.io/pypi/v/hinbert-fastapi)](https://pypi.org/project/hinbert-fastapi/)
6
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+ # Hinbert FastAPI
8
+
9
+ A modern, production-oriented FastAPI backend foundation for secure web applications. Built for teams that want a clean architecture, strong authentication defaults, scalable API design, and quick deployment without starting from scratch.
10
+
11
+ ## Why this project?
12
+
13
+ Hinbert FastAPI combines a pragmatic backend structure with security-first design patterns:
14
+
15
+ - JWT-based authentication with refresh token rotation
16
+ - Password reset and email verification flows
17
+ - Optional TOTP multi-factor authentication
18
+ - OAuth login for Google and Facebook
19
+ - Async SQLAlchemy data layer with PostgreSQL support
20
+ - Rate limiting, request logging, and structured error handling
21
+ - Clean separation between API, services, repositories, and models
22
+ - Docker-ready local environment and deployment support
23
+
24
+ ## Features
25
+
26
+ - Secure user registration and login
27
+ - Email verification and password recovery
28
+ - Access token + refresh token issuance
29
+ - Logout and refresh-token revocation
30
+ - TOTP setup and validation
31
+ - Social authentication hooks
32
+ - Product CRUD endpoints with filtering, sorting, and pagination
33
+ - Redis-backed rate limiting
34
+ - Pydantic-based validation and environment configuration
35
+ - Alembic migrations for database evolution
36
+ - Python testing coverage for core business flows
37
+
38
+
39
+
40
+ ### Available Commands
41
+
42
+ | Command | Description | Example |
43
+ | --- | --- | --- |
44
+ | `hinbert init [PROJECT_NAME]` | Create a new FastAPI project | `hinbert init my_app` |
45
+ | `hinbert init --help` | Show help and available options | `hinbert init --help` |
46
+ | `hinbert init .` | Generate project in current directory | `hinbert init .` |
47
+ | `hinbert init [PROJECT_NAME] --yes` | Skip prompts, use defaults | `hinbert init my_app --yes` |
48
+ | `--db [postgresql|mysql|sqlite]` | Choose database | `--db postgresql` |
49
+ | `--auth [jwt|oauth2|none]` | Choose authentication | `--auth jwt` |
50
+ | `--no-2fa` | Skip two-factor authentication | `--no-2fa` |
51
+ | `--no-email` | Skip email verification | `--no-email` |
52
+ | `--no-rate-limit` | Skip rate limiting | `--no-rate-limit` |
53
+ | `--no-docker` | Skip Docker configuration | `--no-docker` |
54
+ | `--k8s` | Include Kubernetes/Helm | `--k8s` |
55
+ | `--logging [loguru|structlog|none]` | Choose logging library | `--logging structlog` |
56
+ | `-y, --yes` | Skip all confirmation prompts | `-y` |
57
+
58
+ ## Tech Stack
59
+
60
+ - Python 3.12+
61
+ - FastAPI
62
+ - SQLAlchemy 2 with async support
63
+ - PostgreSQL / SQLite compatibility
64
+ - Pydantic v2
65
+ - Redis
66
+ - Alembic
67
+ - JWT + bcrypt + pyotp
68
+ - Docker and Docker Compose
69
+ - pytest
70
+
71
+ ## Architecture
72
+
73
+ ```text
74
+ app/
75
+ ├── api/
76
+ │ ├── deps/
77
+ │ └── v1/
78
+ │ ├── endpoints/
79
+ │ └── routers/
80
+ ├── core/
81
+ │ ├── config/
82
+ │ ├── exceptions/
83
+ │ ├── middleware/
84
+ │ └── security/
85
+ ├── db/
86
+ │ └── migrations/
87
+ ├── models/
88
+ │ ├── domain/
89
+ │ └── schemas/
90
+ ├── repositories/
91
+ ├── services/
92
+ ├── tests/
93
+ ├── main.py
94
+ ├── __init__.py
95
+
96
+ scripts/
97
+ ├── create_admin.py
98
+ ├── run_migrations.py
99
+ ├── seed_data.py
100
+
101
+ docker/
102
+ ├── Dockerfile
103
+ ├── docker-compose.yml
104
+
105
+ alembic.ini
106
+ pyproject.toml
107
+ requirements.txt
108
+ requirements-dev.txt
109
+ .env.example
110
+ README.md
111
+ ```
112
+
113
+ ## Quick Start
114
+
115
+ ### Prerequisites
116
+
117
+ - Python 3.12+
118
+ - PostgreSQL or Docker
119
+ - Redis or Docker
120
+ - Git
121
+
122
+ ### 1. Clone the repository
123
+
124
+ ```bash
125
+ git clone <repository-url>
126
+ cd hinbert_fastapi
127
+ ```
128
+
129
+ ### 2. Create a virtual environment
130
+
131
+ ```bash
132
+ python -m venv .venv
133
+ ```
134
+
135
+ On Windows PowerShell:
136
+
137
+ ```powershell
138
+ .\.venv\Scripts\Activate.ps1
139
+ ```
140
+
141
+ On macOS/Linux:
142
+
143
+ ```bash
144
+ source .venv/bin/activate
145
+ ```
146
+
147
+ ### 3. Install dependencies
148
+
149
+ ```bash
150
+ pip install -r requirements.txt
151
+ pip install -r requirements-dev.txt
152
+ ```
153
+
154
+ ### 4. Configure environment variables
155
+
156
+ ```bash
157
+ copy .env.example .env
158
+ ```
159
+
160
+ or:
161
+
162
+ ```bash
163
+ cp .env.example .env
164
+ ```
165
+
166
+ Update the values in `.env` for your database, Redis, JWT secret, SMTP settings, and OAuth credentials.
167
+
168
+ ### 5. Run database migrations
169
+
170
+ ```bash
171
+ python -m scripts.run_migrations
172
+ ```
173
+
174
+ ### 6. Start the API
175
+
176
+ ```bash
177
+ uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
178
+ ```
179
+
180
+ Once running, the app is available at:
181
+
182
+ - API: http://localhost:8000
183
+ - Swagger UI: http://localhost:8000/docs
184
+ - ReDoc: http://localhost:8000/redoc
185
+ - Health: http://localhost:8000/health
186
+
187
+ ## Docker Setup
188
+
189
+ This project includes a Docker Compose setup for local development.
190
+
191
+ ```bash
192
+ docker compose -f docker/docker-compose.yml up --build
193
+ ```
194
+
195
+ To stop it:
196
+
197
+ ```bash
198
+ docker compose -f docker/docker-compose.yml down
199
+ ```
200
+
201
+ ## API Highlights
202
+
203
+ The application exposes a versioned API under `/api/v1`.
204
+
205
+ ### Auth endpoints
206
+
207
+ - `/api/v1/auth/signup`
208
+ - `/api/v1/auth/login`
209
+ - `/api/v1/auth/refresh`
210
+ - `/api/v1/auth/logout`
211
+ - `/api/v1/auth/forgot-password`
212
+ - `/api/v1/auth/reset-password`
213
+ - `/api/v1/auth/totp/setup`
214
+ - `/api/v1/auth/totp/verify`
215
+ - `/api/v1/auth/google`
216
+ - `/api/v1/auth/facebook`
217
+
218
+ ### Product endpoints
219
+
220
+ - `/api/v1/products`
221
+ - `/api/v1/products/{product_id}`
222
+
223
+ ### User endpoints
224
+
225
+ - `/api/v1/users/me`
226
+ - admin/user management routes where applicable
227
+
228
+ ## Example Authentication Flow
229
+
230
+ ```json
231
+ {
232
+ "email": "user@example.com",
233
+ "password": "StrongPassword!123"
234
+ }
235
+ ```
236
+
237
+ The login response returns both an access token and refresh token:
238
+
239
+ ```http
240
+ Authorization: Bearer <access_token>
241
+ ```
242
+
243
+ ## Environment Configuration
244
+
245
+ The project reads configuration using Pydantic settings from `.env` and supports values such as:
246
+
247
+ - `DATABASE_URL`
248
+ - `REDIS_URL`
249
+ - `SECRET_KEY`
250
+ - `ALGORITHM`
251
+ - `ACCESS_TOKEN_EXPIRE_MINUTES`
252
+ - `REFRESH_TOKEN_EXPIRE_DAYS`
253
+ - `SMTP_HOST`
254
+ - `SMTP_PORT`
255
+ - `EMAIL_FROM`
256
+ - `GOOGLE_CLIENT_ID`
257
+ - `FACEBOOK_CLIENT_ID`
258
+ - `BACKEND_CORS_ORIGINS`
259
+
260
+ ## Testing
261
+
262
+ Run the test suite with:
263
+
264
+ ```bash
265
+ pytest
266
+ ```
267
+
268
+ Targeted test folders:
269
+
270
+ ```bash
271
+ pytest app/tests/unit
272
+ pytest app/tests/integration
273
+ ```
274
+
275
+ ## Security Notes
276
+
277
+ This project includes strong defaults for a starter backend, but production deployments should still:
278
+
279
+ - replace the default JWT secret with a secure secret manager value
280
+ - restrict CORS origins to trusted domains
281
+ - protect database credentials and infrastructure endpoints
282
+ - use HTTPS behind a reverse proxy or load balancer
283
+ - configure valid SMTP and OAuth provider credentials
284
+ - enable monitoring, backups, and secure deployment policies
285
+
286
+ ## Contributing
287
+
288
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md).
289
+
290
+ ## License
291
+
292
+ MIT License. See [LICENSE](LICENSE) for details.
293
+
294
+ ## Support
295
+
296
+ If you find this useful, please give it a ⭐ on GitHub!
297
+
298
+
@@ -1,40 +1,40 @@
1
- """Bearer-token dependencies for protected routes."""
2
-
3
- from uuid import UUID
4
-
5
- from fastapi import Depends
6
- from fastapi.security import OAuth2PasswordBearer
7
- from sqlalchemy.ext.asyncio import AsyncSession
8
-
9
- from app.core.exceptions.custom_exceptions import UnauthorizedError
10
- from app.core.security.jwt import decode_token
11
- from app.db.session import get_db
12
- from app.models.domain.user import User
13
-
14
- oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
15
-
16
-
17
- async def get_current_user(token: str = Depends(oauth2_scheme), session: AsyncSession = Depends(get_db)) -> User:
18
- """Decode an access token and load its user, failing closed on any error."""
19
- try:
20
- subject = UUID(decode_token(token)["sub"])
21
- except (ValueError, KeyError) as exc:
22
- raise UnauthorizedError() from exc
23
- user = await session.get(User, subject)
24
- if user is None:
25
- raise UnauthorizedError()
26
- return user
27
-
28
-
29
- async def get_current_active_user(user: User = Depends(get_current_user)) -> User:
30
- """Reject deactivated accounts before protected business operations."""
31
- if not user.is_active:
32
- raise UnauthorizedError("Inactive account")
33
- return user
34
-
35
-
36
- async def get_current_admin(user: User = Depends(get_current_active_user)) -> User:
37
- """Require an active account with administrator privileges."""
38
- if not user.is_admin:
39
- raise UnauthorizedError("Administrator privileges required")
40
- return user
1
+ """Bearer-token dependencies for protected routes."""
2
+
3
+ from uuid import UUID
4
+
5
+ from fastapi import Depends
6
+ from fastapi.security import OAuth2PasswordBearer
7
+ from sqlalchemy.ext.asyncio import AsyncSession
8
+
9
+ from app.core.exceptions.custom_exceptions import UnauthorizedError
10
+ from app.core.security.jwt import decode_token
11
+ from app.db.session import get_db
12
+ from app.models.domain.user import User
13
+
14
+ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
15
+
16
+
17
+ async def get_current_user(token: str = Depends(oauth2_scheme), session: AsyncSession = Depends(get_db)) -> User:
18
+ """Decode an access token and load its user, failing closed on any error."""
19
+ try:
20
+ subject = UUID(decode_token(token)["sub"])
21
+ except (ValueError, KeyError) as exc:
22
+ raise UnauthorizedError() from exc
23
+ user = await session.get(User, subject)
24
+ if user is None:
25
+ raise UnauthorizedError()
26
+ return user
27
+
28
+
29
+ async def get_current_active_user(user: User = Depends(get_current_user)) -> User:
30
+ """Reject deactivated accounts before protected business operations."""
31
+ if not user.is_active:
32
+ raise UnauthorizedError("Inactive account")
33
+ return user
34
+
35
+
36
+ async def get_current_admin(user: User = Depends(get_current_active_user)) -> User:
37
+ """Require an active account with administrator privileges."""
38
+ if not user.is_admin:
39
+ raise UnauthorizedError("Administrator privileges required")
40
+ return user