Beispiel #1
0
def verify_phone(phoneclaim):
    if phoneclaim.verification_expired:
        flash(_("You provided an incorrect verification code too many times"), 'danger')
        # Block attempts to verify this number, but also keep the claim so that a new
        # claim cannot be made. A periodic sweep to delete old claims is needed.
        return render_redirect(url_for('.account'), code=303)

    form = VerifyPhoneForm()
    form.phoneclaim = phoneclaim
    if form.validate_on_submit():
        if UserPhone.get(phoneclaim.phone) is None:
            if not current_auth.user.phones:
                primary = True
            else:
                primary = False
            userphone = UserPhone(user=current_auth.user, phone=phoneclaim.phone, gets_text=True)
            userphone.primary = primary
            db.session.add(userphone)
            db.session.delete(phoneclaim)
            db.session.commit()
            flash(_("Your phone number has been verified"), 'success')
            user_data_changed.send(current_auth.user, changes=['phone'])
            return render_redirect(url_for('.account'), code=303)
        else:
            db.session.delete(phoneclaim)
            db.session.commit()
            flash(_("This phone number has already been claimed by another user"), 'danger')
    elif request.method == 'POST':
        phoneclaim.verification_attempts += 1
        db.session.commit()
    return render_form(form=form, title=_("Verify phone number"), formid='phone_verify',
        submit=_("Verify"), ajax=True)
Beispiel #2
0
def remove_phone(number):
    userphone = UserPhone.get(phone=number)
    if userphone is None or userphone.user != current_auth.user:
        userphone = UserPhoneClaim.get_for(user=current_auth.user,
                                           phone=number)
        if not userphone:
            abort(404)
        if userphone.verification_expired:
            flash(
                _("This number has been blocked due to too many failed verification attempts"
                  ),
                'danger',
            )
            # Block attempts to delete this number if verification failed.
            # It needs to be deleted in a background sweep.
            return render_redirect(url_for('.account'), code=303)

    if request.method == 'POST':
        # FIXME: Confirm validation success
        user_data_changed.send(current_auth.user, changes=['phone-delete'])
    return render_delete_sqla(
        userphone,
        db,
        title=_("Confirm removal"),
        message=_("Remove phone number {phone} from your account?").format(
            phone=userphone.phone),
        success=_("You have removed your number {phone}").format(
            phone=userphone.phone),
        next=url_for('.account'),
        delete_text=_("Remove"),
    )
Beispiel #3
0
def verify_phone(phoneclaim):
    form = VerifyPhoneForm()
    form.phoneclaim = phoneclaim
    if form.validate_on_submit():
        if UserPhone.get(phoneclaim.phone) is None:
            if not g.user.phones:
                primary = True
            else:
                primary = False
            userphone = UserPhone(user=g.user,
                                  phone=phoneclaim.phone,
                                  gets_text=True)
            userphone.primary = primary
            db.session.add(userphone)
            db.session.delete(phoneclaim)
            db.session.commit()
            flash(_("Your phone number has been verified"), 'success')
            user_data_changed.send(g.user, changes=['phone'])
            return render_redirect(url_for('.profile'), code=303)
        else:
            db.session.delete(phoneclaim)
            db.session.commit()
            flash(
                _("This phone number has already been claimed by another user"
                  ), 'danger')
    return render_form(form=form,
                       title=_("Verify phone number"),
                       formid='phone_verify',
                       submit=_("Verify"),
                       ajax=True)
Beispiel #4
0
def add_phone():
    form = NewPhoneForm()
    if form.validate_on_submit():
        userphone = UserPhoneClaim.get(user=g.user, phone=form.phone.data)
        if userphone is None:
            userphone = UserPhoneClaim(user=g.user,
                                       phone=form.phone.data,
                                       type=form.type.data)
            db.session.add(userphone)
        try:
            send_phone_verify_code(userphone)
            db.session.commit(
            )  # Commit after sending because send_phone_verify_code saves the message sent
            flash(_("We sent a verification code to your phone number"),
                  'success')
            user_data_changed.send(g.user, changes=['phone-claim'])
            return render_redirect(url_for('.verify_phone',
                                           number=userphone.phone),
                                   code=303)
        except ValueError as e:
            db.session.rollback()
            form.phone.errors.append(unicode(e))
    return render_form(form=form,
                       title=_("Add a phone number"),
                       formid='phone_add',
                       submit=_("Add phone"),
                       ajax=True)
Beispiel #5
0
def account_merge():
    if 'merge_buid' not in session:
        return redirect(get_next_url(), code=302)
    other_user = User.get(buid=session['merge_buid'])
    if other_user is None:
        session.pop('merge_buid', None)
        return redirect(get_next_url(), code=302)
    form = ProfileMergeForm()
    if form.validate_on_submit():
        if 'merge' in request.form:
            new_user = merge_users(current_auth.user, other_user)
            login_internal(new_user)
            flash(_("Your accounts have been merged"), 'success')
            session.pop('merge_buid', None)
            db.session.commit()
            user_data_changed.send(new_user, changes=['merge'])
            return redirect(get_next_url(), code=303)
        else:
            session.pop('merge_buid', None)
            return redirect(get_next_url(), code=303)
    return render_template(
        'merge.html.jinja2',
        form=form,
        user=current_auth.user,
        other_user=other_user,
        login_registry=login_registry,
    )
