teste rota /mmpSearch/api/
Deploy / Deploy (push) Successful in 3m12s Details

This commit is contained in:
JotaChina 2025-12-09 20:58:50 -03:00
parent 87f18a86ac
commit d831fd2c57
3 changed files with 47 additions and 20 deletions

Binary file not shown.

View File

@ -302,7 +302,7 @@ document.addEventListener('DOMContentLoaded', async () => {
try {
console.log("Verificando autenticação...");
// Verifica auth via Proxy Apache
const res = await fetch('/api/check_auth');
const res = await fetch('/mmpSearch/api/check_auth');
const authData = await res.json();
console.log("Status do usuário:", authData);
@ -715,7 +715,7 @@ document.addEventListener('DOMContentLoaded', async () => {
}
// URL CORRIGIDA: Usando Proxy reverso (sem porta 33002)
const API_URL = '/api/upload/sample';
const API_URL = '/mmpSearch/api/upload/sample';
// UI Loading
confirmUploadBtn.classList.add('is-loading');

View File

@ -13,21 +13,23 @@ from flask import Flask, request, jsonify, send_file
from flask_cors import CORS
from werkzeug.utils import secure_filename
# --- NOVAS IMPORTAÇÕES DE AUTH ---
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_admin import Admin, AdminIndexView, expose
from flask_admin.contrib.sqla import ModelView
from main import process_single_file, rebuild_indexes, generate_manifests, slugify
from utils import ALLOWED_EXTENSIONS, ALLOWED_SAMPLE_EXTENSIONS, MMP_FOLDER, MMPZ_FOLDER, CERT_PATH, KEY_PATH, BASE_DATA, SRC_MMPSEARCH, SAMPLE_SRC, METADATA_FOLDER, XML_IMPORTED_PATH_PREFIX, SAMPLE_MANIFEST
from utils import ALLOWED_EXTENSIONS, ALLOWED_SAMPLE_EXTENSIONS, MMP_FOLDER, MMPZ_FOLDER, DATA_FOLDER, CERT_PATH, KEY_PATH, BASE_DATA, SRC_MMPSEARCH, SAMPLE_SRC, METADATA_FOLDER, XML_IMPORTED_PATH_PREFIX, SAMPLE_MANIFEST
app = Flask(__name__)
# --- CONFIGURAÇÃO DE SEGURANÇA E BANCO ---
# IMPORTANTE: Troque esta chave em produção!
app.config['SECRET_KEY'] = 'chave_secreta_super_segura_mmp_ecosystem_2025'
app.config['SECRET_KEY'] = '25de5592bf94c2ca18e27baa0ae2d4ee22a63012f32e1be719d31f530c215a387b9ec0c9d96be38e80a7ccdd859e04408facefff8fd9119e7f5a2d987d85abb7'
# O banco ficará salvo em /nethome/jotachina/projetos/mmpSearch/users.db (BASE_DATA)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(BASE_DATA, 'users.db')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(DATA_FOLDER, 'users.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# CORS precisa suportar credenciais para o cookie de login funcionar
@ -43,6 +45,24 @@ class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(150), unique=True, nullable=False)
password = db.Column(db.String(150), nullable=False)
# Novo campo para dizer se é chefe ou não
is_admin = db.Column(db.Boolean, default=False)
class SecureModelView(ModelView):
def is_accessible(self):
return current_user.is_authenticated and current_user.is_admin
def inaccessible_callback(self, name, **kwargs):
# Retorna erro JSON ou redireciona (como é painel, melhor redirecionar ou negar)
return jsonify({"error": "Acesso restrito a administradores."}), 403
# Classe para proteger a Home do Admin (Dashboard)
class SecureIndexView(AdminIndexView):
@expose('/')
def index(self):
if not current_user.is_authenticated or not current_user.is_admin:
return jsonify({"error": "Acesso restrito."}), 403
return super(SecureIndexView, self).index()
# Cria o banco na inicialização se não existir
with app.app_context():
@ -223,7 +243,7 @@ def process_and_build(filename):
# ROTAS DE AUTENTICAÇÃO
# ==============================================================================
@app.route('/api/register', methods=['POST'])
@app.route('/mmpSearch/api/register', methods=['POST'])
def register():
data = request.json
if not data or not data.get('username') or not data.get('password'):
@ -239,7 +259,7 @@ def register():
except Exception as e:
return jsonify({"message": f"Erro: {str(e)}"}), 500
@app.route('/api/login', methods=['POST'])
@app.route('/mmpSearch/api/login', methods=['POST'])
def login():
data = request.json
user = User.query.filter_by(username=data['username']).first()
@ -248,13 +268,13 @@ def login():
return jsonify({"message": "Login realizado", "user": user.username}), 200
return jsonify({"message": "Credenciais inválidas"}), 401
@app.route('/api/logout', methods=['POST'])
@app.route('/mmpSearch/api/logout', methods=['POST'])
@login_required
def logout():
logout_user()
return jsonify({"message": "Logout realizado"}), 200
@app.route('/api/check_auth', methods=['GET'])
@app.route('/mmpSearch/api/check_auth', methods=['GET'])
def check_auth():
if current_user.is_authenticated:
return jsonify({"logged_in": True, "user": current_user.username})
@ -264,7 +284,7 @@ def check_auth():
# ROTAS PRINCIPAIS
# ==============================================================================
@app.route("/api/download/<project_name>", methods=["GET"])
@app.route("/mmpSearch/api/download/<project_name>", methods=["GET"])
def download_project_package(project_name):
"""Gera um ZIP com caminhos limpos (Não exige login para baixar)."""
if not project_name.lower().endswith('.mmp'):
@ -311,7 +331,7 @@ def download_project_package(project_name):
return jsonify({"error": f"Erro ao gerar pacote: {str(e)}"}), 500
@app.route("/api/upload", methods=["POST"])
@app.route("/mmpSearch/api/upload", methods=["POST"])
@login_required # <--- PROTEGIDO
def upload_file():
if "project_file" not in request.files:
@ -367,7 +387,7 @@ def upload_file():
return jsonify({"error": "Tipo de arquivo não permitido"}), 400
@app.route("/api/upload/resolve", methods=["POST"])
@app.route("/mmpSearch/api/upload/resolve", methods=["POST"])
@login_required # <--- PROTEGIDO
def resolve_samples():
project_filename = request.form.get('project_file')
@ -395,7 +415,7 @@ def resolve_samples():
return jsonify({"error": "Falha ao atualizar o arquivo de projeto."}), 500
@app.route('/api/upload/sample', methods=['POST'])
@app.route('/mmpSearch/api/upload/sample', methods=['POST'])
@login_required # <--- PROTEGIDO
def upload_sample_standalone():
if 'sample_file' not in request.files: return jsonify({'error': 'Nenhum arquivo'}), 400
@ -412,12 +432,19 @@ def upload_sample_standalone():
return jsonify({'message': 'Sample enviado!'}), 200
return jsonify({'error': 'Erro no arquivo'}), 400
# Inicializa o Flask-Admin
admin = Admin(
app,
name='MMP Admin',
index_view=SecureIndexView(url='/api/admin')
)
# Adiciona a visualização da tabela de Usuários
admin.add_view(SecureModelView(User, db.session, name="Gerenciar Usuários"))
if __name__ == "__main__":
# Se estiver rodando atrás do Apache, NÃO use ssl_context.
# O Apache já cuida do SSL (https://alice.ufsj.edu.br).
# O Flask deve rodar em HTTP puro localmente.
# DEBUG: Isso vai mostrar no log todas as rotas que o Flask reconheceu
print(app.url_map)
print("Iniciando servidor na porta 33002 (HTTP Mode)...")
app.run(host="0.0.0.0", port=33002, debug=True)
# Removi o ssl_context=context para facilitar o proxy reverso
app.run(host="0.0.0.0", port=33002, debug=True)