diff --git a/.env.example b/.env.example index 19ad718..3851f29 100644 --- a/.env.example +++ b/.env.example @@ -4,10 +4,16 @@ # 必填(长期运行):随机字符串,用于会话与 CSRF。生成见下方「密钥」说明。 # NAV_SECRET_KEY= -# 仅当数据库里还没有任何用户时生效(首次启动):首个管理员账号 +# 首次启动且库中没有任何用户时:创建首个管理员(并建默认分组) # NAV_ADMIN_USERNAME=admin # 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 文件在当前工作目录) # NAV_DATABASE_URL=sqlite:///nav_local.db @@ -20,7 +26,7 @@ # 在 Nginx/Caddy 等反向代理后部署时:信任 X-Forwarded-*,以便 Cookie、CSRF 与 HTTPS 判断正确 # NAV_TRUST_PROXY=1 -# 站点仅通过 HTTPS 对外时建议开启(浏览器只带 Secure Cookie) +# 站点仅通过 https:// 对外访问时建议开启;若用 http://内网IP:端口 访问请勿开启,否则浏览器不保存登录 Cookie # NAV_SESSION_COOKIE_SECURE=1 # CSRF 校验仍失败时,可填前端访问的完整 Origin,多个用英文逗号分隔,例如: # NAV_CSRF_TRUSTED_ORIGINS=https://nav.example.com diff --git a/app.py b/app.py index c915bf6..46e6778 100644 --- a/app.py +++ b/app.py @@ -87,6 +87,7 @@ def create_app() -> Flask: with app.app_context(): db.create_all() _ensure_default_user() + _ensure_admin_from_env() @app.route("/login", methods=["GET", "POST"]) 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() if __name__ == "__main__":