Beispiel #6
0
def confirm_email(md5sum, secret):
    emailclaim = UserEmailClaim.query.filter_by(
        md5sum=md5sum, verification_code=secret).first()
    if emailclaim is not None:
        if 'verify' in emailclaim.permissions(g.user):
            existing = UserEmail.query.filter(
                UserEmail.email.in_(
                    [emailclaim.email,
                     emailclaim.email.lower()])).first()
            if existing is not None:
                claimed_email = emailclaim.email
                claimed_user = emailclaim.user
                db.session.delete(emailclaim)
                db.session.commit()
                if claimed_user != g.user:
                    return render_message(
                        title="Email address already claimed",
                        message=Markup(
                            "The email address <code>%s</code> has already been verified by another user."
                            % escape(claimed_email)))
                else:
                    return render_message(
                        title="Email address already verified",
                        message=Markup(
                            "Hello %s! Your email address <code>%s</code> has already been verified."
                            % (escape(claimed_user.fullname),
                               escape(claimed_email))))

            useremail = emailclaim.user.add_email(
                emailclaim.email.lower(),
                primary=emailclaim.user.email is None)
            db.session.delete(emailclaim)
            for claim in UserEmailClaim.query.filter(
                    UserEmailClaim.email.in_(
                        [useremail.email,
                         useremail.email.lower()])).all():
                db.session.delete(claim)
            db.session.commit()
            user_data_changed.send(g.user, changes=['email'])
            return render_message(
                title="Email address verified",
                message=Markup(
                    "Hello %s! Your email address <code>%s</code> has now been verified."
                    % (escape(emailclaim.user.fullname), escape(
                        useremail.email))))
        else:
            return render_message(
                title="That was not for you",
                message=
                u"You’ve opened an email verification link that was meant for another user. "
                u"If you are managing multiple accounts, please login with the correct account "
                u"and open the link again.",
                code=403)
    else:
        return render_message(
            title="Expired confirmation link",
            message=
            "The confirmation link you clicked on is either invalid or has expired.",
            code=404)
Beispiel #7
0
def remove_phone(number):
    userphone = UserPhone.query.filter_by(phone=number, user=g.user).first()
    if userphone is None:
        userphone = UserPhoneClaim.query.filter_by(phone=number, user=g.user).first_or_404()
    if request.method == 'POST':
        user_data_changed.send(g.user, changes=['phone-delete'])
    return render_delete_sqla(userphone, db, title="Confirm removal", message="Remove phone number %s?" % userphone,
        success="You have removed your number %s." % userphone,
        next=url_for('.profile'))
Beispiel #8
0
def account_edit(newprofile=False):
    form = ProfileForm(obj=current_auth.user)
    form.edit_user = current_auth.user
    form.fullname.description = current_app.config.get('FULLNAME_REASON')
    form.email.description = current_app.config.get('EMAIL_REASON')
    form.username.description = current_app.config.get('USERNAME_REASON')
    form.timezone.description = current_app.config.get('TIMEZONE_REASON')
    if current_auth.user.email or newprofile is False:
        del form.email

    if form.validate_on_submit():
        # Can't auto-populate here because user.email is read-only
        current_auth.user.fullname = form.fullname.data
        current_auth.user.username = form.username.data
        current_auth.user.timezone = form.timezone.data

        if newprofile and not current_auth.user.email:
            useremail = UserEmailClaim.get(user=current_auth.user,
                                           email=form.email.data)
            if useremail is None:
                useremail = UserEmailClaim(user=current_auth.user,
                                           email=form.email.data)
                db.session.add(useremail)
            send_email_verify_link(useremail)
            db.session.commit()
            user_data_changed.send(current_auth.user,
                                   changes=['profile', 'email-claim'])
            flash(_(
                "Your profile has been updated. We sent you an email to confirm your address"
            ),
                  category='success')
        else:
            db.session.commit()
            user_data_changed.send(current_auth.user, changes=['profile'])
            flash(_("Your profile has been updated"), category='success')

        if newprofile:
            return render_redirect(get_next_url(), code=303)
        else:
            return render_redirect(url_for('account'), code=303)
    if newprofile:
        return render_form(
            form,
            title=_("Update profile"),
            formid='account_new',
            submit=_("Continue"),
            message=Markup(
                _(u"Hello, <strong>{fullname}</strong>. Please spare a minute to fill out your profile"
                  ).format(fullname=escape(current_auth.user.fullname))),
            ajax=True)
    else:
        return render_form(form,
                           title=_("Edit profile"),
                           formid='account_edit',
                           submit=_("Save changes"),
                           ajax=True)
