from flask import Flask, request, jsonify, send_from_directory from flask_mysqldb import MySQL import ldap3 import re import os from dotenv import load_dotenv import jwt # Importa a biblioteca JWT para gerar e validar tokens from datetime import datetime, timedelta from ldap3.core.exceptions import LDAPSocketOpenError, LDAPException # Importa as exceções específicas de ldap3 from flask_cors import CORS from flask_wtf.csrf import CSRFProtect # Importa CSRFProtect para proteção CSRF from flask_talisman import Talisman # Carregar variáveis de ambiente do arquivo .env load_dotenv() app = Flask(__name__) # Configuração de cookies seguros app.config['SESSION_COOKIE_SECURE'] = True # Cookies serão enviados apenas em conexões HTTPS app.config['SESSION_COOKIE_HTTPONLY'] = True # Cookies não estarão acessíveis via JavaScript Talisman(app) # Configuração da chave secreta necessária para CSRF e JWT app.config['SECRET_KEY'] = os.getenv('JWT_SECRET') or 'sua_chave_secreta' # Defina uma chave secreta segura # Inicializa a proteção CSRF csrf = CSRFProtect(app) # Permitir apenas uma origem específica CORS(app, resources={r"/*": {"origins": "https://dev.itguys.com.br"}}) # Configuração do MySQL usando variáveis de ambiente app.config['MYSQL_HOST'] = os.getenv('MYSQL_HOST') app.config['MYSQL_USER'] = os.getenv('MYSQL_USER') app.config['MYSQL_PASSWORD'] = os.getenv('MYSQL_PASSWORD') app.config['MYSQL_DB'] = os.getenv('MYSQL_DB') #Configuração do SMTP usando variáveis de ambiente app.config['SMTP_USERNAME'] = os.getenv('SMTP_USERNAME') app.config['SMTP_HOST'] = os.getenv('SMTP_HOST') app.config['SMTP_PASSWORD'] = os.getenv('SMTP_PASSWORD') app.config['SMTP_PORT'] = os.getenv('SMTP_PORT') app.config['SMTP_RECIPIENT'] = os.getenv('SMTP_RECIPIENT') mysql = MySQL(app) def recebe_smtp_variaveis_env(): return { 'SMTP_USERNAME': app.config['SMTP_USERNAME'], 'SMTP_HOST': app.config['SMTP_HOST'], 'SMTP_PASSWORD': app.config['SMTP_PASSWORD'], 'SMTP_PORT': app.config['SMTP_PORT'], 'SMTP_RECIPIENT': app.config['SMTP_RECIPIENT'] } @app.route('/envio-smtp', methods=['GET']) def envio_smtp(): smtp_variaveis_env = recebe_smtp_variaveis_env() return jsonify(smtp_variaveis_env) @app.route('/login', methods=['POST']) @csrf.exempt # Endpoints de autenticação como este podem ser excluídos da proteção CSRF, pois o token CSRF não está disponível antes do login; remova este decorador se quiser aplicar proteção CSRF. def login(): data = request.get_json() username_full = data.get('username') # Extrai o e-mail completo do usuário dos dados da requisição. password = data.get('password') # Extrai a senha dos dados da requisição. # Validação do formato do e-mail if not re.match(r"[^@]+@[^@]+\.[^@]+", username_full): return jsonify({'msg': 'Formato de e-mail inválido'}), 400 # Extrair o nome de usuário (parte antes do @) username = username_full.split('@')[0] # Separar o domínio domain = username_full.split('@')[1] # Verificar se o domínio existe na tabela empresa cur = mysql.connection.cursor() cur.execute("SELECT idempresa, ip_dominio FROM empresa WHERE dominio = %s", (domain,)) empresa_result = cur.fetchone() if empresa_result is None: # Verifica se o domínio não existe na tabela empresa. cur.close() return jsonify({'msg': 'Domínio não encontrado no banco de dados'}), 404 id_empresa, ip_dominio = empresa_result # Armazena o ID da empresa e o IP do domínio encontrados no banco de dados. # Verificar se o usuário está associado à empresa no MySQL usando a view cur.execute("SELECT empresa_id, dominio_empresa FROM view_usuario_empresa WHERE usuario = %s AND dominio_empresa = %s", (username, domain)) result = cur.fetchone() cur.close() if result is None: # Verifica se o usuário não está associado à empresa. return jsonify({'msg': 'Usuário não associado à empresa'}), 404 empresa_id, dominio_empresa = result # Conectar ao servidor LDAP correspondente e autenticar o usuário ldap_server = f'ldap://{ip_dominio}:389' try: # Configurar o servidor LDAP server = ldap3.Server(ldap_server) # Tentar criar a conexão conn = ldap3.Connection(server, user=username_full, password=password) # Tentar autenticar o usuário if conn.bind(): # Gerar o token JWT após autenticação bem-sucedida token = jwt.encode({ 'user': username_full, 'exp': datetime.utcnow() + timedelta(hours=1) # Token expira em 1 hora }, app.config['SECRET_KEY'], algorithm="HS256") return jsonify({'msg': 'Login bem-sucedido', 'token': token}), 200 else: return jsonify({'msg': 'Falha na autenticação LDAP'}), 401 except LDAPSocketOpenError: # Erro específico para problemas de conexão com o servidor LDAP return jsonify({'msg': 'Não foi possível conectar ao servidor LDAP. Verifique a conexão de rede e as configurações do servidor.'}), 503 except LDAPException as e: # Captura qualquer outra exceção LDAP genérica return jsonify({'Erro 500': f'Erro LDAP: {str(e)}'}), 500 # Decorador para proteger rotas com JWT def token_required(f): def wrapper(*args, **kwargs): token = request.headers.get('x-access-token') if not token: return jsonify({'msg': 'Token é necessário!'}), 401 try: # Decodifica o token para validar data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"]) except jwt.ExpiredSignatureError: # O token expirou return jsonify({'msg': 'Token expirado! Por favor, faça login novamente.'}), 401 except jwt.InvalidTokenError: # Token inválido por qualquer outro motivo return jsonify({'msg': 'Token inválido!'}), 401 return f(*args, **kwargs) return wrapper @app.route('/mounting', methods=['GET']) @token_required # Garante que o usuário esteja autenticado e o token JWT seja validado def mounting(): # Decodifica o token para obter o e-mail do usuário token = request.headers.get('x-access-token') data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"]) username_full = data['user'] # Extrair o domínio do email do usuário autenticado domain = username_full.split('@')[1] if not username_full: return jsonify({'msg': 'Token inválido!'}), 401 # Consultar o banco de dados para obter o nome da empresa com base no domínio cur = mysql.connection.cursor() cur.execute("SELECT nome FROM empresa WHERE dominio = %s", (domain,)) empresa_result = cur.fetchone() cur.close() if empresa_result is None: return jsonify({'msg': 'Empresa não encontrada no banco de dados para o domínio fornecido'}), 404 # Obtém o nome da empresa nome_empresa = empresa_result[0] # Definir o caminho do diretório onde os arquivos JSON estão armazenados json_directory = './json/' # Substitua pelo caminho real do diretório # Nome do arquivo JSON correspondente ao nome da empresa json_filename = f"{nome_empresa}.json" # Caminho completo para o arquivo JSON json_filepath = os.path.join(json_directory, json_filename) # Verificar se o arquivo JSON existe if not os.path.isfile(json_filepath): return jsonify({'msg': 'Arquivo JSON não encontrado para a empresa fornecida'}), 404 # Retornar o conteúdo do arquivo JSON return send_from_directory(json_directory, json_filename, as_attachment=False) if __name__ == '__main__': app.run(host="0.0.0.0", port=5000, ssl_context=('./fullchain1.pem','./privkey1.pem'))