Exemple #1
0
def remove_blacklist(request):
    blacklist_id = request.POST.get("blacklist_id")
    if blacklist_id is None:
        raise HTTPBadRequest("Have a blacklist_id to remove.")

    try:
        blacklist = (
            request.db.query(BlacklistedProject)
            .filter(BlacklistedProject.id == blacklist_id)
            .one()
        )
    except NoResultFound:
        raise HTTPNotFound from None

    request.db.delete(blacklist)

    request.session.flash(f"{blacklist.name!r} unblacklisted", queue="success")

    redirect_to = request.POST.get("next")
    # If the user-originating redirection url is not safe, then redirect to
    # the index instead.
    if not redirect_to or not is_safe_url(url=redirect_to, host=request.host):
        redirect_to = request.route_path("admin.blacklist.list")

    return HTTPSeeOther(redirect_to)
Exemple #2
0
def login(request, redirect_field_name=REDIRECT_FIELD_NAME, _form_class=LoginForm):
    # TODO: Logging in should reset request.user
    # TODO: Configure the login view as the default view for not having
    #       permission to view something.
    if request.authenticated_userid is not None:
        return HTTPSeeOther(request.route_path("manage.projects"))

    user_service = request.find_service(IUserService, context=None)
    breach_service = request.find_service(IPasswordBreachedService, context=None)

    redirect_to = request.POST.get(
        redirect_field_name, request.GET.get(redirect_field_name)
    )

    form = _form_class(
        request.POST,
        request=request,
        user_service=user_service,
        breach_service=breach_service,
        check_password_metrics_tags=["method:auth", "auth_method:login_form"],
    )

    if request.method == "POST":
        if form.validate():
            # Get the user id for the given username.
            username = form.username.data
            userid = user_service.find_userid(username)

            # If the user-originating redirection url is not safe, then
            # redirect to the index instead.
            if not redirect_to or not is_safe_url(url=redirect_to, host=request.host):
                redirect_to = request.route_path("manage.projects")

            # Actually perform the login routine for our user.
            headers = _login_user(request, userid)

            # Now that we're logged in we'll want to redirect the user to
            # either where they were trying to go originally, or to the default
            # view.
            resp = HTTPSeeOther(redirect_to, headers=dict(headers))

            # We'll use this cookie so that client side javascript can
            # Determine the actual user ID (not username, user ID). This is
            # *not* a security sensitive context and it *MUST* not be used
            # where security matters.
            #
            # We'll also hash this value just to avoid leaking the actual User
            # IDs here, even though it really shouldn't matter.
            resp.set_cookie(
                USER_ID_INSECURE_COOKIE,
                hashlib.blake2b(str(userid).encode("ascii"), person=b"warehouse.userid")
                .hexdigest()
                .lower(),
            )
            return resp

    return {
        "form": form,
        "redirect": {"field": REDIRECT_FIELD_NAME, "data": redirect_to},
    }
Exemple #3
0
def login(request, redirect_field_name=REDIRECT_FIELD_NAME, _form_class=LoginForm):
    # TODO: Logging in should reset request.user
    # TODO: Configure the login view as the default view for not having
    #       permission to view something.
    if request.authenticated_userid is not None:
        return HTTPSeeOther(request.route_path("manage.projects"))

    user_service = request.find_service(IUserService, context=None)
    breach_service = request.find_service(IPasswordBreachedService, context=None)

    redirect_to = request.POST.get(
        redirect_field_name, request.GET.get(redirect_field_name)
    )

    form = _form_class(
        request.POST,
        request=request,
        user_service=user_service,
        breach_service=breach_service,
        check_password_metrics_tags=["method:auth", "auth_method:login_form"],
    )

    if request.method == "POST":
        if form.validate():
            # Get the user id for the given username.
            username = form.username.data
            userid = user_service.find_userid(username)

            # If the user-originating redirection url is not safe, then
            # redirect to the index instead.
            if not redirect_to or not is_safe_url(url=redirect_to, host=request.host):
                redirect_to = request.route_path("manage.projects")

            # Actually perform the login routine for our user.
            headers = _login_user(request, userid)

            # Now that we're logged in we'll want to redirect the user to
            # either where they were trying to go originally, or to the default
            # view.
            resp = HTTPSeeOther(redirect_to, headers=dict(headers))

            # We'll use this cookie so that client side javascript can
            # Determine the actual user ID (not username, user ID). This is
            # *not* a security sensitive context and it *MUST* not be used
            # where security matters.
            #
            # We'll also hash this value just to avoid leaking the actual User
            # IDs here, even though it really shouldn't matter.
            resp.set_cookie(
                USER_ID_INSECURE_COOKIE,
                hashlib.blake2b(str(userid).encode("ascii"), person=b"warehouse.userid")
                .hexdigest()
                .lower(),
            )
            return resp

    return {
        "form": form,
        "redirect": {"field": REDIRECT_FIELD_NAME, "data": redirect_to},
    }
Exemple #4
0
def remove_prohibited_project_names(request):
    prohibited_project_name_id = request.POST.get("prohibited_project_name_id")
    if prohibited_project_name_id is None:
        raise HTTPBadRequest("Have a prohibited_project_name_id to remove.")

    try:
        prohibited_project_names = (
            request.db.query(ProhibitedProjectName)
            .filter(ProhibitedProjectName.id == prohibited_project_name_id)
            .one()
        )
    except NoResultFound:
        raise HTTPNotFound from None

    request.db.delete(prohibited_project_names)

    request.session.flash(
        f"{prohibited_project_names.name!r} unprohibited", queue="success"
    )

    redirect_to = request.POST.get("next")
    # If the user-originating redirection url is not safe, then redirect to
    # the index instead.
    if not redirect_to or not is_safe_url(url=redirect_to, host=request.host):
        redirect_to = request.route_path("admin.prohibited_project_names.list")

    return HTTPSeeOther(redirect_to)
Exemple #5
0
def logout(request, redirect_field_name=REDIRECT_FIELD_NAME):
    # TODO: If already logged out just redirect to ?next=
    # TODO: Logging out should reset request.user

    redirect_to = request.POST.get(redirect_field_name,
                                   request.GET.get(redirect_field_name))

    if request.method == "POST":
        # A POST to the logout view tells us to logout. There's no form to
        # validate here becuse there's no data. We should be protected against
        # CSRF attacks still because of the CSRF framework, so users will still
        # need a post body that contains the CSRF token.
        headers = forget(request)

        # When crossing an authentication boundry we want to create a new
        # session identifier. We don't want to keep any information in the
        # session when going from authenticated to unauthenticated because
        # user's generally expect that logging out is a desctructive action
        # that erases all of their private data. However if we don't clear the
        # session then another user can use the computer after them, log in to
        # their account, and then gain access to anything sensitive stored in
        # the session for the original user.
        request.session.invalidate()

        # If the user-originating redirection url is not safe, then redirect to
        # the index instead.
        if (not redirect_to or
                not is_safe_url(url=redirect_to, host=request.host)):
            redirect_to = "/"

        # Now that we're logged out we'll want to redirect the user to either
        # where they were originally, or to the default view.
        return HTTPSeeOther(redirect_to, headers=dict(headers))

    return {"redirect": {"field": REDIRECT_FIELD_NAME, "data": redirect_to}}
Exemple #6
0
def logout(request, redirect_field_name=REDIRECT_FIELD_NAME):
    # TODO: If already logged out just redirect to ?next=
    # TODO: Logging out should reset request.user

    redirect_to = request.POST.get(redirect_field_name,
                                   request.GET.get(redirect_field_name))

    if request.method == "POST":
        # A POST to the logout view tells us to logout. There's no form to
        # validate here becuse there's no data. We should be protected against
        # CSRF attacks still because of the CSRF framework, so users will still
        # need a post body that contains the CSRF token.
        headers = forget(request)

        # When crossing an authentication boundry we want to create a new
        # session identifier. We don't want to keep any information in the
        # session when going from authenticated to unauthenticated because
        # user's generally expect that logging out is a desctructive action
        # that erases all of their private data. However if we don't clear the
        # session then another user can use the computer after them, log in to
        # their account, and then gain access to anything sensitive stored in
        # the session for the original user.
        request.session.invalidate()

        # If the user-originating redirection url is not safe, then redirect to
        # the index instead.
        if (not redirect_to or
                not is_safe_url(url=redirect_to, host=request.host)):
            redirect_to = "/"

        # Now that we're logged out we'll want to redirect the user to either
        # where they were originally, or to the default view.
        return HTTPSeeOther(redirect_to, headers=dict(headers))

    return {"redirect": {"field": REDIRECT_FIELD_NAME, "data": redirect_to}}
Exemple #7
0
def login(request, redirect_field_name=REDIRECT_FIELD_NAME, _form_class=LoginForm):
    # TODO: Logging in should reset request.user
    # TODO: Configure the login view as the default view for not having
    #       permission to view something.

    login_service = request.find_service(IUserService, context=None)

    redirect_to = request.POST.get(redirect_field_name, request.GET.get(redirect_field_name))

    form = _form_class(request.POST, login_service=login_service)

    if request.method == "POST" and form.validate():
        # Get the user id for the given username.
        username = form.username.data
        userid = login_service.find_userid(username)

        # We have a session factory associated with this request, so in order
        # to protect against session fixation attacks we're going to make sure
        # that we create a new session (which for sessions with an identifier
        # will cause it to get a new session identifier).

        # We need to protect against session fixation attacks, so make sure
        # that we create a new session (which will cause it to get a new
        # session identifier).
        if request.unauthenticated_userid is not None and request.unauthenticated_userid != userid:
            # There is already a userid associated with this request and it is
            # a different userid than the one we're trying to remember now. In
            # this case we want to drop the existing session completely because
            # we don't want to leak any data between authenticated userids.
            request.session.invalidate()
        else:
            # We either do not have an associated userid with this request
            # already, or the userid is the same one we're trying to remember
            # now. In either case we want to keep all of the data but we want
            # to make sure that we create a new session since we're crossing
            # a privilege boundary.
            data = dict(request.session.items())
            request.session.invalidate()
            request.session.update(data)

        # Remember the userid using the authentication policy.
        headers = remember(request, userid)

        # Cycle the CSRF token since we've crossed an authentication boundary
        # and we don't want to continue using the old one.
        request.session.new_csrf_token()

        # If the user-originating redirection url is not safe, then redirect to
        # the index instead.
        if not redirect_to or not is_safe_url(url=redirect_to, host=request.host):
            redirect_to = "/"

        # Now that we're logged in we'll want to redirect the user to either
        # where they were trying to go originally, or to the default view.
        return HTTPSeeOther(redirect_to, headers=dict(headers))

    return {"form": form, "redirect": {"field": REDIRECT_FIELD_NAME, "data": redirect_to}}
Exemple #8
0
def login(request,
          redirect_field_name=REDIRECT_FIELD_NAME,
          _form_class=forms.LoginForm):
    # TODO: Logging in should reset request.user
    # TODO: Configure the login view as the default view for not having
    #       permission to view something.

    user_service = request.find_service(IUserService, context=None)

    redirect_to = request.POST.get(redirect_field_name,
                                   request.GET.get(redirect_field_name))

    form = _form_class(request.POST, user_service=user_service)

    if request.method == "POST" and form.validate():
        # Get the user id for the given username.
        username = form.username.data
        userid = user_service.find_userid(username)

        # If the user-originating redirection url is not safe, then redirect to
        # the index instead.
        if (not redirect_to
                or not is_safe_url(url=redirect_to, host=request.host)):
            redirect_to = "/"

        # Actually perform the login routine for our user.
        headers = _login_user(request, userid)

        # Now that we're logged in we'll want to redirect the user to either
        # where they were trying to go originally, or to the default view.
        resp = HTTPSeeOther(redirect_to, headers=dict(headers))

        # We'll use this cookie so that client side javascript can Determine
        # the actual user ID (not username, user ID). This is *not* a security
        # sensitive context and it *MUST* not be used where security matters.
        #
        # We'll also hash this value just to avoid leaking the actual User IDs
        # here, even though it really shouldn't matter.
        resp.set_cookie(
            USER_ID_INSECURE_COOKIE,
            blake2b(
                str(userid).encode("ascii"),
                person=b"warehouse.userid",
            ).hexdigest().lower(),
        )

        return resp

    return {
        "form": form,
        "redirect": {
            "field": REDIRECT_FIELD_NAME,
            "data": redirect_to,
        },
    }
Exemple #9
0
def login(request, redirect_field_name=REDIRECT_FIELD_NAME,
          _form_class=forms.LoginForm):
    # TODO: Logging in should reset request.user
    # TODO: Configure the login view as the default view for not having
    #       permission to view something.

    user_service = request.find_service(IUserService, context=None)

    redirect_to = request.POST.get(redirect_field_name,
                                   request.GET.get(redirect_field_name))

    form = _form_class(request.POST, user_service=user_service)

    if request.method == "POST" and form.validate():
        # Get the user id for the given username.
        username = form.username.data
        userid = user_service.find_userid(username)

        # If the user-originating redirection url is not safe, then redirect to
        # the index instead.
        if (not redirect_to or
                not is_safe_url(url=redirect_to, host=request.host)):
            redirect_to = "/"

        # Actually perform the login routine for our user.
        headers = _login_user(request, userid)

        # Now that we're logged in we'll want to redirect the user to either
        # where they were trying to go originally, or to the default view.
        resp = HTTPSeeOther(redirect_to, headers=dict(headers))

        # We'll use this cookie so that client side javascript can Determine
        # the actual user ID (not username, user ID). This is *not* a security
        # sensitive context and it *MUST* not be used where security matters.
        #
        # We'll also hash this value just to avoid leaking the actual User IDs
        # here, even though it really shouldn't matter.
        resp.set_cookie(
            USER_ID_INSECURE_COOKIE,
            blake2b(
                str(userid).encode("ascii"),
                person=b"warehouse.userid",
            ).hexdigest().lower(),
        )

        return resp

    return {
        "form": form,
        "redirect": {
            "field": REDIRECT_FIELD_NAME,
            "data": redirect_to,
        },
    }
Exemple #10
0
def locale(request):
    form = SetLocaleForm(**request.GET)

    redirect_to = request.referer
    if not is_safe_url(redirect_to, host=request.host):
        redirect_to = request.route_path("index")
    resp = HTTPSeeOther(redirect_to)

    if form.validate():
        request.session.flash("Locale updated", queue="success")
        resp.set_cookie(LOCALE_ATTR, form.locale_id.data)

    return resp
Exemple #11
0
def two_factor(request, _form_class=TwoFactorForm):
    if request.authenticated_userid is not None:
        return HTTPSeeOther(request.route_path("manage.projects"))

    token_service = request.find_service(ITokenService, name="two_factor")

    try:
        two_factor_data = token_service.loads(request.query_string)
    except TokenException:
        request.session.flash("Invalid or expired two factor login.",
                              queue="error")
        return HTTPSeeOther(request.route_path("accounts.login"))

    userid = two_factor_data.get("userid")
    if not userid:
        return HTTPSeeOther(request.route_path("accounts.login"))

    redirect_to = two_factor_data.get("redirect_to")

    user_service = request.find_service(IUserService, context=None)

    form = _form_class(
        request.POST,
        user_id=userid,
        user_service=user_service,
        check_password_metrics_tags=["method:auth", "auth_method:login_form"],
    )

    if request.method == "POST":
        if form.validate():
            # If the user-originating redirection url is not safe, then
            # redirect to the index instead.
            if not redirect_to or not is_safe_url(url=redirect_to,
                                                  host=request.host):
                redirect_to = request.route_path("manage.projects")

            _login_user(request, userid)

            resp = HTTPSeeOther(redirect_to)
            resp.set_cookie(
                USER_ID_INSECURE_COOKIE,
                hashlib.blake2b(
                    str(userid).encode("ascii"),
                    person=b"warehouse.userid").hexdigest().lower(),
            )

            return resp
        else:
            form.totp_value.data = ""

    return {"form": form}
Exemple #12
0
def _get_two_factor_data(request, _redirect_to="/"):
    token_service = request.find_service(ITokenService, name="two_factor")
    two_factor_data = token_service.loads(request.query_string)

    if two_factor_data.get("userid") is None:
        raise TokenInvalid

    # If the user-originating redirection url is not safe, then
    # redirect to the index instead.
    redirect_to = two_factor_data.get("redirect_to")
    if redirect_to is None or not is_safe_url(url=redirect_to, host=request.host):
        two_factor_data["redirect_to"] = _redirect_to

    return two_factor_data
Exemple #13
0
    def delete_macaroon(self):
        form = DeleteMacaroonForm(**self.request.POST,
                                  macaroon_service=self.macaroon_service)

        if form.validate():
            description = self.macaroon_service.find_macaroon(
                form.macaroon_id.data).description
            self.macaroon_service.delete_macaroon(form.macaroon_id.data)
            self.request.session.flash(f"Deleted API token '{description}'.",
                                       queue="success")

        redirect_to = self.request.referer
        if not is_safe_url(redirect_to, host=self.request.host):
            redirect_to = self.request.route_path("manage.account")
        return HTTPSeeOther(redirect_to)
