Commit 3ec000ad authored by bodybybuddha's avatar bodybybuddha

Merge branch 'master' of https://github.com/janeczku/calibre-web into ebookconvert-any

parents e160efbd a7a91ae5
...@@ -26,6 +26,7 @@ except ImportError: ...@@ -26,6 +26,7 @@ except ImportError:
pass pass
import web import web
import server import server
import random
try: try:
import unidecode import unidecode
...@@ -76,10 +77,27 @@ def make_mobi(book_id, calibrepath, user_id, kindle_mail): ...@@ -76,10 +77,27 @@ def make_mobi(book_id, calibrepath, user_id, kindle_mail):
def send_test_mail(kindle_mail, user_name): def send_test_mail(kindle_mail, user_name):
global_WorkerThread.add_email(_(u'Calibre-web test email'),None, None, ub.get_mail_settings(), global_WorkerThread.add_email(_(u'Calibre-Web test e-mail'),None, None, ub.get_mail_settings(),
kindle_mail, user_name, _(u"Test E-Mail")) kindle_mail, user_name, _(u"Test e-mail"))
return return
# Send registration email or password reset email, depending on parameter resend (False means welcome email)
def send_registration_mail(e_mail, user_name, default_password, resend=False):
text = "Hello %s!\r\n" % user_name
if not resend:
text += "Your new account at Calibre-Web has been created. Thanks for joining us!\r\n"
text += "Please log in to your account using the following informations:\r\n"
text += "User name: %s\n" % user_name
text += "Password: %s\r\n" % default_password
text += "Don't forget to change your password after first login.\r\n"
text += "Sincerely\r\n\r\n"
text += "Your Calibre-Web team"
global_WorkerThread.add_email(_(u'Get Started with Calibre-Web'),None, None, ub.get_mail_settings(),
e_mail, user_name, _(u"Registration e-mail for user: %s" % user_name),text)
return
# Files are processed in the following order/priority: # Files are processed in the following order/priority:
# 1: If Mobi file is exisiting, it's directly send to kindle email, # 1: If Mobi file is exisiting, it's directly send to kindle email,
# 2: If Epub file is exisiting, it's converted and send to kindle email # 2: If Epub file is exisiting, it's converted and send to kindle email
...@@ -99,7 +117,7 @@ def send_mail(book_id, kindle_mail, calibrepath, user_id): ...@@ -99,7 +117,7 @@ def send_mail(book_id, kindle_mail, calibrepath, user_id):
formats["pdf"] = entry.name + ".pdf" formats["pdf"] = entry.name + ".pdf"
if len(formats) == 0: if len(formats) == 0:
return _(u"Could not find any formats suitable for sending by email") return _(u"Could not find any formats suitable for sending by e-mail")
if 'mobi' in formats: if 'mobi' in formats:
result = formats['mobi'] result = formats['mobi']
...@@ -109,7 +127,7 @@ def send_mail(book_id, kindle_mail, calibrepath, user_id): ...@@ -109,7 +127,7 @@ def send_mail(book_id, kindle_mail, calibrepath, user_id):
elif 'pdf' in formats: elif 'pdf' in formats:
result = formats['pdf'] # worker.get_attachment() result = formats['pdf'] # worker.get_attachment()
else: else:
return _(u"Could not find any formats suitable for sending by email") return _(u"Could not find any formats suitable for sending by e-mail")
if result: if result:
global_WorkerThread.add_email(_(u"Send to Kindle"), book.path, result, ub.get_mail_settings(), global_WorkerThread.add_email(_(u"Send to Kindle"), book.path, result, ub.get_mail_settings(),
kindle_mail, user_id, _(u"E-Mail: %s" % book.title)) kindle_mail, user_id, _(u"E-Mail: %s" % book.title))
...@@ -271,6 +289,11 @@ def delete_book_gdrive(book, book_format): ...@@ -271,6 +289,11 @@ def delete_book_gdrive(book, book_format):
error =_(u'Book path %s not found on Google Drive' % book.path) # file not found error =_(u'Book path %s not found on Google Drive' % book.path) # file not found
return error return error
def generate_random_password():
s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&*()?"
passlen = 8
return "".join(random.sample(s,passlen ))
################################## External interface ################################## External interface
def update_dir_stucture(book_id, calibrepath): def update_dir_stucture(book_id, calibrepath):
......
...@@ -69,7 +69,7 @@ class server: ...@@ -69,7 +69,7 @@ class server:
self.wsgiserver.close(True) self.wsgiserver.close(True)
if self.restart == True: if self.restart == True:
web.app.logger.info("Performing restart of Calibre-web") web.app.logger.info("Performing restart of Calibre-Web")
web.helper.global_WorkerThread.stop() web.helper.global_WorkerThread.stop()
if os.name == 'nt': if os.name == 'nt':
arguments = ["\"" + sys.executable + "\""] arguments = ["\"" + sys.executable + "\""]
...@@ -79,7 +79,7 @@ class server: ...@@ -79,7 +79,7 @@ class server:
else: else:
os.execl(sys.executable, sys.executable, *sys.argv) os.execl(sys.executable, sys.executable, *sys.argv)
else: else:
web.app.logger.info("Performing shutdown of Calibre-web") web.app.logger.info("Performing shutdown of Calibre-Web")
web.helper.global_WorkerThread.stop() web.helper.global_WorkerThread.stop()
sys.exit(0) sys.exit(0)
......
This diff is collapsed.
...@@ -94,7 +94,13 @@ input.pill:not(:checked) + label .glyphicon { ...@@ -94,7 +94,13 @@ input.pill:not(:checked) + label .glyphicon {
.upload-format-input-text {display: initial;} .upload-format-input-text {display: initial;}
#btn-upload-format {display: none;} #btn-upload-format {display: none;}
.upload-format-input-text {display: initial;} .upload-cover-input-text {display: initial;}
#btn-upload-format {display: none;} #btn-upload-cover {display: none;}
.panel-title > a { text-decoration: none;} .panel-title > a { text-decoration: none;}
.editable-buttons { display:inline-block; margin-left: 7px ;}
.editable-input { display:inline-block;}
.editable-cancel { margin-bottom: 0px !important; margin-left: 7px !important;}
.editable-submit { margin-bottom: 0px !important;}
...@@ -246,3 +246,11 @@ $("#btn-upload-format").on("change", function () { ...@@ -246,3 +246,11 @@ $("#btn-upload-format").on("change", function () {
} // Remove c:\fake at beginning from localhost chrome } // Remove c:\fake at beginning from localhost chrome
$("#upload-format").html(filename); $("#upload-format").html(filename);
}); });
$("#btn-upload-cover").on("change", function () {
var filename = $(this).val();
if (filename.substring(3, 11) === "fakepath") {
filename = filename.substring(12);
} // Remove c:\fake at beginning from localhost chrome
$("#upload-cover").html(filename);
});
This diff is collapsed.
/*
* bootstrap-table - v1.12.1 - 2018-03-12
* https://github.com/wenzhixin/bootstrap-table
* Copyright (c) 2018 zhixin wen
* Licensed MIT License
*/
!function(a){"use strict";a.extend(a.fn.bootstrapTable.defaults,{editable:!0,onEditableInit:function(){return!1},onEditableSave:function(){return!1},onEditableShown:function(){return!1},onEditableHidden:function(){return!1}}),a.extend(a.fn.bootstrapTable.Constructor.EVENTS,{"editable-init.bs.table":"onEditableInit","editable-save.bs.table":"onEditableSave","editable-shown.bs.table":"onEditableShown","editable-hidden.bs.table":"onEditableHidden"});var b=a.fn.bootstrapTable.Constructor,c=b.prototype.initTable,d=b.prototype.initBody;b.prototype.initTable=function(){var b=this;c.apply(this,Array.prototype.slice.apply(arguments)),this.options.editable&&a.each(this.columns,function(c,d){if(d.editable){var e={},f=[],g="editable-",h=function(a,b){var c=a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()});if(c.slice(0,g.length)==g){var d=c.replace(g,"data-");e[d]=b}};a.each(b.options,h),d.formatter=d.formatter||function(a){return a},d._formatter=d._formatter?d._formatter:d.formatter,d.formatter=function(c,g,i){var j=d._formatter?d._formatter(c,g,i):c;a.each(d,h),a.each(e,function(a,b){f.push(" "+a+'="'+b+'"')});var k=!1;return d.editable.hasOwnProperty("noeditFormatter")&&(k=d.editable.noeditFormatter(c,g,i)),k===!1?['<a href="javascript:void(0)"',' data-name="'+d.field+'"',' data-pk="'+g[b.options.idField]+'"',' data-value="'+j+'"',f.join(""),"></a>"].join(""):k}}})},b.prototype.initBody=function(){var b=this;d.apply(this,Array.prototype.slice.apply(arguments)),this.options.editable&&(a.each(this.columns,function(c,d){d.editable&&(b.$body.find('a[data-name="'+d.field+'"]').editable(d.editable).off("save").on("save",function(c,e){var f=b.getData(),g=a(this).parents("tr[data-index]").data("index"),h=f[g],i=h[d.field];a(this).data("value",e.submitValue),h[d.field]=e.submitValue,b.trigger("editable-save",d.field,h,i,a(this)),b.resetFooter()}),b.$body.find('a[data-name="'+d.field+'"]').editable(d.editable).off("shown").on("shown",function(c,e){var f=b.getData(),g=a(this).parents("tr[data-index]").data("index"),h=f[g];b.trigger("editable-shown",d.field,h,a(this),e)}),b.$body.find('a[data-name="'+d.field+'"]').editable(d.editable).off("hidden").on("hidden",function(c,e){var f=b.getData(),g=a(this).parents("tr[data-index]").data("index"),h=f[g];b.trigger("editable-hidden",d.field,h,a(this),e)}))}),this.trigger("editable-init"))}}(jQuery);
\ No newline at end of file
$(function() {
$("#domain_submit").click(function(event){
event.preventDefault();
$("#domain_add").ajaxForm();
$(this).closest("form").submit();
$.ajax({
method:"get",
url: window.location.pathname + "/../../ajax/domainlist",
async: true,
timeout: 900,
success:function(data){
$('#domain-table').bootstrapTable("load", data);
}
});
});
$('#domain-table').bootstrapTable({
formatNoMatches: function () {
return '';
},
striped: false
});
$("#btndeletedomain").click(function() {
//get data-id attribute of the clicked element
var domainId = $(this).data('domainId');
$.ajax({
method:"post",
url: window.location.pathname + "/../../ajax/deletedomain",
data: {"domainid":domainId}
});
$('#DeleteDomain').modal('hide');
$.ajax({
method:"get",
url: window.location.pathname + "/../../ajax/domainlist",
async: true,
timeout: 900,
success:function(data){
$('#domain-table').bootstrapTable("load", data);
}
});
});
//triggered when modal is about to be shown
$('#DeleteDomain').on('show.bs.modal', function(e) {
//get data-id attribute of the clicked element and store in button
var domainId = $(e.relatedTarget).data('domain-id');
$(e.currentTarget).find("#btndeletedomain").data('domainId',domainId);
});
});
function TableActions (value, row, index) {
return [
'<a class="danger remove" data-toggle="modal" data-target="#DeleteDomain" data-domain-id="'+row.id+'" title="Remove">',
'<i class="glyphicon glyphicon-trash"></i>',
'</a>'
].join('');
}
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
{% block body %} {% block body %}
<div class="discover"> <div class="discover">
<h2>{{_('User list')}}</h2> <h2>{{_('User list')}}</h2>
<div id="divLoading"></div>
<table class="table table-striped" id="table_user"> <table class="table table-striped" id="table_user">
<tr> <tr>
<th>{{_('Nickname')}}</th> <th>{{_('Nickname')}}</th>
...@@ -13,7 +12,6 @@ ...@@ -13,7 +12,6 @@
<th>{{_('Download')}}</th> <th>{{_('Download')}}</th>
<th>{{_('Upload')}}</th> <th>{{_('Upload')}}</th>
<th>{{_('Edit')}}</th> <th>{{_('Edit')}}</th>
<th>{{_('Passwd')}}</th>
</tr> </tr>
{% for user in content %} {% for user in content %}
{% if not user.role_anonymous() or config.config_anonbrowse %} {% if not user.role_anonymous() or config.config_anonbrowse %}
...@@ -26,20 +24,18 @@ ...@@ -26,20 +24,18 @@
<td>{% if user.role_download() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> <td>{% if user.role_download() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td>
<td>{% if user.role_upload() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> <td>{% if user.role_upload() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td>
<td>{% if user.role_edit() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> <td>{% if user.role_edit() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td>
<td>{% if user.role_passwd() %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td>
</tr> </tr>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</table> </table>
<div class="btn btn-default" id="admin_new_user"><a href="{{url_for('new_user')}}">{{_('Add new user')}}</a></div> <div class="btn btn-default" id="admin_new_user"><a href="{{url_for('new_user')}}">{{_('Add new user')}}</a></div>
<h2>{{_('SMTP mail settings')}}</h2> <h2>{{_('SMTP e-mail server settings')}}</h2>
<table class="table table-striped" id="table_email"> <table class="table table-striped" id="table_email">
<tr> <tr>
<th>{{_('SMTP hostname')}}</th> <th>{{_('SMTP hostname')}}</th>
<th>{{_('SMTP port')}}</th> <th>{{_('SMTP port')}}</th>
<th>{{_('SSL')}}</th> <th>{{_('SSL')}}</th>
<th>{{_('SMTP login')}}</th> <th>{{_('SMTP login')}}</th>
<th>{{_('SMTP password')}}</th>
<th>{{_('From mail')}}</th> <th>{{_('From mail')}}</th>
</tr> </tr>
<tr> <tr>
...@@ -47,44 +43,56 @@ ...@@ -47,44 +43,56 @@
<td>{{email.mail_port}}</td> <td>{{email.mail_port}}</td>
<td>{% if email.mail_use_ssl %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> <td>{% if email.mail_use_ssl %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td>
<td>{{email.mail_login}}</td> <td>{{email.mail_login}}</td>
<td>********</td>
<td>{{email.mail_from}}</td> <td>{{email.mail_from}}</td>
</table> </table>
<div class="btn btn-default" id="admin_edit_email"><a href="{{url_for('edit_mailsettings')}}">{{_('Change SMTP settings')}}</a></div> <div class="btn btn-default" id="admin_edit_email"><a href="{{url_for('edit_mailsettings')}}">{{_('Change SMTP settings')}}</a></div>
<div id="container">
<h2>{{_('Configuration')}}</h2> <h2>{{_('Configuration')}}</h2>
<table class="table table-striped" id="table_configuration"> <div class="col-xs-12 col-sm-6">
<tr> <div class="Row">
<th>{{_('Calibre DB dir')}}</th> <div class="col-xs-6 col-sm-6">{{_('Calibre DB dir')}}</div>
<th>{{_('Log Level')}}</th> <div class="col-xs-6 col-sm-6">{{config.config_calibre_dir}}</div>
<th>{{_('Port')}}</th> </div>
<th>{{_('Books per page')}}</th> <div class="Row">
<th>{{_('Uploading')}}</th> <div class="col-xs-6 col-sm-6">{{_('Log Level')}}</div>
<th>{{_('Public registration')}}</th> <div class="col-xs-6 col-sm-6">{{config.get_Log_Level()}}</div>
<th>{{_('Anonymous browsing')}}</th> </div>
<th>{{_('Remote Login')}}</th> <div class="Row">
</tr> <div class="col-xs-6 col-sm-6">{{_('Port')}}</div>
<tr> <div class="col-xs-6 col-sm-6">{{config.config_port}}</div>
<td>{{config.config_calibre_dir}}</td> </div>
<td>{{config.get_Log_Level()}}</td> </div>
<td>{{config.config_port}}</td> <div class="col-xs-12 col-sm-6">
<td>{{config.config_books_per_page}}</td> <div class="Row">
<td>{% if config.config_uploading %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> <div class="col-xs-6 col-sm-7">{{_('Books per page')}}</div>
<td>{% if config.config_public_reg %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> <div class="col-xs-6 col-sm-5">{{config.config_books_per_page}}</div>
<td>{% if config.config_anonbrowse %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> </div>
<td>{% if config.config_remote_login %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</td> <div class="Row">
</table> <div class="col-xs-6 col-sm-7">{{_('Uploading')}}</div>
<div class="col-xs-6 col-sm-5">{% if config.config_uploading %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</div>
</div>
<div class="Row">
<div class="col-xs-6 col-sm-7">{{_('Public registration')}}</div>
<div class="col-xs-6 col-sm-5">{% if config.config_public_reg %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</div>
</div>
<div class="Row">
<div class="col-xs-6 col-sm-7">{{_('Remote Login')}}</div>
<div class="col-xs-6 col-sm-5">{% if config.config_remote_login %}<span class="glyphicon glyphicon-ok"></span>{% else %}<span class="glyphicon glyphicon-remove"></span>{% endif %}</div>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-12">
<p></p>
<div class="btn btn-default"><a href="{{url_for('configuration')}}">{{_('Basic Configuration')}}</a></div> <div class="btn btn-default"><a href="{{url_for('configuration')}}">{{_('Basic Configuration')}}</a></div>
<div class="btn btn-default"><a href="{{url_for('view_configuration')}}">{{_('UI Configuration')}}</a></div> <div class="btn btn-default"><a href="{{url_for('view_configuration')}}">{{_('UI Configuration')}}</a></div>
</div>
<h2>{{_('Administration')}}</h2> <h2>{{_('Administration')}}</h2>
<div>{{_('Current commit timestamp')}}: <span>{{commit}} </span></div> <div>{{_('Current commit timestamp')}}: <span>{{commit}} </span></div>
<div class="hidden" id="update_info">{{_('Newest commit timestamp')}}: <span></span></div> <div class="hidden" id="update_info">{{_('Newest commit timestamp')}}: <span></span></div>
<p></p> <p></p>
<div class="btn btn-default" id="restart_database">{{_('Reconnect to Calibre DB')}}</div> <div class="btn btn-default" id="restart_database">{{_('Reconnect to Calibre DB')}}</div>
<div class="btn btn-default" data-toggle="modal" data-target="#RestartDialog">{{_('Restart Calibre-web')}}</div> <div class="btn btn-default" data-toggle="modal" data-target="#RestartDialog">{{_('Restart Calibre-Web')}}</div>
<div class="btn btn-default" data-toggle="modal" data-target="#ShutdownDialog">{{_('Stop Calibre-web')}}</div> <div class="btn btn-default" data-toggle="modal" data-target="#ShutdownDialog">{{_('Stop Calibre-Web')}}</div>
<div class="btn btn-default" id="check_for_update">{{_('Check for update')}}</div> <div class="btn btn-default" id="check_for_update">{{_('Check for update')}}</div>
<div class="btn btn-default hidden" id="perform_update" data-toggle="modal" data-target="#UpdateprogressDialog">{{_('Perform Update')}}</div> <div class="btn btn-default hidden" id="perform_update" data-toggle="modal" data-target="#UpdateprogressDialog">{{_('Perform Update')}}</div>
</div> </div>
...@@ -95,7 +103,7 @@ ...@@ -95,7 +103,7 @@
<div class="modal-content"> <div class="modal-content">
<div class="modal-header bg-info"></div> <div class="modal-header bg-info"></div>
<div class="modal-body text-center"> <div class="modal-body text-center">
<p>{{_('Do you really want to restart Calibre-web?')}}</p> <p>{{_('Do you really want to restart Calibre-Web?')}}</p>
<div id="spinner" class="spinner" style="display:none;"> <div id="spinner" class="spinner" style="display:none;">
<img id="img-spinner" src="/static/css/images/loading-icon.gif"/> <img id="img-spinner" src="/static/css/images/loading-icon.gif"/>
</div> </div>
...@@ -113,7 +121,7 @@ ...@@ -113,7 +121,7 @@
<div class="modal-header bg-info"> <div class="modal-header bg-info">
</div> </div>
<div class="modal-body text-center"> <div class="modal-body text-center">
<p>{{_('Do you really want to stop Calibre-web?')}}</p> <p>{{_('Do you really want to stop Calibre-Web?')}}</p>
<button type="button" class="btn btn-default" id="shutdown" data-dismiss="modal">{{_('Ok')}}</button> <button type="button" class="btn btn-default" id="shutdown" data-dismiss="modal">{{_('Ok')}}</button>
<button type="button" class="btn btn-default" data-dismiss="modal">{{_('Back')}}</button> <button type="button" class="btn btn-default" data-dismiss="modal">{{_('Back')}}</button>
</div> </div>
......
...@@ -60,7 +60,11 @@ ...@@ -60,7 +60,11 @@
<label for="cover_url">{{_('Cover URL (jpg, cover is downloaded and stored in database, field is afterwards empty again)')}}</label> <label for="cover_url">{{_('Cover URL (jpg, cover is downloaded and stored in database, field is afterwards empty again)')}}</label>
<input type="text" class="form-control" name="cover_url" id="cover_url" value=""> <input type="text" class="form-control" name="cover_url" id="cover_url" value="">
</div> </div>
<div class="form-group" aria-label="Upload cover from local drive">
<label class="btn btn-default btn-file" for="btn-upload-cover">{{ _('Upload Cover from local drive') }}</label>
<div class="upload-cover-input-text" id="upload-cover"></div>
<input id="btn-upload-cover" name="btn-upload-cover" type="file">
</div>
<div class="form-group"> <div class="form-group">
<label for="pubdate">{{_('Publishing date')}}</label> <label for="pubdate">{{_('Publishing date')}}</label>
<div style="position: relative"> <div style="position: relative">
...@@ -70,7 +74,7 @@ ...@@ -70,7 +74,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="languages">{{_('Language')}}</label> <label for="languages">{{_('Language')}}</label>
<input type="text" class="form-control typeahead" name="languages" id="languages" value="{% for language in book.languages %}{{language.language_name.strip()}}, {% endfor %}"> <input type="text" class="form-control typeahead" name="languages" id="languages" value="{% for language in book.languages %}{{language.language_name.strip()}}{% endfor %}">
</div> </div>
{% if cc|length > 0 %} {% if cc|length > 0 %}
...@@ -170,7 +174,7 @@ ...@@ -170,7 +174,7 @@
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header bg-danger text-center"> <div class="modal-header bg-danger text-center">
<span>{{_('Are really you sure?')}}</span> <span>{{_('Are you really sure?')}}</span>
</div> </div>
<div class="modal-body text-center"> <div class="modal-body text-center">
<span>{{_('Book will be deleted from Calibre database')}}</span> <span>{{_('Book will be deleted from Calibre database')}}</span>
...@@ -255,7 +259,7 @@ ...@@ -255,7 +259,7 @@
var i18nMsg = { var i18nMsg = {
'loading': {{_('Loading...')|safe|tojson}}, 'loading': {{_('Loading...')|safe|tojson}},
'search_error': {{_('Search error!')|safe|tojson}}, 'search_error': {{_('Search error!')|safe|tojson}},
'no_result': {{_('No Result! Please try anonther keyword.')|safe|tojson}}, 'no_result': {{_('No Result(s) found! Please try aonther keyword.')|safe|tojson}},
'author': {{_('Author')|safe|tojson}}, 'author': {{_('Author')|safe|tojson}},
'publisher': {{_('Publisher')|safe|tojson}}, 'publisher': {{_('Publisher')|safe|tojson}},
'description': {{_('Description')|safe|tojson}}, 'description': {{_('Description')|safe|tojson}},
......
{% extends "layout.html" %} {% extends "layout.html" %}
{% block header %}
<link href="{{ url_for('static', filename='css/libs/bootstrap-table.min.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='css/libs/bootstrap-editable.css') }}" rel="stylesheet">
{% endblock %}
{% block body %} {% block body %}
<div class="discover"> <div class="discover">
<h1>{{title}}</h1> <h1>{{title}}</h1>
...@@ -35,6 +39,52 @@ ...@@ -35,6 +39,52 @@
<button type="submit" name="test" value="test" class="btn btn-default">{{_('Save settings and send Test E-Mail')}}</button> <button type="submit" name="test" value="test" class="btn btn-default">{{_('Save settings and send Test E-Mail')}}</button>
<a href="{{ url_for('admin') }}" id="back" class="btn btn-default">{{_('Back')}}</a> <a href="{{ url_for('admin') }}" id="back" class="btn btn-default">{{_('Back')}}</a>
</form> </form>
{% if g.allow_registration %}
<h2>{{_('Allowed domains for registering')}}</h2>
<table class="table table-no-bordered" id="domain-table" data-url="{{url_for('list_domain')}}" data-id-field="id" data-show-header="false" data-editable-mode="inline">
<thead>
<tr>
<th data-field="domain" id="domain" data-editable-type="text" data-editable-url="{{ url_for('edit_domain')}}" data-editable="true" data-editable-title="{{_('Enter domainname')}}"></th>
<th data-field="id" id="id" data-visible="false"></th>
<th data-align="right" data-formatter="TableActions"></th>
</tr>
</thead>
</table>
<form id="domain_add" action="{{ url_for('add_domain')}}" method="POST">
<div class="form-group required">
<label for="domainname">{{_('Add Domain')}}</label>
<input type="text" class="form-control" name="domainname" id="domainname" >
</div>
<button id="domain_submit" class="btn btn-default">{{_('Add')}}</button>
</form>
{% endif %}
</div>
{% endblock %}
{% block modal %}
{% if g.allow_registration %}
<div id="DeleteDomain" class="modal fade" role="dialog">
<div class="modal-dialog modal-sm">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header bg-danger">
</div>
<div class="modal-body text-center">
<p>{{_('Do you really want to delete this domain rule?')}}</p>
<button type="button" class="btn btn-danger" id="btndeletedomain" >{{_('Delete')}}</button>
<!--a href="{{ url_for('delete_domain')}}" class="btn btn-danger">{{_('Delete')}}</a-->
<button type="button" class="btn btn-default" data-dismiss="modal">{{_('Back')}}</button>
</div>
</div>
</div>
</div> </div>
{% endif %}
{% endblock %} {% endblock %}
{% block js %}
{% if g.allow_registration %}
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table-editable.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-editable.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/table.js') }}"></script>
{% endif %}
{% endblock %}
...@@ -124,7 +124,7 @@ ...@@ -124,7 +124,7 @@
{% if g.user.show_sorted() %} {% if g.user.show_sorted() %}
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-sort-by-attributes"></span> {{_('Sorted Books')}} <span class="glyphicon glyphicon-sort-by-attributes"></span>{{_('Sorted Books')}}
<span class="caret"></span> <span class="caret"></span>
</a> </a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
...@@ -136,44 +136,44 @@ ...@@ -136,44 +136,44 @@
</li> </li>
{%endif%} {%endif%}
{% if g.user.show_hot_books() %} {% if g.user.show_hot_books() %}
<li id="nav_hot" {% if page == 'hot' %}class="active"{% endif %}><a href="{{url_for('hot_books')}}"><span class="glyphicon glyphicon-fire"></span> {{_('Hot Books')}}</a></li> <li id="nav_hot" {% if page == 'hot' %}class="active"{% endif %}><a href="{{url_for('hot_books')}}"><span class="glyphicon glyphicon-fire"></span>{{_('Hot Books')}}</a></li>
{%endif%} {%endif%}
{% if g.user.show_best_rated_books() %} {% if g.user.show_best_rated_books() %}
<li {% if page == 'rated' %}class="active"{% endif %}><a href="{{url_for('best_rated_books')}}"><span class="glyphicon glyphicon-star"></span> {{_('Best rated Books')}}</a></li> <li {% if page == 'rated' %}class="active"{% endif %}><a href="{{url_for('best_rated_books')}}"><span class="glyphicon glyphicon-star"></span>{{_('Best rated Books')}}</a></li>
{%endif%} {%endif%}
{% if g.user.show_read_and_unread() %} {% if g.user.show_read_and_unread() %}
{% if not g.user.is_anonymous %} {% if not g.user.is_anonymous %}
<li {% if page == 'read' %}class="active"{% endif %}><a href="{{url_for('read_books')}}"><span class="glyphicon glyphicon-eye-open"></span> {{_('Read Books')}}</a></li> <li {% if page == 'read' %}class="active"{% endif %}><a href="{{url_for('read_books')}}"><span class="glyphicon glyphicon-eye-open"></span>{{_('Read Books')}}</a></li>
{%endif%} {%endif%}
<li {% if page == 'read' %}class="active"{% endif %}><a href="{{url_for('unread_books')}}"><span class="glyphicon glyphicon-eye-close"></span> {{_('Unread Books')}}</a></li> <li {% if page == 'read' %}class="active"{% endif %}><a href="{{url_for('unread_books')}}"><span class="glyphicon glyphicon-eye-close"></span>{{_('Unread Books')}}</a></li>
{%endif%} {%endif%}
{% if g.user.show_random_books() %} {% if g.user.show_random_books() %}
<li id="nav_rand" {% if page == 'discover' %}class="active"{% endif %}><a href="{{url_for('discover')}}"><span class="glyphicon glyphicon-random"></span> {{_('Discover')}}</a></li> <li id="nav_rand" {% if page == 'discover' %}class="active"{% endif %}><a href="{{url_for('discover')}}"><span class="glyphicon glyphicon-random"></span>{{_('Discover')}}</a></li>
{%endif%} {%endif%}
{% if g.user.show_category() %} {% if g.user.show_category() %}
<li id="nav_cat" {% if page == 'discover' %}class="category"{% endif %}><a href="{{url_for('category_list')}}"><span class="glyphicon glyphicon-inbox"></span> {{_('Categories')}}</a></li> <li id="nav_cat" {% if page == 'discover' %}class="category"{% endif %}><a href="{{url_for('category_list')}}"><span class="glyphicon glyphicon-inbox"></span>{{_('Categories')}}</a></li>
{%endif%} {%endif%}
{% if g.user.show_series() %} {% if g.user.show_series() %}
<li id="nav_serie" {% if page == 'series' %}class="active"{% endif %}><a href="{{url_for('series_list')}}"><span class="glyphicon glyphicon-bookmark"></span> {{_('Series')}}</a></li> <li id="nav_serie" {% if page == 'series' %}class="active"{% endif %}><a href="{{url_for('series_list')}}"><span class="glyphicon glyphicon-bookmark"></span>{{_('Series')}}</a></li>
{%endif%} {%endif%}
{% if g.user.show_author() %} {% if g.user.show_author() %}
<li id="nav_author" {% if page == 'author' %}class="active"{% endif %}><a href="{{url_for('author_list')}}"><span class="glyphicon glyphicon-user"></span> {{_('Authors')}}</a></li> <li id="nav_author" {% if page == 'author' %}class="active"{% endif %}><a href="{{url_for('author_list')}}"><span class="glyphicon glyphicon-user"></span>{{_('Authors')}}</a></li>
{%endif%} {%endif%}
{% if g.user.filter_language() == 'all' and g.user.show_language() %} {% if g.user.filter_language() == 'all' and g.user.show_language() %}
<li id="nav_lang" {% if page == 'language' %}class="active"{% endif %}><a href="{{url_for('language_overview')}}"><span class="glyphicon glyphicon-flag"></span> {{_('Languages')}} </a></li> <li id="nav_lang" {% if page == 'language' %}class="active"{% endif %}><a href="{{url_for('language_overview')}}"><span class="glyphicon glyphicon-flag"></span>{{_('Languages')}} </a></li>
{%endif%} {%endif%}
{% if g.user.is_authenticated or g.user.is_anonymous %} {% if g.user.is_authenticated or g.user.is_anonymous %}
<li class="nav-head hidden-xs">{{_('Public Shelves')}}</li> <li class="nav-head hidden-xs">{{_('Public Shelves')}}</li>
{% for shelf in g.public_shelfes %} {% for shelf in g.public_shelfes %}
<li><a href="{{url_for('show_shelf', shelf_id=shelf.id)}}"><span class="glyphicon glyphicon-list"></span> {{shelf.name}}</a></li> <li><a href="{{url_for('show_shelf', shelf_id=shelf.id)}}"><span class="glyphicon glyphicon-list"></span>{{shelf.name}}</a></li>
{% endfor %} {% endfor %}
<li class="nav-head hidden-xs">{{_('Your Shelves')}}</li> <li class="nav-head hidden-xs">{{_('Your Shelves')}}</li>
{% for shelf in g.user.shelf %} {% for shelf in g.user.shelf %}
<li><a href="{{url_for('show_shelf', shelf_id=shelf.id)}}"><span class="glyphicon glyphicon-list"></span> {{shelf.name}}</a></li> <li><a href="{{url_for('show_shelf', shelf_id=shelf.id)}}"><span class="glyphicon glyphicon-list"></span>{{shelf.name}}</a></li>
{% endfor %} {% endfor %}
{% if not g.user.is_anonymous %} {% if not g.user.is_anonymous %}
<li id="nav_createshelf" class="create-shelf"><a href="{{url_for('create_shelf')}}">{{_('Create a Shelf')}}</a></li> <li id="nav_createshelf" class="create-shelf"><a href="{{url_for('create_shelf')}}">{{_('Create a Shelf')}}</a></li>
<li id="nav_about" {% if page == 'stat' %}class="active"{% endif %}><a href="{{url_for('stats')}}"><span class="glyphicon glyphicon-info-sign"></span> {{_('About')}}</a></li> <li id="nav_about" {% if page == 'stat' %}class="active"{% endif %}><a href="{{url_for('stats')}}"><span class="glyphicon glyphicon-info-sign"></span>{{_('About')}}</a></li>
{% endif %} {% endif %}
{% endif %} {% endif %}
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> <OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<LongName>{{instance}}</LongName> <LongName>{{instance}}</LongName>
<ShortName>{{instance}}</ShortName> <ShortName>{{instance}}</ShortName>
<Description>{{_('Calibre Web ebook catalog')}}</Description> <Description>{{_('Calibre-Web ebook catalog')}}</Description>
<Developer>Janeczku</Developer> <Developer>Janeczku</Developer>
<Contact>https://github.com/janeczku/calibre-web</Contact> <Contact>https://github.com/janeczku/calibre-web</Contact>
<Url type="text/html" <Url type="text/html"
......
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
<label for="nickname">{{_('Username')}}</label> <label for="nickname">{{_('Username')}}</label>
<input type="text" class="form-control" id="nickname" name="nickname" placeholder="{{_('Choose a username')}}" required> <input type="text" class="form-control" id="nickname" name="nickname" placeholder="{{_('Choose a username')}}" required>
</div> </div>
<div class="form-group required"> <!--div class="form-group required">
<label for="password">{{_('Password')}}</label> <label for="password">{{_('Password')}}</label>
<input type="password" class="form-control" id="password" name="password" placeholder="{{_('Choose a password')}}" required> <input type="password" class="form-control" id="password" name="password" placeholder="{{_('Choose a password')}}" required>
</div> </div-->
<div class="form-group required"> <div class="form-group required">
<label for="email">{{_('Email address')}}</label> <label for="email">{{_('Email address')}}</label>
<input type="email" class="form-control" id="email" name="email" placeholder="{{_('Your email address')}}" required> <input type="email" class="form-control" id="email" name="email" placeholder="{{_('Your email address')}}" required>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
{% block body %} {% block body %}
<h3>{{_('About')}}</h3> <h3>{{_('About')}}</h3>
<p>{{instance}} powered by <p>{{instance}} powered by
<a href="https://github.com/janeczku/calibre-web" title="Calibre-Web">Calibre Web</a>. <a href="https://github.com/janeczku/calibre-web" title="Calibre-Web">Calibre-Web</a>.
</p> </p>
<h3>{{_('Calibre library statistics')}}</h3> <h3>{{_('Calibre library statistics')}}</h3>
<table id="stats" class="table"> <table id="stats" class="table">
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
{% block js %} {% block js %}
<script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table.min.js') }}"></script> <script src="{{ url_for('static', filename='js/libs/bootstrap-table/bootstrap-table.min.js') }}"></script>
<script> <script>
// ToDo: Move to js file
$('#table').bootstrapTable({ $('#table').bootstrapTable({
formatNoMatches: function () { formatNoMatches: function () {
return ''; return '';
......
...@@ -14,10 +14,16 @@ ...@@ -14,10 +14,16 @@
<input type="email" class="form-control" name="email" id="email" value="{{ content.email if content.email != None }}" autocomplete="off"> <input type="email" class="form-control" name="email" id="email" value="{{ content.email if content.email != None }}" autocomplete="off">
</div> </div>
{% if ( g.user and g.user.role_passwd() or g.user.role_admin() ) and not content.role_anonymous() %} {% if ( g.user and g.user.role_passwd() or g.user.role_admin() ) and not content.role_anonymous() %}
<div class="form-group"> {% if g.user and g.user.role_admin() and g.allow_registration and not new_user and not profile %}
<label for="password">{{_('Password')}}</label> <div class="btn btn-default" id="resend_password"><a href="{{url_for('reset_password', user_id = content.id) }}">{{_('Reset user Password')}}</a></div>
<input type="password" class="form-control" name="password" id="password" value="" autocomplete="off"> {% else %}
</div> <div class="form-group">
<label for="password">{{_('Password')}}</label>
<input type="password" class="form-control" name="password" id="password" value="" autocomplete="off">
</div>
{% endif %}
{% endif %} {% endif %}
<div class="form-group"> <div class="form-group">
<label for="kindle_mail">{{_('Kindle E-Mail')}}</label> <label for="kindle_mail">{{_('Kindle E-Mail')}}</label>
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -149,7 +149,7 @@ class UserBase: ...@@ -149,7 +149,7 @@ class UserBase:
return '<User %r>' % self.nickname return '<User %r>' % self.nickname
# Baseclass for Users in Calibre-web, settings which are depending on certain users are stored here. It is derived from # Baseclass for Users in Calibre-Web, settings which are depending on certain users are stored here. It is derived from
# User Base (all access methods are declared there) # User Base (all access methods are declared there)
class User(UserBase, Base): class User(UserBase, Base):
__tablename__ = 'user' __tablename__ = 'user'
...@@ -216,7 +216,7 @@ class Shelf(Base): ...@@ -216,7 +216,7 @@ class Shelf(Base):
return '<Shelf %r>' % self.name return '<Shelf %r>' % self.name
# Baseclass representing Relationship between books and Shelfs in Calibre-web in app.db (N:M) # Baseclass representing Relationship between books and Shelfs in Calibre-Web in app.db (N:M)
class BookShelf(Base): class BookShelf(Base):
__tablename__ = 'book_shelf_link' __tablename__ = 'book_shelf_link'
...@@ -259,6 +259,17 @@ class Downloads(Base): ...@@ -259,6 +259,17 @@ class Downloads(Base):
def __repr__(self): def __repr__(self):
return '<Download %r' % self.book_id return '<Download %r' % self.book_id
# Baseclass representing allowed domains for registration
class Registration(Base):
__tablename__ = 'registration'
id = Column(Integer, primary_key=True)
domain = Column(String)
def __repr__(self):
return u"<Registration('{0}')>".format(self.domain)
# Baseclass for representing settings in app.db with email server settings and Calibre database settings # Baseclass for representing settings in app.db with email server settings and Calibre database settings
# (application settings) # (application settings)
...@@ -276,7 +287,7 @@ class Settings(Base): ...@@ -276,7 +287,7 @@ class Settings(Base):
config_port = Column(Integer, default=DEFAULT_PORT) config_port = Column(Integer, default=DEFAULT_PORT)
config_certfile = Column(String) config_certfile = Column(String)
config_keyfile = Column(String) config_keyfile = Column(String)
config_calibre_web_title = Column(String, default=u'Calibre-web') config_calibre_web_title = Column(String, default=u'Calibre-Web')
config_books_per_page = Column(Integer, default=60) config_books_per_page = Column(Integer, default=60)
config_random_books = Column(Integer, default=4) config_random_books = Column(Integer, default=4)
config_read_column = Column(Integer, default=0) config_read_column = Column(Integer, default=0)
...@@ -516,35 +527,18 @@ class Config: ...@@ -516,35 +527,18 @@ class Config:
# everywhere to curent should work. Migration is done by checking if relevant coloums are existing, and than adding # everywhere to curent should work. Migration is done by checking if relevant coloums are existing, and than adding
# rows with SQL commands # rows with SQL commands
def migrate_Database(): def migrate_Database():
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"): if not engine.dialect.has_table(engine.connect(), "bookmark"):
Bookmark.__table__.create(bind=engine) Bookmark.__table__.create(bind=engine)
if not engine.dialect.has_table(engine.connect(), "registration"):
try: ReadBook.__table__.create(bind=engine)
session.query(exists().where(User.locale)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some rows are missing
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE user ADD column locale String(2) DEFAULT 'en'") conn.execute("insert into registration (domain) values('%.%')")
conn.execute("ALTER TABLE user ADD column default_language String(3) DEFAULT 'all'")
session.commit()
try:
session.query(exists().where(Settings.config_calibre_dir)).scalar()
session.commit() session.commit()
except exc.OperationalError: # Database is not compatible, some rows are missing # Handle table exists, but no content
cnt = session.query(Registration).count()
if not cnt:
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE Settings ADD column `config_calibre_dir` String") conn.execute("insert into registration (domain) values('%.%')")
conn.execute("ALTER TABLE Settings ADD column `config_port` INTEGER DEFAULT 8083")
conn.execute("ALTER TABLE Settings ADD column `config_calibre_web_title` String DEFAULT 'Calibre-web'")
conn.execute("ALTER TABLE Settings ADD column `config_books_per_page` INTEGER DEFAULT 60")
conn.execute("ALTER TABLE Settings ADD column `config_random_books` INTEGER DEFAULT 4")
conn.execute("ALTER TABLE Settings ADD column `config_title_regex` String DEFAULT "
"'^(A|The|An|Der|Die|Das|Den|Ein|Eine|Einen|Dem|Des|Einem|Eines)\s+'")
conn.execute("ALTER TABLE Settings ADD column `config_log_level` SmallInteger DEFAULT " + str(logging.INFO))
conn.execute("ALTER TABLE Settings ADD column `config_uploading` SmallInteger DEFAULT 0")
conn.execute("ALTER TABLE Settings ADD column `config_anonbrowse` SmallInteger DEFAULT 0")
conn.execute("ALTER TABLE Settings ADD column `config_public_reg` SmallInteger DEFAULT 0")
session.commit() session.commit()
try: try:
session.query(exists().where(Settings.config_use_google_drive)).scalar() session.query(exists().where(Settings.config_use_google_drive)).scalar()
...@@ -553,6 +547,7 @@ def migrate_Database(): ...@@ -553,6 +547,7 @@ def migrate_Database():
conn.execute("ALTER TABLE Settings ADD column `config_use_google_drive` INTEGER DEFAULT 0") conn.execute("ALTER TABLE Settings ADD column `config_use_google_drive` INTEGER DEFAULT 0")
conn.execute("ALTER TABLE Settings ADD column `config_google_drive_folder` String DEFAULT ''") conn.execute("ALTER TABLE Settings ADD column `config_google_drive_folder` String DEFAULT ''")
conn.execute("ALTER TABLE Settings ADD column `config_google_drive_watch_changes_response` String DEFAULT ''") conn.execute("ALTER TABLE Settings ADD column `config_google_drive_watch_changes_response` String DEFAULT ''")
session.commit()
try: try:
session.query(exists().where(Settings.config_columns_to_ignore)).scalar() session.query(exists().where(Settings.config_columns_to_ignore)).scalar()
except exc.OperationalError: except exc.OperationalError:
...@@ -561,14 +556,12 @@ def migrate_Database(): ...@@ -561,14 +556,12 @@ def migrate_Database():
session.commit() session.commit()
try: try:
session.query(exists().where(Settings.config_default_role)).scalar() session.query(exists().where(Settings.config_default_role)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some rows are missing except exc.OperationalError: # Database is not compatible, some rows are missing
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE Settings ADD column `config_default_role` SmallInteger DEFAULT 0") conn.execute("ALTER TABLE Settings ADD column `config_default_role` SmallInteger DEFAULT 0")
session.commit() session.commit()
try: try:
session.query(exists().where(BookShelf.order)).scalar() session.query(exists().where(BookShelf.order)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some rows are missing except exc.OperationalError: # Database is not compatible, some rows are missing
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE book_shelf_link ADD column 'order' INTEGER DEFAULT 1") conn.execute("ALTER TABLE book_shelf_link ADD column 'order' INTEGER DEFAULT 1")
...@@ -576,7 +569,6 @@ def migrate_Database(): ...@@ -576,7 +569,6 @@ def migrate_Database():
try: try:
create = False create = False
session.query(exists().where(User.sidebar_view)).scalar() session.query(exists().where(User.sidebar_view)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some rows are missing except exc.OperationalError: # Database is not compatible, some rows are missing
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE user ADD column `sidebar_view` Integer DEFAULT 1") conn.execute("ALTER TABLE user ADD column `sidebar_view` Integer DEFAULT 1")
...@@ -606,6 +598,7 @@ def migrate_Database(): ...@@ -606,6 +598,7 @@ def migrate_Database():
except exc.OperationalError: except exc.OperationalError:
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE user ADD column `theme` INTEGER DEFAULT 0") conn.execute("ALTER TABLE user ADD column `theme` INTEGER DEFAULT 0")
session.commit()
if session.query(User).filter(User.role.op('&')(ROLE_ANONYMOUS) == ROLE_ANONYMOUS).first() is None: if session.query(User).filter(User.role.op('&')(ROLE_ANONYMOUS) == ROLE_ANONYMOUS).first() is None:
create_anonymous_user() create_anonymous_user()
try: try:
...@@ -627,21 +620,18 @@ def migrate_Database(): ...@@ -627,21 +620,18 @@ def migrate_Database():
conn.execute("ALTER TABLE Settings ADD column `config_mature_content_tags` String DEFAULT ''") conn.execute("ALTER TABLE Settings ADD column `config_mature_content_tags` String DEFAULT ''")
try: try:
session.query(exists().where(Settings.config_default_show)).scalar() session.query(exists().where(Settings.config_default_show)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some rows are missing except exc.OperationalError: # Database is not compatible, some rows are missing
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE Settings ADD column `config_default_show` SmallInteger DEFAULT 2047") conn.execute("ALTER TABLE Settings ADD column `config_default_show` SmallInteger DEFAULT 2047")
session.commit() session.commit()
try: try:
session.query(exists().where(Settings.config_logfile)).scalar() session.query(exists().where(Settings.config_logfile)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some rows are missing except exc.OperationalError: # Database is not compatible, some rows are missing
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE Settings ADD column `config_logfile` String DEFAULT ''") conn.execute("ALTER TABLE Settings ADD column `config_logfile` String DEFAULT ''")
session.commit() session.commit()
try: try:
session.query(exists().where(Settings.config_certfile)).scalar() session.query(exists().where(Settings.config_certfile)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some rows are missing except exc.OperationalError: # Database is not compatible, some rows are missing
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE Settings ADD column `config_certfile` String DEFAULT ''") conn.execute("ALTER TABLE Settings ADD column `config_certfile` String DEFAULT ''")
...@@ -649,14 +639,12 @@ def migrate_Database(): ...@@ -649,14 +639,12 @@ def migrate_Database():
session.commit() session.commit()
try: try:
session.query(exists().where(Settings.config_read_column)).scalar() session.query(exists().where(Settings.config_read_column)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some rows are missing except exc.OperationalError: # Database is not compatible, some rows are missing
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE Settings ADD column `config_read_column` INTEGER DEFAULT 0") conn.execute("ALTER TABLE Settings ADD column `config_read_column` INTEGER DEFAULT 0")
session.commit() session.commit()
try: try:
session.query(exists().where(Settings.config_ebookconverter)).scalar() session.query(exists().where(Settings.config_ebookconverter)).scalar()
session.commit()
except exc.OperationalError: # Database is not compatible, some rows are missing except exc.OperationalError: # Database is not compatible, some rows are missing
conn = engine.connect() conn = engine.connect()
conn.execute("ALTER TABLE Settings ADD column `config_ebookconverter` INTEGER DEFAULT 0") conn.execute("ALTER TABLE Settings ADD column `config_ebookconverter` INTEGER DEFAULT 0")
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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