def edit_listing(permalink): """Allow a seller to update or unpublish a listing.""" # Retrieve the listing by key. listing = helpers.lookup_listing(permalink) if not listing: abort(404) form = forms.EditListingForm() # Prevent non-creators from editing a listing. if session.get("email") != listing.seller or not session["email"]: abort(403) # Allow the author of a listing to unpublish it. if request.form.get("unpublish"): listing.posting_time = 0.0 listing.put() helpers.invalidate_listing(listing) return redirect("/") # Upload photos after validate_on_submit(), even if other fields in the form # are invalid. is_valid = form.validate_on_submit() if request.method == "POST": photos = [] for photo in form.photos: if not photo.data: continue image = photo.data["image"] if not image or (hasattr(image, "filename") and not image.filename): continue photos.append(image) listing.photos = photos # Allow authors to edit listings. if is_valid: listing.title = form.title.data listing.body = form.description.data listing.categories = form.categories.data listing.price = int(form.price.data * 100) listing.put() helpers.invalidate_listing(listing) return redirect(url_for("show_listing", permalink=listing.permalink)) # Display an edit form. form.title.data = listing.title form.description.data = listing.body form.categories.data = listing.categories form.price.data = listing.price / 100.0 for index, entry in enumerate(form.photos.entries): if index < len(listing.photos): entry["image"].data = listing.photos[index] else: entry["image"].data = None return render_template("listing_form.html", type="Edit", form=form)
def migrate_schema(): q = entities.Listing.all() q = q.filter("version <", entities.Listing.SCHEMA_VERSION) for listing in q.fetch(100): db.run_in_transaction(lambda: (listing.migrate(), listing.put())) helpers.invalidate_listing(listing) return "ok"
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() buyer = buyer_form.buyer.data message = buyer_form.message.data seller = listing.seller # Validate emails with the submission of the form. buyer_form.post_validate = ( lambda: policy.place_inquiry(listing, buyer, message)) # Handle submissions on the form. if buyer_form.validate_on_submit(): # Track what requests are sent to which people. helpers.add_inqury(listing, buyer, message) # Provide a flash message. flash("Your inquiry has been sent.") 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)
def test_lookups(): a = entities.Listing(title="lista", body="ba", key_name="foo") a.put() assert helpers.lookup_listing("foo").title == "lista" a.title = "listb" a.put() assert helpers.lookup_listing("foo").title == "lista" helpers.invalidate_listing(a) assert helpers.lookup_listing("foo").title == "listb"
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() buyer = buyer_form.buyer.data message = buyer_form.message.data seller = listing.seller # Validate emails with the submission of the form. buyer_form.post_validate = ( lambda: policy.place_inquiry(listing, buyer, message)) # Handle submissions on the form. if buyer_form.validate_on_submit(): # Track what requests are sent to which people. helpers.add_inqury(listing, buyer, message) # Provide a flash message. flash("Your inquiry has been sent.") 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)
def test_search(): entities.Listing(title="title for test", posting_time=1.0e5, key_name="search_test").put() assert tuple(helpers.fetch_shard("title")) == ("search_test",) assert (tuple(x.permalink for x in helpers.run_query("title for test")) == ("search_test",)) ent = entities.Listing(title="new title", posting_time=1.0e5, key_name="search_test") ent.put() helpers.invalidate_listing(ent) assert not helpers.run_query("title for test")
def test_search(): entities.Listing(title="title for test", posting_time=1.0e5, key_name="search_test").put() assert tuple(helpers.fetch_shard("title")) == ("search_test", ) assert (tuple( x.permalink for x in helpers.run_query("title for test")) == ("search_test", )) ent = entities.Listing(title="new title", posting_time=1.0e5, key_name="search_test") ent.put() helpers.invalidate_listing(ent) assert not helpers.run_query("title for test")
minutes=float( json_data["renewed_at"][-2:]))).timetuple()) # Remove HTML tags from body. cleaned_body = re.sub(r'<[^>]+>', '', json_data["details"]) # Prepare a listing to update. listing = entities.Listing(key_name=json_data["permalink"], seller=json_data["seller"]["email"], posting_time=posting_time, title=json_data["description"], body=cleaned_body, price=(int(float(json_data["price"]) * 100))) # Download all original photos for this listing. html = _urlopen(url).read() images = re.finditer(r"<a class='fancybox-image' href='([^']*)'", html) prefix = "http://marketplace.uchicago.edu" listing.photos = [_urlopen(prefix + m.group(1)) for m in images] # Extract the current category from the production site. category = re.search(r'<a href=".*categories.*">([^<]*)</a>', html) listing.categories = [category.group(1).lower()] # (Idempotently) save this entity into the datastore. listing.put() # Invalidate the cache. helpers.invalidate_listing(listing)
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)
def new_listing(): """Creates or removes this listing.""" # Populate a form to create a listing. form = forms.NewListingForm() # Create a temporary listing so that photos can be uploaded. listing = entities.Listing( key_name=str(uuid.uuid4()), # FIXME: add proper permalink generator. title=form.title.data, price=int(form.price.data * 100) if form.price.data else 0, body=form.description.data, categories=form.categories.data or [], seller=form.seller.data, posting_time=(time.time() if session.get("email") else 0.0), admin_key=str(uuid.uuid4()) ) # Allow uploading and saving the given request. is_valid = form.validate_on_submit() if request.method == "POST": photos = [] for photo in form.photos: if not photo.data: continue image = photo.data["image"] if not image or( hasattr(image, "filename") and not image.filename): continue photos.append(image) listing.photos = photos # Allow anyone to create listings. if is_valid: listing.title = form.title.data listing.body = form.description.data listing.categories = form.categories.data listing.price = int(form.price.data * 100) listing.put() helpers.invalidate_listing(listing) # Send the user an email to let them edit the listing. email.send_mail( to=listing.seller, subject="Marketplace Listing \"{}\"".format(listing.title), html=render_template("email/welcome.html", listing=listing), text=render_template("email/welcome.txt", listing=listing) ) # If running locally, print a link to this listing. print url_for("show_listing", permalink=listing.key().name(), key=listing.admin_key, _external=True) # Only allow the user to see the listing if they are signed in. if session.get("email") == listing.seller: flash("Your listing has been published.") return redirect(url_for("show_listing", permalink=listing.permalink)) else: flash("Your listing has been created. " "Click the link in your email to publish it.") return redirect(url_for("search_listings")) # Have the form email default to the value from the session. if not form.seller.data: form.seller.data = session.get("email") # Display the photo URL of any uploaded photos. for index, entry in enumerate(form.photos.entries): if index < len(listing.photos): entry["image"].data = listing.photos[index] else: entry["image"].data = None return render_template("listing_form.html", type="New", form=form)
def new_listing(): """Creates or removes this listing.""" # Populate a form to create a listing. form = forms.NewListingForm() # Create a temporary listing so that photos can be uploaded. listing = entities.Listing( key_name=str(uuid.uuid4()), # FIXME: add proper permalink generator. title=form.title.data, price=int(form.price.data * 100) if form.price.data else 0, body=form.description.data, categories=form.categories.data or [], seller=form.seller.data, posting_time=(time.time() if session.get("email") else 0.0), admin_key=str(uuid.uuid4())) # Ensure that validations check with policy. form.post_validate = lambda: policy.claim_listing(listing) # Allow uploading and saving the given request. is_valid = form.validate_on_submit() if request.method == "POST": photos = [] for photo in form.photos: if not photo.data: continue image = photo.data["image"] if not image or (hasattr(image, "filename") and not image.filename): continue photos.append(image) listing.photos = photos # Allow anyone to create listings. if is_valid: # Update the listing on the server. listing.put() helpers.invalidate_listing(listing) # Only allow the user to see the listing if they are signed in. if session.get("email") == listing.seller: flash("Your listing has been published.") return redirect( url_for("show_listing", permalink=listing.permalink)) else: flash("Your listing has been created. " "Click the link in your email to publish it.") return redirect(url_for("search_listings")) # Have the form email default to the value from the session. if not form.seller.data: form.seller.data = session.get("email") # Display the photo URL of any uploaded photos. for index, entry in enumerate(form.photos.entries): if index < len(listing.photos): entry["image"].data = listing.photos[index] else: entry["image"].data = None return render_template("listing_form.html", type="New", form=form)
# Remove HTML tags from body. cleaned_body = re.sub(r'<[^>]+>', '', json_data["details"]) # Prepare a listing to update. listing = entities.Listing( key_name=json_data["permalink"], seller=json_data["seller"]["email"], posting_time=posting_time, title=json_data["description"], body=cleaned_body, price=(int(float(json_data["price"]) * 100)) ) # Download all original photos for this listing. html = _urlopen(url).read() images = re.finditer(r"<a class='fancybox-image' href='([^']*)'", html) prefix = "http://marketplace.uchicago.edu" listing.photos = [_urlopen(prefix + m.group(1)) for m in images] # Extract the current category from the production site. category = re.search(r'<a href=".*categories.*">([^<]*)</a>', html) listing.categories = [category.group(1).lower()] # (Idempotently) save this entity into the datastore. listing.put() # Invalidate the cache. helpers.invalidate_listing(listing)
def new_listing(): """Creates or removes this listing.""" # Populate a form to create a listing. form = forms.NewListingForm() # Create a temporary listing so that photos can be uploaded. listing = entities.Listing( key_name=str(uuid.uuid4()), # FIXME: add proper permalink generator. title=form.title.data, price=int(form.price.data * 100) if form.price.data else 0, body=form.description.data, categories=form.categories.data or [], seller=form.seller.data, posting_time=(time.time() if session.get("email") else 0.0), admin_key=str(uuid.uuid4()) ) # Ensure that validations check with policy. form.post_validate = lambda: policy.claim_listing(listing) # Allow uploading and saving the given request. is_valid = form.validate_on_submit() if request.method == "POST": photos = [] for photo in form.photos: if not photo.data: continue image = photo.data["image"] if not image or (hasattr(image, "filename") and not image.filename): continue photos.append(image) listing.photos = photos # Allow anyone to create listings. if is_valid: # Update the listing on the server. listing.put() helpers.invalidate_listing(listing) # Only allow the user to see the listing if they are signed in. if session.get("email") == listing.seller: flash("Your listing has been published.") return redirect(url_for("show_listing", permalink=listing.permalink)) else: flash("Your listing has been created. " "Click the link in your email to publish it.") return redirect(url_for("search_listings")) # Have the form email default to the value from the session. if not form.seller.data: form.seller.data = session.get("email") # Display the photo URL of any uploaded photos. for index, entry in enumerate(form.photos.entries): if index < len(listing.photos): entry["image"].data = listing.photos[index] else: entry["image"].data = None return render_template("listing_form.html", type="New", form=form)