Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
D
douban-api-proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
captainwong
douban-api-proxy
Commits
1da4efec
Commit
1da4efec
authored
Dec 31, 2019
by
Ozzieisaacs
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into Develop
parents
1c630eb6
5887f0fe
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
1342 additions
and
2528 deletions
+1342
-2528
admin.py
cps/admin.py
+23
-15
config_sql.py
cps/config_sql.py
+5
-1
constants.py
cps/constants.py
+2
-0
helper.py
cps/helper.py
+9
-3
opds.py
cps/opds.py
+4
-3
server.py
cps/server.py
+1
-1
main.css
cps/static/css/main.css
+0
-1
table.js
cps/static/js/table.js
+36
-8
email_edit.html
cps/templates/email_edit.html
+25
-7
user_edit.html
cps/templates/user_edit.html
+1
-2
ub.py
cps/ub.py
+13
-4
web.py
cps/web.py
+32
-15
worker.py
cps/worker.py
+1
-1
Calibre-Web TestSummary.html
test/Calibre-Web TestSummary.html
+1190
-2467
No files found.
cps/admin.py
View file @
1da4efec
...
...
@@ -197,10 +197,10 @@ def update_view_configuration():
return
view_configuration
()
@
admi
.
route
(
"/ajax/editdomain"
,
methods
=
[
'POST'
])
@
admi
.
route
(
"/ajax/editdomain
/<int:allow>
"
,
methods
=
[
'POST'
])
@
login_required
@
admin_required
def
edit_domain
():
def
edit_domain
(
allow
):
# POST /post
# name: 'username', //name of field (column in db)
# pk: 1 //primary key (record id)
...
...
@@ -213,14 +213,14 @@ def edit_domain():
return
""
@
admi
.
route
(
"/ajax/adddomain"
,
methods
=
[
'POST'
])
@
admi
.
route
(
"/ajax/adddomain
/<int:allow>
"
,
methods
=
[
'POST'
])
@
login_required
@
admin_required
def
add_domain
():
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
)
.
first
()
check
=
ub
.
session
.
query
(
ub
.
Registration
)
.
filter
(
ub
.
Registration
.
domain
==
domain_name
)
.
fi
lter
(
ub
.
Registration
.
allow
==
allow
)
.
fi
rst
()
if
not
check
:
new_domain
=
ub
.
Registration
(
domain
=
domain_name
)
new_domain
=
ub
.
Registration
(
domain
=
domain_name
,
allow
=
allow
)
ub
.
session
.
add
(
new_domain
)
ub
.
session
.
commit
()
return
""
...
...
@@ -234,18 +234,18 @@ def delete_domain():
ub
.
session
.
query
(
ub
.
Registration
)
.
filter
(
ub
.
Registration
.
id
==
domain_id
)
.
delete
()
ub
.
session
.
commit
()
# If last domain was deleted, add all domains by default
if
not
ub
.
session
.
query
(
ub
.
Registration
)
.
count
():
new_domain
=
ub
.
Registration
(
domain
=
"
%
.
%
"
)
if
not
ub
.
session
.
query
(
ub
.
Registration
)
.
filter
(
ub
.
Registration
.
allow
==
1
)
.
count
():
new_domain
=
ub
.
Registration
(
domain
=
"
%
.
%
"
,
allow
=
1
)
ub
.
session
.
add
(
new_domain
)
ub
.
session
.
commit
()
return
""
@
admi
.
route
(
"/ajax/domainlist"
)
@
admi
.
route
(
"/ajax/domainlist
/<int:allow>
"
)
@
login_required
@
admin_required
def
list_domain
():
answer
=
ub
.
session
.
query
(
ub
.
Registration
)
.
all
()
def
list_domain
(
allow
):
answer
=
ub
.
session
.
query
(
ub
.
Registration
)
.
filter
(
ub
.
Registration
.
allow
==
allow
)
.
all
()
json_dumps
=
json
.
dumps
([{
"domain"
:
r
.
domain
.
replace
(
'
%
'
,
'*'
)
.
replace
(
'_'
,
'?'
),
"id"
:
r
.
id
}
for
r
in
answer
])
js
=
json
.
dumps
(
json_dumps
.
replace
(
'"'
,
"'"
))
.
lstrip
(
'"'
)
.
strip
(
'"'
)
response
=
make_response
(
js
.
replace
(
"'"
,
'"'
))
...
...
@@ -635,6 +635,7 @@ def edit_user(user_id):
else
:
flash
(
_
(
u"Found an existing account for this e-mail address."
),
category
=
"error"
)
return
render_title_template
(
"user_edit.html"
,
translations
=
translations
,
languages
=
languages
,
mail_configured
=
config
.
get_mail_server_configured
(),
new_user
=
0
,
content
=
content
,
downloads
=
downloads
,
registered_oauth
=
oauth_check
,
title
=
_
(
u"Edit User
%(nick)
s"
,
nick
=
content
.
nickname
),
page
=
"edituser"
)
if
"nickname"
in
to_save
and
to_save
[
"nickname"
]
!=
content
.
nickname
:
...
...
@@ -646,11 +647,11 @@ def edit_user(user_id):
return
render_title_template
(
"user_edit.html"
,
translations
=
translations
,
languages
=
languages
,
mail_configured
=
config
.
get_mail_server_configured
(),
new_user
=
0
,
content
=
content
,
downloads
=
downloads
,
registered_oauth
=
oauth_check
,
title
=
_
(
u"Edit User
%(nick)
s"
,
nick
=
content
.
nickname
),
title
=
_
(
u"Edit User
%(nick)
s"
,
nick
=
content
.
nickname
),
page
=
"edituser"
)
if
"kindle_mail"
in
to_save
and
to_save
[
"kindle_mail"
]
!=
content
.
kindle_mail
:
...
...
@@ -663,21 +664,27 @@ def edit_user(user_id):
flash
(
_
(
u"An unknown error occured."
),
category
=
"error"
)
return
render_title_template
(
"user_edit.html"
,
translations
=
translations
,
languages
=
languages
,
new_user
=
0
,
content
=
content
,
downloads
=
downloads
,
registered_oauth
=
oauth_check
,
mail_configured
=
config
.
get_mail_server_configured
(),
title
=
_
(
u"Edit User
%(nick)
s"
,
nick
=
content
.
nickname
),
page
=
"edituser"
)
@
admi
.
route
(
"/admin/resetpassword/<int:user_id>"
)
@
login_required
@
admin_required
def
reset_password
(
user_id
):
def
reset_
user_
password
(
user_id
):
if
not
config
.
config_public_reg
:
abort
(
404
)
if
current_user
is
not
None
and
current_user
.
is_authenticated
:
ret
,
message
=
reset_password
(
user_id
)
if
ret
==
1
:
log
.
debug
(
u"Password for user
%(user)
s reset"
,
user
=
message
)
flash
(
_
(
u"Password for user
%(user)
s reset"
,
user
=
message
),
category
=
"success"
)
else
:
elif
ret
==
0
:
log
.
error
(
u"An unknown error occurred. Please try again later."
)
flash
(
_
(
u"An unknown error occurred. Please try again later."
),
category
=
"error"
)
else
:
log
.
error
(
u"Please configure the SMTP mail settings first..."
)
flash
(
_
(
u"Please configure the SMTP mail settings first..."
),
category
=
"error"
)
return
redirect
(
url_for
(
'admin.admin'
))
...
...
@@ -711,6 +718,7 @@ def send_logfile(logtype):
@
admi
.
route
(
"/get_update_status"
,
methods
=
[
'GET'
])
@
login_required_if_no_ano
def
get_update_status
():
log
.
info
(
u"Update status requested"
)
return
updater_thread
.
get_available_updates
(
request
.
method
,
locale
=
get_locale
())
...
...
cps/config_sql.py
View file @
1da4efec
...
...
@@ -38,7 +38,7 @@ class _Settings(_Base):
__tablename__
=
'settings'
id
=
Column
(
Integer
,
primary_key
=
True
)
mail_server
=
Column
(
String
,
default
=
'mail.example.org'
)
mail_server
=
Column
(
String
,
default
=
constants
.
DEFAULT_MAIL_SERVER
)
mail_port
=
Column
(
Integer
,
default
=
25
)
mail_use_ssl
=
Column
(
SmallInteger
,
default
=
0
)
mail_login
=
Column
(
String
,
default
=
'mail@example.com'
)
...
...
@@ -193,6 +193,10 @@ class _ConfigSQL(object):
def
get_mail_settings
(
self
):
return
{
k
:
v
for
k
,
v
in
self
.
__dict__
.
items
()
if
k
.
startswith
(
'mail_'
)}
def
get_mail_server_configured
(
self
):
return
not
bool
(
self
.
mail_server
==
constants
.
DEFAULT_MAIL_SERVER
)
def
set_from_dictionary
(
self
,
dictionary
,
field
,
convertor
=
None
,
default
=
None
):
'''Possibly updates a field of this object.
The new value, if present, is grabbed from the given dictionary, and optionally passed through a convertor.
...
...
cps/constants.py
View file @
1da4efec
...
...
@@ -94,6 +94,7 @@ LOGIN_LDAP = 1
LOGIN_OAUTH
=
2
# LOGIN_OAUTH_GOOGLE = 3
DEFAULT_MAIL_SERVER
=
"mail.example.org"
DEFAULT_PASSWORD
=
"admin123"
DEFAULT_PORT
=
8083
...
...
@@ -105,6 +106,7 @@ except ValueError:
del
env_CALIBRE_PORT
EXTENSIONS_AUDIO
=
{
'mp3'
,
'm4a'
,
'm4b'
}
EXTENSIONS_CONVERT
=
{
'pdf'
,
'epub'
,
'mobi'
,
'azw3'
,
'docx'
,
'rtf'
,
'fb2'
,
'lit'
,
'lrf'
,
'txt'
,
'htmlz'
,
'rtf'
,
'odt'
}
EXTENSIONS_UPLOAD
=
{
'txt'
,
'pdf'
,
'epub'
,
'mobi'
,
'azw'
,
'azw3'
,
'cbr'
,
'cbz'
,
'cbt'
,
'djvu'
,
'prc'
,
'doc'
,
'docx'
,
...
...
cps/helper.py
View file @
1da4efec
...
...
@@ -125,7 +125,7 @@ def send_registration_mail(e_mail, user_name, default_password, resend=False):
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
+=
"User name:
%
s
\
r\
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
"
...
...
@@ -416,6 +416,8 @@ def reset_password(user_id):
existing_user
=
ub
.
session
.
query
(
ub
.
User
)
.
filter
(
ub
.
User
.
id
==
user_id
)
.
first
()
password
=
generate_random_password
()
existing_user
.
password
=
generate_password_hash
(
password
)
if
not
config
.
get_mail_server_configured
():
return
(
2
,
None
)
try
:
ub
.
session
.
commit
()
send_registration_mail
(
existing_user
.
email
,
existing_user
.
nickname
,
password
,
True
)
...
...
@@ -735,9 +737,13 @@ def speaking_language(languages=None):
# from https://code.luasoftware.com/tutorials/flask/execute-raw-sql-in-flask-sqlalchemy/
def
check_valid_domain
(
domain_text
):
domain_text
=
domain_text
.
split
(
'@'
,
1
)[
-
1
]
.
lower
()
sql
=
"SELECT * FROM registration WHERE
:domain LIKE domain
;"
sql
=
"SELECT * FROM registration WHERE
(:domain LIKE domain and allow = 1)
;"
result
=
ub
.
session
.
query
(
ub
.
Registration
)
.
from_statement
(
text
(
sql
))
.
params
(
domain
=
domain_text
)
.
all
()
return
len
(
result
)
if
not
len
(
result
):
return
False
sql
=
"SELECT * FROM registration WHERE (:domain LIKE domain and allow = 0);"
result
=
ub
.
session
.
query
(
ub
.
Registration
)
.
from_statement
(
text
(
sql
))
.
params
(
domain
=
domain_text
)
.
all
()
return
not
len
(
result
)
# Orders all Authors in the list according to authors sort
...
...
cps/opds.py
View file @
1da4efec
...
...
@@ -382,11 +382,12 @@ def feed_get_cover(book_id):
@
requires_basic_auth_if_no_ano
def
feed_read_books
():
off
=
request
.
args
.
get
(
"offset"
)
or
0
re
turn
render_read_books
(
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
,
True
,
True
)
re
sult
,
pagination
=
render_read_books
(
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
,
True
,
True
)
return
render_xml_template
(
'feed.xml'
,
entries
=
result
,
pagination
=
pagination
)
@
opds
.
route
(
"/opds/unreadbooks"
)
@
requires_basic_auth_if_no_ano
def
feed_unread_books
():
off
=
request
.
args
.
get
(
"offset"
)
or
0
return
render_read_books
(
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
,
False
,
True
)
result
,
pagination
=
render_read_books
(
int
(
off
)
/
(
int
(
config
.
config_books_per_page
))
+
1
,
False
,
True
)
return
render_xml_template
(
'feed.xml'
,
entries
=
result
,
pagination
=
pagination
)
cps/server.py
View file @
1da4efec
...
...
@@ -24,7 +24,7 @@ import signal
import
socket
try
:
from
gevent.pywsgi
import
WSGIServer
from
gevent.py
s
wsgi
import
WSGIServer
from
gevent.pool
import
Pool
from
gevent
import
__version__
as
_version
VERSION
=
'Gevent '
+
_version
...
...
cps/static/css/main.css
View file @
1da4efec
...
...
@@ -134,7 +134,6 @@ body {
user-select
:
none
;
padding-top
:
160px
;
padding-bottom
:
160px
;
padding-right
:
80px
;
}
.arrow
:hover
{
...
...
cps/static/js/table.js
View file @
1da4efec
...
...
@@ -19,21 +19,41 @@
$
(
function
()
{
$
(
"#domain_submit"
).
click
(
function
(
event
)
{
$
(
"#domain_
allow_
submit"
).
click
(
function
(
event
)
{
event
.
preventDefault
();
$
(
"#domain_add"
).
ajaxForm
();
$
(
"#domain_add
_allow
"
).
ajaxForm
();
$
(
this
).
closest
(
"form"
).
submit
();
$
.
ajax
({
method
:
"get"
,
url
:
window
.
location
.
pathname
+
"/../../ajax/domainlist"
,
url
:
window
.
location
.
pathname
+
"/../../ajax/domainlist
/1
"
,
async
:
true
,
timeout
:
900
,
success
:
function
(
data
)
{
$
(
"#domain-table"
).
bootstrapTable
(
"load"
,
data
);
$
(
"#domain-
allow-
table"
).
bootstrapTable
(
"load"
,
data
);
}
});
});
$
(
"#domain-table"
).
bootstrapTable
({
$
(
"#domain-allow-table"
).
bootstrapTable
({
formatNoMatches
:
function
()
{
return
""
;
},
striped
:
false
});
$
(
"#domain_deny_submit"
).
click
(
function
(
event
)
{
event
.
preventDefault
();
$
(
"#domain_add_deny"
).
ajaxForm
();
$
(
this
).
closest
(
"form"
).
submit
();
$
.
ajax
({
method
:
"get"
,
url
:
window
.
location
.
pathname
+
"/../../ajax/domainlist/0"
,
async
:
true
,
timeout
:
900
,
success
:
function
(
data
)
{
$
(
"#domain-deny-table"
).
bootstrapTable
(
"load"
,
data
);
}
});
});
$
(
"#domain-deny-table"
).
bootstrapTable
({
formatNoMatches
:
function
()
{
return
""
;
},
...
...
@@ -50,14 +70,22 @@ $(function() {
$
(
"#DeleteDomain"
).
modal
(
"hide"
);
$
.
ajax
({
method
:
"get"
,
url
:
window
.
location
.
pathname
+
"/../../ajax/domainlist"
,
url
:
window
.
location
.
pathname
+
"/../../ajax/domainlist
/1
"
,
async
:
true
,
timeout
:
900
,
success
:
function
(
data
)
{
$
(
"#domain-table"
).
bootstrapTable
(
"load"
,
data
);
$
(
"#domain-allow-table"
).
bootstrapTable
(
"load"
,
data
);
}
});
$
.
ajax
({
method
:
"get"
,
url
:
window
.
location
.
pathname
+
"/../../ajax/domainlist/0"
,
async
:
true
,
timeout
:
900
,
success
:
function
(
data
)
{
$
(
"#domain-deny-table"
).
bootstrapTable
(
"load"
,
data
);
}
});
});
//triggered when modal is about to be shown
$
(
"#DeleteDomain"
).
on
(
"show.bs.modal"
,
function
(
e
)
{
...
...
cps/templates/email_edit.html
View file @
1da4efec
...
...
@@ -41,22 +41,40 @@
</form>
{% if g.allow_registration %}
<h2>
{{_('Allowed domains for registering')}}
</h2>
<table
class=
"table table-no-bordered"
id=
"domain-table"
data-url=
"{{url_for('admin.list_domain')}}"
data-id-field=
"id"
data-show-header=
"false"
data-editable-mode=
"inline"
>
<form
id=
"domain_add_allow"
action=
"{{ url_for('admin.add_domain',allow=1)}}"
method=
"POST"
>
<div
class=
"form-group required"
>
<label
for=
"domainname_allow"
>
{{_('Add Domain')}}
</label>
<input
type=
"text"
class=
"form-control"
name=
"domainname"
id=
"domainname_allow"
>
</div>
<button
id=
"domain_allow_submit"
class=
"btn btn-default"
>
{{_('Add')}}
</button>
</form>
<table
class=
"table table-no-bordered"
id=
"domain-allow-table"
data-url=
"{{url_for('admin.list_domain', allow=1)}}"
data-id-field=
"id"
data-show-header=
"false"
data-editable-mode=
"inline"
>
<thead>
<tr>
<th
data-field=
"domain"
id=
"domain-allow"
data-editable-type=
"text"
data-editable-url=
"{{ url_for('admin.edit_domain', allow = 1)}}"
data-editable=
"true"
data-editable-title=
"{{_('Enter domainname')}}"
></th>
<th
data-field=
"id"
id=
"id-allow"
data-visible=
"false"
></th>
<th
data-align=
"right"
data-formatter=
"TableActions"
></th>
</tr>
</thead>
</table>
<h2>
{{_('Denied domains for registering')}}
</h2>
<table
class=
"table table-no-bordered"
id=
"domain-deny-table"
data-url=
"{{url_for('admin.list_domain', allow=0)}}"
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('admin.edit_domain'
)}}"
data-editable=
"true"
data-editable-title=
"{{_('Enter domainname')}}"
></th>
<th
data-field=
"id"
id=
"id"
data-visible=
"false"
></th>
<th
data-field=
"domain"
id=
"domain
-deny"
data-editable-type=
"text"
data-editable-url=
"{{ url_for('admin.edit_domain', allow = 0
)}}"
data-editable=
"true"
data-editable-title=
"{{_('Enter domainname')}}"
></th>
<th
data-field=
"id"
id=
"id
-deny
"
data-visible=
"false"
></th>
<th
data-align=
"right"
data-formatter=
"TableActions"
></th>
</tr>
</thead>
</table>
<form
id=
"domain_add
"
action=
"{{ url_for('admin.add_domain'
)}}"
method=
"POST"
>
<form
id=
"domain_add
_deny"
action=
"{{ url_for('admin.add_domain',allow=0
)}}"
method=
"POST"
>
<div
class=
"form-group required"
>
<label
for=
"domainname"
>
{{_('Add Domain')}}
</label>
<input
type=
"text"
class=
"form-control"
name=
"domainname"
id=
"domainname"
>
<label
for=
"domainname
_deny
"
>
{{_('Add Domain')}}
</label>
<input
type=
"text"
class=
"form-control"
name=
"domainname"
id=
"domainname
_deny
"
>
</div>
<button
id=
"domain_submit"
class=
"btn btn-default"
>
{{_('Add')}}
</button>
<button
id=
"domain_
deny_
submit"
class=
"btn btn-default"
>
{{_('Add')}}
</button>
</form>
{% endif %}
</div>
{% endblock %}
...
...
cps/templates/user_edit.html
View file @
1da4efec
...
...
@@ -14,7 +14,7 @@
<input
type=
"email"
class=
"form-control"
name=
"email"
id=
"email"
value=
"{{ content.email if content.email != None }}"
autocomplete=
"off"
>
</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_admin() and not new_user and not profile and ( mail_configured and content.email if content.email != None
)
%}
{% if g.user and g.user.role_admin() and not new_user and not profile and ( mail_configured and content.email if content.email != None %}
<div
class=
"btn btn-default"
id=
"resend_password"
><a
href=
"{{url_for('admin.reset_user_password', user_id = content.id) }}"
>
{{_('Reset user Password')}}
</a></div>
{% endif %}
<div
class=
"form-group"
>
...
...
@@ -22,7 +22,6 @@
<input
type=
"password"
class=
"form-control"
name=
"password"
id=
"password"
value=
""
autocomplete=
"off"
>
</div>
{% endif %}
{% endif %}
<div
class=
"form-group"
>
<label
for=
"kindle_mail"
>
{{_('Kindle E-Mail')}}
</label>
<input
type=
"email"
class=
"form-control"
name=
"kindle_mail"
id=
"kindle_mail"
value=
"{{ content.kindle_mail if content.kindle_mail != None }}"
>
...
...
cps/ub.py
View file @
1da4efec
...
...
@@ -324,6 +324,7 @@ class Registration(Base):
id
=
Column
(
Integer
,
primary_key
=
True
)
domain
=
Column
(
String
)
allow
=
Column
(
Integer
)
def
__repr__
(
self
):
return
u"<Registration('{0}')>"
.
format
(
self
.
domain
)
...
...
@@ -359,24 +360,32 @@ def migrate_Database(session):
if
not
engine
.
dialect
.
has_table
(
engine
.
connect
(),
"registration"
):
ReadBook
.
__table__
.
create
(
bind
=
engine
)
conn
=
engine
.
connect
()
conn
.
execute
(
"insert into registration (domain) values('
%
.
%
')"
)
conn
.
execute
(
"insert into registration (domain, allow) values('
%
.
%
',1)"
)
session
.
commit
()
try
:
session
.
query
(
exists
()
.
where
(
Registration
.
allow
))
.
scalar
()
session
.
commit
()
except
exc
.
OperationalError
:
# Database is not compatible, some columns are missing
conn
=
engine
.
connect
()
conn
.
execute
(
"ALTER TABLE registration ADD column 'allow' INTEGER"
)
conn
.
execute
(
"update registration set 'allow' = 1"
)
session
.
commit
()
# Handle table exists, but no content
cnt
=
session
.
query
(
Registration
)
.
count
()
if
not
cnt
:
conn
=
engine
.
connect
()
conn
.
execute
(
"insert into registration (domain
) values('
%
.
%
'
)"
)
conn
.
execute
(
"insert into registration (domain
, allow) values('
%
.
%
',1
)"
)
session
.
commit
()
try
:
session
.
query
(
exists
()
.
where
(
BookShelf
.
order
))
.
scalar
()
except
exc
.
OperationalError
:
# Database is not compatible, some
row
s are missing
except
exc
.
OperationalError
:
# Database is not compatible, some
column
s are missing
conn
=
engine
.
connect
()
conn
.
execute
(
"ALTER TABLE book_shelf_link ADD column 'order' INTEGER DEFAULT 1"
)
session
.
commit
()
try
:
create
=
False
session
.
query
(
exists
()
.
where
(
User
.
sidebar_view
))
.
scalar
()
except
exc
.
OperationalError
:
# Database is not compatible, some
row
s are missing
except
exc
.
OperationalError
:
# Database is not compatible, some
column
s are missing
conn
=
engine
.
connect
()
conn
.
execute
(
"ALTER TABLE user ADD column `sidebar_view` Integer DEFAULT 1"
)
session
.
commit
()
...
...
cps/web.py
View file @
1da4efec
...
...
@@ -93,7 +93,6 @@ def error_http(error):
def
internal_error
(
error
):
# __, __, tb = sys.exc_info()
return
render_template
(
'http_error.html'
,
error_code
=
"Internal Server Error"
,
error_name
=
str
(
error
),
...
...
@@ -1041,8 +1040,7 @@ def download_link(book_id, book_format):
@
login_required
@
download_required
def
send_to_kindle
(
book_id
,
book_format
,
convert
):
settings
=
config
.
get_mail_settings
()
if
settings
.
get
(
"mail_server"
,
"mail.example.org"
)
==
"mail.example.org"
:
if
not
config
.
get_mail_server_configured
():
flash
(
_
(
u"Please configure the SMTP mail settings first..."
),
category
=
"error"
)
elif
current_user
.
kindle_mail
:
result
=
send_mail
(
book_id
,
book_format
,
convert
,
current_user
.
kindle_mail
,
config
.
config_calibre_dir
,
...
...
@@ -1067,16 +1065,19 @@ def register():
abort
(
404
)
if
current_user
is
not
None
and
current_user
.
is_authenticated
:
return
redirect
(
url_for
(
'web.index'
))
if
not
config
.
get_mail_server_configured
():
flash
(
_
(
u"E-Mail server is not configured, please contact your administrator!"
),
category
=
"error"
)
return
render_title_template
(
'register.html'
,
title
=
_
(
u"register"
),
page
=
"register"
)
if
request
.
method
==
"POST"
:
to_save
=
request
.
form
.
to_dict
()
if
not
to_save
[
"nickname"
]
or
not
to_save
[
"email"
]:
flash
(
_
(
u"Please fill out all fields!"
),
category
=
"error"
)
return
render_title_template
(
'register.html'
,
title
=
_
(
u"register"
),
page
=
"register"
)
existing_user
=
ub
.
session
.
query
(
ub
.
User
)
.
filter
(
func
.
lower
(
ub
.
User
.
nickname
)
==
to_save
[
"nickname"
]
.
lower
())
.
first
()
existing_email
=
ub
.
session
.
query
(
ub
.
User
)
.
filter
(
ub
.
User
.
email
==
to_save
[
"email"
]
.
lower
())
.
first
()
if
not
existing_user
and
not
existing_email
:
content
=
ub
.
User
()
# content.password = generate_password_hash(to_save["password"])
...
...
@@ -1116,10 +1117,12 @@ def register():
@
web
.
route
(
'/login'
,
methods
=
[
'GET'
,
'POST'
])
def
login
():
if
not
config
.
db_configured
:
log
.
debug
(
u"Redirect to initial configuration"
)
return
redirect
(
url_for
(
'admin.basic_configuration'
))
if
current_user
is
not
None
and
current_user
.
is_authenticated
:
return
redirect
(
url_for
(
'web.index'
))
if
config
.
config_login_type
==
constants
.
LOGIN_LDAP
and
not
services
.
ldap
:
log
.
error
(
u"Cannot activate LDAP authentication"
)
flash
(
_
(
u"Cannot activate LDAP authentication"
),
category
=
"error"
)
if
request
.
method
==
"POST"
:
form
=
request
.
form
.
to_dict
()
...
...
@@ -1129,10 +1132,12 @@ def login():
login_result
=
services
.
ldap
.
bind_user
(
form
[
'username'
],
form
[
'password'
])
if
login_result
:
login_user
(
user
,
remember
=
True
)
log
.
debug
(
u"You are now logged in as: '
%
s'"
,
user
.
nickname
)
flash
(
_
(
u"you are now logged in as: '
%(nickname)
s'"
,
nickname
=
user
.
nickname
),
category
=
"success"
)
return
redirect_back
(
url_for
(
"web.index"
))
if
login_result
is
None
:
log
.
error
(
'Could not login. LDAP server down, please contact your administrator'
)
flash
(
_
(
u"Could not login. LDAP server down, please contact your administrator"
),
category
=
"error"
)
else
:
ipAdress
=
request
.
headers
.
get
(
'X-Forwarded-For'
,
request
.
remote_addr
)
...
...
@@ -1147,6 +1152,7 @@ def login():
flash
(
_
(
u"New Password was send to your email address"
),
category
=
"info"
)
log
.
info
(
'Password reset for user "
%
s" IP-adress:
%
s'
,
form
[
'username'
],
ipAdress
)
else
:
log
.
info
(
u"An unknown error occurred. Please try again later."
)
flash
(
_
(
u"An unknown error occurred. Please try again later."
),
category
=
"error"
)
else
:
flash
(
_
(
u"Please enter valid username to reset password"
),
category
=
"error"
)
...
...
@@ -1154,18 +1160,16 @@ def login():
else
:
if
user
and
check_password_hash
(
str
(
user
.
password
),
form
[
'password'
])
and
user
.
nickname
!=
"Guest"
:
login_user
(
user
,
remember
=
True
)
log
.
debug
(
u"You are now logged in as: '
%
s'"
,
user
.
nickname
)
flash
(
_
(
u"You are now logged in as: '
%(nickname)
s'"
,
nickname
=
user
.
nickname
),
category
=
"success"
)
return
redirect_back
(
url_for
(
"web.index"
))
else
:
log
.
info
(
'Login failed for user "
%
s" IP-adress:
%
s'
,
form
[
'username'
],
ipAdress
)
flash
(
_
(
u"Wrong Username or Password"
),
category
=
"error"
)
settings
=
config
.
get_mail_settings
()
mail_configured
=
bool
(
settings
.
get
(
"mail_server"
,
"mail.example.org"
)
!=
"mail.example.org"
)
next_url
=
url_for
(
'web.index'
)
return
render_title_template
(
'login.html'
,
title
=
_
(
u"login"
),
next_url
=
next_url
,
config
=
config
,
mail
=
mail_configured
,
page
=
"login"
)
mail
=
config
.
get_mail_server_configured
()
,
page
=
"login"
)
@
web
.
route
(
'/logout'
)
...
...
@@ -1175,6 +1179,7 @@ def logout():
logout_user
()
if
feature_support
[
'oauth'
]
and
(
config
.
config_login_type
==
2
or
config
.
config_login_type
==
3
):
logout_oauth_user
()
log
.
debug
(
u"User logged out"
)
return
redirect
(
url_for
(
'web.login'
))
...
...
@@ -1186,7 +1191,7 @@ def remote_login():
ub
.
session
.
commit
()
verify_url
=
url_for
(
'web.verify_token'
,
token
=
auth_token
.
auth_token
,
_external
=
true
)
log
.
debug
(
u"Remot Login request with token:
%
s"
,
auth_token
.
auth_token
)
return
render_title_template
(
'remote_login.html'
,
title
=
_
(
u"login"
),
token
=
auth_token
.
auth_token
,
verify_url
=
verify_url
,
page
=
"remotelogin"
)
...
...
@@ -1200,6 +1205,7 @@ def verify_token(token):
# Token not found
if
auth_token
is
None
:
flash
(
_
(
u"Token not found"
),
category
=
"error"
)
log
.
error
(
u"Remote Login token not found"
)
return
redirect
(
url_for
(
'web.index'
))
# Token expired
...
...
@@ -1208,6 +1214,7 @@ def verify_token(token):
ub
.
session
.
commit
()
flash
(
_
(
u"Token has expired"
),
category
=
"error"
)
log
.
error
(
u"Remote Login token expired"
)
return
redirect
(
url_for
(
'web.index'
))
# Update token with user information
...
...
@@ -1216,6 +1223,7 @@ def verify_token(token):
ub
.
session
.
commit
()
flash
(
_
(
u"Success! Please return to your device"
),
category
=
"success"
)
log
.
debug
(
u"Remote Login token for userid
%
s verified"
,
auth_token
.
user_id
)
return
redirect
(
url_for
(
'web.index'
))
...
...
@@ -1251,6 +1259,7 @@ def token_verified():
ub
.
session
.
commit
()
data
[
'status'
]
=
'success'
log
.
debug
(
u"Remote Login for userid
%
s succeded"
,
user
.
id
)
flash
(
_
(
u"you are now logged in as: '
%(nickname)
s'"
,
nickname
=
user
.
nickname
),
category
=
"success"
)
response
=
make_response
(
json
.
dumps
(
data
,
ensure_ascii
=
False
))
...
...
@@ -1278,8 +1287,6 @@ def profile():
downloads
.
append
(
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book
.
book_id
)
.
first
())
else
:
ub
.
delete_download
(
book
.
book_id
)
# ub.session.query(ub.Downloads).filter(book.book_id == ub.Downloads.book_id).delete()
# ub.session.commit()
if
request
.
method
==
"POST"
:
to_save
=
request
.
form
.
to_dict
()
current_user
.
random_books
=
0
...
...
@@ -1333,15 +1340,17 @@ def profile():
ub
.
session
.
commit
()
except
IntegrityError
:
ub
.
session
.
rollback
()
flash
(
_
(
u"Found an existing account for this e-mail address or Kobo UserKey."
),
category
=
"error"
)
flash
(
_
(
u"Found an existing account for this e-mail address."
),
category
=
"error"
)
log
.
debug
(
u"Found an existing account for this e-mail address."
)
return
render_title_template
(
"user_edit.html"
,
content
=
current_user
,
downloads
=
downloads
,
translations
=
translations
,
title
=
_
(
u"
%(name)
s's profile"
,
name
=
current_user
.
nickname
),
page
=
"me"
,
registered_oauth
=
oauth_check
,
oauth_status
=
oauth_status
)
flash
(
_
(
u"Profile updated"
),
category
=
"success"
)
log
.
debug
(
u"Profile updated"
)
return
render_title_template
(
"user_edit.html"
,
translations
=
translations
,
profile
=
1
,
languages
=
languages
,
content
=
current_user
,
downloads
=
downloads
,
title
=
_
(
u"
%(name)
s's profile"
,
name
=
current_user
.
nickname
),
content
=
current_user
,
downloads
=
downloads
,
title
=
_
(
u"
%(name)
s's profile"
,
name
=
current_user
.
nickname
),
page
=
"me"
,
registered_oauth
=
oauth_check
,
oauth_status
=
oauth_status
)
...
...
@@ -1355,6 +1364,7 @@ def read_book(book_id, book_format):
book
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
common_filters
())
.
first
()
if
not
book
:
flash
(
_
(
u"Error opening eBook. File does not exist or file is not accessible:"
),
category
=
"error"
)
log
.
debug
(
u"Error opening eBook. File does not exist or file is not accessible:"
)
return
redirect
(
url_for
(
"web.index"
))
# check if book has bookmark
...
...
@@ -1364,20 +1374,25 @@ def read_book(book_id, book_format):
ub
.
Bookmark
.
book_id
==
book_id
,
ub
.
Bookmark
.
format
==
book_format
.
upper
()))
.
first
()
if
book_format
.
lower
()
==
"epub"
:
log
.
debug
(
u"Start epub reader for
%
d"
,
book_id
)
return
render_title_template
(
'read.html'
,
bookid
=
book_id
,
title
=
_
(
u"Read a Book"
),
bookmark
=
bookmark
)
elif
book_format
.
lower
()
==
"pdf"
:
log
.
debug
(
u"Start pdf reader for
%
d"
,
book_id
)
return
render_title_template
(
'readpdf.html'
,
pdffile
=
book_id
,
title
=
_
(
u"Read a Book"
))
elif
book_format
.
lower
()
==
"txt"
:
log
.
debug
(
u"Start txt reader for
%
d"
,
book_id
)
return
render_title_template
(
'readtxt.html'
,
txtfile
=
book_id
,
title
=
_
(
u"Read a Book"
))
else
:
for
fileExt
in
[
"mp3"
,
"m4b"
,
"m4a"
]:
if
book_format
.
lower
()
==
fileExt
:
entries
=
db
.
session
.
query
(
db
.
Books
)
.
filter
(
db
.
Books
.
id
==
book_id
)
.
filter
(
common_filters
())
.
first
()
log
.
debug
(
u"Start mp3 listening for
%
d"
,
book_id
)
return
render_title_template
(
'listenmp3.html'
,
mp3file
=
book_id
,
audioformat
=
book_format
.
lower
(),
title
=
_
(
u"Read a Book"
),
entry
=
entries
,
bookmark
=
bookmark
)
for
fileExt
in
[
"cbr"
,
"cbt"
,
"cbz"
]:
if
book_format
.
lower
()
==
fileExt
:
all_name
=
str
(
book_id
)
log
.
debug
(
u"Start comic reader for
%
d"
,
book_id
)
return
render_title_template
(
'readcbr.html'
,
comicfile
=
all_name
,
title
=
_
(
u"Read a Book"
),
extension
=
fileExt
)
# if feature_support['rar']:
...
...
@@ -1388,6 +1403,7 @@ def read_book(book_id, book_format):
# if book_format.lower() == fileext:
# return render_title_template('readcbr.html', comicfile=book_id,
# extension=fileext, title=_(u"Read a Book"), book=book)
log
.
debug
(
u"Error opening eBook. File does not exist or file is not accessible:"
)
flash
(
_
(
u"Error opening eBook. File does not exist or file is not accessible."
),
category
=
"error"
)
return
redirect
(
url_for
(
"web.index"
))
...
...
@@ -1420,7 +1436,7 @@ def show_book(book_id):
matching_have_read_book
=
getattr
(
entries
,
'custom_column_'
+
str
(
config
.
config_read_column
))
have_read
=
len
(
matching_have_read_book
)
>
0
and
matching_have_read_book
[
0
]
.
value
except
KeyError
:
log
.
error
(
"Custom Column No.
%
d is not exis
i
ting in calibre database"
,
config
.
config_read_column
)
log
.
error
(
"Custom Column No.
%
d is not existing in calibre database"
,
config
.
config_read_column
)
have_read
=
None
else
:
...
...
@@ -1442,5 +1458,6 @@ def show_book(book_id):
is_xhr
=
request
.
is_xhr
,
title
=
entries
.
title
,
books_shelfs
=
book_in_shelfs
,
have_read
=
have_read
,
kindle_list
=
kindle_list
,
reader_list
=
reader_list
,
page
=
"book"
)
else
:
log
.
debug
(
u"Error opening eBook. File does not exist or file is not accessible:"
)
flash
(
_
(
u"Error opening eBook. File does not exist or file is not accessible:"
),
category
=
"error"
)
return
redirect
(
url_for
(
"web.index"
))
cps/worker.py
View file @
1da4efec
...
...
@@ -231,7 +231,7 @@ class WorkerThread(threading.Thread):
self
.
queue
.
pop
(
index
)
self
.
UIqueue
.
pop
(
index
)
# if we are deleting entries before the current index, adjust the index
if
index
<=
self
.
current
and
index
:
if
index
<=
self
.
current
and
self
.
current
:
self
.
current
-=
1
self
.
last
=
len
(
self
.
queue
)
...
...
test/Calibre-Web TestSummary.html
View file @
1da4efec
This source diff could not be displayed because it is too large. You can
view the blob
instead.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment