예제 #1
0
 def test_is_json_request(self):
     with self.app.test_request_context(content_type='application/json'):
         assert_true(is_json_request())
     with self.app.test_request_context(content_type=None):
         assert_false(is_json_request())
     with self.app.test_request_context(content_type='application/json;charset=UTF-8'):
         assert_true(is_json_request())
예제 #2
0
 def test_is_json_request(self):
     with self.app.test_request_context(content_type='application/json'):
         assert_true(is_json_request())
     with self.app.test_request_context(content_type=None):
         assert_false(is_json_request())
     with self.app.test_request_context(content_type='application/json;charset=UTF-8'):
         assert_true(is_json_request())
예제 #3
0
def claim_user_form(auth, **kwargs):
    """View for rendering the set password page for a claimed user.

    Must have ``token`` as a querystring argument.

    Renders the set password form, validates it, and sets the user's password.
    """
    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(
            web_url_for('claim_user_registered', uid=uid, pid=pid,
                        token=token))

    user = User.load(uid)  # The unregistered user
    # user ID is invalid. Unregistered user is not in database
    if not user:
        raise HTTPError(http.BAD_REQUEST)
    # If claim token not valid, redirect to registration page
    if not verify_claim_token(user, token, pid):
        return redirect(web_url_for('auth_login'))
    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get(
        'claimer_email') or unclaimed_record.get('email')
    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if form.validate():
            username, password = claimer_email, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = security.random_string(20)
            user.save()
            # Authenticate user and redirect to project page
            node = Node.load(pid)
            status.push_status_message(
                language.CLAIMED_CONTRIBUTOR.format(node=node),
                kind='success',
                trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            return redirect(
                cas.get_login_url(web_url_for('user_profile', _absolute=True),
                                  auto=True,
                                  username=user.username,
                                  verification_key=user.verification_key))
        else:
            forms.push_errors_to_status(form.errors)
    return {
        'firstname': user.given_name,
        'email': claimer_email if claimer_email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
예제 #4
0
def claim_user_registered(auth, node, **kwargs):
    """View that prompts user to enter their password in order to claim
    contributorship on a project.

    A user must be logged in.
    """
    current_user = auth.user

    sign_out_url = web_url_for('auth_login', logout=True, next=request.url)
    if not current_user:
        return redirect(sign_out_url)
    # Logged in user should not be a contributor the project
    if node.is_contributor(current_user):
        logout_url = web_url_for('auth_logout', redirect_url=request.url)
        data = {
            'message_short': 'Already a contributor',
            'message_long': ('The logged-in user is already a contributor to this '
                'project. Would you like to <a href="{}">log out</a>?').format(logout_url)
        }
        raise HTTPError(http.BAD_REQUEST, data=data)
    uid, pid, token = kwargs['uid'], kwargs['pid'], kwargs['token']
    unreg_user = User.load(uid)
    if not verify_claim_token(unreg_user, token, pid=node._primary_key):
        raise HTTPError(http.BAD_REQUEST)

    # Store the unreg_user data on the session in case the user registers
    # a new account
    session.data['unreg_user'] = {
        'uid': uid, 'pid': pid, 'token': token
    }

    form = PasswordForm(request.form)
    if request.method == 'POST':
        if form.validate():
            if current_user.check_password(form.password.data):
                node.replace_contributor(old=unreg_user, new=current_user)
                node.save()
                status.push_status_message(
                    'You are now a contributor to this project.',
                    kind='success',
                    trust=False
                )
                return redirect(node.url)
            else:
                status.push_status_message(language.LOGIN_FAILED, kind='warning', trust=False)
        else:
            forms.push_errors_to_status(form.errors)
    if is_json_request():
        form_ret = forms.utils.jsonify(form)
        user_ret = profile_utils.serialize_user(current_user, full=False)
    else:
        form_ret = form
        user_ret = current_user
    return {
        'form': form_ret,
        'user': user_ret,
        'signOutUrl': sign_out_url
    }
def claim_user_form(auth, **kwargs):
    """
    View for rendering the set password page for a claimed user.
    Must have ``token`` as a querystring argument.
    Renders the set password form, validates it, and sets the user's password.
    HTTP Method: GET, POST
    """

    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')
    user = User.load(uid)

    # If unregistered user is not in database, or url bears an invalid token raise HTTP 400 error
    if not user or not verify_claim_token(user, token, pid):
        error_data = {
            'message_short': 'Invalid url.',
            'message_long': 'Claim user does not exists, the token in the URL is invalid or has expired.'
        }
        raise HTTPError(http.BAD_REQUEST, data=error_data)

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(web_url_for('claim_user_registered',
            uid=uid, pid=pid, token=token))

    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get('claimer_email') or unclaimed_record.get('email')
    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if not form.validate():
            forms.push_errors_to_status(form.errors)
        elif settings.RECAPTCHA_SITE_KEY and not validate_recaptcha(request.form.get('g-recaptcha-response'), remote_ip=request.remote_addr):
            status.push_status_message('Invalid captcha supplied.', kind='error')
        else:
            username, password = claimer_email, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = generate_verification_key()
            user.save()
            # Authenticate user and redirect to project page
            status.push_status_message(language.CLAIMED_CONTRIBUTOR, kind='success', trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            return redirect(cas.get_login_url(
                web_url_for('view_project', pid=pid, _absolute=True),
                username=user.username,
                verification_key=user.verification_key
            ))

    return {
        'firstname': user.given_name,
        'email': claimer_email if claimer_email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
예제 #6
0
def claim_user_form(auth, **kwargs):
    """
    View for rendering the set password page for a claimed user.
    Must have ``token`` as a querystring argument.
    Renders the set password form, validates it, and sets the user's password.
    HTTP Method: GET, POST
    """

    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')
    user = User.load(uid)

    # If unregistered user is not in database, or url bears an invalid token raise HTTP 400 error
    if not user or not verify_claim_token(user, token, pid):
        error_data = {
            'message_short': 'Invalid url.',
            'message_long': 'Claim user does not exists, the token in the URL is invalid or has expired.'
        }
        raise HTTPError(http.BAD_REQUEST, data=error_data)

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(web_url_for('claim_user_registered',
            uid=uid, pid=pid, token=token))

    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get('claimer_email') or unclaimed_record.get('email')
    form = SetEmailAndPasswordForm(request.form, token=token)

    if request.method == 'POST':
        if form.validate():
            username, password = claimer_email, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = generate_verification_key()
            user.save()
            # Authenticate user and redirect to project page
            status.push_status_message(language.CLAIMED_CONTRIBUTOR, kind='success', trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            return redirect(cas.get_login_url(
                web_url_for('view_project', pid=pid, _absolute=True),
                username=user.username,
                verification_key=user.verification_key
            ))
        else:
            forms.push_errors_to_status(form.errors)

    return {
        'firstname': user.given_name,
        'email': claimer_email if claimer_email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
예제 #7
0
def claim_user_form(auth, **kwargs):
    """View for rendering the set password page for a claimed user.

    Must have ``token`` as a querystring argument.

    Renders the set password form, validates it, and sets the user's password.
    """
    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(web_url_for('claim_user_registered',
            uid=uid, pid=pid, token=token))

    user = User.load(uid)  # The unregistered user
    # user ID is invalid. Unregistered user is not in database
    if not user:
        raise HTTPError(http.BAD_REQUEST)
    # If claim token not valid, redirect to registration page
    if not verify_claim_token(user, token, pid):
        return redirect(web_url_for('auth_login'))
    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get('claimer_email') or unclaimed_record.get('email')
    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if form.validate():
            username, password = claimer_email, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = security.random_string(20)
            user.save()
            # Authenticate user and redirect to project page
            node = Node.load(pid)
            status.push_status_message(language.CLAIMED_CONTRIBUTOR.format(node=node),
                                       kind='success',
                                       trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            return redirect(cas.get_login_url(
                web_url_for('user_profile', _absolute=True),
                auto=True,
                username=user.username,
                verification_key=user.verification_key
            ))
        else:
            forms.push_errors_to_status(form.errors)
    return {
        'firstname': user.given_name,
        'email': claimer_email if claimer_email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
예제 #8
0
def claim_user_registered(auth, node, **kwargs):
    """
    View that prompts user to enter their password in order to claim being a contributor on a project.
    A user must be logged in.
    """

    current_user = auth.user

    sign_out_url = web_url_for("auth_register", logout=True, next=request.url)
    if not current_user:
        return redirect(sign_out_url)

    # Logged in user should not be a contributor the project
    if node.is_contributor(current_user):
        logout_url = web_url_for("auth_logout", redirect_url=request.url)
        data = {
            "message_short": "Already a contributor",
            "message_long": (
                "The logged-in user is already a contributor to this "
                'project. Would you like to <a href="{}">log out</a>?'
            ).format(logout_url),
        }
        raise HTTPError(http.BAD_REQUEST, data=data)

    uid, pid, token = kwargs["uid"], kwargs["pid"], kwargs["token"]
    unreg_user = User.load(uid)
    if not verify_claim_token(unreg_user, token, pid=node._primary_key):
        error_data = {
            "message_short": "Invalid url.",
            "message_long": "The token in the URL is invalid or has expired.",
        }
        raise HTTPError(http.BAD_REQUEST, data=error_data)

    # Store the unreg_user data on the session in case the user registers
    # a new account
    session.data["unreg_user"] = {"uid": uid, "pid": pid, "token": token}

    form = PasswordForm(request.form)
    if request.method == "POST":
        if form.validate():
            if current_user.check_password(form.password.data):
                node.replace_contributor(old=unreg_user, new=current_user)
                node.save()
                status.push_status_message("You are now a contributor to this project.", kind="success", trust=False)
                return redirect(node.url)
            else:
                status.push_status_message(language.LOGIN_FAILED, kind="warning", trust=False)
        else:
            forms.push_errors_to_status(form.errors)
    if is_json_request():
        form_ret = forms.utils.jsonify(form)
        user_ret = profile_utils.serialize_user(current_user, full=False)
    else:
        form_ret = form
        user_ret = current_user
    return {"form": form_ret, "user": user_ret, "signOutUrl": sign_out_url}
예제 #9
0
def claim_user_form(auth, **kwargs):
    """View for rendering the set password page for a claimed user.

    Must have ``token`` as a querystring argument.

    Renders the set password form, validates it, and sets the user's password.
    """
    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(
            web_url_for('claim_user_registered', uid=uid, pid=pid,
                        token=token))

    user = User.load(uid)  # The unregistered user
    # user ID is invalid. Unregistered user is not in database
    if not user:
        raise HTTPError(http.BAD_REQUEST)
    # If claim token not valid, redirect to registration page
    if not verify_claim_token(user, token, pid):
        return redirect('/account/')
    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    email = unclaimed_record['email']
    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if form.validate():
            username, password = form.username.data, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.save()
            # Authenticate user and redirect to project page
            response = redirect('/settings/')
            node = Node.load(pid)
            status.push_status_message(
                language.CLAIMED_CONTRIBUTOR.format(node=node), 'success')
            return authenticate(user, response)
        else:
            forms.push_errors_to_status(form.errors)
    return {
        'firstname': user.given_name,
        'email': email if email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
예제 #10
0
def handle_error(code):
    """Display an error thrown outside a routed view function.

    :param int code: Error status code
    :return: Flask `Response` object

    """
    # TODO: Remove circular import
    from website.routes import OsfWebRenderer
    json_renderer = JSONRenderer()
    web_renderer = OsfWebRenderer('', render_mako_string)

    error = HTTPError(code)
    renderer = json_renderer if is_json_request() else web_renderer
    return make_response(renderer.handle_error(error))
예제 #11
0
def claim_user_form(auth, **kwargs):
    """View for rendering the set password page for a claimed user.

    Must have ``token`` as a querystring argument.

    Renders the set password form, validates it, and sets the user's password.
    """
    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(web_url_for('claim_user_registered',
            uid=uid, pid=pid, token=token))

    user = User.load(uid)  # The unregistered user
    # user ID is invalid. Unregistered user is not in database
    if not user:
        raise HTTPError(http.BAD_REQUEST)
    # If claim token not valid, redirect to registration page
    if not verify_claim_token(user, token, pid):
        return redirect('/account/')
    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    email = unclaimed_record['email']
    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if form.validate():
            username, password = email, form.password.data
            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.save()
            # Authenticate user and redirect to project page
            response = redirect('/settings/')
            node = Node.load(pid)
            status.push_status_message(language.CLAIMED_CONTRIBUTOR.format(node=node),
                'success')
            return authenticate(user, response)
        else:
            forms.push_errors_to_status(form.errors)
    return {
        'firstname': user.given_name,
        'email': email if email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
    }
예제 #12
0
def claim_user_form(auth, **kwargs):
    """
    View for rendering the set password page for a claimed user.
    Must have ``token`` as a querystring argument.
    Renders the set password form, validates it, and sets the user's password.
    HTTP Method: GET, POST
    """

    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')
    user = OSFUser.load(uid)

    # If unregistered user is not in database, or url bears an invalid token raise HTTP 400 error
    if not user or not verify_claim_token(user, token, pid):
        error_data = {
            'message_short': 'Invalid url.',
            'message_long': 'Claim user does not exists, the token in the URL is invalid or has expired.'
        }
        raise HTTPError(http.BAD_REQUEST, data=error_data)

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(web_url_for('claim_user_registered',
            uid=uid, pid=pid, token=token))

    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get('claimer_email') or unclaimed_record.get('email')
    # If there is a registered user with this email, redirect to 're-enter password' page
    try:
        user_from_email = OSFUser.objects.get(emails__address=claimer_email.lower().strip()) if claimer_email else None
    except OSFUser.DoesNotExist:
        user_from_email = None
    if user_from_email and user_from_email.is_registered:
        return redirect(web_url_for('claim_user_registered', uid=uid, pid=pid, token=token))

    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if not form.validate():
            forms.push_errors_to_status(form.errors)
        elif settings.RECAPTCHA_SITE_KEY and not validate_recaptcha(request.form.get('g-recaptcha-response'), remote_ip=request.remote_addr):
            status.push_status_message('Invalid captcha supplied.', kind='error')
        else:
            username, password = claimer_email, form.password.data
            if not username:
                raise HTTPError(http.BAD_REQUEST, data=dict(
                    message_long='No email associated with this account. Please claim this '
                    'account on the project to which you were invited.'
                ))

            user.register(username=username, password=password, accepted_terms_of_service=form.accepted_terms_of_service.data)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = generate_verification_key()
            user.save()
            # Authenticate user and redirect to project page
            status.push_status_message(language.CLAIMED_CONTRIBUTOR, kind='success', trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            provider = PreprintProvider.load(pid)
            redirect_url = None
            if provider:
                redirect_url = web_url_for('auth_login', next=provider.landing_url, _absolute=True)
            else:
                redirect_url = web_url_for('resolve_guid', guid=pid, _absolute=True)

            return redirect(cas.get_login_url(
                redirect_url,
                username=user.username,
                verification_key=user.verification_key
            ))

    return {
        'firstname': user.given_name,
        'email': claimer_email if claimer_email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
        'osf_contact_email': settings.OSF_CONTACT_EMAIL,
    }
예제 #13
0
def claim_user_form(auth, **kwargs):
    """
    View for rendering the set password page for a claimed user.
    Must have ``token`` as a querystring argument.
    Renders the set password form, validates it, and sets the user's password.
    HTTP Method: GET, POST
    """

    uid, pid = kwargs['uid'], kwargs['pid']
    token = request.form.get('token') or request.args.get('token')
    user = OSFUser.load(uid)

    # If unregistered user is not in database, or url bears an invalid token raise HTTP 400 error
    if not user or not verify_claim_token(user, token, pid):
        error_data = {
            'message_short':
            'Invalid url.',
            'message_long':
            'Claim user does not exists, the token in the URL is invalid or has expired.'
        }
        raise HTTPError(http_status.HTTP_400_BAD_REQUEST, data=error_data)

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(
            web_url_for('claim_user_registered', uid=uid, pid=pid,
                        token=token))

    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record['name']
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get(
        'claimer_email') or unclaimed_record.get('email')
    # If there is a registered user with this email, redirect to 're-enter password' page
    try:
        user_from_email = OSFUser.objects.get(
            emails__address=claimer_email.lower().strip(
            )) if claimer_email else None
    except OSFUser.DoesNotExist:
        user_from_email = None
    if user_from_email and user_from_email.is_registered:
        return redirect(
            web_url_for('claim_user_registered', uid=uid, pid=pid,
                        token=token))

    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == 'POST':
        if not form.validate():
            forms.push_errors_to_status(form.errors)
        elif settings.RECAPTCHA_SITE_KEY and not validate_recaptcha(
                request.form.get('g-recaptcha-response'),
                remote_ip=request.remote_addr):
            status.push_status_message('Invalid captcha supplied.',
                                       kind='error')
        else:
            username, password = claimer_email, form.password.data
            if not username:
                raise HTTPError(
                    http_status.HTTP_400_BAD_REQUEST,
                    data=dict(
                        message_long=
                        'No email associated with this account. Please claim this '
                        'account on the project to which you were invited.'))

            user.register(
                username=username,
                password=password,
                accepted_terms_of_service=form.accepted_terms_of_service.data)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = generate_verification_key()
            user.save()
            # Authenticate user and redirect to project page
            status.push_status_message(language.CLAIMED_CONTRIBUTOR,
                                       kind='success',
                                       trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            provider = PreprintProvider.load(pid)
            redirect_url = None
            if provider:
                redirect_url = web_url_for('auth_login',
                                           next=provider.landing_url,
                                           _absolute=True)
            else:
                redirect_url = web_url_for('resolve_guid',
                                           guid=pid,
                                           _absolute=True)

            return redirect(
                cas.get_login_url(redirect_url,
                                  username=user.username,
                                  verification_key=user.verification_key))

    return {
        'firstname': user.given_name,
        'email': claimer_email if claimer_email else '',
        'fullname': user.fullname,
        'form': forms.utils.jsonify(form) if is_json_request() else form,
        'osf_contact_email': settings.OSF_CONTACT_EMAIL,
    }
예제 #14
0
def claim_user_registered(auth, node, **kwargs):
    """
    View that prompts user to enter their password in order to claim being a contributor on a project.
    A user must be logged in.
    """

    current_user = auth.user

    sign_out_url = cas.get_logout_url(service_url=cas.get_login_url(
        service_url=request.url))
    if not current_user:
        return redirect(sign_out_url)

    # Logged in user should not be a contributor the project
    if hasattr(node, 'is_contributor') and node.is_contributor(current_user):
        data = {
            'message_short':
            'Already a contributor',
            'message_long':
            ('The logged-in user is already a contributor to this '
             'project. Would you like to <a href="{}">log out</a>?'
             ).format(sign_out_url)
        }
        raise HTTPError(http_status.HTTP_400_BAD_REQUEST, data=data)

    # Logged in user is already a member of the OSF Group
    if hasattr(node, 'is_member') and node.is_member(current_user):
        data = {
            'message_short':
            'Already a member',
            'message_long':
            ('The logged-in user is already a member of this OSF Group. '
             'Would you like to <a href="{}">log out</a>?'
             ).format(sign_out_url)
        }
        raise HTTPError(http_status.HTTP_400_BAD_REQUEST, data=data)

    uid, pid, token = kwargs['uid'], kwargs['pid'], kwargs['token']
    unreg_user = OSFUser.load(uid)
    if not verify_claim_token(unreg_user, token, pid=node._primary_key):
        error_data = {
            'message_short': 'Invalid url.',
            'message_long': 'The token in the URL is invalid or has expired.'
        }
        raise HTTPError(http_status.HTTP_400_BAD_REQUEST, data=error_data)

    # Store the unreg_user data on the session in case the user registers
    # a new account
    session.data['unreg_user'] = {'uid': uid, 'pid': pid, 'token': token}
    session.save()

    # If a user is already validated though external auth, it is OK to claim
    should_claim = check_external_auth(auth.user)
    form = PasswordForm(request.form)
    if request.method == 'POST':
        if form.validate():
            if current_user.check_password(form.password.data):
                should_claim = True
            else:
                status.push_status_message(language.LOGIN_FAILED,
                                           kind='warning',
                                           trust=False)
        else:
            forms.push_errors_to_status(form.errors)
    if should_claim:
        node.replace_contributor(old=unreg_user, new=current_user)
        node.save()
        if isinstance(node, OSFGroup):
            status.push_status_message(
                'You are now a member of this OSFGroup.',
                kind='success',
                trust=False)
        else:
            status.push_status_message(
                'You are now a contributor to this project.',
                kind='success',
                trust=False)
        return redirect(node.url)
    if is_json_request():
        form_ret = forms.utils.jsonify(form)
        user_ret = profile_utils.serialize_user(current_user, full=False)
    else:
        form_ret = form
        user_ret = current_user
    return {'form': form_ret, 'user': user_ret, 'signOutUrl': sign_out_url}
예제 #15
0
def claim_user_form(auth, **kwargs):
    """
    View for rendering the set password page for a claimed user.
    Must have ``token`` as a querystring argument.
    Renders the set password form, validates it, and sets the user's password.
    HTTP Method: GET, POST
    """

    uid, pid = kwargs["uid"], kwargs["pid"]
    token = request.form.get("token") or request.args.get("token")
    user = User.load(uid)

    # If unregistered user is not in database, or url bears an invalid token raise HTTP 400 error
    if not user or not verify_claim_token(user, token, pid):
        error_data = {
            "message_short": "Invalid url.",
            "message_long": "Claim user does not exists, the token in the URL is invalid or has expired.",
        }
        raise HTTPError(http.BAD_REQUEST, data=error_data)

    # If user is logged in, redirect to 're-enter password' page
    if auth.logged_in:
        return redirect(web_url_for("claim_user_registered", uid=uid, pid=pid, token=token))

    unclaimed_record = user.unclaimed_records[pid]
    user.fullname = unclaimed_record["name"]
    user.update_guessed_names()
    # The email can be the original referrer email if no claimer email has been specified.
    claimer_email = unclaimed_record.get("claimer_email") or unclaimed_record.get("email")

    # If there is a registered user with this email, redirect to 're-enter password' page
    found_by_email = User.find_by_email(claimer_email)
    user_from_email = found_by_email[0] if found_by_email else None
    if user_from_email and user_from_email.is_registered:
        return redirect(web_url_for("claim_user_registered", uid=uid, pid=pid, token=token))

    form = SetEmailAndPasswordForm(request.form, token=token)
    if request.method == "POST":
        if not form.validate():
            forms.push_errors_to_status(form.errors)
        elif settings.RECAPTCHA_SITE_KEY and not validate_recaptcha(
            request.form.get("g-recaptcha-response"), remote_ip=request.remote_addr
        ):
            status.push_status_message("Invalid captcha supplied.", kind="error")
        else:
            username, password = claimer_email, form.password.data
            if not username:
                raise HTTPError(
                    http.BAD_REQUEST,
                    data=dict(
                        message_long="No email associated with this account. Please claim this "
                        "account on the project to which you were invited."
                    ),
                )

            user.register(username=username, password=password)
            # Clear unclaimed records
            user.unclaimed_records = {}
            user.verification_key = generate_verification_key()
            user.save()
            # Authenticate user and redirect to project page
            status.push_status_message(language.CLAIMED_CONTRIBUTOR, kind="success", trust=True)
            # Redirect to CAS and authenticate the user with a verification key.
            return redirect(
                cas.get_login_url(
                    web_url_for("view_project", pid=pid, _absolute=True),
                    username=user.username,
                    verification_key=user.verification_key,
                )
            )

    return {
        "firstname": user.given_name,
        "email": claimer_email if claimer_email else "",
        "fullname": user.fullname,
        "form": forms.utils.jsonify(form) if is_json_request() else form,
    }