1
0
mirror of https://github.com/janeczku/calibre-web synced 2024-11-30 21:40:00 +00:00

Add HTTP-BASIC Auth for OPDS downloads

This commit is contained in:
Jan Broer 2015-10-13 19:06:37 +02:00
parent 6b4ddbe946
commit 350285607b
2 changed files with 48 additions and 10 deletions

View File

@ -55,7 +55,7 @@
{% for format in entry.data %} {% for format in entry.data %}
<link rel="http://opds-spec.org/acquisition" <link rel="http://opds-spec.org/acquisition"
href="{{ url_for('get_download_link', book_id=entry.id, format=format.format|lower)}}"{% if format.format|lower == "epub" %} href="{{ url_for('get_opds_download_link', book_id=entry.id, format=format.format|lower)}}"{% if format.format|lower == "epub" %}
type="application/epub+zip"/> type="application/epub+zip"/>
{% else %} {% else %}
type="application/x-mobipocket-ebook"/> type="application/x-mobipocket-ebook"/>

View File

@ -3,7 +3,7 @@
import mimetypes import mimetypes
mimetypes.add_type('application/xhtml+xml','.xhtml') mimetypes.add_type('application/xhtml+xml','.xhtml')
from flask import Flask, render_template, session, request, redirect, url_for, send_from_directory, make_response, g, flash, abort from flask import Flask, render_template, session, request, Response, redirect, url_for, send_from_directory, make_response, g, flash, abort
from cps import db, config, ub, helper from cps import db, config, ub, helper
import os import os
from sqlalchemy.sql.expression import func from sqlalchemy.sql.expression import func
@ -14,6 +14,7 @@ from flask.ext.principal import Principal, Identity, AnonymousIdentity, identity
import requests, zipfile import requests, zipfile
from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.security import generate_password_hash, check_password_hash
from functools import wraps from functools import wraps
import base64
app = (Flask(__name__)) app = (Flask(__name__))
@ -32,16 +33,42 @@ def load_user(id):
@lm.header_loader @lm.header_loader
def load_user_from_header(header_val): def load_user_from_header(header_val):
print header_val
if header_val.startswith('Basic '): if header_val.startswith('Basic '):
header_val = header_val.replace('Basic ', '', 1) header_val = header_val.replace('Basic ', '', 1)
print header_val
try: try:
header_val = base64.b64decode(header_val) header_val = base64.b64decode(header_val)
print header_val basic_username = header_val.split(':')[0]
basic_password = header_val.split(':')[1]
#print basic_username
#print basic_password
except TypeError: except TypeError:
pass pass
return ub.session.query(ub.User).filter(ub.User.password == header_val).first() user = ub.session.query(ub.User).filter(ub.User.nickname == basic_username).first()
if user and check_password_hash(user.password, basic_password):
return user
return
def check_auth(username, password):
user = ub.session.query(ub.User).filter(ub.User.nickname == username).first()
if user and check_password_hash(user.password, password):
return True
else:
return False
def authenticate():
return Response(
'Could not verify your access level for that URL.\n'
'You have to login with proper credentials', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'})
def requires_basic_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
#simple pagination for the feed #simple pagination for the feed
class Pagination(object): class Pagination(object):
@ -84,6 +111,7 @@ def url_for_other_page(page):
app.jinja_env.globals['url_for_other_page'] = url_for_other_page app.jinja_env.globals['url_for_other_page'] = url_for_other_page
def admin_required(f): def admin_required(f):
""" """
Checks if current_user.role == 1 Checks if current_user.role == 1
@ -169,6 +197,17 @@ def feed_hot():
response.headers["Content-Type"] = "application/xml" response.headers["Content-Type"] = "application/xml"
return response return response
@app.route("/feed/download/<int:book_id>/<format>")
@requires_basic_auth
def get_opds_download_link(book_id, format):
format = format.split(".")[0]
book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
data = db.session.query(db.Data).filter(db.Data.book == book.id).filter(db.Data.format == format.upper()).first()
helper.update_download(book_id, int(current_user.id))
response = make_response(send_from_directory(os.path.join(config.DB_ROOT, book.path), data.name + "." +format))
response.headers["Content-Disposition"] = "attachment; filename=%s.%s" % (data.name, format)
return response
@app.route("/", defaults={'page': 1}) @app.route("/", defaults={'page': 1})
@app.route('/page/<int:page>') @app.route('/page/<int:page>')
def index(page): def index(page):
@ -471,7 +510,7 @@ def profile():
downloads.append(db.session.query(db.Books).filter(db.Books.id == book.book_id).first()) downloads.append(db.session.query(db.Books).filter(db.Books.id == book.book_id).first())
if request.method == "POST": if request.method == "POST":
to_save = request.form.to_dict() to_save = request.form.to_dict()
print to_save #print to_save
if to_save["password"]: if to_save["password"]:
content.password = generate_password_hash(to_save["password"]) content.password = generate_password_hash(to_save["password"])
if to_save["kindle_mail"] and to_save["kindle_mail"] != content.kindle_mail: if to_save["kindle_mail"] and to_save["kindle_mail"] != content.kindle_mail:
@ -583,8 +622,7 @@ def edit_book(book_id):
book = db.session.query(db.Books).filter(db.Books.id == book_id).first() book = db.session.query(db.Books).filter(db.Books.id == book_id).first()
if request.method == 'POST': if request.method == 'POST':
to_save = request.form.to_dict() to_save = request.form.to_dict()
print to_save #print to_save
#print title_sort(to_save["book_title"])
book.title = to_save["book_title"] book.title = to_save["book_title"]
book.authors[0].name = to_save["author_name"] book.authors[0].name = to_save["author_name"]
@ -603,7 +641,7 @@ def edit_book(book_id):
for tag in to_save["tags"].split(","): for tag in to_save["tags"].split(","):
if tag.strip(): if tag.strip():
print tag #print tag
is_tag = db.session.query(db.Tags).filter(db.Tags.name.like('%' + tag.strip() + '%')).first() is_tag = db.session.query(db.Tags).filter(db.Tags.name.like('%' + tag.strip() + '%')).first()
if is_tag: if is_tag:
book.tags.append(is_tag) book.tags.append(is_tag)