Exemple #14
0
def two_factor(request, _form_class=TwoFactorForm):
    if request.authenticated_userid is not None:
        return HTTPSeeOther(request.route_path("manage.projects"))

    token_service = request.find_service(ITokenService, name="two_factor")

    try:
        two_factor_data = token_service.loads(request.query_string)
    except TokenException:
        request.session.flash("Invalid or expired two factor login.", queue="error")
        return HTTPSeeOther(request.route_path("accounts.login"))

    userid = two_factor_data.get("userid")
    if not userid:
        return HTTPSeeOther(request.route_path("accounts.login"))

    redirect_to = two_factor_data.get("redirect_to")

    user_service = request.find_service(IUserService, context=None)

    form = _form_class(
        request.POST,
        user_id=userid,
        user_service=user_service,
        check_password_metrics_tags=["method:auth", "auth_method:login_form"],
    )

    if request.method == "POST":
        if form.validate():
            # If the user-originating redirection url is not safe, then
            # redirect to the index instead.
            if not redirect_to or not is_safe_url(url=redirect_to, host=request.host):
                redirect_to = request.route_path("manage.projects")

            _login_user(request, userid)

            resp = HTTPSeeOther(redirect_to)
            resp.set_cookie(
                USER_ID_INSECURE_COOKIE,
                hashlib.blake2b(str(userid).encode("ascii"), person=b"warehouse.userid")
                .hexdigest()
                .lower(),
            )

            return resp

    return {"form": form}
Exemple #15
0
def logout(request, redirect_field_name=REDIRECT_FIELD_NAME):
    # TODO: Logging out should reset request.user

    redirect_to = request.POST.get(
        redirect_field_name, request.GET.get(redirect_field_name)
    )

    # If the user-originating redirection url is not safe, then redirect to
    # the index instead.
    if not redirect_to or not is_safe_url(url=redirect_to, host=request.host):
        redirect_to = "/"

    # If we're already logged out, then we'll go ahead and issue our redirect right
    # away instead of trying to log a non-existent user out.
    if request.user is None:
        return HTTPSeeOther(redirect_to)

    if request.method == "POST":
        # A POST to the logout view tells us to logout. There's no form to
        # validate here because there's no data. We should be protected against
        # CSRF attacks still because of the CSRF framework, so users will still
        # need a post body that contains the CSRF token.
        headers = forget(request)

        # When crossing an authentication boundary we want to create a new
        # session identifier. We don't want to keep any information in the
        # session when going from authenticated to unauthenticated because
        # user's generally expect that logging out is a destructive action
        # that erases all of their private data. However, if we don't clear the
        # session then another user can use the computer after them, log in to
        # their account, and then gain access to anything sensitive stored in
        # the session for the original user.
        request.session.invalidate()

        # Now that we're logged out we'll want to redirect the user to either
        # where they were originally, or to the default view.
        resp = HTTPSeeOther(redirect_to, headers=dict(headers))

        # Ensure that we delete our user_id__insecure cookie, since the user is
        # no longer logged in.
        resp.delete_cookie(USER_ID_INSECURE_COOKIE)

        return resp

    return {"redirect": {"field": REDIRECT_FIELD_NAME, "data": redirect_to}}
Exemple #16
0
    def delete_macaroon(self):
        form = DeleteMacaroonForm(
            password=self.request.POST["confirm_password"],
            macaroon_id=self.request.POST["macaroon_id"],
            macaroon_service=self.macaroon_service,
            username=self.request.user.username,
            user_service=self.user_service,
        )

        if form.validate():
            macaroon = self.macaroon_service.find_macaroon(
                form.macaroon_id.data)
            self.macaroon_service.delete_macaroon(form.macaroon_id.data)
            self.user_service.record_event(
                self.request.user.id,
                tag="account:api_token:removed",
                ip_address=self.request.remote_addr,
                additional={"macaroon_id": form.macaroon_id.data},
            )
            if "projects" in macaroon.caveats["permissions"]:
                projects = [
                    project for project in self.request.user.projects
                    if project.normalized_name in
                    macaroon.caveats["permissions"]["projects"]
                ]
                for project in projects:
                    project.record_event(
                        tag="project:api_token:removed",
                        ip_address=self.request.remote_addr,
                        additional={
                            "description": macaroon.description,
                            "user": self.request.user.username,
                        },
                    )
            self.request.session.flash(
                f"Deleted API token '{macaroon.description}'.",
                queue="success")
        else:
            self.request.session.flash("Invalid credentials. Try again",
                                       queue="error")

        redirect_to = self.request.referer
        if not is_safe_url(redirect_to, host=self.request.host):
            redirect_to = self.request.route_path("manage.account")
        return HTTPSeeOther(redirect_to)
