Login finalizado, admin funcionando corretamente e sendo gerado oQRcode na raiz do projeto
This commit is contained in:
105
app.py
105
app.py
@@ -1,4 +1,4 @@
|
||||
from flask import Flask, request, render_template, redirect, url_for, flash, session
|
||||
from flask import Flask, request, render_template, redirect, url_for, flash, session, jsonify
|
||||
from functions.database import (
|
||||
Base,
|
||||
Militante,
|
||||
@@ -17,12 +17,14 @@ from functions.database import (
|
||||
)
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from flask_bootstrap import Bootstrap5
|
||||
from routes.cota import cota_bp
|
||||
from functions.validations import validar_cpf
|
||||
from functools import wraps
|
||||
from pathlib import Path
|
||||
from time import time
|
||||
from create_admin import generate_qr_code
|
||||
|
||||
app = Flask(__name__)
|
||||
app.secret_key = 'sua_chave_secreta_aqui' # Necessário para sessões do Flask
|
||||
@@ -41,6 +43,39 @@ def login_required(f):
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
# Decorator para verificar se a sessão expirou
|
||||
def session_timeout(f):
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if 'user_id' not in session:
|
||||
return redirect(url_for('login'))
|
||||
|
||||
# Verificar se existe timestamp do último acesso
|
||||
if 'last_activity' in session:
|
||||
last_activity = datetime.fromtimestamp(session['last_activity'])
|
||||
now = datetime.now()
|
||||
|
||||
# Se passaram mais de 2 horas
|
||||
if now - last_activity > timedelta(hours=2):
|
||||
# Registrar o logout por timeout
|
||||
try:
|
||||
user = db_session.query(Usuario).get(session['user_id'])
|
||||
if user:
|
||||
user.ultimo_logout = datetime.now()
|
||||
user.motivo_logout = "Timeout de sessão"
|
||||
db_session.commit()
|
||||
except Exception as e:
|
||||
print(f"Erro ao registrar logout por timeout: {e}")
|
||||
|
||||
session.clear()
|
||||
flash('Sua sessão expirou. Por favor, faça login novamente.', 'warning')
|
||||
return redirect(url_for('login'))
|
||||
|
||||
# Atualizar timestamp de último acesso
|
||||
session['last_activity'] = time()
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
# Rota raiz - redireciona para login se não estiver autenticado
|
||||
@app.route("/")
|
||||
def index():
|
||||
@@ -85,6 +120,12 @@ def login():
|
||||
print(f"Login bem sucedido para o usuário '{username}'")
|
||||
session['user_id'] = user.id
|
||||
session['is_admin'] = user.is_admin
|
||||
session['last_activity'] = time() # Inicializar timestamp
|
||||
|
||||
# Registrar horário do login
|
||||
user.ultimo_login = datetime.now()
|
||||
db_session.commit()
|
||||
|
||||
next_page = request.args.get('next')
|
||||
flash('Login realizado com sucesso!', 'success')
|
||||
return redirect(next_page or url_for('home'))
|
||||
@@ -101,6 +142,7 @@ def logout():
|
||||
# Rota home (protegida)
|
||||
@app.route("/home")
|
||||
@login_required
|
||||
@session_timeout
|
||||
def home():
|
||||
"""Página inicial do sistema"""
|
||||
try:
|
||||
@@ -137,6 +179,7 @@ def home():
|
||||
# Rota para criar um novo militante
|
||||
@app.route("/militantes/novo", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@session_timeout
|
||||
def novo_militante():
|
||||
if request.method == "POST":
|
||||
cpf = request.form["cpf"]
|
||||
@@ -172,6 +215,7 @@ def novo_militante():
|
||||
# Rota para listar militantes
|
||||
@app.route("/militantes")
|
||||
@login_required
|
||||
@session_timeout
|
||||
def listar_militantes():
|
||||
militantes = db_session.query(Militante).all()
|
||||
return render_template("listar_militantes.html", militantes=militantes)
|
||||
@@ -179,6 +223,7 @@ def listar_militantes():
|
||||
# Rota para criar uma nova cota mensal
|
||||
@app.route("/cotas/novo", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@session_timeout
|
||||
def nova_cota():
|
||||
if request.method == "POST":
|
||||
cotas_mensais = CotaMensal(
|
||||
@@ -203,6 +248,7 @@ def nova_cota():
|
||||
# Rota para listar cotas mensais
|
||||
@app.route("/cotas")
|
||||
@login_required
|
||||
@session_timeout
|
||||
def listar_cotas():
|
||||
cotas = db_session.query(CotaMensal).all()
|
||||
return render_template("listar_cotas.html", cotas=cotas)
|
||||
@@ -210,6 +256,7 @@ def listar_cotas():
|
||||
# Rota para criar um novo pagamento
|
||||
@app.route("/pagamentos/novo", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@session_timeout
|
||||
def novo_pagamento():
|
||||
if request.method == "POST":
|
||||
pagamentos = Pagamento(
|
||||
@@ -234,6 +281,7 @@ def novo_pagamento():
|
||||
# Rota para listar pagamentos
|
||||
@app.route("/pagamentos")
|
||||
@login_required
|
||||
@session_timeout
|
||||
def listar_pagamentos():
|
||||
pagamentos = db_session.query(Pagamento).all()
|
||||
return render_template("listar_pagamentos.html", pagamentos=pagamentos)
|
||||
@@ -241,6 +289,7 @@ def listar_pagamentos():
|
||||
# Rota para criar um novo material vendido
|
||||
@app.route("/materiais/novo", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@session_timeout
|
||||
def novo_material():
|
||||
if request.method == "POST":
|
||||
materiais_vendidos = MaterialVendido(
|
||||
@@ -266,6 +315,7 @@ def novo_material():
|
||||
# Rota para listar materiais vendidos
|
||||
@app.route("/materiais")
|
||||
@login_required
|
||||
@session_timeout
|
||||
def listar_materiais():
|
||||
materiais = db_session.query(MaterialVendido).all()
|
||||
return render_template("listar_materiais.html", materiais=materiais)
|
||||
@@ -273,6 +323,7 @@ def listar_materiais():
|
||||
# Rota para criar uma nova venda de jornais avulsos
|
||||
@app.route("/jornais/novo", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@session_timeout
|
||||
def nova_venda_jornal():
|
||||
if request.method == "POST":
|
||||
vendas_jornais_avulsos = VendaJornalAvulso(
|
||||
@@ -297,6 +348,7 @@ def nova_venda_jornal():
|
||||
# Rota para listar vendas de jornais avulsos
|
||||
@app.route("/jornais")
|
||||
@login_required
|
||||
@session_timeout
|
||||
def listar_vendas_jornal():
|
||||
vendas = db_session.query(VendaJornalAvulso).all()
|
||||
return render_template("listar_vendas_jornal.html", vendas=vendas)
|
||||
@@ -304,6 +356,7 @@ def listar_vendas_jornal():
|
||||
# Rota para criar uma nova assinatura anual
|
||||
@app.route("/assinaturas/novo", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@session_timeout
|
||||
def nova_assinatura():
|
||||
if request.method == "POST":
|
||||
assinaturas_anuais = AssinaturaAnual(
|
||||
@@ -330,6 +383,7 @@ def nova_assinatura():
|
||||
# Rota para listar assinaturas anuais
|
||||
@app.route("/assinaturas")
|
||||
@login_required
|
||||
@session_timeout
|
||||
def listar_assinaturas():
|
||||
assinaturas = db_session.query(AssinaturaAnual).all()
|
||||
return render_template("listar_assinaturas.html", assinaturas=assinaturas)
|
||||
@@ -337,6 +391,7 @@ def listar_assinaturas():
|
||||
# Rota para criar um novo relatório de cotas mensais
|
||||
@app.route("/relatorios/cotas/novo", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@session_timeout
|
||||
def novo_relatorio_cotas():
|
||||
if request.method == "POST":
|
||||
relatorio_cotas_mensais = RelatorioCotasMensais(
|
||||
@@ -361,6 +416,7 @@ def novo_relatorio_cotas():
|
||||
# Rota para listar relatórios de cotas mensais
|
||||
@app.route("/relatorios/cotas")
|
||||
@login_required
|
||||
@session_timeout
|
||||
def listar_relatorios_cotas():
|
||||
relatorios = db_session.query(RelatorioCotasMensais).all()
|
||||
return render_template("listar_relatorios_cotas.html", relatorios=relatorios)
|
||||
@@ -368,6 +424,7 @@ def listar_relatorios_cotas():
|
||||
# Rota para criar um novo relatório de vendas de materiais
|
||||
@app.route("/relatorios/vendas/novo", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@session_timeout
|
||||
def novo_relatorio_vendas():
|
||||
if request.method == "POST":
|
||||
relatorio_vendas_materiais = RelatorioVendasMateriais(
|
||||
@@ -392,12 +449,14 @@ def novo_relatorio_vendas():
|
||||
# Rota para listar relatórios de vendas de materiais
|
||||
@app.route("/relatorios/vendas")
|
||||
@login_required
|
||||
@session_timeout
|
||||
def listar_relatorios_vendas():
|
||||
relatorios = db_session.query(RelatorioVendasMateriais).all()
|
||||
return render_template("listar_relatorios_vendas.html", relatorios=relatorios)
|
||||
|
||||
@app.route("/militantes/editar/<int:id>", methods=["GET", "POST"])
|
||||
@login_required
|
||||
@session_timeout
|
||||
def editar_militante(id):
|
||||
militante = db_session.query(Militante).get(id)
|
||||
if not militante:
|
||||
@@ -469,17 +528,11 @@ def novo_usuario():
|
||||
db_session.add(novo_usuario)
|
||||
db_session.commit()
|
||||
|
||||
# Gerar QR code para configuração do OTP
|
||||
# Gerar QR code usando a função do create_admin.py
|
||||
qr_uri = novo_usuario.get_otp_uri()
|
||||
qr_path = generate_qr_code(novo_usuario)
|
||||
|
||||
flash('Usuário criado com sucesso!', 'success')
|
||||
|
||||
# Modificação alternativa para salvar no diretório atual
|
||||
qr_path = Path('admin_qr.png')
|
||||
img = qrcode.QRCode(version=1, box_size=10, border=5)
|
||||
img.add_data(qr_uri)
|
||||
img.make(fit=True)
|
||||
img.save(str(qr_path))
|
||||
|
||||
return render_template('mostrar_qr_code.html', qr_uri=qr_uri)
|
||||
|
||||
except Exception as e:
|
||||
@@ -490,6 +543,30 @@ def novo_usuario():
|
||||
|
||||
return render_template('novo_usuario.html')
|
||||
|
||||
@app.route('/check_session')
|
||||
def check_session():
|
||||
if 'last_activity' not in session:
|
||||
return jsonify({'expired': True})
|
||||
|
||||
last_activity = datetime.fromtimestamp(session['last_activity'])
|
||||
now = datetime.now()
|
||||
|
||||
if now - last_activity > timedelta(hours=2):
|
||||
# Registrar o logout por timeout
|
||||
try:
|
||||
user = db_session.query(Usuario).get(session.get('user_id'))
|
||||
if user:
|
||||
user.ultimo_logout = datetime.now()
|
||||
user.motivo_logout = "Timeout de sessão"
|
||||
db_session.commit()
|
||||
except Exception as e:
|
||||
print(f"Erro ao registrar logout por timeout: {e}")
|
||||
|
||||
session.clear()
|
||||
return jsonify({'expired': True})
|
||||
|
||||
return jsonify({'expired': False})
|
||||
|
||||
def create_app():
|
||||
app = Flask(__name__)
|
||||
# ... existing code ...
|
||||
@@ -501,4 +578,10 @@ def create_app():
|
||||
|
||||
# Iniciar o servidor Flask
|
||||
if __name__ == "__main__":
|
||||
# Verificar se existe usuário admin e gerar QR code
|
||||
admin = db_session.query(Usuario).filter_by(username="admin").first()
|
||||
if admin:
|
||||
print("\n=== Gerando QR Code para usuário admin existente ===")
|
||||
generate_qr_code(admin)
|
||||
|
||||
app.run(debug=True)
|
||||
|
||||
Reference in New Issue
Block a user