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 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 pypi(app, request): # if the MIME type of the request is XML then we go into XML-RPC mode if request.headers.get("Content-Type") == "text/xml": return xmlrpc.handle_request(app, request) # check for the legacy :action-style dispatch action = request.args.get(":action") if action in _action_methods: return _action_methods[action](app, request) # no XML-RPC and no :action means we render the index, or at least we # redirect to where it moved to return redirect(url_for(request, "warehouse.views.index"), code=301)
def pypi(app, request): # if the MIME type of the request is XML then we go into XML-RPC mode if request.headers.get('Content-Type') == 'text/xml': return xmlrpc.handle_request(app, request) # no XML-RPC and no :action means we render the index, or at least we # redirect to where it moved to return redirect( url_for( request, "warehouse.views.index", ), code=301, )
def pypi(app, request): # check for the legacy :action-style dispatch action = request.args.get(':action') if action in _action_methods: return _action_methods[action](app, request) # No :action means we render the index, or at least we redirect to where it # moved to return redirect( url_for( request, "warehouse.views.index", ), code=301, )
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 test_url_for(external): request = pretend.stub(url_adapter=pretend.stub( build=pretend.call_recorder(lambda *a, **k: "/foo/"), ), ) assert url_for( request, "warehouse.test", foo="bar", _force_external=external, ) == "/foo/" assert request.url_adapter.build.calls == [ pretend.call( "warehouse.test", {"foo": "bar"}, force_external=external, ), ]
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 rss(app, request): """Dump the last N days' updates as an RSS feed. """ releases = app.db.packaging.get_recently_updated(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'], version=release['version'], _force_external=True) release.update(dict(url=url)) response = render_response( app, request, "legacy/rss.xml", description='package updates', 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 test_url_for(external): request = pretend.stub( url_adapter=pretend.stub( build=pretend.call_recorder(lambda *a, **k: "/foo/"), ), ) assert url_for( request, "warehouse.test", foo="bar", _force_external=external, ) == "/foo/" assert request.url_adapter.build.calls == [ pretend.call( "warehouse.test", {"foo": "bar"}, force_external=external, ), ]
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_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) 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, ), ) if project != 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, 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 not version 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, ), ) # Get the release data for the version release = app.db.packaging.get_release(project, version) 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) return render_response( app, request, "projects/detail.html", project=project, release=release, releases=releases, description_html=description_html, download_counts=app.db.packaging.get_download_counts(project), downloads=app.db.packaging.get_downloads(project, version), classifiers=app.db.packaging.get_classifiers(project, version), documentation=app.db.packaging.get_documentation_url(project), bugtracker=app.db.packaging.get_bugtrack_url(project), maintainers=app.db.packaging.get_users_for_project(project), )
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
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