diff --git a/lib/AccessCheck/App.pm b/lib/AccessCheck/App.pm index 16cfbc1ab2f3f056e3fbdebdcba4e117c7834d75..d3e9538e140a9e04fe6ce7a0bb0aeea41bf084a5 100644 --- a/lib/AccessCheck/App.pm +++ b/lib/AccessCheck/App.pm @@ -86,14 +86,14 @@ sub startup { my $routes = $self->routes(); - $routes->get('/')->to(controller => 'home', action => 'run')->name('home'); - $routes->get('/status')->to(controller => 'status', action => 'run')->name('status'); - $routes->get('/step1')->to(controller => 'step1', action => 'run')->name('step1'); - $routes->get('/step2')->to(controller => 'step2', action => 'run')->name('step2'); - $routes->get('/send_challenge')->to(controller => 'send_challenge', action => 'run')->name('send_challenge'); - $routes->get('/validate_challenge')->to(controller => 'validate_challenge', action => 'run')->name('validate_challenge'); - $routes->get('/step4')->to(controller => 'step4', action => 'run')->name('step4'); - $routes->get('/step5')->to(controller => 'step5', action => 'run')->name('step5'); + $routes->get('/')->to(controller => 'controller', action => 'home')->name('home'); + $routes->get('/status')->to(controller => 'controller', action => 'status')->name('status'); + $routes->get('/select_entity')->to(controller => 'controller', action => 'select_entity')->name('select_entity'); + $routes->get('/select_email')->to(controller => 'controller', action => 'select_email')->name('select_email'); + $routes->get('/send_challenge')->to(controller => 'controller', action => 'send_challenge')->name('send_challenge'); + $routes->get('/validate_challenge')->to(controller => 'controller', action => 'validate_challenge')->name('validate_challenge'); + $routes->get('/show_accounts_html')->to(controller => 'controller', action => 'show_accounts_html')->name('show_accounts_html'); + $routes->get('/show_accounts_csv')->to(controller => 'controller', action => 'show_accounts_csv')->name('show_accounts_csv'); } diff --git a/lib/AccessCheck/App/Controller.pm b/lib/AccessCheck/App/Controller.pm index 9851bbf5cafe09bbfa75ddd6d1da17c8afc295de..4b03fac613ca2eefa8ff6ee378581a79b2fbf217 100644 --- a/lib/AccessCheck/App/Controller.pm +++ b/lib/AccessCheck/App/Controller.pm @@ -5,12 +5,16 @@ use Mojo::Base qw(Mojolicious::Controller); use English qw(-no_match_vars); use HTTP::AcceptLanguage; use Syntax::Keyword::Try; +use Template::Constants qw(:chomp); +use UNIVERSAL::require; +use AccessCheck::Data::Account; use AccessCheck::Data::DB; use AccessCheck::Data::Entity; use AccessCheck::Data::Token; use AccessCheck::L10N; use AccessCheck::Regexp; +use AccessCheck::Tools; sub init_l10n { my $self = shift; @@ -228,4 +232,515 @@ sub mock_contacts { } } +sub home { + my $self = shift; + + $self->init_l10n(); + + $self->render(status => 200, template => 'home', format => 'html'); +} + +=head2 status() + +Return the health status of the frontend. + +=cut + +sub status { + my $self = shift; + + my $config = $self->app()->config(); + + if (!$config->{status}) { + $self->render( + status => 403, + text => "unauthorized access" + ); + return; + } + + List::MoreUtils->require(); + Mojo::Util->require(); + + my $client_ip = $self->forwarded_for(); + my @allowed_ips = $self->string_to_list($config->{status}->{allowed}); + + if (List::MoreUtils::none { Mojo::Util::network_contains($_, $client_ip) } @allowed_ips) { + $self->render( + status => 403, + text => "unauthorized access" + ); + return; + } + + Sys::Hostname->require(); + my $status = $config->{status}->{disabled} ? 'disabled' : 'available'; + + my $health = { + status => $status, + host => hostname(), + }; + + $self->render(status => 200, json => $health); +} + +sub select_entity { + my $self = shift; + + my $app = $self->app(); + my $config = $app->config(); + my $log = $app->log(); + + my $l10n = $self->init_l10n(); + my $user = $self->init_user(); + my $db = $self->init_db(); + + if ($config->{app}->{login_url}) { + return if !$self->check_authentication(); + } + + my $sps = AccessCheck::Data::Entity->get_entities( + db => $db, + query => [ + type => 'sp', + ], + sort_by => 'display_name' + ); + + my $idp; + if ($user) { + my $idps = AccessCheck::Data::Entity->get_entities( + db => $db, + query => [ + type => 'idp', + entityid => $user->{idp} + ] + ); + $idp = $idps->[0]; + } + + $self->stash(sps => $sps); + $self->stash(idp => $idp); + + $self->render( + status => 200, + template => 'select_entity', + format => 'html' + ); +} + +sub select_email { + my $self = shift; + + my $app = $self->app(); + my $config = $app->config(); + my $log = $app->log(); + + my $l10n = $self->init_l10n(); + my $user = $self->init_user(); + my $db = $self->init_db(); + + if ($config->{app}->{login_url}) { + return if !$self->check_authentication(); + } + + my $entityid = $self->param('entityid'); + my $sp = $self->get_sp(entityid => $entityid); + return if !$sp; + + # override metadata contacts if needed + $self->mock_contacts($sp); + + $self->stash(sp => $sp); + $self->stash(entityid => $entityid); + + $self->render( + status => 200, + template => 'select_email', + format => 'html' + ); +} + +sub send_challenge { + my $self = shift; + + my $app = $self->app(); + my $config = $app->config(); + my $log = $app->log(); + + my $l10n = $self->init_l10n(); + my $user = $self->init_user(); + my $db = $self->init_db(); + + if ($config->{app}->{login_url}) { + return if !$self->check_authentication(); + } + + return if !$self->check_csrf_token(); + + my $entityid = $self->param('entityid'); + my $email = $self->param('email'); + + my $sp = $self->get_sp(entityid => $entityid); + return if !$sp; + + return $self->abort( + log_message => "Missing parameter: email", + user_message => "missing_email" + ) if !$email; + + return $self->abort( + log_message => "Invalid parameter: email", + user_message => "invalid_email" + ) if $email !~ $AccessCheck::Regexp::email; + + # override metadata contacts if needed + $self->mock_contacts($sp); + + ## Check that email is a known contact for this SP + return $self->abort( + log_message => "Requested a token for SP $entityid with unautorized address $email", + user_message => "internal", + ) if !$sp->is_contact($email); + + # delete any previous token for the same email/service couple + my $old_token = AccessCheck::Data::Token->new( + db => $db, + email_address => $email, + entityid => $entityid, + ); + + if ($old_token->load(speculative => 1)) { + try { + $old_token->delete(); + } catch { + return $self->abort( + log_message => "Failed to delete old authentication token", + user_message => "internal" + ); + } + } + + # compute a new token + DateTime->require(); + my $validity_period = + $config->{service}->{tokens_validity_period}; + my $token = AccessCheck::Data::Token->new( + db => $db, + email_address => $email, + entityid => $entityid, + creation_date => DateTime->now(), + expiration_date => DateTime->now()->add(hours => $validity_period), + secret => AccessCheck::Tools::generate_secret(20) + ); + + try { + $token->save(); + } catch { + return $self->abort( + log_message => "Failed to save creation authentication token", + user_message => "internal" + ); + } + + # build content + my $theme = $config->{setup}->{templates_theme} || 'default'; + my $base_templates_dir = $self->app()->home()->child('templates'); + my $tt2 = Template->new({ + ENCODING => 'utf8', + PRE_CHOMP => CHOMP_ONE, + INCLUDE_PATH => [ + $base_templates_dir->child('mail', $theme), + $base_templates_dir->child('mail'), + ] + }); + + my $data = { + app => { + url => $config->{app}->{url}, + support_email => $config->{app}->{support_email}, + version => $config->{app}->{version}, + name => $config->{app}->{name}, + }, + user => $user->{name}, + source_ip => $self->forwarded_for(), + idp => { entityid => $user->{idp}, }, + sp => { entityid => $entityid, }, + to => $email, + token => $token->secret(), + challenge_url => $self->url_for('validate_challenge')->query(entityid => $entityid, email => $email)->to_abs(), + lh => $l10n + }; + my $text_content; + my $html_content; + $tt2->process('send_challenge.txt.tt2', $data, \$text_content); + $tt2->process('send_challenge.html.tt2', $data, \$html_content); + + Email::MIME->require(); + Email::Sender::Simple->require(); + my $message = Email::MIME->create( + header_str => [ + 'From' => sprintf('%s <%s>', $config->{app}->{name}, $config->{mailer}->{from}), + 'To' => $email, + 'Subject' => sprintf('[%s] %s', $config->{app}->{name}, $l10n->maketext("Test accounts request")), + 'Content-Type' => 'multipart/alternative' + ], + parts => [ + Email::MIME->create( + attributes => { + content_type => "text/plain", + charset => 'utf-8', + encoding => 'quoted-printable' + }, + body_str => $text_content + ), + Email::MIME->create( + attributes => { + content_type => "text/html", + charset => 'utf-8', + encoding => 'quoted-printable' + }, + body_str => $html_content + ), + ] + ); + + try { + local $ENV{PATH} = '/bin:/sbin:/usr/bin:/usr/sbin'; + Email::Sender::Simple->send($message); + } catch($error) { + return $self->abort( + log_message => "Mail notification error: $error", + user_message => "mail_notification_failure" + ); + } + + $log->info( + sprintf( + "Token %s send to %s for entity %s", + $token->secret(), + $email, + $entityid, + ) + ); + + $self->redirect_to('validate_challenge', email => $email, entityid => $entityid); +} + +sub validate_challenge { + my $self = shift; + + my $app = $self->app(); + my $config = $app->config(); + my $log = $app->log(); + + my $l10n = $self->init_l10n(); + my $user = $self->init_user(); + my $db = $self->init_db(); + + if ($config->{app}->{login_url}) { + return if !$self->check_authentication(); + } + + my $entityid = $self->param('entityid'); + my $email = $self->param('email'); + + my $sp = $self->get_sp(entityid => $entityid); + return if !$sp; + + return $self->abort( + log_message => "Missing parameter: email", + user_message => "missing_email" + ) if !$email; + + return $self->abort( + log_message => "Invalid parameter: email", + user_message => "invalid_email" + ) if $email !~ $AccessCheck::Regexp::email; + + my $base_templates_dir = $self->app()->home()->child('templates'); + my $profiles = $base_templates_dir + ->child('accounts') + ->list() + ->map(sub { m/([^\/]+).tt2$/}) + ->to_array(); + + $self->stash(entityid => $entityid); + $self->stash(email => $email); + $self->stash(validity => $config->{service}->{account_validity_period}); + $self->stash(profiles => $profiles); + + $self->render( + status => 200, + template => 'validate_challenge', + format => 'html' + ); +} + +sub display_accounts_html { + my $self = shift; + + my $app = $self->app(); + my $config = $app->config(); + my $log = $app->log(); + + my $l10n = $self->init_l10n(); + my $user = $self->init_user(); + my $db = $self->init_db(); + + if ($config->{app}->{login_url}) { + return if !$self->check_authentication(); + } + + my $entityid = $self->param('entityid'); + my $email = $self->param('email'); + my $token = $self->param('token'); + my $validity = $self->param('validity'); + my $profiles = $self->every_param('profiles'); + + my $sp = $self->get_sp(entityid => $entityid); + return if !$sp; + + return if !$self->check_token(token => $token, entityid => $entityid); + + ## create test accounts + my @accounts; + + DateTime->require(); + my $creation_date = DateTime->now(); + my $token_expiration_date = DateTime->now()->add( + hours => $config->{service}->{tokens_validity_period} + ); + my $account_expiration_date = DateTime->now()->add( + days => $validity + ); + + my $download_token = AccessCheck::Data::Token->new( + db => $db, + email_address => $email, + entityid => $entityid, + creation_date => $creation_date, + expiration_date => $token_expiration_date, + secret => AccessCheck::Tools::generate_secret(20) + ); + + try { + $download_token->save(); + } catch { + return $self->abort( + log_message => "Failed to save download authentication token", + user_message => "internal" + ); + } + + my $key = AccessCheck::Tools::generate_secret(10); + + foreach my $profile (@$profiles) { + my $password = AccessCheck::Tools::generate_password(10); + my $account = AccessCheck::Data::Account->new( + db => $db, + profile => $profile, + entityid => $entityid, + scope => $config->{idp}->{scope}, + password => $password, + password_crypt => AccessCheck::Tools::encrypt($password, $key), + password_hash => AccessCheck::Tools::hash($password), + token => $download_token->secret(), + creation_date => $creation_date, + expiration_date => $account_expiration_date, + ); + next unless $account->save(); + push @accounts, $account; + } + + return $self->abort( + log_message => "Failed to create test accounts for SP $entityid", + user_message => "accounts_creation_failure" + ) if !@accounts; + + ## Update simpleSAMLphp configuration to enable test accounts + my $accounts = AccessCheck::Data::Account->get_accounts(db => $db); + + try { + AccessCheck::Tools::update_ssp_authsources( + $self->app()->home()->child('templates'), + $config->{setup}->{accounts_file}, + $accounts + ); + } catch($error) { + return $self->abort( + log_message => "Failed to create simpleSAMLphp configuration file: $error", + user_message => "accounts_creation_failure" + ); + } + + $log->info(sprintf("Token validated for entityid=%s", $entityid)); + + $self->stash(accounts => \@accounts); + $self->stash(idp => { name => $config->{idp}->{name} }); + $self->stash(sp => { entityid => $entityid, url => $sp->information_url() }); + $self->stash(email => $email); + $self->stash(days => $validity); + $self->stash( + download_url => $self->url_for('show_accounts_csv')->query( + entityid => $entityid, + token => $download_token->secret(), + key => $key + ) + ); + + $self->render( + status => 200, + template => 'show_accounts', + format => 'html' + ); +} + +sub display_accounts_csv { + my $self = shift; + + my $app = $self->app(); + my $config = $app->config(); + my $log = $app->log(); + + my $l10n = $self->init_l10n(); + my $user = $self->init_user(); + my $db = $self->init_db(); + + if ($config->{app}->{login_url}) { + return if !$self->check_authentication(); + } + + my $entityid = $self->param('entityid'); + my $token = $self->param('token'); + my $key = $self->param('key'); + + return if !$self->check_token(token => $token, entityid => $entityid); + + # load accounts from database + my $accounts = AccessCheck::Data::Account->get_accounts( + db => $db, + query => [ + token => $token + ], + ); + + foreach my $account (@$accounts) { + my $password = AccessCheck::Tools::decrypt( + $account->password_crypt(), $key + ); + $account->password($password); + } + + $app->types()->type(csv => 'text/csv'); + + $self->stash(accounts => $accounts); + + $self->render( + status => 200, + template => 'accounts', + format => 'csv' + ); +} + 1; diff --git a/lib/AccessCheck/App/Home.pm b/lib/AccessCheck/App/Home.pm deleted file mode 100644 index 0ef09af0cc954ceb6daea0afbcee8cad5b33045e..0000000000000000000000000000000000000000 --- a/lib/AccessCheck/App/Home.pm +++ /dev/null @@ -1,24 +0,0 @@ -package AccessCheck::App::Home; - -=head1 NAME - -AccessCheck::App::Home - Home page controller - -=head1 DESCRIPTION - -=cut - -use Mojo::Base qw(AccessCheck::App::Controller); - -use English qw(-no_match_vars); -use Syntax::Keyword::Try; - -sub run { - my $self = shift; - - $self->init_l10n(); - - $self->render(status => 200, template => 'home', format => 'html'); -} - -1; diff --git a/lib/AccessCheck/App/Status.pm b/lib/AccessCheck/App/Status.pm deleted file mode 100644 index b4bea276ba7fc6a1e3653e9fb35e1e1168b45aa0..0000000000000000000000000000000000000000 --- a/lib/AccessCheck/App/Status.pm +++ /dev/null @@ -1,65 +0,0 @@ -package AccessCheck::App::Status; - -=head1 NAME - -AccessCheck::App::Status - Health monitoring controller - -=head1 DESCRIPTION - -Health monitoring page - -Access: restricted by IP address - -=cut - -use Mojo::Base qw(AccessCheck::App::Controller); - -use English qw(-no_match_vars); -use List::MoreUtils qw(none); -use Mojo::Util qw(network_contains); -use Sys::Hostname; -use Syntax::Keyword::Try; - -=head1 INSTANCE METHODS - -=head2 run() - -Return the health status of the frontend. - -=cut - -sub run { - my $self = shift; - - my $config = $self->app()->config(); - - if (!$config->{status}) { - $self->render( - status => 403, - text => "unauthorized access" - ); - return; - } - - my $client_ip = $self->forwarded_for(); - my @allowed_ips = $self->string_to_list($config->{status}->{allowed}); - - if (none { network_contains($_, $client_ip) } @allowed_ips) { - $self->render( - status => 403, - text => "unauthorized access" - ); - return; - } - - my $status = $config->{status}->{disabled} ? 'disabled' : 'available'; - - my $health = { - status => $status, - host => hostname(), - }; - - $self->render(status => 200, json => $health); -} - -1; diff --git a/lib/AccessCheck/App/Step1.pm b/lib/AccessCheck/App/Step1.pm deleted file mode 100644 index 4750fa380699b1ad7e9b508872dca9b5a8bf33bb..0000000000000000000000000000000000000000 --- a/lib/AccessCheck/App/Step1.pm +++ /dev/null @@ -1,55 +0,0 @@ -package AccessCheck::App::Step1; - -use Mojo::Base qw(AccessCheck::App::Controller); - -use English qw(-no_match_vars); -use Syntax::Keyword::Try; - -use AccessCheck::Data::Entity; - -sub run { - my $self = shift; - - my $app = $self->app(); - my $config = $app->config(); - my $log = $app->log(); - - my $l10n = $self->init_l10n(); - my $user = $self->init_user(); - my $db = $self->init_db(); - - if ($config->{app}->{login_url}) { - return if !$self->check_authentication(); - } - - my $sps = AccessCheck::Data::Entity->get_entities( - db => $db, - query => [ - type => 'sp', - ], - sort_by => 'display_name' - ); - - my $idp; - if ($user) { - my $idps = AccessCheck::Data::Entity->get_entities( - db => $db, - query => [ - type => 'idp', - entityid => $user->{idp} - ] - ); - $idp = $idps->[0]; - } - - $self->stash(sps => $sps); - $self->stash(idp => $idp); - - $self->render( - status => 200, - template => 'step1', - format => 'html' - ); -} - -1; diff --git a/lib/AccessCheck/App/Step2.pm b/lib/AccessCheck/App/Step2.pm deleted file mode 100644 index 4a81b52962d29351340de2b58c22d64aeee2f292..0000000000000000000000000000000000000000 --- a/lib/AccessCheck/App/Step2.pm +++ /dev/null @@ -1,40 +0,0 @@ -package AccessCheck::App::Step2; - -use Mojo::Base qw(AccessCheck::App::Controller); - -use English qw(-no_match_vars); -use Syntax::Keyword::Try; - -sub run { - my $self = shift; - - my $app = $self->app(); - my $config = $app->config(); - my $log = $app->log(); - - my $l10n = $self->init_l10n(); - my $user = $self->init_user(); - my $db = $self->init_db(); - - if ($config->{app}->{login_url}) { - return if !$self->check_authentication(); - } - - my $entityid = $self->param('entityid'); - my $sp = $self->get_sp(entityid => $entityid); - return if !$sp; - - # override metadata contacts if needed - $self->mock_contacts($sp); - - $self->stash(sp => $sp); - $self->stash(entityid => $entityid); - - $self->render( - status => 200, - template => 'step2', - format => 'html' - ); -} - -1; diff --git a/lib/AccessCheck/App/Step4.pm b/lib/AccessCheck/App/Step4.pm deleted file mode 100644 index f3b68a1bd06f3f26bbde8f2a53c4a3f743a74d9e..0000000000000000000000000000000000000000 --- a/lib/AccessCheck/App/Step4.pm +++ /dev/null @@ -1,134 +0,0 @@ -package AccessCheck::App::Step4; - -use Mojo::Base qw(AccessCheck::App::Controller); - -use DateTime; -use Email::MIME; -use Email::Sender::Simple; -use English qw(-no_match_vars); -use Syntax::Keyword::Try; -use Template::Constants qw(:chomp); - -use AccessCheck::Data::Account; -use AccessCheck::Data::Token; -use AccessCheck::Tools; - -sub run { - my $self = shift; - - my $app = $self->app(); - my $config = $app->config(); - my $log = $app->log(); - - my $l10n = $self->init_l10n(); - my $user = $self->init_user(); - my $db = $self->init_db(); - - if ($config->{app}->{login_url}) { - return if !$self->check_authentication(); - } - - my $entityid = $self->param('entityid'); - my $email = $self->param('email'); - my $token = $self->param('token'); - my $validity = $self->param('validity'); - my $profiles = $self->every_param('profiles'); - - my $sp = $self->get_sp(entityid => $entityid); - return if !$sp; - - return if !$self->check_token(token => $token, entityid => $entityid); - - ## create test accounts - my @accounts; - - my $creation_date = DateTime->now(); - my $token_expiration_date = DateTime->now()->add( - hours => $config->{service}->{tokens_validity_period} - ); - my $account_expiration_date = DateTime->now()->add( - days => $validity - ); - - my $download_token = AccessCheck::Data::Token->new( - db => $db, - email_address => $email, - entityid => $entityid, - creation_date => $creation_date, - expiration_date => $token_expiration_date, - secret => AccessCheck::Tools::generate_secret(20) - ); - - try { - $download_token->save(); - } catch { - return $self->abort( - log_message => "Failed to save download authentication token", - user_message => "internal" - ); - } - - my $key = AccessCheck::Tools::generate_secret(10); - - foreach my $profile (@$profiles) { - my $password = AccessCheck::Tools::generate_password(10); - my $account = AccessCheck::Data::Account->new( - db => $db, - profile => $profile, - entityid => $entityid, - scope => $config->{idp}->{scope}, - password => $password, - password_crypt => AccessCheck::Tools::encrypt($password, $key), - password_hash => AccessCheck::Tools::hash($password), - token => $download_token->secret(), - creation_date => $creation_date, - expiration_date => $account_expiration_date, - ); - next unless $account->save(); - push @accounts, $account; - } - - return $self->abort( - log_message => "Failed to create test accounts for SP $entityid", - user_message => "accounts_creation_failure" - ) if !@accounts; - - ## Update simpleSAMLphp configuration to enable test accounts - my $accounts = AccessCheck::Data::Account->get_accounts(db => $db); - - try { - AccessCheck::Tools::update_ssp_authsources( - $self->app()->home()->child('templates'), - $config->{setup}->{accounts_file}, - $accounts - ); - } catch($error) { - return $self->abort( - log_message => "Failed to create simpleSAMLphp configuration file: $error", - user_message => "accounts_creation_failure" - ); - } - - $log->info(sprintf("Token validated for entityid=%s", $entityid)); - - $self->stash(accounts => \@accounts); - $self->stash(idp => { name => $config->{idp}->{name} }); - $self->stash(sp => { entityid => $entityid, url => $sp->information_url() }); - $self->stash(email => $email); - $self->stash(days => $validity); - $self->stash( - download_url => $self->url_for('step5')->query( - entityid => $entityid, - token => $download_token->secret(), - key => $key - ) - ); - - $self->render( - status => 200, - template => 'step4', - format => 'html' - ); -} - -1; diff --git a/lib/AccessCheck/App/Step5.pm b/lib/AccessCheck/App/Step5.pm deleted file mode 100644 index 9618c9f308d7627259687ab97025adbb13182b6b..0000000000000000000000000000000000000000 --- a/lib/AccessCheck/App/Step5.pm +++ /dev/null @@ -1,62 +0,0 @@ -package AccessCheck::App::Step5; - -use Mojo::Base qw(AccessCheck::App::Controller); - -use DateTime; -use Email::MIME; -use Email::Sender::Simple; -use English qw(-no_match_vars); -use Syntax::Keyword::Try; -use Template::Constants qw(:chomp); - -use AccessCheck::Data::Account; -use AccessCheck::Tools; - -sub run { - my $self = shift; - - my $app = $self->app(); - my $config = $app->config(); - my $log = $app->log(); - - my $l10n = $self->init_l10n(); - my $user = $self->init_user(); - my $db = $self->init_db(); - - if ($config->{app}->{login_url}) { - return if !$self->check_authentication(); - } - - my $entityid = $self->param('entityid'); - my $token = $self->param('token'); - my $key = $self->param('key'); - - return if !$self->check_token(token => $token, entityid => $entityid); - - # load accounts from database - my $accounts = AccessCheck::Data::Account->get_accounts( - db => $db, - query => [ - token => $token - ], - ); - - foreach my $account (@$accounts) { - my $password = AccessCheck::Tools::decrypt( - $account->password_crypt(), $key - ); - $account->password($password); - } - - $app->types()->type(csv => 'text/csv'); - - $self->stash(accounts => $accounts); - - $self->render( - status => 200, - template => 'accounts', - format => 'csv' - ); -} - -1; diff --git a/lib/Makefile.am b/lib/Makefile.am index 9c90300f04a636df23fd0e13ec5dec780e82d4d6..4e08d6a074acd65da2d30535521963d5b2551cec 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -13,15 +13,7 @@ nobase_applib_DATA = \ AccessCheck/L10N/en.pm \ AccessCheck/L10N/fr.pm \ AccessCheck/App.pm \ - AccessCheck/App/Home.pm \ AccessCheck/App/Controller.pm \ - AccessCheck/App/Status.pm \ - AccessCheck/App/Step1.pm \ - AccessCheck/App/Step2.pm \ - AccessCheck/App/SendChallenge.pm \ - AccessCheck/App/ValidateChallenge.pm \ - AccessCheck/App/Step4.pm \ - AccessCheck/App/Step5.pm \ AccessCheck/Template/Plugin/Quote.pm EXTRA_DIST = $(nobase_applib_DATA) diff --git a/t/app.t b/t/app.t index 01fc8c197f19d44dc1361d67740e214c3f45bb2c..13c840df70d703947220bc218cda2be5b8cebc1d 100755 --- a/t/app.t +++ b/t/app.t @@ -170,7 +170,7 @@ named_subtest "index page" => sub { $t->get_ok('/') ->status_is(200) ->text_is('html head title' => 'eduGAIN Access Check') - ->text_is('a[href=/step1]' => 'Get started', 'get started button'); + ->text_is('a[href=/select_entity]' => 'Get started', 'get started button'); my $res = $t->tx()->res(); html_ok($res) or diag_file($res, $test_dir); @@ -179,7 +179,7 @@ named_subtest "index page" => sub { named_subtest "SP selection page" => sub { my $t = get_test_object(test => $_[0]); - $t->get_ok('/step1') + $t->get_ok('/select_entity') ->status_is(200) ->text_is('html head title' => 'eduGAIN Access Check', 'expected title') ->element_exists('select[id=all][name=all]', 'SP selection widget'); @@ -191,7 +191,7 @@ named_subtest "SP selection page" => sub { named_subtest "email selection page, missing entityid" => sub { my $t = get_test_object(test => $_[0]); - $t->get_ok('/step2') + $t->get_ok('/select_email') ->status_is(200) ->text_is('html head title' => 'eduGAIN Access Check', 'expected title') ->content_like(qr/Error:[\n\s]+missing parameter 'entityid'/, 'expected error message'); @@ -203,7 +203,7 @@ named_subtest "email selection page, missing entityid" => sub { named_subtest "email selection page, invalid entityid" => sub { my $t = get_test_object(test => $_[0]); - $t->get_ok('/step2' => form => {entityid => 'foo'}) + $t->get_ok('/select_email' => form => {entityid => 'foo'}) ->status_is(200) ->text_is('html head title' => 'eduGAIN Access Check', 'expected title') ->content_like(qr/Error:[\n\s]+invalid parameter 'entityid'/, 'expected error message'); @@ -215,7 +215,7 @@ named_subtest "email selection page, invalid entityid" => sub { named_subtest "email selection page, valid entityid" => sub { my $t = get_test_object(test => $_[0]); - $t->get_ok('/step2' => form => {entityid => 'https://sp.renater.fr/'}) + $t->get_ok('/select_email' => form => {entityid => 'https://sp.renater.fr/'}) ->status_is(200) ->text_is('html head title' => 'eduGAIN Access Check', 'expected title') ->element_exists('input[name=email][value=contact1@renater.fr]', 'email selection widget'); @@ -362,7 +362,7 @@ named_subtest "index page, french version" => sub { $t->get_ok('/') ->status_is(200) ->text_is('html head title' => 'eduGAIN Access Check') - ->text_is('html body a[href=/step1]' => 'Commencer', 'get started button'); + ->text_is('html body a[href=/select_entity]' => 'Commencer', 'get started button'); my $res = $t->tx()->res(); html_ok($res) or diag_file($res, $test_dir); diff --git a/templates/Makefile.am b/templates/Makefile.am index 95f86b9d11ec5ea7ac250a01f06352bf5f2fb05e..cc20499bf1c1ecf1db14f36d2c811e25058bd926 100644 --- a/templates/Makefile.am +++ b/templates/Makefile.am @@ -19,17 +19,17 @@ nobase_apptemplates_DATA = \ web/edugain/errors.html.tt2 \ web/edugain/home.html.tt2 \ web/edugain/index.html.tt2 \ - web/edugain/step1.html.tt2 \ - web/edugain/step2.html.tt2 \ + web/edugain/select_entity.html.tt2 \ + web/edugain/select_email.html.tt2 \ web/edugain/validate_challenge.html.tt2 \ - web/edugain/step4.html.tt2 \ + web/edugain/show_accounts.html.tt2 \ web/renater/errors.html.tt2 \ web/renater/home.html.tt2 \ web/renater/index.html.tt2 \ - web/renater/step1.html.tt2 \ - web/renater/step2.html.tt2 \ + web/renater/select_entity.html.tt2 \ + web/renater/select_email.html.tt2 \ web/renater/validate_challenge.html.tt2 \ - web/renater/step4.html.tt2 + web/renater/show_accounts.html.tt2 EXTRA_DIST = $(nobase_apptemplates_DATA) diff --git a/templates/web/edugain/home.html.tt2 b/templates/web/edugain/home.html.tt2 index fc64d08c11404102d6b3b06184d5d6f7f4ed3593..6141b0bd51fb587e693e5216f1ce34bbd8bc9dae 100644 --- a/templates/web/edugain/home.html.tt2 +++ b/templates/web/edugain/home.html.tt2 @@ -9,6 +9,6 @@ <h2>[% c.loc("Get started") %]</h2> <p>[% c.loc("To start testing your own services, start by selecting one your are administrator for.") %]</p> -<p class="text-center"><a href="[% IF app.login_url %][% app.login_url %]?target=[% c.url_for('step1') %][% ELSE %][% c.url_for('step1') %][% END %]" class="button">[% c.loc("Get started") %]</a></p> +<p class="text-center"><a href="[% IF app.login_url %][% app.login_url %]?target=[% c.url_for('select_entity') %][% ELSE %][% c.url_for('select_entity') %][% END %]" class="button">[% c.loc("Get started") %]</a></p> [% END %] diff --git a/templates/web/edugain/step2.html.tt2 b/templates/web/edugain/select_email.html.tt2 similarity index 97% rename from templates/web/edugain/step2.html.tt2 rename to templates/web/edugain/select_email.html.tt2 index c544c15158530eea36a7ff6a2534cc5d1fbfb27f..303efc9237cbc3bddbe8387aa7044a3cd78491c4 100644 --- a/templates/web/edugain/step2.html.tt2 +++ b/templates/web/edugain/select_email.html.tt2 @@ -35,7 +35,7 @@ </div> <div class="actions clearfix"> - <button type="submit" class="button" formaction="[% c.url_for('step1') %]" formnovalidate>[% c.loc("Previous") %]</button> + <button type="submit" class="button" formaction="[% c.url_for('select_entity') %]" formnovalidate>[% c.loc("Previous") %]</button> <button type="submit" class="button">[% c.loc("Next") %]</button> </div> </form> diff --git a/templates/web/edugain/step1.html.tt2 b/templates/web/edugain/select_entity.html.tt2 similarity index 98% rename from templates/web/edugain/step1.html.tt2 rename to templates/web/edugain/select_entity.html.tt2 index a1f6b705bf8608c3dc044aaad3257605b855f8cf..9d8a463efcd4e52ef29b35376238780624beb648 100644 --- a/templates/web/edugain/step1.html.tt2 +++ b/templates/web/edugain/select_entity.html.tt2 @@ -1,5 +1,5 @@ [% WRAPPER index.html.tt2 %] -<form class="wizard clearfix" action="[% c.url_for('step2') %]" method="get"> +<form class="wizard clearfix" action="[% c.url_for('select_email') %]" method="get"> <div class="steps clearfix"> <ol> <li class="current">[% c.loc("Select your service provider") %]</li> diff --git a/templates/web/edugain/step4.html.tt2 b/templates/web/edugain/show_accounts.html.tt2 similarity index 96% rename from templates/web/edugain/step4.html.tt2 rename to templates/web/edugain/show_accounts.html.tt2 index 1e6b54f719f19760f5ef2a946b3a41debb97151e..817b062db0a41f447cbe3c8e22a99433783ed39f 100644 --- a/templates/web/edugain/step4.html.tt2 +++ b/templates/web/edugain/show_accounts.html.tt2 @@ -79,5 +79,5 @@ </div> </div> -<p class="text-center"><a href="[% c.url_for('step1') %]" class="button">[% c.loc("Test another service") %]</a></p> +<p class="text-center"><a href="[% c.url_for('select_entity') %]" class="button">[% c.loc("Test another service") %]</a></p> [% END %] diff --git a/templates/web/edugain/validate_challenge.html.tt2 b/templates/web/edugain/validate_challenge.html.tt2 index 1e9388414867e348262fa4afc80713a054b7fae8..df7203626dfebb27e59374c39b4bf4a79c89b098 100644 --- a/templates/web/edugain/validate_challenge.html.tt2 +++ b/templates/web/edugain/validate_challenge.html.tt2 @@ -1,5 +1,5 @@ [% WRAPPER index.html.tt2 %] -<form class="wizard clearfix" action="[% c.url_for('step4') %]" method="get"> +<form class="wizard clearfix" action="[% c.url_for('show_accounts_html') %]" method="get"> <div class="steps clearfix"> <ol> <li class="done">[% c.loc("Select your service provider") %]</li> @@ -42,7 +42,7 @@ </div> <div class="actions clearfix"> - <button type="submit" class="button" formaction="[% c.url_for('step2') %]" formnovalidate>[% c.loc("Previous") %]</button> + <button type="submit" class="button" formaction="[% c.url_for('select_email') %]" formnovalidate>[% c.loc("Previous") %]</button> <button type="submit" class="button">[% c.loc("Next") %]</button> </div> </form> diff --git a/templates/web/renater/home.html.tt2 b/templates/web/renater/home.html.tt2 index 819da9c63de4f330a003730c5bab17fc4b1e3ffa..86b8cd139a81acd9a8d671bb2a87389d77d4a4f4 100644 --- a/templates/web/renater/home.html.tt2 +++ b/templates/web/renater/home.html.tt2 @@ -9,6 +9,6 @@ <h2>[% c.loc("Get started") %]</h2> <p>[% c.loc("To start testing your own services, start by selecting one your are administrator for.") %]</p> -<p class="text-center"><a href="[% IF app.login_url %][% app.login_url %]?target=[% c.url_for('step1') %][% ELSE %][% c.url_for('step1') %][% END %]" class="button">[% c.loc("Get started") %]</a></p> +<p class="text-center"><a href="[% IF app.login_url %][% app.login_url %]?target=[% c.url_for('select_entity') %][% ELSE %][% c.url_for('select_entity') %][% END %]" class="button">[% c.loc("Get started") %]</a></p> [% END %] diff --git a/templates/web/renater/step2.html.tt2 b/templates/web/renater/select_email.html.tt2 similarity index 100% rename from templates/web/renater/step2.html.tt2 rename to templates/web/renater/select_email.html.tt2 diff --git a/templates/web/renater/step1.html.tt2 b/templates/web/renater/select_entity.html.tt2 similarity index 99% rename from templates/web/renater/step1.html.tt2 rename to templates/web/renater/select_entity.html.tt2 index dc46ca310c611c2d0ec0c9b6460315a348e4452e..f405a8a440675b0e69826a27d8cbc26f6049fb39 100644 --- a/templates/web/renater/step1.html.tt2 +++ b/templates/web/renater/select_entity.html.tt2 @@ -1,5 +1,5 @@ [% WRAPPER index.html.tt2 %] -<form class="wizard clearfix" action="[% c.url_for('step2') %]" method="get"> +<form class="wizard clearfix" action="[% c.url_for('select_email') %]" method="get"> <div class="steps clearfix"> <ol> <li class="current">[% c.loc("Select your service provider") %]</li> diff --git a/templates/web/renater/step4.html.tt2 b/templates/web/renater/show_accounts.html.tt2 similarity index 96% rename from templates/web/renater/step4.html.tt2 rename to templates/web/renater/show_accounts.html.tt2 index 9e5d2bdd5d20184ed6507a7e7d277ce52bfa0746..0e63867e3e942557d11de1353a75d03929414298 100644 --- a/templates/web/renater/step4.html.tt2 +++ b/templates/web/renater/show_accounts.html.tt2 @@ -81,5 +81,5 @@ </div> </div> -<p class="text-center"><a href="[% c.url_for('step1') %]" class="button">[% c.loc("Test another service") %]</a></p> +<p class="text-center"><a href="[% c.url_for('select_entity') %]" class="button">[% c.loc("Test another service") %]</a></p> [% END %] diff --git a/templates/web/renater/validate_challenge.html.tt2 b/templates/web/renater/validate_challenge.html.tt2 index bb83a121405c8fa841a1414ec799f26f34a30b80..2c922f3ca0416bdcf67c14702357ffa86409c400 100644 --- a/templates/web/renater/validate_challenge.html.tt2 +++ b/templates/web/renater/validate_challenge.html.tt2 @@ -1,5 +1,5 @@ [% WRAPPER index.html.tt2 %] -<form class="wizard clearfix" action="[% c.url_for('step4') %]" method="get"> +<form class="wizard clearfix" action="[% c.url_for('show_accounts_html') %]" method="get"> <div class="steps clearfix"> <ol> <li class="done">[% c.loc("Select your service provider") %]</li>