package Reporter::Routes; use Dancer2; use Dancer2::Plugin::Deferred; use Dancer2::Plugin::Auth::Extensible; # 'p' generates error (maybe conflict with DPP from another place?) use Data::Printer alias => 'ddp'; use Reporter; # use Reporter::Routes::Test; # do we need this? =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) = @_; # ddp $request; ddp $username; $refhash{$request} = guard { undef $Local::QueryLogger::CurrentUsername }; $Local::QueryLogger::CurrentUsername = $username; return; } } =cut # switch on sql_trace for test scripts (or though connamd-line with SQL_TRACE=1): # set enable_sql_trace => 1 if $ENV{HARNESS_VERSION}; # ddp \%ENV; set auto_page => 1; # eg /login, /denied (DPAE) # app, contains model & db classes: my $app = Reporter->new( config => config() ); 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'); # ddp $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; # ddp 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 { my $page = param('page') || 1; # get list of reported requests for this user: my $user = session('user_profile'); # ddp $user; my %args = ( user_id => $user->{id}, page => $page, uri => uri_for('/'), ); my $data = $app->model->get_reports_for_user(\%args); template load => { data => $data }; }; # submitted user credentials: post '/login' => sub { my $params = params; # ddp $params; # validate username/password if ( my $user = $app->model->validate_user_credentials($params) ) { ddp $user; session user_profile => $user; my @user_details = ( $user->{username}, $user->{password} ); # authenticate using DPAE authenticate_user() method: my ($success, $realm) = authenticate_user(@user_details); # ddp $success; ddp $realm; if ($success) { # ddp $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; # ddp $params; # validate lab number format: my $validation = $app->model->validator->validate( search => $params ); # ddp $validation; if ( $validation->{failed} ) { # ddp $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); # ddp $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'); # ddp $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; # ddp $params; my $validation = $app->model->validator->validate( report => $params ); # ddp $validation; my $record = session('record'); $record->{report} = $params; # in case validation fails if ( $validation->{failed} ) { # ddp $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}; # ddp $data; my $user = session('user_profile'); # ddp $user; # add user_id & request_id to $data: $data->{request_id} = param('request_id'); $data->{user_id} = $user->{id}; # ddp $data; my $result = $app->model->save_report($data); if ( my $err = $result->{error} ) { # ddp $result; my %args = ( target => uri_for('/report'), error => $err ); return template report => \%args; } # ddp $params->{request_id}; else { flash info => $result->{message}; } my $lab_number = $app->model->get_lab_number($params->{request_id}); # ddp $lab_number; redirect '/load?lab_number='.$lab_number; }; get '/register' => require_role qr/admin/ => sub { # ddp logged_in_user; ddp 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 qr/admin/ => sub { my $params = params; # ddp $params; my $validation = $app->model->validator->validate( register => $params ); if ( $validation->{failed} ) { # ddp $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}; # ddp $data; { # register validated user: my $result = $app->model->register_user($data); if ( my $err = $result->{error} ) { # ddp $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 } }; get '/report_summary' => sub { my $user_id = session('user_profile')->{id}; # ddp $user_id; my $data = $app->model->user_reports_list($user_id); { # set headers & return PDF form for user to print & send: my $content = template 'report_summary', { data => $data }, { layout => undef }; # override default 'main' layout return $content if dancer_app->environment eq 'development'; my $pdf = $app->model->render_pdf($content); header 'Content-Type' => 'application/pdf'; return $pdf; } }; # ajax calls (also available as separate app in Routes::AJAX if loaded by app.psgi) prefix '/ajax' => sub { get '/get_diagnoses' => sub { my $diagnoses = $app->model->get_diagnoses( param('diagnosis') ) || return; # p $diagnoses; # doesn't do query unless str >= 3 chars my @results = map { { id => $_->{id}, value => $_->{diagnosis}, info => $_->{icdo3} || '[non-ICDO3]', } } @$diagnoses; # ddp \@results; my $ref = { results => \@results }; # p $ref; encode_json($ref); }; }; # 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')); ddp $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;