Exemple #17
0
def logout(request, redirect_field_name=REDIRECT_FIELD_NAME):
    # TODO: Logging out should reset request.user

    redirect_to = request.POST.get(
        redirect_field_name, request.GET.get(redirect_field_name)
    )

    # If the user-originating redirection url is not safe, then redirect to
    # the index instead.
    if not redirect_to or not is_safe_url(url=redirect_to, host=request.host):
        redirect_to = "/"

    # If we're already logged out, then we'll go ahead and issue our redirect right
    # away instead of trying to log a non-existent user out.
    if request.user is None:
        return HTTPSeeOther(redirect_to)

    if request.method == "POST":
        # A POST to the logout view tells us to logout. There's no form to
        # validate here because there's no data. We should be protected against
        # CSRF attacks still because of the CSRF framework, so users will still
        # need a post body that contains the CSRF token.
        headers = forget(request)

        # When crossing an authentication boundary we want to create a new
        # session identifier. We don't want to keep any information in the
        # session when going from authenticated to unauthenticated because
        # user's generally expect that logging out is a destructive action
        # that erases all of their private data. However, if we don't clear the
        # session then another user can use the computer after them, log in to
        # their account, and then gain access to anything sensitive stored in
        # the session for the original user.
        request.session.invalidate()

        # Now that we're logged out we'll want to redirect the user to either
        # where they were originally, or to the default view.
        resp = HTTPSeeOther(redirect_to, headers=dict(headers))

        # Ensure that we delete our user_id__insecure cookie, since the user is
        # no longer logged in.
        resp.delete_cookie(USER_ID_INSECURE_COOKIE)

        return resp

    return {"redirect": {"field": REDIRECT_FIELD_NAME, "data": redirect_to}}
Exemple #18
0
def locale(request):
    form = SetLocaleForm(**request.GET)

    redirect_to = request.referer
    if not is_safe_url(redirect_to, host=request.host):
        redirect_to = request.route_path("index")
    resp = HTTPSeeOther(redirect_to)

    if form.validate():
        # Build a localizer for the locale we're about to switch to. This will
        # happen automatically once the cookie is set, but if we want the flash
        # message indicating success to be in the new language as well, we need
        # to do it here.
        tdirs = request.registry.queryUtility(ITranslationDirectories)
        _ = make_localizer(form.locale_id.data, tdirs).translate
        request.session.flash(_("Locale updated"), queue="success")
        resp.set_cookie(LOCALE_ATTR, form.locale_id.data)

    return resp
Exemple #19
0
def _get_two_factor_data(request, _redirect_to="/"):
    token_service = request.find_service(ITokenService, name="two_factor")
    two_factor_data, timestamp = token_service.loads(
        request.query_string, return_timestamp=True
    )

    if two_factor_data.get("userid") is None:
        raise TokenInvalid

    user_service = request.find_service(IUserService, context=None)
    user = user_service.get_user(two_factor_data.get("userid"))
    if timestamp < user.last_login:
        raise TokenInvalid

    # If the user-originating redirection url is not safe, then
    # redirect to the index instead.
    redirect_to = two_factor_data.get("redirect_to")
    if redirect_to is None or not is_safe_url(url=redirect_to, host=request.host):
        two_factor_data["redirect_to"] = _redirect_to

    return two_factor_data
Exemple #20
0
def login(request,
          redirect_field_name=REDIRECT_FIELD_NAME,
          _form_class=forms.LoginForm):
    # TODO: Logging in should reset request.user
    # TODO: Configure the login view as the default view for not having
    #       permission to view something.

    user_service = request.find_service(IUserService, context=None)

    redirect_to = request.POST.get(redirect_field_name,
                                   request.GET.get(redirect_field_name))

    form = _form_class(request.POST, user_service=user_service)

    if request.method == "POST" and form.validate():
        # Get the user id for the given username.
        username = form.username.data
        userid = user_service.find_userid(username)

        # If the user-originating redirection url is not safe, then redirect to
        # the index instead.
        if (not redirect_to
                or not is_safe_url(url=redirect_to, host=request.host)):
            redirect_to = "/"

        # Actually perform the login routine for our user.
        headers = _login_user(request, userid)

        # Now that we're logged in we'll want to redirect the user to either
        # where they were trying to go originally, or to the default view.
        return HTTPSeeOther(redirect_to, headers=dict(headers))

    return {
        "form": form,
        "redirect": {
            "field": REDIRECT_FIELD_NAME,
            "data": redirect_to,
        },
    }
