def claim_listing(permalink): """Allow a seller to claim a listing whose email they have lost.""" # Look up the existing listing used for this person. listing = helpers.lookup_listing(permalink) if not listing: abort(404) # Prevent button spamming. seller = listing.seller title = listing.title if dos.rate_limit(listing.seller, 4, 60) or dos.rate_limit(listing.key().name, 2, 60): seller = "*****@*****.**" title = "SPAM REQUEST: " + listing.title # Send the user an email to let them edit the listing. message = sendgrid.Mail() message.set_from("Marketplace Team <*****@*****.**>") message.add_to(seller) message.set_subject('Marketplace Listing "{}"'.format(title)) message.set_html(render_template("email/welcome.html", listing=listing)) message.set_text(render_template("email/welcome.txt", listing=listing)) config.send_grid_client.send(message) flash("We've emailed you a link to edit this listing.") return redirect(url_for("show_listing", permalink=listing.permalink))
def claim_listing(permalink): """Allow a seller to claim a listing whose email they have lost.""" # Look up the existing listing used for this person. listing = helpers.lookup_listing(permalink) if not listing: abort(404) # Prevent button spamming. seller = listing.seller title = listing.title if (dos.rate_limit(listing.seller, 4, 60) or dos.rate_limit(listing.key().name, 2, 60)): seller = "*****@*****.**" title = "SPAM REQUEST: " + listing.title # Send the user an email to let them edit the listing. email.send_mail( to=seller, subject="Marketplace Listing \"{}\"".format(title), html=render_template("email/welcome.html", listing=listing), text=render_template("email/welcome.txt", listing=listing) ) flash("We've emailed you a link to edit this listing.") return redirect(url_for("show_listing", permalink=listing.permalink))
def test_rate_limit(): now = 0 _time, time.time = time.time, lambda: now try: trace = [] for i in xrange(5): trace.append(dos.rate_limit("key", 3, 60)) now = 100 for i in xrange(2): trace.append(dos.rate_limit("key", 3, 60)) assert tuple(trace) == (False, False, False, True, True, False, False) finally: time.time = _time
def test_rate_limit(self): trace = [] # Post a bunch. with self.current_time(0): for i in xrange(5): trace.append(dos.rate_limit("key", 3, 60)) # Pause, then post some more. with self.current_time(100): for i in xrange(2): trace.append(dos.rate_limit("key", 3, 60)) self.assertEquals(trace, [ False, False, False, True, True, False, False])
def is_too_frequent(principals, rates): """ Use all of the given buckets from acting faster than the given rates. """ for ident, (limit, time_range) in itertools.product(principals, rates): if dos.rate_limit(ident, limit, time_range): return True return False
def api_all_listings(): """Display a list of listings that match the given query.""" # Parse filtering options from query. query = request.args.get("q", "") offset = int(request.args.get("offset", "0")) if offset < 0: offset = 0 limit = int(request.args.get("limit", "100")) if limit < 0: limit = 0 if limit > 100: limit = 100 # Provide a burst limit on search queries. if dos.rate_limit("api_search:{}".format(request.remote_addr), 10, 3600 * 24): abort(403) # Compute the results matching that query. listings = list(itertools.islice(model.Listing.matching(query), offset, offset + limit)) # Display only whitelisted properties as JSON. externalized = [_externalize(listing) for listing in listings] pages = {} if len(listings) == limit: pages["nextURL"] = url_for("api_all_listings", offset=offset + limit, _external=True) if offset != 0: pages["previousURL"] = url_for( "api_all_listings", offset=max( 0, offset - limit), _external=True) # Return JSON if requested. return jsonify( offset=offset, listings=externalized, limit=limit, **pages )
def api_all_listings(): """Display a list of listings that match the given query.""" # Parse filtering options from query. query = request.args.get("q", "") offset = int(request.args.get("offset", "0")) if offset < 0: offset = 0 limit = int(request.args.get("limit", "100")) if limit < 0: limit = 0 if limit > 100: limit = 100 # Provide a burst limit on search queries. if dos.rate_limit("api_search:{}".format(request.remote_addr), 10, 3600 * 24): abort(403) # Compute the results matching that query. listings = list( itertools.islice(model.Listing.matching(query), offset, offset + limit)) # Display only whitelisted properties as JSON. externalized = [_externalize(listing) for listing in listings] pages = {} if len(listings) == limit: pages["nextURL"] = url_for("api_all_listings", offset=offset + limit, _external=True) if offset != 0: pages["previousURL"] = url_for("api_all_listings", offset=max(0, offset - limit), _external=True) # Return JSON if requested. return jsonify(offset=offset, listings=externalized, limit=limit, **pages)
def show_listing(permalink): """View a particular listing and provide links to place an inquiry.""" # Retrieve the listing by key. listing = helpers.lookup_listing(permalink) if not listing: abort(404) # If the listing isn't yet published, check the URL key and update session. if request.args.get("key") == listing.admin_key and listing.admin_key: session["email"] = listing.seller if not listing.posting_time: listing.posting_time = time.time() listing.put() helpers.invalidate_listing(listing) flash("Your listing has been published.") return redirect(url_for("show_listing", permalink=permalink, q=request.args.get("q"))) # Otherwise, hide the listing. elif not listing.posting_time: abort(404) # Display a form for buyers to place an offer. buyer_form = forms.BuyerForm() # Handle submissions on the form. if buyer_form.validate_on_submit(): buyer = buyer_form.buyer.data message = buyer_form.message.data seller = listing.seller # Track what requests are sent to which people. helpers.add_inqury(listing, buyer, message) # Block spam inquiries. if (buyer.strip() == "*****@*****.**" or buyer.strip() == "*****@*****.**" or dos.rate_limit(buyer.strip(), 4, 60) or dos.rate_limit(request.remote_addr, 4, 60) or dos.rate_limit(listing.seller, 20, 3600 * 24)): message = "MESSAGE BLOCKED!\n\n" + str(message) seller = "*****@*****.**" # Send a listing to the person. email.send_mail( to=seller, reply_to=buyer, subject="Re: Marketplace Listing \"{}\"".format(listing.title), html=render_template("email/inquiry.html", **locals()), text=render_template("email/inquiry.txt", **locals()), ) return redirect(url_for("show_listing", permalink=permalink)) # Have the form email default to the value from the session. if not buyer_form.buyer.data: buyer_form.buyer.data = session.get("email") # Display the resulting template. return render_template("listing_show.html", listing=listing, buyer_form=buyer_form)