Sincrionizacion con SeaFile general
This commit is contained in:
parent
f2c9de3660
commit
37aea443d6
|
@ -11,3 +11,15 @@ DEFAULT_PASSWORD = 'blades3.3'
|
||||||
|
|
||||||
#~ Establece una ruta accesible para el servidor web
|
#~ Establece una ruta accesible para el servidor web
|
||||||
LOG_PATH = '/srv/empresa/logs/empresalibre.log'
|
LOG_PATH = '/srv/empresa/logs/empresalibre.log'
|
||||||
|
|
||||||
|
# ~ Establece los valores para sincronizar los backups de la base de datos
|
||||||
|
# ~ por ejemplo
|
||||||
|
# ~ SEAFILE_SERVER = {
|
||||||
|
# ~ 'URL': 'https://tu_servidor_seafile',
|
||||||
|
# ~ 'USER': 'tu_usuario',
|
||||||
|
# ~ 'PASS': 'tu_contraseña',
|
||||||
|
# ~ 'REPO': 'id_repo',
|
||||||
|
# ~ }
|
||||||
|
|
||||||
|
|
||||||
|
SEAFILE_SERVER = {}
|
|
@ -12,6 +12,9 @@ from email.mime.text import MIMEText
|
||||||
from email import encoders
|
from email import encoders
|
||||||
from email.utils import formatdate
|
from email.utils import formatdate
|
||||||
|
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
|
||||||
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Image
|
from reportlab.platypus import BaseDocTemplate, Frame, PageTemplate, Image
|
||||||
from reportlab.lib import colors
|
from reportlab.lib import colors
|
||||||
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
||||||
|
@ -724,3 +727,140 @@ class ReportTemplate(BaseDocTemplate):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class SeaFileAPI(object):
|
||||||
|
FILE_DOES_NOT_EXIST = 441
|
||||||
|
|
||||||
|
def __init__(self, url, username, password):
|
||||||
|
self._url = url
|
||||||
|
self._headers = self._get_auth(username, password)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_connect(self):
|
||||||
|
return bool(self._headers)
|
||||||
|
|
||||||
|
def _open(self, path):
|
||||||
|
return open(path, 'rb')
|
||||||
|
|
||||||
|
def _get_auth(self, username, password):
|
||||||
|
url = self._url + 'auth-token/'
|
||||||
|
data = {
|
||||||
|
'username': username,
|
||||||
|
'password': password,
|
||||||
|
}
|
||||||
|
resp = requests.post(url, data=data)
|
||||||
|
if resp.status_code != requests.codes.ok:
|
||||||
|
msg = 'Token Error: {}'.format(resp.status_code)
|
||||||
|
print (msg)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
headers = {'Authorization': 'Token {}'.format(resp.json()['token'])}
|
||||||
|
return headers
|
||||||
|
|
||||||
|
def _get_upload_link(self, repo_id):
|
||||||
|
if not self._headers:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
url = '{}repos/{}/upload-link/'.format(self._url, repo_id)
|
||||||
|
resp = requests.get(url, headers=self._headers)
|
||||||
|
if resp.status_code != requests.codes.ok:
|
||||||
|
msg = 'Error: {}'.format(resp.status_code)
|
||||||
|
print (msg)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
def _get_update_link(self, repo_id):
|
||||||
|
if not self._headers:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
url = '{}repos/{}/update-link/'.format(self._url, repo_id)
|
||||||
|
data = {'p': '/'}
|
||||||
|
resp = requests.get(url, data=data, headers=self._headers)
|
||||||
|
if resp.status_code != requests.codes.ok:
|
||||||
|
msg = 'Error: {}'.format(resp.status_code)
|
||||||
|
print (msg)
|
||||||
|
return ''
|
||||||
|
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
def _decrypt(self, repo_id, password):
|
||||||
|
if not self._headers:
|
||||||
|
return False
|
||||||
|
|
||||||
|
url = '{}repos/{}/'.format(self._url, repo_id)
|
||||||
|
data = {'password': password}
|
||||||
|
resp = requests.post(url, data=data, headers=self._headers)
|
||||||
|
if resp.status_code != requests.codes.ok:
|
||||||
|
msg = 'Error: {}'.format(resp.status_code)
|
||||||
|
print (msg)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def upload_file(self, path_file, repo_id, password):
|
||||||
|
if not self._headers:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if password:
|
||||||
|
if not self._decrypt(repo_id, password):
|
||||||
|
return False
|
||||||
|
|
||||||
|
upload_link = self._get_upload_link(repo_id)
|
||||||
|
data = {
|
||||||
|
'filename': path_file,
|
||||||
|
'parent_dir': '/',
|
||||||
|
'relative_path': '',
|
||||||
|
}
|
||||||
|
files = {'file': self._open(path_file)}
|
||||||
|
|
||||||
|
resp = requests.post(
|
||||||
|
upload_link, data=data, files=files, headers=self._headers)
|
||||||
|
if resp.status_code != requests.codes.ok:
|
||||||
|
msg = 'Upload Code: {}\n{}'.format(resp.status_code, resp.text)
|
||||||
|
print (msg)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _info_path(self, path):
|
||||||
|
path, filename = os.path.split(path)
|
||||||
|
return path, filename
|
||||||
|
|
||||||
|
def update_file(self, path_file, repo_id, password, create=True):
|
||||||
|
if not self._headers:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if password:
|
||||||
|
if not self._decrypt(repo_id, password):
|
||||||
|
return False
|
||||||
|
|
||||||
|
update_link = self._get_update_link(repo_id)
|
||||||
|
_, filename = self._info_path(path_file)
|
||||||
|
files = {
|
||||||
|
'file': (filename, self._open(path_file)),
|
||||||
|
'filename': (None, filename),
|
||||||
|
'target_file': (None, '/{}'.format(filename))
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = requests.post(update_link, files=files, headers=self._headers)
|
||||||
|
if resp.status_code != requests.codes.ok:
|
||||||
|
msg = 'Update Code: {}\n{}'.format(resp.status_code, resp.text)
|
||||||
|
print (msg)
|
||||||
|
if resp.status_code == self.FILE_DOES_NOT_EXIST and create:
|
||||||
|
return self.upload_file(path_file, repo_id, password)
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def ping(self):
|
||||||
|
url = self._url + 'ping/'
|
||||||
|
resp = requests.get(url)
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
|
||||||
|
def auth_ping(self):
|
||||||
|
url = self._url + 'auth/ping/'
|
||||||
|
resp = requests.get(url, headers=self._headers)
|
||||||
|
return resp.json()
|
||||||
|
|
||||||
|
|
|
@ -33,18 +33,13 @@ except:
|
||||||
import pyqrcode
|
import pyqrcode
|
||||||
from dateutil import parser
|
from dateutil import parser
|
||||||
|
|
||||||
from .helper import CaseInsensitiveDict, NumLet, SendMail, TemplateInvoice
|
from .helper import CaseInsensitiveDict, NumLet, SendMail, TemplateInvoice, \
|
||||||
|
SeaFileAPI
|
||||||
from settings import DEBUG, log, template_lookup, COMPANIES, DB_SAT, \
|
from settings import DEBUG, log, template_lookup, COMPANIES, DB_SAT, \
|
||||||
PATH_XSLT, PATH_XSLTPROC, PATH_OPENSSL, PATH_TEMPLATES, PATH_MEDIA, PRE, \
|
PATH_XSLT, PATH_XSLTPROC, PATH_OPENSSL, PATH_TEMPLATES, PATH_MEDIA, PRE, \
|
||||||
PATH_XMLSEC, TEMPLATE_CANCEL, DEFAULT_SAT_PRODUCTO, DECIMALES
|
PATH_XMLSEC, TEMPLATE_CANCEL, DEFAULT_SAT_PRODUCTO, DECIMALES
|
||||||
|
|
||||||
|
from settings import SEAFILE_SERVER
|
||||||
#~ def _get_hash(password):
|
|
||||||
#~ return bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
|
|
||||||
|
|
||||||
|
|
||||||
#~ def validate_password(hashed, password):
|
|
||||||
#~ return bcrypt.hashpw(password.encode(), hashed.encode()) == hashed.encode()
|
|
||||||
|
|
||||||
|
|
||||||
def _call(args):
|
def _call(args):
|
||||||
|
@ -1390,11 +1385,46 @@ def crear_db(nombre):
|
||||||
|
|
||||||
|
|
||||||
def _to_seafile(path_db, data):
|
def _to_seafile(path_db, data):
|
||||||
msg = '\tSincronizando backup...'
|
# ~ if DEBUG:
|
||||||
log.info(msg)
|
# ~ return
|
||||||
|
|
||||||
|
_, filename = os.path.split(path_db)
|
||||||
|
if SEAFILE_SERVER:
|
||||||
|
msg = '\tSincronizando backup general...'
|
||||||
|
log.info(msg)
|
||||||
|
seafile = SeaFileAPI(
|
||||||
|
SEAFILE_SERVER['URL'],
|
||||||
|
SEAFILE_SERVER['USER'],
|
||||||
|
SEAFILE_SERVER['PASS'])
|
||||||
|
|
||||||
|
if seafile.is_connect:
|
||||||
|
msg = '\tSincronizando: {} '.format(filename)
|
||||||
|
log.info(msg)
|
||||||
|
seafile.update_file(
|
||||||
|
path_db, SEAFILE_SERVER['REPO'], SEAFILE_SERVER['PASS'])
|
||||||
|
msg = '\tRespaldo general de {} sincronizado'.format(filename)
|
||||||
|
log.info(msg)
|
||||||
|
|
||||||
|
if len(data) < 2:
|
||||||
|
return
|
||||||
|
if not data[0] or not data[1]:
|
||||||
|
return
|
||||||
|
|
||||||
|
# ~ msg = '\tSincronizando backup particular...'
|
||||||
|
# ~ log.info(msg)
|
||||||
|
# ~ seafile = SeaFileAPI(SEAFILE_SERVER['URL'], data[0], data[1])
|
||||||
|
# ~ if seafile.is_connect:
|
||||||
|
# ~ msg = '\tSincronizando: {} '.format(filename)
|
||||||
|
# ~ log.info(msg)
|
||||||
|
# ~ seafile.update_file(
|
||||||
|
# ~ path_db, SEAFILE_SERVER['REPO'], data[1])
|
||||||
|
# ~ msg = '\tRespaldo partícular de {} sincronizado'.format(filename)
|
||||||
|
# ~ log.info(msg)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@run_in_thread
|
||||||
def _backup_and_sync(rfc, data):
|
def _backup_and_sync(rfc, data):
|
||||||
msg = 'Generando backup de: {}'.format(rfc)
|
msg = 'Generando backup de: {}'.format(rfc)
|
||||||
log.info(msg)
|
log.info(msg)
|
||||||
|
@ -1413,11 +1443,6 @@ def _backup_and_sync(rfc, data):
|
||||||
msg = '\tBackup generado...'
|
msg = '\tBackup generado...'
|
||||||
log.info(msg)
|
log.info(msg)
|
||||||
result = _call(sql).strip().split('|')
|
result = _call(sql).strip().split('|')
|
||||||
if len(result) < 2:
|
|
||||||
return
|
|
||||||
if not result[0] or not result[1]:
|
|
||||||
return
|
|
||||||
|
|
||||||
_to_seafile(path_bk, result)
|
_to_seafile(path_bk, result)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.info(e)
|
log.info(e)
|
||||||
|
@ -1438,7 +1463,7 @@ def backup_dbs():
|
||||||
|
|
||||||
for rfc, data in rows:
|
for rfc, data in rows:
|
||||||
args = loads(data)
|
args = loads(data)
|
||||||
run_in_thread(_backup_and_sync(rfc, args))
|
_backup_and_sync(rfc, args)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,11 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
DEFAULT_PASSWORD = 'blades3.3'
|
DEFAULT_PASSWORD = 'blades3.3'
|
||||||
|
|
||||||
|
try:
|
||||||
|
from conf import SEAFILE_SERVER
|
||||||
|
except ImportError:
|
||||||
|
SEAFILE_SERVER = {}
|
||||||
|
|
||||||
|
|
||||||
DEBUG = DEBUG
|
DEBUG = DEBUG
|
||||||
VERSION = '0.2.1'
|
VERSION = '0.2.1'
|
||||||
|
|
|
@ -148,7 +148,7 @@ var emisor_otros_datos= [
|
||||||
{view: 'text', id: 'token_timbrado',
|
{view: 'text', id: 'token_timbrado',
|
||||||
name: 'token_timbrado', label: 'Token de Timbrado: '},
|
name: 'token_timbrado', label: 'Token de Timbrado: '},
|
||||||
{view: 'text', id: 'token_soporte',
|
{view: 'text', id: 'token_soporte',
|
||||||
name: 'token_soporte', label: 'Token de Soporte: '},
|
name: 'token_soporte', label: 'Token para Respaldos: '},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue