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 get_users_observations(self, username): if not username: return None work_id = extract_numeric_id_from_olid(self.key) raw_observations = Observations.get_patron_observations(username, work_id) formatted_observations = defaultdict(list) for r in raw_observations: kv_pair = Observations.get_key_value_pair(r['type'], r['value']) formatted_observations[kv_pair.key].append(kv_pair.value) return formatted_observations
def DELETE(self, work_id): user = accounts.get_current_user() username = user.key.split('/')[2] if not user: raise web.seeother('/account/login') Observations.remove_observations(username, work_id) def response(msg, status="success"): return delegate.RawText(json.dumps({status: msg}), content_type="application/json") return response('Observations removed')
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 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 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 GET(self, work_id): user = accounts.get_current_user() if not user: raise web.seeother('/account/login') username = user.key.split('/')[2] existing_records = Observations.get_patron_observations( username, work_id) patron_observations = defaultdict(list) for r in existing_records: kv_pair = Observations.get_key_value_pair(r['type'], r['value']) patron_observations[kv_pair.key].append(kv_pair.value) return delegate.RawText(json.dumps(patron_observations), content_type="application/json")
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_reviews(self, username: str) -> str: def format_observation(observation: Mapping) -> dict: return { "work_id": f"OL{observation['work_id']}W", "review_category": f'"{observation["observation_type"]}"', "review_value": f'"{observation["observation_value"]}"', "created_on": observation['created'].strftime(self.date_format), } observations = Observations.select_all_by_username(username) return csv_string(observations, format_observation)
def get_observations(self, limit=RESULTS_PER_PAGE, page=1): observations = Observations.get_observations_grouped_by_work( self.username, limit=limit, page=page) for entry in observations: 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']) ids = {} for item in entry['observations']: ids[item['observation_type']] = item['observation_values'] entry['observations'] = convert_observation_ids(ids) return observations
def generate_reviews(self, username): csv = [] csv.append('Work ID,Review Category,Review Value,Created On') observations = Observations.select_all_by_username(username) for o in observations: row = [ f"OL{o['work_id']}W", f'"{o["observation_type"]}"', f'"{o["observation_value"]}"', o['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), }