def _generate_tagcloud(self): retval = {} for tag in db.query(Tag).all(): count = db.query(QuoteToTag).filter_by(tag_id=tag.id).count() retval[tag.tag] = count or 1 retval[tag.tag] = math.log(retval[tag.tag], math.e/2) return retval
def _generate_tagcloud(self): retval = {} for tag in db.query(Tag).all(): count = db.query(QuoteToTag).filter_by(tag_id=tag.id).count() retval[tag.tag] = count or 1 retval[tag.tag] = math.log(retval[tag.tag], math.e / 2) return retval
def report(self, quote_id): authorize() quote = db.query(Quote).filter(Quote.id == quote_id).first() if not quote: return {'msg': 'Invalid quote ID.', 'status': 'error'} if request.environ['REQUEST_METHOD'] == 'POST': if self._has_made_too_many_reports(): # TODO: This should return a HTTP 429! But pylons.controllers.util.abort() # doesn't seem to support it :/ return {'msg': 'You are reporting quotes too fast. Slow down!', 'status': 'error'} if db.query(ReportedQuotes).filter_by(user_id=c.user.id).\ filter_by(quote_id=quote.id).first(): return {'msg': 'You already reported this quote in the past. Ignored.', 'status': 'error'} if not quote.status == QSTATUS['approved']: return {'msg': 'Quote is not approved, therefore cannot be reported.', 'status': 'error'} if db.query(ReportedQuotes).filter_by(user_id=c.user.id).\ filter_by(quote_id=quote.id).first(): return {'msg': 'You already reported this quote in the past. Ignored.', 'status': 'error'} c.user.reported_quotes.append(quote) quote.status = QSTATUS['reported'] db.commit() return {'msg': 'Quote reported.', 'status': 'success'} else: abort(405)
def reset_password(self): c.page = 'pw reset' c.key = request.params.get('key') c.redirect_url = url(controller='account', action='login') if request.environ['REQUEST_METHOD'] == 'GET': if not c.key: return render('/pw_reset/request.mako') else: reset_token = self._check_valid_pw_reset_key(c.key) if not reset_token: h.add_message('Invalid reset token', 'error') return render('/blank.mako') return render('/pw_reset/set.mako') elif request.environ['REQUEST_METHOD'] == 'POST': if not c.key: # create a password request key email = request.params['email'] user = db.query(User).filter(User.email == email).first() if not user: h.add_message('Invalid email address provided.', 'error') return render('/pw_reset/request.mako') already_requested = db.query(PasswordResets).filter(PasswordResets.user_id == user.id).first() if already_requested: if already_requested.created < now() - datetime.timedelta(hours=2): db.delete(already_requested) else: h.add_message('A password reset has already been requested for this user.', 'error') return render('/blank.mako') pw_reset_key = PasswordResets() pw_reset_key.user_id = user.id pw_reset_key.key = self._generate_pw_reset_key() db.add(pw_reset_key) db.commit() send_reset_password_email(user.email, pw_reset_key.key) h.add_message('Password reset email sent!', 'success') return render('/blank.mako') else: # reset the user's password to what they've submitted reset_token = self._check_valid_pw_reset_key(c.key) if not reset_token: h.add_message('Invalid reset token', 'error') return render('/blank.mako') password = request.params['password'] password_confirm = request.params['password_confirm'] valid_password = validate_password(password, password_confirm) if not valid_password['status']: h.add_message(valid_password['msg'], 'error') return render('/pw_reset/set.mako') user = db.query(User).filter(User.id == reset_token.user_id).first() hashed_pass = h.hash_password(password) user.password = hashed_pass db.delete(reset_token) db.commit() h.add_message('Password successfully set. You should now be able to login.', 'success') return render('/blank.mako')
def tags(self, tag=None, page=1): c.page = 'tags' if tag is None: c.rainbow = False if 'rainbow' in request.params: c.rainbow = ['', 'label-success', 'label-warning', 'label-important', 'label-info', 'label-inverse'] c.tags = self._generate_tagcloud() return render('/tagcloud.mako') else: tag_obj = db.query(Tag).filter(Tag.tag == tag).first() quotes = db.query(Quote).filter(Quote.tags.contains(tag_obj)).filter(Quote.status == QSTATUS['approved']).all() c.paginator = self._create_paginator(quotes, page) c.tag_filter = tag return render('/browse.mako')
def create(self): c.page = 'sign up' if request.environ['REQUEST_METHOD'] == 'GET': return render('/signup/form.mako') elif request.environ['REQUEST_METHOD'] == 'POST': username = request.params['username'] password = request.params['password'] password_confirm = request.params['password_confirm'] email = request.params['email'] validity = validate_signup(username, password, password_confirm, email) if not validity['status']: h.add_message(validity['msg'], 'error') return render('/signup/form.mako') try: create_user(username, password, email) authenticate(username, password) c.logged_in = True c.user = db.query(User).filter( User.username == username).first() return render('/signup/success.mako') except NameError, e: h.add_message(e.__str__(), 'error') return render('/signup/form.mako')
def _check_valid_pw_reset_key(self, key): reset_token = db.query(PasswordResets).filter(PasswordResets.key == key).first() if not reset_token: return None elif reset_token.created < now() - datetime.timedelta(hours=2): db.delete(reset_token) return None return reset_token
def create_or_get_tag(tagname): tag = db.query(Tag).filter(Tag.tag == tagname).first() if not tag: tag = Tag() tag.tag = tagname db.add(tag) db.commit() return tag
def authenticate(username, password): user = db.query(User).filter(User.username == username).first() if not user: return False if bcrypt.hashpw(password, config['PASSWORD_SALT']) == user.password: set_auth_cookie(user) return True return False
def view_one(self, ref_id): quote = db.query(Quote).filter(Quote.id == ref_id).first() if not quote or quote.approved != 1: abort(404) else: c.quote = quote c.page = 'browse' return render(self._get_template_name())
def unapproved(self, page=1): if not h.is_admin(): h.add_message('You must be an admin to perform that action.', 'error') return render('/blank.mako') quotes = db.query(Quote).filter(Quote.approved == 0).order_by(Quote.submitted.desc()).all() c.paginator = self._create_paginator(quotes, page) c.page = 'unapproved' return render(self._get_template_name())
def view_one(self, ref_id): quote = db.query(Quote).filter(Quote.id == ref_id).first() if not quote or quote.status != QSTATUS['approved']: abort(404) else: c.quote = quote c.page = 'browse' return render('/browse.mako')
def disapproved(self, page=1): authorize() quotes = db.query(Quote).filter( Quote.status == QSTATUS['disapproved']).order_by( Quote.submitted.desc()).all() c.paginator = self._create_paginator(quotes, page) c.page = 'disapproved' return render('/browse.mako')
def reported(self, page=1): if not h.is_admin(): h.add_message('You must be an admin to perform that action.', 'error') return render('/blank.mako') quotes = db.query(Quote).filter(Quote.status == QSTATUS['reported']).all() c.paginator = self._create_paginator(quotes, page) c.page = 'reported' return render('/browse.mako')
def _check_valid_pw_reset_key(self, key): reset_token = db.query(PasswordResets).filter( PasswordResets.key == key).first() if not reset_token: return None elif reset_token.created < now() - datetime.timedelta(hours=2): db.delete(reset_token) return None return reset_token
def search(self, keyword='', page=1): if request.environ['REQUEST_METHOD'] == 'POST': keyword = request.params.get('keyword', '') redirect(url(controller='browse', action='search', keyword=keyword)) query = '%' + keyword + '%' quotes = db.query(Quote).filter(Quote.body.like(query)).order_by(Quote.submitted.desc()).all() c.paginator = self._create_paginator(quotes, page) c.page = 'search: %s' % keyword return render(self._get_template_name())
def search(self, term='', page=1): if request.environ['REQUEST_METHOD'] == 'POST': term = request.params.get('term', '') redirect(url(controller='browse', action='search', term=term)) query = '%' + term + '%' quotes = db.query(Quote).filter(Quote.body.like(query)).filter(Quote.status == QSTATUS['approved']).order_by(Quote.submitted.desc()).all() c.paginator = self._create_paginator(quotes, page) c.page = 'search: %s' % term return render('/browse.mako')
def deleted(self, page=1): if not h.is_admin(): h.add_message('You must be an admin to perform that action.', 'error') return render('/blank.mako') quotes = db.query(Quote).filter( Quote.status == QSTATUS['deleted']).all() c.paginator = self._create_paginator(quotes, page) c.page = 'deleted' return render('/browse.mako')
def authenticate(username, password): user = db.query(User).filter(User.username == username).first() if not user: return False elif bcrypt.hashpw(password, config['PASSWORD_SALT']) == user.password: set_auth_cookie(user) return True else: clear_cookies() return False
def _generate_pw_reset_key(self): chars = string.ascii_letters + string.digits valid = False key = '' while not valid: key = ''.join(random.choice(chars) for _ in range(26)) already_exists = db.query(PasswordResets).filter(PasswordResets.key == key).first() if not already_exists: valid = True return key
def vote(self, direction, quote_id): authorize() quote = db.query(Quote).filter(Quote.id == quote_id).first() if request.environ['REQUEST_METHOD'] == 'PUT': if not quote: return {'msg': 'Invalid quote ID', 'status': 'error'} already_voted = '' for assoc in quote.voters: if assoc.user == c.user: already_voted = True # cancel the last vote: if assoc.direction == 'up': quote.rating -= 1 elif assoc.direction == 'down': quote.rating += 1 db.delete(assoc) assoc = VoteToUser(direction=direction) assoc.user = c.user quote.voters.append(assoc) if direction == 'up': quote.rating += 1 elif direction == 'down': quote.rating -= 1 else: return {'msg': 'Invalid vote direction', 'status': 'error'} if not already_voted: quote.votes += 1 db.commit() return {'status': 'success', 'msg': 'Vote cast!'} elif request.environ['REQUEST_METHOD'] == 'DELETE': for assoc in quote.voters: if assoc.user == c.user: db.delete(assoc) if direction == 'up': quote.rating -= 1 elif direction == 'down': quote.rating += 1 else: return {'msg': 'Invalid vote direction', 'status': 'error'} quote.votes -= 1 db.commit() return {'status': 'success', 'msg': 'Vote annulled!!'} else: abort(405)
def _generate_pw_reset_key(self): chars = string.ascii_letters + string.digits valid = False key = '' while not valid: key = ''.join(random.choice(chars) for _ in range(26)) already_exists = db.query(PasswordResets).filter( PasswordResets.key == key).first() if not already_exists: valid = True return key
def tags(self, tag=None, page=1): c.page = 'tags' if tag is None: c.rainbow = False if 'rainbow' in request.params: c.rainbow = [ '', 'label-success', 'label-warning', 'label-important', 'label-info', 'label-inverse' ] c.tags = self._generate_tagcloud() return render('/tagcloud.mako') else: tag_obj = db.query(Tag).filter(Tag.tag == tag).first() quotes = db.query(Quote).filter( Quote.tags.contains(tag_obj)).filter( Quote.status == QSTATUS['approved']).all() c.paginator = self._create_paginator(quotes, page) c.tag_filter = tag return render('/browse.mako')
def search(self, term='', page=1): if request.environ['REQUEST_METHOD'] == 'POST': term = request.params.get('term', '') redirect(url(controller='browse', action='search', term=term)) query = '%' + term + '%' quotes = db.query(Quote).filter(Quote.body.like(query)).filter( Quote.status == QSTATUS['approved']).order_by( Quote.submitted.desc()).all() c.paginator = self._create_paginator(quotes, page) c.page = 'search: %s' % term return render('/browse.mako')
def _is_deleteable_or_disapprovable(self, quote_id): authorize() quote = db.query(Quote).filter(Quote.id == quote_id).first() if not quote: return {'msg': 'Invalid quote ID.', 'status': 'error'} if not h.quote_is_deleteable(quote): return {'msg': 'You do not have permission to delete this quote.', 'status': 'error'} c.user.deleted_quotes.append(quote) return {'status': 'success', 'quote': quote}
def _is_deleteable_or_disapprovable(self, quote_id): authorize() quote = db.query(Quote).filter(Quote.id == quote_id).first() if not quote: return {'msg': 'Invalid quote ID.', 'status': 'error'} if not h.quote_is_deleteable(quote): return { 'msg': 'You do not have permission to delete this quote.', 'status': 'error' } c.user.deleted_quotes.append(quote) return {'status': 'success', 'quote': quote}
def report(self, quote_id): authorize() quote = db.query(Quote).filter(Quote.id == quote_id).first() if not quote: return {'msg': 'Invalid quote ID.', 'status': 'error'} if request.environ['REQUEST_METHOD'] == 'POST': if self._has_made_too_many_reports(): # TODO: This should return a HTTP 429! But pylons.controllers.util.abort() # doesn't seem to support it :/ return { 'msg': 'You are reporting quotes too fast. Slow down!', 'status': 'error' } if db.query(ReportedQuotes).filter_by(user_id=c.user.id).\ filter_by(quote_id=quote.id).first(): return { 'msg': 'You already reported this quote in the past. Ignored.', 'status': 'error' } if not quote.status == QSTATUS['approved']: return { 'msg': 'Quote is not approved, therefore cannot be reported.', 'status': 'error' } if db.query(ReportedQuotes).filter_by(user_id=c.user.id).\ filter_by(quote_id=quote.id).first(): return { 'msg': 'You already reported this quote in the past. Ignored.', 'status': 'error' } c.user.reported_quotes.append(quote) quote.status = QSTATUS['reported'] db.commit() return {'msg': 'Quote reported.', 'status': 'success'} else: abort(405)
def approve(self, quote_id): authorize() if not h.is_admin(): abort(401) if request.environ['REQUEST_METHOD'] == 'POST': quote = db.query(Quote).filter(Quote.id == quote_id).first() if not quote: return {'msg': 'Invalid quote ID', 'status': 'error'} quote.approved = 1 db.commit() return {'msg': 'Quote approved', 'status': 'success'}
def approve(self, quote_id): authorize() if not h.is_admin(): abort(401) if request.environ['REQUEST_METHOD'] == 'POST': quote = db.query(Quote).filter(Quote.id == quote_id).first() if not quote: return {'msg': 'Invalid quote ID.', 'status': 'error'} quote.status = QSTATUS['approved'] db.commit() return {'msg': 'Quote approved.', 'status': 'success'} else: abort(405)
def vote(self, quote_id, direction): authorize() quote = db.query(Quote).filter(Quote.id == quote_id).first() if request.environ['REQUEST_METHOD'] == 'POST': if not quote: return {'msg': 'Invalid quote ID.', 'status': 'error'} already_voted = '' for assoc in quote.voters: if assoc.user == c.user: already_voted = True # cancel the last vote: if assoc.direction == 'up': quote.rating -= 1 elif assoc.direction == 'down': quote.rating += 1 db.delete(assoc) assoc = VoteToUser(direction=direction) assoc.user = c.user quote.voters.append(assoc) if direction == 'up': quote.rating += 1 elif direction == 'down': quote.rating -= 1 else: return {'msg': 'Invalid vote direction.', 'status': 'error'} if not already_voted: quote.votes += 1 db.commit() return {'status': 'success', 'msg': 'Vote cast!'} elif request.environ['REQUEST_METHOD'] == 'DELETE': for assoc in quote.voters: if assoc.user == c.user: db.delete(assoc) if direction == 'up': quote.rating -= 1 elif direction == 'down': quote.rating += 1 else: return {'msg': 'Invalid vote direction.', 'status': 'error'} quote.votes -= 1 db.commit() return {'status': 'success', 'msg': 'Vote annulled!'} else: abort(405)
def create_user(username, password, email): conflicts = db.query(User).filter( or_(User.email == email, User.username == username)).first() if conflicts: if conflicts.email == email: raise NameError('Sorry! That email already exists in the system.') elif conflicts.username == username: raise NameError('Sorry! That username is already taken.') hashed_pass = h.hash_password(password) new_user = User() new_user.username = username new_user.password = hashed_pass new_user.email = email db.add(new_user) db.commit() return True
def create_user(username, password, email): conflicts = db.query(User).filter(or_(User.email == email, User.username == username)).first() if conflicts: if conflicts.email == email: raise NameError('Sorry! That email already exists in the system.') elif conflicts.username == username: raise NameError('Sorry! That username is already taken.') hashed_pass = h.hash_password(password) new_user = User() new_user.username = username new_user.password = hashed_pass new_user.email = email db.add(new_user) db.commit() return True
def favourite(self, quote_id): authorize() quote = db.query(Quote).filter(Quote.id == quote_id).first() if not quote: return {'msg': 'Invalid quote ID', 'status': 'error'} if request.environ['REQUEST_METHOD'] == 'PUT': c.user.favourites.append(quote) db.commit() return {'msg': 'Quote favourited', 'status': 'success'} elif request.environ['REQUEST_METHOD'] == 'DELETE': if not quote in c.user.favourites: return {'msg': "Can't remove: This quote isn't in your favourites", 'status': 'error'} c.user.favourites.remove(quote) db.commit() return {'msg': 'Removed favourite', 'status': 'success'}
def _has_made_too_many_reports(self): # TODO: # This filtering / counting should be done by SQLAlchemy. # # This is a quick hack to get around problems with between() and filter/filter_by, # possibly caused by the fact that ReportedQuotes is a Table() obj and not a class # reports = db.query(ReportedQuotes).filter_by(user_id=c.user.id).all() limit = 5 limit_time = now() - datetime.timedelta(hours=1) i = 0 found = [] for report in reports: if limit_time < report.time: found.append(report) if i == limit: break i += 1 return len(found) >= limit
def favourite(self, quote_id): authorize() quote = db.query(Quote).filter(Quote.id == quote_id).first() if not quote: return {'msg': 'Invalid quote ID.', 'status': 'error'} if request.environ['REQUEST_METHOD'] == 'POST': c.user.favourites.append(quote) db.commit() return {'msg': 'Quote favourited.', 'status': 'success'} elif request.environ['REQUEST_METHOD'] == 'DELETE': if not quote in c.user.favourites: return { 'msg': "Can't remove: This quote isn't in your favourites.", 'status': 'error' } c.user.favourites.remove(quote) db.commit() return {'msg': 'Removed favourite.', 'status': 'success'} else: abort(405)
def create(self): c.page = 'sign up' if request.environ['REQUEST_METHOD'] == 'GET': return render('/signup/form.mako') elif request.environ['REQUEST_METHOD'] == 'POST': username = request.params['username'] password = request.params['password'] password_confirm = request.params['password_confirm'] email = request.params['email'] validity = validate_signup(username, password, password_confirm, email) if not validity['status']: h.add_message(validity['msg'], 'error') return render('/signup/form.mako') try: create_user(username, password, email) authenticate(username, password) c.logged_in = True c.user = db.query(User).filter(User.username == username).first() return render('/signup/success.mako') except NameError, e: h.add_message(e.__str__(), 'error') return render('/signup/form.mako')
def worst(self, page=1): quotes = db.query(Quote).order_by( Quote.rating).filter(Quote.status == QSTATUS['approved']).all() c.paginator = self._create_paginator(quotes, page) c.page = 'worst' return render('/browse.mako')
def random(self): c.quote = db.query(Quote).order_by(sql.func.rand()).filter( Quote.status == QSTATUS['approved']).first() c.page = 'random' return render('/browse.mako')
def disapproved(self, page=1): authorize() quotes = db.query(Quote).filter(Quote.status == QSTATUS['disapproved']).order_by(Quote.submitted.desc()).all() c.paginator = self._create_paginator(quotes, page) c.page = 'disapproved' return render('/browse.mako')
def main(self, page=1): quotes = db.query(Quote).order_by(Quote.submitted.desc()).filter(Quote.approved == 1).all() c.paginator = self._create_paginator(quotes, page) c.page = 'browse' return render(self._get_template_name())
def worst(self, page=1): quotes = db.query(Quote).order_by(Quote.score).filter(Quote.approved == 1).all() c.paginator = self._create_paginator(quotes, page) c.page = 'worst' return render(self._get_template_name())
def random(self): c.quote = db.query(Quote).order_by(sql.func.rand()).filter(Quote.approved == 1).first() c.page = 'random' return render(self._get_template_name())
def random(self): c.quote = db.query(Quote).order_by(sql.func.rand()).filter(Quote.status == QSTATUS['approved']).first() c.page = 'random' return render('/browse.mako')
def worst(self, page=1): quotes = db.query(Quote).order_by(Quote.rating).filter(Quote.status == QSTATUS['approved']).all() c.paginator = self._create_paginator(quotes, page) c.page = 'worst' return render('/browse.mako')
def reset_password(self): c.page = 'pw reset' c.key = request.params.get('key') c.redirect_url = url(controller='account', action='login') if request.environ['REQUEST_METHOD'] == 'GET': if not c.key: return render('/pw_reset/request.mako') else: reset_token = self._check_valid_pw_reset_key(c.key) if not reset_token: h.add_message('Invalid reset token', 'error') return render('/blank.mako') return render('/pw_reset/set.mako') elif request.environ['REQUEST_METHOD'] == 'POST': if not c.key: # create a password request key email = request.params['email'] user = db.query(User).filter(User.email == email).first() if not user: h.add_message('Invalid email address provided.', 'error') return render('/pw_reset/request.mako') already_requested = db.query(PasswordResets).filter( PasswordResets.user_id == user.id).first() if already_requested: if already_requested.created < now() - datetime.timedelta( hours=2): db.delete(already_requested) else: h.add_message( 'A password reset has already been requested for this user.', 'error') return render('/blank.mako') pw_reset_key = PasswordResets() pw_reset_key.user_id = user.id pw_reset_key.key = self._generate_pw_reset_key() db.add(pw_reset_key) db.commit() send_reset_password_email(user.email, pw_reset_key.key) h.add_message('Password reset email sent!', 'success') return render('/blank.mako') else: # reset the user's password to what they've submitted reset_token = self._check_valid_pw_reset_key(c.key) if not reset_token: h.add_message('Invalid reset token', 'error') return render('/blank.mako') password = request.params['password'] password_confirm = request.params['password_confirm'] valid_password = validate_password(password, password_confirm) if not valid_password['status']: h.add_message(valid_password['msg'], 'error') return render('/pw_reset/set.mako') user = db.query(User).filter( User.id == reset_token.user_id).first() hashed_pass = h.hash_password(password) user.password = hashed_pass db.delete(reset_token) db.commit() h.add_message( 'Password successfully set. You should now be able to login.', 'success') return render('/blank.mako')