Beispiel #9
0
def confirm_email(md5sum, secret):
    emailclaim = UserEmailClaim.query.filter_by(md5sum=md5sum, verification_code=secret).first()
    if emailclaim is not None:
        if "verify" in emailclaim.permissions(g.user):
            existing = UserEmail.query.filter(UserEmail.email.in_([emailclaim.email, emailclaim.email.lower()])).first()
            if existing is not None:
                claimed_email = emailclaim.email
                claimed_user = emailclaim.user
                db.session.delete(emailclaim)
                db.session.commit()
                if claimed_user != g.user:
                    return render_message(
                        title="Email address already claimed",
                        message=Markup(
                            "The email address <code>%s</code> has already been verified by another user."
                            % escape(claimed_email)
                        ),
                    )
                else:
                    return render_message(
                        title="Email address already verified",
                        message=Markup(
                            "Hello %s! Your email address <code>%s</code> has already been verified."
                            % (escape(claimed_user.fullname), escape(claimed_email))
                        ),
                    )

            useremail = emailclaim.user.add_email(emailclaim.email.lower(), primary=emailclaim.user.email is None)
            db.session.delete(emailclaim)
            for claim in UserEmailClaim.query.filter(
                UserEmailClaim.email.in_([useremail.email, useremail.email.lower()])
            ).all():
                db.session.delete(claim)
            db.session.commit()
            user_data_changed.send(g.user, changes=["email"])
            return render_message(
                title="Email address verified",
                message=Markup(
                    "Hello %s! Your email address <code>%s</code> has now been verified."
                    % (escape(emailclaim.user.fullname), escape(useremail.email))
                ),
            )
        else:
            return render_message(
                title="That was not for you",
                message=u"You’ve opened an email verification link that was meant for another user. "
                u"If you are managing multiple accounts, please login with the correct account "
                u"and open the link again.",
                code=403,
            )
    else:
        return render_message(
            title="Expired confirmation link",
            message="The confirmation link you clicked on is either invalid or has expired.",
            code=404,
        )
Beispiel #10
0
def add_email():
    form = NewEmailAddressForm()
    if form.validate_on_submit():
        useremail = UserEmailClaim(user=g.user, email=form.email.data)
        db.session.add(useremail)
        db.session.commit()
        send_email_verify_link(useremail)
        flash("We sent you an email to confirm your address.", 'success')
        user_data_changed.send(g.user, changes=['email-claim'])
        return render_redirect(url_for('.profile'), code=303)
    return render_form(form=form, title="Add an email address", formid="email_add", submit="Add email", ajax=True)
Beispiel #11
0
def add_phone():
    form = NewPhoneForm()
    if form.validate_on_submit():
        userphone = UserPhoneClaim(user=g.user, phone=form.phone.data)
        db.session.add(userphone)
        send_phone_verify_code(userphone)
        db.session.commit()
        flash("We sent a verification code to your phone number.", 'success')
        user_data_changed.send(g.user, changes=['phone-claim'])
        return render_redirect(url_for('.verify_phone', number=userphone.phone), code=303)
    return render_form(form=form, title="Add a phone number", formid="phone_add", submit="Add phone", ajax=True)
Beispiel #12
0
def remove_email(md5sum):
    useremail = UserEmail.query.filter_by(md5sum=md5sum, user=g.user).first()
    if not useremail:
        useremail = UserEmailClaim.query.filter_by(md5sum=md5sum, user=g.user).first_or_404()
    if isinstance(useremail, UserEmail) and useremail.primary:
        flash("You cannot remove your primary email address", "error")
        return render_redirect(url_for('.profile'), code=303)
    if request.method == 'POST':
        user_data_changed.send(g.user, changes=['email-delete'])
    return render_delete_sqla(useremail, db, title="Confirm removal", message="Remove email address %s?" % useremail,
        success="You have removed your email address %s." % useremail,
        next=url_for('.profile'))
Beispiel #13
0
def remove_phone(number):
    userphone = UserPhone.query.filter_by(phone=number, user=g.user).first()
    if userphone is None:
        userphone = UserPhoneClaim.query.filter_by(phone=number, user=g.user).first_or_404()
    if request.method == 'POST':
        # FIXME: Confirm validation success
        user_data_changed.send(g.user, changes=['phone-delete'])
    return render_delete_sqla(userphone, db, title=_(u"Confirm removal"),
        message=_(u"Remove phone number {phone}?").format(
            phone=userphone.phone),
        success=_(u"You have removed your number {phone}").format(phone=userphone.phone),
        next=url_for('.profile'))
Beispiel #14
0
def profile_edit(newprofile=False):
    form = ProfileForm(obj=g.user)
    form.fullname.description = current_app.config.get('FULLNAME_REASON')
    form.email.description = current_app.config.get('EMAIL_REASON')
    form.username.description = current_app.config.get('USERNAME_REASON')
    form.description.description = current_app.config.get('BIO_REASON')
    form.timezone.description = current_app.config.get('TIMEZONE_REASON')
    if g.user.email or newprofile is False:
        del form.email

    if form.validate_on_submit():
        # Can't auto-populate here because user.email is read-only
        g.user.fullname = form.fullname.data
        g.user.username = form.username.data
        g.user.description = form.description.data
        g.user.timezone = form.timezone.data

        if newprofile and not g.user.email:
            useremail = UserEmailClaim(user=g.user, email=form.email.data)
            db.session.add(useremail)
            send_email_verify_link(useremail)
            db.session.commit()
            user_data_changed.send(g.user, changes=['profile', 'email-claim'])
            flash(
                "Your profile has been updated. We sent you an email to confirm your address",
                category='success')
        else:
            db.session.commit()
            user_data_changed.send(g.user, changes=['profile'])
            flash("Your profile has been updated.", category='success')

        if newprofile:
            return render_redirect(get_next_url(), code=303)
        else:
            return render_redirect(url_for('profile'), code=303)
    if newprofile:
        return render_form(
            form,
            title="Update profile",
            formid="profile_new",
            submit="Continue",
            message=
            u"Hello, %s. Please spare a minute to fill out your profile." %
            g.user.fullname,
            ajax=True)
    else:
        return render_form(form,
                           title="Edit profile",
                           formid="profile_edit",
                           submit="Save changes",
                           ajax=True)
