Exemplo n.º 1
0
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"),
    )
Exemplo n.º 2
0
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(),
    )
Exemplo n.º 3
0
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"]],
    )
Exemplo n.º 4
0
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,
        ),
    ]
Exemplo n.º 5
0
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(),
    )
Exemplo n.º 6
0
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"),
    )
Exemplo n.º 7
0
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
Exemplo n.º 8
0
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"),
    )
Exemplo n.º 9
0
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
Exemplo n.º 10
0
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
Exemplo n.º 11
0
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
Exemplo n.º 12
0
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"]),
    )
Exemplo n.º 13
0
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"]),
    )
Exemplo n.º 14
0
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,
        ),
    ]
Exemplo n.º 15
0
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"),
    )
Exemplo n.º 16
0
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"]),
    )
Exemplo n.º 17
0
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
Exemplo n.º 18
0
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"]),
    )
Exemplo n.º 19
0
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