package Reporter::Routes; use Dancer2; use Dancer2::Plugin::Deferred; use Dancer2::Plugin::Auth::Extensible; use Data::Printer; use Reporter; use Reporter::Routes::AJAX; use Reporter::Routes::Test; =begin # seems to work the same setting $Local::QueryLogger::CurrentUsername directly use Tie::RefHash::Weak; use Scope::Guard qw(guard); { tie my %refhash, 'Tie::RefHash::Weak'; sub set_username { my ($request, $username) = @_; # p $request; p $username; $refhash{$request} = guard { undef $Local::QueryLogger::CurrentUsername }; $Local::QueryLogger::CurrentUsername = $username; return; } } =cut set auto_page => 1; # eg /login, /denied (DPAE) # disable sql_trace if test script (needs explicit export SQL_TRACE=1 if req'd): set enable_sql_trace => 0 if $ENV{HARNESS_VERSION}; # app, contains model & db classes: our $app = Reporter->new( dbname => 'hilis4', config => config() ); # make $app available to other routes that need it: $Reporter::Routes::AJAX::app = $app; sub flash { deferred @_ } # to use old term flash instead of deferred hook before => sub { # discard old db connection if mysql has gone away since last request: $app->check_db_connection; # Local::DB - creates new DBIx::Simple object on demand # sql query output to stdout: $app->enable_sql_trace if setting('enable_sql_trace'); # development env # all routes need login (except /login): my $session = session('user_profile'); # p $session; # beware auto-vivification here unless ( $session ) { redirect '/login' unless request->path_info =~ m!^/login!; } # set_username(request(), $session->{username}); # works the same setting directly: $Local::QueryLogger::CurrentUsername = $session->{username}; }; hook before_template_render => sub { # do NOT use 'var' in here or 500.tt fails my $tokens = shift; $tokens->{app_version} = $app->version; # warn $app->version; $tokens->{symbolise} = sub { $app->symbolise(@_) }; if ( session->read('logged_in_user_realm') ) { # fatal if called before login $tokens->{user_roles} = user_roles; # p user_roles; # DPAE } }; # fix for broken 500.tt rendering if use of 'var' in before_template_render() : # hook on_route_exception => sub { send_error($_[1]) }; # err msg available in [% content %] # default route: get '/' => sub { { # get list of reported requests for this user: my $user = session('user_profile'); # p $user; my $data = $app->model->get_reports_for_user($user->{id}); var user_reports => $data; } template load => { target => uri_for('/load') }; }; # submitted user credentials: post '/login' => sub { my $params = params; # p $params; # validate username/password if ( my $user = $app->model->authenticate_user($params) ) { # p $user; session user_profile => $user; # set D::P::Auth::Extensible params - not using password in config as already logged in my ($success, $realm) = authenticate_user($user->{username}); # no password !! if ($success) { # p $realm; # # for DPAE: session logged_in_user => $user->{username}; session logged_in_user_realm => $realm; } redirect '/'; } else { my $failed_logins = session('failed_logins') || 0; session failed_logins => $failed_logins + 1; # increment redirect '/login'; } }; get '/load' => sub { my $params = params; # p $params; # validate lab number format: my $validation = $app->model->validator->validate( search => $params ); # p $validation; if ( $validation->{failed} ) { # p $result->{errors}; return template load => $validation; # href containing dfv_errs key } my $lab_number = param('lab_number'); my $session = session('user_profile'); { # get request for lab_number: my %h = ( lab_number => $lab_number, user_id => $session->{id}, ); my $data = $app->model->load_request(\%h); # p $data; if (! $data) { my $msg = 'request with lab number %s not found'; flash warning => sprintf $msg, $lab_number; redirect '/'; } # store data in session for tt, and in case needed for re-display to report.tt: session record => $data; } { # get validation profile to configure required fields: my $profile = $app->model->get_validation_profile('report'); # p $profile; session validation_profile => $profile; } # tt gets data from session.record: template report => { target => uri_for('/report') }; }; post '/report/:request_id' => sub { my $params = params; # p $params; my $validation = $app->model->validator->validate( report => $params ); # p $validation; my $record = session('record'); $record->{report} = $params; # in case validation fails if ( $validation->{failed} ) { # p $validation->{errors}; my %args = ( target => uri_for('/report'), dfv_errs => $validation->{dfv_errs}, # href containing dfv_errs key ); return template report => \%args; } my $data = $validation->{valid}; # p $data; my $user = session('user_profile'); # p $user; # add user_id & request_id to $data: $data->{request_id} = param('request_id'); $data->{user_id} = $user->{id}; # p $data; my $result = $app->model->save_report($data); if ( my $err = $result->{error} ) { # p $result; my %args = ( target => uri_for('/report'), error => $err ); return template report => \%args; } # p $params->{request_id}; else { flash info => $result->{message}; } my $lab_number = $app->model->get_lab_number($params->{request_id}); # p $lab_number; redirect '/load?lab_number='.$lab_number; }; get '/register' => require_role admin => sub { # p logged_in_user; p user_roles; # return 'access_denied' unless user_has_role('admin'); # permission_denied_page_handler return template register => { target => uri_for('/register') }; }; post '/register' => require_role admin => sub { my $params = params; # p $params; my $validation = $app->model->validator->validate( register => $params ); if ( $validation->{failed} ) { # p $validation; my %args = ( target => uri_for('/register'), dfv_errs => $validation->{dfv_errs}, # href containing dfv_errs key ); return template register => \%args; } my $data = $validation->{valid}; # p $data; { # register validated user: my $result = $app->model->register_user($data); if ( my $err = $result->{error} ) { # p $result; my %args = ( target => uri_for('/register'), error => $err ); return template register => \%args; } } { # OK, registration success, email message to user: my $result = $app->model->email_registration($data); return template registration => $result; # hand $result straight to tt } }; # logout route: get '/logout' => sub { app->destroy_session; redirect('/'); # should redirect to /login }; get '/gitlog' => sub { template gitlog => { log => $app->gitlog } }; # default Dancer2 app index page: get '/index' => sub { template index => {}, { layout => 'index' } }; #=============================================================================== # http://blog.geekuni.com/2015/06/three-ways-to-implement-sessions.html =begin get '/count' => sub { if ( my $user = session('user') ) { session count => session('count') + 1; my $ordinal = $app->model->num2ordinal(session('count')); p $ordinal; return 'Click here for the name of the eldest son of ' . 'Count von '. ucfirst $user.' the '. ucfirst $ordinal .''; } return 'Cookie Monster!'; }; get '/do_login/:user' => sub { session user => params->{user}; session count => 0; redirect '/count'; }; =cut #=============================================================================== true;