Beispiel #15
0
def add_email():
    form = NewEmailAddressForm()
    if form.validate_on_submit():
        useremail = UserEmailClaim.get(user=current_auth.user, email=form.email.data)
        if useremail is None:
            useremail = UserEmailClaim(user=current_auth.user, email=form.email.data, type=form.type.data)
            db.session.add(useremail)
            db.session.commit()
        send_email_verify_link(useremail)
        flash(_("We sent you an email to confirm your address"), 'success')
        user_data_changed.send(current_auth.user, changes=['email-claim'])
        return render_redirect(url_for('.account'), code=303)
    return render_form(form=form, title=_("Add an email address"), formid='email_add',
        submit=_("Add email"), ajax=True)
Beispiel #16
0
def remove_phone(number):
    userphone = UserPhone.query.filter_by(phone=number, user=g.user).first()
    if userphone is None:
        userphone = UserPhoneClaim.query.filter_by(phone=number,
                                                   user=g.user).first_or_404()
    if request.method == 'POST':
        user_data_changed.send(g.user, changes=['phone-delete'])
    return render_delete_sqla(userphone,
                              db,
                              title="Confirm removal",
                              message="Remove phone number %s?" % userphone,
                              success="You have removed your number %s." %
                              userphone,
                              next=url_for('.profile'))
Beispiel #17
0
def remove_email(md5sum):
    useremail = UserEmail.query.filter_by(md5sum=md5sum, user=current_auth.user).first()
    if not useremail:
        useremail = UserEmailClaim.query.filter_by(md5sum=md5sum, user=current_auth.user).first_or_404()
    if isinstance(useremail, UserEmail) and useremail.primary:
        flash(_("You cannot remove your primary email address"), 'danger')
        return render_redirect(url_for('.account'), code=303)
    if request.method == 'POST':
        # FIXME: Confirm validation success
        user_data_changed.send(current_auth.user, changes=['email-delete'])
    return render_delete_sqla(useremail, db, title=_(u"Confirm removal"),
        message=_(u"Remove email address {email} from your account?").format(email=useremail.email),
        success=_(u"You have removed your email address {email}").format(email=useremail.email),
        next=url_for('.account'),
        delete_text=_(u"Remove"))
Beispiel #18
0
def add_email():
    form = NewEmailAddressForm()
    if form.validate_on_submit():
        useremail = UserEmailClaim(user=g.user, email=form.email.data)
        db.session.add(useremail)
        db.session.commit()
        send_email_verify_link(useremail)
        flash("We sent you an email to confirm your address.", 'success')
        user_data_changed.send(g.user, changes=['email-claim'])
        return render_redirect(url_for('.profile'), code=303)
    return render_form(form=form,
                       title="Add an email address",
                       formid="email_add",
                       submit="Add email",
                       ajax=True)
Beispiel #19
0
def profile_edit(newprofile=False):
    form = ProfileForm(obj=g.user)
    form.fullname.description = current_app.config.get("FULLNAME_REASON")
    form.email.description = current_app.config.get("EMAIL_REASON")
    form.username.description = current_app.config.get("USERNAME_REASON")
    form.description.description = current_app.config.get("BIO_REASON")
    form.timezone.description = current_app.config.get("TIMEZONE_REASON")
    if g.user.email or newprofile is False:
        del form.email

    if newprofile is True:
        del form.description

    if form.validate_on_submit():
        # Can't auto-populate here because user.email is read-only
        g.user.fullname = form.fullname.data
        g.user.username = form.username.data
        if not newprofile:
            g.user.description = form.description.data
        g.user.timezone = form.timezone.data

        if newprofile and not g.user.email:
            useremail = UserEmailClaim(user=g.user, email=form.email.data)
            db.session.add(useremail)
            send_email_verify_link(useremail)
            db.session.commit()
            user_data_changed.send(g.user, changes=["profile", "email-claim"])
            flash("Your profile has been updated. We sent you an email to confirm your address", category="success")
        else:
            db.session.commit()
            user_data_changed.send(g.user, changes=["profile"])
            flash("Your profile has been updated.", category="success")

        if newprofile:
            return render_redirect(get_next_url(), code=303)
        else:
            return render_redirect(url_for("profile"), code=303)
    if newprofile:
        return render_form(
            form,
            title="Update profile",
            formid="profile_new",
            submit="Continue",
            message=u"Hello, %s. Please spare a minute to fill out your profile." % g.user.fullname,
            ajax=True,
        )
    else:
        return render_form(form, title="Edit profile", formid="profile_edit", submit="Save changes", ajax=True)
Beispiel #20
0
def verify_phone(phoneclaim):
    form = VerifyPhoneForm()
    form.phoneclaim = phoneclaim
    if form.validate_on_submit():
        if not g.user.phones:
            primary = True
        else:
            primary = False
        userphone = UserPhone(user=g.user, phone=phoneclaim.phone, gets_text=True, primary=primary)
        db.session.add(userphone)
        db.session.delete(phoneclaim)
        db.session.commit()
        flash("Your phone number has been verified.", 'success')
        user_data_changed.send(g.user, 'phone')
        return render_redirect(url_for('.profile'), code=303)
    return render_form(form=form, title="Verify phone number", formid="phone_verify", submit="Verify", ajax=True)