Exemple #21
0
def login(request, redirect_field_name=REDIRECT_FIELD_NAME,
          _form_class=forms.LoginForm):
    # TODO: Logging in should reset request.user
    # TODO: Configure the login view as the default view for not having
    #       permission to view something.

    user_service = request.find_service(IUserService, context=None)

    redirect_to = request.POST.get(redirect_field_name,
                                   request.GET.get(redirect_field_name))

    form = _form_class(request.POST, user_service=user_service)

    if request.method == "POST" and form.validate():
        # Get the user id for the given username.
        username = form.username.data
        userid = user_service.find_userid(username)

        # If the user-originating redirection url is not safe, then redirect to
        # the index instead.
        if (not redirect_to or
                not is_safe_url(url=redirect_to, host=request.host)):
            redirect_to = "/"

        # Actually perform the login routine for our user.
        headers = _login_user(request, userid)

        # Now that we're logged in we'll want to redirect the user to either
        # where they were trying to go originally, or to the default view.
        return HTTPSeeOther(redirect_to, headers=dict(headers))

    return {
        "form": form,
        "redirect": {
            "field": REDIRECT_FIELD_NAME,
            "data": redirect_to,
        },
    }
Exemple #22
0
def login(request, redirect_field_name=REDIRECT_FIELD_NAME,
          _form_class=LoginForm):
    # TODO: Logging in should reset request.user
    # TODO: Configure the login view as the default view for not having
    #       permission to view something.

    login_service = request.find_service(IUserService, context=None)

    redirect_to = request.POST.get(redirect_field_name,
                                   request.GET.get(redirect_field_name))

    form = _form_class(request.POST, login_service=login_service)

    if request.method == "POST" and form.validate():
        # Get the user id for the given username.
        username = form.username.data
        userid = login_service.find_userid(username)

        # We have a session factory associated with this request, so in order
        # to protect against session fixation attacks we're going to make sure
        # that we create a new session (which for sessions with an identifier
        # will cause it to get a new session identifier).

        # We need to protect against session fixation attacks, so make sure
        # that we create a new session (which will cause it to get a new
        # session identifier).
        if (request.unauthenticated_userid is not None and
                request.unauthenticated_userid != userid):
            # There is already a userid associated with this request and it is
            # a different userid than the one we're trying to remember now. In
            # this case we want to drop the existing session completely because
            # we don't want to leak any data between authenticated userids.
            request.session.invalidate()
        else:
            # We either do not have an associated userid with this request
            # already, or the userid is the same one we're trying to remember
            # now. In either case we want to keep all of the data but we want
            # to make sure that we create a new session since we're crossing
            # a privilege boundary.
            data = dict(request.session.items())
            request.session.invalidate()
            request.session.update(data)

        # Remember the userid using the authentication policy.
        headers = remember(request, userid)

        # Cycle the CSRF token since we've crossed an authentication boundary
        # and we don't want to continue using the old one.
        request.session.new_csrf_token()

        # If the user-originating redirection url is not safe, then redirect to
        # the index instead.
        if (not redirect_to or
                not is_safe_url(url=redirect_to, host=request.host)):
            redirect_to = "/"

        # Now that we're logged in we'll want to redirect the user to either
        # where they were trying to go originally, or to the default view.
        return HTTPSeeOther(redirect_to, headers=dict(headers))

    return {
        "form": form,
        "redirect": {
            "field": REDIRECT_FIELD_NAME,
            "data": redirect_to,
        },
    }
Exemple #23
0
 def test_rejects_bad_url(self, url):
     assert not is_safe_url(url, host="testserver")
Exemple #24
0
 def test_rejects_bad_url(self, url):
     assert not is_safe_url(url, host="testserver")
Exemple #25
0
 def test_accepts_good_url(self, url):
     assert is_safe_url(url, host="testserver")
Exemple #26
0
 def test_accepts_good_url(self, url):
     assert is_safe_url(url, host="testserver")