feat: create NAV_ADMIN user if missing; optional password sync from env

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-05-12 15:57:29 +08:00
parent a5e1e94fb2
commit 9632b91e70
2 changed files with 35 additions and 2 deletions
+8 -2
View File
@@ -4,10 +4,16 @@
# 必填(长期运行):随机字符串,用于会话与 CSRF。生成见下方「密钥」说明。 # 必填(长期运行):随机字符串,用于会话与 CSRF。生成见下方「密钥」说明。
# NAV_SECRET_KEY= # NAV_SECRET_KEY=
# 仅当数据库里还没有任何用户时生效(首次启动):首个管理员账号 # 首次启动且库中没有任何用户时:创建首个管理员(并建默认分组)
# NAV_ADMIN_USERNAME=admin # NAV_ADMIN_USERNAME=admin
# NAV_ADMIN_PASSWORD=请改成强密码 # NAV_ADMIN_PASSWORD=请改成强密码
# 若库中已有用户(例如曾创建过 admin),仅改 .env 不会改旧账号密码。
# 下面两项在「每次启动」时生效:
# - 若 NAV_ADMIN_USERNAME 在库中尚不存在:自动创建该用户(密码取 NAV_ADMIN_PASSWORD)。
# - 若该用户已存在且设置 NAV_ADMIN_UPDATE_PASSWORD=1:用 NAV_ADMIN_PASSWORD 覆盖其密码(改完请删去或置 0,避免每次启动重置)。
# NAV_ADMIN_UPDATE_PASSWORD=1
# 数据库(默认 SQLite 文件在当前工作目录) # 数据库(默认 SQLite 文件在当前工作目录)
# NAV_DATABASE_URL=sqlite:///nav_local.db # NAV_DATABASE_URL=sqlite:///nav_local.db
@@ -20,7 +26,7 @@
# 在 Nginx/Caddy 等反向代理后部署时:信任 X-Forwarded-*,以便 Cookie、CSRF 与 HTTPS 判断正确 # 在 Nginx/Caddy 等反向代理后部署时:信任 X-Forwarded-*,以便 Cookie、CSRF 与 HTTPS 判断正确
# NAV_TRUST_PROXY=1 # NAV_TRUST_PROXY=1
# 站点仅通过 HTTPS 对外时建议开启(浏览器只带 Secure Cookie # 站点仅通过 https:// 对外访问时建议开启;若用 http://内网IP:端口 访问请勿开启,否则浏览器不保存登录 Cookie
# NAV_SESSION_COOKIE_SECURE=1 # NAV_SESSION_COOKIE_SECURE=1
# CSRF 校验仍失败时,可填前端访问的完整 Origin,多个用英文逗号分隔,例如: # CSRF 校验仍失败时,可填前端访问的完整 Origin,多个用英文逗号分隔,例如:
# NAV_CSRF_TRUSTED_ORIGINS=https://nav.example.com # NAV_CSRF_TRUSTED_ORIGINS=https://nav.example.com
+27
View File
@@ -87,6 +87,7 @@ def create_app() -> Flask:
with app.app_context(): with app.app_context():
db.create_all() db.create_all()
_ensure_default_user() _ensure_default_user()
_ensure_admin_from_env()
@app.route("/login", methods=["GET", "POST"]) @app.route("/login", methods=["GET", "POST"])
def login(): def login():
@@ -327,6 +328,32 @@ def _ensure_default_user() -> None:
) )
def _ensure_admin_from_env() -> None:
"""库中已有用户后,.env 里的管理员账号不会自动覆盖旧库;若配置了用户名且尚不存在则补建。"""
username = (os.environ.get("NAV_ADMIN_USERNAME") or "").strip()
password = os.environ.get("NAV_ADMIN_PASSWORD")
if not username or password is None or password == "":
return
existing = User.query.filter_by(username=username).first()
if existing:
if os.environ.get("NAV_ADMIN_UPDATE_PASSWORD") == "1":
existing.set_password(password)
db.session.commit()
print(
f"[nav] 已按 NAV_ADMIN_UPDATE_PASSWORD=1 更新用户「{username}」的登录密码。",
flush=True,
)
return
u = User(username=username)
u.set_password(password)
db.session.add(u)
db.session.commit()
print(
f"[nav] 已从环境变量创建用户「{username}」(此前库中无此用户名)。",
flush=True,
)
app = create_app() app = create_app()
if __name__ == "__main__": if __name__ == "__main__":