account-kit 0.2.2__tar.gz → 0.2.3__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 (73) hide show
  1. {account_kit-0.2.2 → account_kit-0.2.3}/MANIFEST.in +1 -0
  2. account_kit-0.2.3/PKG-INFO +382 -0
  3. account_kit-0.2.3/README.md +337 -0
  4. {account_kit-0.2.2 → account_kit-0.2.3}/pyproject.toml +2 -2
  5. account_kit-0.2.3/src/account_kit/__init__.py +19 -0
  6. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/admin_router.py +31 -0
  7. account_kit-0.2.3/src/account_kit/admin_setup.py +114 -0
  8. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/audit.py +1 -0
  9. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/captcha.py +13 -3
  10. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/captcha_image.py +1 -1
  11. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/catalog.py +23 -2
  12. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/config.py +31 -2
  13. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/deps.py +33 -1
  14. account_kit-0.2.3/src/account_kit/lockout.py +68 -0
  15. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/models.py +10 -2
  16. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/router.py +35 -6
  17. account_kit-0.2.3/src/account_kit/schema_setup.py +75 -0
  18. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/schemas.py +1 -1
  19. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/security.py +4 -3
  20. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/service.py +23 -9
  21. account_kit-0.2.3/src/account_kit/sql/upgrade_0_2_3.sql +28 -0
  22. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/state.py +15 -0
  23. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/two_factor/router.py +20 -4
  24. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/two_factor/service.py +4 -0
  25. account_kit-0.2.3/src/account_kit.egg-info/PKG-INFO +382 -0
  26. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit.egg-info/SOURCES.txt +4 -0
  27. {account_kit-0.2.2 → account_kit-0.2.3}/tests/helpers.py +9 -0
  28. account_kit-0.2.3/tests/test_admin_security.py +353 -0
  29. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_auth.py +1 -1
  30. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_refresh_logout.py +1 -1
  31. account_kit-0.2.3/tests/test_schema.py +149 -0
  32. account_kit-0.2.2/PKG-INFO +0 -198
  33. account_kit-0.2.2/README.md +0 -153
  34. account_kit-0.2.2/src/account_kit/__init__.py +0 -9
  35. account_kit-0.2.2/src/account_kit/schema_setup.py +0 -35
  36. account_kit-0.2.2/src/account_kit.egg-info/PKG-INFO +0 -198
  37. account_kit-0.2.2/tests/test_schema.py +0 -68
  38. {account_kit-0.2.2 → account_kit-0.2.3}/LICENSE +0 -0
  39. {account_kit-0.2.2 → account_kit-0.2.3}/setup.cfg +0 -0
  40. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/admin_schemas.py +0 -0
  41. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/avatar.py +0 -0
  42. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/crypto.py +0 -0
  43. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/db.py +0 -0
  44. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/emailer.py +0 -0
  45. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/otp.py +0 -0
  46. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/profile.py +0 -0
  47. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/seed.py +0 -0
  48. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/sql/upgrade_0_2_2.sql +0 -0
  49. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/templates/emails/two_factor_disable_en.html +0 -0
  50. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/templates/emails/two_factor_disable_zh.html +0 -0
  51. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/templates/emails/two_factor_login_en.html +0 -0
  52. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/templates/emails/two_factor_login_zh.html +0 -0
  53. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/templates/emails/verification_en.html +0 -0
  54. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/templates/emails/verification_zh.html +0 -0
  55. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/tokens.py +0 -0
  56. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/two_factor/__init__.py +0 -0
  57. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/two_factor/challenges.py +0 -0
  58. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit/two_factor/totp.py +0 -0
  59. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit.egg-info/dependency_links.txt +0 -0
  60. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit.egg-info/requires.txt +0 -0
  61. {account_kit-0.2.2 → account_kit-0.2.3}/src/account_kit.egg-info/top_level.txt +0 -0
  62. {account_kit-0.2.2 → account_kit-0.2.3}/tests/__init__.py +0 -0
  63. {account_kit-0.2.2 → account_kit-0.2.3}/tests/conftest.py +0 -0
  64. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_avatar.py +0 -0
  65. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_change_email.py +0 -0
  66. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_change_password.py +0 -0
  67. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_delete_audit_captcha.py +0 -0
  68. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_email_2fa_captcha.py +0 -0
  69. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_otp_limits.py +0 -0
  70. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_role_change_me.py +0 -0
  71. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_templates.py +0 -0
  72. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_two_factor.py +0 -0
  73. {account_kit-0.2.2 → account_kit-0.2.3}/tests/test_user_response_birth.py +0 -0
