Пример #1
0
def test_a_confusing_case(client, msend):
    """
    Final boss.
    """

    prepare()
    try:
        _, uf = create_user_and_form(client)
        DB.session.add(
            Form(email=uf.email, confirmed=False, host="example.com"))
        DB.session.add(
            Form(email=uf.email, confirmed=True, host="example.com/contact"))
        DB.session.add(
            Form(email=uf.email, confirmed=True, host="www.example.com/"))
        DB.session.commit()

        assert Form.query.count() == 4

        form = Form.get_with(email=uf.email, host="example.com/")
        assert form
        assert form.confirmed
        assert form.host == "www.example.com/"

        form2 = Form.get_with(email=uf.email, host="www.example.com")
        assert form2
        assert form2.confirmed
        assert form.host == "www.example.com/"

        contact = form.get_with(email=uf.email,
                                host="www.example.com/contact/")
        assert contact
        assert contact.host == "example.com/contact"

        assert form.id != contact.id
        assert form.id == form2.id

        r = client.post(
            "/" + uf.email,
            headers={"Referer": "http://example.com/"},
            data={"name": "example"},
        )
        assert r.status_code == 302
        assert "next" in r.location

        r = client.post(
            "/" + uf.email,
            headers={"Referer": "www.example.com"},
            data={"name": "example"},
        )
        assert r.status_code == 302
        assert "next" in r.location

        assert msend.call_count == 2
        assert Form.query.count() == 4
        form3 = Form.get_with(email=uf.email, host="example.com")
        assert 2 == form.submissions.count()
        assert form3.id == form2.id == form.id

    finally:
        revert()
Пример #2
0
def test_unconfirm_process(client, msend):
    # confirm some forms for the same email address
    f1 = Form('*****@*****.**', 'testwebsite.com')
    f1.confirmed = True
    DB.session.add(f1)

    f2 = Form('*****@*****.**', 'othertestwebsite.com')
    f2.confirmed = True
    DB.session.add(f2)

    f3 = Form('*****@*****.**', 'anothertestwebsite.com')
    f3.confirmed = True
    DB.session.add(f3)
    DB.session.commit()

    # try a submission
    r = client.post('/[email protected]',
                    headers={'Referer': 'http://testwebsite.com'},
                    data={'name': 'carol'})
    assert msend.called
    request_unconfirm_url = url_for('request_unconfirm_form',
                                    form_id=f1.id,
                                    _external=True)
    assert request_unconfirm_url in msend.call_args[1]['text']
    msend.reset_mock()

    # this should send a confirmation email
    r = client.get(request_unconfirm_url)
    assert r.status_code == 200
    assert msend.called

    unconfirm_url_with_digest = url_for('unconfirm_form',
                                        form_id=f1.id,
                                        digest=f1.unconfirm_digest(),
                                        _external=True)
    assert unconfirm_url_with_digest in msend.call_args[1]['text']
    msend.reset_mock()

    # unconfirm this
    r = client.get(unconfirm_url_with_digest)
    assert f1.confirmed == False

    # should show a page with the other options
    assert r.status_code == 200
    assert 'Select all' in r.data.decode('utf-8')
    assert f2.host in r.data.decode('utf-8')
    assert f3.host in r.data.decode('utf-8')

    unconfirm_multiple_url = url_for('unconfirm_multiple')
    assert unconfirm_multiple_url in r.data.decode('utf-8')

    # we can use unconfirm_multiple to unconfirm f2
    assert f2.confirmed == True
    r = client.post(unconfirm_multiple_url, data={'form_ids': [f2.id]})
    assert r.status_code == 200
    assert 'Success' in r.data.decode('utf-8')
    assert f2.confirmed == False
Пример #3
0
def test_backwards_multiple(client, msend, confirmed_host):
    """
    Same as previous, but now instead of having a single form, we have all,
    but each time only one of the them is confirmed.
    """

    prepare()
    try:
        for host in hosts:
            f = Form(email=email,
                     confirmed=(host == confirmed_host),
                     host=host)
            DB.session.add(f)
            DB.session.commit()

        for referer in hosts:
            r = client.post(
                "/" + email,
                headers={"Referer": "http://" + referer},
                data={"name": "example"},
            )

            assert r.status_code == 302
            assert "next" in r.location

        assert (len(hosts) == Form.query.filter_by(
            host=confirmed_host).first().submissions.count())

    finally:
        revert()
Пример #4
0
def test_backwards_single(client, msend, host):
    """
    Here we have a single form with one of the 8 host formats,
    then try to submit using all the 8.
    Everything must succeed.
    """

    prepare()
    try:
        f = Form(email=email, confirmed=True, host=host)
        DB.session.add(f)
        DB.session.commit()

        for referrer in hosts:
            r = client.post(
                "/" + email,
                headers={"Referer": "http://" + referrer},
                data={"name": "example"},
            )

            assert 1 == Form.query.count()
            assert r.status_code == 302
            assert "next" in r.location

        assert len(hosts) == Form.query.first().submissions.count()

    finally:
        revert()
