teste rota /mmpSearch/api/
Deploy / Deploy (push) Successful in 3m12s
Details
Deploy / Deploy (push) Successful in 3m12s
Details
This commit is contained in:
parent
87f18a86ac
commit
d831fd2c57
Binary file not shown.
|
|
@ -302,7 +302,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
try {
|
try {
|
||||||
console.log("Verificando autenticação...");
|
console.log("Verificando autenticação...");
|
||||||
// Verifica auth via Proxy Apache
|
// 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();
|
const authData = await res.json();
|
||||||
|
|
||||||
console.log("Status do usuário:", authData);
|
console.log("Status do usuário:", authData);
|
||||||
|
|
@ -715,7 +715,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// URL CORRIGIDA: Usando Proxy reverso (sem porta 33002)
|
// URL CORRIGIDA: Usando Proxy reverso (sem porta 33002)
|
||||||
const API_URL = '/api/upload/sample';
|
const API_URL = '/mmpSearch/api/upload/sample';
|
||||||
|
|
||||||
// UI Loading
|
// UI Loading
|
||||||
confirmUploadBtn.classList.add('is-loading');
|
confirmUploadBtn.classList.add('is-loading');
|
||||||
|
|
|
||||||
|
|
@ -13,21 +13,23 @@ from flask import Flask, request, jsonify, send_file
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
|
|
||||||
# --- NOVAS IMPORTAÇÕES DE AUTH ---
|
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_bcrypt import Bcrypt
|
from flask_bcrypt import Bcrypt
|
||||||
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
|
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 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__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
# --- CONFIGURAÇÃO DE SEGURANÇA E BANCO ---
|
# --- CONFIGURAÇÃO DE SEGURANÇA E BANCO ---
|
||||||
# IMPORTANTE: Troque esta chave em produção!
|
# 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)
|
# 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
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
|
||||||
# CORS precisa suportar credenciais para o cookie de login funcionar
|
# 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)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
username = db.Column(db.String(150), unique=True, nullable=False)
|
username = db.Column(db.String(150), unique=True, nullable=False)
|
||||||
password = db.Column(db.String(150), 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
|
# Cria o banco na inicialização se não existir
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
|
|
@ -223,7 +243,7 @@ def process_and_build(filename):
|
||||||
# ROTAS DE AUTENTICAÇÃO
|
# ROTAS DE AUTENTICAÇÃO
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
@app.route('/api/register', methods=['POST'])
|
@app.route('/mmpSearch/api/register', methods=['POST'])
|
||||||
def register():
|
def register():
|
||||||
data = request.json
|
data = request.json
|
||||||
if not data or not data.get('username') or not data.get('password'):
|
if not data or not data.get('username') or not data.get('password'):
|
||||||
|
|
@ -239,7 +259,7 @@ def register():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({"message": f"Erro: {str(e)}"}), 500
|
return jsonify({"message": f"Erro: {str(e)}"}), 500
|
||||||
|
|
||||||
@app.route('/api/login', methods=['POST'])
|
@app.route('/mmpSearch/api/login', methods=['POST'])
|
||||||
def login():
|
def login():
|
||||||
data = request.json
|
data = request.json
|
||||||
user = User.query.filter_by(username=data['username']).first()
|
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": "Login realizado", "user": user.username}), 200
|
||||||
return jsonify({"message": "Credenciais inválidas"}), 401
|
return jsonify({"message": "Credenciais inválidas"}), 401
|
||||||
|
|
||||||
@app.route('/api/logout', methods=['POST'])
|
@app.route('/mmpSearch/api/logout', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def logout():
|
def logout():
|
||||||
logout_user()
|
logout_user()
|
||||||
return jsonify({"message": "Logout realizado"}), 200
|
return jsonify({"message": "Logout realizado"}), 200
|
||||||
|
|
||||||
@app.route('/api/check_auth', methods=['GET'])
|
@app.route('/mmpSearch/api/check_auth', methods=['GET'])
|
||||||
def check_auth():
|
def check_auth():
|
||||||
if current_user.is_authenticated:
|
if current_user.is_authenticated:
|
||||||
return jsonify({"logged_in": True, "user": current_user.username})
|
return jsonify({"logged_in": True, "user": current_user.username})
|
||||||
|
|
@ -264,7 +284,7 @@ def check_auth():
|
||||||
# ROTAS PRINCIPAIS
|
# 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):
|
def download_project_package(project_name):
|
||||||
"""Gera um ZIP com caminhos limpos (Não exige login para baixar)."""
|
"""Gera um ZIP com caminhos limpos (Não exige login para baixar)."""
|
||||||
if not project_name.lower().endswith('.mmp'):
|
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
|
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
|
@login_required # <--- PROTEGIDO
|
||||||
def upload_file():
|
def upload_file():
|
||||||
if "project_file" not in request.files:
|
if "project_file" not in request.files:
|
||||||
|
|
@ -367,7 +387,7 @@ def upload_file():
|
||||||
return jsonify({"error": "Tipo de arquivo não permitido"}), 400
|
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
|
@login_required # <--- PROTEGIDO
|
||||||
def resolve_samples():
|
def resolve_samples():
|
||||||
project_filename = request.form.get('project_file')
|
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
|
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
|
@login_required # <--- PROTEGIDO
|
||||||
def upload_sample_standalone():
|
def upload_sample_standalone():
|
||||||
if 'sample_file' not in request.files: return jsonify({'error': 'Nenhum arquivo'}), 400
|
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({'message': 'Sample enviado!'}), 200
|
||||||
return jsonify({'error': 'Erro no arquivo'}), 400
|
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__":
|
if __name__ == "__main__":
|
||||||
# Se estiver rodando atrás do Apache, NÃO use ssl_context.
|
# DEBUG: Isso vai mostrar no log todas as rotas que o Flask reconheceu
|
||||||
# O Apache já cuida do SSL (https://alice.ufsj.edu.br).
|
print(app.url_map)
|
||||||
# O Flask deve rodar em HTTP puro localmente.
|
|
||||||
|
|
||||||
print("Iniciando servidor na porta 33002 (HTTP Mode)...")
|
print("Iniciando servidor na porta 33002 (HTTP Mode)...")
|
||||||
app.run(host="0.0.0.0", port=33002, debug=True)
|
app.run(host="0.0.0.0", port=33002, debug=True)
|
||||||
|
|
||||||
# Removi o ssl_context=context para facilitar o proxy reverso
|
|
||||||
Loading…
Reference in New Issue