def GET(self, key): if not is_admin(): return render_template('permission_denied', web.ctx.path, "Permission denied.") edition = web.ctx.site.get(key) if not edition: raise web.notfound() if edition.ocaid: ebook_key = "ebooks/" + edition.ocaid ebook = web.ctx.site.store.get(ebook_key) or {} else: ebook = None i = web.input(updatestatus=None) if i.updatestatus == 't': edition.update_loan_status() edition_loans = get_edition_loans(edition) user_loans = [] user = accounts.get_current_user() if user: user_loans = get_loans(user) return render_template("borrow_admin", edition, edition_loans, ebook, user_loans, web.ctx.ip)
def GET(self): try: if 'counts_db' in config.admin: stats = admin.get_stats() else: stats = None except Exception: logger.error("Error in getting stats", exc_info=True) stats = None blog_posts = get_blog_feeds() lending_list = config.get("home", {}).get("lending_list") returncart_list = config.get("home", {}).get("returncart_list") user = accounts.get_current_user() loans = borrow.get_loans(user) if user else None popular_available, popular_waitlist = popular_carousel() return render_template( "home/index", stats=stats, blog_posts=blog_posts, lending_list=lending_list, returncart_list=returncart_list, user=user, loans=loans, popular_books=popular_available, waitlisted_books=popular_waitlist )
def GET(self): if not support_db: return "The Openlibrary support system is currently offline. Please try again later." i = web.input(path=None) user = accounts.get_current_user() email = user and user.email return render_template("support", email=email, url=i.path)
def _get_prevnext(self, caseid): """Redirects prev and next urls. """ i = web.input(all="false", filter="new", _method="GET") sort = "status" desc = "false" cases = support_db.get_all_cases(i.filter, summarise=False, sortby=sort, desc=desc) cases = list(cases) if i.all == "false": current_user = accounts.get_current_user() email = current_user.get_email() cases = [x for x in cases if x.assignee == email] try: index = [case.caseid for case in cases].index(caseid) except ValueError: return None, None if index > 0: case = cases[index-1] prev = "/admin/support/" + str(case.caseno) + "?" + urllib.urlencode(i) else: prev = None if index < len(cases)-1: case = cases[index+1] next = "/admin/support/" + str(case.caseno) + "?" + urllib.urlencode(i) else: next = None return prev, next
def POST(self): if not support_db: return "Couldn't initialise connection to support database" form = web.input() email = form.get("email", "") topic = form.get("topic", "") description = form.get("question", "") url = form.get("url", "") user = accounts.get_current_user() useragent = web.ctx.env.get("HTTP_USER_AGENT","") if not all([email, topic, description]): return "" c = support_db.create_case(creator_name = user and user.get_name() or "", creator_email = email, creator_useragent = useragent, creator_username = user and user.get_username() or "", subject = topic, description = description, url = url, assignee = config.get("support_case_default_address","*****@*****.**")) # Send an email to the creator of the case subject = "Case #%s: %s"%(c.caseno, topic) message = render_template("email/support_case", c) web.sendmail(config.get("support_case_control_address","*****@*****.**"), email, subject, message) return render_template("email/case_created", c)
def POST(self): form = web.input() email = form.get("email", "") topic = form.get("topic", "") description = form.get("question", "") url = form.get("url", "") user = accounts.get_current_user() useragent = web.ctx.env.get("HTTP_USER_AGENT","") if not all([email, topic, description]): return "" default_assignees = config.get("support_default_assignees",{}) topic_key = str(topic.replace(" ","_").lower()) if topic_key in default_assignees: assignee = default_assignees.get(topic_key) else: assignee = default_assignees.get("default", "*****@*****.**") stats.increment("ol.support.all") subject = "Support case *%s*"%topic url = web.ctx.home + url displayname = user and user.get_name() or "" username = user and user.get_username() or "" message = SUPPORT_EMAIL_TEMPLATE % locals() sendmail(email, assignee, subject, message) return render_template("email/case_created", assignee)
def GET(self): i = web.input(path=None) user = accounts.get_current_user() email = user and user.email template = render_template("support", email=email, url=i.path) template.v2 = True return template
def POST(self, work_id): user = accounts.get_current_user() i = web.input(edition_id=None, action="add", redir=False, bookshelf_id=None) key = i.edition_id if i.edition_id else ('/works/OL%sW' % work_id) if not user: raise web.seeother('/account/login?redirect=%s' % key) username = user.key.split('/')[2] current_status = models.Bookshelves.get_users_read_status_of_work(username, work_id) try: bookshelf_id = int(i.bookshelf_id) if bookshelf_id not in models.Bookshelves.PRESET_BOOKSHELVES.values(): raise ValueError except ValueError: return delegate.RawText(simplejson.dumps({ 'error': 'Invalid bookshelf' }), content_type="application/json") if bookshelf_id == current_status: work_bookshelf = models.Bookshelves.remove( username=username, work_id=work_id, bookshelf_id=i.bookshelf_id) else: edition_id = int(i.edition_id.split('/')[2][2:-1]) if i.edition_id else None work_bookshelf = models.Bookshelves.add( username=username, bookshelf_id=bookshelf_id, work_id=work_id, edition_id=edition_id) if i.redir: raise web.seeother(key) return delegate.RawText(simplejson.dumps({ 'bookshelves_affected': work_bookshelf }), content_type="application/json")
def upload(self, key, i): """Uploads a cover to coverstore and returns the response.""" olid = key.split("/")[-1] if i.file is not None and hasattr(i.file, 'value'): data = i.file.value else: data = None if i.url and i.url.strip() == "http://": i.url = "" user = accounts.get_current_user() params = dict(author=user and user.key, data=data, source_url=i.url, olid=olid, ip=web.ctx.ip) upload_url = '%s/%s/upload2' % (get_coverstore_url(), self.cover_category) if upload_url.startswith("//"): upload_url = "http:" + upload_url try: response = urllib2.urlopen(upload_url, urllib.urlencode(params)) out = response.read() except urllib2.HTTPError as e: out = e.read() return web.storage(simplejson.loads(out))
def add_cover(cover_url, ekey): olid = ekey.split("/")[-1] coverstore_url = config.get('coverstore_url').rstrip('/') upload_url = coverstore_url + '/b/upload2' if upload_url.startswith("//"): upload_url = "{0}:{1}".format(web.ctx.get("protocol", "http"), upload_url) user = accounts.get_current_user() params = { 'author': user.key, 'data': None, 'source_url': cover_url, 'olid': olid, 'ip': web.ctx.ip, } for attempt in range(10): try: res = urllib.urlopen(upload_url, urllib.urlencode(params)) except IOError: print 'retry, attempt', attempt sleep(2) continue body = res.read() if body != '': reply = json.loads(body) if res.getcode() == 200 and body != '': if 'id' in reply: break print 'retry, attempt', attempt sleep(2) if not reply or reply.get('message') == 'Invalid URL': return cover_id = int(reply['id']) return cover_id
def create_edition_from_amazon_metadata(isbn): """Fetches amazon metadata by isbn from affiliates API, attempts to create OL edition from metadata, and returns the resulting edition key `/key/OL..M` if successful or None otherwise """ md = get_amazon_metadata(isbn) if md: # Save token of currently logged in user (or no-user) account = accounts.get_current_user() auth_token = account.generate_login_code() if account else '' try: # Temporarily behave (act) as ImportBot for import tmp_account = accounts.find(username='******') web.ctx.conn.set_auth_token(tmp_account.generate_login_code()) reply = load(clean_amazon_metadata_for_load(md), account=tmp_account) except Exception as e: web.ctx.conn.set_auth_token(auth_token) raise e # Return auth token to original user or no-user web.ctx.conn.set_auth_token(auth_token) if reply and reply.get('success'): return reply['edition']['key']
def POST_reopencase(self, form, case): user = accounts.get_current_user() by = user.get_email() text = "Case reopened" case.add_worklog_entry(by = by, text = text) case.change_status("new", by) add_flash_message("info", "Case reopened")
def GET(self, key='loans'): user = accounts.get_current_user() is_public = user.preferences().get('public_readlog', 'no') == 'yes' readlog = ReadingLog() works = readlog.get_works(key) return render['account/books']( works, key, reading_log=readlog.reading_log_counts, lists=readlog.lists, user=user, public=is_public)
def POST(self, key): i = web.input("v", _comment=None) v = i.v and safeint(i.v, None) if v is None: raise web.seeother(web.changequery({})) user = accounts.get_current_user() is_admin = user and user.key in [m.key for m in web.ctx.site.get('/usergroup/admin').members] if not (is_admin and web.ctx.site.can_write(key)): return render.permission_denied(web.ctx.fullpath, "Permission denied to edit " + key + ".") thing = web.ctx.site.get(key, i.v) if not thing: raise web.notfound() def revert(thing): if thing.type.key == "/type/delete" and thing.revision > 1: prev = web.ctx.site.get(thing.key, thing.revision-1) if prev.type.key in ["/type/delete", "/type/redirect"]: return revert(prev) else: prev._save("revert to revision %d" % prev.revision) return prev elif thing.type.key == "/type/redirect": redirect = web.ctx.site.get(thing.location) if redirect and redirect.type.key not in ["/type/delete", "/type/redirect"]: return redirect else: # bad redirect. Try the previous revision prev = web.ctx.site.get(thing.key, thing.revision-1) return revert(prev) else: return thing def process(value): if isinstance(value, list): return [process(v) for v in value] elif isinstance(value, client.Thing): if value.key: if value.type.key in ['/type/delete', '/type/revert']: return revert(value) else: return value else: for k in value.keys(): value[k] = process(value[k]) return value else: return value for k in thing.keys(): thing[k] = process(thing[k]) comment = i._comment or "reverted to revision %d" % v thing._save(comment) raise web.seeother(key)
def POST_closecase(self, form, case): user = accounts.get_current_user() by = user.get_email() text = "Case closed" case.add_worklog_entry(by = by, text = text) case.change_status("closed", by) add_flash_message("info", "Case closed") raise web.redirect("/admin/support")
def __init__(self, user=None): self.user = user or accounts.get_current_user() #self.user.update_loan_status() self.KEYS = { 'waitlists': self.get_waitlisted_editions, 'loans': self.get_loans, 'want-to-read': self.get_want_to_read, 'currently-reading': self.get_currently_reading, 'already-read': self.get_already_read }
def save(self, formdata): """Update work and edition documents according to the specified formdata.""" comment = formdata.pop('_comment', '') user = accounts.get_current_user() delete = user and user.is_admin() and formdata.pop('_delete', '') formdata = utils.unflatten(formdata) work_data, edition_data = self.process_input(formdata) self.process_new_fields(formdata) saveutil = DocSaveHelper() if delete: if self.edition: self.delete(self.edition.key, comment=comment) if self.work and self.work.edition_count == 0: self.delete(self.work.key, comment=comment) return if work_data: # Create any new authors that were added for i, author in enumerate(work_data.get("authors") or []): if author['author']['key'] == "__new__": a = self.new_author(formdata['authors'][i]) author['author']['key'] = a.key saveutil.save(a) if self.work is None: self.work = self.new_work(self.edition) edition_data.works = [{'key': self.work.key}] self.work.update(work_data) saveutil.save(self.work) if self.edition and edition_data: identifiers = edition_data.pop('identifiers', []) self.edition.set_identifiers(identifiers) classifications = edition_data.pop('classifications', []) self.edition.set_classifications(classifications) self.edition.set_physical_dimensions(edition_data.pop('physical_dimensions', None)) self.edition.set_weight(edition_data.pop('weight', None)) self.edition.set_toc_text(edition_data.pop('table_of_contents', '')) if edition_data.pop('translation', None) != 'yes': edition_data.translation_of = None edition_data.translated_from = None self.edition.update(edition_data) saveutil.save(self.edition) saveutil.commit(comment=comment, action="edit-book")
def verify_password(password): user = accounts.get_current_user() if user is None: return False try: username = user.key.split('/')[-1] web.ctx.site.login(username, password) except ClientException: return False return True
def POST(self): user = accounts.get_current_user() key = user.key + '/preferences' prefs = web.ctx.site.get(key) d = (prefs and prefs.dict()) or {'key': key, 'type': {'key': '/type/object'}} d['notifications'] = web.input() web.ctx.site.save(d, 'save notifications') add_flash_message('note', _("Notification preferences have been updated successfully.")) web.seeother("/account")
def POST_closecase(self, form, case): # Next/Prev links should be computed before the case is updated prev_url, next_url = self._get_prevnext(case.caseid) user = accounts.get_current_user() by = user.get_email() text = "Case closed" case.add_worklog_entry(by = by, text = text) case.change_status("closed", by) add_flash_message("info", "Case closed") raise web.redirect(next_url or "/admin/support")
def GET(self, typ = "new"): current_user = accounts.get_current_user() if not support_db: return render_template("admin/cases", None, None, True, False) i = web.input(sort="status", desc = "false", all = "false") sortby = i['sort'] desc = i['desc'] cases = support_db.get_all_cases(typ, summarise = False, sortby = sortby, desc = desc) if i['all'] == "false": cases = (x for x in cases if x.assignee == current_user.get_email()) summary = support_db.get_all_cases(typ, summarise = True, user = current_user.get_email()) else: summary = support_db.get_all_cases(typ, summarise = True) total = sum(int(x) for x in summary.values()) desc = desc == "false" and "true" or "false" return render_template("admin/cases", summary, total, cases, desc)
def _prevent_ocaid_deletion(self, edition): # Allow admins to modify ocaid user = accounts.get_current_user() if user and user.is_admin(): return # read ocaid from form data try: ocaid = [id['value'] for id in edition.get('identifiers', []) if id['name'] == 'ocaid'][0] except IndexError: ocaid = None # 'self.edition' is the edition doc from the db and 'edition' is the doc from formdata if self.edition and self.edition.get('ocaid') and self.edition.get('ocaid') != ocaid: logger.warn("Attempt to change ocaid of %s from %r to %r.", self.edition.key, self.edition.get('ocaid'), ocaid) raise ValidationException("Changing Internet Archive ID is not allowed.")
def POST(self): # if not support_db: # return "Couldn't initialise connection to support database" form = web.input() email = form.get("email", "") topic = form.get("topic", "") description = form.get("question", "") url = form.get("url", "") user = accounts.get_current_user() useragent = web.ctx.env.get("HTTP_USER_AGENT", "") if not all([email, topic, description]): return "" default_assignees = config.get("support_default_assignees", {}) topic_key = str(topic.replace(" ", "_").lower()) if topic_key in default_assignees: # This is set to False to prevent cases from being created # even if there is a designated assignee. This prevents # the database from being updated. create_case = False assignee = default_assignees.get(topic_key) else: create_case = False assignee = default_assignees.get("default", "*****@*****.**") if create_case: c = support_db.create_case( creator_name=user and user.get_name() or "", creator_email=email, creator_useragent=useragent, creator_username=user and user.get_username() or "", subject=topic, description=description, url=url, assignee=assignee, ) stats.increment("support.all") else: stats.increment("support.all") subject = "Support case *%s*" % topic url = web.ctx.home + url displayname = user and user.get_name() or "" username = user and user.get_username() or "" message = SUPPORT_EMAIL_TEMPLATE % locals() sendmail(email, assignee, subject, message) return render_template("email/case_created", assignee)
def POST(self): f = forms.ChangeEmail() i = web.input() if not f.validates(i): return render['account/email'](self.get_email(), f) else: user = accounts.get_current_user() username = user.key.split('/')[-1] displayname = user.displayname or username send_email_change_email(username, i.email) title = _("Hi %(user)s", user=user.displayname or username) message = _("We've sent an email to %(email)s. You'll need to read that and click on the verification link to update your email.", email=i.email) return render.message(title, message)
def POST_update(self, form, case): casenote = form.get("casenote2", False) assignee = form.get("assignee", False) user = accounts.get_current_user() by = user.get_email() text = casenote or "" if case.status == "closed": case.change_status("new", by) if assignee != case.assignee: case.reassign(assignee, by, text) subject = "Case #%s has been assigned to you"%case.caseno message = render_template("admin/email_reassign", case, text) web.sendmail(config.get("support_case_control_address","*****@*****.**"), assignee, subject, message) else: case.add_worklog_entry(by = by, text = text) add_flash_message("info", "Case updated")
def POST(self): f = forms.ChangePassword() i = web.input() if not f.validates(i): return render['account/password'](f) user = accounts.get_current_user() username = user.key.split("/")[-1] if self.try_login(username, i.password): accounts.update_account(username, password=i.new_password) add_flash_message('note', _('Your password has been updated successfully.')) raise web.seeother('/account') else: f.note = "Invalid password" return render['account/password'](f)
def POST_sendreply(self, form, case): user = accounts.get_current_user() assignee = case.assignee casenote = form.get("casenote1", "") casenote = "%s replied:\n\n%s"%(user.get_name(), casenote) case.add_worklog_entry(by = user.get_email(), text = casenote) case.change_status("replied", user.get_email()) email_to = form.get("email", False) subject = "Case #%s: %s"%(case.caseno, case.subject) if assignee != user.get_email(): case.reassign(user.get_email(), user.get_name(), "") if email_to: message = render_template("admin/email", case, casenote) web.sendmail(config.get("support_case_control_address","*****@*****.**"), email_to, subject, message) add_flash_message("info", "Reply sent") raise web.redirect("/admin/support")
def GET(self, key): if not is_admin(): return render_template('permission_denied', web.ctx.path, "Permission denied.") edition = web.ctx.site.get(key) if not edition: raise web.notfound() edition_loans = get_edition_loans(edition) user_loans = [] user = accounts.get_current_user() if user: user_loans = get_loans(user) return render_template("borrow_admin_no_update", edition, edition_loans, user_loans, web.ctx.ip)
def GET(self, item_id): i = web.input(_method='GET', callback=None, loan=None, token=None) resource_id = 'bookreader:%s' % item_id content_type = "application/json" # check that identifier is valid user = accounts.get_current_user() auth_json = simplejson.dumps( get_ia_auth_dict(user, item_id, resource_id, i.loan, i.token ) ) output = auth_json if i.callback: content_type = "text/javascript" output = '%s ( %s );' % (i.callback, output) return delegate.RawText(output, content_type=content_type)
def _prevent_system_subjects_deletion(self, work): # Allow admins to modify system systems user = accounts.get_current_user() if user and user.is_admin(): return # Note: work is the new work object from the formdata and self.work is the work doc from the database. old_subjects = self.work and self.work.get("subjects") or [] # If condition is added to handle the possibility of bad data set_old_subjects = set(s.lower() for s in old_subjects if isinstance(s, basestring)) set_new_subjects = set(s.lower() for s in work.subjects) for s in SYSTEM_SUBJECTS: # if a system subject has been removed if s.lower() in set_old_subjects and s.lower() not in set_new_subjects: work_key = self.work and self.work.key logger.warn("Prevented removal of system subject %r from %s.", s, work_key) work.subjects.append(s)
def POST(self, path): book = get_book(path) record = get_scan_record(path) user = accounts.get_current_user() delegate.admin_login() q = { 'key': '/scan_record' + path, 'scan_status': { 'connect': 'update', 'value': 'WAITING_FOR_BOOK' }, 'sponsor': { 'connect': 'update', 'key': user.key }, 'request_date': { 'connect': 'update', 'value': datetime.datetime.utcnow().isoformat() } } try: web.ctx.site.write(q) finally: web.ctx.headers = [] def get_to(): if config.get('plugin_scod') is not None: return config.plugin_scod.get('email_recipients', []) else: return config.get('scan_email_recipients', []) to = get_to() if to: scan_record = get_scan_record(path) message = render.scan_request_email(book, scan_record) web.sendmail(config.from_address, to, message.subject.strip(), message) to = get_email(user) message = render.scan_waiting_email(book, scan_record) web.sendmail(config.from_address, to, message.subject.strip(), message) return render.scan_inprogress(book)
def add_cover(cover_url, ekey, account=None): """ Adds a cover to coverstore and returns the cover id. :param str cover_url: URL of cover image :param str ekey: Edition key /book/OL..M :rtype: int or None :return: Cover id, or None if upload did not succeed """ olid = ekey.split("/")[-1] coverstore_url = config.get('coverstore_url').rstrip('/') upload_url = coverstore_url + '/b/upload2' if upload_url.startswith("//"): upload_url = "{0}:{1}".format(web.ctx.get("protocol", "http"), upload_url) user = account or accounts.get_current_user() params = { 'author': user.get('key') or user.get('_key'), 'data': None, 'source_url': cover_url, 'olid': olid, 'ip': web.ctx.ip, } reply = None for attempt in range(10): try: res = urllib.urlopen(upload_url, urllib.urlencode(params)) except IOError: sleep(2) continue body = res.read() if res.getcode() == 500: raise CoverNotSaved(body) if body not in ['', 'None']: reply = json.loads(body) if res.getcode() == 200 and 'id' in reply: break sleep(2) if not reply or reply.get('message') == 'Invalid URL': return cover_id = int(reply['id']) return cover_id
def create_edition_from_amazon_metadata(id_, id_type='isbn'): """Fetches Amazon metadata by id from Amazon Product Advertising API, attempts to create OL edition from metadata, and returns the resulting edition key `/key/OL..M` if successful or None otherwise. :param str id_: The item id: isbn (10/13), or Amazon ASIN. :param str id_type: 'isbn' or 'asin'. :return: Edition key '/key/OL..M' or None :rtype: str or None """ md = get_amazon_metadata(id_, id_type=id_type) if md and md.get('product_group') == 'Book': with accounts.RunAs('ImportBot'): reply = load( clean_amazon_metadata_for_load(md), account=accounts.get_current_user()) if reply and reply.get('success'): return reply['edition'].get('key')
def POST(self): user = accounts.get_current_user() key = user.key + '/preferences' prefs = web.ctx.site.get(key) d = (prefs and prefs.dict()) or { 'key': key, 'type': { 'key': '/type/object' } } d['notifications'] = web.input() web.ctx.site.save(d, 'save notifications') add_flash_message( 'note', _("Notification preferences have been updated successfully.")) web.seeother("/account")
def POST(self, key): doc = web.ctx.site.get(key) if doc is None or doc.type.key != "/type/library": raise web.notfound() elif not web.ctx.site.can_write(key): raise render_template("permission_denied") else: i = web.input(note="") user = accounts.get_current_user() author = user and {"key": user.key} timestamp = {"type": "/type/datetime", "value": datetime.datetime.utcnow().isoformat()} note = {"note": i.note, "author": {"key": user.key}, "timestamp": timestamp} if not doc.notes: doc.notes = [] doc.notes.append(note) doc._save(comment="Added a note.") raise web.seeother(key)
def GET(self): user = accounts.get_current_user() username = user.key.split('/')[-1] books = Bookshelves.get_users_logged_books(username, limit=10000) csv = [] csv.append('Work Id,Edition Id,Bookshelf\n') mapping = {1: 'Want to Read', 2: 'Currently Reading', 3: 'Already Read'} for book in books: row = [ 'OL{}W'.format(book['work_id']), 'OL{}M'.format(book['edition_id']) if book['edition_id'] else '', '{}\n'.format(mapping[book['bookshelf_id']]), ] csv.append(','.join(row)) web.header('Content-Type', 'text/csv') web.header( 'Content-disposition', 'attachment; filename=OpenLibrary_ReadingLog.csv' ) csv = ''.join(csv) return delegate.RawText(csv, content_type="text/csv")
def POST(self, work_id): """ Add a note to a work (or a work and an edition) GET params: - edition_id str (optional) - redir bool: if patron not logged in, redirect back to page after login :param str work_id: e.g. OL123W :rtype: json :return: the note """ user = accounts.get_current_user() i = web.input(notes=None, edition_id=None, redir=None) edition_id = int( extract_numeric_id_from_olid(i.edition_id)) if i.edition_id else -1 if not user: raise web.seeother('/account/login?redirect=/works/%s' % work_id) username = user.key.split('/')[2] def response(msg, status="success"): return delegate.RawText(json.dumps({ status: msg }), content_type="application/json") if i.notes is None: Booknotes.remove(username, work_id, edition_id=edition_id) return response('removed note') Booknotes.add( username=username, work_id=work_id, notes=i.notes, edition_id=edition_id ) if i.redir: raise web.seeother("/works/%s" % work_id) return response('note added')
def POST(self, work_id): user = accounts.get_current_user() if not user: raise web.seeother('/account/login') data = json.loads(web.data()) Observations.persist_observation( data['username'], work_id, data['observation'], data['action'] ) def response(msg, status="success"): return delegate.RawText(json.dumps({ status: msg }), content_type="application/json") return response('Observations added')
def GET(self, typ="new"): i = web.input(sort="status", desc="false", all="false", filter="new") typ = i.filter current_user = accounts.get_current_user() if not support_db: return render_template("admin/cases", None, None, True, False) sortby = i['sort'] desc = i['desc'] cases = support_db.get_all_cases(typ, summarise=False, sortby=sortby, desc=desc) if i['all'] == "false": email = current_user.get_email() cases = (x for x in cases if x.assignee == email) summary = support_db.get_all_cases(typ, summarise=True, user=email) else: summary = support_db.get_all_cases(typ, summarise=True) total = sum(int(x) for x in summary.values()) desc = desc == "false" and "true" or "false" return render_template("admin/cases", summary, total, cases, desc)
def GET(self, key): if not is_admin(): return render_template( 'permission_denied', web.ctx.path, "Permission denied." ) edition = web.ctx.site.get(key) if not edition: raise web.notfound() edition_loans = get_edition_loans(edition) user_loans = [] user = accounts.get_current_user() if user: user_loans = get_loans(user) return render_template( "borrow_admin_no_update", edition, edition_loans, user_loans, web.ctx.ip )
def GET(self, key='loans'): i = web.input(page=1) user = accounts.get_current_user() is_public = user.preferences().get('public_readlog', 'no') == 'yes' readlog = ReadingLog() sponsorships = get_sponsored_editions(user) if key == 'sponsorships': books = (web.ctx.site.get( web.ctx.site.things({ 'type': '/type/edition', 'isbn_%s' % len(s['isbn']): s['isbn'] })[0]) for s in sponsorships) else: books = readlog.get_works(key, page=i.page) page = render['account/books']( books, key, sponsorship_count=len(sponsorships), reading_log_counts=readlog.reading_log_counts, lists=readlog.lists, user=user, public=is_public ) page.v2 = True return page
def GET(self, key): edition = web.ctx.site.get(key) if not edition: raise web.notfound() edition.update_loan_status() loans = [] user = accounts.get_current_user() if user: user.update_loan_status() loans = get_loans(user) # Check if we recently did a return i = web.input(r=None) if i.r == 't': have_returned = True else: have_returned = False return render_template("borrow", edition, loans, have_returned)
def _prevent_system_subjects_deletion(self, work): # Allow admins to modify system systems user = accounts.get_current_user() if user and user.is_admin(): return # Note: work is the new work object from the formdata and self.work is the work doc from the database. old_subjects = self.work and self.work.get("subjects") or [] # If condition is added to handle the possibility of bad data set_old_subjects = set(s.lower() for s in old_subjects if isinstance(s, six.string_types)) set_new_subjects = set(s.lower() for s in work.subjects) for s in SYSTEM_SUBJECTS: # if a system subject has been removed if s.lower() in set_old_subjects and s.lower( ) not in set_new_subjects: work_key = self.work and self.work.key logger.warn("Prevented removal of system subject %r from %s.", s, work_key) work.subjects.append(s)
def _prevent_ocaid_deletion(self, edition): # Allow admins to modify ocaid user = accounts.get_current_user() if user and user.is_admin(): return # read ocaid from form data try: ocaid = [ id['value'] for id in edition.get('identifiers', []) if id['name'] == 'ocaid' ][0] except IndexError: ocaid = None # 'self.edition' is the edition doc from the db and 'edition' is the doc from formdata if self.edition and self.edition.get( 'ocaid') and self.edition.get('ocaid') != ocaid: logger.warn("Attempt to change ocaid of %s from %r to %r.", self.edition.key, self.edition.get('ocaid'), ocaid) raise ValidationException( "Changing Internet Archive ID is not allowed.")
def POST(self, work_id): """Registers new ratings for this work""" user = accounts.get_current_user() i = web.input(edition_id=None, rating=None, redir=False) key = i.edition_id if i.edition_id else ('/works/OL%sW' % work_id) edition_id = int(extract_numeric_id_from_olid( i.edition_id)) if i.edition_id else None if not user: raise web.seeother('/account/login?redirect=%s' % key) username = user.key.split('/')[2] def response(msg, status="success"): return delegate.RawText(json.dumps({status: msg}), content_type="application/json") if i.rating is None: models.Ratings.remove(username, work_id) r = response('removed rating') else: try: rating = int(i.rating) if rating not in models.Ratings.VALID_STAR_RATINGS: raise ValueError except ValueError: return response('invalid rating', status="error") models.Ratings.add(username=username, work_id=work_id, rating=rating, edition_id=edition_id) r = response('rating added') if i.redir: raise web.seeother(key) return r
def GET(self, key): if not is_admin(): return render_template('permission_denied', web.ctx.path, "Permission denied.") edition = web.ctx.site.get(key) if not edition: raise web.notfound() if edition.ocaid: lending.sync_loan(edition.ocaid) ebook_key = "ebooks/" + edition.ocaid ebook = web.ctx.site.store.get(ebook_key) or {} else: ebook = None edition_loans = get_edition_loans(edition) user_loans = [] user = accounts.get_current_user() if user: user_loans = get_loans(user) return render_template("borrow_admin", edition, edition_loans, ebook, user_loans, web.ctx.ip)
def GET(self, key): if not is_admin(): return render_template('permission_denied', web.ctx.path, "Permission denied.") edition = web.ctx.site.get(key) ebook_key = "ebooks" + key ebook = web.ctx.site.store.get(ebook_key) or {} if not edition: raise web.notfound() i = web.input(updatestatus=None) if i.updatestatus == 't': edition.update_loan_status() edition_loans = get_edition_loans(edition) user_loans = [] user = accounts.get_current_user() if user: user_loans = get_loans(user) return render_template("borrow_admin", edition, edition_loans, ebook, user_loans, web.ctx.ip)
def POST(self, work_id: str): user = accounts.get_current_user() if not (user and (user.is_admin() or user.is_librarian())): return web.HTTPError('403 Forbidden') web_input = web.input(comment=None) comment = web_input.get('comment') work: Work = web.ctx.site.get(f'/works/{work_id}') if work is None: return web.HTTPError(status='404 Not Found') editions: list[dict] = self.get_editions_of_work(work) keys_to_delete: list = [el.get('key') for el in [*editions, work.dict()]] delete_payload: list[dict] = [ {'key': key, 'type': {'key': '/type/delete'}} for key in keys_to_delete ] web.ctx.site.save_many(delete_payload, comment) return delegate.RawText(json.dumps({ 'status': 'ok', }), content_type="application/json")
def GET(self): user = accounts.get_current_user() user.update_loan_status() loans = borrow.get_loans(user) return render['account/borrow'](user, loans)
def GET(self): user = accounts.get_current_user() raise web.seeother(user.key + '/lists')
def GET(self): user = accounts.get_current_user() email = user.email return render['account/notifications'](user.preferences(), email)
def GET(self): user = accounts.get_current_user() return render['account/privacy'](user.preferences())
def get_email(self): user = accounts.get_current_user() return user.get_account()['email']
def GET(self): user = accounts.get_current_user() page = render.account(user) page.v2 = True return page
def GET(self): user = accounts.get_current_user() username = user.key.split('/')[-1] raise web.seeother('/people/%s/books' % (username))
def GET(self, rest='loans'): user = accounts.get_current_user() username = user.key.split('/')[-1] raise web.seeother('/people/%s/books/%s' % (username, rest))
def POST(self): user = accounts.get_current_user() user.save_preferences(web.input()) add_flash_message('note', _("Notification preferences have been updated successfully.")) web.seeother("/account")
def GET(self): user = accounts.get_current_user() return render.account(user)
def is_admin(): """"Returns True if the current user is in admin usergroup.""" user = accounts.get_current_user() return user and user.key in [ m.key for m in web.ctx.site.get('/usergroup/admin').members ]
def POST(self, key): """Called when the user wants to borrow the edition""" i = web.input(action='borrow', format=None, ol_host=None) if i.ol_host: ol_host = i.ol_host else: ol_host = 'openlibrary.org' edition = web.ctx.site.get(key) if not edition: raise web.notfound() # Make a call to availability v2 update the subjects according # to result if `open`, redirect to bookreader response = lending.get_availability_of_ocaid(edition.ocaid) availability = response[edition.ocaid] if response else {} if availability and availability['status'] == 'open': raise web.seeother('https://archive.org/stream/' + edition.ocaid + '?ref=ol') error_redirect = ('https://archive.org/stream/' + edition.ocaid + '?ref=ol') user = accounts.get_current_user() if user: account = OpenLibraryAccount.get_by_email(user.email) ia_itemname = account.itemname if account else None if not user or not ia_itemname: web.setcookie(config.login_cookie_name, "", expires=-1) raise web.seeother("/account/login?redirect=%s/borrow?action=%s" % (edition.url(), i.action)) action = i.action # Intercept a 'borrow' action if the user has already # borrowed the book and convert to a 'read' action. # Added so that direct bookreader links being routed through # here can use a single action of 'borrow', regardless of # whether the book has been checked out or not. if action == 'borrow' and user.has_borrowed(edition): action = 'read' if action == 'borrow': resource_type = i.format or 'bookreader' if resource_type not in ['epub', 'pdf', 'bookreader']: raise web.seeother(error_redirect) user_meets_borrow_criteria = user_can_borrow_edition( user, edition, resource_type) if user_meets_borrow_criteria: # This must be called before the loan is initiated, # otherwise the user's waitlist status will be cleared # upon loan creation track_loan = False if is_users_turn_to_borrow( user, edition) else True loan = lending.create_loan(identifier=edition.ocaid, resource_type=resource_type, user_key=ia_itemname, book_key=key) if loan: loan_link = loan['loan_link'] if resource_type == 'bookreader': if track_loan: # As of 2017-12-14, Petabox will be # responsible for tracking borrows which # are the result of waitlist redemptions, # so we don't want to track them here to # avoid double accounting. When a reader # is at the head of a waitlist and goes to # claim their loan, Petabox now checks # whether the waitlist was initiated from # OL, and if it was, petabox tracks # ol.loans.bookreader accordingly via # lending.create_loan. stats.increment('ol.loans.bookreader') raise web.seeother( make_bookreader_auth_link( loan.get_key(), edition.ocaid, '/stream/' + edition.ocaid, ol_host)) elif resource_type == 'pdf': stats.increment('ol.loans.pdf') raise web.seeother(loan_link) elif resource_type == 'epub': stats.increment('ol.loans.epub') raise web.seeother(loan_link) else: raise web.seeother(error_redirect) else: raise web.seeother(error_redirect) elif action == 'return': # Check that this user has the loan user.update_loan_status() loans = get_loans(user) # We pick the first loan that the user has for this book that is returnable. # Assumes a user can't borrow multiple formats (resource_type) of the same book. user_loan = None for loan in loans: # Handle the case of multiple edition records for the same # ocaid and the user borrowed from one and returning from another has_loan = (loan['book'] == edition.key or loan['ocaid'] == edition.ocaid) if has_loan: user_loan = loan break if not user_loan: # $$$ add error message raise web.seeother(error_redirect) user_loan.return_loan() # Show the page with "you've returned this". Use a dummy slug. # $$$ this would do better in a session variable that can be cleared # after the message is shown once raise web.seeother(edition.url()) elif action == 'read': # Look for loans for this book user.update_loan_status() loans = get_loans(user) for loan in loans: if loan['book'] == edition.key: raise web.seeother( make_bookreader_auth_link(loan['_key'], edition.ocaid, '/stream/' + edition.ocaid, ol_host)) elif action == 'join-waitinglist': return self.POST_join_waitinglist(edition, user) elif action == 'leave-waitinglist': return self.POST_leave_waitinglist(edition, user, i) # Action not recognized raise web.seeother(error_redirect)