Beispiel #21
0
def profile_edit(newprofile=False):
    form = ProfileForm(obj=g.user)
    form.edit_user = g.user
    form.fullname.description = current_app.config.get('FULLNAME_REASON')
    form.email.description = current_app.config.get('EMAIL_REASON')
    form.username.description = current_app.config.get('USERNAME_REASON')
    form.description.description = current_app.config.get('BIO_REASON')
    form.timezone.description = current_app.config.get('TIMEZONE_REASON')
    if g.user.email or newprofile is False:
        del form.email

    if newprofile is True:
        del form.description

    if form.validate_on_submit():
        # Can't auto-populate here because user.email is read-only
        g.user.fullname = form.fullname.data
        g.user.username = form.username.data
        if not newprofile:
            g.user.description = form.description.data
        g.user.timezone = form.timezone.data

        if newprofile and not g.user.email:
            useremail = UserEmailClaim.get(user=g.user, email=form.email.data)
            if useremail is None:
                useremail = UserEmailClaim(user=g.user, email=form.email.data)
                db.session.add(useremail)
            send_email_verify_link(useremail)
            db.session.commit()
            user_data_changed.send(g.user, changes=['profile', 'email-claim'])
            flash("Your profile has been updated. We sent you an email to confirm your address", category='success')
        else:
            db.session.commit()
            user_data_changed.send(g.user, changes=['profile'])
            flash("Your profile has been updated.", category='success')

        if newprofile:
            return render_redirect(get_next_url(), code=303)
        else:
            return render_redirect(url_for('profile'), code=303)
    if newprofile:
        return render_form(form, title="Update profile", formid="profile_new", submit="Continue",
            message=Markup(u"Hello, <strong>{fullname}</strong>. Please spare a minute to fill out your profile.".format(
                fullname=escape(g.user.fullname))),
            ajax=True)
    else:
        return render_form(form, title="Edit profile", formid="profile_edit", submit="Save changes", ajax=True)
Beispiel #22
0
def confirm_email(md5sum, secret):
    emailclaim = UserEmailClaim.query.filter_by(md5sum=md5sum, verification_code=secret).first()
    if emailclaim is not None:
        if 'verify' in emailclaim.permissions(current_auth.user):
            existing = UserEmail.query.filter(UserEmail.email.in_([emailclaim.email, emailclaim.email.lower()])).first()
            if existing is not None:
                claimed_email = emailclaim.email
                claimed_user = emailclaim.user
                db.session.delete(emailclaim)
                db.session.commit()
                if claimed_user != current_auth.user:
                    return render_message(title=_("Email address already claimed"),
                        message=Markup(
                            _(u"The email address <code>{email}</code> has already been verified by another user").format(
                                email=escape(claimed_email))))
                else:
                    return render_message(title=_("Email address already verified"),
                        message=Markup(_(u"Hello <strong>{fullname}</strong>! "
                            u"Your email address <code>{email}</code> has already been verified").format(
                                fullname=escape(claimed_user.fullname), email=escape(claimed_email))))

            useremail = emailclaim.user.add_email(emailclaim.email,
                primary=emailclaim.user.email is None,
                type=emailclaim.type,
                private=emailclaim.private)
            db.session.delete(emailclaim)
            for claim in UserEmailClaim.query.filter(
                    UserEmailClaim.email.in_([useremail.email, useremail.email.lower()])).all():
                db.session.delete(claim)
            db.session.commit()
            user_data_changed.send(current_auth.user, changes=['email'])
            return render_message(title=_("Email address verified"),
                message=Markup(_(u"Hello <strong>{fullname}</strong>! "
                    u"Your email address <code>{email}</code> has now been verified").format(
                        fullname=escape(emailclaim.user.fullname), email=escape(useremail.email))))
        else:
            return render_message(
                title=_("This was not for you"),
                message=_(u"You’ve opened an email verification link that was meant for another user. "
                        u"If you are managing multiple accounts, please login with the correct account "
                        u"and open the link again"),
                code=403)
    else:
        return render_message(
            title=_("Expired confirmation link"),
            message=_(u"The confirmation link you clicked on is either invalid or has expired"),
            code=404)
Beispiel #23
0
def make_email_primary():
    form = EmailPrimaryForm()
    if form.validate_on_submit():
        useremail = UserEmail.query.filter_by(email=form.email.data, user=current_auth.user).first()
        if useremail is not None and isinstance(useremail, UserEmail):
            if useremail.primary:
                flash(_("This is already your primary email address"), 'info')
            else:
                current_auth.user.primary_email = useremail
                db.session.commit()
                user_data_changed.send(current_auth.user, changes=['email-update-primary'])
                flash(_(u"Your primary email address has been updated"), 'success')
        else:
            flash(_("No such email address is linked to this user account"), 'danger')
    else:
            flash(_("Please select an email address"), 'danger')
    return render_redirect(url_for('.account'), code=303)
Beispiel #24
0
def remove_phone(number):
    userphone = UserPhone.query.filter_by(phone=number, user=g.user).first()
    if userphone is None:
        userphone = UserPhoneClaim.query.filter_by(phone=number,
                                                   user=g.user).first_or_404()
    if request.method == 'POST':
        # FIXME: Confirm validation success
        user_data_changed.send(g.user, changes=['phone-delete'])
    return render_delete_sqla(
        userphone,
        db,
        title=_(u"Confirm removal"),
        message=_(u"Remove phone number {phone}?").format(
            phone=userphone.phone),
        success=_(u"You have removed your number {phone}").format(
            phone=userphone.phone),
        next=url_for('.profile'))
