- 新增 apps/blog、apps/solutions、apps/home、apps/api 测试文件,覆盖标签/排序/ 草稿过滤、HomePage.subpage_types 回归测试、page_preview 预览接口 - apps/core/tests.py 新增健康检查端点、发布 webhook 信号、bootstrap_deployment 命令的测试用例,pytest 用例数从 40 增至 65,全部通过 - 修复 apps/api/urls.py 中 PagePreviewAPIViewSet.get_object() 未捕获 DoesNotExist 导致 500 而非文档承诺 404 的 bug - 新增 apps/core/management/commands/bootstrap_deployment.py:部署时按环境变量 幂等创建首个超级管理员账号并联动初始化 RBAC 权限组,.env.example 补充对应 环境变量说明 - 新增 OpenSearch + 中文分词本地 PoC 脚手架(docker-compose.opensearch.yml + docker/opensearch/Dockerfile),调研结论详见设计文档 §2.10 - 更新设计文档 §2.16 Phase 1 进度清单
57 lines
2.6 KiB
Python
57 lines
2.6 KiB
Python
"""
|
|
部署引导命令:首次上线(或每次部署)时自动完成"能登录后台 + 拥有正确权限组"这两件事,
|
|
避免每次部署都要人工登录服务器手动执行 `createsuperuser`。
|
|
|
|
用法:
|
|
python manage.py bootstrap_deployment
|
|
|
|
行为(幂等,可安全重复执行,适合放进部署脚本/容器启动脚本的 migrate 之后):
|
|
1. 若环境变量 DJANGO_SUPERUSER_USERNAME / DJANGO_SUPERUSER_EMAIL /
|
|
DJANGO_SUPERUSER_PASSWORD 均已设置,且该用户名尚不存在,则创建一个超级管理员账号。
|
|
- 若用户名已存在,跳过创建(不会重置密码,避免每次部署都覆盖已被人工修改过的密码)。
|
|
- 若三个环境变量未完整设置,跳过此步骤并给出提示(适用于已手动创建过超管、
|
|
或本地开发环境无需自动建号的场景)。
|
|
2. 调用 `setup_rbac_groups` 命令初始化/重置 RBAC 权限组(详见该命令的说明)。
|
|
|
|
安全说明:
|
|
- 密码只应通过环境变量/密钥管理服务注入,不会被写入日志。
|
|
- 本命令不会修改已存在用户的密码或权限,避免误覆盖人工调整过的账号状态。
|
|
"""
|
|
import os
|
|
|
|
from django.contrib.auth import get_user_model
|
|
from django.core.management import call_command
|
|
from django.core.management.base import BaseCommand
|
|
|
|
|
|
class Command(BaseCommand):
|
|
help = "部署引导:按需创建首个超级管理员账号 + 初始化 RBAC 权限组,可重复执行。"
|
|
|
|
def handle(self, *args, **options):
|
|
self._bootstrap_superuser()
|
|
call_command("setup_rbac_groups")
|
|
|
|
def _bootstrap_superuser(self):
|
|
username = os.environ.get("DJANGO_SUPERUSER_USERNAME")
|
|
email = os.environ.get("DJANGO_SUPERUSER_EMAIL")
|
|
password = os.environ.get("DJANGO_SUPERUSER_PASSWORD")
|
|
|
|
if not (username and email and password):
|
|
self.stdout.write(
|
|
self.style.WARNING(
|
|
"未完整设置 DJANGO_SUPERUSER_USERNAME / DJANGO_SUPERUSER_EMAIL / "
|
|
"DJANGO_SUPERUSER_PASSWORD,跳过自动创建超级管理员账号。"
|
|
)
|
|
)
|
|
return
|
|
|
|
User = get_user_model()
|
|
if User.objects.filter(username=username).exists():
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f"超级管理员账号 '{username}' 已存在,跳过创建。")
|
|
)
|
|
return
|
|
|
|
User.objects.create_superuser(username=username, email=email, password=password)
|
|
self.stdout.write(self.style.SUCCESS(f"已创建超级管理员账号 '{username}'。"))
|