Apply per library restrictions to all endpoints (I hope)

This commit is contained in:
Kovid Goyal 2017-05-18 15:11:11 +05:30
parent e457f12194
commit cf11444a41
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 19 additions and 15 deletions

View File

@ -168,7 +168,7 @@ def book(ctx, rd, book_id, library_id):
book_id = None
except Exception:
book_id = None
if book_id is None or not db.has_id(book_id):
if book_id is None or not ctx.has_id(rd, db, book_id):
raise HTTPNotFound('Book with id %r does not exist' % oid)
category_urls = rd.query.get('category_urls', 'true').lower()
device_compatible = rd.query.get('device_compatible', 'false').lower()
@ -216,8 +216,9 @@ def books(ctx, rd, library_id):
device_compatible = rd.query.get('device_compatible', 'false').lower() == 'true'
device_for_template = rd.query.get('device_for_template', None)
ans = {}
allowed_book_ids = ctx.allowed_book_ids(rd, db)
for book_id in ids:
if not db.has_id(book_id):
if book_id not in allowed_book_ids:
ans[book_id] = None
continue
data, lm = book_to_json(
@ -483,7 +484,7 @@ def books_in(ctx, rd, encoded_category, encoded_item, library_id):
raise HTTPNotFound('%s is not a valid sort field'%sort)
if dname in ('allbooks', 'newest'):
ids = db.all_book_ids()
ids = ctx.allowed_book_ids(rd, db)
elif dname == 'search':
try:
ids = ctx.search(rd, db, 'search:"%s"'%ditem)
@ -497,7 +498,7 @@ def books_in(ctx, rd, encoded_category, encoded_item, library_id):
if dname == 'news':
dname = 'tags'
ids = db.get_books_for_category(dname, cid)
ids = db.get_books_for_category(dname, cid) & ctx.allowed_book_ids(rd, db)
ids = db.multisort(fields=[(sfield, sort_order == 'asc')], ids_to_sort=ids)
total_num = len(ids)

View File

@ -130,7 +130,7 @@ def book_manifest(ctx, rd, book_id, fmt):
force_reload = rd.query.get('force_reload') == '1'
if plugin_for_input_format(fmt) is None:
raise HTTPNotFound('The format %s cannot be viewed' % fmt.upper())
if not db.has_id(book_id):
if not ctx.has_id(rd, db, book_id):
raise HTTPNotFound('No book with id: %s in library: %s' % (book_id, library_id))
with db.safe_read_lock:
fm = db.format_metadata(book_id, fmt)
@ -166,7 +166,7 @@ def book_manifest(ctx, rd, book_id, fmt):
@endpoint('/book-file/{book_id}/{fmt}/{size}/{mtime}/{+name}', types={'book_id':int, 'size':int, 'mtime':int})
def book_file(ctx, rd, book_id, fmt, size, mtime, name):
db, library_id = get_library_data(ctx, rd)[:2]
if not db.has_id(book_id):
if not ctx.has_id(rd, db, book_id):
raise HTTPNotFound('No book with id: %s in library: %s' % (book_id, library_id))
bhash = book_hash(db.library_id, book_id, fmt, size, mtime)
base = abspath(os.path.join(books_cache_dir(), 'f'))
@ -190,13 +190,14 @@ def get_last_read_position(ctx, rd, library_id, which):
db = get_db(ctx, rd, library_id)
user = rd.username or None
ans = {}
allowed_book_ids = ctx.allowed_book_ids(rd, db)
for item in which.split('_'):
book_id, fmt = item.partition('-')[::2]
try:
book_id = int(book_id)
except Exception:
continue
if not db.has_id(book_id):
if book_id not in allowed_book_ids:
continue
key = '{}:{}'.format(book_id, fmt)
ans[key] = db.get_last_read_positions(book_id, fmt, user)
@ -207,7 +208,7 @@ def get_last_read_position(ctx, rd, library_id, which):
def set_last_read_position(ctx, rd, library_id, book_id, fmt):
db = get_db(ctx, rd, library_id)
user = rd.username or None
if not db.has_id(book_id):
if not ctx.has_id(rd, db, book_id):
raise HTTPNotFound('No book with id {} found'.format(book_id))
try:
data = jsonlib.load(rd.request_body_file)

View File

@ -8,7 +8,7 @@ from functools import partial
from calibre import as_unicode
from calibre.db.cli import module_for_cmd
from calibre.srv.errors import HTTPBadRequest, HTTPNotFound
from calibre.srv.errors import HTTPBadRequest, HTTPNotFound, HTTPForbidden
from calibre.srv.routes import endpoint, msgpack_or_json
from calibre.srv.utils import get_library_data
from calibre.utils.serialize import MSGPACK_MIME, json_loads, msgpack_loads
@ -38,6 +38,8 @@ def cdb_run(ctx, rd, which, version):
except Exception:
raise HTTPBadRequest('args are not valid encoded data')
db = get_library_data(ctx, rd, strict_library_id=True)[0]
if ctx.restriction_for(rd, db):
raise HTTPForbidden('Cannot use the command-line db interface with a user who has per library restrictions')
if getattr(m, 'needs_srv_ctx', False):
args = [ctx] + list(args)
try:

View File

@ -312,9 +312,9 @@ def book_metadata(ctx, rd, book_id):
raise HTTPNotFound(_('No book with id: {} in library: {}').format(book_id, library_id))
if not book_id:
all_ids = db.books_in_virtual_library(vl) if vl else db.all_book_ids()
all_ids = ctx.allowed_book_ids(rd, db)
book_id = random.choice(tuple(all_ids))
elif not db.has_id(book_id):
elif not ctx.has_id(rd, db, book_id):
notfound()
data = book_as_json(db, book_id)
if data is None:

View File

@ -280,7 +280,7 @@ def get(ctx, rd, what, book_id, library_id):
if db is None:
raise HTTPNotFound('Library %r not found' % library_id)
with db.safe_read_lock:
if not db.has_id(book_id):
if not ctx.has_id(rd, db, book_id):
raise HTTPNotFound('Book with id %r does not exist' % book_id)
library_id = db.server_library_id # in case library_id was None
if what == 'thumb':

View File

@ -367,8 +367,8 @@ class RequestContext(object):
ans += '?' + urlencode(q)
return ans
def all_book_ids(self):
return self.db.all_book_ids()
def allowed_book_ids(self):
return self.ctx.allowed_book_ids(self.rd, self.db)
@property
def outheaders(self):
@ -414,7 +414,7 @@ def get_all_books(rc, which, page_url, up_url, offset=0):
ascending = which == 'title'
feed_title = {'newest':_('Newest'), 'title': _('Title')}.get(which, which)
feed_title = default_feed_title + ' :: ' + _('By %s') % feed_title
ids = rc.all_book_ids()
ids = rc.allowed_book_ids()
return get_acquisition_feed(rc, ids, offset, page_url, up_url,
id_='calibre-all:'+sort, sort_by=sort, ascending=ascending,
feed_title=feed_title)