- padronizando o nome de get_db_connection e session para get_db_session, para não confundir com session do Flask ou sessoes web
- corrigindo potenciais erros
-- has_permission nao consegue com lazy load carregar permission depois de load_user fechar a conexao, entao joinedLoad com Permission antes de fechar
-- db.rollback não existe caso db = get_db_session() apareça muito depois dentro do try, padronizando antes de try
--- comparar role por nivel (Role.SECRETARIO_GERAL) e nao por nome ("Secretario Geral")
- unificacao de get_otp_qr_code
- mudança de nowutc() para now(UTC) conforme novo padrão
199 lines
6.3 KiB
Python
199 lines
6.3 KiB
Python
import os
|
|
import pyotp
|
|
from pathlib import Path
|
|
from functions.database import Usuario, Role, get_db_session
|
|
from services.otp_service import generate_qr_code
|
|
|
|
ADMIN_USERNAME = "admin"
|
|
ADMIN_PASSWORD = "admin123"
|
|
ADMIN_ROLE = Role.SECRETARIO_GERAL
|
|
|
|
|
|
def salvar_qr_code(user):
|
|
"""
|
|
Gera o QR code para um usuário específico
|
|
|
|
Args:
|
|
user: Instância do modelo Usuario
|
|
|
|
Returns:
|
|
tuple: (caminho do arquivo, URI do OTP)
|
|
"""
|
|
# Tentar diferentes caminhos para salvar o QR code
|
|
qr_paths = [
|
|
Path('/tmp/admin_qr.png'), # Diretório temporário do sistema
|
|
Path('/data/admin_qr.png'), # Diretório de dados do container
|
|
Path('admin_qr.png') # Diretório atual (fallback fora do container)
|
|
]
|
|
|
|
# Tentar salvar em diferentes locais
|
|
qr_saved = False
|
|
saved_path = None
|
|
|
|
img = generate_qr_code(user) # Gera o QR code para o usuário
|
|
|
|
for qr_path in qr_paths:
|
|
try:
|
|
# Tentar salvar o arquivo
|
|
img.save(qr_path)
|
|
qr_saved = True
|
|
saved_path = qr_path
|
|
break
|
|
except Exception as e:
|
|
print(f"Não foi possível salvar o QR code em {qr_path}: {e}")
|
|
continue
|
|
|
|
if not qr_saved:
|
|
print("AVISO: Não foi possível salvar o QR code em nenhum local")
|
|
print("O QR code pode ser gerado manualmente usando o URI OTP")
|
|
saved_path = None
|
|
|
|
return saved_path
|
|
|
|
|
|
def _ensure_admin_role(db, admin_user, role):
|
|
admin_role = db.query(Role).filter_by(nome=role).first()
|
|
if admin_role is None:
|
|
admin_role = Role(nome=role, nivel=Role.SECRETARIO_GERAL)
|
|
db.add(admin_role)
|
|
db.flush()
|
|
|
|
if admin_role not in admin_user.roles:
|
|
admin_user.roles.append(admin_role)
|
|
db.flush()
|
|
|
|
|
|
def _ensure_admin_otp(db, admin_user):
|
|
if admin_user.otp_secret:
|
|
return False
|
|
secret = (os.environ.get('ADMIN_OTP_SECRET') or "").strip()
|
|
admin_user.otp_secret = secret or admin_user.generate_otp_secret()
|
|
db.flush()
|
|
return True
|
|
|
|
|
|
def create_admin(username=ADMIN_USERNAME, password=ADMIN_PASSWORD, role=ADMIN_ROLE, save_qr=True):
|
|
"""Limpa e cria o usuário admin"""
|
|
db = get_db_session()
|
|
try:
|
|
# Verificar se já existe um usuário admin
|
|
admin_user = db.query(Usuario).filter_by(username=username).first()
|
|
if admin_user is not None:
|
|
db.delete(admin_user)
|
|
db.flush()
|
|
|
|
print("\n=== Criando Novo Usuário Admin ===")
|
|
admin_user = Usuario(
|
|
username=username,
|
|
email="admin@example.com",
|
|
is_admin=True
|
|
)
|
|
admin_user.set_password(password)
|
|
_ensure_admin_otp(db, admin_user)
|
|
_ensure_admin_role(db, admin_user, role)
|
|
|
|
db.add(admin_user)
|
|
db.commit()
|
|
|
|
qr_path = salvar_qr_code(admin_user)
|
|
|
|
# Mostrar informações
|
|
print("\n=== Informações do Admin ===")
|
|
print(f"Username: {admin_user.username}")
|
|
print(f"Email: {admin_user.email}")
|
|
print(f"Senha: {password}")
|
|
print(f"Segredo OTP: {admin_user.otp_secret}")
|
|
print(f"URI do OTP: {admin_user.get_otp_uri()}")
|
|
if qr_path:
|
|
print(f"QR Code salvo em: {qr_path}")
|
|
else:
|
|
print("QR Code não foi salvo. Use o URI do OTP ou o Segredo OTP para configuração manual.")
|
|
|
|
print("\n=== Instruções para Configuração ===")
|
|
print("1. Instale um aplicativo autenticador no seu celular")
|
|
print(" (Google Authenticator, Microsoft Authenticator, etc)")
|
|
print("2. Abra o aplicativo")
|
|
print("3. Selecione a opção para adicionar uma nova conta")
|
|
if qr_path:
|
|
print("4. Escaneie o QR Code salvo em:", qr_path)
|
|
print("\nOU configure manualmente:")
|
|
print(f"- Nome da conta: {admin_user.username}")
|
|
print(f"- Segredo OTP: {admin_user.otp_secret}")
|
|
print("- Tipo: Baseado em tempo (TOTP)")
|
|
print("- Algoritmo: SHA1")
|
|
print("- Dígitos: 6")
|
|
print("- Intervalo: 30 segundos")
|
|
|
|
# Gerar código atual para verificação
|
|
totp = pyotp.TOTP(admin_user.otp_secret)
|
|
current_code = totp.now()
|
|
print("\n=== Verificação do OTP ===")
|
|
print(f"Código OTP atual: {current_code}")
|
|
is_valid = admin_user.verify_otp(current_code)
|
|
print(f"Verificação do código: {'Sucesso' if is_valid else 'Falha'}")
|
|
|
|
if not is_valid:
|
|
print("\nALERTA: Verificação do OTP falhou!")
|
|
print("Por favor, verifique se o segredo OTP está correto.")
|
|
|
|
# Fazer commit final para garantir que tudo foi salvo
|
|
db.commit()
|
|
|
|
except Exception as e:
|
|
db.rollback()
|
|
raise e
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
def verify_admin(username=ADMIN_USERNAME, role=ADMIN_ROLE, save_qr=False):
|
|
"""Verifica se o usuário admin existe e tem OTP configurado"""
|
|
db = get_db_session()
|
|
try:
|
|
admin_user = db.query(Usuario).filter_by(username=username).first()
|
|
if admin_user is not None:
|
|
print("\n=== Usuário Admin Encontrado ===")
|
|
_ensure_admin_otp(db, admin_user)
|
|
_ensure_admin_role(db, admin_user, role)
|
|
return True
|
|
else:
|
|
print("\n=== Usuário Admin NÃO Encontrado ===")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"Erro ao verificar o usuário admin: {e}")
|
|
raise
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
def rotate_admin_otp(username=ADMIN_USERNAME, save_qr=False):
|
|
db = get_db_session()
|
|
try:
|
|
admin_user = db.query(Usuario).filter_by(username=username).first()
|
|
if admin_user is None:
|
|
print("Usuário admin não encontrado")
|
|
return False
|
|
|
|
admin_user.generate_otp_secret()
|
|
db.commit()
|
|
print(f"OTP do usuário '{username}' foi rotacionado.")
|
|
print(f"Novo segredo OTP: {admin_user.otp_secret}")
|
|
|
|
if save_qr:
|
|
qr_path = salvar_qr_code(admin_user)
|
|
if qr_path:
|
|
print(f"Novo QR code salvo em: {qr_path}")
|
|
else:
|
|
print("Não foi possível salvar o QR code automaticamente.")
|
|
|
|
except Exception:
|
|
db.rollback()
|
|
raise
|
|
finally:
|
|
db.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
create_admin()
|