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, }
def register_user(**kwargs): """ Register new user account. HTTP Method: POST :param-json str email1: :param-json str email2: :param-json str password: :param-json str fullName: :param-json str campaign: :raises: HTTPError(http.BAD_REQUEST) if validation fails or user already exists """ # Verify that email address match. # Note: Both `landing.mako` and `register.mako` already have this check on the form. Users can not submit the form # if emails do not match. However, this check should not be removed given we may use the raw api call directly. json_data = request.get_json() if str(json_data['email1']).lower() != str(json_data['email2']).lower(): raise HTTPError(http.BAD_REQUEST, data=dict(message_long='Email addresses must match.')) # Verify that captcha is valid if settings.RECAPTCHA_SITE_KEY and not validate_recaptcha( json_data.get('g-recaptcha-response'), remote_ip=request.remote_addr): raise HTTPError(http.BAD_REQUEST, data=dict(message_long='Invalid Captcha')) try: full_name = request.json['fullName'] full_name = strip_html(full_name) campaign = json_data.get('campaign') if campaign and campaign not in campaigns.get_campaigns(): campaign = None user = framework_auth.register_unconfirmed( request.json['email1'], request.json['password'], full_name, campaign=campaign, ) framework_auth.signals.user_registered.send(user) except (ValidationValueError, DuplicateEmailError): raise HTTPError( http.BAD_REQUEST, data=dict(message_long=language.ALREADY_REGISTERED.format( email=markupsafe.escape(request.json['email1'])))) except ValidationError as e: raise HTTPError(http.BAD_REQUEST, data=dict(message_long=e.message)) if settings.CONFIRM_REGISTRATIONS_BY_EMAIL: send_confirm_email(user, email=user.username) message = language.REGISTRATION_SUCCESS.format(email=user.username) return {'message': message} else: return {'message': 'You may now log in.'}
def register_user(**kwargs): """ Register new user account. HTTP Method: POST :param-json str email1: :param-json str email2: :param-json str password: :param-json str fullName: :param-json str campaign: :raises: HTTPError(http.BAD_REQUEST) if validation fails or user already exists """ # Verify that email address match. # Note: Both `landing.mako` and `register.mako` already have this check on the form. Users can not submit the form # if emails do not match. However, this check should not be removed given we may use the raw api call directly. json_data = request.get_json() if str(json_data['email1']).lower() != str(json_data['email2']).lower(): raise HTTPError( http.BAD_REQUEST, data=dict(message_long='Email addresses must match.') ) # Verify that captcha is valid if settings.RECAPTCHA_SITE_KEY and not validate_recaptcha(json_data.get('g-recaptcha-response'), remote_ip=request.remote_addr): raise HTTPError( http.BAD_REQUEST, data=dict(message_long='Invalid Captcha') ) try: full_name = request.json['fullName'] full_name = strip_html(full_name) campaign = json_data.get('campaign') if campaign and campaign not in campaigns.get_campaigns(): campaign = None user = framework_auth.register_unconfirmed( request.json['email1'], request.json['password'], full_name, campaign=campaign, ) framework_auth.signals.user_registered.send(user) except (ValidationValueError, DuplicateEmailError): raise HTTPError( http.BAD_REQUEST, data=dict( message_long=language.ALREADY_REGISTERED.format( email=markupsafe.escape(request.json['email1']) ) ) ) except ValidationError as e: raise HTTPError( http.BAD_REQUEST, data=dict(message_long=e.message) ) if settings.CONFIRM_REGISTRATIONS_BY_EMAIL: send_confirm_email(user, email=user.username) message = language.REGISTRATION_SUCCESS.format(email=user.username) return {'message': message} else: return {'message': 'You may now log in.'}
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, }
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, }
def test_validate_recaptcha_empty_response(self, req_post): # ensure None short circuits execution (no call to google) assert_false(validate_recaptcha(None))
def test_validate_recaptcha_invalid_req_failure(self, req_post): resp = mock.Mock() resp.status_code = http.BAD_REQUEST resp.json = mock.Mock(return_value={'success': True}) req_post.return_value = resp assert_false(validate_recaptcha(None))
def test_validate_recaptcha_success(self, req_post): resp = mock.Mock() resp.status_code = http.OK resp.json = mock.Mock(return_value={'success': True}) req_post.return_value = resp assert_true(validate_recaptcha('a valid captcha'))
def test_validate_recaptcha_empty_response(self, req_post): req_post.side_effect=AssertionError() # ensure None short circuits execution (no call to google) assert_false(validate_recaptcha(None))
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, }
def test_validate_recaptcha_valid_req_failure(self, req_post): resp = mock.Mock() resp.status_code = http_status.HTTP_200_OK resp.json = mock.Mock(return_value={'success': False}) req_post.return_value = resp assert_false(validate_recaptcha(None))