def test_update_username(self): before_where = {"username": "******"} after_where = {"username": "******"} assert len( list(self.db.select("bookshelves_books", where=before_where))) == 2 Bookshelves.update_username("@kilgore_trout", "@anonymous") assert len( list(self.db.select("bookshelves_books", where=before_where))) == 0 assert len(list(self.db.select("bookshelves_books", where=after_where))) == 2 assert len(list(self.db.select("booknotes", where=before_where))) == 1 Booknotes.update_username("@kilgore_trout", "@anonymous") assert len(list(self.db.select("booknotes", where=before_where))) == 0 assert len(list(self.db.select("booknotes", where=after_where))) == 1 assert len(list(self.db.select("ratings", where=before_where))) == 1 Ratings.update_username("@kilgore_trout", "@anonymous") assert len(list(self.db.select("ratings", where=before_where))) == 0 assert len(list(self.db.select("ratings", where=after_where))) == 1 assert len(list(self.db.select("observations", where=before_where))) == 1 Observations.update_username("@kilgore_trout", "@anonymous") assert len(list(self.db.select("observations", where=before_where))) == 0 assert len(list(self.db.select("observations", where=after_where))) == 1
def main(self, test=False): params = web.input(key='', test='') # Provide an escape hatch to let POST requests preview if test is False and params.test: test = True summary = {'key': params.key, 'redirect_chain': [], 'resolved_key': None} if params.key: redirect_chain = Work.get_redirect_chain(params.key) summary['redirect_chain'] = [ { "key": thing.key, "occurrences": {}, "updates": {} } for thing in redirect_chain ] summary['resolved_key'] = redirect_chain[-1].key for r in summary['redirect_chain']: olid = r['key'].split('/')[-1][2:-1] new_olid = summary['resolved_key'].split('/')[-1][2:-1] # count reading log entries r['occurrences']['readinglog'] = len( Bookshelves.get_works_shelves(olid)) r['occurrences']['ratings'] = len( Ratings.get_all_works_ratings(olid)) r['occurrences']['booknotes'] = len( Booknotes.get_booknotes_for_work(olid)) r['occurrences']['observations'] = len( Observations.get_observations_for_work(olid)) # track updates r['updates']['readinglog'] = Bookshelves.update_work_id( olid, new_olid, _test=test ) r['updates']['ratings'] = Ratings.update_work_id( olid, new_olid, _test=test ) r['updates']['booknotes'] = Booknotes.update_work_id( olid, new_olid, _test=test ) r['updates']['observations'] = Observations.update_work_id( olid, new_olid, _test=test ) return delegate.RawText( json.dumps(summary), content_type="application/json")
def test_delete_all_by_username(self): assert len(list(self.db.select("bookshelves_books"))) == 3 Bookshelves.delete_all_by_username("@kilgore_trout") assert len(list(self.db.select("bookshelves_books"))) == 1 assert len(list(self.db.select("booknotes"))) == 2 Booknotes.delete_all_by_username('@kilgore_trout') assert len(list(self.db.select("booknotes"))) == 1 assert len(list(self.db.select("ratings"))) == 2 Ratings.delete_all_by_username("@kilgore_trout") assert len(list(self.db.select("ratings"))) == 1 assert len(list(self.db.select("observations"))) == 2 Observations.delete_all_by_username("@kilgore_trout") assert len(list(self.db.select("observations"))) == 1
def has_book_note(self, username, edition_olid): if not username: return False work_id = extract_numeric_id_from_olid(self.key) edition_id = extract_numeric_id_from_olid(edition_olid) return (len( Booknotes.get_patron_booknote( username, work_id, edition_id=edition_id)) > 0)
def get_users_notes(self, username, edition_olid=None): if not username: return None work_id = extract_numeric_id_from_olid(self.key) edition_id = extract_numeric_id_from_olid( edition_olid) if edition_olid else -1 return Booknotes.get_patron_booknote(username, work_id, edition_id=edition_id)
def test_no_allow_delete_on_conflict(self): rows = [ {"username": "******", "work_id": 1, "edition_id": 1, "notes": "Jimmeny"}, {"username": "******", "work_id": 2, "edition_id": 1, "notes": "Cricket"}, ] self.db.multiple_insert("booknotes", rows) resp = Booknotes.update_work_id("1", "2") assert resp == {'rows_changed': 0, 'rows_deleted': 0, 'failed_deletes': 1} assert [dict(row) for row in self.db.select("booknotes")] == rows
def resolve_redirect_chain(cls, work_key: str, test: bool = False) -> dict[str, Any]: summary: dict[str, Any] = { 'key': work_key, 'redirect_chain': [], 'resolved_key': None, } redirect_chain = cls.get_redirect_chain(work_key) summary['redirect_chain'] = [{ "key": thing.key, "occurrences": {}, "updates": {} } for thing in redirect_chain] summary['resolved_key'] = redirect_chain[-1].key for r in summary['redirect_chain']: olid = r['key'].split('/')[-1][2:-1] # 'OL1234x' --> '1234' new_olid = summary['resolved_key'].split('/')[-1][2:-1] # count reading log entries r['occurrences']['readinglog'] = len( Bookshelves.get_works_shelves(olid)) r['occurrences']['ratings'] = len( Ratings.get_all_works_ratings(olid)) r['occurrences']['booknotes'] = len( Booknotes.get_booknotes_for_work(olid)) r['occurrences']['observations'] = len( Observations.get_observations_for_work(olid)) # track updates r['updates']['readinglog'] = Bookshelves.update_work_id(olid, new_olid, _test=test) r['updates']['ratings'] = Ratings.update_work_id(olid, new_olid, _test=test) r['updates']['booknotes'] = Booknotes.update_work_id(olid, new_olid, _test=test) r['updates']['observations'] = Observations.update_work_id( olid, new_olid, _test=test) return summary
def generate_book_notes(self, username: str) -> str: def format_booknote(booknote: Mapping) -> dict: escaped_note = booknote['notes'].replace('"', '""') return { "work_id": f"OL{booknote['work_id']}W", "edition_id": f"OL{booknote['edition_id']}M", "note": f'"{escaped_note}"', "created_on": booknote['created'].strftime(self.date_format), } return csv_string(Booknotes.select_all_by_username(username), format_booknote)
def get_notes(self, limit=RESULTS_PER_PAGE, page=1): notes = Booknotes.get_notes_grouped_by_work( self.username, limit=limit, page=page ) for entry in notes: entry['work_key'] = f"/works/OL{entry['work_id']}W" entry['work'] = self._get_work(entry['work_key']) entry['work_details'] = self._get_work_details(entry['work']) entry['notes'] = {i['edition_id']: i['notes'] for i in entry['notes']} entry['editions'] = { k: web.ctx.site.get(f'/books/OL{k}M') for k in entry['notes'] if k != Booknotes.NULL_EDITION_VALUE } return notes
def generate_book_notes(self, username): csv = [] csv.append('Work ID,Edition ID,Note,Created On') notes = Booknotes.select_all_by_username(username) for note in notes: escaped_note = note['notes'].replace('"', '""') row = [ f"OL{note['work_id']}W", f"OL{note['edition_id']}M", f'"{escaped_note}"', note['created'].strftime(self.date_format) ] csv.append(','.join(row)) return '\n'.join(csv)
def anonymize(self, test=False): # Generate new unique username for patron: # Note: Cannot test get_activation_link() locally uuid = (self.get_activation_link()['code'] if self.get_activation_link() else generate_uuid()) new_username = f'anonymous-{uuid}' results = {'new_username': new_username} # Delete all of the patron's book notes: results['booknotes_count'] = Booknotes.delete_all_by_username( self.username, _test=test) # Anonymize patron's username in OL DB tables: results['ratings_count'] = Ratings.update_username(self.username, new_username, _test=test) results['observations_count'] = Observations.update_username( self.username, new_username, _test=test) results['bookshelves_count'] = Bookshelves.update_username( self.username, new_username, _test=test) if not test: patron = self.get_user() email = self.email username = self.username # Remove patron from all usergroups: for grp in patron.usergroups: grp.remove_user(patron.key) # Set preferences to default: patron.save_preferences({'updates': 'no', 'public_readlog': 'no'}) # Clear patron's profile page: data = {'key': patron.key, 'type': '/type/delete'} patron.set_data(data) # Remove account information from store: del web.ctx.site.store[f'account/{username}'] del web.ctx.site.store[f'account/{username}/verify'] del web.ctx.site.store[f'account/{username}/password'] del web.ctx.site.store[f'account-email/{email}'] return results
def get_counts(cls, username): return { 'notes': Booknotes.count_works_with_notes_by_user(username), 'observations': Observations.count_distinct_observations(username), }
def get_users_notes(self, username): if not username: return None work_id = extract_numeric_id_from_olid(self.key) return Booknotes.get_patron_booknote(username, work_id)