feat: password change 3-step modal with strength meter, default admin/admin123

This commit is contained in:
nogueiraguh
2026-04-02 18:09:44 -03:00
parent eb34a44664
commit 856e3b6674
5 changed files with 233 additions and 41 deletions

View File

@@ -543,13 +543,11 @@ def init_db():
log.info(f"Recovered stuck workspace {ws['id']}: {ws['status']} -> {prev}")
adm = c.execute("SELECT id FROM users WHERE username='admin'").fetchone()
if not adm:
_tmp_pw = secrets.token_urlsafe(16)
c.execute(
"INSERT INTO users (id,first_name,last_name,username,email,password_hash,role,must_change_password) VALUES (?,?,?,?,?,?,?,?)",
(str(uuid.uuid4()), "Admin", "Sistema", "admin", "admin@local", _hash_pw(_tmp_pw), "admin", 1)
(str(uuid.uuid4()), "Admin", "Sistema", "admin", "admin@local", _hash_pw("admin123"), "admin", 1)
)
log.info(f"Default admin created — username: admin / password: {_tmp_pw}")
log.info("⚠ Change the admin password on first login!")
log.info("Default admin created — username: admin / password: admin123")
# ── Crypto helpers ────────────────────────────────────────────────────────────
def _hash_pw(pw): salt=secrets.token_hex(16); h=hashlib.pbkdf2_hmac("sha256",pw.encode(),salt.encode(),100_000); return f"{salt}:{h.hex()}"
@@ -899,7 +897,15 @@ async def change_pw(req: ChangePwReq, u=Depends(current_user)):
if u.get("auth_provider") == "oidc":
raise HTTPException(400, "Usuários OIDC não podem alterar senha localmente")
if not _verify_pw(req.current_password, u["password_hash"]): raise HTTPException(400, "Senha atual incorreta")
with db() as c: c.execute("UPDATE users SET password_hash=?, must_change_password=0 WHERE id=?", (_hash_pw(req.new_password), u["id"]))
pw = req.new_password
import re
if len(pw) < 8: raise HTTPException(400, "Senha deve ter no mínimo 8 caracteres")
if not re.search(r'[A-Z]', pw): raise HTTPException(400, "Senha deve conter ao menos uma letra maiúscula")
if not re.search(r'[a-z]', pw): raise HTTPException(400, "Senha deve conter ao menos uma letra minúscula")
if not re.search(r'\d', pw): raise HTTPException(400, "Senha deve conter ao menos um número")
if not re.search(r'[^A-Za-z0-9]', pw): raise HTTPException(400, "Senha deve conter ao menos um caractere especial")
if pw == req.current_password: raise HTTPException(400, "A nova senha deve ser diferente da atual")
with db() as c: c.execute("UPDATE users SET password_hash=?, must_change_password=0 WHERE id=?", (_hash_pw(pw), u["id"]))
return {"ok": True}
# ── OIDC endpoints ───────────────────────────────────────────────────────────