Novo Ambiente | Atualização 4
17
.env
|
|
@ -10,6 +10,7 @@ SMTP_PASSWORD=j5j@QaSB\Z4<)W]M|hOYbC\605zfGcv:
|
||||||
SMTP_HOST=mail.itguys.com.br
|
SMTP_HOST=mail.itguys.com.br
|
||||||
SMTP_PORT=465
|
SMTP_PORT=465
|
||||||
SMTP_RECIPIENT=comercial@itguys.com.br
|
SMTP_RECIPIENT=comercial@itguys.com.br
|
||||||
|
|
||||||
# Configurações LDAP (Windows AD)
|
# Configurações LDAP (Windows AD)
|
||||||
LDAP_SERVER=10.10.253.199/itguys.com.br
|
LDAP_SERVER=10.10.253.199/itguys.com.br
|
||||||
LDAP_DOMAIN=itguys.com.br
|
LDAP_DOMAIN=itguys.com.br
|
||||||
|
|
@ -17,7 +18,21 @@ LDAP_BASE_DN=dc=itguys,dc=com,dc=br
|
||||||
LDAP_USER=itguys\teste.dev
|
LDAP_USER=itguys\teste.dev
|
||||||
LDAP_PASSWORD=123Mudar
|
LDAP_PASSWORD=123Mudar
|
||||||
|
|
||||||
ZAMMAD_API=http://10.10.253.59/api/v1/
|
#API ZAMMAD
|
||||||
|
ZAMMAD_API= https://zammad.itguys.com.br/api/v1
|
||||||
ZAMMAD_USERNAME=teste.dev@itguys.com.br
|
ZAMMAD_USERNAME=teste.dev@itguys.com.br
|
||||||
ZAMMAD_PASSWORD=123Mudar
|
ZAMMAD_PASSWORD=123Mudar
|
||||||
|
ZAMMAD_TOKEN =QiFbQ7txT0BS_3N8GrwOzAS6f7ziVTa1VqcGGpaPFscvdcfnBVjgq699fFj6NpQW #Token expira em 2065
|
||||||
|
|
||||||
|
|
||||||
|
#API Inter
|
||||||
|
CLIENT_ID = bfedfb96-7caf-4310-8632-a924c5daa7e1
|
||||||
|
CLIENT_SECRET = 502d577e-b324-4b93-9624-e6b082588dc5
|
||||||
|
CERT_PATH = InterAPI_Certificado.crt
|
||||||
|
CERT_KEY_PATH = keyinter.pem
|
||||||
|
|
||||||
|
#API ZABBIX
|
||||||
|
ZABBIX_URL = https://mimir.itguys.com.br/zabbix/api_jsonrpc.php
|
||||||
|
TOKEN_ZABBIX = 10925e9e452cade5270f4d930feb3b5e1aa2cc9b366c1c5b4d72996212b12c93
|
||||||
|
ZABBIX_USER = vitoria.oliveira
|
||||||
|
ZABBIX_PASSWORD = 123Mudar
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEljCCA36gAwIBAgIQJ18cUeVWL5QojTvvnDiLyTANBgkqhkiG9w0BAQsFADCB
|
||||||
|
ijELMAkGA1UEBhMCQlIxFTATBgNVBAgMDE1pbmFzIEdlcmFpczEXMBUGA1UEBwwO
|
||||||
|
QmVsbyBIb3Jpem9udGUxDDAKBgNVBAoMA0FQSTELMAkGA1UECwwCSVQxMDAuBgNV
|
||||||
|
BAMMJ0FQSSBJbnRlcm1lZGlhdGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5CTAeFw0y
|
||||||
|
NTAxMjcxOTAyNTlaFw0yNjAxMjcyMDAyNTlaMIGrMQswCQYDVQQGEwJCUjELMAkG
|
||||||
|
A1UECBMCUkoxFzAVBgNVBAcTDlJJTyBERSBKQU5FSVJPMS0wKwYDVQQLEyRjMzI3
|
||||||
|
NWVhZi04NDA2LTQzMDAtOTMzNC04OTRlZTRhMWYyOGIxDTALBgNVBAoTBG51bGwx
|
||||||
|
ODA2BgNVBAMTL1IgUk9DQU5DT1VSVCBDQVZBREFTIENPTlNVTFRPUklBIEVNIElO
|
||||||
|
Rk9STUFUSUNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl8fvYOJe
|
||||||
|
kMJ1BH9m95lQO9zLEG153PZuoSBgEvCJ522tJlAPp1oo+SgC1LCSRLaDOxhlJbIo
|
||||||
|
0BIC5/ule6QmAMtaoC+qt+e8QzT8PKm7IX/SzpjziV7HNHKlEiNCeGC047iYTOWv
|
||||||
|
c843uUVicMBZfSJXodzE9RYIC4oTZnB83gvlaVk7xVyP4Auimg09F4dZTQjeI06T
|
||||||
|
RBgiPNJDn0+ilKWRUX2HGs0wnD2JX7wGPB+mkV0z5Rsv0F1D7IsIa3TdMsyBdzxX
|
||||||
|
0haz/bSB/R5ZxMTHZ3bzYoPWd5cSKenYu1FyFTKHebFhIFy2Vz6kbakVOgrWZDFx
|
||||||
|
yg8dzuTnKUzdWwIDAQABo4HUMIHRMAkGA1UdEwQCMAAwHwYDVR0jBBgwFoAUFBVp
|
||||||
|
/TT0EQj/WbtOGcyVlyKK4DwwHQYDVR0OBBYEFHQ+z6vbCts4TrDS5s+hIVHbh6rz
|
||||||
|
MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
|
||||||
|
VQYDVR0fBE4wTDBKoEigRoZEaHR0cDovL2NybC1hcGkuYmkubG9jYWwvY3JsLzE5
|
||||||
|
MzY0ZTc2LWM0YmUtNDBiNi05YzcxLWEzYTdiNDA0NzRhNC5jcmwwDQYJKoZIhvcN
|
||||||
|
AQELBQADggEBAHbjYT794YA7W9KsX+uXQIxXvd5IBVt+xzQw787/PgQ3elJNS36R
|
||||||
|
Yq5FdFjdvYDXTyFEi2YS+egqW+4wdBIvMUcM+86HhuhcKbkAjeMu1yM6vcORuuTV
|
||||||
|
BJ47vbR3hQiABGYhzOeq00CazFcpnDgydxx0sIhzWsEYrKOozUcXqdPFxVCpeR0X
|
||||||
|
rzEJgyrJd1l6fI+X8z/n3BCqYfCk+OJ8HYgTT8wpAJBVynuRNJRjYTIU3yySyEal
|
||||||
|
Fyny4CZxltqbnS+gZedyJZYf9aEPxQKNXcdpqGdvnmLv62EuWU129Z97FJ9rWB39
|
||||||
|
uFVdK6Uz+Klv+DqP3hDLatxqDsp30QrdwG0=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
@ -9,6 +9,13 @@ from .routes.perfil import perfil
|
||||||
from .routes.montagem import montagem
|
from .routes.montagem import montagem
|
||||||
from .routes.zabbix import zabbix
|
from .routes.zabbix import zabbix
|
||||||
from .routes.integrator import zammad
|
from .routes.integrator import zammad
|
||||||
|
from.routes.boletos import boletos
|
||||||
|
from.routes.upload_img import imagem
|
||||||
|
from.routes.servicos import servicos
|
||||||
|
from.routes.empresas import empresas
|
||||||
|
from.routes.newuser import newuser
|
||||||
|
from.routes.integrazabbix import integra
|
||||||
|
|
||||||
# Inicializa o MySQL
|
# Inicializa o MySQL
|
||||||
mysql = MySQL()
|
mysql = MySQL()
|
||||||
|
|
||||||
|
|
@ -33,7 +40,14 @@ def create_app():
|
||||||
app.register_blueprint(perfil)
|
app.register_blueprint(perfil)
|
||||||
app.register_blueprint(montagem)
|
app.register_blueprint(montagem)
|
||||||
app.register_blueprint(zabbix)
|
app.register_blueprint(zabbix)
|
||||||
|
app.register_blueprint(integra)
|
||||||
app.register_blueprint(zammad)
|
app.register_blueprint(zammad)
|
||||||
|
app.register_blueprint(boletos)
|
||||||
|
app.register_blueprint(imagem)
|
||||||
|
app.register_blueprint(servicos)
|
||||||
|
app.register_blueprint(empresas)
|
||||||
|
app.register_blueprint(newuser)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def home():
|
def home():
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class Config:
|
||||||
MYSQL_DB = os.getenv('MYSQL_DB', 'itguys')
|
MYSQL_DB = os.getenv('MYSQL_DB', 'itguys')
|
||||||
MYSQL_CURSORCLASS = 'DictCursor'
|
MYSQL_CURSORCLASS = 'DictCursor'
|
||||||
|
|
||||||
# Configurações do LDAP (Windows AD)
|
# Configurações do LDAP (Windows AD)
|
||||||
LDAP_SERVER = os.getenv('LDAP_SERVER', 'ldap://itguys.com.br') # IP/Hostname do servidor LDAP
|
LDAP_SERVER = os.getenv('LDAP_SERVER', 'ldap://itguys.com.br') # IP/Hostname do servidor LDAP
|
||||||
LDAP_DOMAIN = os.getenv('LDAP_DOMAIN', 'itguys.com.br') # Domínio do AD (FQDN)
|
LDAP_DOMAIN = os.getenv('LDAP_DOMAIN', 'itguys.com.br') # Domínio do AD (FQDN)
|
||||||
LDAP_BASE_DN = os.getenv('LDAP_BASE_DN', 'dc=itguys,dc=com,dc=br') # Distinguished Name (DN)
|
LDAP_BASE_DN = os.getenv('LDAP_BASE_DN', 'dc=itguys,dc=com,dc=br') # Distinguished Name (DN)
|
||||||
|
|
@ -25,8 +25,14 @@ class Config:
|
||||||
LDAP_PASSWORD = os.getenv('LDAP_PASSWORD', '123Mudar') # Senha do usuário LDAP
|
LDAP_PASSWORD = os.getenv('LDAP_PASSWORD', '123Mudar') # Senha do usuário LDAP
|
||||||
|
|
||||||
#Api Zammad
|
#Api Zammad
|
||||||
zammad_api_url = 'http://zammad.itguys.com.br/api/v1'
|
zammad_api_url = os.getenv('zammad_api_url','http://zammad.itguys.com.br/api/v1')
|
||||||
zammad_token = 'L081vJ19kood2uDlTSSt59LWBaewT9-a-MH_VKno8RY'
|
zammad_token = os.getenv('zammad_token','L081vJ19kood2uDlTSSt59LWBaewT9-a-MH_VKno8RY')
|
||||||
|
|
||||||
|
#ID Inter
|
||||||
|
CLIENT_ID = os.getenv('CLIENT_ID',"bfedfb96-7caf-4310-8632-a924c5daa7e1")
|
||||||
|
CLIENT_SECRET = os.getenv ('CLIENT_SECRET',"502d577e-b324-4b93-9624-e6b082588dc5")
|
||||||
|
CERT_PATH = os.getenv('CERT_PATH',"InterAPI_Certificado.crt")
|
||||||
|
CERT_KEY_PATH = os.getenv('CERT_KEY_PATH',"keyinter.pem")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import re
|
||||||
import ldap3
|
import ldap3
|
||||||
from ldap3.core.exceptions import LDAPSocketOpenError, LDAPException
|
from ldap3.core.exceptions import LDAPSocketOpenError, LDAPException
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from flask_mysqldb import MySQL
|
|
||||||
import logging
|
import logging
|
||||||
|
from flask_mysqldb import MySQL
|
||||||
|
|
||||||
# Configuração de logging para depuração
|
# Configuração de logging para depuração
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
@ -14,7 +14,6 @@ logging.basicConfig(level=logging.DEBUG)
|
||||||
auth = Blueprint('auth', __name__)
|
auth = Blueprint('auth', __name__)
|
||||||
mysql = MySQL()
|
mysql = MySQL()
|
||||||
|
|
||||||
|
|
||||||
# Decorador para validar o token JWT
|
# Decorador para validar o token JWT
|
||||||
def token_required(f):
|
def token_required(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
|
|
@ -26,22 +25,7 @@ def token_required(f):
|
||||||
try:
|
try:
|
||||||
data = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=["HS256"])
|
data = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=["HS256"])
|
||||||
except jwt.ExpiredSignatureError:
|
except jwt.ExpiredSignatureError:
|
||||||
# Caso o token esteja expirado, gere um novo token
|
return jsonify({'msg': 'Token expirado!'}), 401
|
||||||
try:
|
|
||||||
# Obter o payload original para criar um novo token
|
|
||||||
payload = jwt.decode(token, current_app.config['SECRET_KEY'], algorithms=["HS256"], options={"verify_exp": False})
|
|
||||||
|
|
||||||
# Gere um novo token com nova validade
|
|
||||||
new_token = jwt.encode({
|
|
||||||
'user_id': payload['user_id'],
|
|
||||||
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1)
|
|
||||||
}, current_app.config['SECRET_KEY'], algorithm="HS256")
|
|
||||||
|
|
||||||
response = jsonify({'msg': 'Token expirado! Novo token gerado.', 'new_token': new_token})
|
|
||||||
response.status_code = 401
|
|
||||||
return response
|
|
||||||
except Exception as e:
|
|
||||||
return jsonify({'msg': 'Erro ao processar o token expirado.', 'error': str(e)}), 401
|
|
||||||
except jwt.InvalidTokenError:
|
except jwt.InvalidTokenError:
|
||||||
return jsonify({'msg': 'Token inválido!'}), 401
|
return jsonify({'msg': 'Token inválido!'}), 401
|
||||||
|
|
||||||
|
|
@ -84,31 +68,20 @@ def login():
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return jsonify({'msg': 'Formato de usuário inválido. Use "usuario@dominio.com".'}), 400
|
return jsonify({'msg': 'Formato de usuário inválido. Use "usuario@dominio.com".'}), 400
|
||||||
|
|
||||||
# Buscar informações de domínio no banco de dados
|
# Verificar se o usuário está associado à empresa no MySQL
|
||||||
try:
|
try:
|
||||||
with mysql.connection.cursor() as cur:
|
|
||||||
cur.execute("SELECT idempresa, ip_dominio FROM empresa WHERE dominio = %s", (domain,))
|
|
||||||
empresa_result = cur.fetchone()
|
|
||||||
|
|
||||||
if not empresa_result:
|
|
||||||
return jsonify({'msg': 'Domínio não encontrado no banco de dados'}), 404
|
|
||||||
|
|
||||||
id_empresa, ip_dominio = empresa_result
|
|
||||||
|
|
||||||
# Verificar se o usuário está associado à empresa no MySQL
|
|
||||||
with mysql.connection.cursor() as cur:
|
with mysql.connection.cursor() as cur:
|
||||||
cur.execute("SELECT empresa_id, dominio FROM view_usuario_empresa WHERE usuario = %s AND dominio = %s", (username, domain))
|
cur.execute("SELECT empresa_id, dominio FROM view_usuario_empresa WHERE usuario = %s AND dominio = %s", (username, domain))
|
||||||
result = cur.fetchone()
|
result = cur.fetchone()
|
||||||
|
|
||||||
if not result:
|
if not result:
|
||||||
return jsonify({'msg': 'Usuário não associado à empresa'}), 404
|
return jsonify({'msg': 'Usuário não associado à empresa'}), 404
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Erro no banco de dados: {str(e)}")
|
logging.error(f"Erro no banco de dados: {str(e)}")
|
||||||
return jsonify({'msg': 'Erro no banco de dados'}), 500
|
return jsonify({'msg': 'Erro no banco de dados'}), 500
|
||||||
|
|
||||||
# Conexão LDAP com autenticação
|
# Autenticação LDAP usando domínio extraído
|
||||||
ldap_server = f'ldap://{"itguys.com.br:389"}'
|
ldap_server = f'ldap://{domain}:389'
|
||||||
ldap_user = f'{domain}\\{username}'
|
ldap_user = f'{domain}\\{username}'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -144,6 +117,3 @@ def login():
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Erro inesperado: {str(e)}")
|
logging.error(f"Erro inesperado: {str(e)}")
|
||||||
return jsonify({'msg': 'Erro inesperado durante a autenticação.'}), 500
|
return jsonify({'msg': 'Erro inesperado durante a autenticação.'}), 500
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,334 @@
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
from time import time
|
||||||
|
from functools import wraps
|
||||||
|
from base64 import b64decode
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from flask import Flask, Blueprint, jsonify, request, Response
|
||||||
|
from flask_mysqldb import MySQL
|
||||||
|
from flask_cors import CORS
|
||||||
|
from .auth import token_required
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from flask import send_file
|
||||||
|
import io
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# Configurações da API do Banco Inter
|
||||||
|
CLIENT_ID = os.environ.get("CLIENT_ID")
|
||||||
|
CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
|
||||||
|
CERT_PATH = os.environ.get("CERT_PATH")
|
||||||
|
CERT_KEY_PATH = os.environ.get("CERT_KEY_PATH")
|
||||||
|
ACCOUNT = os.environ.get("ACCOUNT", None)
|
||||||
|
API_BASE_URL = "https://cdpj.partners.bancointer.com.br"
|
||||||
|
|
||||||
|
boletos = Blueprint('boletos', __name__)
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
cors = CORS(app, resources={r"/v1/boletos/*": {"origins": "*", "methods": ["GET", "POST", "PUT", "OPTIONS"]}})
|
||||||
|
app.config["CORS_HEADERS"] = ["Content-Type", "Authorization", "Content-Disposition", "Content-Length"]
|
||||||
|
|
||||||
|
MYSQL_HOST = os.environ.get('MYSQL_HOST')
|
||||||
|
MYSQL_PORT = os.environ.get('MYSQL_PORT')
|
||||||
|
MYSQL_USER = os.environ.get('MYSQL_USER')
|
||||||
|
MYSQL_PASSWORD = os.environ.get('MYSQL_PASSWORD')
|
||||||
|
MYSQL_DB = os.environ.get('MYSQL_DB')
|
||||||
|
MYSQL_CURSORCLASS = os.environ.get("MYSQL_CURSORCLASS")
|
||||||
|
|
||||||
|
mysql = MySQL()
|
||||||
|
token_cache = {}
|
||||||
|
|
||||||
|
def intercept_options(f):
|
||||||
|
@wraps(f)
|
||||||
|
def decorated(*args, **kwargs):
|
||||||
|
if request.method == "OPTIONS":
|
||||||
|
response = jsonify({"status": "ok"})
|
||||||
|
response.headers.add("Access-Control-Allow-Origin", "*")
|
||||||
|
response.headers.add("Access-Control-Allow-Methods", "GET,POST,PUT,OPTIONS")
|
||||||
|
response.headers.add("Access-Control-Allow-Headers", "Content-Type,Authorization,Content-Disposition,Content-Length")
|
||||||
|
return response, 200
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
return decorated
|
||||||
|
|
||||||
|
|
||||||
|
def obter_token(scopes=["boleto-cobranca.write", "boleto-cobranca.read"]):
|
||||||
|
"""Obtem um token de acesso para a API do Banco Inter."""
|
||||||
|
scopes_param = " ".join(scopes)
|
||||||
|
if token_cache.get(scopes_param):
|
||||||
|
cached_token = token_cache.get(scopes_param)
|
||||||
|
# token is still valid
|
||||||
|
if cached_token.get("expires_at") > int(time()):
|
||||||
|
return cached_token["token"]
|
||||||
|
try:
|
||||||
|
request_string = f"client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&scope={scopes_param}&grant_type=client_credentials"
|
||||||
|
print("request_string", request_string)
|
||||||
|
response = requests.post(url=f"{API_BASE_URL}/oauth/v2/token",
|
||||||
|
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||||
|
cert=(CERT_PATH, CERT_KEY_PATH),
|
||||||
|
data=request_string)
|
||||||
|
data_json = response.json()
|
||||||
|
token = data_json.get("access_token")
|
||||||
|
token_cache[scopes_param] = {
|
||||||
|
"token": token,
|
||||||
|
"expires_at": data_json.get("expires_in") + int(time()),
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erro ao obter token de acesso: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def emitir_cobranca(token, dados_cobranca):
|
||||||
|
"""Emite uma cobrança para o Banco Inter de forma assíncrona."""
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json"
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
response = requests.post(
|
||||||
|
f"{API_BASE_URL}/cobranca/v3/cobrancas",
|
||||||
|
headers=headers,
|
||||||
|
cert=(CERT_PATH, CERT_KEY_PATH),
|
||||||
|
json=dados_cobranca
|
||||||
|
)
|
||||||
|
|
||||||
|
# Captura a resposta completa
|
||||||
|
resposta_json = response.json()
|
||||||
|
|
||||||
|
# Exibe detalhes da resposta para debug
|
||||||
|
print("Código de status:", response.status_code)
|
||||||
|
print("Resposta da API:", json.dumps(resposta_json, indent=4, ensure_ascii=False))
|
||||||
|
|
||||||
|
return resposta_json
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erro ao emitir cobrança: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def obter_cobranca(token, codigo_solicitacao):
|
||||||
|
"""Obtem uma cobrança."""
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Content-Type": "Application/json",
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
response = requests.get(f"{API_BASE_URL}/cobranca/v3/cobrancas/{codigo_solicitacao}",
|
||||||
|
headers=headers,
|
||||||
|
cert=(CERT_PATH, CERT_KEY_PATH))
|
||||||
|
return response.json()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erro ao emitir cobrança:{e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def obter_cobranca_pdf(token, codigo_solicitacao):
|
||||||
|
"""Obtem o PDF de uma cobrança."""
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Content-Type": "Application/json",
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
# Certifique-se de que o codigo_solicitacao seja inserido corretamente na URL
|
||||||
|
url = f"{API_BASE_URL}/cobranca/v3/cobrancas/{codigo_solicitacao}/pdf"
|
||||||
|
response = requests.get(url,
|
||||||
|
headers=headers,
|
||||||
|
cert=(CERT_PATH, CERT_KEY_PATH))
|
||||||
|
return response.json()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erro ao emitir cobrança:{e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def processar_cobranca_cliente(cliente, token):
|
||||||
|
"""
|
||||||
|
Processa a emissão da cobrança para um cliente específico,
|
||||||
|
retornando os dados relevantes.
|
||||||
|
"""
|
||||||
|
id_empresa = cliente["idempresa"]
|
||||||
|
hoje = datetime.now()
|
||||||
|
vencimento = (hoje + timedelta(days=5)).strftime("%Y-%m-%d")
|
||||||
|
|
||||||
|
dados_cobranca = {
|
||||||
|
"seuNumero": f"boleto-{id_empresa}",
|
||||||
|
"valorNominal": str(cliente["valor_servico"]),
|
||||||
|
"dataVencimento": vencimento,
|
||||||
|
"numDiasAgenda": 30,
|
||||||
|
"pagador": {
|
||||||
|
"cpfCnpj": cliente["cpf_cnpj"],
|
||||||
|
"tipoPessoa": cliente["tipo_pessoa"],
|
||||||
|
"nome": cliente["nome"],
|
||||||
|
"telefone": cliente["telefone"],
|
||||||
|
"endereco": cliente["endereco"],
|
||||||
|
"cidade": cliente["cidade"],
|
||||||
|
"uf": cliente["uf"],
|
||||||
|
"cep": cliente["cep"],
|
||||||
|
},
|
||||||
|
"formasRecebimento": ["BOLETO", "PIX"],
|
||||||
|
}
|
||||||
|
|
||||||
|
emissao_cobranca = emitir_cobranca(token, dados_cobranca)
|
||||||
|
codigo_solicitacao = emissao_cobranca.get("codigoSolicitacao") if emissao_cobranca else None
|
||||||
|
if not codigo_solicitacao:
|
||||||
|
return {
|
||||||
|
"cliente": cliente,
|
||||||
|
"status": "erro",
|
||||||
|
"mensagem": "Falha ao emitir cobrança."
|
||||||
|
}
|
||||||
|
|
||||||
|
cobranca = obter_cobranca(token, codigo_solicitacao)
|
||||||
|
if not cobranca:
|
||||||
|
return {
|
||||||
|
"cliente": cliente,
|
||||||
|
"status": "erro",
|
||||||
|
"mensagem": "Falha ao obter cobrança."
|
||||||
|
}
|
||||||
|
|
||||||
|
boleto_data = cobranca.get("cobranca", {}).get("boleto", {})
|
||||||
|
codigo_barras = boleto_data.get("codigoBarras")
|
||||||
|
linha_digitavel = cobranca.get("boleto", {}).get("linhaDigitavel")
|
||||||
|
pix_data = cobranca.get("pix", {})
|
||||||
|
pix_copia_e_cola = pix_data.get("pixCopiaECola")
|
||||||
|
|
||||||
|
cobranca_pdf = obter_cobranca_pdf(token, codigo_solicitacao)
|
||||||
|
if not cobranca_pdf or "pdf" not in cobranca_pdf:
|
||||||
|
return {
|
||||||
|
"cliente": cliente,
|
||||||
|
"status": "erro",
|
||||||
|
"mensagem": "Falha ao obter PDF da cobrança."
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
"cliente": cliente,
|
||||||
|
"status": "sucesso",
|
||||||
|
"codigo_solicitacao": codigo_solicitacao,
|
||||||
|
"codigo_barras": codigo_barras,
|
||||||
|
"linha_digitavel": linha_digitavel,
|
||||||
|
"pix_copia_e_cola": pix_copia_e_cola,
|
||||||
|
"pdf": cobranca_pdf["pdf"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@boletos.route('/', methods=['POST', 'OPTIONS'])
|
||||||
|
@intercept_options
|
||||||
|
@token_required
|
||||||
|
def gerar_boletos(data):
|
||||||
|
|
||||||
|
domain = data.get('domain')
|
||||||
|
escopos = data.get('scopes', [])
|
||||||
|
escopos.append("boleto-cobranca.write")
|
||||||
|
escopos.append("boleto-cobranca.read")
|
||||||
|
print("data", data)
|
||||||
|
print(domain)
|
||||||
|
print(escopos)
|
||||||
|
if 'boleto-cobranca.write' not in escopos:
|
||||||
|
return jsonify({"erro": "Permissão necessária: boleto-cobranca.write"}), 403
|
||||||
|
if not domain:
|
||||||
|
return jsonify({"error": "Domínio não encontrado no token"}), 400
|
||||||
|
|
||||||
|
hoje = datetime.now()
|
||||||
|
if hoje.day > 12:
|
||||||
|
return jsonify({"erro": "Boletos só podem ser gerados até o dia 12 de cada mês."}), 403
|
||||||
|
|
||||||
|
try:
|
||||||
|
cur = mysql.connection.cursor()
|
||||||
|
cur.execute(
|
||||||
|
"SELECT idempresa, nome, cpf_cnpj, tipo_pessoa, telefone, endereco, cidade, uf, cep, valor_servico FROM empresa WHERE dominio = %s",
|
||||||
|
(domain,)
|
||||||
|
)
|
||||||
|
clientes = cur.fetchall()
|
||||||
|
cur.close()
|
||||||
|
if not clientes:
|
||||||
|
return jsonify({"erro": "Nenhum cliente encontrado."}), 404
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erro ao acessar o banco de dados: {e}")
|
||||||
|
return jsonify({"erro": "Erro ao acessar o banco de dados."}), 500
|
||||||
|
|
||||||
|
token = obter_token(escopos)
|
||||||
|
if not token:
|
||||||
|
return jsonify({"erro": "Falha ao obter o token de acesso."}), 401
|
||||||
|
|
||||||
|
resultados = []
|
||||||
|
for cliente in clientes:
|
||||||
|
resultado = processar_cobranca_cliente(cliente, token)
|
||||||
|
resultados.append(resultado)
|
||||||
|
|
||||||
|
return jsonify({"resultados": resultados}), 200
|
||||||
|
|
||||||
|
|
||||||
|
@boletos.route('/<codigo_solicitacao>', methods=['GET', 'OPTIONS'])
|
||||||
|
@intercept_options
|
||||||
|
@token_required
|
||||||
|
def recuperar_cobranca(token_data, codigo_solicitacao):
|
||||||
|
print("codigo_solicitacao", codigo_solicitacao)
|
||||||
|
|
||||||
|
scopes = token_data.get('scopes', [])
|
||||||
|
print("token_data", token_data)
|
||||||
|
|
||||||
|
if 'boleto-cobranca.read' not in scopes:
|
||||||
|
return jsonify({"erro": "Permissao necessaria: boleto-cobranca.read"}), 403
|
||||||
|
|
||||||
|
token = obter_token(scopes)
|
||||||
|
if not token:
|
||||||
|
return jsonify({"erro": "Falha ao obter o token de acesso"}), 401
|
||||||
|
|
||||||
|
cobranca = obter_cobranca(token, codigo_solicitacao)
|
||||||
|
if cobranca is None:
|
||||||
|
return jsonify({"erro": "Erro ao obter PDF"}), 404
|
||||||
|
|
||||||
|
try:
|
||||||
|
codigo_barras = cobranca.get("boleto").get("codigoBarras")
|
||||||
|
linha_digitavel = cobranca.get("boleto").get("linhaDigitavel")
|
||||||
|
pix_copia_e_cola = cobranca.get("pix").get("pixCopiaECola")
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
"codigo_solicitacao": codigo_solicitacao,
|
||||||
|
"codigo_barras": codigo_barras,
|
||||||
|
"linha_digitavel": linha_digitavel,
|
||||||
|
"pix_copia_e_cola": pix_copia_e_cola,
|
||||||
|
}), 200
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"erro": f"Erro ao buscar cobranca: {e}"}), 500
|
||||||
|
|
||||||
|
|
||||||
|
@boletos.route('/<codigo_solicitacao>/pdf', methods=['GET', 'OPTIONS'])
|
||||||
|
@intercept_options
|
||||||
|
@token_required
|
||||||
|
def recuperar_boleto(token_data, codigo_solicitacao):
|
||||||
|
print("codigo_solicitacao", codigo_solicitacao)
|
||||||
|
|
||||||
|
scopes = token_data.get('scopes', [])
|
||||||
|
print("token_data", token_data)
|
||||||
|
|
||||||
|
if 'boleto-cobranca.read' not in scopes:
|
||||||
|
return jsonify({"erro": "Permissao necessaria: boleto-cobranca.read"}), 403
|
||||||
|
|
||||||
|
token = obter_token(scopes)
|
||||||
|
if not token:
|
||||||
|
return jsonify({"erro": "Falha ao obter o token de acesso"}), 401
|
||||||
|
|
||||||
|
cobranca_pdf = obter_cobranca_pdf(token, codigo_solicitacao)
|
||||||
|
if cobranca_pdf is None:
|
||||||
|
return jsonify({"erro": "Erro ao obter PDF"}), 404
|
||||||
|
|
||||||
|
try:
|
||||||
|
pdf_content_base64 = cobranca_pdf["pdf"]
|
||||||
|
pdf_content_bytes = b64decode(pdf_content_base64, validate=True)
|
||||||
|
return Response(pdf_content_bytes,
|
||||||
|
mimetype='application/pdf',
|
||||||
|
headers={
|
||||||
|
"Content-Disposition": "inline; filename=boleto.pdf",
|
||||||
|
"Content-Type": "application/pdf",
|
||||||
|
"Content-Length": len(pdf_content_bytes)
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({"erro": f"Erro ao decodificar PDF: {e}"}), 500
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.register_blueprint(boletos)
|
||||||
|
app.run(port=5000, debug=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import requests
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from flask import Blueprint
|
||||||
|
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
codigo_solicitacao = "<ALGUM_CODIGO_DE_SOLICITACAO>"
|
||||||
|
API_BASE_URL = "https://dev.itguys.com.br"
|
||||||
|
url = f"{API_BASE_URL}/v1/boletos/{codigo_solicitacao}/pdf"
|
||||||
|
headers = {
|
||||||
|
"Authorization": "Bearer <JWT_SECRET>",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
if response.status_code != 200:
|
||||||
|
print("Erro obtendo o PDF")
|
||||||
|
sys.exit(1)
|
||||||
|
# salva o conteudo da resposta em um arquivo, pois ja retorna como bytes
|
||||||
|
with open(f"{codigo_solicitacao}-cobranca.pdf", "wb") as pdf_file:
|
||||||
|
pdf_file.write(response.content)
|
||||||
|
print(f"PDF salvo em {codigo_solicitacao}-cobranca.pdf")
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
@ -5,7 +5,7 @@ from dotenv import load_dotenv
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
# Configurações Gerais
|
# Configurações Gerais
|
||||||
SECRET_KEY = os.getenv('SECRET_KEY', 'd702717e2361ba1a31ce3b98d28ee3e24e2e6a9be8e2afd8e004f842563bacbd')
|
SECRET_KEY = os.getenv('SECRET_KEY', 'd702717e2361ba1a31ce3b98d28ee3e24e2e6a9be8e2afd8e004f842563bacbd')
|
||||||
DEBUG = os.getenv('DEBUG', 'True') == 'True'
|
DEBUG = os.getenv('DEBUG', 'True') == 'True'
|
||||||
JSON_SORT_KEYS = False
|
JSON_SORT_KEYS = False
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
import logging
|
||||||
|
from flask import Blueprint, jsonify
|
||||||
|
from flask_mysqldb import MySQL
|
||||||
|
from .auth import token_required # Importando o token_required
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
empresas = Blueprint('empresas', __name__) # Criando o Blueprint
|
||||||
|
mysql = MySQL() # Criando a instância do MySQL
|
||||||
|
|
||||||
|
@empresas.route('/empresas', methods=['GET'])
|
||||||
|
@token_required
|
||||||
|
def listar_empresas(data): # Agora aceita o argumento 'data'
|
||||||
|
try:
|
||||||
|
cur = mysql.connection.cursor()
|
||||||
|
cur.execute("SELECT idempresa, nome, dominio FROM empresa")
|
||||||
|
resultados = cur.fetchall()
|
||||||
|
|
||||||
|
# Ajuste aqui: Adicionando o 'id_empresa' no dicionário
|
||||||
|
empresas_list = [{"idempresa": row['idempresa'], "nome": row['nome'], "dominio": row['dominio']} for row in resultados]
|
||||||
|
|
||||||
|
return jsonify(empresas_list), 200
|
||||||
|
except Exception:
|
||||||
|
return jsonify({"erro": "Erro interno no servidor"}), 500
|
||||||
|
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
import os
|
||||||
|
from time import time
|
||||||
|
from functools import wraps
|
||||||
|
from datetime import date
|
||||||
|
import requests
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Carregar variáveis de ambiente do arquivo .env
|
||||||
|
load_dotenv()
|
||||||
|
|
||||||
|
# Definição das credenciais e URL base da API
|
||||||
|
CLIENT_ID = os.environ.get("CLIENT_ID")
|
||||||
|
CLIENT_SECRET = os.environ.get("CLIENT_SECRET")
|
||||||
|
CERT_PATH = os.environ.get("CERT_PATH")
|
||||||
|
CERT_KEY_PATH = os.environ.get("CERT_KEY_PATH")
|
||||||
|
ACCOUNT = os.environ.get("ACCOUNT", None)
|
||||||
|
API_BASE_URL = "https://cdpj.partners.bancointer.com.br"
|
||||||
|
|
||||||
|
# Cache para tokens de acesso
|
||||||
|
token_cache = {}
|
||||||
|
|
||||||
|
def token_required(f):
|
||||||
|
@wraps(f)
|
||||||
|
def decorated(*args, **kwargs):
|
||||||
|
data = {
|
||||||
|
"domain": "example.com",
|
||||||
|
"scopes": ["boleto-cobranca.write", "boleto-cobranca.read"]
|
||||||
|
}
|
||||||
|
return f(data, *args, **kwargs)
|
||||||
|
return decorated
|
||||||
|
|
||||||
|
def obter_token(scopes=["boleto-cobranca.write", "boleto-cobranca.read"]):
|
||||||
|
"""Obtem um token de acesso para a API do Banco Inter."""
|
||||||
|
scopes_param = " ".join(scopes)
|
||||||
|
if token_cache.get(scopes_param):
|
||||||
|
cached_token = token_cache.get(scopes_param)
|
||||||
|
# token is still valid
|
||||||
|
if cached_token.get("expires_at") > int(time()):
|
||||||
|
return cached_token["token"]
|
||||||
|
try:
|
||||||
|
request_string = f"client_id={CLIENT_ID}&client_secret={CLIENT_SECRET}&scope={scopes_param}&grant_type=client_credentials"
|
||||||
|
print("request_string", request_string)
|
||||||
|
response = requests.post(url=f"{API_BASE_URL}/oauth/v2/token",
|
||||||
|
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
||||||
|
cert=(CERT_PATH, CERT_KEY_PATH),
|
||||||
|
data=request_string)
|
||||||
|
|
||||||
|
# Verificar o status da resposta
|
||||||
|
if response.status_code != 200:
|
||||||
|
print(f"Erro na requisição: {response.status_code}")
|
||||||
|
print("Resposta bruta:", response.text) # Imprime a resposta bruta para debugar
|
||||||
|
|
||||||
|
data_json = response.json()
|
||||||
|
print("Resposta JSON:", data_json) # Imprimir o JSON da resposta
|
||||||
|
token = data_json.get("access_token")
|
||||||
|
|
||||||
|
# Cache do token
|
||||||
|
token_cache[scopes_param] = {
|
||||||
|
"token": token,
|
||||||
|
"expires_at": data_json.get("expires_in") + int(time()),
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erro ao obter token de acesso: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_balance():
|
||||||
|
"""Obtém o saldo da conta no Banco Inter."""
|
||||||
|
token = obter_token(["saldo.read"])
|
||||||
|
if not token:
|
||||||
|
print("Erro: não foi possível obter o token de acesso.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(
|
||||||
|
f"{API_BASE_URL}/banking/v2/saldo",
|
||||||
|
headers={"Authorization": f"Bearer {token}"},
|
||||||
|
cert=(CERT_PATH, CERT_KEY_PATH)
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"Erro ao obter saldo: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_statements(start_date: str, end_date: str):
|
||||||
|
"""Obtém o extrato da conta no Banco Inter entre as datas informadas."""
|
||||||
|
token = obter_token(["extrato.read"])
|
||||||
|
if not token:
|
||||||
|
print("Erro: não foi possível obter o token de acesso.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.get(
|
||||||
|
f"{API_BASE_URL}/banking/v2/extrato",
|
||||||
|
params={"dataInicio": start_date, "dataFim": end_date},
|
||||||
|
headers={"Authorization": f"Bearer {token}"},
|
||||||
|
cert=(CERT_PATH, CERT_KEY_PATH)
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
except requests.RequestException as e:
|
||||||
|
print(f"Erro ao obter extrato: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
time_now = time()
|
||||||
|
yesterday = date.fromtimestamp(time_now - 60 * 60 * 24).strftime("%Y-%m-%d")
|
||||||
|
today = date.fromtimestamp(time_now).strftime("%Y-%m-%d")
|
||||||
|
|
||||||
|
print(f"Obtendo informações financeiras para o período: {yesterday} - {today}")
|
||||||
|
|
||||||
|
# Obter saldo
|
||||||
|
balance_data = get_balance()
|
||||||
|
print("Saldo:", balance_data)
|
||||||
|
|
||||||
|
# Obter extrato
|
||||||
|
statements_data = get_statements(yesterday, today)
|
||||||
|
print("Extrato:", statements_data)
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
from flask import Blueprint, jsonify
|
||||||
|
from .auth import token_required # Importa o decorador de autenticação
|
||||||
|
from .newzabbix import zapi # Importa a conexão Zabbix
|
||||||
|
|
||||||
|
integra = Blueprint('integra', __name__)
|
||||||
|
|
||||||
|
def obter_dados_zabbix():
|
||||||
|
try:
|
||||||
|
grupos = zapi.hostgroup.get(output="extend")
|
||||||
|
resultado = []
|
||||||
|
|
||||||
|
for grupo in grupos:
|
||||||
|
hosts = zapi.host.get(groupids=grupo['groupid'], output="extend")
|
||||||
|
hosts_info = []
|
||||||
|
|
||||||
|
for host in hosts:
|
||||||
|
itens = zapi.item.get(hostids=host['hostid'], output="extend",
|
||||||
|
filter={"key_": ["system.uptime", "net.if.in", "net.if.out", "vm.memory.size", "vfs.fs.size"]})
|
||||||
|
|
||||||
|
metricas = {item['key_']: item.get('lastvalue', 'N/A') for item in itens}
|
||||||
|
|
||||||
|
packet_loss = zapi.item.get(hostids=host['hostid'], filter={"key_": "net.ping.loss"}, output="extend")
|
||||||
|
metricas["net.ping.loss"] = packet_loss[0]['lastvalue'] if packet_loss else 'N/A'
|
||||||
|
|
||||||
|
hosts_info.append({
|
||||||
|
"host_name": host['name'],
|
||||||
|
"metrics": metricas
|
||||||
|
})
|
||||||
|
|
||||||
|
resultado.append({
|
||||||
|
"group_id": grupo['groupid'],
|
||||||
|
"group_name": grupo['name'],
|
||||||
|
"hosts": hosts_info
|
||||||
|
})
|
||||||
|
|
||||||
|
return resultado, 200
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return {"error": "Erro ao buscar dados do Zabbix", "details": str(e)}, 500
|
||||||
|
|
||||||
|
@integra.route('/zabbix/hosts', methods=['GET'])
|
||||||
|
@token_required
|
||||||
|
def hosts_e_metricas(_):
|
||||||
|
dados, status_code = obter_dados_zabbix()
|
||||||
|
return jsonify(dados), status_code
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import logging
|
||||||
|
from flask import Blueprint, jsonify, request
|
||||||
|
from .auth import token_required
|
||||||
|
from flask_mysqldb import MySQL
|
||||||
|
|
||||||
|
newuser = Blueprint('newuser', __name__)
|
||||||
|
|
||||||
|
mysql = MySQL()
|
||||||
|
|
||||||
|
# Configuração de logging
|
||||||
|
logging.basicConfig(level=logging.DEBUG) # Log no nível de debug
|
||||||
|
|
||||||
|
@newuser.route('/inserir', methods=['POST'])
|
||||||
|
@token_required
|
||||||
|
def inserir_dados(get): # Recebe current_user do decorador
|
||||||
|
data = request.get_json()
|
||||||
|
|
||||||
|
nome_completo = data.get('nome_completo')
|
||||||
|
usuario_ad = data.get('usuario_ad')
|
||||||
|
empresa = data.get('empresa')
|
||||||
|
dominio_empresa = data.get('dominio_empresa')
|
||||||
|
|
||||||
|
if not nome_completo or not usuario_ad or not empresa or not dominio_empresa:
|
||||||
|
return jsonify({'erro': 'Todos os campos são obrigatórios'}), 400
|
||||||
|
|
||||||
|
conn = mysql.connection
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
try:
|
||||||
|
query = """
|
||||||
|
INSERT INTO usuarios (nome, usuario, empresa, dominio)
|
||||||
|
VALUES (%s, %s, %s, %s)
|
||||||
|
"""
|
||||||
|
cursor.execute(query, (nome_completo, usuario_ad, empresa, dominio_empresa))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
return jsonify({'message': 'Dados inseridos com sucesso!'}), 200
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
logging.error(f"Erro ao inserir dados: {str(err)}", exc_info=True) # Logando erro com traceback
|
||||||
|
return jsonify({'erro': f'Erro ao inserir dados: {str(err)}'}), 500
|
||||||
|
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
from pyzabbix import ZabbixAPI
|
||||||
|
|
||||||
|
# Connect to the Zabbix server
|
||||||
|
zapi = ZabbixAPI("https://mimir.itguys.com.br/zabbix/api_jsonrpc.php")
|
||||||
|
|
||||||
|
# Login to the Zabbix API
|
||||||
|
zapi.login(token="10925e9e452cade5270f4d930feb3b5e1aa2cc9b366c1c5b4d72996212b12c93")
|
||||||
|
|
||||||
|
# Retrieve a list of host groups (not hosts themselves)
|
||||||
|
groups = zapi.hostgroup.get(output="extend")
|
||||||
|
|
||||||
|
# Print group information and metrics
|
||||||
|
for group in groups:
|
||||||
|
print(f"Group ID: {group['groupid']}, Group Name: {group['name']}")
|
||||||
|
|
||||||
|
# Retrieve hosts in this group
|
||||||
|
hosts = zapi.host.get(groupids=group['groupid'], output="extend")
|
||||||
|
|
||||||
|
for host in hosts:
|
||||||
|
print(f" Host Name: {host['name']}")
|
||||||
|
|
||||||
|
# Retrieve items (metrics) for each host
|
||||||
|
items = zapi.item.get(hostids=host['hostid'], output="extend",
|
||||||
|
filter={"key_": ["system.uptime", "net.if.in", "net.if.out", "vm.memory.size", "vfs.fs.size"]})
|
||||||
|
|
||||||
|
# Print metrics for each host
|
||||||
|
for item in items:
|
||||||
|
# Check which metric it corresponds to and print it
|
||||||
|
if item['key_'] == "system.uptime":
|
||||||
|
print(f" Uptime: {item['lastvalue']} seconds")
|
||||||
|
elif item['key_'] == "net.if.in":
|
||||||
|
print(f" Network In: {item['lastvalue']} bytes")
|
||||||
|
elif item['key_'] == "net.if.out":
|
||||||
|
print(f" Network Out: {item['lastvalue']} bytes")
|
||||||
|
elif item['key_'] == "vm.memory.size":
|
||||||
|
print(f" Memory Usage: {item['lastvalue']} bytes")
|
||||||
|
elif item['key_'] == "vfs.fs.size":
|
||||||
|
print(f" Disk Usage: {item['lastvalue']} bytes")
|
||||||
|
|
||||||
|
# Retrieve the network packet loss (example metric)
|
||||||
|
# This can vary depending on your Zabbix configuration for ping or similar metrics
|
||||||
|
network_packet_loss = zapi.item.get(hostids=host['hostid'],
|
||||||
|
filter={"key_": "net.ping.loss"}, output="extend")
|
||||||
|
for loss in network_packet_loss:
|
||||||
|
print(f" Packet Loss: {loss['lastvalue']} %")
|
||||||
|
|
||||||
|
# Logout from the Zabbix API
|
||||||
|
zapi.user.logout()
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
from flask import Blueprint, jsonify
|
||||||
|
from flask_mysqldb import MySQL
|
||||||
|
from .auth import token_required
|
||||||
|
|
||||||
|
servicos = Blueprint('servicos', __name__)
|
||||||
|
|
||||||
|
mysql = MySQL() # Instância do MySQL será configurada no app principal
|
||||||
|
|
||||||
|
@servicos.route('/servicos', methods=['GET'])
|
||||||
|
@token_required
|
||||||
|
def listar_servicos(data):
|
||||||
|
try:
|
||||||
|
domain = data.get('domain', '') # Obtém o domínio do usuário do token
|
||||||
|
if not domain:
|
||||||
|
return jsonify({"status": "error", "message": "Usuário não autenticado!"}), 401
|
||||||
|
|
||||||
|
# Conecta ao banco de dados e consulta os serviços
|
||||||
|
cur = mysql.connection.cursor()
|
||||||
|
|
||||||
|
query = """
|
||||||
|
SELECT `servico1`, `servico2`, `servico3`, `servico4`, `servico5`,
|
||||||
|
`servico6`, `servico9`, `servico12`
|
||||||
|
FROM `servicos` WHERE `dominio` = %s
|
||||||
|
"""
|
||||||
|
cur.execute(query, (domain,))
|
||||||
|
results = cur.fetchall()
|
||||||
|
cur.close()
|
||||||
|
|
||||||
|
|
||||||
|
# Verificando se resultados foram retornados
|
||||||
|
if results:
|
||||||
|
# Quando a consulta retorna uma tupla com dicionário, acessamos o primeiro item da tupla
|
||||||
|
row = results[0] # A primeira linha é um dicionário
|
||||||
|
servicos_prestados = {
|
||||||
|
"servico1": row.get('servico1'),
|
||||||
|
"servico2": row.get('servico2'),
|
||||||
|
"servico3": row.get('servico3'),
|
||||||
|
"servico4": row.get('servico4'),
|
||||||
|
"servico5": row.get('servico5'),
|
||||||
|
"servico6": row.get('servico6'),
|
||||||
|
"servico9": row.get('servico9'),
|
||||||
|
"servico12": row.get('servico12'),
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonify(servicos_prestados), 200
|
||||||
|
else:
|
||||||
|
return jsonify({"erro": "Nenhum serviço encontrado"}), 404
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erro interno: {e}") # Print detalhado do erro
|
||||||
|
return jsonify({"status": "error", "message": "Erro interno"}), 500
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
from flask_mysqldb import MySQL
|
||||||
|
from flask import Flask, Blueprint, jsonify, request
|
||||||
|
from .auth import token_required
|
||||||
|
import os
|
||||||
|
import traceback
|
||||||
|
import MySQLdb
|
||||||
|
|
||||||
|
imagem = Blueprint('imagem', __name__)
|
||||||
|
mysql = MySQL()
|
||||||
|
|
||||||
|
CAMINHO_PERFIL = "/var/www/Backend/itguys/ambiente_python/repositorio_img/perfil/"
|
||||||
|
CAMINHO_FUNDOS = "/var/www/Backend/itguys/ambiente_python/repositorio_img/fundos/"
|
||||||
|
|
||||||
|
def salvar_imagem(arquivo, tipo_imagem, nome_usuario):
|
||||||
|
"""Salva a imagem no diretório correspondente e retorna o caminho relativo"""
|
||||||
|
nome_arquivo = f"{nome_usuario}.jpg"
|
||||||
|
|
||||||
|
if tipo_imagem == "perfil":
|
||||||
|
caminho_diretorio = CAMINHO_PERFIL
|
||||||
|
caminho_relativo = f"perfil/{nome_arquivo}"
|
||||||
|
else:
|
||||||
|
caminho_diretorio = CAMINHO_FUNDOS
|
||||||
|
caminho_relativo = f"fundos/{nome_arquivo}"
|
||||||
|
|
||||||
|
caminho_completo = os.path.join(caminho_diretorio, nome_arquivo)
|
||||||
|
|
||||||
|
# Garante que o diretório existe
|
||||||
|
os.makedirs(caminho_diretorio, exist_ok=True)
|
||||||
|
|
||||||
|
# Salva a imagem
|
||||||
|
arquivo.save(caminho_completo)
|
||||||
|
|
||||||
|
return caminho_relativo # Retorna o caminho relativo para o banco de dados
|
||||||
|
|
||||||
|
def get_db_connection():
|
||||||
|
"""Verifica e retorna uma conexão válida com o banco de dados"""
|
||||||
|
try:
|
||||||
|
conn = mysql.connection
|
||||||
|
conn.ping() # Verifica se a conexão está ativa
|
||||||
|
return conn
|
||||||
|
except MySQLdb.OperationalError:
|
||||||
|
return mysql.connection # Tenta criar uma nova conexão
|
||||||
|
|
||||||
|
@imagem.route('/imagem', methods=['POST'])
|
||||||
|
@token_required
|
||||||
|
def receber_imagem(data):
|
||||||
|
try:
|
||||||
|
nome_usuario = data.get('user', '') # Separa o usuário do dominío
|
||||||
|
if not nome_usuario:
|
||||||
|
return jsonify({"status": "error", "message": "Usuário não autenticado!"}), 405
|
||||||
|
|
||||||
|
nome_usuario = nome_usuario.split('@')[0]
|
||||||
|
|
||||||
|
|
||||||
|
imagem_perfil = request.files.get('perfil')
|
||||||
|
imagem_foto_fundo = request.files.get('foto_fundo')
|
||||||
|
|
||||||
|
# Verifica se as imagens foram enviadas corretamente
|
||||||
|
if not imagem_perfil or not imagem_foto_fundo:
|
||||||
|
return jsonify({"status": "error", "message": "Imagens não enviadas corretamente!"}), 400
|
||||||
|
|
||||||
|
# Salva as imagens e obtém os caminhos relativos
|
||||||
|
caminho_perfil = salvar_imagem(imagem_perfil, "perfil", nome_usuario)
|
||||||
|
caminho_foto_fundo = salvar_imagem(imagem_foto_fundo, "fundo", nome_usuario)
|
||||||
|
|
||||||
|
# Conecta-se ao banco e executa a query de atualização
|
||||||
|
conn = get_db_connection()
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
query = """
|
||||||
|
UPDATE usuarios
|
||||||
|
SET img_perfil = %s, img_fundo = %s
|
||||||
|
WHERE usuario = %s
|
||||||
|
"""
|
||||||
|
valores = (caminho_perfil, caminho_foto_fundo, nome_usuario)
|
||||||
|
|
||||||
|
cursor.execute(query, valores)
|
||||||
|
conn.commit()
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
return jsonify({"status": "success", "message": "Imagens enviadas e salvas com sucesso!"}), 200
|
||||||
|
|
||||||
|
except MySQLdb.OperationalError as e:
|
||||||
|
return jsonify({"status": "error", "message": f"Erro de conexão com o banco de dados: {str(e)}"}), 500
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
return jsonify({"status": "error", "message": str(e)}), 500
|
||||||
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
import requests
|
import requests
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
base_url = "http://zammad.itguys.com.br/api/v1"
|
load_dotenv()
|
||||||
zammad_token = "kT0IXO8aVhPoTLcMRNL290rqd9jbRhhM0zf8MgBo3n00NLChToSU6rOGnMgWA0M2"
|
|
||||||
|
|
||||||
def listar_tickets(domain):
|
base_url = "https://zammad.itguys.com.br/api/v1"
|
||||||
|
zammad_token = "QiFbQ7txT0BS_3N8GrwOzAS6f7ziVTa1VqcGGpaPFscvdcfnBVjgq699fFj6NpQW" #Token expira em 2065
|
||||||
|
|
||||||
|
def listar_tickets(domain, limit=500, offset=0):
|
||||||
try:
|
try:
|
||||||
headers = {
|
headers = {
|
||||||
"Authorization": f"Token token={zammad_token}",
|
"Authorization": f"Token token={zammad_token}",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCXx+9g4l6QwnUE
|
||||||
|
f2b3mVA73MsQbXnc9m6hIGAS8Innba0mUA+nWij5KALUsJJEtoM7GGUlsijQEgLn
|
||||||
|
+6V7pCYAy1qgL6q357xDNPw8qbshf9LOmPOJXsc0cqUSI0J4YLTjuJhM5a9zzje5
|
||||||
|
RWJwwFl9Ileh3MT1FggLihNmcHzeC+VpWTvFXI/gC6KaDT0Xh1lNCN4jTpNEGCI8
|
||||||
|
0kOfT6KUpZFRfYcazTCcPYlfvAY8H6aRXTPlGy/QXUPsiwhrdN0yzIF3PFfSFrP9
|
||||||
|
tIH9HlnExMdndvNig9Z3lxIp6di7UXIVMod5sWEgXLZXPqRtqRU6CtZkMXHKDx3O
|
||||||
|
5OcpTN1bAgMBAAECggEAC9e4SEVxXnclvTuZk6EdPwZ7u6TnGMQLnrvRczjccbe/
|
||||||
|
hllB12tz/fjOu7ypNP5On/pHzhioEZAONP6QC2Uj5/T19cCyX9YPfOjx82PE65i3
|
||||||
|
IJKTkfjYrzFwyskAgzb8djYtf/Z96ZnCBE0zIJwJf3eCAemhXoQhDZFw8RG+1G5X
|
||||||
|
YtOoItBE5oIAXuUe3pYTaMY/1XnGe/vynFKeIcU9O2v6E3au8oueevqppmhfHkiM
|
||||||
|
a6gtNhjU3wpii3ZJk/L4Cpka752CjbXrZCaU1qMXB4hNkSuOi1Hq9clU91Fz4PXw
|
||||||
|
MHzeAZInlH3J29uxvDlGoMwTvpFIL2iRnrVzr40AfQKBgQC6+q31kAi818ciXxvh
|
||||||
|
ZxyEJEwQw/q5x/pTZQ2VRJB3kBpt7Lq570IZfDpaOsPg2wB/4SbE8XHpX7FzJAMd
|
||||||
|
BDCAzkBl8+fREbfL57/KKxV2EoHRfazSx23w8f5N5R+/OcXErgOAGUzcF2T53yXU
|
||||||
|
TXDpzgjTOEU/4p+h7wqceSenNwKBgQDPzxB0Xk8oYHWejIWVRuLV0US+kTxFiLX4
|
||||||
|
rrRppdk52oEzZFKJ0rosf00fHtxIyqW2NdPQlkphmyMjRUw3fPedK/FvNU8PnTo6
|
||||||
|
3MJ61QRgGSAi6/YMIs9K/Y83iFRKTBynZi36UCOUZbEncpZXuiOmplJWWE17FmHj
|
||||||
|
5IFItd5E/QKBgQCVD/oVVcGRg1iO71HTzZcvRZyalRLSfznyuBIvGN0vZGOdlOd8
|
||||||
|
CeEhXidK/aRhI1bvm/iDc5UDnzVhfKk6vbdJSKSQYvVBeKWVWmlM7DIM0k5KS622
|
||||||
|
0CS2vMWnJe28Tnt7A9toiUL8B26Jwbtv2FkXHBlvAmI6vxnSSDambfQN2wKBgQCm
|
||||||
|
IYqtDUxJIjxFwV91xJLJjyBfHSrLCA06PyjaIQ11c9rAZB6cMkxGEItuKrS+uMsb
|
||||||
|
zRKF+fCC8Yx4wQi6f3xROXUti7el6vNHZX9QxYVW8h8/69XrQ9Tmxai+I44HS6vI
|
||||||
|
pCZzq6eWFmo2+CN7BMNFkkfW4YcntPATSXWV1FdaXQKBgQC3mKzwS/3GZ4NOarCL
|
||||||
|
ISXGef+QZLPYj4eV08ccmRYXjlBR6rA2BNn9vPayB1E/IqG91Rj2tENLiE/NjVkG
|
||||||
|
ZuAss8FdQS19oiPRPEA+u11+pNy0RfJ9uxjrP9l//x8lA0cw/Pv6S/m2c+1DSjVd
|
||||||
|
UD2LwbNvaS6W4Vhy53LNGpbwmQ==
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLXKbJUo6/xfnj
|
||||||
|
1f6Pt/wKw4Ko4tS0WiK+DSfzXBuEStHtXvcB5PPbnMJ5KNGQiPcFq5rkcwlERg8F
|
||||||
|
Z/+hjhuyn1as4fMxquKTBH7FpYHMRbuURSXtp9aZGMf6oMc1lzWF3aVQEgGPcAi4
|
||||||
|
Pbp9ddFb4vhu/INe+At4WiQvWK0mD+TfX2XFdUcl1cNUQCz0VfeuBGpnjKApIqd3
|
||||||
|
2ed2wF7U7bYBic2p9TA4Fw+VYArng12AbV5f9BQWuUUhjRSM7rYFs/R2bOHhB3y0
|
||||||
|
5EP72jwqwYnXVZMKGOomq4Vhrdj0VmUjxC2r3iui+tH2HteHCNzNMrcoTOn+ag1/
|
||||||
|
lHfTZK41AgMBAAECggEAJ80wtI70suqB09qGeeT5zraAvGK23DyW96j2BH6mwQ/u
|
||||||
|
wd1YDVYc90LZWiLHz1jLNiAlzugH7IWku3tlEB7S43Ulnu0TLsmiEkGrOS5BNvR/
|
||||||
|
989H0tmKWgj8XNx6WM4JMvPUPtVjWkpEXqDwPs1gJjKISpqf8KauAgZsdhrOOrhA
|
||||||
|
w+2qmOd/5w7oZCNu9sm53XoR6pSifdpRl+AjY+XRK+/hfyD3DqLJoZcW5al2ZHsh
|
||||||
|
iUWgfDDexFXVEeSc9OSyh5vTVXweXv8WVbpxAcD3l7Bsi7hltPW4bxyUcXjVfNy4
|
||||||
|
rjITSASeVOgI4Kwguwl4WuTd4iMHgopPsKxZqP+1QQKBgQDs5ka//ie79V0I+wDY
|
||||||
|
Y5vLSRRb9rLg0MDQxNUs9Gsg/+cYiaJrBEh1V+RTKWVEfxHS/hcUvMPgmW73EHRb
|
||||||
|
vVp652bwcGd3RVY0cOoID6267lqoWim8h0hv5yF82tcRVr5TJO/6DUlpXKgDiDyi
|
||||||
|
Zqe1Sf/j3mCE0opnByQrX+2MdQKBgQDbwiR6MryH1xZR0O+OFKmnpcxoda3xSoZi
|
||||||
|
JNxlw/d3U69iPKnV0w7YN4a5ytG2+fLvb2X8FUrvpGBn2TCTOCMvCFHWN9FrAUqA
|
||||||
|
HhTGHq3HGhA1DnGby+sE6Wn1kLfBYTS/PCusnqXgSVb/NpBqV4uSprweLVwfr2mN
|
||||||
|
bt9zHkViwQKBgQDbHIIDwkduCZtrWv2FJ1xJweYaySrZ1TsB3YxucANGGmrcvzCC
|
||||||
|
WwvJvOlqIbeQixcpV+pxO8bQThncWlPFJnYxhyYm7VBFeNQq3OUZX6cIZr1jSUGh
|
||||||
|
Jl9RYS4QFTkmyFxw+pEbbn6f/RtJaRDsBJbJjxAm6t/K+hEZCfniRG+qoQKBgEyb
|
||||||
|
axfmI+6+vhsbWMcQ0OuOUql/jHl2303LR8F6BQRl+denChVuE9iv0pll6KF+lH9/
|
||||||
|
N/AehBbyGGFbRyGrCijVH6IrpydENfJfiiJeg3nKzieQt232MiFuNO/T2Rrihf68
|
||||||
|
PQVZ8L01E8y3+rP3fMJMuXtTmK+6+HLDWcXJoaqBAoGAdHcfcm1S1NNpizSlpAvv
|
||||||
|
WGmCBxSa4qz5/22RnuL0tSnOd59Uiwp0u6SKSSc+fhw7oMpWQYq8QnsAXjsit0P4
|
||||||
|
GRmb5Ox/fHR0oF6IclmWmZin6c5ZeIDYDuGBig1/c6doG1j6WkHJO7xVQ04t7CcA
|
||||||
|
jk4uwg6pRoaTCArAU3+1Pzk=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCXx+9g4l6QwnUE
|
||||||
|
f2b3mVA73MsQbXnc9m6hIGAS8Innba0mUA+nWij5KALUsJJEtoM7GGUlsijQEgLn
|
||||||
|
+6V7pCYAy1qgL6q357xDNPw8qbshf9LOmPOJXsc0cqUSI0J4YLTjuJhM5a9zzje5
|
||||||
|
RWJwwFl9Ileh3MT1FggLihNmcHzeC+VpWTvFXI/gC6KaDT0Xh1lNCN4jTpNEGCI8
|
||||||
|
0kOfT6KUpZFRfYcazTCcPYlfvAY8H6aRXTPlGy/QXUPsiwhrdN0yzIF3PFfSFrP9
|
||||||
|
tIH9HlnExMdndvNig9Z3lxIp6di7UXIVMod5sWEgXLZXPqRtqRU6CtZkMXHKDx3O
|
||||||
|
5OcpTN1bAgMBAAECggEAC9e4SEVxXnclvTuZk6EdPwZ7u6TnGMQLnrvRczjccbe/
|
||||||
|
hllB12tz/fjOu7ypNP5On/pHzhioEZAONP6QC2Uj5/T19cCyX9YPfOjx82PE65i3
|
||||||
|
IJKTkfjYrzFwyskAgzb8djYtf/Z96ZnCBE0zIJwJf3eCAemhXoQhDZFw8RG+1G5X
|
||||||
|
YtOoItBE5oIAXuUe3pYTaMY/1XnGe/vynFKeIcU9O2v6E3au8oueevqppmhfHkiM
|
||||||
|
a6gtNhjU3wpii3ZJk/L4Cpka752CjbXrZCaU1qMXB4hNkSuOi1Hq9clU91Fz4PXw
|
||||||
|
MHzeAZInlH3J29uxvDlGoMwTvpFIL2iRnrVzr40AfQKBgQC6+q31kAi818ciXxvh
|
||||||
|
ZxyEJEwQw/q5x/pTZQ2VRJB3kBpt7Lq570IZfDpaOsPg2wB/4SbE8XHpX7FzJAMd
|
||||||
|
BDCAzkBl8+fREbfL57/KKxV2EoHRfazSx23w8f5N5R+/OcXErgOAGUzcF2T53yXU
|
||||||
|
TXDpzgjTOEU/4p+h7wqceSenNwKBgQDPzxB0Xk8oYHWejIWVRuLV0US+kTxFiLX4
|
||||||
|
rrRppdk52oEzZFKJ0rosf00fHtxIyqW2NdPQlkphmyMjRUw3fPedK/FvNU8PnTo6
|
||||||
|
3MJ61QRgGSAi6/YMIs9K/Y83iFRKTBynZi36UCOUZbEncpZXuiOmplJWWE17FmHj
|
||||||
|
5IFItd5E/QKBgQCVD/oVVcGRg1iO71HTzZcvRZyalRLSfznyuBIvGN0vZGOdlOd8
|
||||||
|
CeEhXidK/aRhI1bvm/iDc5UDnzVhfKk6vbdJSKSQYvVBeKWVWmlM7DIM0k5KS622
|
||||||
|
0CS2vMWnJe28Tnt7A9toiUL8B26Jwbtv2FkXHBlvAmI6vxnSSDambfQN2wKBgQCm
|
||||||
|
IYqtDUxJIjxFwV91xJLJjyBfHSrLCA06PyjaIQ11c9rAZB6cMkxGEItuKrS+uMsb
|
||||||
|
zRKF+fCC8Yx4wQi6f3xROXUti7el6vNHZX9QxYVW8h8/69XrQ9Tmxai+I44HS6vI
|
||||||
|
pCZzq6eWFmo2+CN7BMNFkkfW4YcntPATSXWV1FdaXQKBgQC3mKzwS/3GZ4NOarCL
|
||||||
|
ISXGef+QZLPYj4eV08ccmRYXjlBR6rA2BNn9vPayB1E/IqG91Rj2tENLiE/NjVkG
|
||||||
|
ZuAss8FdQS19oiPRPEA+u11+pNy0RfJ9uxjrP9l//x8lA0cw/Pv6S/m2c+1DSjVd
|
||||||
|
UD2LwbNvaS6W4Vhy53LNGpbwmQ==
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDLXKbJUo6/xfnj
|
||||||
|
1f6Pt/wKw4Ko4tS0WiK+DSfzXBuEStHtXvcB5PPbnMJ5KNGQiPcFq5rkcwlERg8F
|
||||||
|
Z/+hjhuyn1as4fMxquKTBH7FpYHMRbuURSXtp9aZGMf6oMc1lzWF3aVQEgGPcAi4
|
||||||
|
Pbp9ddFb4vhu/INe+At4WiQvWK0mD+TfX2XFdUcl1cNUQCz0VfeuBGpnjKApIqd3
|
||||||
|
2ed2wF7U7bYBic2p9TA4Fw+VYArng12AbV5f9BQWuUUhjRSM7rYFs/R2bOHhB3y0
|
||||||
|
5EP72jwqwYnXVZMKGOomq4Vhrdj0VmUjxC2r3iui+tH2HteHCNzNMrcoTOn+ag1/
|
||||||
|
lHfTZK41AgMBAAECggEAJ80wtI70suqB09qGeeT5zraAvGK23DyW96j2BH6mwQ/u
|
||||||
|
wd1YDVYc90LZWiLHz1jLNiAlzugH7IWku3tlEB7S43Ulnu0TLsmiEkGrOS5BNvR/
|
||||||
|
989H0tmKWgj8XNx6WM4JMvPUPtVjWkpEXqDwPs1gJjKISpqf8KauAgZsdhrOOrhA
|
||||||
|
w+2qmOd/5w7oZCNu9sm53XoR6pSifdpRl+AjY+XRK+/hfyD3DqLJoZcW5al2ZHsh
|
||||||
|
iUWgfDDexFXVEeSc9OSyh5vTVXweXv8WVbpxAcD3l7Bsi7hltPW4bxyUcXjVfNy4
|
||||||
|
rjITSASeVOgI4Kwguwl4WuTd4iMHgopPsKxZqP+1QQKBgQDs5ka//ie79V0I+wDY
|
||||||
|
Y5vLSRRb9rLg0MDQxNUs9Gsg/+cYiaJrBEh1V+RTKWVEfxHS/hcUvMPgmW73EHRb
|
||||||
|
vVp652bwcGd3RVY0cOoID6267lqoWim8h0hv5yF82tcRVr5TJO/6DUlpXKgDiDyi
|
||||||
|
Zqe1Sf/j3mCE0opnByQrX+2MdQKBgQDbwiR6MryH1xZR0O+OFKmnpcxoda3xSoZi
|
||||||
|
JNxlw/d3U69iPKnV0w7YN4a5ytG2+fLvb2X8FUrvpGBn2TCTOCMvCFHWN9FrAUqA
|
||||||
|
HhTGHq3HGhA1DnGby+sE6Wn1kLfBYTS/PCusnqXgSVb/NpBqV4uSprweLVwfr2mN
|
||||||
|
bt9zHkViwQKBgQDbHIIDwkduCZtrWv2FJ1xJweYaySrZ1TsB3YxucANGGmrcvzCC
|
||||||
|
WwvJvOlqIbeQixcpV+pxO8bQThncWlPFJnYxhyYm7VBFeNQq3OUZX6cIZr1jSUGh
|
||||||
|
Jl9RYS4QFTkmyFxw+pEbbn6f/RtJaRDsBJbJjxAm6t/K+hEZCfniRG+qoQKBgEyb
|
||||||
|
axfmI+6+vhsbWMcQ0OuOUql/jHl2303LR8F6BQRl+denChVuE9iv0pll6KF+lH9/
|
||||||
|
N/AehBbyGGFbRyGrCijVH6IrpydENfJfiiJeg3nKzieQt232MiFuNO/T2Rrihf68
|
||||||
|
PQVZ8L01E8y3+rP3fMJMuXtTmK+6+HLDWcXJoaqBAoGAdHcfcm1S1NNpizSlpAvv
|
||||||
|
WGmCBxSa4qz5/22RnuL0tSnOd59Uiwp0u6SKSSc+fhw7oMpWQYq8QnsAXjsit0P4
|
||||||
|
GRmb5Ox/fHR0oF6IclmWmZin6c5ZeIDYDuGBig1/c6doG1j6WkHJO7xVQ04t7CcA
|
||||||
|
jk4uwg6pRoaTCArAU3+1Pzk=
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 99 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 198 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 56 KiB |
|
|
@ -0,0 +1 @@
|
||||||
|
49a8c9c3-aac6-44fe-bc8d-f295677b96a6
|
||||||