aboutsummaryrefslogtreecommitdiffstats
path: root/lib/strip_attributes/test
ModeNameSize
-rw-r--r--strip_attributes_test.rb2409logstatsplain
-rw-r--r--test_helper.rb506logstatsplain
o { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
use Test::MockModule;

use FixMyStreet::TestMech;
my $mech = FixMyStreet::TestMech->new;

my $test_email    = 'test@example.com';
my $test_email3   = 'newuser@example.org';
my $test_password = 'foobar123';

END {
    done_testing();
}

$mech->get_ok('/auth');

# check that we can't reach a page that is only available to authenticated users
$mech->not_logged_in_ok;

# check that submitting form with no / bad email creates an error.
$mech->get_ok('/auth');

for my $test (
    [ ''                         => 'Please enter your email' ],
    [ 'not an email'             => 'Please check your email address is correct' ],
    [ 'bob@foo'                  => 'Please check your email address is correct' ],
    [ 'bob@foonaoedudnueu.co.uk' => 'Please check your email address is correct' ],
  )
{
    my ( $email, $error_message ) = @$test;

    my $resolver = Test::MockModule->new('Net::DNS::Resolver');
    $resolver->mock('send', sub {
        my ($self, $domain, $type) = @_;
        return Net::DNS::Packet->new;
    });

    pass "--- testing bad email '$email' gives error '$error_message'";
    $mech->get_ok('/auth');
    is_deeply $mech->page_errors, [], 'no errors initially';
    $mech->submit_form_ok(
        {
            form_name => 'general_auth',
            fields => { username => $email, },
            button => 'sign_in_by_code',
        },
        "try to create an account with email '$email'"
    );
    is $mech->uri->path, '/auth', "still on auth page";
    is_deeply $mech->page_errors, [ $error_message ], 'errors match';
}

# Email address parsing should pass from here
my $resolver = Test::MockModule->new('Email::Valid');
$resolver->mock('address', sub { $_[1] });

# create a new account
$mech->clear_emails_ok;
$mech->get_ok('/auth');
$mech->submit_form_ok(
    {
        form_name => 'general_auth',
        fields => { username => $test_email, password_register => $test_password },
        button => 'sign_in_by_code',
    },
    "create an account for '$test_email'"
);

# check that we are not logged in yet
$mech->not_logged_in_ok;

# check that we got one email
{
    my $email = $mech->get_email;
    $mech->clear_emails_ok;
    is $email->header('Subject'), "Your FixMyStreet account details",
      "subject is correct";
    is $email->header('To'), $test_email, "to is correct";

    # extract the link
    my $link = $mech->get_link_from_email($email);

    # check that the user does not exist
    sub get_user {
        FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
    }
    ok !get_user(), "no user exists";

    # visit the confirm link (with bad token) and check user no confirmed
    $mech->get_ok( $link . 'XXX' );
    ok !get_user(), "no user exists";
    $mech->not_logged_in_ok;

    # visit the confirm link and check user is confirmed
    $mech->get_ok($link);
    ok get_user(), "user created";
    is $mech->uri->path, '/my', "redirected to the 'my' section of site";
    $mech->logged_in_ok;

    # logout
    $mech->log_out_ok;
}

foreach my $remember_me ( '1', '0' ) {
    subtest "sign in using valid details (remember_me => '$remember_me')" => sub {
        $mech->get_ok('/auth');
        $mech->submit_form_ok(
            {
                form_name => 'general_auth',
                fields    => {
                    username => $test_email,
                    password_sign_in => $test_password,
                    remember_me => ( $remember_me ? 1 : undef ),
                },
                button => 'sign_in_by_password',
            },
            "sign in with '$test_email' & '$test_password'"
        );
        is $mech->uri->path, '/my', "redirected to correct page";

        my $expiry = $mech->session_cookie_expiry;
        $remember_me
          ? cmp_ok( $expiry, '>', 86400, "long expiry time" )
          : is( $expiry, 0, "no expiry time" );

        # logout
        $mech->log_out_ok;
    };
}

# try to sign in with bad details
$mech->get_ok('/auth');
$mech->submit_form_ok(
    {
        form_name => 'general_auth',
        fields    => {
            username => $test_email,
            password_sign_in => 'not the password',
        },
        button => 'sign_in_by_password',
    },
    "sign in with '$test_email' & 'not the password'"
);
is $mech->uri->path, '/auth', "redirected to correct page";
$mech->content_contains( 'problem with your login information', 'found error message' );

subtest "sign in but have email form autofilled" => sub {
    $mech->get_ok('/auth');
    $mech->submit_form_ok(
        {
            form_name => 'general_auth',
            fields    => {
                username => $test_email,
                password_sign_in => $test_password,
                name => 'Auto-completed from elsewhere',
            },
            button => 'sign_in_by_password',
        },
        "sign in with '$test_email' and auto-completed name"
    );
    is $mech->uri->path, '/my', "redirected to correct page";
};

$mech->log_out_ok;

subtest "sign in with uppercase email" => sub {
    $mech->get_ok('/auth');
    my $uc_test_email = uc $test_email;
    $mech->submit_form_ok(
        {
            form_name => 'general_auth',
            fields    => {
                username => $uc_test_email,
                password_sign_in => $test_password,
            },
            button => 'sign_in_by_password',
        },
        "sign in with '$uc_test_email' and auto-completed name"
    );
    is $mech->uri->path, '/my', "redirected to correct page";

    $mech->content_contains($test_email);
    $mech->content_lacks($uc_test_email);

    my $count = FixMyStreet::App->model('DB::User')->search( { email => $uc_test_email } )->count;
    is $count, 0, "uppercase user wasn't created";
};


FixMyStreet::override_config {
    SIGNUPS_DISABLED => 1,
}, sub {
    subtest 'signing in with an unknown email address disallowed' => sub {
        $mech->log_out_ok;
        # create a new account
        $mech->clear_emails_ok;
        $mech->get_ok('/auth');
        $mech->submit_form_ok(
            {
                form_name => 'general_auth',
                fields => { username => $test_email3, },
                button => 'sign_in_by_code',
            },
            "create a new account"
        );

        ok $mech->email_count_is(0);

        my $count = FixMyStreet::App->model('DB::User')->search( { email => $test_email3 } )->count;
        is $count, 0, "no user exists";
    };

    subtest 'signing in as known email address with new password is allowed' => sub {
        my $new_password = "myshinynewpassword";

        $mech->clear_emails_ok;
        $mech->get_ok('/auth');
        $mech->submit_form_ok(
            {
                form_name => 'general_auth',
                fields    => {
                    username => "$test_email",
                    password_register => $new_password,
                    r                 => 'faq', # Just as a test
                },
                button => 'sign_in_by_code',
            },
            "sign_in_by_code with '$test_email'"
        );

        $mech->not_logged_in_ok;

        ok $mech->email_count_is(1);
        my $link = $mech->get_link_from_email;
        $mech->get_ok($link);
        is $mech->uri->path, '/faq', "redirected to the Help page";

        $mech->log_out_ok;

        $mech->get_ok('/auth');
        $mech->submit_form_ok(
            {
                form_name => 'general_auth',
                fields    => {
                    username => $test_email,
                    password_sign_in => $new_password,
                },
                button => 'sign_in_by_password',
            },
            "sign in with '$test_email' and new password"
        );
        is $mech->uri->path, '/my', "redirected to correct page";
    };
};

subtest "check logging in with token" => sub {
    $mech->log_out_ok;
    $mech->not_logged_in_ok;

    my $user =  FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
    # token needs to be 18 characters
    $user->set_extra_metadata('access_token', '1234567890abcdefgh');
    $user->update();

    $mech->add_header('Authorization', 'Bearer 1234567890abcdefgh');
    $mech->logged_in_ok;

    $mech->delete_header('Authorization');
    $mech->not_logged_in_ok;

    $mech->get_ok('/auth/check_auth?access_token=1234567890abcdefgh');

    $mech->add_header('Authorization', 'Bearer 1234567890abcdefgh');
    $user->set_extra_metadata('access_token', 'XXXXXXXXXXXXXXXXXX');
    $user->update();
    $mech->not_logged_in_ok;

    $mech->delete_header('Authorization');
};

subtest 'check password length/common' => sub {
    $mech->get_ok('/auth');
    $mech->submit_form_ok({
        form_name => 'general_auth',
        fields => { username => $test_email, password_register => 'short' },
        button => 'sign_in_by_code',
    });
    $mech->content_contains("Please make sure your password is at least");
    $mech->submit_form_ok({
        form_name => 'general_auth',
        fields => { username => $test_email, password_register => 'common' },
        button => 'sign_in_by_code',
    });
    $mech->content_contains("Please choose a less commonly-used password");
};

subtest 'check common password AJAX call' => sub {
    $mech->post_ok('/auth/common_password', { password_register => 'password' });
    $mech->content_contains("Please choose a less commonly-used password");
    $mech->post_ok('/auth/common_password', { password_register => 'squirblewirble' });
    $mech->content_contains("true");
};

subtest "Test two-factor authentication login" => sub {
    use Auth::GoogleAuth;
    my $auth = Auth::GoogleAuth->new;
    my $code = $auth->code;
    my $wrong_code = $auth->code(undef, time() - 120);

    my $user = FixMyStreet::App->model('DB::User')->find( { email => $test_email } );
    $user->is_superuser(1);
    $user->password('password');
    $user->set_extra_metadata('2fa_secret', $auth->secret32);
    $user->update;

    $mech->get_ok('/auth');
    $mech->submit_form_ok(
        { with_fields => { username => $test_email, password_sign_in => 'password' } },
        "sign in using form" );
    $mech->content_contains('Please generate a two-factor code');
    $mech->submit_form_ok({ with_fields => { '2fa_code' => $wrong_code } }, "provide wrong 2FA code" );
    $mech->content_contains('Try again');
    $mech->submit_form_ok({ with_fields => { '2fa_code' => $code } }, "provide correct 2FA code" );
    $mech->logged_in_ok;
};