63 lines
2.7 KiB
Python
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()
|