Beispiel #25
0
def add_phone():
    form = NewPhoneForm()
    if form.validate_on_submit():
        userphone = UserPhoneClaim(user=g.user, phone=form.phone.data)
        db.session.add(userphone)
        send_phone_verify_code(userphone)
        db.session.commit()
        flash("We sent a verification code to your phone number.", 'success')
        user_data_changed.send(g.user, changes=['phone-claim'])
        return render_redirect(url_for('.verify_phone',
                                       number=userphone.phone),
                               code=303)
    return render_form(form=form,
                       title="Add a phone number",
                       formid="phone_add",
                       submit="Add phone",
                       ajax=True)
Beispiel #26
0
def make_phone_primary():
    form = PhonePrimaryForm()
    if form.validate_on_submit():
        userphone = UserPhone.query.filter_by(phone=form.phone.data, user=current_auth.user).first()
        if userphone is not None and isinstance(userphone, UserPhone):
            if userphone.primary:
                flash(_("This is already your primary phone number"), 'info')
            else:
                current_auth.user.primary_phone = userphone
                db.session.commit()
                user_data_changed.send(current_auth.user, changes=['phone-update-primary'])
                flash(_(u"Your primary phone number has been updated"), 'success')
        else:
            flash(_("No such phone number is linked to this user account"), 'danger')
    else:
            flash(_("Please select a phone number"), 'danger')
    return render_redirect(url_for('.account'), code=303)
Beispiel #27
0
def remove_email(md5sum):
    useremail = UserEmail.query.filter_by(md5sum=md5sum, user=g.user).first()
    if not useremail:
        useremail = UserEmailClaim.query.filter_by(md5sum=md5sum,
                                                   user=g.user).first_or_404()
    if isinstance(useremail, UserEmail) and useremail.primary:
        flash("You cannot remove your primary email address", "error")
        return render_redirect(url_for('.profile'), code=303)
    if request.method == 'POST':
        user_data_changed.send(g.user, changes=['email-delete'])
    return render_delete_sqla(
        useremail,
        db,
        title="Confirm removal",
        message="Remove email address %s?" % useremail,
        success="You have removed your email address %s." % useremail,
        next=url_for('.profile'))
Beispiel #28
0
def add_phone():
    form = NewPhoneForm()
    if form.validate_on_submit():
        userphone = UserPhoneClaim.get(user=current_auth.user, phone=form.phone.data)
        if userphone is None:
            userphone = UserPhoneClaim(user=current_auth.user, phone=form.phone.data)
            db.session.add(userphone)
        try:
            send_phone_verify_code(userphone)
            db.session.commit()  # Commit after sending because send_phone_verify_code saves the message sent
            flash(_("We sent a verification code to your phone number"), 'success')
            user_data_changed.send(current_auth.user, changes=['phone-claim'])
            return render_redirect(url_for('.verify_phone', number=userphone.phone), code=303)
        except ValueError as e:
            db.session.rollback()
            form.phone.errors.append(unicode(e))
    return render_form(form=form, title=_("Add a phone number"), formid='phone_add',
        submit=_("Verify phone"), ajax=True)
Beispiel #29
0
def verify_phone(phoneclaim):
    if phoneclaim.verification_expired:
        flash(_("You provided an incorrect verification code too many times"),
              'danger')
        # Block attempts to verify this number, but also keep the claim so that a new
        # claim cannot be made. A periodic sweep to delete old claims is needed.
        return render_redirect(url_for('.account'), code=303)

    form = VerifyPhoneForm()
    form.phoneclaim = phoneclaim
    if form.validate_on_submit():
        if UserPhone.get(phoneclaim.phone) is None:
            if not current_auth.user.phones:
                primary = True
            else:
                primary = False
            userphone = UserPhone(user=current_auth.user,
                                  phone=phoneclaim.phone,
                                  gets_text=True)
            userphone.primary = primary
            db.session.add(userphone)
            db.session.delete(phoneclaim)
            db.session.commit()
            flash(_("Your phone number has been verified"), 'success')
            user_data_changed.send(current_auth.user, changes=['phone'])
            return render_redirect(url_for('.account'), code=303)
        else:
            db.session.delete(phoneclaim)
            db.session.commit()
            flash(
                _("This phone number has already been claimed by another user"
                  ),
                'danger',
            )
    elif request.method == 'POST':
        phoneclaim.verification_attempts += 1
        db.session.commit()
    return render_form(
        form=form,
        title=_("Verify phone number"),
        formid='phone_verify',
        submit=_("Verify"),
        ajax=True,
    )
Beispiel #30
0
def remove_phone(number):
    userphone = UserPhone.query.filter_by(phone=number, user=current_auth.user).first()
    if userphone is None:
        userphone = UserPhoneClaim.query.filter_by(phone=number, user=current_auth.user).first_or_404()
        if userphone.verification_expired:
            flash(_("This number has been blocked due to too many failed verification attempts"), 'danger')
            # Block attempts to delete this number if verification failed.
            # It needs to be deleted in a background sweep.
            return render_redirect(url_for('.account'), code=303)

    if request.method == 'POST':
        # FIXME: Confirm validation success
        user_data_changed.send(current_auth.user, changes=['phone-delete'])
    return render_delete_sqla(userphone, db, title=_(u"Confirm removal"),
        message=_(u"Remove phone number {phone} from your account?").format(
            phone=userphone.phone),
        success=_(u"You have removed your number {phone}").format(phone=userphone.phone),
        next=url_for('.account'),
        delete_text=_(u"Remove"))