Пример #5
0
def test_backwards_none_confirmed(client, msend):
    """
    This time no form is confirmed.
    """

    prepare()
    try:
        for host in hosts:
            f = Form(email=email, confirmed=False, host=host)
            DB.session.add(f)
            DB.session.commit()

        for referer in hosts:
            r = client.post(
                "/" + email,
                headers={"Referer": "http://" + referer},
                data={"name": "example"},
            )

            assert r.status_code == 200
            assert b"confirm" in r.get_data()
            assert Form.get_with(email=email, host=referer).host == hosts[0]

        assert Form.query.count() == len(hosts)
        assert Form.query.filter_by(confirmed=True).count() == 0
        assert Submission.query.count() == 0

    finally:
        revert()
Пример #6
0
def test_backwards_multiple_confirmed(client, msend, unconfirmed_host):
    """
    Same as previous, but now instead of having a single form confirmed, we
    have all but one confirmed. Submissions should go through the form which they
    specify directly, and fallback to the first in the priority when that is not
    confirmed.
    """

    prepare()
    try:
        for host in hosts:
            f = Form(email=email,
                     confirmed=(host != unconfirmed_host),
                     host=host)
            DB.session.add(f)
            DB.session.commit()

        for referer in hosts:
            r = client.post(
                "/" + email,
                headers={"Referer": "http://" + referer},
                data={"name": "example"},
            )

            assert r.status_code == 302
            assert "next" in r.location

        first = None
        for host in hosts:
            form = Form.query.filter_by(host=host).first()

            if host == unconfirmed_host:
                assert form.submissions.count() == 0
            else:
                if not first:
                    first = form
                    continue

                assert form.submissions.count() == 1
        assert first.submissions.count() == 2

    finally:
        revert()
Пример #7
0
def get_or_create_form(email, host):
    """
    Gets the form if it already exits, otherwise checks to ensure
    that this is a valid new form submission. If so, creates a
    new form.
    """

    form = Form.get_with(email=email, host=host)

    if not form:
        if request_wants_json():
            # Can't create a new ajax form unless from the dashboard
            ajax_error_str = (
                "To prevent spam, only "
                + settings.UPGRADED_PLAN_NAME
                + " accounts may create AJAX forms."
            )
            raise SubmitFormError((jsonify({"error": ajax_error_str}), 400))

        if (
            url_domain(settings.SERVICE_URL) in host
            and host.rstrip("/") != settings.TEST_URL
        ):
            # Bad user is trying to submit a form spoofing formspree.io
            g.log.info(
                "User attempting to create new form spoofing SERVICE_URL. Ignoring."
            )
            raise SubmitFormError(
                (
                    render_template(
                        "error.html", title="Unable to submit form", text="Sorry."
                    ),
                    400,
                )
            )

        # all good, create form
        form = Form(email, host=host, confirmed=False, normalize=True)

    if form.disabled:
        raise SubmitFormError(errors.disabled_error())

    return form
Пример #8
0
def create_user_and_form(client, login=True):
    # create user and form
    username = "".join(
        [random.choice(string.ascii_lowercase) for i in range(10)])
    email = username + "@example.com"
    user, _ = User.register(email, PASSWORD)
    user.plan = Plan.gold
    user.emails[0].verified = True
    form = Form(username + "@example.com",
                name="example",
                owner=user,
                confirmed=True)
    DB.session.add(user)
    DB.session.add(form)
    DB.session.commit()

    if login:
        client.post("/login", data={"email": email, "password": PASSWORD})

    return user, form
Пример #9
0
def get_or_create_form(email, host):
    '''
    Gets the form if it already exits, otherwise checks to ensure
    that this is a valid new form submission. If so, creates a
    new form.
    '''

    form = Form.query.filter_by(hash=HASH(email, host)).first()

    if not form:

        if request_wants_json():
            # Can't create a new ajax form unless from the dashboard
            ajax_error_str = "To prevent spam, only " + \
                                settings.UPGRADED_PLAN_NAME + \
                                " accounts may create AJAX forms."
            raise SubmitFormError(jsonerror(400, {'error': ajax_error_str}))

        if url_domain(settings.SERVICE_URL) in host:
            # Bad user is trying to submit a form spoofing formspree.io
            g.log.info(
                'User attempting to create new form spoofing SERVICE_URL. Ignoring.'
            )
            raise SubmitFormError(
                (render_template('error.html',
                                 title='Unable to submit form',
                                 text='Sorry'), 400))

        # all good, create form
        form = Form(email, host)

    # Check if it has been assigned using AJAX or not
    assign_ajax(form, request_wants_json())

    if form.disabled:
        raise SubmitFormError(errors.disabled_error())

    return form
