def do_password_change(request): localizer = request.localizer token = request.matchdict.get('ticket') (verified, user_id) = verify_password_change_token(token, 24) if not verified: if not user_id: raise HTTPBadRequest(localizer.translate(_( "Wrong password token."))) else: return HTTPFound(location=maybe_contextual_route( request, 'password_change_sent', profile_id=user_id, _query=dict( sent=True, error=localizer.translate(_( "This token is expired. " "Do you want us to send another?"))))) user = User.get(user_id) headers = remember(request, user_id) request.response.headerlist.extend(headers) user.last_login = datetime.utcnow() slug = request.matchdict.get('discussion_slug', None) slug_prefix = "/" + slug if slug else "" return dict( get_default_context(request), slug_prefix=slug_prefix, title=localizer.translate(_('Change your password')))
def do_password_change(request): localizer = request.localizer token = request.matchdict.get('ticket') (verified, user_id) = verify_password_change_token(token, 24) if not verified: if not user_id: raise HTTPBadRequest( localizer.translate(_("Wrong password token."))) else: return HTTPFound(location=maybe_contextual_route( request, 'password_change_sent', profile_id=user_id, _query=dict(sent=True, error=localizer.translate( _("This token is expired. " "Do you want us to send another?"))))) user = User.get(user_id) headers = remember(request, user_id) request.response.headerlist.extend(headers) user.last_login = datetime.utcnow() slug = request.matchdict.get('discussion_slug', None) slug_prefix = "/" + slug if slug else "" return dict(get_default_context(request), slug_prefix=slug_prefix, title=localizer.translate(_('Change your password')))
def do_password_change(request): token = request.json_body.get('token') or '' password = request.json_body.get('password') or '' # TODO: Check password quality! localizer = request.localizer user, validity = verify_password_change_token(token) token_date = get_data_token_time(token) old_token = ( user is None or token_date is None or ( user.last_login and token_date < user.last_login)) if (validity != Validity.VALID or old_token): # V-, V+P+W-B-L-: Invalid or obsolete token (obsolete+logged in treated later.) # Offer to send a new token if validity != Validity.VALID: error = localizer.translate(_( "This link is not valid. Do you want us to send another?")) else: error = localizer.translate(_( "This link has been used. Do you want us to send another?")) raise JSONError(error, validity) user.password_p = password user.last_login = datetime.utcnow() headers = remember(request, user.id) request.response.headerlist.extend(headers) return HTTPOk()
def do_password_change(request): token = request.json_body.get('token') or '' password1 = request.json_body.get('password1', '').strip() password2 = request.json_body.get('password2', '').strip() localizer = request.localizer if password1 is '' or password2 is '' or password2 != password1: error = localizer.translate( _("The passwords that were entered are mismatched!")) raise JSONError(error, ErrorTypes.PASSWORD) # TODO: Check password quality! user, validity = verify_password_change_token(token) token_date = get_data_token_time(token) old_token = (user is None or token_date is None or (user.last_login and token_date < user.last_login)) if (validity != Validity.VALID or old_token): # V-, V+P+W-B-L-: Invalid or obsolete token (obsolete+logged in treated later.) # Offer to send a new token if validity != Validity.VALID: error = localizer.translate( _("This link is not valid. Do you want us to send another?")) else: error = localizer.translate( _("This link has been used. Do you want us to send another?")) raise JSONError(error, validity) user.password_p = password1 user.successful_login() headers = remember(request, user.id) request.response.headerlist.extend(headers) return HTTPOk()
def finish_password_change(request): localizer = request.localizer token = request.params.get('token') title = request.params.get('title') welcome = asbool(request.params.get('welcome')) discussion = discussion_from_request(request) if welcome: title = localizer.translate( _('Welcome to {discussion_topic}.')).format( discussion_topic=discussion.topic if discussion else "Assembl") else: title = localizer.translate(_('Change your password')) user, validity = verify_password_change_token(token) logged_in = request.authenticated_userid # if mismatch? if user and user.id != logged_in: # token for someone else: forget login. logged_in = None forget(request) token_date = get_data_token_time(token) old_token = (user is None or token_date is None or (user.last_login and token_date < user.last_login)) if (validity != Validity.VALID or old_token) and not logged_in: # V-, V+P+W-B-L-: Invalid or obsolete token (obsolete+logged in treated later.) # Offer to send a new token if validity != Validity.VALID: error = localizer.translate( _("This link is not valid. Do you want us to send another?")) else: error = localizer.translate( _("This link has been used. Do you want us to send another?")) request.session.flash(error) return HTTPFound(location=maybe_contextual_route( request, 'request_password_change', _query=dict(user_id=user.id if user else ''))) error = None p1, p2 = (request.params.get('password1', '').strip(), request.params.get('password2', '').strip()) if p1 != p2: error = localizer.translate(_('The passwords are not identical')) elif p1: user.password_p = p1 user.successful_login() headers = remember(request, user.id) request.response.headerlist.extend(headers) if discussion: maybe_auto_subscribe(user, discussion) request.session.flash(localizer.translate(_("Password changed")), 'message') return HTTPFound(location=request.route_url( 'home' if discussion else 'discussion_list', discussion_slug=discussion.slug)) return dict(get_default_context(request), title=title, token=token, error=error)
def do_password_change(request): token = request.json_body.get('token') or '' password1 = request.json_body.get('password1', '').strip() password2 = request.json_body.get('password2', '').strip() localizer = request.localizer if password1 is '' or password2 is '' or password2 != password1: error = localizer.translate( _("The passwords that were entered are mismatched!")) raise JSONError(error, ErrorTypes.PASSWORD) # TODO: Check password quality! user, validity = verify_password_change_token(token) token_date = get_data_token_time(token) old_token = ( user is None or token_date is None or ( user.last_login and token_date < user.last_login)) if (validity != Validity.VALID or old_token): # V-, V+P+W-B-L-: Invalid or obsolete token (obsolete+logged in treated later.) # Offer to send a new token if validity != Validity.VALID: error = localizer.translate(_( "This link is not valid. Do you want us to send another?")) else: error = localizer.translate(_( "This link has been used. Do you want us to send another?")) raise JSONError(error, validity) user.password_p = password1 user.successful_login() headers = remember(request, user.id) request.response.headerlist.extend(headers) return HTTPOk()
def finish_password_change(request): localizer = request.localizer token = request.params.get('token') title = request.params.get('title') welcome = asbool(request.params.get('welcome')) discussion = discussion_from_request(request) if welcome: title = localizer.translate(_( 'Welcome to {discussion_topic}.')).format( discussion_topic=discussion.topic if discussion else "Assembl") else: title = localizer.translate(_('Change your password')) user, validity = verify_password_change_token(token) logged_in = request.authenticated_userid # if mismatch? if user and user.id != logged_in: # token for someone else: forget login. logged_in = None forget(request) token_date = get_data_token_time(token) old_token = ( user is None or token_date is None or ( user.last_login and token_date < user.last_login)) if (validity != Validity.VALID or old_token) and not logged_in: # V-, V+P+W-B-L-: Invalid or obsolete token (obsolete+logged in treated later.) # Offer to send a new token if validity != Validity.VALID: error = localizer.translate(_( "This link is not valid. Do you want us to send another?")) else: error = localizer.translate(_( "This link has been used. Do you want us to send another?")) request.session.flash(error) return HTTPFound(location=maybe_contextual_route( request, 'request_password_change', _query=dict( user_id=user.id if user else ''))) error = None p1, p2 = (request.params.get('password1', '').strip(), request.params.get('password2', '').strip()) if p1 != p2: error = localizer.translate(_('The passwords are not identical')) elif p1: user.password_p = p1 user.successful_login() headers = remember(request, user.id) request.response.headerlist.extend(headers) if discussion: maybe_auto_subscribe(user, discussion) request.session.flash(localizer.translate(_( "Password changed")), 'message') return HTTPFound(location=request.route_url( 'home' if discussion else 'discussion_list', discussion_slug=discussion.slug)) return dict( get_default_context(request), title=title, token=token, error=error)
def setup_change_password(user, password): old_password = user.password token = password_change_token(user) password_change_payload = {"token": token, "password1": password, "password2": password} user, validity = verify_password_change_token(token) assert validity == Validity.VALID return old_password, password_change_payload
def finish_password_change(request): localizer = request.localizer token = request.params.get('token') title = request.params.get('title') user, validity = verify_password_change_token(token) logged_in = authenticated_userid(request) # if mismatch? if user and user.id != logged_in: # token for someone else: forget login. logged_in = None forget(request) token_date = get_data_token_time(token) old_token = ( user is None or token_date is None or ( user.last_login and token_date < user.last_login)) if (validity != Validity.VALID or old_token) and not logged_in: # V-, V+P+W-B-L-: Invalid or obsolete token (obsolete+logged in treated later.) # Offer to send a new token if validity != Validity.VALID: error = localizer.translate(_( "This link is not valid. Do you want us to send another?")) else: error = localizer.translate(_( "This link has been used. Do you want us to send another?")) return HTTPFound(location=maybe_contextual_route( request, 'request_password_change', _query=dict( user_id=user.id if user else '', error=error))) discussion_slug = request.matchdict.get('discussion_slug', None) error = None p1, p2 = (request.params.get('password1', '').strip(), request.params.get('password2', '').strip()) if p1 != p2: error = localizer.translate(_('The passwords are not identical')) elif p1: user.password_p = p1 user.last_login = datetime.utcnow() headers = remember(request, user.id) request.response.headerlist.extend(headers) if discussion_slug: discussion = discussion_from_request(request) maybe_auto_subscribe(user, discussion) return HTTPFound(location=request.route_url( 'home' if discussion_slug else 'discussion_list', discussion_slug=discussion_slug, _query=dict( message=localizer.translate(_( "Password changed"))))) slug_prefix = "/" + discussion_slug if discussion_slug else "" return dict( get_default_context(request), title=title, slug_prefix=slug_prefix, token=token, error=error)
def finish_password_change(request): localizer = request.localizer token = request.params.get('token') title = request.params.get('title') user, validity = verify_password_change_token(token) logged_in = authenticated_userid(request) # if mismatch? if user and user.id != logged_in: # token for someone else: forget login. logged_in = None forget(request) token_date = get_data_token_time(token) old_token = ( user is None or token_date is None or ( user.last_login and token_date < user.last_login)) if (validity != Validity.VALID or old_token) and not logged_in: # V-, V+P+W-B-L-: Invalid or obsolete token (obsolete+logged in treated later.) # Offer to send a new token if validity != Validity.VALID: error = localizer.translate(_( "This link is not valid. Do you want us to send another?")) else: error = localizer.translate(_( "This link has been used. Do you want us to send another?")) return HTTPFound(location=maybe_contextual_route( request, 'request_password_change', _query=dict( user_id=user.id if user else '', error=error))) discussion_slug = request.matchdict.get('discussion_slug', None) error = None p1, p2 = (request.params.get('password1', '').strip(), request.params.get('password2', '').strip()) if p1 != p2: error = localizer.translate(_('The passwords are not identical')) elif p1: user.password_p = p1 user.last_login = datetime.utcnow() headers = remember(request, user.id) request.response.headerlist.extend(headers) if discussion_slug: discussion = discussion_from_request(request) maybe_auto_subscribe(user, discussion) return HTTPFound(location=request.route_url( 'home' if discussion_slug else 'discussion_list', discussion_slug=discussion_slug, _query=dict( message=localizer.translate(_( "Password changed"))))) slug_prefix = "/" + discussion_slug if discussion_slug else "" return dict( get_default_context(request), title=title, slug_prefix=slug_prefix, token=token, error=error)
def test_change_password_token(test_app, participant1_user): # Set up old_password = participant1_user.password token = password_change_token(participant1_user) my_json = {"token": token, "password1": "lolo", "password2": "lolo"} # Test token user, validity = verify_password_change_token(token) assert validity == Validity.VALID # Test API response = test_app.post_json('/data/AgentProfile/do_password_change', my_json) assert response.status_code == 200 assert old_password != participant1_user.password assert participant1_user.check_password("lolo") == True
def do_password_change(request): "Validate the change_password token, and react accordingly." # Codes below refer to those cases: # V. token Valid(+) or invalid(-)? (Possibly expired through internal date) # P. user has(+) a Password or not (-)? # W. Welcome(+) vs change password(-) # B. last login absent, or Before token created (+) vs last login after token created (-) # L. user is already Logged in(+) or not(-)? welcome = 'welcome' in request.matched_route.name localizer = request.localizer discussion = discussion_from_request(request) token = request.matchdict.get('token') user, validity = verify_password_change_token(token) logged_in = authenticated_userid(request) if user and user.id != logged_in: # token for someone else: forget login. logged_in = None forget(request) lacking_password = user is not None and user.password is None token_date = get_data_token_time(token) old_token = ( user is None or token_date is None or ( user.last_login and token_date < user.last_login)) print "pwc V%sP%sW%sB%sL%s" % tuple(map(lambda b: "-" if b else "+", ( validity != Validity.VALID, lacking_password, not welcome, old_token, logged_in is None))) if welcome and not lacking_password: # W+P+: welcome link sends onwards irrespective of token if logged_in: # L+: send onwards to discussion return HTTPFound(location=request.route_url( 'home' if discussion else 'discussion_list', discussion_slug=discussion.slug)) else: # L-: offer to login return HTTPFound(location=maybe_contextual_route( request, 'login', _query=dict( identifier=user.get_preferred_email() if user else None))) if (validity != Validity.VALID or old_token) and not logged_in: # V-, V+P+W-B-L-: Invalid or obsolete token (obsolete+logged in treated later.) # Offer to send a new token if validity != Validity.VALID: error = localizer.translate(_( "This link is not valid. Do you want us to send another?")) else: error = localizer.translate(_( "This link has been used. Do you want us to send another?")) request.session.flash(error) return HTTPFound(location=maybe_contextual_route( request, 'request_password_change', _query=dict( user_id=user.id if user else ''))) # V+: Valid token (encompasses P-B+, W-, B-L+); ALSO V-L+ # V+P-B- should not happen, but we'll treat it the same. # go through password change dialog. We'll complete login afterwards. if welcome: if discussion: request.session.flash(localizer.translate(_( "You will enter the discussion as <b>{name}</b>.") ).format(name=user.name), 'message') else: request.session.flash(localizer.translate(_( "You will enter Assembl as <b>{name}</b>.") ).format(name=user.name), 'message') request.session.flash(localizer.translate(_( "Please choose your password for security reasons.") ).format(name=user.name), 'message') return HTTPFound(location=maybe_contextual_route( request, 'react_do_password_change', _query=dict( token=token, welcome=welcome)))
def check_password_token(request): token = request.matchdict.get('token', None) user, validity = verify_password_change_token(token) if validity != Validity.VALID: raise HTTPBadRequest(validity.name) return {"user": user.uri()}
def do_password_change(request): "Validate the change_password token, and react accordingly." # Codes below refer to those cases: # V. token Valid(+) or invalid(-)? (Possibly expired through internal date) # P. user has(+) a Password or not (-)? # W. Welcome(+) vs change password(-) # B. last login absent, or Before token created (+) vs last login after token created (-) # L. user is already Logged in(+) or not(-)? welcome = 'welcome' in request.matched_route.name localizer = request.localizer discussion = discussion_from_request(request) token = request.matchdict.get('ticket') user, validity = verify_password_change_token(token) logged_in = authenticated_userid(request) if user and user.id != logged_in: # token for someone else: forget login. logged_in = None forget(request) lacking_password = user is not None and user.password is None token_date = get_data_token_time(token) old_token = ( user is None or token_date is None or ( user.last_login and token_date < user.last_login)) print "pwc V%sP%sW%sB%sL%s" % tuple(map(lambda b: "-" if b else "+", ( validity != Validity.VALID, lacking_password, not welcome, old_token, logged_in is None))) if welcome and not lacking_password: # W+P+: welcome link sends onwards irrespective of token if logged_in: # L+: send onwards to discussion return HTTPFound(location=request.route_url( 'home' if discussion else 'discussion_list', discussion_slug=discussion.slug)) else: # L-: offer to login return HTTPFound(location=maybe_contextual_route( request, 'login', _query=dict( identifier=user.get_preferred_email() if user else None))) if (validity != Validity.VALID or old_token) and not logged_in: # V-, V+P+W-B-L-: Invalid or obsolete token (obsolete+logged in treated later.) # Offer to send a new token if validity != Validity.VALID: error = localizer.translate(_( "This link is not valid. Do you want us to send another?")) else: error = localizer.translate(_( "This link has been used. Do you want us to send another?")) return HTTPFound(location=maybe_contextual_route( request, 'request_password_change', _query=dict( user_id=user.id if user else '', error=error))) # V+: Valid token (encompasses P-B+, W-, B-L+); ALSO V-L+ # V+P-B- should not happen, but we'll treat it the same. # go through password change dialog. We'll complete login afterwards. slug = discussion.slug if discussion else "" slug_prefix = "/" + slug if slug else "" if welcome: if discussion: discussion_topic = discussion.topic welcome_text = localizer.translate(_( "You will enter the discussion as <b>{name}</b>.")).format(name=user.name) else: discussion_topic = "Assembl" welcome_text = localizer.translate(_( "You will enter Assembl as <b>{name}</b>.")) welcome_text += "</p><p>" + localizer.translate(_( "Please choose your password for security reasons.")) title = localizer.translate(_('Welcome to {discussion_topic}.')).format( discussion_topic=discussion_topic) else: title = localizer.translate(_('Change your password')) welcome_text = "" return dict( get_default_context(request), slug_prefix=slug_prefix, description=welcome_text, token=token, title=title)
def check_password_token(request): token = request.matchdict.get('token', None) user, validity = verify_password_change_token(token) if validity != Validity.VALID: raise HTTPBadRequest(validity.name) return {"user": user.uri()}