Beispiel #31
0
def profile_merge():
    if "merge_userid" not in session:
        return redirect(get_next_url(), code=302)
    other_user = User.query.filter_by(userid=session["merge_userid"]).first()
    if other_user is None:
        session.pop("merge_userid", None)
        return redirect(get_next_url(), code=302)
    form = ProfileMergeForm()
    if form.validate_on_submit():
        if "merge" in request.form:
            new_user = merge_users(g.user, other_user)
            login_internal(new_user)
            user_data_changed.send(new_user, changes=["merge"])
            flash("Your accounts have been merged.", "success")
            session.pop("merge_userid", None)
            return redirect(get_next_url(), code=303)
        else:
            session.pop("merge_userid", None)
            return redirect(get_next_url(), code=303)
    return render_template("merge.html", form=form, user=g.user, other_user=other_user, login_registry=login_registry)
Beispiel #32
0
def add_email():
    form = NewEmailAddressForm()
    if form.validate_on_submit():
        useremail = UserEmailClaim.get(user=current_auth.user,
                                       email=form.email.data)
        if useremail is None:
            useremail = UserEmailClaim(user=current_auth.user,
                                       email=form.email.data,
                                       type=form.type.data)
            db.session.add(useremail)
            db.session.commit()
        send_email_verify_link(useremail)
        flash(_("We sent you an email to confirm your address"), 'success')
        user_data_changed.send(current_auth.user, changes=['email-claim'])
        return render_redirect(url_for('.account'), code=303)
    return render_form(form=form,
                       title=_("Add an email address"),
                       formid='email_add',
                       submit=_("Add email"),
                       ajax=True)
Beispiel #33
0
def remove_email(md5sum):
    useremail = UserEmail.query.filter_by(md5sum=md5sum, user=g.user).first()
    if not useremail:
        useremail = UserEmailClaim.query.filter_by(md5sum=md5sum,
                                                   user=g.user).first_or_404()
    if isinstance(useremail, UserEmail) and useremail.primary:
        flash(_("You cannot remove your primary email address"), 'error')
        return render_redirect(url_for('.profile'), code=303)
    if request.method == 'POST':
        # FIXME: Confirm validation success
        user_data_changed.send(g.user, changes=['email-delete'])
    return render_delete_sqla(
        useremail,
        db,
        title=_(u"Confirm removal"),
        message=_(u"Remove email address {email}?").format(
            email=useremail.email),
        success=_(u"You have removed your email address {email}").format(
            email=useremail.email),
        next=url_for('.profile'))
Beispiel #34
0
def make_email_primary():
    form = EmailPrimaryForm()
    if form.validate_on_submit():
        useremail = UserEmail.get_for(user=current_auth.user,
                                      email=form.email.data)
        if useremail is not None:
            if useremail.primary:
                flash(_("This is already your primary email address"), 'info')
            else:
                current_auth.user.primary_email = useremail
                db.session.commit()
                user_data_changed.send(current_auth.user,
                                       changes=['email-update-primary'])
                flash(_("Your primary email address has been updated"),
                      'success')
        else:
            flash(_("No such email address is linked to this user account"),
                  'danger')
    else:
        flash(_("Please select an email address"), 'danger')
    return render_redirect(url_for('.account'), code=303)
Beispiel #35
0
def make_phone_primary():
    form = PhonePrimaryForm()
    if form.validate_on_submit():
        userphone = UserPhone.get_for(user=current_auth.user,
                                      phone=form.phone.data)
        if userphone is not None:
            if userphone.primary:
                flash(_("This is already your primary phone number"), 'info')
            else:
                current_auth.user.primary_phone = userphone
                db.session.commit()
                user_data_changed.send(current_auth.user,
                                       changes=['phone-update-primary'])
                flash(_("Your primary phone number has been updated"),
                      'success')
        else:
            flash(_("No such phone number is linked to this user account"),
                  'danger')
    else:
        flash(_("Please select a phone number"), 'danger')
    return render_redirect(url_for('.account'), code=303)
Beispiel #36
0
def verify_phone(phoneclaim):
    form = VerifyPhoneForm()
    form.phoneclaim = phoneclaim
    if form.validate_on_submit():
        if UserPhone.get(phoneclaim.phone) is None:
            if not g.user.phones:
                primary = True
            else:
                primary = False
            userphone = UserPhone(user=g.user, phone=phoneclaim.phone, gets_text=True, primary=primary)
            db.session.add(userphone)
            db.session.delete(phoneclaim)
            db.session.commit()
            flash(_("Your phone number has been verified"), 'success')
            user_data_changed.send(g.user, changes=['phone'])
            return render_redirect(url_for('.profile'), code=303)
        else:
            db.session.delete(phoneclaim)
            db.session.commit()
            flash(_("This phone number has already been claimed by another user"), 'danger')
    return render_form(form=form, title=_("Verify phone number"), formid='phone_verify',
        submit=_("Verify"), ajax=True)