Пример #10
0
def create_and_activate_form(client, email, host):
    # create user and form
    form = Form(email, host=host, confirmed=True)
    DB.session.add(form)
    DB.session.commit()
    return form
Пример #11
0
def test_recaptcha_is_rendered(client, msend):
    def revert(testing, seq):
        settings.TESTING = testing
        settings.FORM_AJAX_DISABLE_ACTIVATION_SEQUENCE = seq

    revert = partial(
        revert,
        testing=settings.TESTING,
        seq=settings.FORM_AJAX_DISABLE_ACTIVATION_SEQUENCE,
    )
    settings.TESTING = False

    try:
        # create the form
        f = Form("*****@*****.**", confirmed=True, host="example.com")
        DB.session.add(f)
        DB.session.commit()

        # normal submission
        r = client.post(
            "/[email protected]",
            headers={"Referer": "example.com"},
            data={"hello": "world"},
        )
        assert r.status_code == 401  # recaptcha
        assert b"google.com/recaptcha" in r.data
        assert not msend.called

        # ajax submission
        r = client.post(
            "/[email protected]",
            headers={
                "Referer": "example.com",
                "Content-Type": "application/json"
            },
            data=json.dumps({"hello": "world"}),
        )
        assert r.status_code == 403  # should get a json error
        assert "error" in json.loads(r.data.decode("utf-8"))
        assert not msend.called

        # a form that is before ajax disable sequence shouldn't show recaptcha
        # when the submission is ajax
        settings.FORM_AJAX_DISABLE_ACTIVATION_SEQUENCE = 1

        # normal submission
        r = client.post(
            "/[email protected]",
            headers={"Referer": "example.com"},
            data={"hello": "world"},
        )
        assert r.status_code == 401  # recaptcha
        assert b"google.com/recaptcha" in r.data
        assert not msend.called

        # ajax submission
        r = client.post(
            "/[email protected]",
            headers={
                "Referer": "example.com",
                "Content-Type": "application/json"
            },
            data=json.dumps({"hello": "world"}),
        )
        assert r.status_code == 200
        assert b"google.com/recaptcha" not in r.data
        assert msend.called

    finally:
        revert()
Пример #12
0
def test_unconfirm_process(client, msend):
    # confirm some forms for the same email address
    f1 = Form("*****@*****.**", host="testwebsite.com", confirmed=True)
    DB.session.add(f1)

    f2 = Form("*****@*****.**",
              host="othertestwebsite.com",
              confirmed=True)
    DB.session.add(f2)

    f3 = Form("*****@*****.**",
              host="anothertestwebsite.com",
              confirmed=True)
    DB.session.add(f3)
    DB.session.commit()

    # try a submission
    r = client.post(
        "/[email protected]",
        headers={"Referer": "http://testwebsite.com"},
        data={"name": "carol"},
    )
    assert msend.called
    request_unconfirm_url = url_for("request_unconfirm_form",
                                    form_id=f1.id,
                                    _external=True,
                                    _scheme="https")
    assert request_unconfirm_url in msend.call_args[1]["text"]
    msend.reset_mock()

    # this should send a confirmation email
    r = client.get(request_unconfirm_url)

    # actually, it should fail unless the request comes from a browser
    assert not msend.called

    # now it must work
    r = client.get(
        request_unconfirm_url,
        headers={
            "User-Agent":
            "Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0"
        },
    )
    assert r.status_code == 200
    assert msend.called

    unconfirm_url_with_digest = url_for(
        "unconfirm_form",
        form_id=f1.id,
        digest=f1.unconfirm_digest(),
        _external=True,
        _scheme="https",
    )
    assert unconfirm_url_with_digest in msend.call_args[1]["text"]
    msend.reset_mock()

    # unconfirm this
    r = client.get(unconfirm_url_with_digest)
    assert f1.confirmed == False

    # should show a page with the other options
    assert r.status_code == 200
    assert "Select all" in r.data.decode("utf-8")
    assert f2.host in r.data.decode("utf-8")
    assert f3.host in r.data.decode("utf-8")

    unconfirm_multiple_url = url_for("unconfirm_multiple")
    assert unconfirm_multiple_url in r.data.decode("utf-8")

    # we can use unconfirm_multiple to unconfirm f2
    assert f2.confirmed == True
    r = client.post(unconfirm_multiple_url, data={"form_ids": [f2.id]})
    assert r.status_code == 200
    assert "Success" in r.data.decode("utf-8")
    assert f2.confirmed == False