@@ -1,2 +1,3 @@
1
1
  graft tests
2
+ prune examples
2
3
  global-exclude __pycache__ *.py[cod]
@@ -0,0 +1,382 @@
1
+ Metadata-Version: 2.4
2
+ Name: account-kit
3
+ Version: 0.2.3
4
+ Summary: Reusable async account/auth service for FastAPI + PostgreSQL
5
+ Author: kqstone
6
+ License-Expression: MIT
7
+ Keywords: fastapi,authentication,account,jwt,totp,2fa,sqlalchemy,asyncpg,postgresql
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Framework :: FastAPI
10
+ Classifier: Framework :: AsyncIO
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Natural Language :: Chinese (Simplified)
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
22
+ Classifier: Topic :: Security
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Requires-Python: >=3.9
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: fastapi>=0.110
28
+ Requires-Dist: sqlalchemy[asyncio]>=2.0
29
+ Requires-Dist: asyncpg>=0.29
30
+ Requires-Dist: pydantic[email]>=2.0
31
+ Requires-Dist: python-jose[cryptography]>=3.3
32
+ Requires-Dist: bcrypt>=4.0
33
+ Requires-Dist: python-multipart
34
+ Requires-Dist: jinja2>=3.1
35
+ Requires-Dist: pyotp>=2.9
36
+ Requires-Dist: cryptography
37
+ Provides-Extra: captcha
38
+ Requires-Dist: Pillow>=9.2; extra == "captcha"
39
+ Provides-Extra: dev
40
+ Requires-Dist: pytest>=8; extra == "dev"
41
+ Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
42
+ Requires-Dist: httpx>=0.27; extra == "dev"
43
+ Requires-Dist: Pillow>=9.2; extra == "dev"
44
+ Dynamic: license-file
45
+
46
+ # account-kit
47
+
48
+ [![PyPI Version](https://img.shields.io/pypi/v/account-kit.svg)](https://pypi.org/project/account-kit/)
49
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
50
+
51
+ 通用、可复用的 **FastAPI + PostgreSQL** 异步账号与认证库(基于 SQLAlchemy 2.0 + asyncpg,数据表统一置于 `auth` schema,用户主键为 UUID)。配套开箱即用的 Vue 3 与 React 界面组件包:`@kqstone/account-ui-vue`、`@kqstone/account-ui-react`。
52
+
53
+ > **边界划分**:`account-kit` 专注提供账号注册、认证鉴权、安全凭据维护、两步验证与用户目录等通用账号基础能力;宿主应用的业务限额、积分/会员权益规则、业务接口级频控限流等请在宿主应用中实现。
54
+
55
+ ---
56
+
57
+ ## 功能列表 (0.2.2)
58
+
59
+ - **核心认证**:账号密码注册与登录、邮箱验证码流转、管理员注册审批机制、单设备互踢会话模式 (`single_device`)、自定义业务角色与用户等级目录、后台管理员权限 (`is_admin`) 隔离。
60
+ - **两步验证 (2FA / MFA)**:基于 TOTP 标准的时间戳动态口令、应急备用恢复码、受信设备免验证保持、邮箱验证码作为备用第二因素(用于免验证器登录或紧急解绑)。
61
+ - **图形验证码 (Captcha)**:连续登录失败自动触发验证码拦截,支持宿主自定义校验服务或开箱即用的内置图形验证码。
62
+ - **防爆破与频控限流**:验证码输错上限熔断与失效锁定机制,全站验证码发信、密码重置、登录端点 IP 与用户维度的滑动窗口频控。
63
+ - **账号与资料安全**:换绑邮箱强制新邮箱验证码验证、刷新令牌 (Refresh Token) 家族轮换与重放检测惩罚、标准注销登录端点、用户自助注销账号(支持硬删除与脱敏软删除)。
64
+ - **安全审计与扩展**:独立事务记录的关键安全审计日志与后台查询、用户头像管理回调、Jinja2 邮件模板按用途覆盖机制、安全临时状态后端存储(支持跨进程/实例共享的 `db` 模式及单进程 `memory` 模式)。
65
+
66
+ ---
67
+
68
+ ## 安装
69
+
70
+ ### Python 后端包
71
+
72
+ 从 [PyPI](https://pypi.org/project/account-kit/) 安装:
73
+
74
+ ```bash
75
+ # 基础核心包
76
+ pip install account-kit
77
+
78
+ # 若需要使用内置图形验证码功能(包含 Pillow 图像处理依赖)
79
+ pip install "account-kit[captcha]"
80
+ ```
81
+
82
+ ### 前端界面组件包
83
+
84
+ 配套的前端界面组件发布于 **GitHub Packages**。在项目根目录下配置 `.npmrc` 文件:
85
+
86
+ ```ini
87
+ @kqstone:registry=https://npm.pkg.github.com
88
+ //npm.pkg.github.com/:_authToken=${NPM_TOKEN}
89
+ ```
90
+
91
+ - 本地安装时,`NPM_TOKEN` 需配置具备 `read:packages` 权限的 Personal Access Token (Classic PAT)。
92
+ - 在 CI/CD(如 GitHub Actions)中,若使用默认的 `GITHUB_TOKEN`,需预先在包管理页面的 **Manage Actions access** 中为你的消费仓库授权 Read 访问权限。
93
+
94
+ 安装对应的框架包:
95
+
96
+ ```bash
97
+ # Vue 3 项目
98
+ npm install @kqstone/account-ui-vue
99
+
100
+ # React 18 / 19 项目
101
+ npm install @kqstone/account-ui-react
102
+ ```
103
+
104
+ ---
105
+
106
+ ## 快速开始
107
+
108
+ 以下为最小可运行的 FastAPI 应用示例:
109
+
110
+ ```python
111
+ from contextlib import asynccontextmanager
112
+ from fastapi import FastAPI
113
+ from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
114
+
115
+ from account_kit import ensure_schema, ensure_schema_sync, init_db, mount_account, seed_defaults
116
+ from account_kit.config import AccountKitConfig, SmtpConfig
117
+
118
+ DATABASE_URL = "postgresql+asyncpg://postgres:postgres@localhost:5432/my_app"
119
+
120
+ engine = create_async_engine(DATABASE_URL)
121
+ session_factory = async_sessionmaker(engine, expire_on_commit=False)
122
+
123
+
124
+ async def get_db():
125
+ async with session_factory() as session:
126
+ yield session
127
+
128
+
129
+ @asynccontextmanager
130
+ async def lifespan(app: FastAPI):
131
+ # 自动创建 auth schema 及相关数据表(幂等安全,亦可使用 ensure_schema)
132
+ await init_db(engine)
133
+ # 初始化预置角色 (user) 与等级 (free, pro)
134
+ async with session_factory() as session:
135
+ await seed_defaults(session)
136
+ yield
137
+ await engine.dispose()
138
+
139
+
140
+ app = FastAPI(title="My App", lifespan=lifespan)
141
+
142
+ # 配置并挂载账号系统
143
+ config = AccountKitConfig(
144
+ jwt_secret="your-secure-jwt-secret-key",
145
+ brand_name="MyApp",
146
+ # 可选:配置真实发信邮箱
147
+ # smtp=SmtpConfig(host="smtp.example.com", port=587, user="no-reply@example.com", password="pwd", from_email="no-reply@example.com"),
148
+ )
149
+
150
+ mount_account(app, get_db, config)
151
+ ```
152
+
153
+ 启动应用后,认证路由将自动挂载至 `/api/auth`,后台管理路由将挂载至 `/api/admin/account`。
154
+
155
+ ---
156
+
157
+ ## 配置参考
158
+
159
+ 宿主应用在初始化时向 `mount_account` 传入 `AccountKitConfig`。下表列出最常用的核心配置项:
160
+
161
+ | 配置项 | 默认值 | 说明 |
162
+ | :--- | :--- | :--- |
163
+ | `jwt_secret` | *(必填)* | JWT 签名密钥(生产环境请务必保持保密且随机) |
164
+ | `session_mode` | `"stateless"` | 会话模式:`"stateless"`(无状态令牌)或 `"single_device"`(单设备互踢) |
165
+ | `require_approval` | `False` | 新用户注册是否需管理员在后台审批通过后方可登录 |
166
+ | `state_backend` | `"db"` | 安全临时状态存储:`"db"`(写入数据库,支持多进程共享)或 `"memory"` |
167
+ | `refresh_token_enabled` | `False` | 是否启用 Refresh Token 轮换与无感刷新机制 |
168
+ | `two_factor_enabled` | `True` | 是否启用 TOTP 两步验证能力 |
169
+ | `two_factor_email_enabled` | `False` | 是否允许通过邮箱验证码作为登录第二因素(跳过验证器) |
170
+ | `captcha_builtin` | `False` | 是否启用内置图形验证码接口(需安装 `account-kit[captcha]`) |
171
+ | `logout_enabled` | `True` | 是否挂载注销登录端点(默认路径 `/logout`) |
172
+ | `self_delete_enabled` | `False` | 是否允许普通用户自助注销账号 |
173
+ | `user_delete_mode` | `"hard"` | 账号删除模式:`"hard"`(物理删除)或 `"soft"`(数据脱敏软删除) |
174
+ | `audit_log_enabled` | `True` | 是否将登录、改密、2FA 变更等敏感事件记入审计日志表 |
175
+ | `api_prefix` | `"/api/auth"` | 用户端与公共端点挂载前缀 |
176
+ | `admin_prefix` | `"/api/admin/account"` | 管理员端点挂载前缀 |
177
+
178
+ 完整的 70+ 项配置与 `SmtpConfig` 详细说明,请参阅完整文档:[docs/configuration.md](docs/configuration.md)。
179
+
180
+ ---
181
+
182
+ ## API 端点概览
183
+
184
+ 路由挂载前缀默认为 `{api_prefix}`(`/api/auth`)与 `{admin_prefix}`(`/api/admin/account`)。
185
+
186
+ ### 用户与公共端点
187
+
188
+ | 方法 | 路径 | 说明 | 所需配置开关 |
189
+ | :--- | :--- | :--- | :--- |
190
+ | `POST` | `{api_prefix}/login` | 用户名密码登录(支持单设备、图形验证码与 2FA) | - |
191
+ | `POST` | `{api_prefix}/send-code` | 发送邮箱验证码(注册/找回密码/改密) | - |
192
+ | `POST` | `{api_prefix}/verify-code` | 预校验邮箱验证码有效性 | - |
193
+ | `POST` | `{api_prefix}/register` | 用户注册 | - |
194
+ | `POST` | `{api_prefix}/reset-password` | 通过验证码重置密码 | - |
195
+ | `POST` | `{api_prefix}/refresh` | 轮换刷新令牌换取新的 Access Token | `refresh_token_enabled` |
196
+ | `POST` | `{api_prefix}{logout_path}` | 退出登录(吊销会话及刷新令牌,默认 `/logout`) | `logout_enabled` |
197
+ | `GET` | `{api_prefix}/captcha` | 获取内置图形验证码图片与 ID | `captcha_builtin` |
198
+ | `GET` | `{api_prefix}/me` | 获取当前登录用户详细资料 | - |
199
+ | `PATCH` | `{api_prefix}/me` | 更新用户资料(修改邮箱默认要求验证码) | - |
200
+ | `POST` | `{api_prefix}/change-password` | 独立修改密码端点(校验旧密码) | - |
201
+ | `POST` | `{api_prefix}/me/email/send-code`| 向新邮箱发送换绑验证码 | - |
202
+ | `POST` | `{api_prefix}/me/email` | 验证并确认换绑邮箱 | - |
203
+ | `POST` | `{api_prefix}/me/delete` / `DELETE` | 自助注销账号(需密码;开启 2FA 需提供第二因素) | `self_delete_enabled` |
204
+ | `POST` | `{api_prefix}/me/delete/email-code` | 发送用于账号注销的邮箱验证码 | `self_delete_enabled` + `two_factor_email_enabled` |
205
+ | `POST` | `{api_prefix}/me/avatar` | 上传个人头像 | `avatar_enabled` |
206
+ | `DELETE` | `{api_prefix}/me/avatar` | 删除个人头像 | `avatar_enabled` |
207
+ | `GET` | `{api_prefix}/users/{user_id}/avatar` | 获取指定用户头像 | `avatar_enabled` |
208
+ | `GET` | `{api_prefix}/roles` | 获取公开注册可选的角色列表 | - |
209
+ | `GET` | `{api_prefix}/tiers` | 获取公开的用户等级目录 | - |
210
+ | `POST` | `{api_prefix}/role-change-requests` | 提交角色变更申请 | `role_change_enabled` |
211
+ | `GET` | `{api_prefix}/role-change-requests/me` | 查询当前用户未决的角色申请 | `role_change_enabled` |
212
+
213
+ ### 两步验证 (2FA) 端点
214
+
215
+ 需开启 `two_factor_enabled=True`(默认开启)。
216
+
217
+ | 方法 | 路径 | 说明 | 所需配置开关 |
218
+ | :--- | :--- | :--- | :--- |
219
+ | `GET` | `{api_prefix}/2fa/status` | 查询两步验证状态与剩余恢复码数量 | - |
220
+ | `POST` | `{api_prefix}/2fa/setup` | 获取 TOTP 密钥与绑定二维码 URI | - |
221
+ | `POST` | `{api_prefix}/2fa/enable` | 提交 TOTP 码激活 2FA,并获取 10 组恢复码 | - |
222
+ | `POST` | `{api_prefix}/2fa/disable` | 关闭 2FA(需当前密码 + 验证码/恢复码/邮箱码) | - |
223
+ | `POST` | `{api_prefix}/2fa/disable/email-code` | 发送用于关闭 2FA 的邮箱验证码 | `two_factor_email_enabled` |
224
+ | `POST` | `{api_prefix}/2fa/recovery-codes/regenerate` | 重新生成恢复码 | - |
225
+ | `GET` | `{api_prefix}/trusted-devices` | 查询当前用户的受信任免密设备列表 | - |
226
+ | `DELETE` | `{api_prefix}/trusted-devices/{device_id}` | 吊销指定的受信任设备 | - |
227
+ | `DELETE` | `{api_prefix}/trusted-devices` | 吊销全部受信任设备 | - |
228
+ | `POST` | `{api_prefix}/login/2fa` | 登录第二步验证(提交 TOTP/恢复码/邮箱码) | - |
229
+ | `POST` | `{api_prefix}/login/2fa/email/send` | 登录时向邮箱发送一次性第二因素验证码 | `two_factor_email_enabled` |
230
+
231
+ ### 管理员后台端点
232
+
233
+ 需具备管理员权限 (`is_admin=True`)。系统恰好一名管理员,只能由宿主调用 `account_kit.ensure_admin(db, username, email, password)` 创建,任何 API 都不能修改 `is_admin`、删除或停用管理员;管理员登录默认连续 5 次失败锁定 15 分钟。详见 [docs/configuration.md](docs/configuration.md) 与 [docs/upgrade.md](docs/upgrade.md)。
234
+
235
+ | 方法 | 路径 | 说明 | 所需配置开关 |
236
+ | :--- | :--- | :--- | :--- |
237
+ | `GET` / `POST` | `{admin_prefix}/roles` | 查询/创建角色 | - |
238
+ | `PATCH` / `DELETE` | `{admin_prefix}/roles/{code}` | 修改/删除指定角色 | - |
239
+ | `GET` / `POST` | `{admin_prefix}/tiers` | 查询/创建用户等级 | - |
240
+ | `PATCH` / `DELETE` | `{admin_prefix}/tiers/{code}` | 修改/删除指定等级 | - |
241
+ | `GET` | `{admin_prefix}/users` | 分页/全量查询用户列表 | - |
242
+ | `PATCH` | `{admin_prefix}/users/{user_id}` | 后台修改用户信息(角色、等级、审批、状态等) | - |
243
+ | `DELETE` | `{admin_prefix}/users/{user_id}` | 删除或软删除用户 | - |
244
+ | `POST` | `{admin_prefix}/users/{user_id}/2fa/reset` | 管理员强制重置用户 2FA | `two_factor_enabled` |
245
+ | `POST` | `{admin_prefix}/role-change-requests/{id}/review` | 审批角色变更申请 | - |
246
+ | `GET` | `{admin_prefix}/audit-logs` | 分页检索安全审计日志 | `audit_log_enabled` |
247
+
248
+ 接口传参、完整响应格式及业务错误码规范请阅读:[docs/api.md](docs/api.md)。
249
+
250
+ ---
251
+
252
+ ## 界面组件概览
253
+
254
+ `@kqstone/account-ui-vue` (Vue 3) 与 `@kqstone/account-ui-react` (React 18/19) 提供统一的组件能力与样式封装:
255
+
256
+ ### 核心 UI 组件
257
+
258
+ | 组件名 | 说明 |
259
+ | :--- | :--- |
260
+ | `LoginForm` | 账号密码登录表单,内置图形验证码拦截与 2FA 挑战引导 |
261
+ | `RegisterForm` | 用户注册表单,支持发送验证码与角色选择 |
262
+ | `ResetPasswordForm` | 密码找回与重置表单 |
263
+ | `TwoFactorSettings` | 2FA 管理面板(TOTP 绑定向导、二维码展示、恢复码生成、受信设备列表) |
264
+ | `TwoFactorLoginDialog` | 登录双因素验证弹窗(支持 TOTP 动态码、恢复码与邮箱备用码) |
265
+ | `ChangeEmailForm` | 换绑邮箱独立表单(向新邮箱发码、安全冷却与密码核验) |
266
+ | `DeleteAccountForm` | 自助注销账号表单(密码确认及 2FA 第二因素校验) |
267
+ | `ProfileFields` | 个人资料信息展示与编辑字段(支持改密邮箱验证码模式) |
268
+ | `AvatarUploader` | 头像上传与更新组件 |
269
+ | `UserAvatar` | 用户头像展示组件(支持性别默认占位与图片加载兜底) |
270
+ | `CaptchaImage` | 图形验证码图片展示与点击刷新组件 |
271
+ | `TierBadge` | 用户等级/会员徽章标签组件 |
272
+ | `LogoutButton` | 快捷登出按钮,自动清空本地会话并调用服务端注销接口 |
273
+
274
+ ### 客户端工具与 Token 管理
275
+
276
+ 界面包内置了请求客户端 `createAccountClient` 与令牌管理器 `createTokenStore`,支持 401 单飞(Single Flight)自动轮换 Token 与请求无感重试:
277
+
278
+ ```ts
279
+ import { createAccountClient, createTokenStore } from "@kqstone/account-ui-vue" // 或 @kqstone/account-ui-react
280
+
281
+ // 1. 创建本地令牌存储器(默认基于 localStorage)
282
+ const tokenStore = createTokenStore("my-app:tokens")
283
+
284
+ // 2. 初始化 API 客户端并配置 401 自动无感刷新
285
+ const client = createAccountClient("/api/auth", {
286
+ getToken: () => tokenStore.getAccessToken(),
287
+ autoRefresh: {
288
+ getRefreshToken: () => tokenStore.getRefreshToken(),
289
+ onTokens: (tokens) => tokenStore.set(tokens),
290
+ onRefreshFailed: () => tokenStore.clear(),
291
+ },
292
+ })
293
+
294
+ // 3. 发起调用(需传入 access token)
295
+ const user = await client.me(tokenStore.getAccessToken()!)
296
+ ```
297
+
298
+ ---
299
+
300
+ ## 升级说明 (0.2.1 → 0.2.2)
301
+
302
+ 从 0.2.1 升级至 0.2.2 的必做注意事项:
303
+
304
+ 1. **数据库补齐 4 张新表**:新增了限流计数、2FA 挑战、刷新令牌和图形验证码表。启动时调用 `await ensure_schema(engine)`,或在数据库执行 `sql/upgrade_0_2_2.sql`(可调 `upgrade_sql("0.2.2")` 读取)。
305
+ 2. **`PATCH /me` 修改邮箱默认需验证**:默认 `profile_email_change="verify"`。若请求中提交 `email` 必须携带验证码与密码;前端需适配换绑流程,或在服务端显式设置 `profile_email_change="direct"` 过渡。
306
+ 3. **状态存储默认切为数据库**:`state_backend="db"` 为默认值,安全计数跨进程/实例共享。单元测试若需快速重置计数,建议配置为 `state_backend="memory"`。
307
+ 4. **内置注册 `/logout` 端点**:kit 默认注册注销路由,若宿主应用在 `mount_account` 之后挂载了相同路径的路由,请注意避免冲突或设置 `logout_enabled=False`。
308
+ 5. **底层内部 API 异步化**:`mfa_required`、`captcha.*` 及 2FA 挑战读写方法已调整为 `async` 并要求传入 `db` 参数。
309
+
310
+ 查看包含 0.2.0 与 0.2.2 的完整演进说明,请参阅:[docs/upgrade.md](docs/upgrade.md)。
311
+
312
+ ---
313
+
314
+ ## 示例应用
315
+
316
+ 仓库内置了免 Docker 依赖、开箱即用的官方全功能演示程序(包含配置向导、站内虚拟信箱、前后端集成):
317
+
318
+ - 演示项目说明与操作指南:[examples/demo/README.md](examples/demo/README.md)
319
+ - 演示接口契约:[examples/demo/API.md](examples/demo/API.md)
320
+
321
+ 运行示例:
322
+
323
+ ```bash
324
+ cd examples/demo
325
+
326
+ # 运行 Vue 3 版本演示
327
+ ./run.sh vue
328
+
329
+ # 或运行 React 版本演示
330
+ ./run.sh react
331
+ ```
332
+
333
+ ---
334
+
335
+ ## 本地开发与测试
336
+
337
+ ### Python 后端单元测试
338
+
339
+ 测试基于 `pytest`,需要连接一个可用的 PostgreSQL 测试数据库:
340
+
341
+ ```bash
342
+ # 设置测试数据库连接串
343
+ export ACCOUNT_KIT_TEST_DATABASE_URL="postgresql+asyncpg://postgres:postgres@localhost:5432/account_kit_test"
344
+
345
+ # 安装开发依赖并运行测试
346
+ pip install -e ".[dev]"
347
+ pytest -q
348
+ ```
349
+
350
+ ### 前端组件包构建与测试
351
+
352
+ ```bash
353
+ cd packages/account-ui-vue
354
+ npm ci
355
+ npm run build
356
+ npm run typecheck
357
+
358
+ # React 包同理
359
+ cd ../account-ui-react
360
+ npm ci
361
+ npm run build
362
+ npm run typecheck
363
+ ```
364
+
365
+ ### 版本发布流程
366
+
367
+ 1. 确认版本号一致:`pyproject.toml`、`src/account_kit/__init__.py` 的 `__version__` 以及两个 `packages/*/package.json` 的 `version` 必须保持相同。
368
+ 2. 推送版本 Tag(如 `v0.2.2`):
369
+ ```bash
370
+ git tag v0.2.2
371
+ git push origin v0.2.2
372
+ ```
373
+ 3. GitHub Actions 自动执行:
374
+ - 检查三处版本号与 Tag 一致性并执行完整自动化测试。
375
+ - 通过 **PyPI Trusted Publishing**(OIDC 免密认证)将 Python 包发布到 PyPI。
376
+ - 使用 `GITHUB_TOKEN` 将前端组件包发布到 **GitHub Packages**。
377
+
378
+ ---
379
+
380
+ ## 许可证
381
+
382
+ 本项目基于 [MIT 许可证](LICENSE) 开源。