def logout(app, request): if request.method == "POST": # Delete our session, the user is logging out and we no longer want it request.session.delete() # We'll want to redirect the user with a 303 once we've completed the # log in process. resp = redirect_next( request, default=url_for(request, "warehouse.views.index"), ) # Delete the username cookie, the user is logging out and we no longer # want to store the username that they used when they were logged in. resp.delete_cookie("username") # Return our prepared response to the now logged out user return resp # This is a simple GET request, so we just want to render the template return render_response( app, request, "accounts/logout.html", next=request.values.get("next"), )
def index(app, request): return render_response( app, request, "index.html", project_count=app.db.packaging.get_project_count(), download_count=app.db.packaging.get_download_count(), recently_updated=app.db.packaging.get_recently_updated(), )
def search(app, request, doctype): if doctype not in app.search.types: raise NotFound limit = app.search.types[doctype].SEARCH_LIMIT query = request.args.get("q") try: page = int(request.args.get("page", 1)) except ValueError: raise NotFound if page <= 0: page = 1 offset = (page - 1) * limit results = app.search.types[doctype].search(query, limit, offset) total = results.get("hits", {}).get("total", 0) url_partial = functools.partial( url_for, request, 'warehouse.search.views.search', doctype='project', q=query) pages = SearchPagination(page, total, limit, url_partial) return render_response( app, request, "search/results.html", query=query, total=total, pages=pages, results=[r["_source"] for r in results["hits"]["hits"]], )
def test_render_response(): template = pretend.stub(render=pretend.call_recorder(lambda **k: "test")) app = pretend.stub( config=pretend.stub(), templates=pretend.stub( get_template=pretend.call_recorder(lambda t: template), ), ) request = pretend.stub() resp = render_response(app, request, "template.html", foo="bar") assert resp.get_wsgi_headers(create_environ())["Content-Length"] == "4" assert resp.data == b"test" assert app.templates.get_template.calls == [pretend.call("template.html")] assert template.render.calls == [ pretend.call( foo="bar", config=app.config, csrf_token=mock.ANY, gravatar_url=mock.ANY, url_for=mock.ANY, static_url=mock.ANY, ), ]
def login(app, request): form = LoginForm( request.form, authenticator=app.db.accounts.user_authenticate, translations=app.translations, ) if request.method == "POST" and form.validate(): # Get the user's ID, this is what we will use as the identifier anytime # we need to securely reference the user within the database. user_id = app.db.accounts.get_user_id(form.username.data) if request.session.get("user.id") != user_id: # To avoid reusing another user's session data, clear the session # data if the existing session corresponds to a different # authenticated user. request.session.clear() # Cycle the session key to prevent session fixation attacks from # crossing an authentication boundary request.session.cycle() # Cycle the CSRF token to prevent a CSRF via session fixation attack # from crossing an authentication boundary csrf_cycle(request.session) # Log the user in by storing their user id in their session request.session["user.id"] = user_id # We'll want to redirect the user with a 303 once we've completed the # log in process. resp = redirect_next( request, default=url_for(request, "warehouse.views.index"), ) # Store the user's name in a cookie so that the client side can use # it for display purposes. This value **MUST** not be used for any # sort of access control. resp.set_cookie("username", form.username.data) # Return our prepared response to the user return resp # Either this is a GET request or it is a POST request with a failing form # validation. Either way we want to simply render our template with the # form available. return render_response( app, request, "accounts/login.html", form=form, next=request.values.get("next"), )
def index(app, request): projects = app.db.packaging.all_projects() resp = render_response( app, request, "legacy/simple/index.html", projects=projects, ) # Add a header that points to the last serial serial = app.db.packaging.get_last_serial() resp.headers.add("X-PyPI-Last-Serial", serial) return resp
def packages_rss(app, request): """Dump the last N days' new projects as an RSS feed. """ releases = app.db.packaging.get_recent_projects(num=40) for release in releases: # TODO update _force_external to _external when Flask-ification is done url = url_for(request, 'warehouse.packaging.views.project_detail', project_name=release['name'], _force_external=True) release.update(dict(url=url)) response = render_response( app, request, "legacy/rss.xml", description='new projects', releases=releases, site=app.config.site, ) response.mimetype = 'text/xml; charset=utf-8' # TODO: throw in a last-modified header too? return response
def user_profile(app, request, username): user = app.db.accounts.get_user(username) if user is None: raise NotFound("Could not find user {}".format(username)) if user["username"] != username: return redirect( url_for( request, "warehouse.accounts.views.user_profile", username=user["username"], ), code=301, ) return render_response( app, request, "accounts/profile.html", user=user, projects=app.db.packaging.get_projects_for_user(user["username"]), )
def project_detail(app, request, project_name, version=None): # Get the real project name for this project project = app.db.packaging.get_project(project_name) if project is None: raise NotFound("Cannot find a project named {}".format(project_name)) # Look up all the releases for the given project releases = app.db.packaging.get_releases(project["name"]) if not releases: # If there are no releases then we need to return a simpler response # that simply states the project exists but that there is no versions # registered. raise NotFound( "There are no releases registered for the {} project".format( project["name"], ), ) if project["name"] != project_name: # We've found the project, and the version exists, but the project name # isn't quite right so we'll redirect them to the correct one. return redirect( url_for( request, "warehouse.packaging.views.project_detail", project_name=project["name"], version=version, ), code=301, ) if version is None: # If there's no version specified, then we use the latest version version = releases[0]["version"] elif version not in (r["version"] for r in releases): # If a version was specified then we need to ensure it's one of the # versions this project has, else raise a NotFound raise NotFound( "Cannot find the {} version of the {} project".format( version, project["name"], ), ) # Get the release data for the version release = app.db.packaging.get_release(project["name"], version) # Get the number of reverse dependencies for this project project_url = lambda name: url_for( request, 'warehouse.packaging.views.project_detail', project_name=name) reverse_dependencies = [{ 'name': row['name'], 'url': project_url(row['name']) } for row in app.db.packaging.get_reverse_dependencies(project["name"] + ' %')] if release.get("description"): # Render the project description description_html, rendered = readme.rst.render(release["description"]) if not rendered: description_html = description_html.replace("\n", "<br>") if app.config.camo: description_html = camouflage_images( app.config.camo.url, app.config.camo.key, description_html, ) else: description_html = "" # Mark our description_html as safe as it's already been cleaned by bleach description_html = jinja2.Markup(description_html) # Split the requirement string to (project name, the rest) requirements = [] for req in release.get('requires_dist', []): project_name, *other = req.split(' ', 1) url = url_for(request, 'warehouse.packaging.views.project_detail', project_name=project_name) requirements.append({ 'project_name': project_name, 'project_url': url, 'other': other[0] if other else '' }) return render_response( app, request, "projects/detail.html", project=project["name"], release=release, releases=releases, requirements=requirements, reverse_dependencies=reverse_dependencies, description_html=description_html, download_counts=app.db.packaging.get_download_counts(project["name"]), downloads=app.db.packaging.get_downloads(project["name"], version), classifiers=app.db.packaging.get_classifiers(project["name"], version), documentation=app.db.packaging.get_documentation_url(project["name"]), bugtracker=app.db.packaging.get_bugtrack_url(project["name"]), maintainers=app.db.packaging.get_users_for_project(project["name"]), )
def project(app, request, project_name): # Get the real project name for this project project = app.db.packaging.get_project(project_name) if project is None: raise NotFound("{} does not exist".format(project_name)) # Generate the Package URLs for the packages we've hosted file_urls = app.db.packaging.get_file_urls(project) # Determine what the hosting mode is for this package hosting_mode = app.db.packaging.get_hosting_mode(project) project_urls = [] if hosting_mode in {"pypi-scrape-crawl", "pypi-scrape"}: rel_prefix = "" if hosting_mode == "pypi-scrape-crawl" else "ext-" home_rel = "{}homepage".format(rel_prefix) download_rel = "{}download".format(rel_prefix) # Generate the Homepage and Download URL links release_urls = app.db.packaging.get_release_urls(project) for version, (home_page, download_url) in release_urls.items(): if home_page and home_page != "UNKNOWN": project_urls.append({ "rel": home_rel, "url": home_page, "name": "{} home_page".format(version), }) if download_url and download_url != "UNKNOWN": project_urls.append({ "rel": download_rel, "url": download_url, "name": "{} download_url".format(version), }) # Fetch the explicitly provided URLs external_urls = app.db.packaging.get_external_urls(project) resp = render_response( app, request, "legacy/simple/detail.html", project=project, files=file_urls, project_urls=project_urls, external_urls=external_urls, ) # Add a header that points to the last serial serial = app.db.packaging.get_last_serial(project) resp.headers.add("X-PyPI-Last-Serial", serial) # Add a Link header to point at the canonical URL can_url = url_for( request, "warehouse.legacy.simple.project", project_name=project, _force_external=True, ) resp.headers.add("Link", "<" + can_url + ">", rel="canonical") return resp
def project_detail(app, request, project_name, version=None): # Get the real project name for this project project = app.db.packaging.get_project(project_name) if project is None: raise NotFound("Cannot find a project named {}".format(project_name)) # Look up all the releases for the given project releases = app.db.packaging.get_releases(project["name"]) if not releases: # If there are no releases then we need to return a simpler response # that simply states the project exists but that there is no versions # registered. raise NotFound("There are no releases registered for the {} project".format(project["name"])) if project["name"] != project_name: # We've found the project, and the version exists, but the project name # isn't quite right so we'll redirect them to the correct one. return redirect( url_for(request, "warehouse.packaging.views.project_detail", project_name=project["name"], version=version), code=301, ) if version is None: # If there's no version specified, then we use the latest version version = releases[0]["version"] elif version not in (r["version"] for r in releases): # If a version was specified then we need to ensure it's one of the # versions this project has, else raise a NotFound raise NotFound("Cannot find the {} version of the {} project".format(version, project["name"])) # Get the release data for the version release = app.db.packaging.get_release(project["name"], version) # Get the number of reverse dependencies for this project project_url = lambda name: url_for(request, "warehouse.packaging.views.project_detail", project_name=name) reverse_dependencies = [ {"name": row["name"], "url": project_url(row["name"])} for row in app.db.packaging.get_reverse_dependencies(project["name"] + " %") ] if release.get("description"): # Render the project description description_html, rendered = readme.rst.render(release["description"]) if not rendered: description_html = description_html.replace("\n", "<br>") if app.config.camo: description_html = camouflage_images(app.config.camo.url, app.config.camo.key, description_html) else: description_html = "" # Mark our description_html as safe as it's already been cleaned by bleach description_html = jinja2.Markup(description_html) # Split the requirement string to (project name, the rest) requirements = [] for req in release.get("requires_dist", []): project_name, *other = req.split(" ", 1) url = url_for(request, "warehouse.packaging.views.project_detail", project_name=project_name) requirements.append({"project_name": project_name, "project_url": url, "other": other[0] if other else ""}) return render_response( app, request, "projects/detail.html", project=project["name"], release=release, releases=releases, requirements=requirements, reverse_dependencies=reverse_dependencies, description_html=description_html, download_counts=app.db.packaging.get_download_counts(project["name"]), downloads=app.db.packaging.get_downloads(project["name"], version), classifiers=app.db.packaging.get_classifiers(project["name"], version), documentation=app.db.packaging.get_documentation_url(project["name"]), bugtracker=app.db.packaging.get_bugtrack_url(project["name"]), maintainers=app.db.packaging.get_users_for_project(project["name"]), )
def project(app, request, project_name): # Get the real project name for this project project = app.db.packaging.get_project(project_name) if project is None: raise NotFound("{} does not exist".format(project_name)) # Generate the Package URLs for the packages we've hosted file_urls = app.db.packaging.get_file_urls(project['name']) # Determine what the hosting mode is for this package hosting_mode = app.db.packaging.get_hosting_mode(project['name']) project_urls = [] if hosting_mode in {"pypi-scrape-crawl", "pypi-scrape"}: rel_prefix = "" if hosting_mode == "pypi-scrape-crawl" else "ext-" home_rel = "{}homepage".format(rel_prefix) download_rel = "{}download".format(rel_prefix) # Generate the Homepage and Download URL links release_urls = app.db.packaging.get_release_urls(project['name']) for version, (home_page, download_url) in release_urls.items(): if home_page and home_page != "UNKNOWN": project_urls.append({ "rel": home_rel, "url": home_page, "name": "{} home_page".format(version), }) if download_url and download_url != "UNKNOWN": project_urls.append({ "rel": download_rel, "url": download_url, "name": "{} download_url".format(version), }) # Fetch the explicitly provided URLs external_urls = app.db.packaging.get_external_urls(project['name']) resp = render_response( app, request, "legacy/simple/detail.html", project=project['name'], files=file_urls, project_urls=project_urls, external_urls=external_urls, ) # Add a header that points to the last serial serial = app.db.packaging.get_last_serial(project['name']) resp.headers.add("X-PyPI-Last-Serial", serial) # Add a Link header to point at the canonical URL can_url = url_for( request, "warehouse.legacy.simple.project", project_name=project['name'], _force_external=True, ) resp.headers.add("Link", "<" + can_url + ">", rel="canonical") return resp