1
0
mirror of https://github.com/janeczku/calibre-web synced 2024-12-25 01:20:32 +00:00

Added function to download debug information

This commit is contained in:
Ozzieisaacs 2020-11-15 14:19:25 +01:00
parent 4081895a78
commit 32b7b39223
7 changed files with 131 additions and 22 deletions

View File

@ -82,6 +82,12 @@ _VERSIONS = OrderedDict(
_VERSIONS.update(uploader.get_versions())
def collect_stats():
_VERSIONS['ebook converter'] = _(converter.get_calibre_version())
_VERSIONS['unrar'] = _(converter.get_unrar_version())
_VERSIONS['kepubify'] = _(converter.get_kepubify_version())
return _VERSIONS
@about.route("/stats")
@flask_login.login_required
def stats():
@ -89,8 +95,7 @@ def stats():
authors = calibre_db.session.query(db.Authors).count()
categorys = calibre_db.session.query(db.Tags).count()
series = calibre_db.session.query(db.Series).count()
_VERSIONS['ebook converter'] = _(converter.get_calibre_version())
_VERSIONS['unrar'] = _(converter.get_unrar_version())
_VERSIONS['kepubify'] = _(converter.get_kepubify_version())
return render_title_template('stats.html', bookcounter=counter, authorcounter=authors, versions=_VERSIONS,
return render_title_template('stats.html', bookcounter=counter, authorcounter=authors, versions=collect_stats(),
categorycounter=categorys, seriecounter=series, title=_(u"Statistics"), page="stat")

View File

@ -41,7 +41,8 @@ from . import constants, logger, helper, services
from . import db, calibre_db, ub, web_server, get_locale, config, updater_thread, babel, gdriveutils
from .helper import check_valid_domain, send_test_mail, reset_password, generate_password_hash
from .gdriveutils import is_gdrive_ready, gdrive_support
from .web import admin_required, render_title_template, before_request, unconfigured, login_required_if_no_ano
from .web import admin_required, render_title_template, before_request, unconfigured
from . import debug_info
log = logger.create()
@ -218,7 +219,8 @@ def edit_domain(allow):
@admin_required
def add_domain(allow):
domain_name = request.form.to_dict()['domainname'].replace('*', '%').replace('?', '_').lower()
check = ub.session.query(ub.Registration).filter(ub.Registration.domain == domain_name).filter(ub.Registration.allow == allow).first()
check = ub.session.query(ub.Registration).filter(ub.Registration.domain == domain_name)\
.filter(ub.Registration.allow == allow).first()
if not check:
new_domain = ub.Registration(domain=domain_name, allow=allow)
ub.session.add(new_domain)
@ -548,12 +550,14 @@ def _configuration_logfile_helper(to_save, gdriveError):
reboot_required |= _config_int(to_save, "config_log_level")
reboot_required |= _config_string(to_save, "config_logfile")
if not logger.is_valid_logfile(config.config_logfile):
return reboot_required, _configuration_result(_('Logfile Location is not Valid, Please Enter Correct Path'), gdriveError)
return reboot_required, \
_configuration_result(_('Logfile Location is not Valid, Please Enter Correct Path'), gdriveError)
reboot_required |= _config_checkbox_int(to_save, "config_access_log")
reboot_required |= _config_string(to_save, "config_access_logfile")
if not logger.is_valid_logfile(config.config_access_logfile):
return reboot_required, _configuration_result(_('Access Logfile Location is not Valid, Please Enter Correct Path'), gdriveError)
return reboot_required, \
_configuration_result(_('Access Logfile Location is not Valid, Please Enter Correct Path'), gdriveError)
return reboot_required, None
def _configuration_ldap_helper(to_save, gdriveError):
@ -585,28 +589,32 @@ def _configuration_ldap_helper(to_save, gdriveError):
if config.config_ldap_authentication > constants.LDAP_AUTH_ANONYMOUS:
if config.config_ldap_authentication > constants.LDAP_AUTH_UNAUTHENTICATE:
if not config.config_ldap_serv_username or not bool(config.config_ldap_serv_password):
return reboot_required, _configuration_result('Please Enter a LDAP Service Account and Password', gdriveError)
return reboot_required, _configuration_result('Please Enter a LDAP Service Account and Password',
gdriveError)
else:
if not config.config_ldap_serv_username:
return reboot_required, _configuration_result('Please Enter a LDAP Service Account', gdriveError)
if config.config_ldap_group_object_filter:
if config.config_ldap_group_object_filter.count("%s") != 1:
return reboot_required, _configuration_result(_('LDAP Group Object Filter Needs to Have One "%s" Format Identifier'),
return reboot_required, \
_configuration_result(_('LDAP Group Object Filter Needs to Have One "%s" Format Identifier'),
gdriveError)
if config.config_ldap_group_object_filter.count("(") != config.config_ldap_group_object_filter.count(")"):
return reboot_required, _configuration_result(_('LDAP Group Object Filter Has Unmatched Parenthesis'),
gdriveError)
if config.config_ldap_user_object.count("%s") != 1:
return reboot_required, _configuration_result(_('LDAP User Object Filter needs to Have One "%s" Format Identifier'),
return reboot_required, \
_configuration_result(_('LDAP User Object Filter needs to Have One "%s" Format Identifier'),
gdriveError)
if config.config_ldap_user_object.count("(") != config.config_ldap_user_object.count(")"):
return reboot_required, _configuration_result(_('LDAP User Object Filter Has Unmatched Parenthesis'),
gdriveError)
if config.config_ldap_cert_path and not os.path.isfile(config.config_ldap_cert_path):
return reboot_required, _configuration_result(_('LDAP Certificate Location is not Valid, Please Enter Correct Path'),
return reboot_required, \
_configuration_result(_('LDAP Certificate Location is not Valid, Please Enter Correct Path'),
gdriveError)
return reboot_required, None
@ -617,7 +625,10 @@ def _configuration_update_helper():
to_save = request.form.to_dict()
gdriveError = None
to_save['config_calibre_dir'] = re.sub('[\\/]metadata\.db$', '', to_save['config_calibre_dir'], flags=re.IGNORECASE)
to_save['config_calibre_dir'] = re.sub('[\\/]metadata\.db$',
'',
to_save['config_calibre_dir'],
flags=re.IGNORECASE)
try:
db_change |= _config_string(to_save, "config_calibre_dir")
@ -1028,6 +1039,27 @@ def send_logfile(logtype):
else:
return ""
@admi.route("/admin/logdownload/<int:logtype>")
@login_required
@admin_required
def download_log(logtype):
if logtype == 0:
file_name = logger.get_logfile(config.config_logfile)
elif logtype == 1:
file_name = logger.get_accesslogfile(config.config_access_logfile)
else:
abort(404)
if logger.is_valid_logfile(file_name):
return debug_info.assemble_logfiles(file_name)
abort(404)
@admi.route("/admin/debug")
@login_required
@admin_required
def download_debug():
return debug_info.send_debug()
@admi.route("/get_update_status", methods=['GET'])
@login_required

55
cps/debug_info.py Normal file
View File

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
# This file is part of the Calibre-Web (https://github.com/janeczku/calibre-web)
# Copyright (C) 2012-2019 cervinko, idalin, SiphonSquirrel, ouzklcn, akushsky,
# OzzieIsaacs, bodybybuddha, jkrehm, matthazinski, janeczku
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import shutil
import glob
import zipfile
import json
import io
import os
from flask import send_file
from . import logger, config
from .about import collect_stats
log = logger.create()
def assemble_logfiles(file_name):
log_list = glob.glob(file_name + '*')
wfd = io.StringIO()
for f in log_list:
with open(f, 'r') as fd:
shutil.copyfileobj(fd, wfd)
return send_file(wfd,
as_attachment=True,
attachment_filename=os.path.basename(file_name))
def send_debug():
file_list = glob.glob(logger.get_logfile(config.config_logfile) + '*')
file_list.extend(glob.glob(logger.get_accesslogfile(config.config_access_logfile) + '*'))
memory_zip = io.BytesIO()
with zipfile.ZipFile(memory_zip, 'w', compression=zipfile.ZIP_DEFLATED) as zf:
zf.writestr('libs.txt', json.dumps(collect_stats()))
for fp in file_list:
zf.write(fp, os.path.basename(fp))
memory_zip.seek(0)
return send_file(memory_zip,
as_attachment=True,
attachment_filename="Calibre-Web-debug-pack.zip")

View File

@ -24,7 +24,10 @@ import io
import mimetypes
import re
import shutil
import glob
import time
import zipfile
import json
import unicodedata
from datetime import datetime, timedelta
from tempfile import gettempdir
@ -32,14 +35,12 @@ from tempfile import gettempdir
import requests
from babel.dates import format_datetime
from babel.units import format_unit
from flask import send_from_directory, make_response, redirect, abort, url_for
from flask import send_from_directory, make_response, redirect, abort, url_for, send_file
from flask_babel import gettext as _
from flask_login import current_user
from sqlalchemy.sql.expression import true, false, and_, text
from werkzeug.datastructures import Headers
from werkzeug.security import generate_password_hash
from . import calibre_db
from .tasks.convert import TaskConvert
try:
from urllib.parse import quote
@ -59,6 +60,8 @@ try:
except ImportError:
use_PIL = False
from . import calibre_db
from .tasks.convert import TaskConvert
from . import logger, config, get_locale, db, ub
from . import gdriveutils as gd
from .constants import STATIC_DIR as _STATIC_DIR
@ -824,3 +827,4 @@ def get_download_link(book_id, book_format, client):
return do_download_file(book, book_format, client, data1, headers)
else:
abort(404)

View File

@ -132,14 +132,16 @@
</div>
</div>
<div class="row">
<div class="col">
<h2>{{_('Administration')}}</h2>
<div class="row form-group">
<h2>{{_('Administration')}}</h2>
<div class="btn btn-default"><a id="debug" href="{{url_for('admin.download_debug')}}">{{_('Download Debug Package')}}</a></div>
<div class="btn btn-default"><a id="logfile" href="{{url_for('admin.view_logfile')}}">{{_('View Logs')}}</a></div>
</div>
<div class="row form-group">
<div class="btn btn-default" id="restart_database" data-toggle="modal" data-target="#StatusDialog">{{_('Reconnect Calibre Database')}}</div>
<div class="btn btn-default" id="admin_restart" data-toggle="modal" data-target="#RestartDialog">{{_('Restart')}}</div>
<div class="btn btn-default" id="admin_stop" data-toggle="modal" data-target="#ShutdownDialog">{{_('Shutdown')}}</div>
</div>
</div>
<div class="row">

View File

@ -12,7 +12,18 @@
<label for="log0">{{_('Show Access Log: ')}}</label>{{logfiles[1]}}</div>
{% endif %}
</div>
<div class="row">
<div class="col-xs-6 col-sm-7">
{% if log_enable %}
<div class="btn btn-default"><a id="log_file" href="{{url_for('admin.download_log', logtype=0)}}">{{_('Download Calibre-Web Log')}}</a></div>
{% endif %}
{% if accesslog_enable %}
<div class="btn btn-default"><a id="log_file" href="{{url_for('admin.download_log', logtype=1)}}">{{_('Download Access Log')}}</a></div>
{% endif %}
</div>
</div>
<div id="renderer" class="log"></div>
{% endblock %}
{% block js %}
<script src="{{ url_for('static', filename='js/logviewer.js') }}"></script>

View File

@ -8,8 +8,8 @@ Flask>=1.0.2,<1.2.0
iso-639>=0.4.5,<0.5.0
PyPDF2==1.26.0,<1.27.0
pytz>=2016.10
requests>=2.11.1,<2.24.0
requests>=2.11.1,<2.26.0
SQLAlchemy>=1.3.0,<1.4.0
tornado>=4.1,<6.1
tornado>=4.1,<6.2
Wand>=0.4.4,<0.6.0
unidecode>=0.04.19,<1.2.0