Exemple #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"),
    )
Exemple #2
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"),
    )
Exemple #3
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"),
    )
Exemple #4
0
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)
Exemple #5
0
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,
    )
Exemple #6
0
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,
    )
Exemple #7
0
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,
    )
Exemple #8
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
Exemple #9
0
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,
        ),
    ]
Exemple #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
Exemple #11
0
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
Exemple #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"]),
    )
Exemple #13
0
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,
        ),
    ]
Exemple #14
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"]),
    )
Exemple #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"),
    )
Exemple #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"]),
    )
Exemple #17
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)

    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),
    )
Exemple #18
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
Exemple #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)

    # 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