Exemple #1
0
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))
Exemple #2
0
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))
Exemple #3
0
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
Exemple #4
0
    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])
Exemple #5
0
    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])
Exemple #6
0
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
Exemple #7
0
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
Exemple #8
0
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
    )
Exemple #9
0
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)
Exemple #10
0
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)