Commit 725fc658 authored by Ozzie Isaacs's avatar Ozzie Isaacs

Some code cosmetics

parent e4e27662
......@@ -74,6 +74,41 @@ def _cover_processing(tmp_file_name, img, extension):
return tmp_cover_name
def _extract_Cover_from_archive(original_file_extension, tmp_file_name, rarExecutable):
cover_data = None
if original_file_extension.upper() == '.CBZ':
cf = zipfile.ZipFile(tmp_file_name)
for name in cf.namelist():
ext = os.path.splitext(name)
if len(ext) > 1:
extension = ext[1].lower()
if extension in COVER_EXTENSIONS:
cover_data = cf.read(name)
break
elif original_file_extension.upper() == '.CBT':
cf = tarfile.TarFile(tmp_file_name)
for name in cf.getnames():
ext = os.path.splitext(name)
if len(ext) > 1:
extension = ext[1].lower()
if extension in COVER_EXTENSIONS:
cover_data = cf.extractfile(name).read()
break
elif original_file_extension.upper() == '.CBR' and use_rarfile:
try:
rarfile.UNRAR_TOOL = rarExecutable
cf = rarfile.RarFile(tmp_file_name)
for name in cf.getnames():
ext = os.path.splitext(name)
if len(ext) > 1:
extension = ext[1].lower()
if extension in COVER_EXTENSIONS:
cover_data = cf.read(name)
break
except Exception as e:
log.debug('Rarfile failed with error: %s', e)
return cover_data
def _extractCover(tmp_file_name, original_file_extension, rarExecutable):
cover_data = extension = None
......@@ -87,37 +122,7 @@ def _extractCover(tmp_file_name, original_file_extension, rarExecutable):
cover_data = archive.getPage(index)
break
else:
if original_file_extension.upper() == '.CBZ':
cf = zipfile.ZipFile(tmp_file_name)
for name in cf.namelist():
ext = os.path.splitext(name)
if len(ext) > 1:
extension = ext[1].lower()
if extension in COVER_EXTENSIONS:
cover_data = cf.read(name)
break
elif original_file_extension.upper() == '.CBT':
cf = tarfile.TarFile(tmp_file_name)
for name in cf.getnames():
ext = os.path.splitext(name)
if len(ext) > 1:
extension = ext[1].lower()
if extension in COVER_EXTENSIONS:
cover_data = cf.extractfile(name).read()
break
elif original_file_extension.upper() == '.CBR' and use_rarfile:
try:
rarfile.UNRAR_TOOL = rarExecutable
cf = rarfile.RarFile(tmp_file_name)
for name in cf.getnames():
ext = os.path.splitext(name)
if len(ext) > 1:
extension = ext[1].lower()
if extension in COVER_EXTENSIONS:
cover_data = cf.read(name)
break
except Exception as e:
log.debug('Rarfile failed with error: %s', e)
cover_data = _extract_Cover_from_archive(original_file_extension, tmp_file_name, rarExecutable)
return _cover_processing(tmp_file_name, cover_data, extension)
......@@ -142,7 +147,8 @@ def get_comic_info(tmp_file_path, original_file_name, original_file_extension, r
file_path=tmp_file_path,
extension=original_file_extension,
title=loadedMetadata.title or original_file_name,
author=" & ".join([credit["person"] for credit in loadedMetadata.credits if credit["role"] == "Writer"]) or u'Unknown',
author=" & ".join([credit["person"]
for credit in loadedMetadata.credits if credit["role"] == "Writer"]) or u'Unknown',
cover=_extractCover(tmp_file_path, original_file_extension, rarExecutable),
description=loadedMetadata.comments or "",
tags="",
......
......@@ -146,15 +146,16 @@ class _ConfigSQL(object):
self.load()
change = False
if self.config_converterpath == None:
if self.config_converterpath == None: # pylint: disable=access-member-before-definition
change = True
self.config_converterpath = autodetect_calibre_binary()
if self.config_kepubifypath == None:
if self.config_kepubifypath == None: # pylint: disable=access-member-before-definition
change = True
self.config_kepubifypath = autodetect_kepubify_binary()
if self.config_rarfile_location == None:
if self.config_rarfile_location == None: # pylint: disable=access-member-before-definition
change = True
self.config_rarfile_location = autodetect_unrar_binary()
if change:
......@@ -181,7 +182,8 @@ class _ConfigSQL(object):
return None
return self.config_keyfile
def get_config_ipaddress(self):
@staticmethod
def get_config_ipaddress():
return cli.ipadress or ""
def _has_role(self, role_flag):
......@@ -299,6 +301,7 @@ class _ConfigSQL(object):
have_metadata_db = os.path.isfile(db_file)
self.db_configured = have_metadata_db
constants.EXTENSIONS_UPLOAD = [x.lstrip().rstrip().lower() for x in self.config_upload_formats.split(',')]
# pylint: disable=access-member-before-definition
logfile = logger.setup(self.config_logfile, self.config_log_level)
if logfile != self.config_logfile:
log.warning("Log path %s not valid, falling back to default", self.config_logfile)
......
......@@ -104,7 +104,7 @@ LDAP_AUTH_SIMPLE = 0
DEFAULT_MAIL_SERVER = "mail.example.org"
DEFAULT_PASSWORD = "admin123"
DEFAULT_PASSWORD = "admin123" # nosec # noqa
DEFAULT_PORT = 8083
env_CALIBRE_PORT = os.environ.get("CALIBRE_PORT", DEFAULT_PORT)
try:
......
......@@ -134,63 +134,71 @@ def send_registration_mail(e_mail, user_name, default_password, resend=False):
taskMessage=_(u"Registration e-mail for user: %(name)s", name=user_name),
text=txt
))
return
def check_send_to_kindle_without_converter(entry):
bookformats = list()
# no converter - only for mobi and pdf formats
for ele in iter(entry.data):
if ele.uncompressed_size < config.mail_size:
if 'MOBI' in ele.format:
bookformats.append({'format': 'Mobi',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Mobi')})
if 'PDF' in ele.format:
bookformats.append({'format': 'Pdf',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Pdf')})
if 'AZW' in ele.format:
bookformats.append({'format': 'Azw',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Azw')})
return bookformats
def check_send_to_kindle_with_converter(entry):
bookformats = list()
formats = list()
for ele in iter(entry.data):
if ele.uncompressed_size < config.mail_size:
formats.append(ele.format)
if 'MOBI' in formats:
bookformats.append({'format': 'Mobi',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Mobi')})
if 'AZW' in formats:
bookformats.append({'format': 'Azw',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Azw')})
if 'PDF' in formats:
bookformats.append({'format': 'Pdf',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Pdf')})
if 'EPUB' in formats and 'MOBI' not in formats:
bookformats.append({'format': 'Mobi',
'convert': 1,
'text': _('Convert %(orig)s to %(format)s and send to Kindle',
orig='Epub',
format='Mobi')})
if 'AZW3' in formats and not 'MOBI' in formats:
bookformats.append({'format': 'Mobi',
'convert': 2,
'text': _('Convert %(orig)s to %(format)s and send to Kindle',
orig='Azw3',
format='Mobi')})
return bookformats
def check_send_to_kindle(entry):
"""
returns all available book formats for sending to Kindle
"""
if len(entry.data):
bookformats = list()
if not config.config_converterpath:
# no converter - only for mobi and pdf formats
for ele in iter(entry.data):
if ele.uncompressed_size < config.mail_size:
if 'MOBI' in ele.format:
bookformats.append({'format': 'Mobi',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Mobi')})
if 'PDF' in ele.format:
bookformats.append({'format': 'Pdf',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Pdf')})
if 'AZW' in ele.format:
bookformats.append({'format': 'Azw',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Azw')})
book_formats = check_send_to_kindle_with_converter(entry)
else:
formats = list()
for ele in iter(entry.data):
if ele.uncompressed_size < config.mail_size:
formats.append(ele.format)
if 'MOBI' in formats:
bookformats.append({'format': 'Mobi',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Mobi')})
if 'AZW' in formats:
bookformats.append({'format': 'Azw',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Azw')})
if 'PDF' in formats:
bookformats.append({'format': 'Pdf',
'convert': 0,
'text': _('Send %(format)s to Kindle', format='Pdf')})
if config.config_converterpath:
if 'EPUB' in formats and 'MOBI' not in formats:
bookformats.append({'format': 'Mobi',
'convert':1,
'text': _('Convert %(orig)s to %(format)s and send to Kindle',
orig='Epub',
format='Mobi')})
if 'AZW3' in formats and not 'MOBI' in formats:
bookformats.append({'format': 'Mobi',
'convert': 2,
'text': _('Convert %(orig)s to %(format)s and send to Kindle',
orig='Azw3',
format='Mobi')})
return bookformats
book_formats = check_send_to_kindle_with_converter(entry)
return book_formats
else:
log.error(u'Cannot find book entry %d', entry.id)
return None
......@@ -742,7 +750,7 @@ def format_runtime(runtime):
# helper function to apply localize status information in tasklist entries
def render_task_status(tasklist):
renderedtasklist = list()
for num, user, added, task in tasklist:
for __, user, added, task in tasklist:
if user == current_user.nickname or current_user.role_admin():
ret = {}
if task.start_time:
......
......@@ -71,7 +71,7 @@ def get_valid_language_codes(locale, language_names, remainder=None):
languages = list()
if "" in language_names:
language_names.remove("")
for k, v in get_language_names(locale).items():
for k, __ in get_language_names(locale).items():
if k in language_names:
languages.append(k)
language_names.remove(k)
......
This diff is collapsed.
......@@ -35,7 +35,10 @@ from sqlalchemy.orm.exc import NoResultFound
from . import constants, logger, config, app, ub
from .oauth import OAuthBackend, backend_resultcode
try:
from .oauth import OAuthBackend, backend_resultcode
except NameError:
pass
oauth_check = {}
......
......@@ -137,7 +137,7 @@ class WebServer(object):
return sock, _readable_listen_address(*address)
@staticmethod
def _get_args_for_reloading(self):
"""Determine how the script was executed, and return the args needed
to execute it again in a new process.
......
......@@ -64,7 +64,7 @@ class SyncToken:
books_last_modified: Datetime representing the last modified book that the device knows about.
"""
SYNC_TOKEN_HEADER = "x-kobo-synctoken"
SYNC_TOKEN_HEADER = "x-kobo-synctoken" # nosec
VERSION = "1-1-0"
LAST_MODIFIED_ADDED_VERSION = "1-1-0"
MIN_VERSION = "1-0-0"
......@@ -91,7 +91,7 @@ class SyncToken:
def __init__(
self,
raw_kobo_store_token="",
raw_kobo_store_token="", # nosec
books_last_created=datetime.min,
books_last_modified=datetime.min,
archive_last_modified=datetime.min,
......@@ -110,7 +110,7 @@ class SyncToken:
@staticmethod
def from_headers(headers):
sync_token_header = headers.get(SyncToken.SYNC_TOKEN_HEADER, "")
if sync_token_header == "":
if sync_token_header == "": # nosec
return SyncToken()
# On the first sync from a Kobo device, we may receive the SyncToken
......
body.serieslist.grid-view div.container-fluid>div>div.col-sm-10:before{
display: none;
body.serieslist.grid-view div.container-fluid > div > div.col-sm-10:before{
display: none;
}
.cover .badge{
position: absolute;
top: 0;
left: 0;
color: #fff;
background-color: #cc7b19;
border-radius: 0;
padding: 0 8px;
box-shadow: 0 0 4px rgba(0,0,0,.6);
line-height: 24px;
position: absolute;
top: 0;
left: 0;
color: #fff;
background-color: #cc7b19;
border-radius: 0;
padding: 0 8px;
box-shadow: 0 0 4px rgba(0, 0, 0, .6);
line-height: 24px;
}
.cover{
box-shadow: 0 0 4px rgba(0,0,0,.6);
.cover {
box-shadow: 0 0 4px rgba(0, 0, 0, .6);
}
.cover .read{
padding: 0 0px;
line-height: 15px;
.cover .read {
padding: 0px 0px;
line-height: 15px;
}
......@@ -33,7 +33,6 @@ body {
position: relative;
cursor: pointer;
padding: 4px;
transition: all 0.2s ease;
}
......@@ -45,7 +44,7 @@ body {
#sidebar a.active,
#sidebar a.active img + span {
background-color: #45B29D;
background-color: #45b29d;
}
#sidebar li img {
......@@ -99,7 +98,7 @@ body {
background-color: #ccc;
}
#progress .bar-read {
#progress .bar-read {
color: #fff;
background-color: #45b29d;
}
......
......@@ -490,7 +490,6 @@ input:-moz-placeholder { color: #454545; }
position: fixed;
top: 50%;
left: 50%;
// width: 50%;
width: 630px;
height: auto;
z-index: 2000;
......@@ -593,7 +592,6 @@ input:-moz-placeholder { color: #454545; }
}
.md-content > .closer {
//font-size: 18px;
position: absolute;
right: 0;
top: 0;
......
.tooltip.bottom .tooltip-inner {
font-size: 13px;
font-family: Open Sans Semibold,Helvetica Neue,Helvetica,Arial,sans-serif;
font-family: Open Sans Semibold, Helvetica Neue, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
padding: 3px 10px;
......@@ -48,25 +48,25 @@ body {
body h2 {
font-weight: normal;
color:#444;
color: #444;
}
a, .danger,.book-remove, .editable-empty, .editable-empty:hover { color: #45b29d; }
a, .danger, .book-remove, .editable-empty, .editable-empty:hover { color: #45b29d; }
.book-remove:hover { color: #23527c; }
.btn-default a { color: #444; }
.btn-default a:hover {
color: #45b29d;
text-decoration: None;
color: #45b29d;
text-decoration: None;
}
.btn-default:hover {
color: #45b29d;
color: #45b29d;
}
.editable-click, a.editable-click, a.editable-click:hover { border-bottom: None; }
.editable-click, a.editable-click, a.editable-click:hover { border-bottom: None; }
.navigation .nav-head {
text-transform: uppercase;
......@@ -119,7 +119,7 @@ a, .danger,.book-remove, .editable-empty, .editable-empty:hover { color: #45b29d
max-height: 100%;
}
.container-fluid .discover{ margin-bottom: 50px; }
.container-fluid .discover { margin-bottom: 50px; }
.container-fluid .new-books { border-top: 1px solid #ccc; }
.container-fluid .new-books h2 { margin: 50px 0 0 0; }
.container-fluid .book {
......@@ -174,9 +174,10 @@ a, .danger,.book-remove, .editable-empty, .editable-empty:hover { color: #45b29d
.container-fluid .book .meta .rating { margin-top: 5px; }
.rating .glyphicon-star-empty { color: #444; }
.rating .glyphicon-star.good { color: #444; }
.rating-clear .glyphicon-remove { color: #333 }
.rating-clear .glyphicon-remove { color: #333; }
.container-fluid .author .author-hidden, .container-fluid .author .author-hidden-divider { display: none; }
.container-fluid .author .author-hidden,
.container-fluid .author .author-hidden-divider { display: none; }
.navbar-brand {
font-family: 'Grand Hotel', cursive;
......@@ -190,7 +191,7 @@ a, .danger,.book-remove, .editable-empty, .editable-empty:hover { color: #45b29d
border-top: 1px solid #ccc;
}
.more-stuff>li { margin-bottom: 10px; }
.more-stuff > li { margin-bottom: 10px; }
.navbar-collapse.in .navbar-nav { margin: 0; }
span.glyphicon.glyphicon-tags {
......@@ -211,17 +212,17 @@ span.glyphicon.glyphicon-tags {
box-shadow: 0 5px 8px -6px #777;
}
.navbar-default .navbar-toggle .icon-bar {background-color: #000; }
.navbar-default .navbar-toggle {border-color: #000; }
.navbar-default .navbar-toggle .icon-bar { background-color: #000; }
.navbar-default .navbar-toggle { border-color: #000; }
.cover { margin-bottom: 10px; }
.cover .badge{
position: absolute;
top: 2px;
left: 2px;
color: #000;
border-radius: 10px;
background-color: #fff;
position: absolute;
top: 2px;
left: 2px;
color: #000;
border-radius: 10px;
background-color: #fff;
}
.cover .read{
left: auto;
......@@ -231,14 +232,14 @@ span.glyphicon.glyphicon-tags {
display: inline-block;
padding: 2px;
}
.cover-height { max-height: 100px;}
.cover-height { max-height: 100px; }
.col-sm-2 a .cover-small {
margin: 5px;
max-height: 200px;
}
.btn-file {position: relative; overflow: hidden;}
.btn-file { position: relative; overflow: hidden; }
.btn-file input[type=file] {
position: absolute;
......@@ -256,22 +257,42 @@ span.glyphicon.glyphicon-tags {
display: block;
}
.btn-toolbar .btn,.discover .btn { margin-bottom: 5px; }
.button-link {color: #fff; }
.btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary{ background-color: #1C5484; }
.btn-primary.disabled, .btn-primary[disabled], fieldset[disabled] .btn-primary, .btn-primary.disabled:hover, .btn-primary[disabled]:hover, fieldset[disabled] .btn-primary:hover, .btn-primary.disabled:focus, .btn-primary[disabled]:focus, fieldset[disabled] .btn-primary:focus, .btn-primary.disabled:active, .btn-primary[disabled]:active, fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active { background-color: #89B9E2; }
.btn-toolbar>.btn+.btn, .btn-toolbar>.btn-group+.btn, .btn-toolbar>.btn+.btn-group, .btn-toolbar>.btn-group+.btn-group { margin-left: 0; }
.panel-body {background-color: #f5f5f5; }
.spinner {margin: 0 41%; }
.spinner2 {margin: 0 41%; }
.btn-toolbar .btn,
.discover .btn { margin-bottom: 5px; }
.button-link { color: #fff; }
.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active,
.btn-primary.active,
.open .dropdown-toggle.btn-primary { background-color: #1c5484; }
.btn-primary.disabled,
.btn-primary[disabled],
fieldset[disabled] .btn-primary,
.btn-primary.disabled:hover,
.btn-primary[disabled]:hover,
fieldset[disabled] .btn-primary:hover,
.btn-primary.disabled:focus,
.btn-primary[disabled]:focus,
fieldset[disabled] .btn-primary:focus, .btn-primary.disabled:active, .btn-primary[disabled]:active, fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active { background-color: #89B9E2; }
.btn-toolbar > .btn+.btn,
.btn-toolbar > .btn-group+.btn,
.btn-toolbar > .btn+.btn-group,
.btn-toolbar > .btn-group+.btn-group { margin-left: 0; }
.panel-body { background-color: #f5f5f5; }
.spinner { margin: 0 41%; }
.spinner2 { margin: 0 41%; }
.intend-form { margin-left:20px; }
table .bg-dark-danger {background-color: #d9534f; color: #fff; }
table .bg-dark-danger a {color: #fff; }
table .bg-dark-danger:hover {background-color: #c9302c; }
table .bg-primary:hover {background-color: #1C5484; }
table .bg-primary a {color: #fff; }
.block-label {display: block;}
.fake-input {position: absolute; pointer-events: none; top: 0; }
table .bg-dark-danger { background-color: #d9534f; color: #fff; }
table .bg-dark-danger a { color: #fff; }
table .bg-dark-danger:hover { background-color: #c9302c; }
table .bg-primary:hover { background-color: #1c5484; }
table .bg-primary a { color: #fff; }
.block-label { display: block; }
.fake-input { position: absolute; pointer-events: none; top: 0; }
input.pill { position: absolute; opacity: 0; }
......
......@@ -677,7 +677,7 @@ $(".navbar-collapse.collapse.in").before('<div class="sidebar-backdrop"></div>')
// Get rid of leading white space
recentlyAdded = $("#nav_new a:contains('Recently')").text().trim();
$("#nav_new a:contains('Recently')").contents().filter(function () {
return this.nodeType == 3
return this.nodeType === 3
}).each(function () {
this.textContent = this.textContent.replace(" Recently Added", recentlyAdded);
});
......
......@@ -88,7 +88,7 @@ $("#desc").click(function() {
// Find count of middle element
var count = $(".row:visible").length;
if (count > 20) {
middle = parseInt(count / 2) + (count % 2);
middle = parseInt(count / 2, 10) + (count % 2);
//var middle = parseInt(count / 2) + (count % 2);
// search for the middle of all visible elements
......@@ -135,7 +135,7 @@ $("#asc").click(function() {
// Find count of middle element
var count = $(".row:visible").length;
if (count > 20) {
var middle = parseInt(count / 2) + (count % 2);
var middle = parseInt(count / 2, 10) + (count % 2);
//var middle = parseInt(count / 2) + (count % 2);
// search for the middle of all visible elements
......
......@@ -38,10 +38,10 @@ $(document).on("change", "input[type=\"checkbox\"][data-control]", function () {
$(document).on("change", "select[data-control]", function() {
var $this = $(this);
var name = $this.data("control");
var showOrHide = parseInt($this.val());
var showOrHide = parseInt($this.val(), 10);
// var showOrHideLast = $("#" + name + " option:last").val()
for (var i = 0; i < $(this)[0].length; i++) {
var element = parseInt($(this)[0][i].value);
var element = parseInt($(this)[0][i].value, 10);
if (element === showOrHide) {
$("[data-related^=" + name + "][data-related*=-" + element + "]").show();
} else {
......
......@@ -16,6 +16,7 @@
*/
/* exported TableActions, RestrictionActions, EbookActions, responseHandler */
/* global getPath, ConfirmDialog */
var selections = [];
......
......@@ -12,7 +12,6 @@ class TaskUpload(CalibreTask):
def run(self, worker_thread):
"""Upload task doesn't have anything to do, it's simply a way to add information to the task list"""
pass
@property
def name(self):
......
......@@ -138,15 +138,15 @@ class UserBase:
mct = self.allowed_column_value or ""
return [t.strip() for t in mct.split(",")]
def get_view_property(self, page, property):
def get_view_property(self, page, prop):
if not self.view_settings.get(page):
return None
return self.view_settings[page].get(property)
return self.view_settings[page].get(prop)
def set_view_property(self, page, property, value):
def set_view_property(self, page, prop, value):
if not self.view_settings.get(page):
self.view_settings[page] = dict()
self.view_settings[page][property] = value
self.view_settings[page][prop] = value
try:
flag_modified(self, "view_settings")
except AttributeError:
......@@ -437,11 +437,8 @@ class RemoteAuthToken(Base):
return '<Token %r>' % self.id
# Migrate database to current version, has to be updated after every database change. Currently migration from
# everywhere to current should work. Migration is done by checking if relevant columns are existing, and than adding
# rows with SQL commands
def migrate_Database(session):
engine = session.bind
# Add missing tables during migration of database
def add_missing_tables(engine, session):
if not engine.dialect.has_table(engine.connect(), "book_read_link"):
ReadBook.__table__.create(bind=engine)
if not engine.dialect.has_table(engine.connect(), "bookmark"):
......@@ -459,6 +456,10 @@ def migrate_Database(session):
with engine.connect() as conn:
conn.execute("insert into registration (domain, allow) values('%.%',1)")
session.commit()
# migrate all settings missing in registration table
def migrate_registration_table(engine, session):
try:
session.query(exists().where(Registration.allow)).scalar()
session.commit()
......@@ -468,27 +469,29 @@ def migrate_Database(session):
conn.execute("update registration set 'allow' = 1")
session.commit()
try:
session.query(exists().where(RemoteAuthToken.token_type)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some columns are missing
with engine.connect() as conn:
conn.execute("ALTER TABLE remote_auth_token ADD column 'token_type' INTEGER DEFAULT 0")
conn.execute("update remote_auth_token set 'token_type' = 0")
session.commit()
# Handle table exists, but no content
cnt = session.query(Registration).count()
if not cnt:
with engine.connect() as conn:
conn.execute("insert into registration (domain, allow) values('%.%',1)")
session.commit()
except exc.OperationalError: # Database is not writeable
print('Settings database is not writeable. Exiting...')
sys.exit(2)
# Remove login capability of user Guest
def migrate_guest_password(engine, session):
try:
session.query(exists().where(ReadBook.read_status)).scalar()
except exc.OperationalError:
with engine.connect() as conn:
conn.execute("ALTER TABLE book_read_link ADD column 'read_status' INTEGER DEFAULT 0")
conn.execute("UPDATE book_read_link SET 'read_status' = 1 WHERE is_read")
conn.execute("ALTER TABLE book_read_link ADD column 'last_modified' DATETIME")
conn.execute("ALTER TABLE book_read_link ADD column 'last_time_started_reading' DATETIME")
conn.execute("ALTER TABLE book_read_link ADD column 'times_started_reading' INTEGER DEFAULT 0")
conn.execute("UPDATE user SET password='' where nickname = 'Guest' and password !=''")
session.commit()
test = session.query(ReadBook).filter(ReadBook.last_modified == None).all()
for book in test:
book.last_modified = datetime.datetime.utcnow()
session.commit()
except exc.OperationalError:
print('Settings database is not writeable. Exiting...')
sys.exit(2)
def migrate_shelfs(engine, session):
try:
session.query(exists().where(Shelf.uuid)).scalar()
except exc.OperationalError:
......@@ -504,22 +507,51 @@ def migrate_Database(session):
for book_shelf in session.query(BookShelf).all():
book_shelf.date_added = datetime.datetime.now()
session.commit()
try:
# Handle table exists, but no content
cnt = session.query(Registration).count()
if not cnt:
with engine.connect() as conn:
conn.execute("insert into registration (domain, allow) values('%.%',1)")
session.commit()
except exc.OperationalError: # Database is not writeable
print('Settings database is not writeable. Exiting...')
sys.exit(2)
try:
session.query(exists().where(BookShelf.order)).scalar()
except exc.OperationalError: # Database is not compatible, some columns are missing
with engine.connect() as conn:
conn.execute("ALTER TABLE book_shelf_link ADD column 'order' INTEGER DEFAULT 1")
session.commit()
def migrate_readBook(engine, session):
try:
session.query(exists().where(ReadBook.read_status)).scalar()
except exc.OperationalError:
with engine.connect() as conn:
conn.execute("ALTER TABLE book_read_link ADD column 'read_status' INTEGER DEFAULT 0")
conn.execute("UPDATE book_read_link SET 'read_status' = 1 WHERE is_read")
conn.execute("ALTER TABLE book_read_link ADD column 'last_modified' DATETIME")
conn.execute("ALTER TABLE book_read_link ADD column 'last_time_started_reading' DATETIME")
conn.execute("ALTER TABLE book_read_link ADD column 'times_started_reading' INTEGER DEFAULT 0")
session.commit()
test = session.query(ReadBook).filter(ReadBook.last_modified == None).all()
for book in test:
book.last_modified = datetime.datetime.utcnow()
session.commit()
def migrate_remoteAuthToken(engine, session):
try:
session.query(exists().where(RemoteAuthToken.token_type)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some columns are missing
with engine.connect() as conn:
conn.execute("ALTER TABLE remote_auth_token ADD column 'token_type' INTEGER DEFAULT 0")
conn.execute("update remote_auth_token set 'token_type' = 0")
session.commit()
# Migrate database to current version, has to be updated after every database change. Currently migration from
# everywhere to current should work. Migration is done by checking if relevant columns are existing, and than adding
# rows with SQL commands
def migrate_Database(session):
engine = session.bind
add_missing_tables(engine, session)
migrate_registration_table(engine, session)
migrate_readBook(engine, session)
migrate_remoteAuthToken(engine, session)
migrate_shelfs(engine, session)
try:
create = False
session.query(exists().where(User.sidebar_view)).scalar()
......@@ -578,8 +610,7 @@ def migrate_Database(session):
"locale VARCHAR(2),"
"sidebar_view INTEGER,"
"default_language VARCHAR(3),"
# "series_view VARCHAR(10),"
"view_settings VARCHAR,"
"view_settings VARCHAR,"
"UNIQUE (nickname),"
"UNIQUE (email))")
conn.execute("INSERT INTO user_id(id, nickname, email, role, password, kindle_mail,locale,"
......@@ -590,15 +621,7 @@ def migrate_Database(session):
conn.execute("DROP TABLE user")
conn.execute("ALTER TABLE user_id RENAME TO user")
session.commit()
# Remove login capability of user Guest
try:
with engine.connect() as conn:
conn.execute("UPDATE user SET password='' where nickname = 'Guest' and password !=''")
session.commit()
except exc.OperationalError:
print('Settings database is not writeable. Exiting...')
sys.exit(2)
migrate_guest_password(engine, session)
def clean_database(session):
......
......@@ -72,7 +72,7 @@ def load_user_from_request(request):
def load_user_from_auth_header(header_val):
if header_val.startswith('Basic '):
header_val = header_val.replace('Basic ', '', 1)
basic_username = basic_password = ''
basic_username = basic_password = '' # nosec
try:
header_val = base64.b64decode(header_val).decode('utf-8')
basic_username = header_val.split(':')[0]
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment