Files
neon-bar86.ru/crm/set_all_passwords.py
2026-10-11 22:24:54 +05:00

63 lines
2.7 KiB
Python

"""Разовая утилита: задать ВСЕМ действующим учёткам CRM один пароль.
Использование:
python set_all_passwords.py neon2026
Обновляет dev-базу SQLite (crm/data/crm.db) и, если контейнер neon-db
запущен, базу PostgreSQL в docker-стеке. Только для тестового стенда:
на живом сервере пароли меняют в панели (свой — кнопка 🔑, чужой —
владелец в разделе «Сотрудники»). После смены пароля в .env не забудь:
он действует только при ПЕРВОМ создании учётки.
"""
import hashlib
import secrets
import sqlite3
import subprocess
import sys
from pathlib import Path
def hash_password(password: str) -> str:
# тот же формат, что storage.hash_password: pbkdf2_sha256$iter$salt$hex
salt = secrets.token_hex(16)
digest = hashlib.pbkdf2_hmac("sha256", password.encode(), bytes.fromhex(salt), 200_000)
return f"pbkdf2_sha256$200000${salt}${digest.hex()}"
def main() -> None:
if len(sys.argv) != 2 or len(sys.argv[1]) < 8:
print("Использование: python set_all_passwords.py <пароль-минимум-8-символов>")
sys.exit(2)
password = sys.argv[1]
new_hash = hash_password(password)
# 1) dev-база SQLite рядом со скриптом
sqlite_path = Path(__file__).resolve().parent / "data" / "crm.db"
if sqlite_path.exists():
with sqlite3.connect(sqlite_path) as conn:
cur = conn.execute(
"UPDATE crm_users SET password_hash = ? WHERE NOT deleted", (new_hash,)
)
print(f"SQLite ({sqlite_path.name}): пароль изменён у {cur.rowcount} учёток")
else:
print(f"SQLite не найдена ({sqlite_path}) — пропускаю")
# 2) PostgreSQL в docker-стеке (контейнер neon-db)
sql = f"UPDATE crm_users SET password_hash = '{new_hash}' WHERE NOT deleted;"
try:
proc = subprocess.run(
["docker", "exec", "neon-db", "psql", "-U", "neon", "-d", "neon_crm", "-c", sql],
capture_output=True, text=True, timeout=30,
)
except (FileNotFoundError, subprocess.TimeoutExpired):
print("docker или контейнер neon-db недоступен — postgres-базу не трогал")
return
if proc.returncode == 0:
print("PostgreSQL (neon-db): пароль изменён у всех действующих учёток")
else:
print(f"postgres UPDATE не прошёл:\n{proc.stderr.strip()}")
if __name__ == "__main__":
main()