Beispiel #37
0
def account_merge():
    if 'merge_buid' not in session:
        return redirect(get_next_url(), code=302)
    other_user = User.get(buid=session['merge_buid'])
    if other_user is None:
        session.pop('merge_buid', None)
        return redirect(get_next_url(), code=302)
    form = ProfileMergeForm()
    if form.validate_on_submit():
        if 'merge' in request.form:
            new_user = merge_users(current_auth.user, other_user)
            login_internal(new_user)
            flash(_("Your accounts have been merged"), 'success')
            session.pop('merge_buid', None)
            db.session.commit()
            user_data_changed.send(new_user, changes=['merge'])
            return redirect(get_next_url(), code=303)
        else:
            session.pop('merge_buid', None)
            return redirect(get_next_url(), code=303)
    return render_template('merge.html.jinja2', form=form, user=current_auth.user, other_user=other_user,
        login_registry=login_registry)
Beispiel #38
0
def verify_phone(phoneclaim):
    form = VerifyPhoneForm()
    form.phoneclaim = phoneclaim
    if form.validate_on_submit():
        if not g.user.phones:
            primary = True
        else:
            primary = False
        userphone = UserPhone(user=g.user,
                              phone=phoneclaim.phone,
                              gets_text=True,
                              primary=primary)
        db.session.add(userphone)
        db.session.delete(phoneclaim)
        db.session.commit()
        flash("Your phone number has been verified.", 'success')
        user_data_changed.send(g.user, 'phone')
        return render_redirect(url_for('.profile'), code=303)
    return render_form(form=form,
                       title="Verify phone number",
                       formid="phone_verify",
                       submit="Verify",
                       ajax=True)
Beispiel #39
0
def profile_merge():
    if 'merge_userid' not in session:
        return redirect(get_next_url(), code=302)
    other_user = User.get(userid=session['merge_userid'])
    if other_user is None:
        session.pop('merge_userid', None)
        return redirect(get_next_url(), code=302)
    form = ProfileMergeForm()
    if form.validate_on_submit():
        if 'merge' in request.form:
            new_user = merge_users(g.user, other_user)
            login_internal(new_user)
            user_data_changed.send(new_user, changes=['merge'])
            flash("Your accounts have been merged.", 'success')
            session.pop('merge_userid', None)
            return redirect(get_next_url(), code=303)
        else:
            session.pop('merge_userid', None)
            return redirect(get_next_url(), code=303)
    return render_template("merge.html",
                           form=form,
                           user=g.user,
                           other_user=other_user,
                           login_registry=login_registry)
Beispiel #40
0
def remove_email(md5sum):
    useremail = UserEmail.get_for(user=current_auth.user, md5sum=md5sum)
    if not useremail:
        useremail = UserEmailClaim.get_for(user=current_auth.user,
                                           md5sum=md5sum)
        if not useremail:
            abort(404)
    if isinstance(useremail, UserEmail) and useremail.primary:
        flash(_("You cannot remove your primary email address"), 'danger')
        return render_redirect(url_for('.account'), code=303)
    if request.method == 'POST':
        # FIXME: Confirm validation success
        user_data_changed.send(current_auth.user, changes=['email-delete'])
    return render_delete_sqla(
        useremail,
        db,
        title=_("Confirm removal"),
        message=_("Remove email address {email} from your account?").format(
            email=useremail.email),
        success=_("You have removed your email address {email}").format(
            email=useremail.email),
        next=url_for('.account'),
        delete_text=_("Remove"),
    )
Beispiel #41
0
def confirm_email(md5sum, secret):
    emailclaim = UserEmailClaim.get_by(md5sum=md5sum, verification_code=secret)
    if emailclaim is not None:
        if 'verify' in emailclaim.permissions(current_auth.user):
            existing = UserEmail.get(email=emailclaim.email)
            if existing is not None:
                claimed_email = emailclaim.email
                claimed_user = emailclaim.user
                db.session.delete(emailclaim)
                db.session.commit()
                if claimed_user != current_auth.user:
                    return render_message(
                        title=_("Email address already claimed"),
                        message=Markup(
                            _(
                                "The email address <code>{email}</code> has already been verified by another user"
                            ).format(email=escape(claimed_email))
                        ),
                    )
                else:
                    return render_message(
                        title=_("Email address already verified"),
                        message=Markup(
                            _(
                                "Hello <strong>{fullname}</strong>! "
                                "Your email address <code>{email}</code> has already been verified"
                            ).format(
                                fullname=escape(claimed_user.fullname),
                                email=escape(claimed_email),
                            )
                        ),
                    )

            useremail = emailclaim.user.add_email(
                emailclaim.email,
                primary=emailclaim.user.email is None,
                type=emailclaim.type,
                private=emailclaim.private,
            )
            db.session.delete(emailclaim)
            UserEmailClaim.all(useremail.email).delete(synchronize_session=False)
            db.session.commit()
            user_data_changed.send(current_auth.user, changes=['email'])
            return render_message(
                title=_("Email address verified"),
                message=Markup(
                    _(
                        "Hello <strong>{fullname}</strong>! "
                        "Your email address <code>{email}</code> has now been verified"
                    ).format(
                        fullname=escape(emailclaim.user.fullname),
                        email=escape(useremail.email),
                    )
                ),
            )
        else:
            return render_message(
                title=_("This was not for you"),
                message=_(
                    "You’ve opened an email verification link that was meant for another user. "
                    "If you are managing multiple accounts, please login with the correct account "
                    "and open the link again"
                ),
                code=403,
            )
    else:
        return render_message(
            title=_("Expired confirmation link"),
            message=_(
                "The confirmation link you clicked on is either invalid or has expired"
            ),
            code=404,
        )