diff --git a/.perltidyrc b/.perltidyrc index 7c2cf62..f2ac20c 100644 --- a/.perltidyrc +++ b/.perltidyrc @@ -2,7 +2,7 @@ -w # Show all warnings -iob # Ignore old breakpoints -l=80 # 80 characters per line --mbl=2 # No more than 2 blank lines +-mbl=1 # No more than 2 blank lines -i=2 # Indentation is 2 columns -ci=2 # Continuation indentation is 2 columns -vt=0 # Less vertical tightness diff --git a/.travis.yml b/.travis.yml index 5147752..13a5212 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,15 +33,14 @@ before_script: - mojo version - coverage-setup notifications: - slack: - secure: hwihdXrKIOilNPyIunNh5yqBwtgwj4SnheF8DlsmQI2TqpcyFWgjvspnvquiV7+OEBb5mFUSZeEUj5cgIgJ3VaBFIbcij0nq3TTHAvSmx+oTboAxUkg62zdPaaFV+iK9BpCNm6eGsjE1Wfp6LXzBHOZetCXJ1IgQ02mOknkW2ysztNhF4G/MMUXvDe5ApgTHshGYvkaD+StHcLt2c6Quy4DUkKeU6Djun6Dyp3foSBibBRsQK9q0yXo5ooYkoVllEaSvu94FpxBjsF+lBQJveM2Wc090EgM1An/Oc/ptMVvMmSE0mmM8RR9vM5dUZwmZHd/kECo1cvGQG1nVJZ9qWnrCeWcnJS7M9FkFucEBjFJTzh1FL3tgYKnXkS04uQLaj84byQr7f+l4l8ExsJPUriQia9829+OeiRblOdB3mEEMgHleMhE0trfre7iz5Beob5sPwTq9z7ywrRVGX8vKeDXPEmwDi+5gdYXRw3QwNP7sWAePOdpZPzUBc5fUYZh8kJB22b8zoF1T81gxME0MQOc4nCgSCETtLWih3R8sngooAXXo9kYM3zb38ijoLpPwlOmE0BR9rvcSz8BBp1bVhWZ4k4ploe5uTtb+Mg31Amj6d5I5z9/KwYJQ6Mcy3y8Ijozm7+FpDLfjz70ZjAYguurmHFZsDQJQp4fJUcOFabc= + # slack: + # secure: hwihdXrKIOilNPyIunNh5yqBwtgwj4SnheF8DlsmQI2TqpcyFWgjvspnvquiV7+OEBb5mFUSZeEUj5cgIgJ3VaBFIbcij0nq3TTHAvSmx+oTboAxUkg62zdPaaFV+iK9BpCNm6eGsjE1Wfp6LXzBHOZetCXJ1IgQ02mOknkW2ysztNhF4G/MMUXvDe5ApgTHshGYvkaD+StHcLt2c6Quy4DUkKeU6Djun6Dyp3foSBibBRsQK9q0yXo5ooYkoVllEaSvu94FpxBjsF+lBQJveM2Wc090EgM1An/Oc/ptMVvMmSE0mmM8RR9vM5dUZwmZHd/kECo1cvGQG1nVJZ9qWnrCeWcnJS7M9FkFucEBjFJTzh1FL3tgYKnXkS04uQLaj84byQr7f+l4l8ExsJPUriQia9829+OeiRblOdB3mEEMgHleMhE0trfre7iz5Beob5sPwTq9z7ywrRVGX8vKeDXPEmwDi+5gdYXRw3QwNP7sWAePOdpZPzUBc5fUYZh8kJB22b8zoF1T81gxME0MQOc4nCgSCETtLWih3R8sngooAXXo9kYM3zb38ijoLpPwlOmE0BR9rvcSz8BBp1bVhWZ4k4ploe5uTtb+Mg31Amj6d5I5z9/KwYJQ6Mcy3y8Ijozm7+FpDLfjz70ZjAYguurmHFZsDQJQp4fJUcOFabc= email: on_success: always on_failure: always script: - export BIBSPACE_CONFIG=lib/BibSpace/files/config/default.conf - export BIBSPACE_USE_DUMP=1 -# - PERL5OPT=-MDevel::Cover=-coverage,statement,branch,condition,path,subroutine bin/bibspace test - PERL5OPT=-MDevel::Cover=-coverage,statement,branch,condition,path,subroutine prove -lr after_success: - cover -report coveralls diff --git a/Changelog.md b/Changelog.md index ddbc318..bb6582d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,9 @@ ### Changelog ### +#### v0.5.1 08.2017 #### +* Add support for docekrizing +* Move json files to json_data directory + #### v0.5.0 05.2016 #### * remove Redis-based caching * Big refactoring diff --git a/cpanfile b/cpanfile index b5664fe..30d30bd 100644 --- a/cpanfile +++ b/cpanfile @@ -1,7 +1,7 @@ requires 'Array::Utils' , '>= 0.0'; requires 'Apache::DBI' , '>= 0.0'; requires 'Crypt::Eksblowfish::Bcrypt' , '>= 0.0'; -requires 'Crypt::Random' , '>= 0.0'; +requires 'Bytes::Random' , '>= 0.0'; requires 'Cwd' , '>= 0.0'; requires 'DBD::mysql' , '>= 0.0'; requires 'DBI', '>= 1.619'; diff --git a/lib/BibSpace.pm b/lib/BibSpace.pm index 960e0da..62c307f 100644 --- a/lib/BibSpace.pm +++ b/lib/BibSpace.pm @@ -1,4 +1,4 @@ -package BibSpace v0.5.0; +package BibSpace v0.5.1; # ABSTRACT: BibSpace is a system to manage Bibtex references for authors and research groups web page. @@ -8,7 +8,7 @@ use BibSpace::Functions::MySqlBackupFunctions; use BibSpace::Functions::FDB; use BibSpace::Functions::FPublications; -# on test server: +# on test server: # BIBSPACE_CONFIG=/etc/bibspace_test.conf BIBSPACE_USE_DUMP=0 MOJO_MODE=development hypnotoad bin/bibspace use Mojo::Base 'Mojolicious'; @@ -16,6 +16,7 @@ use Mojo::Base 'Mojolicious::Plugin::Config'; use Data::Dumper; + # use File::Slurp; use POSIX qw/strftime/; use Try::Tiny; @@ -49,40 +50,48 @@ use BibSpace::Util::Preferences; use BibSpace::Util::EntityFactory; # STATE keyword -# state declares a lexically scoped variable, just like my. -# However, those variables will never be reinitialized, -# contrary to lexical variables that are reinitialized each time their enclosing block is entered. +# state declares a lexically scoped variable, just like my. +# However, those variables will never be reinitialized, +# contrary to lexical variables that are reinitialized each time their enclosing block is entered. # See Persistent Private Variables in perlsub for details. use feature qw( state say ); - ## OBJECTS CREATED AND CONTAINED IN HAS METHODS CANNOT BE CHANGED AT RUNTIME! + has preferences => sub { - return state $prefs = Preferences->new->load_maybe; + my $self = shift; + my $file + = $self->app->home->rel_file("bibspace_preferences.json"); + return state $prefs + = Preferences->new( filename => "" . $file )->load_maybe; }; has statistics => sub { - return state $stats = Statistics->new; + my $self = shift; + my $file = $self->app->home->rel_file("bibspace_stats.json"); + say $file; + return state $stats = Statistics->new( filename => "" . $file )->load_maybe; }; has config_file => sub { - my $self = shift; - my $candidate; - $candidate = $ENV{BIBSPACE_CONFIG}; - return $candidate if defined $candidate and -e $candidate; + my $self = shift; + my $candidate; + $candidate = $ENV{BIBSPACE_CONFIG}; + return $candidate if defined $candidate and -e $candidate; - $candidate = $self->app->home->rel_file('/etc/bibspace.conf'); - return $candidate if -e $candidate; + $candidate = $self->app->home->rel_file('/etc/bibspace.conf'); + return $candidate if -e $candidate; - $candidate = $self->app->home->rel_file('lib/BibSpace/files/config/default.conf'); - return $candidate if -e $candidate; + $candidate + = $self->app->home->rel_file('lib/BibSpace/files/config/default.conf'); + return $candidate if -e $candidate; - $candidate = $self->app->home->rel_file('config/default.conf'); # for travis - return $candidate if -e $candidate; + $candidate = $self->app->home->rel_file('config/default.conf'); # for travis + return $candidate if -e $candidate; - die "Cannot find Bibspace config!"; - return; + die "Cannot find Bibspace config!"; + return; }; has get_backups_dir => sub { @@ -107,7 +116,7 @@ has get_log_dir => sub { }; # do not use this - if MySQL server dies during operation, you will be not able to reconnect! -# use helper +# use helper ## OBJECTS CREATED AND CONTAINED IN HAS METHODS CANNOT BE CHANGED AT RUNTIME! # has db => sub { # my $self = shift; @@ -118,679 +127,658 @@ has get_log_dir => sub { # }; has version => sub { - return $BibSpace::VERSION // "0.5.0"; + return $BibSpace::VERSION // "0.5.0"; }; has quick_load_fixture_filename => sub { - return 'bibspace.dat'; + my $self = shift; + return $self->app->home->rel_file('bibspace.dat'); }; # don't want to read data form DB and wait to link them every reload? # use quick_load_fixture! Useful for development and testing. # better disable it for production has use_quick_load_fixture => sub { - my $self = shift; - return if $self->mode eq 'production'; + my $self = shift; + return if $self->mode eq 'production'; - return 1 - if defined $ENV{BIBSPACE_USE_DUMP} and $ENV{BIBSPACE_USE_DUMP} == 1; - return; + return 1 + if defined $ENV{BIBSPACE_USE_DUMP} and $ENV{BIBSPACE_USE_DUMP} == 1; + return; }; -# please use only a single type of logger at once. +# please use only a single type of logger at once. # Using multiple may not be supported currently # if you really want to use multiple different loggers or state-full loggers (please don't), # then you need to move the object construction INTO the LayeredReposity and provide a helper to access it for everywhere. has logger => sub { state $logger = SimpleLogger->new() }; - has smartArrayBackend => sub { - my $self = shift; - return SmartArray->new( logger => $self->logger ); + my $self = shift; + return SmartArray->new( logger => $self->logger ); }; ## I moved this to helpers as app->attr for a while has layeredRepository => sub { - my $self = shift; - $self->app->logger->info("Building layeredRepository"); - - - my $LR = LayeredRepository->new( - logger => $self->logger, - preferences => $self->preferences, - # id_provider_class => 'DummyUidProvider', - id_provider_class => 'IntegerUidProvider', - ); + my $self = shift; + $self->app->logger->info("Building layeredRepository"); - my $smartArrayLayer = RepositoryLayer->new( - name => 'smart', - priority => 1, - creates_on_read => undef, - backendFactoryName => "SmartArrayDAOFactory", - logger => $self->logger, - handle => $self->smartArrayBackend, + + my $LR = LayeredRepository->new( + logger => $self->logger, + preferences => $self->preferences, + + # id_provider_class => 'DummyUidProvider', + id_provider_class => 'IntegerUidProvider', + ); + + my $smartArrayLayer = RepositoryLayer->new( + name => 'smart', + priority => 1, + creates_on_read => undef, + backendFactoryName => "SmartArrayDAOFactory", + logger => $self->logger, + handle => $self->smartArrayBackend, # reset_data_callback must be undef if you want to create and restore backups using Storable. - reset_data_callback => undef, - is_read => 1 + reset_data_callback => undef, + is_read => 1 + ); + $LR->add_layer($smartArrayLayer); + + if ( !$self->db ) { + $self->logger->error( + "You add SQL layer, but there is no connection to the database! Skipping this layer." + . " You need to start MySQL server and restart BibSpace to use this layer" ); - $LR->add_layer($smartArrayLayer); - - if ( !$self->db ) { - $self->logger->error( - "You add SQL layer, but there is no connection to the database! Skipping this layer." - . " You need to start MySQL server and restart BibSpace to use this layer" - ); - } - else { - my $mySQLLayer = RepositoryLayer->new( - name => 'mysql', - priority => 99, - creates_on_read => 1, - backendFactoryName => "MySQLDAOFactory", - logger => $self->logger, - handle => $self->db, - reset_data_callback => \&reset_db_data, - reset_data_callback_arguments => [ $self->db ], - ); - $LR->add_layer($mySQLLayer); - } - return $LR; + } + else { + my $mySQLLayer = RepositoryLayer->new( + name => 'mysql', + priority => 99, + creates_on_read => 1, + backendFactoryName => "MySQLDAOFactory", + logger => $self->logger, + handle => $self->db, + reset_data_callback => \&reset_db_data, + reset_data_callback_arguments => [ $self->db ], + ); + $LR->add_layer($mySQLLayer); + } + return $LR; }; # layeredRepository will not change at runtime => repo neither. has repo => sub { - my $self = shift; - return RepositoryFacade->new( lr => $self->layeredRepository ); + my $self = shift; + return RepositoryFacade->new( lr => $self->layeredRepository ); }; ################################################################ sub startup { - my $self = shift; - $self->app->logger->info("*** Starting BibSpace ***"); - + my $self = shift; + $self->app->logger->info("*** Starting BibSpace ***"); - $self->setup_config; - $self->setup_plugins; - $self->app->preferences->local_time_zone( DateTime::TimeZone->new( name => 'local' )->name ); + $self->setup_config; + $self->setup_plugins; - $self->setup_routes; - $self->setup_hooks; - $self->setup_repositories; - $self->insert_admin; + $self->app->preferences->local_time_zone( + DateTime::TimeZone->new( name => 'local' )->name ); + $self->setup_routes; + $self->setup_hooks; + $self->setup_repositories; + $self->insert_admin; - - $self->app->logger->info("Setup done."); + $self->app->logger->info("Setup done."); - $self->app->logger->info( "Using CONFIG: " . $self->app->config_file ); - $self->app->logger->info( "App home is: " . $self->app->home ); - $self->app->logger->info( "Active bst file is: " . $self->app->bst ); + $self->app->logger->info( "Using CONFIG: " . $self->app->config_file ); + $self->app->logger->info( "App home is: " . $self->app->home ); + $self->app->logger->info( "Active bst file is: " . $self->app->bst ); - ############################### - ########### SANDBOX ########### - ############################### - - # # cool! - # my $author = $self->app->entityFactory->new_Author( uid => "AabakusAston" ); - # say $author->uid; - # say $author->id; - # # say $author->preferences; + ############################### + ########### SANDBOX ########### + ############################### - # say Dumper $author; - # $self->app->repo->authors_save($author); +# # cool! +# my $author = $self->app->entityFactory->new_Author( uid => "AabakusAston" ); +# say $author->uid; +# say $author->id; +# # say $author->preferences; + # say Dumper $author; + # $self->app->repo->authors_save($author); - # my @users = $self->app->repo->users_all; - # $self->logger->warn("All users: ".@users); - # map {say $_->toString } @users; + # my @users = $self->app->repo->users_all; + # $self->logger->warn("All users: ".@users); + # map {say $_->toString } @users; - # my @users_to_delete = $self->app->repo->users_filter(sub{$_->email =~ /\@example.com/}); - # $self->logger->warn("To delete: ".@users_to_delete); - # map {say $_->toString } @users_to_delete; - # $self->app->repo->users_delete(@users_to_delete); +# my @users_to_delete = $self->app->repo->users_filter(sub{$_->email =~ /\@example.com/}); +# $self->logger->warn("To delete: ".@users_to_delete); +# map {say $_->toString } @users_to_delete; +# $self->app->repo->users_delete(@users_to_delete); - # $self->logger->info("this is info"); - # $self->logger->warn("this is warning"); - # $self->logger->error("this is error"); + # $self->logger->info("this is info"); + # $self->logger->warn("this is warning"); + # $self->logger->error("this is error"); } ################################################################ sub insert_admin { - my $self = shift; - $self->app->logger->info("Add startup admin user..."); - - my $admin_exists - = $self->app->repo->users_find( sub { $_->login eq 'pub_admin' } ); - if ( !$admin_exists ) { - my $salt = salt(); - my $hash = encrypt_password( 'asdf', $salt ); - my $new_user = $self->app->entityFactory->new_User( - login => 'pub_admin', - email => 'pub_admin@example.com', - real_name => 'Admin', - rank => 99, - pass => $hash, - pass2 => $salt - ); - $self->app->repo->users_save($new_user); - } - else { - # this email is used in tests! - $admin_exists->email('pub_admin@example.com'); - $admin_exists->make_admin; - $self->app->repo->users_update($admin_exists); - } + my $self = shift; + $self->app->logger->info("Add startup admin user..."); + + my $admin_exists + = $self->app->repo->users_find( sub { $_->login eq 'pub_admin' } ); + if ( !$admin_exists ) { + my $salt = salt(); + my $hash = encrypt_password( 'asdf', $salt ); + my $new_user = $self->app->entityFactory->new_User( + login => 'pub_admin', + email => 'pub_admin@example.com', + real_name => 'Admin', + rank => 99, + pass => $hash, + pass2 => $salt + ); + $self->app->repo->users_save($new_user); + } + else { + # this email is used in tests! + $admin_exists->email('pub_admin@example.com'); + $admin_exists->make_admin; + $self->app->repo->users_update($admin_exists); + } } ################################################################ sub setup_repositories { - my $self = shift; + my $self = shift; - $self->app->logger->info("Setup repositories..."); + $self->app->logger->info("Setup repositories..."); - if ( -e $self->quick_load_fixture_filename - and $self->use_quick_load_fixture ) - { + if ( -e $self->quick_load_fixture_filename + and $self->use_quick_load_fixture ) + { # $self->app->logger->info("Retrieving dump from '".$self->quick_load_fixture_filename."'."); - my $layer = retrieve( $self->quick_load_fixture_filename ); + my $layer = retrieve( $self->quick_load_fixture_filename ); - # reser read layer = not needed, layer empty by start of the app - # $self->app->logger->info("Replacing layer 'smart' with the dump."); - $self->repo->lr->replace_layer( 'smart', $layer ); + # reser read layer = not needed, layer empty by start of the app + # $self->app->logger->info("Replacing layer 'smart' with the dump."); + $self->repo->lr->replace_layer( 'smart', $layer ); # $self->app->logger->debug("State after replacement:".$self->repo->lr->get_summary_table); - } - else { - $self->app->logger->info( "We do not use dump file '" - . $self->quick_load_fixture_filename - . "'." ); - } + } + else { + $self->app->logger->info( "We do not use dump file '" + . $self->quick_load_fixture_filename + . "'." ); + } - # no data, no fun = no need to copy, link, and store - if ( $self->repo->entries_empty ) { - $self->app->logger->info("Repo has no entries. Reseting read_layer."); + # no data, no fun = no need to copy, link, and store + if ( $self->repo->entries_empty ) { + $self->app->logger->info("Repo has no entries. Reseting read_layer."); - $self->repo->lr->copy_data( { from => 'mysql', to => 'smart' } ); + $self->repo->lr->copy_data( { from => 'mysql', to => 'smart' } ); - # Entities and Relations in the smart layer must be linked! - $self->link_data; - - $self->app->logger->info( "Storing current state to dump file '" - . $self->quick_load_fixture_filename - . "'." ); + # Entities and Relations in the smart layer must be linked! + $self->link_data; - # store current state to file - store $self->repo->lr->get_read_layer, - $self->quick_load_fixture_filename; - } + $self->app->logger->info( "Storing current state to dump file '" + . $self->quick_load_fixture_filename + . "'." ); + + # store current state to file + store $self->repo->lr->get_read_layer, $self->quick_load_fixture_filename; + } } ################################################################ sub link_data { - my $self = shift; - $self->app->logger->info("Linking data..."); - - $self->app->logger->info("Linking Authors (N) to (1) Authors."); - foreach my $author ( - $self->repo->authors_filter( sub { $_->id != $_->master_id } ) ) - { - my $master - = $self->repo->authors_find( sub { $_->id == $author->master_id } - ); - if ( $master and $author ) { - $author->set_master($master); - } + my $self = shift; + $self->app->logger->info("Linking data..."); + + $self->app->logger->info("Linking Authors (N) to (1) Authors."); + foreach my $author ( + $self->repo->authors_filter( sub { $_->id != $_->master_id } ) ) + { + my $master + = $self->repo->authors_find( sub { $_->id == $author->master_id } ); + if ( $master and $author ) { + $author->set_master($master); } - - - $self->app->logger->info("Linking Authors (N) to (M) Entries."); - foreach my $auth ( $self->repo->authorships_all ) { - my $entry - = $self->repo->entries_find( sub { $_->id == $auth->entry_id } ); - my $author - = $self->repo->authors_find( sub { $_->id == $auth->author_id } ); - if ( $entry and $author ) { - $auth->entry($entry); - $auth->author($author); - $entry->authorships_add($auth); - $author->authorships_add($auth); - } + } + + + $self->app->logger->info("Linking Authors (N) to (M) Entries."); + foreach my $auth ( $self->repo->authorships_all ) { + my $entry + = $self->repo->entries_find( sub { $_->id == $auth->entry_id } ); + my $author + = $self->repo->authors_find( sub { $_->id == $auth->author_id } ); + if ( $entry and $author ) { + $auth->entry($entry); + $auth->author($author); + $entry->authorships_add($auth); + $author->authorships_add($auth); } - - $self->app->logger->info("Linking Tags (N) to (M) Entries."); - foreach my $labeling ( $self->repo->labelings_all ) { - my $entry - = $self->repo->entries_find( sub { $_->id == $labeling->entry_id } - ); - my $tag - = $self->repo->tags_find( sub { $_->id == $labeling->tag_id } ); - if ( $entry and $tag ) { - $labeling->entry($entry); - $labeling->tag($tag); - $entry->labelings_add($labeling); - $tag->labelings_add($labeling); - } + } + + $self->app->logger->info("Linking Tags (N) to (M) Entries."); + foreach my $labeling ( $self->repo->labelings_all ) { + my $entry + = $self->repo->entries_find( sub { $_->id == $labeling->entry_id } ); + my $tag = $self->repo->tags_find( sub { $_->id == $labeling->tag_id } ); + if ( $entry and $tag ) { + $labeling->entry($entry); + $labeling->tag($tag); + $entry->labelings_add($labeling); + $tag->labelings_add($labeling); } - - $self->app->logger->info( - "Linking Teams (Exceptions) (N) to (M) Entries."); - foreach my $exception ( $self->repo->exceptions_all ) { - my $entry = $self->repo->entries_find( - sub { $_->id == $exception->entry_id } ); - my $team - = $self->repo->teams_find( sub { $_->id == $exception->team_id } - ); - if ( $entry and $team ) { - $exception->entry($entry); - $exception->team($team); - $entry->exceptions_add($exception); - $team->exceptions_add($exception); - } + } + + $self->app->logger->info("Linking Teams (Exceptions) (N) to (M) Entries."); + foreach my $exception ( $self->repo->exceptions_all ) { + my $entry + = $self->repo->entries_find( sub { $_->id == $exception->entry_id } ); + my $team + = $self->repo->teams_find( sub { $_->id == $exception->team_id } ); + if ( $entry and $team ) { + $exception->entry($entry); + $exception->team($team); + $entry->exceptions_add($exception); + $team->exceptions_add($exception); } + } - $self->app->logger->info("Linking Teams (N) to (M) Authors."); - foreach my $membership ( $self->repo->memberships_all ) { - my $author = $self->repo->authors_find( - sub { $_->id == $membership->author_id } ); - my $team - = $self->repo->teams_find( sub { $_->id == $membership->team_id } - ); - if ( defined $author and defined $team ) { - $membership->author($author); - $membership->team($team); - $author->memberships_add($membership); - $team->memberships_add($membership); - } + $self->app->logger->info("Linking Teams (N) to (M) Authors."); + foreach my $membership ( $self->repo->memberships_all ) { + my $author + = $self->repo->authors_find( sub { $_->id == $membership->author_id } + ); + my $team + = $self->repo->teams_find( sub { $_->id == $membership->team_id } ); + if ( defined $author and defined $team ) { + $membership->author($author); + $membership->team($team); + $author->memberships_add($membership); + $team->memberships_add($membership); } + } - $self->app->logger->info("Linking TagTypes (N) to (1) Tags."); - foreach my $tag ( $self->repo->tags_all ) { - my $tagtype - = $self->repo->tagTypes_find( sub { $_->id == $tag->type } ); - if ( $tag and $tagtype ) { - $tag->tagtype($tagtype); - } + $self->app->logger->info("Linking TagTypes (N) to (1) Tags."); + foreach my $tag ( $self->repo->tags_all ) { + my $tagtype = $self->repo->tagTypes_find( sub { $_->id == $tag->type } ); + if ( $tag and $tagtype ) { + $tag->tagtype($tagtype); } + } - $self->app->logger->info("TODO: Linking OurTypes (N) to (1) Entries."); + $self->app->logger->info("TODO: Linking OurTypes (N) to (1) Entries."); - $self->app->logger->info("Linking Finished."); + $self->app->logger->info("Linking Finished."); } ################################################################ sub setup_config { - my $self = shift; - my $app = $self; - $self->app->logger->info("Setup config..."); - $self->plugin( 'Config' => { file => $self->app->config_file } ); - - $ENV{MOJO_MAX_MESSAGE_SIZE} = 40 * 1024 * 1024; - $self->app->logger->info( "Setting max upload size to " - . $ENV{MOJO_MAX_MESSAGE_SIZE} - . " Bytes." ); + my $self = shift; + my $app = $self; + $self->app->logger->info("Setup config..."); + $self->plugin( 'Config' => { file => $self->app->config_file } ); + + $ENV{MOJO_MAX_MESSAGE_SIZE} = 40 * 1024 * 1024; + $self->app->logger->info( + "Setting max upload size to " . $ENV{MOJO_MAX_MESSAGE_SIZE} . " Bytes." ); } ################################################################ sub setup_plugins { - my $self = shift; - $self->app->logger->info("Setup plugins..."); - - $ENV{MOJO_REVERSE_PROXY} = 1; - - $self->app->plugin('InstallablePaths'); - $self->app->plugin('RenderFile'); - $self->plugin('BibSpace::Controller::Helpers'); - - push @{ $self->app->static->paths }, $self->app->home->rel_file('public'); - - # push @{$self->app->static->paths}, $self->config->{backups_dir}; - - $self->app->logger->info("App version: " . $self->app->version); - $self->app->logger->info("Creating directories..."); - for my $dir ( ( $self->app->get_backups_dir, - $self->app->get_upload_dir, - $self->app->get_upload_dir."papers", - $self->app->get_upload_dir."slides", - $self->app->get_log_dir) ) - { - $self->app->logger->debug("Creating directory: $dir"); - try { - Path::Tiny->new($dir)->mkpath; - } - catch { - $self->app->logger->error("Exception: cannot create directory $dir. Msg: $_"); - }; + my $self = shift; + $self->app->logger->info("Setup plugins..."); + + $ENV{MOJO_REVERSE_PROXY} = 1; + + $self->app->plugin('InstallablePaths'); + $self->app->plugin('RenderFile'); + $self->plugin('BibSpace::Controller::Helpers'); + + push @{ $self->app->static->paths }, $self->app->home->rel_file('public'); + + # push @{$self->app->static->paths}, $self->config->{backups_dir}; + + $self->app->logger->info( "App version: " . $self->app->version ); + $self->app->logger->info("Creating directories..."); + for my $dir ( + ( $self->app->get_backups_dir, + $self->app->get_upload_dir, + $self->app->get_upload_dir . "papers", + $self->app->get_upload_dir . "slides", + $self->app->get_log_dir + ) + ) + { + $self->app->logger->debug("Creating directory: $dir"); + try { + Path::Tiny->new($dir)->mkpath; } + catch { + $self->app->logger->error( + "Exception: cannot create directory $dir. Msg: $_"); + }; + } - # set logging dir in the logger - $self->app->logger->debug("Setting log dir to the logger"); - $self->logger->set_log_dir("".Path::Tiny->new($self->get_log_dir) ); + # set logging dir in the logger + $self->app->logger->debug("Setting log dir to the logger"); + $self->logger->set_log_dir( "" . Path::Tiny->new( $self->get_log_dir ) ); + # this is supposed to trigger connection to the DB + $self->app->db; - # this is supposed to trigger connection to the DB - $self->app->db; - - - $self->secrets( [ $self->config->{key_cookie} ] ); - - $self->helper( proxy_prefix => sub { $self->config->{proxy_prefix} } ); + $self->secrets( [ $self->config->{key_cookie} ] ); + $self->helper( proxy_prefix => sub { $self->config->{proxy_prefix} } ); } ################################################################ ################################################################ sub setup_routes { - my $self = shift; - $self->app->logger->info("Setup routes..."); - - my $anyone = $self->routes; - $anyone->get('/')->to('display#index')->name('start'); - - - $anyone->get('/forgot')->to('login#forgot'); - $anyone->post('/forgot/gen')->to('login#post_gen_forgot_token'); - $anyone->get('/forgot/reset/:token')->to('login#token_clicked') - ->name("token_clicked"); - $anyone->post('/forgot/store')->to('login#store_password'); - - $anyone->get('/login_form')->to('login#login_form')->name('login_form'); - $anyone->post('/do_login')->to('login#login')->name('do_login'); - $anyone->get('/youneedtologin')->to('login#not_logged_in') - ->name('youneedtologin'); - $anyone->get('/badpassword')->to('login#bad_password') - ->name('badpassword'); - - $anyone->get('/logout')->to('login#logout')->name('logout'); - - $anyone->any('/test/500')->to('display#test500')->name('error500'); - $anyone->any('/test/404')->to('display#test404')->name('error404'); - - $anyone->get('/register')->to('login#register')->name('register'); - $anyone->post('/register')->to('login#post_do_register') - ->name('post_do_register'); - $anyone->any('/noregister')->to('login#register_disabled'); - - my $logged_user = $anyone->under->to('login#check_is_logged_in'); - my $manager_user - = $logged_user->under->to('login#under_check_is_manager'); - my $admin_user = $logged_user->under->to('login#under_check_is_admin'); - - ################ PREFERENCES ################ - - $manager_user->get('/preferences')->to('preferences#index')->name('preferences'); - $admin_user->post('/preferences')->to('preferences#save')->name('save_preferences'); - - ################ EXPERIMENTAL / PERSISTENCE ################ - - $anyone->get('/system_status')->to('persistence#system_status') - ->name('system_status'); - $admin_user->get('/persistence/load')->to('persistence#load_fixture') - ->name('load_fixture'); - $admin_user->get('/persistence/save')->to('persistence#save_fixture') - ->name('save_fixture'); - $admin_user->get('/persistence/copy_mysql_to_smart') - ->to('persistence#copy_mysql_to_smart')->name('copy_mysql_to_smart'); - $admin_user->get('/persistence/copy_smart_to_mysql') - ->to('persistence#copy_smart_to_mysql')->name('copy_smart_to_mysql'); - - $admin_user->get('/persistence/persistence_status') - ->to('persistence#persistence_status')->name('persistence_status'); - $admin_user->get('/persistence/persistence_status_ajax') - ->to('persistence#persistence_status_ajax')->name('persistence_status_ajax'); - - - $admin_user->get('/persistence/reset_mysql') - ->to('persistence#reset_mysql')->name('reset_mysql'); - $admin_user->get('/persistence/reset_smart') - ->to('persistence#reset_smart')->name('reset_smart'); - $admin_user->get('/persistence/reset_all') - ->to('persistence#reset_all')->name('reset_all'); - - $admin_user->get('/persistence/insert_random_data') - ->to('persistence#insert_random_data')->name('insert_random_data'); - - - - ################ SETTINGS ################ - $logged_user->get('/profile')->to('login#profile'); - $admin_user->get('/manage_users')->to('login#manage_users') - ->name('manage_users'); - $admin_user->get('/profile/:id')->to('login#foreign_profile') - ->name('show_user_profile'); - $admin_user->get('/profile/delete/:id')->to('login#delete_user') - ->name('delete_user'); - - $admin_user->get('/profile/make_user/:id')->to('login#make_user') - ->name('make_user'); - $admin_user->get('/profile/make_manager/:id')->to('login#make_manager') - ->name('make_manager'); - $admin_user->get('/profile/make_admin/:id')->to('login#make_admin') - ->name('make_admin'); - - $manager_user->get('/log')->to('display#show_log')->name('show_log'); - # websocket for fun - $manager_user->websocket('/log_websocket/:num')->to('display#show_log_ws')->name('show_log_websocket'); - $manager_user->websocket('/statistics/:num')->to('display#show_stats_websocket')->name('show_stats_websocket'); - - - + my $self = shift; + $self->app->logger->info("Setup routes..."); + + my $anyone = $self->routes; + $anyone->get('/')->to('display#index')->name('start'); + + + $anyone->get('/forgot')->to('login#forgot'); + $anyone->post('/forgot/gen')->to('login#post_gen_forgot_token'); + $anyone->get('/forgot/reset/:token')->to('login#token_clicked') + ->name("token_clicked"); + $anyone->post('/forgot/store')->to('login#store_password'); + + $anyone->get('/login_form')->to('login#login_form')->name('login_form'); + $anyone->post('/do_login')->to('login#login')->name('do_login'); + $anyone->get('/youneedtologin')->to('login#not_logged_in') + ->name('youneedtologin'); + $anyone->get('/badpassword')->to('login#bad_password')->name('badpassword'); + + $anyone->get('/logout')->to('login#logout')->name('logout'); - $admin_user->get('/settings/fix_months') - ->to('publications#fixMonths') - ->name('fix_all_months'); - - $manager_user->get('/settings/clean_all') - ->to('publications#clean_ugly_bibtex') - ->name('clean_ugly_bibtex'); - - $manager_user->get('/settings/mark_all_to_regenerate') - ->to('publications#mark_all_to_regenerate') - ->name('mark_all_to_regenerate'); - - $manager_user->get('/settings/mark_author_to_regenerate/:author_id') - ->to('publications#mark_author_to_regenerate') - ->name('mark_author_to_regenerate'); - - $manager_user->get('/settings/regenerate_all') - ->to('publications#regenerate_html_for_all') - ->name('regenerate_html_for_all'); - - $logged_user->get('/settings/regenerate_html_in_chunk/:chunk_size') - ->to('publications#regenerate_html_in_chunk') - ->name('regenerate_html_in_chunk'); - - - - - - - $manager_user->get('/backups') - ->to('backup#index')->name('backup_index'); - $manager_user->put('/backups') - ->to('backup#save')->name('backup_do'); - $manager_user->put('/backups/mysql') - ->to('backup#save_mysql')->name('backup_do_mysql'); - $manager_user->get('/backups/:id') - ->to('backup#backup_download')->name('backup_download'); - - $admin_user->delete('/backups/:id') - ->to('backup#delete_backup')->name('backup_delete'); - $admin_user->put('/backups/:id') - ->to('backup#restore_backup')->name('backup_restore'); - $admin_user->delete('/backups') - ->to('backup#cleanup')->name('backup_cleanup'); - - - ################ TYPES ################ - $logged_user->get('/types')->to('types#all_our')->name('all_types'); - $manager_user->get('/types/add')->to('types#add_type') - ->name('add_type_get'); - $manager_user->post('/types/add')->to('types#post_add_type') - ->name('add_type_post'); - $manager_user->get('/types/manage/:name')->to('types#manage') - ->name('edit_type'); - $manager_user->get('/types/delete/:name')->to('types#delete_type') - ->name('delete_type'); - - $manager_user->post('/types/store_description') - ->to('types#post_store_description')->name('update_type_description'); - $manager_user->get('/types/toggle/:name')->to('types#toggle_landing') - ->name('toggle_landing_type'); - - $manager_user->get('/types/:our_type/map/:bibtex_type') - ->to('types#map_types'); - $manager_user->get('/types/:our_type/unmap/:bibtex_type') - ->to('types#unmap_types')->name('unmap_bibtex_type'); - - ################ AUTHORS ################ - - $logged_user->get('/authors/')->to('authors#all_authors') - ->name('all_authors'); - $manager_user->get('/authors/add')->to('authors#add_author') - ->name('add_author'); - $manager_user->post('/authors/add/')->to('authors#add_post'); - - $logged_user->get('/authors/edit/:id')->to('authors#edit_author') - ->name('edit_author'); - $manager_user->post('/authors/edit/')->to('authors#edit_post') - ->name('edit_author_post'); - $manager_user->get('/authors/delete/:id')->to('authors#delete_author') - ->name('delete_author'); - - - $admin_user->get('/authors/delete/:id/force') - ->to('authors#delete_author_force'); - - - - # for dev only!! - $admin_user->get('/authors/decimate') - ->to('authors#delete_invisible_authors'); - - - - - - $manager_user->post('/authors/edit_membership_dates') - ->to('authors#post_edit_membership_dates') - ->name('edit_author_membership_dates'); - - $manager_user->get('/authors/:id/add_to_team/:tid') - ->to('authors#add_to_team')->name('add_author_to_team'); - $manager_user->get('/authors/:id/remove_from_team/:tid') - ->to('authors#remove_from_team')->name('remove_author_from_team'); - $manager_user->get('/authors/:masterid/remove_uid/:uid') - ->to('authors#remove_uid')->name('remove_author_uid'); - - $manager_user->post('/authors/merge/')->to('authors#merge_authors') - ->name('merge_authors'); - - $admin_user->get('/authors/fix_masters') - ->to('authors#fix_masters')->name('fix_masters'); - - $manager_user->get('/authors/reassign') - ->to('authors#reassign_authors_to_entries'); - $admin_user->get('/authors/reassign_and_create') - ->to('authors#reassign_authors_to_entries_and_create_authors'); - - $manager_user->get('/authors/toggle_visibility/:id') - ->to('authors#toggle_visibility')->name('toggle_author_visibility'); - - # $logged_user->get('/authors/toggle_visibility') - # ->to('authors#toggle_visibility'); - - ################ TAG TYPES ################ - # $logged_user->get('/tags/')->to('tags#index')->name("tags_index"); - $logged_user->get('/tagtypes')->to('tagtypes#index') - ->name('all_tag_types'); - $admin_user->get('/tagtypes/add')->to('tagtypes#add') - ->name('add_tag_type'); - $admin_user->post('/tagtypes/add')->to('tagtypes#add_post') - ->name('add_tag_type_post'); - $admin_user->get('/tagtypes/delete/:id')->to('tagtypes#delete') - ->name('delete_tag_type'); - $manager_user->any('/tagtypes/edit/:id')->to('tagtypes#edit') - ->name('edit_tag_type'); - - ################ TAGS ################ - $logged_user->get('/tags/:type')->to( 'tags#index', type => 1 ) - ->name('all_tags'); - $admin_user->get('/tags/add/:type')->to( 'tags#add', type => 1 ) - ->name('add_tag_get'); - $admin_user->post('/tags/add/:type')->to( 'tags#add_post', type => 1 ) - ->name('add_tag_post'); - $logged_user->get('/tags/authors/:id/:type') - ->to( 'tags#get_authors_for_tag', type => 1 ) - ->name('get_authors_for_tag'); - $admin_user->get('/tags/delete/:id')->to('tags#delete') - ->name('delete_tag'); - - ### EDIT TAG FORM GOES WITH GET - WTF!?! - # FIXME: FIX THIS - $manager_user->get('/tags/edit/:id')->to('tags#edit')->name('edit_tag'); - - $anyone->get('/read/authors-for-tag/:tag_id/:team_id') - ->to('tags#get_authors_for_tag_and_team') - ->name('get_authors_for_tag_and_team'); - - #ALIAS - $anyone->get('/r/a4t/:tag_id/:team_id') - ->to('tags#get_authors_for_tag_and_team') - ->name('get_authors_for_tag_and_team'); - - $anyone->get('/read/authors-for-tag/:tag_id/:team_id') - ->to('tags#get_authors_for_tag_and_team') - ->name('get_authors_for_tag_and_team'); - - #ALIAS - $anyone->get('/r/a4t/:tag_id/:team_id') - ->to('tags#get_authors_for_tag_and_team') - ->name('get_authors_for_tag_and_team'); - - $anyone->get('/read/tags-for-author/:author_id') - ->to('tags#get_tags_for_author_read')->name('tags_for_author'); - - #ALIAS - $anyone->get('/r/t4a/:author_id')->to('tags#get_tags_for_author_read'); - - $anyone->get('/read/tags-for-team/:team_id') - ->to('tags#get_tags_for_team_read')->name('tags_for_team'); - - #ALIAS - $anyone->get('/r/t4t/:team_id')->to('tags#get_tags_for_team_read'); - - ################ TEAMS ################ - $logged_user->get('/teams')->to('teams#show')->name('all_teams'); - $logged_user->get('/teams/members/:teamid')->to('teams#team_members'); - - $manager_user->get('/teams/edit/:id')->to('teams#edit') - ->name('edit_team'); - $manager_user->get('/teams/delete/:id')->to('teams#delete_team') - ->name('delete_team'); - $manager_user->get('/teams/delete/:id/force') - ->to('teams#delete_team_force')->name('delete_team_force'); - $logged_user->get('/teams/unrealted_papers/:teamid') - ->to('publications#show_unrelated_to_team') - ->name('unrelated_papers_for_team'); - - $manager_user->get('/teams/add')->to('teams#add_team') - ->name('add_team_get'); - $manager_user->post('/teams/add/')->to('teams#add_team_post'); - - ################ EDITING PUBLICATIONS ################ + $anyone->any('/test/500')->to('display#test500')->name('error500'); + $anyone->any('/test/404')->to('display#test404')->name('error404'); + + $anyone->get('/register')->to('login#register')->name('register'); + $anyone->post('/register')->to('login#post_do_register') + ->name('post_do_register'); + $anyone->any('/noregister')->to('login#register_disabled'); + + my $logged_user = $anyone->under->to('login#check_is_logged_in'); + my $manager_user = $logged_user->under->to('login#under_check_is_manager'); + my $admin_user = $logged_user->under->to('login#under_check_is_admin'); + + ################ PREFERENCES ################ + + $manager_user->get('/preferences')->to('preferences#index') + ->name('preferences'); + $admin_user->post('/preferences')->to('preferences#save') + ->name('save_preferences'); + + ################ EXPERIMENTAL / PERSISTENCE ################ + + $anyone->get('/system_status')->to('persistence#system_status') + ->name('system_status'); + $admin_user->get('/persistence/load')->to('persistence#load_fixture') + ->name('load_fixture'); + $admin_user->get('/persistence/save')->to('persistence#save_fixture') + ->name('save_fixture'); + $admin_user->get('/persistence/copy_mysql_to_smart') + ->to('persistence#copy_mysql_to_smart')->name('copy_mysql_to_smart'); + $admin_user->get('/persistence/copy_smart_to_mysql') + ->to('persistence#copy_smart_to_mysql')->name('copy_smart_to_mysql'); + + $admin_user->get('/persistence/persistence_status') + ->to('persistence#persistence_status')->name('persistence_status'); + $admin_user->get('/persistence/persistence_status_ajax') + ->to('persistence#persistence_status_ajax') + ->name('persistence_status_ajax'); + + + $admin_user->get('/persistence/reset_mysql')->to('persistence#reset_mysql') + ->name('reset_mysql'); + $admin_user->get('/persistence/reset_smart')->to('persistence#reset_smart') + ->name('reset_smart'); + $admin_user->get('/persistence/reset_all')->to('persistence#reset_all') + ->name('reset_all'); + + $admin_user->get('/persistence/insert_random_data') + ->to('persistence#insert_random_data')->name('insert_random_data'); + + + ################ SETTINGS ################ + $logged_user->get('/profile')->to('login#profile'); + $admin_user->get('/manage_users')->to('login#manage_users') + ->name('manage_users'); + $admin_user->get('/profile/:id')->to('login#foreign_profile') + ->name('show_user_profile'); + $admin_user->get('/profile/delete/:id')->to('login#delete_user') + ->name('delete_user'); + + $admin_user->get('/profile/make_user/:id')->to('login#make_user') + ->name('make_user'); + $admin_user->get('/profile/make_manager/:id')->to('login#make_manager') + ->name('make_manager'); + $admin_user->get('/profile/make_admin/:id')->to('login#make_admin') + ->name('make_admin'); + + $manager_user->get('/log')->to('display#show_log')->name('show_log'); + $manager_user->get('/statistics')->to('display#show_stats') + ->name('show_stats'); + + # websocket for fun + $manager_user->websocket('/log_websocket/:num')->to('display#show_log_ws') + ->name('show_log_websocket'); + $manager_user->websocket('/statistics/:num') + ->to('display#show_stats_websocket')->name('show_stats_websocket'); + + + $admin_user->get('/settings/fix_months')->to('publications#fixMonths') + ->name('fix_all_months'); + + $manager_user->get('/settings/clean_all') + ->to('publications#clean_ugly_bibtex')->name('clean_ugly_bibtex'); + + $manager_user->get('/settings/mark_all_to_regenerate') + ->to('publications#mark_all_to_regenerate') + ->name('mark_all_to_regenerate'); + + $manager_user->get('/settings/mark_author_to_regenerate/:author_id') + ->to('publications#mark_author_to_regenerate') + ->name('mark_author_to_regenerate'); + + $manager_user->get('/settings/regenerate_all') + ->to('publications#regenerate_html_for_all') + ->name('regenerate_html_for_all'); + + $logged_user->get('/settings/regenerate_html_in_chunk/:chunk_size') + ->to('publications#regenerate_html_in_chunk') + ->name('regenerate_html_in_chunk'); + + + $manager_user->get('/backups')->to('backup#index')->name('backup_index'); + $manager_user->put('/backups')->to('backup#save')->name('backup_do'); + $manager_user->put('/backups/mysql')->to('backup#save_mysql') + ->name('backup_do_mysql'); + $manager_user->get('/backups/:id')->to('backup#backup_download') + ->name('backup_download'); + + $admin_user->delete('/backups/:id')->to('backup#delete_backup') + ->name('backup_delete'); + $admin_user->put('/backups/:id')->to('backup#restore_backup') + ->name('backup_restore'); + $admin_user->delete('/backups')->to('backup#cleanup') + ->name('backup_cleanup'); + + + ################ TYPES ################ + $logged_user->get('/types')->to('types#all_our')->name('all_types'); + $manager_user->get('/types/add')->to('types#add_type') + ->name('add_type_get'); + $manager_user->post('/types/add')->to('types#post_add_type') + ->name('add_type_post'); + $manager_user->get('/types/manage/:name')->to('types#manage') + ->name('edit_type'); + $manager_user->get('/types/delete/:name')->to('types#delete_type') + ->name('delete_type'); + + $manager_user->post('/types/store_description') + ->to('types#post_store_description')->name('update_type_description'); + $manager_user->get('/types/toggle/:name')->to('types#toggle_landing') + ->name('toggle_landing_type'); + + $manager_user->get('/types/:our_type/map/:bibtex_type') + ->to('types#map_types'); + $manager_user->get('/types/:our_type/unmap/:bibtex_type') + ->to('types#unmap_types')->name('unmap_bibtex_type'); + + ################ AUTHORS ################ + + $logged_user->get('/authors/')->to('authors#all_authors') + ->name('all_authors'); + $manager_user->get('/authors/add')->to('authors#add_author') + ->name('add_author'); + $manager_user->post('/authors/add/')->to('authors#add_post'); + + $logged_user->get('/authors/edit/:id')->to('authors#edit_author') + ->name('edit_author'); + $manager_user->post('/authors/edit/')->to('authors#edit_post') + ->name('edit_author_post'); + $manager_user->get('/authors/delete/:id')->to('authors#delete_author') + ->name('delete_author'); + + + $admin_user->get('/authors/delete/:id/force') + ->to('authors#delete_author_force'); + + + # for dev only!! + $admin_user->get('/authors/decimate') + ->to('authors#delete_invisible_authors'); + + + $manager_user->post('/authors/edit_membership_dates') + ->to('authors#post_edit_membership_dates') + ->name('edit_author_membership_dates'); + + $manager_user->get('/authors/:id/add_to_team/:tid') + ->to('authors#add_to_team')->name('add_author_to_team'); + $manager_user->get('/authors/:id/remove_from_team/:tid') + ->to('authors#remove_from_team')->name('remove_author_from_team'); + $manager_user->get('/authors/:masterid/remove_uid/:uid') + ->to('authors#remove_uid')->name('remove_author_uid'); + + $manager_user->post('/authors/merge/')->to('authors#merge_authors') + ->name('merge_authors'); + + $admin_user->get('/authors/fix_masters')->to('authors#fix_masters') + ->name('fix_masters'); + + $manager_user->get('/authors/reassign') + ->to('authors#reassign_authors_to_entries'); + $admin_user->get('/authors/reassign_and_create') + ->to('authors#reassign_authors_to_entries_and_create_authors'); + + $manager_user->get('/authors/toggle_visibility/:id') + ->to('authors#toggle_visibility')->name('toggle_author_visibility'); + + # $logged_user->get('/authors/toggle_visibility') + # ->to('authors#toggle_visibility'); + + ################ TAG TYPES ################ + # $logged_user->get('/tags/')->to('tags#index')->name("tags_index"); + $logged_user->get('/tagtypes')->to('tagtypes#index')->name('all_tag_types'); + $admin_user->get('/tagtypes/add')->to('tagtypes#add')->name('add_tag_type'); + $admin_user->post('/tagtypes/add')->to('tagtypes#add_post') + ->name('add_tag_type_post'); + $admin_user->get('/tagtypes/delete/:id')->to('tagtypes#delete') + ->name('delete_tag_type'); + $manager_user->any('/tagtypes/edit/:id')->to('tagtypes#edit') + ->name('edit_tag_type'); + + ################ TAGS ################ + $logged_user->get('/tags/:type')->to( 'tags#index', type => 1 ) + ->name('all_tags'); + $admin_user->get('/tags/add/:type')->to( 'tags#add', type => 1 ) + ->name('add_tag_get'); + $admin_user->post('/tags/add/:type')->to( 'tags#add_post', type => 1 ) + ->name('add_tag_post'); + $logged_user->get('/tags/authors/:id/:type') + ->to( 'tags#get_authors_for_tag', type => 1 ) + ->name('get_authors_for_tag'); + $admin_user->get('/tags/delete/:id')->to('tags#delete')->name('delete_tag'); + + ### EDIT TAG FORM GOES WITH GET - WTF!?! + # FIXME: FIX THIS + $manager_user->get('/tags/edit/:id')->to('tags#edit')->name('edit_tag'); + + $anyone->get('/read/authors-for-tag/:tag_id/:team_id') + ->to('tags#get_authors_for_tag_and_team') + ->name('get_authors_for_tag_and_team'); + + #ALIAS + $anyone->get('/r/a4t/:tag_id/:team_id') + ->to('tags#get_authors_for_tag_and_team') + ->name('get_authors_for_tag_and_team'); + + $anyone->get('/read/authors-for-tag/:tag_id/:team_id') + ->to('tags#get_authors_for_tag_and_team') + ->name('get_authors_for_tag_and_team'); + + #ALIAS + $anyone->get('/r/a4t/:tag_id/:team_id') + ->to('tags#get_authors_for_tag_and_team') + ->name('get_authors_for_tag_and_team'); + + $anyone->get('/read/tags-for-author/:author_id') + ->to('tags#get_tags_for_author_read')->name('tags_for_author'); + + #ALIAS + $anyone->get('/r/t4a/:author_id')->to('tags#get_tags_for_author_read'); + + $anyone->get('/read/tags-for-team/:team_id') + ->to('tags#get_tags_for_team_read')->name('tags_for_team'); + + #ALIAS + $anyone->get('/r/t4t/:team_id')->to('tags#get_tags_for_team_read'); + + ################ TEAMS ################ + $logged_user->get('/teams')->to('teams#show')->name('all_teams'); + $logged_user->get('/teams/members/:teamid')->to('teams#team_members'); + + $manager_user->get('/teams/edit/:id')->to('teams#edit')->name('edit_team'); + $manager_user->get('/teams/delete/:id')->to('teams#delete_team') + ->name('delete_team'); + $manager_user->get('/teams/delete/:id/force') + ->to('teams#delete_team_force')->name('delete_team_force'); + $logged_user->get('/teams/unrealted_papers/:teamid') + ->to('publications#show_unrelated_to_team') + ->name('unrelated_papers_for_team'); + + $manager_user->get('/teams/add')->to('teams#add_team') + ->name('add_team_get'); + $manager_user->post('/teams/add/')->to('teams#add_team_post'); + + ################ EDITING PUBLICATIONS ################ #<<< no perltidy here # EXPERIMENTAL @@ -1013,39 +1001,38 @@ sub setup_routes { ################################################################ sub setup_hooks { - my $self = shift; - $self->app->logger->info("Setup hooks..."); - - # $self->hook(after_render => sub { - # my ($c, $args) = @_; - # $c->push_url_history; - # # say "History of visisited URLS ".$c->get_url_history.":\n".join("\n", $c->get_url_history); - # }); - - $self->hook( - before_dispatch => sub { - my $c = shift; - - if( $c->req->headers->header('X-Forwarded-HTTPS') ){ - $c->req->url->base->scheme('https'); - } - $c->app->statistics->log_url($c->req->url); - - - # dirty fix for production deployment in a directory - # config->{proxy_prefix} stores the proxy prefix, e.g., /app - my $proxy_prefix = $self->config->{proxy_prefix}; - if ( $proxy_prefix ne "" ) { - - # we remove the leading slash - $proxy_prefix =~ s!^/!!; - - # and let Mojolicious add it again - push @{ $c->req->url->base->path->trailing_slash(1) }, - $proxy_prefix; - } - } - ); + my $self = shift; + $self->app->logger->info("Setup hooks..."); + +# $self->hook(after_render => sub { +# my ($c, $args) = @_; +# $c->push_url_history; +# # say "History of visisited URLS ".$c->get_url_history.":\n".join("\n", $c->get_url_history); +# }); + + $self->hook( + before_dispatch => sub { + my $c = shift; + + if ( $c->req->headers->header('X-Forwarded-HTTPS') ) { + $c->req->url->base->scheme('https'); + } + $c->app->statistics->log_url( $c->req->url ); + + + # dirty fix for production deployment in a directory + # config->{proxy_prefix} stores the proxy prefix, e.g., /app + my $proxy_prefix = $self->config->{proxy_prefix}; + if ( $proxy_prefix ne "" ) { + + # we remove the leading slash + $proxy_prefix =~ s!^/!!; + + # and let Mojolicious add it again + push @{ $c->req->url->base->path->trailing_slash(1) }, $proxy_prefix; + } + } + ); } 1; diff --git a/lib/BibSpace/Controller/Backup.pm b/lib/BibSpace/Controller/Backup.pm index 81abbeb..e8881d9 100644 --- a/lib/BibSpace/Controller/Backup.pm +++ b/lib/BibSpace/Controller/Backup.pm @@ -4,9 +4,10 @@ use Data::Dumper; use utf8; use Text::BibTeX; # parsing bib files use DateTime; + # use File::Slurp; -use v5.16; +use v5.16; use Try::Tiny; use strict; use warnings; @@ -18,6 +19,7 @@ use List::Util qw(first); use BibSpace::Functions::Core; use BibSpace::Functions::MySqlBackupFunctions; use BibSpace::Functions::BackupFunctions; + # use BibSpace::Functions::FDB; use BibSpace::Model::Backup; @@ -28,154 +30,189 @@ use Mojo::Base 'Mojolicious::Plugin::Config'; use Mojo::Log; - - #################################################################################### sub index { - my $self = shift; - my $dbh = $self->app->db; - - my $backup_dir = $self->app->get_backups_dir; - my $dir_size = get_dir_size($backup_dir); - $dir_size = $dir_size >> 20; - - my @backups_arr = sort {$b->date cmp $a->date} read_backups($backup_dir); - - foreach my $backup (@backups_arr){ - if( $backup->get_age->days >= $self->app->config->{allow_delete_backups_older_than}){ - $backup->allow_delete(1); - } - else{ - $backup->allow_delete(undef); - } + my $self = shift; + my $dbh = $self->app->db; + + my $backup_dir = $self->app->get_backups_dir; + my $dir_size = get_dir_size($backup_dir); + $dir_size = $dir_size >> 20; + + my @backups_arr = sort { $b->date cmp $a->date } read_backups($backup_dir); + + foreach my $backup (@backups_arr) { + if ( $backup->get_age->days + >= $self->app->config->{allow_delete_backups_older_than} ) + { + $backup->allow_delete(1); } + else { + $backup->allow_delete(undef); + } + } - $self->stash( - backups_arr => \@backups_arr, - dir_size => $dir_size - ); - $self->render( template => 'backup/backup' ); + $self->stash( backups_arr => \@backups_arr, dir_size => $dir_size ); + $self->render( template => 'backup/backup' ); } #################################################################################### sub save { - my $self = shift; + my $self = shift; - my $backup = do_storable_backup($self->app); + my $backup = do_storable_backup( $self->app ); - if ( $backup->is_healthy ) { - $self->flash( msg_type=>'success', msg => "Backup created successfully" ); - } - else { - $self->flash(msg_type=>'danger', msg => "Backup create failed!" ); - } - $self->redirect_to( 'backup_index' ); + if ( $backup->is_healthy ) { + $self->flash( + msg_type => 'success', + msg => "Backup created successfully" + ); + } + else { + $self->flash( msg_type => 'danger', msg => "Backup create failed!" ); + } + $self->redirect_to('backup_index'); } #################################################################################### sub save_mysql { - my $self = shift; + my $self = shift; - my $backup = do_mysql_backup($self->app); + my $backup = do_mysql_backup( $self->app ); - if ( $backup->is_healthy ) { - $self->flash( msg_type=>'success', msg => "Backup created successfully" ); - } - else { - $self->flash(msg_type=>'danger', msg => "Backup create failed!" ); - } - $self->redirect_to( 'backup_index' ); + if ( $backup->is_healthy ) { + $self->flash( + msg_type => 'success', + msg => "Backup created successfully" + ); + } + else { + $self->flash( msg_type => 'danger', msg => "Backup create failed!" ); + } + $self->redirect_to('backup_index'); } #################################################################################### sub cleanup { - my $self = shift; - my $age_treshold = $self->config->{backup_age_in_days_to_delete_automatically}; - - my $num_deleted = delete_old_backups($self->app, $age_treshold); - - $self->app->logger->info("Deleting old backups. $num_deleted backups have been cleaned."); - $self->flash( msg_type=>'success', msg => "$num_deleted backups have been cleaned." ); - - # redirecting to referrer here breaks the test if the test supports redirects! why? - # disabling redirects for test and putting here referrer allows test to pass - $self->redirect_to( 'backup_index' ); + my $self = shift; + my $age_treshold + = $self->config->{backup_age_in_days_to_delete_automatically}; + + my $num_deleted = delete_old_backups( $self->app, $age_treshold ); + + $self->app->logger->info( + "Deleting old backups. $num_deleted backups have been cleaned."); + $self->flash( + msg_type => 'success', + msg => "$num_deleted backups have been cleaned." + ); + +# redirecting to referrer here breaks the test if the test supports redirects! why? +# disabling redirects for test and putting here referrer allows test to pass + $self->redirect_to('backup_index'); } #################################################################################### sub backup_download { - my $self = shift; - my $uuid = $self->param('id'); + my $self = shift; + my $uuid = $self->param('id'); + + my $backup = find_backup( $uuid, $self->app->get_backups_dir ); + + if ( $backup and $backup->is_healthy ) { + $self->app->logger->info( "Downloading backup " . $backup->uuid ); + $self->render_file( 'filepath' => $backup->get_path ); + } + else { + $self->flash( + msg_type => 'danger', + msg => "Cannot download backup $uuid - backup not healthy." + ); + $self->redirect_to( $self->get_referrer ); + } +} - my $backup = find_backup($uuid, $self->app->get_backups_dir); +#################################################################################### +sub delete_backup { + my $self = shift; + my $uuid = $self->param('id'); + + my $backup = find_backup( $uuid, $self->app->get_backups_dir ); - if ( $backup and $backup->is_healthy ) { - $self->app->logger->info("Downloading backup ".$backup->uuid); - $self->render_file( 'filepath' => $backup->get_path ); + if ( $backup and $backup->is_healthy ) { + if ( $backup->get_age->days + >= $self->app->config->{allow_delete_backups_older_than} ) + { + $backup->allow_delete(1); } else { - $self->flash( msg_type=>'danger', msg => "Cannot download backup $uuid - backup not healthy." ); - $self->redirect_to( $self->get_referrer ); + $backup->allow_delete(undef); } -} - -#################################################################################### -sub delete_backup { - my $self = shift; - my $uuid = $self->param('id'); - - my $backup = find_backup($uuid, $self->app->get_backups_dir); - - if ( $backup and $backup->is_healthy ) { - if( $backup->get_age->days >= $self->app->config->{allow_delete_backups_older_than}){ - $backup->allow_delete(1); - } - else{ - $backup->allow_delete(undef); - } - if($backup->allow_delete){ - try{ - unlink $backup->get_path; - $self->app->logger->info("Deleting backup ".$backup->uuid); - $self->flash( msg_type=>'success', msg => "Backup id $uuid deleted!" ); - } - catch{ - $self->flash( msg_type=>'danger', msg => "Exception during deleting backup '$uuid': $_." ); - }; - } - else{ - $self->flash( msg_type=>'warning', msg => "Backup $uuid is too young to be deleted!" ); - } + if ( $backup->allow_delete ) { + try { + unlink $backup->get_path; + $self->app->logger->info( "Deleting backup " . $backup->uuid ); + $self->flash( + msg_type => 'success', + msg => "Backup id $uuid deleted!" + ); + } + catch { + $self->flash( + msg_type => 'danger', + msg => "Exception during deleting backup '$uuid': $_." + ); + }; } - else{ - $self->flash( msg_type=>'danger', msg => "Cannot delete backup $uuid - you need to do this manually." ); + else { + $self->flash( + msg_type => 'warning', + msg => "Backup $uuid is too young to be deleted!" + ); } + } + else { + $self->flash( + msg_type => 'danger', + msg => "Cannot delete backup $uuid - you need to do this manually." + ); + } - $self->res->code(303); - $self->redirect_to($self->url_for('backup_index')); + $self->res->code(303); + $self->redirect_to( $self->url_for('backup_index') ); } #################################################################################### sub restore_backup { - my $self = shift; - my $uuid = $self->param('id'); + my $self = shift; + my $uuid = $self->param('id'); - my $backup = find_backup($uuid, $self->app->get_backups_dir); + my $backup = find_backup( $uuid, $self->app->get_backups_dir ); - if($backup and $backup->is_healthy){ + if ( $backup and $backup->is_healthy ) { - restore_storable_backup($backup, $self->app); + restore_storable_backup( $backup, $self->app ); - $self->app->logger->info("Restoring backup ".$backup->uuid); + $self->app->logger->info( "Restoring backup " . $backup->uuid ); - my $status = "Status:
".$self->app->repo->lr->get_summary_table."
"; + my $status + = "Status:
"
+        . $self->app->repo->lr->get_summary_table
+        . "
"; - $self->flash( msg_type=>'success', msg => "Backup restored successfully. Database recreated, persistence layers in sync. $status" ); - } - else { - $self->flash( msg_type=>'danger', msg => "Cannot restore - backup not healthy!" ); - } - $self->redirect_to('backup_index'); + $self->flash( + msg_type => 'success', + msg => + "Backup restored successfully. Database recreated, persistence layers in sync. $status" + ); + } + else { + $self->flash( + msg_type => 'danger', + msg => "Cannot restore - backup not healthy!" + ); + } + $self->redirect_to('backup_index'); } #################################################################################### diff --git a/lib/BibSpace/Controller/Cron.pm b/lib/BibSpace/Controller/Cron.pm index 8ec7f0e..2d08bc2 100644 --- a/lib/BibSpace/Controller/Cron.pm +++ b/lib/BibSpace/Controller/Cron.pm @@ -135,7 +135,6 @@ sub cron_run { } ############ Cron ACTIONS - $self->log_cron_usage($level); $self->app->logger->info("Cron level $level started"); if ( $level == 0 ) { @@ -156,6 +155,8 @@ sub cron_run { else { # do nothing } + # this may cause: [error] Unable to open file (bibspace_preferences.json) for storing : Permission denied at + $self->log_cron_usage($level); $self->app->logger->info("Cron level $level has finished"); return $text_to_render; diff --git a/lib/BibSpace/Controller/Display.pm b/lib/BibSpace/Controller/Display.pm index c19c0ce..ad7d7cd 100644 --- a/lib/BibSpace/Controller/Display.pm +++ b/lib/BibSpace/Controller/Display.pm @@ -105,9 +105,20 @@ sub show_log_ws { $self->on(finish => sub { my ($c, $code, $reason) = @_; - say "WS closed"; + say "show_log_ws WS closed"; }); } +################################################################################# +sub show_stats { + my $self = shift; + my $num = $self->param('num') // 20; + + my @lines = $self->app->statistics->toLines; + + $self->stash( lines => \@lines, num => $num); + $self->render( template => 'display/stats' ); +} + ################################################################################# sub show_stats_websocket { my $self = shift; @@ -124,7 +135,7 @@ sub show_stats_websocket { $self->on(finish => sub { my ($c, $code, $reason) = @_; - say "WS closed"; + say "show_stats_websocket WS closed"; }); } ################################################################################# diff --git a/lib/BibSpace/Controller/Helpers.pm b/lib/BibSpace/Controller/Helpers.pm index 262a067..df81f00 100644 --- a/lib/BibSpace/Controller/Helpers.pm +++ b/lib/BibSpace/Controller/Helpers.pm @@ -60,15 +60,20 @@ sub register { } ); - $app->helper( - db => sub { - my $self = shift; - return db_connect( - $self->app->config->{db_host}, $self->app->config->{db_user}, - $self->app->config->{db_database}, $self->app->config->{db_pass} - ); - } - ); + $app->helper( + db => sub { + my $self = shift; + my $db_host + = $ENV{BIBSPACE_DB_HOST} || $self->app->config->{db_host}; + my $db_user + = $ENV{BIBSPACE_DB_USER} || $self->app->config->{db_user}; + my $db_database + = $ENV{BIBSPACE_DB_DATABASE} || $self->app->config->{db_database}; + my $db_pass + = $ENV{BIBSPACE_DB_PASS} || $self->app->config->{db_pass}; + return db_connect( $db_host, $db_user, $db_database, $db_pass ); + } + ); $app->helper( bst => sub { diff --git a/lib/BibSpace/Controller/Persistence.pm b/lib/BibSpace/Controller/Persistence.pm index e6b1790..fdeae4e 100644 --- a/lib/BibSpace/Controller/Persistence.pm +++ b/lib/BibSpace/Controller/Persistence.pm @@ -21,9 +21,12 @@ use Mojo::Base 'Mojolicious::Controller'; ################################################################################# sub persistence_status { - my $self = shift; + my $self = shift; - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; + my $status + = "Status:
"
+      . $self->app->repo->lr->get_summary_table
+      . "
"; $self->stash( msg_type => 'success', msg => $status ); $self->flash( msg_type => 'success', msg => $status ); $self->redirect_to( $self->get_referrer ); @@ -31,9 +34,12 @@ sub persistence_status { ################################################################################# sub persistence_status_ajax { - my $self = shift; + my $self = shift; - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; + my $status + = "Status:
"
+      . $self->app->repo->lr->get_summary_table
+      . "
"; $self->render( text => $status ); } @@ -41,17 +47,27 @@ sub persistence_status_ajax { sub load_fixture { my $self = shift; - $self->app->logger->warn("PERSISTENCE CONTROLLER does: load_fixture"); + my $fixture_file + = $self->app->home->rel_file('fixture/bibspace_fixture.dat'); + $self->app->logger->info( + "Loading fixture from: " . $fixture_file->to_string ); - my $fixture_name = "bibspace_fixture.dat"; - my $fixture_dir = "./fixture/"; - my $fixture = Backup->new( dir => $fixture_dir, filename => $fixture_name ); + my $fixture = Backup->new( + dir => '' . $fixture_file->dirname, + filename => '' . $fixture_file->basename + ); restore_storable_backup( $fixture, $self->app ); - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; - $self->flash( msg_type => 'success', msg => "Fixture loaded into memory and mysql. $status" ); + my $status + = "Status:
"
+      . $self->app->repo->lr->get_summary_table
+      . "
"; + $self->flash( + msg_type => 'success', + msg => "Fixture loaded into memory and mysql. $status" + ); $self->redirect_to( $self->get_referrer ); } ################################################################################# @@ -60,36 +76,51 @@ sub save_fixture { $self->app->logger->warn("PERSISTENCE CONTROLLER does: save_fixture"); - my $fixture_name = "bibspace_fixture.dat"; - my $fixture_dir = "./fixture/"; - my $backup = Backup->create( 'dummy', "storable" ); - $backup->dir($fixture_dir); - $backup->filename($fixture_name); + my $fixture_file + = $self->app->home->rel_file('fixture/bibspace_fixture.dat'); + + my $backup = Backup->create( 'dummy', "storable" ); + $backup->dir( '' . $fixture_file->dirname ); + $backup->filename( '' . $fixture_file->basename ); my $layer = $self->app->repo->lr->get_read_layer; my $path = "" . $backup->get_path; - $Storable::forgive_me = "do store regexp please, we will not use them anyway"; + $Storable::forgive_me + = "do store regexp please, we will not use them anyway"; - # if you see any exceptions being thrown here, this might be due to REGEXP caused by DateTime pattern. - # this should not happen currently however - I think it is fixed now. +# if you see any exceptions being thrown here, this might be due to REGEXP caused by DateTime pattern. +# this should not happen currently however - I think it is fixed now. Storable::store $layer, $path; - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; - $self->flash( msg_type => 'success', msg => "Fixture stored to '" . $backup->get_path . "'. $status" ); + my $status + = "Status:
"
+      . $self->app->repo->lr->get_summary_table
+      . "
"; + $self->flash( + msg_type => 'success', + msg => "Fixture stored to '" . $backup->get_path . "'. $status" + ); $self->redirect_to( $self->get_referrer ); } ################################################################################# sub copy_mysql_to_smart { my $self = shift; - $self->app->logger->warn("PERSISTENCE CONTROLLER does: copy_mysql_to_smart"); + $self->app->logger->warn( + "PERSISTENCE CONTROLLER does: copy_mysql_to_smart"); $self->app->repo->lr->copy_data( { from => 'mysql', to => 'smart' } ); $self->app->link_data; - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; - $self->flash( msg_type => 'success', msg => "Copied mysql => smart. $status" ); + my $status + = "Status:
"
+      . $self->app->repo->lr->get_summary_table
+      . "
"; + $self->flash( + msg_type => 'success', + msg => "Copied mysql => smart. $status" + ); $self->redirect_to( $self->get_referrer ); } ################################################################################# @@ -99,8 +130,14 @@ sub copy_smart_to_mysql { $self->app->repo->lr->copy_data( { from => 'smart', to => 'mysql' } ); - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; - $self->flash( msg_type => 'success', msg => "Copied smart => mysql. $status" ); + my $status + = "Status:
"
+      . $self->app->repo->lr->get_summary_table
+      . "
"; + $self->flash( + msg_type => 'success', + msg => "Copied smart => mysql. $status" + ); $self->redirect_to( $self->get_referrer ); } @@ -111,49 +148,51 @@ sub insert_random_data { my $str_len = 60; - for (1..$num){ + for ( 1 .. $num ) { my $obj = $self->app->entityFactory->new_User( - login => random_string($str_len), - email => random_string($str_len).'@example.com', - real_name => random_string($str_len), - pass => random_string($str_len), - pass2 => random_string($str_len) + login => random_string($str_len), + email => random_string($str_len) . '@example.com', + real_name => random_string($str_len), + pass => random_string($str_len), + pass2 => random_string($str_len) ); $self->app->repo->users_save($obj); $obj = $self->app->entityFactory->new_Author( - uid => random_string($str_len), - ); + uid => random_string($str_len), ); $self->app->repo->authors_save($obj); $obj = $self->app->entityFactory->new_Entry( - bib => random_string($str_len), - ); + bib => random_string($str_len), ); $self->app->repo->entries_save($obj); $obj = $self->app->entityFactory->new_TagType( - name => random_string($str_len), - ); + name => random_string($str_len), ); $self->app->repo->tagTypes_save($obj); - my $tt = ($self->app->repo->tagTypes_all)[0]; + my $tt = ( $self->app->repo->tagTypes_all )[0]; $obj = $self->app->entityFactory->new_Tag( - name => random_string($str_len), - type => $tt->id + name => random_string($str_len), + type => $tt->id ); $self->app->repo->tags_save($obj); $obj = $self->app->entityFactory->new_Team( - name => random_string($str_len), - ); + name => random_string($str_len), ); $self->app->repo->teams_save($obj); } - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; - $self->flash( msg_type => 'success', msg => "Copied smart => mysql. $status" ); + my $status + = "Status:
"
+      . $self->app->repo->lr->get_summary_table
+      . "
"; + $self->flash( + msg_type => 'success', + msg => "Copied smart => mysql. $status" + ); $self->redirect_to( $self->get_referrer ); } ################################################################################# @@ -173,10 +212,14 @@ sub reset_smart { # instead, do not insert admin and set system in demo mode $self->app->preferences->run_in_demo_mode(1); - say "setting preferences->run_in_demo_mode to: '".$self->app->preferences->run_in_demo_mode."'"; + say "setting preferences->run_in_demo_mode to: '" + . $self->app->preferences->run_in_demo_mode . "'"; - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; + my $status + = "Status:
"
+      . $self->app->repo->lr->get_summary_table
+      . "
"; $self->flash( msg_type => 'success', msg => $status ); $self->redirect_to( $self->get_referrer ); } @@ -189,12 +232,21 @@ sub reset_mysql { my $layer = $self->app->repo->lr->get_layer('mysql'); if ($layer) { $layer->reset_data; - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; + my $status + = "Status:
"
+        . $self->app->repo->lr->get_summary_table
+        . "
"; $self->flash( msg_type => 'success', msg => $status ); } else { - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; - $self->flash( msg_type => 'danger', msg => "Reset failed - backend handle undefined. " . $status ); + my $status + = "Status:
"
+        . $self->app->repo->lr->get_summary_table
+        . "
"; + $self->flash( + msg_type => 'danger', + msg => "Reset failed - backend handle undefined. " . $status + ); } $self->redirect_to( $self->get_referrer ); @@ -206,10 +258,9 @@ sub reset_all { $self->app->logger->warn("PERSISTENCE CONTROLLER does: reset_all"); my @layers = $self->app->repo->lr->get_all_layers; - foreach (@layers){ $_->reset_data }; + foreach (@layers) { $_->reset_data } $self->app->repo->lr->reset_uid_providers; - - + # no pub_admin user would lock the whole system # if you insert it here, it may will cause clash of IDs @@ -218,7 +269,10 @@ sub reset_all { $self->app->preferences->run_in_demo_mode(1); - my $status = "Status:
" . $self->app->repo->lr->get_summary_table . "
"; + my $status + = "Status:
"
+      . $self->app->repo->lr->get_summary_table
+      . "
"; $self->flash( msg_type => 'success', msg => $status ); $self->redirect_to( $self->get_referrer ); } @@ -233,7 +287,8 @@ sub system_status { my $backup_dir_absolute = $self->config->{backups_dir}; - $backup_dir_absolute =~ s!/*$!/!; # makes sure that there is exactly one / at the end + $backup_dir_absolute + =~ s!/*$!/!; # makes sure that there is exactly one / at the end my $errored = 0; diff --git a/lib/BibSpace/Controller/Preferences.pm b/lib/BibSpace/Controller/Preferences.pm index d391505..35f738a 100644 --- a/lib/BibSpace/Controller/Preferences.pm +++ b/lib/BibSpace/Controller/Preferences.pm @@ -59,9 +59,6 @@ sub save { $self->app->preferences->output_time_format($output_time_format); - # # store to file - # my $json_str = $self->app->preferences->store('bibspace_preferences.json'); - $self->stash( preferences => $self->app->preferences, msg_type=>$msg_type, msg =>$msg ); # $self->render( template => 'display/preferences' ); $self->redirect_to( $self->get_referrer ); diff --git a/lib/BibSpace/Controller/Publications.pm b/lib/BibSpace/Controller/Publications.pm index 307fab3..1b60534 100644 --- a/lib/BibSpace/Controller/Publications.pm +++ b/lib/BibSpace/Controller/Publications.pm @@ -6,7 +6,6 @@ use Text::BibTeX; # parsing bib files use DateTime; use Mojo::IOLoop; -# use File::Slurp; # should be replaced in the future use Path::Tiny; # for creating directories use Try::Tiny; @@ -29,18 +28,18 @@ use Mojo::UserAgent; use Mojo::Log; our %mons = ( - 1 => 'January', - 2 => 'February', - 3 => 'March', - 4 => 'April', - 5 => 'May', - 6 => 'June', - 7 => 'July', - 8 => 'August', - 9 => 'September', - 10 => 'October', - 11 => 'November', - 12 => 'December' + 1 => 'January', + 2 => 'February', + 3 => 'March', + 4 => 'April', + 5 => 'May', + 6 => 'June', + 7 => 'July', + 8 => 'August', + 9 => 'September', + 10 => 'October', + 11 => 'November', + 12 => 'December' ); #################################################################################### # work, but not for now @@ -55,163 +54,174 @@ our %mons = ( # } #################################################################################### sub all { - my $self = shift; + my $self = shift; - my @all = Fget_publications_main_hashed_args( $self, {year=>undef}); - my @filtered = Fget_publications_main_hashed_args( $self, {}, \@all); + my @all = Fget_publications_main_hashed_args( $self, { year => undef } ); + my @filtered = Fget_publications_main_hashed_args( $self, {}, \@all ); - $self->stash( entries => \@filtered, all_entries => \@all); - my $html = $self->render_to_string( template => 'publications/all' ); - $self->render( data => $html ); + $self->stash( entries => \@filtered, all_entries => \@all ); + my $html = $self->render_to_string( template => 'publications/all' ); + $self->render( data => $html ); } #################################################################################### sub all_recently_added { - my $self = shift; - my $num = $self->param('num') // 10; + my $self = shift; + my $num = $self->param('num') // 10; - $self->app->logger->info("Displaying recently added entries."); + $self->app->logger->info("Displaying recently added entries."); - my @all = Fget_publications_main_hashed_args( $self, {year=>undef}); - my @added_entries = sort { $b->creation_time cmp $a->creation_time } @all; - @added_entries = @added_entries[ 0 .. $num - 1 ]; + my @all = Fget_publications_main_hashed_args( $self, { year => undef } ); + my @added_entries = sort { $b->creation_time cmp $a->creation_time } @all; + @added_entries = @added_entries[ 0 .. $num - 1 ]; - my @filtered = Fget_publications_main_hashed_args( $self, {}, \@added_entries); - # special sorting here - @filtered = sort { $b->creation_time cmp $a->creation_time } @filtered; + my @filtered + = Fget_publications_main_hashed_args( $self, {}, \@added_entries ); - $self->stash( entries => \@filtered, all_entries => \@added_entries ); - $self->render( template => 'publications/all' ); + # special sorting here + @filtered = sort { $b->creation_time cmp $a->creation_time } @filtered; + + $self->stash( entries => \@filtered, all_entries => \@added_entries ); + $self->render( template => 'publications/all' ); } #################################################################################### sub all_recently_modified { - my $self = shift; - my $num = $self->param('num') // 10; + my $self = shift; + my $num = $self->param('num') // 10; + + $self->app->logger->info("Displaying recently modified entries."); + - $self->app->logger->info("Displaying recently modified entries."); + my @all = Fget_publications_main_hashed_args( $self, { year => undef } ); + my @modified_entries + = sort { $b->modified_time cmp $a->modified_time } @all; + @modified_entries = @modified_entries[ 0 .. $num - 1 ]; - - my @all = Fget_publications_main_hashed_args( $self, {year=>undef}); - my @modified_entries = sort { $b->modified_time cmp $a->modified_time } @all; - @modified_entries = @modified_entries[ 0 .. $num - 1 ]; + my @filtered + = Fget_publications_main_hashed_args( $self, {}, \@modified_entries ); - my @filtered = Fget_publications_main_hashed_args( $self, {}, \@modified_entries); - # special sorting here - @filtered = sort { $b->modified_time cmp $a->modified_time } @filtered; + # special sorting here + @filtered = sort { $b->modified_time cmp $a->modified_time } @filtered; - $self->stash( entries => \@filtered, all_entries => \@modified_entries ); - $self->render( template => 'publications/all' ); + $self->stash( entries => \@filtered, all_entries => \@modified_entries ); + $self->render( template => 'publications/all' ); } #################################################################################### sub all_without_tag { - my $self = shift; - my $tagtype = $self->param('tagtype') // 1; + my $self = shift; + my $tagtype = $self->param('tagtype') // 1; - # this will filter entries based on query - my @all = Fget_publications_main_hashed_args( $self, {year=>undef} ); - - my @untagged_entries = grep { scalar $_->get_tags($tagtype) == 0 } @all; - my @filtered = Fget_publications_main_hashed_args( $self, {}, \@untagged_entries); + # this will filter entries based on query + my @all = Fget_publications_main_hashed_args( $self, { year => undef } ); + my @untagged_entries = grep { scalar $_->get_tags($tagtype) == 0 } @all; + my @filtered + = Fget_publications_main_hashed_args( $self, {}, \@untagged_entries ); - my $msg - = "This list contains papers that have no tags of type '$tagtype'. Use this list to tag the untagged papers! "; - $self->stash( msg_type => 'info', msg => $msg ); - $self->stash( entries => \@filtered, all_entries => \@untagged_entries ); - $self->render( template => 'publications/all' ); + + my $msg + = "This list contains papers that have no tags of type '$tagtype'. Use this list to tag the untagged papers! "; + $self->stash( msg_type => 'info', msg => $msg ); + $self->stash( entries => \@filtered, all_entries => \@untagged_entries ); + $self->render( template => 'publications/all' ); } #################################################################################### sub all_orphaned { - my $self = shift; + my $self = shift; - my @all = Fget_publications_main_hashed_args( $self, {year=>undef} ); + my @all = Fget_publications_main_hashed_args( $self, { year => undef } ); - my @entries = grep { scalar( $_->get_authors ) == 0 } @all; - - my @filtered = Fget_publications_main_hashed_args( $self, {}, \@entries); + my @entries = grep { scalar( $_->get_authors ) == 0 } @all; - my $msg - = "This list contains papers, that are currently not assigned to any of authors."; - $msg .= ' Click to delete '; + my @filtered = Fget_publications_main_hashed_args( $self, {}, \@entries ); + + my $msg + = "This list contains papers, that are currently not assigned to any of authors."; + $msg + .= ' Click to delete '; - $self->stash( msg_type => 'info', msg => $msg ); - $self->stash(entries => \@filtered, all_entries => \@entries); - $self->render( template => 'publications/all' ); + $self->stash( msg_type => 'info', msg => $msg ); + $self->stash( entries => \@filtered, all_entries => \@entries ); + $self->render( template => 'publications/all' ); } #################################################################################### sub show_unrelated_to_team { - my $self = shift; - my $team_id = $self->param('teamid'); + my $self = shift; + my $team_id = $self->param('teamid'); - $self->app->logger->info( - "Displaying entries unrelated to team '$team_id'."); + $self->app->logger->info( + "Displaying entries unrelated to team '$team_id'."); - my $team_name = ""; - my $team = $self->app->repo->teams_find( sub { $_->id == $team_id } ); - $team_name = $team->name if defined $team; + my $team_name = ""; + my $team = $self->app->repo->teams_find( sub { $_->id == $team_id } ); + $team_name = $team->name if defined $team; - my @all = Fget_publications_main_hashed_args( $self, {year=>undef} ); - my @teamEntres = $team->get_entries; + my @all = Fget_publications_main_hashed_args( $self, { year => undef } ); + my @teamEntres = $team->get_entries; - my %inTeam = map { $_ => 1 } @teamEntres; - my @entriesUnrelated = grep { not $inTeam{$_} } @all; + my %inTeam = map { $_ => 1 } @teamEntres; + my @entriesUnrelated = grep { not $inTeam{$_} } @all; - # hash destroys order! - @entriesUnrelated = sort_publications(@entriesUnrelated); - my @filtered = Fget_publications_main_hashed_args( $self, {}, \@entriesUnrelated); + # hash destroys order! + @entriesUnrelated = sort_publications(@entriesUnrelated); + my @filtered + = Fget_publications_main_hashed_args( $self, {}, \@entriesUnrelated ); - my $msg = "This list contains papers, that are: + my $msg = "This list contains papers, that are: "; - $self->stash( msg_type => 'info', msg => $msg ); - $self->stash( entries => \@filtered, all_entries => \@entriesUnrelated); - $self->render( template => 'publications/all' ); + $self->stash( msg_type => 'info', msg => $msg ); + $self->stash( entries => \@filtered, all_entries => \@entriesUnrelated ); + $self->render( template => 'publications/all' ); } #################################################################################### sub all_with_missing_month { - my $self = shift; + my $self = shift; - $self->app->logger->info("Displaying entries without month"); + $self->app->logger->info("Displaying entries without month"); - my @all = Fget_publications_main_hashed_args( $self, {year=>undef} ); - my @entries = grep { !defined $_->month or $_->month < 1 or $_->month > 12 } @all; + my @all = Fget_publications_main_hashed_args( $self, { year => undef } ); + my @entries + = grep { !defined $_->month or $_->month < 1 or $_->month > 12 } @all; - my @filtered = Fget_publications_main_hashed_args( $self, {}, \@entries); + my @filtered = Fget_publications_main_hashed_args( $self, {}, \@entries ); - my $msg - = "This list contains entries with missing BibTeX field 'month'. "; - $msg .= "Add this data to get the proper chronological sorting."; + my $msg = "This list contains entries with missing BibTeX field 'month'. "; + $msg .= "Add this data to get the proper chronological sorting."; - $self->stash( msg_type => 'info', msg => $msg ); - $self->stash( entries => \@filtered, all_entries => \@entries ); - $self->render( template => 'publications/all' ); + $self->stash( msg_type => 'info', msg => $msg ); + $self->stash( entries => \@filtered, all_entries => \@entries ); + $self->render( template => 'publications/all' ); } #################################################################################### sub all_candidates_to_delete { - my $self = shift; + my $self = shift; - $self->app->logger->info( - "Displaying entries that are candidates_to_delete"); + $self->app->logger->info( + "Displaying entries that are candidates_to_delete"); - my @all = Fget_publications_main_hashed_args( $self, {year=>undef} ); - my @entries = grep { scalar $_->get_tags == 0 } @all; # no tags - @entries = grep { scalar $_->get_teams == 0 } @entries; # no relation to teams - @entries = grep { scalar $_->get_exceptions == 0 } @entries; # no exceptions - my @filtered = Fget_publications_main_hashed_args( $self, {}, \@entries); + my @all = Fget_publications_main_hashed_args( $self, { year => undef } ); + my @entries = grep { scalar $_->get_tags == 0 } @all; # no tags + @entries + = grep { scalar $_->get_teams == 0 } @entries; # no relation to teams + @entries = grep { scalar $_->get_exceptions == 0 } @entries; # no exceptions + my @filtered = Fget_publications_main_hashed_args( $self, {}, \@entries ); - my $msg = "

This list contains papers, that are:

+ my $msg = "

This list contains papers, that are:

Such entries may wanted to be removed form the system or serve as a help with configuration.

"; - $self->stash( msg_type => 'info', msg => $msg ); - $self->stash( entries => \@filtered, all_entries => \@entries ); - $self->render( template => 'publications/all' ); + $self->stash( msg_type => 'info', msg => $msg ); + $self->stash( entries => \@filtered, all_entries => \@entries ); + $self->render( template => 'publications/all' ); } #################################################################################### #################################################################################### #################################################################################### sub all_bibtex { - my $self = shift; + my $self = shift; - my @objs = Fget_publications_main_hashed_args( $self, { hidden => 0 } ); + my @objs = Fget_publications_main_hashed_args( $self, { hidden => 0 } ); - my $big_str = "
\n";
-    foreach my $obj (@objs) {
-        $big_str .= $obj->{bib};
-        $big_str .= "\n";
-    }
-    $big_str .= "\n
"; - $self->render( text => $big_str ); + my $big_str = "
\n";
+  foreach my $obj (@objs) {
+    $big_str .= $obj->{bib};
+    $big_str .= "\n";
+  }
+  $big_str .= "\n
"; + $self->render( text => $big_str ); } #################################################################################### sub all_read { - my $self = shift; + my $self = shift; - # this function does filtering ! - my @objs = Fget_publications_main_hashed_args( $self, { hidden => 0 } ); + # this function does filtering ! + my @objs = Fget_publications_main_hashed_args( $self, { hidden => 0 } ); - $self->stash( entries => \@objs ); - my $html = $self->render_to_string( template => 'publications/all_read' ); - $self->render( data => $html ); + $self->stash( entries => \@objs ); + my $html = $self->render_to_string( template => 'publications/all_read' ); + $self->render( data => $html ); } #################################################################################### sub single { - my $self = shift; - my $id = $self->param('id'); - - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - - my @objs; - if ( defined $entry ) { - push @objs, $entry; - } - else { - $self->stash( - msg_type => 'danger', - msg => "Entry $id does not exist." - ); - } - $self->stash( entries => \@objs ); - $self->render( template => 'publications/all' ); + my $self = shift; + my $id = $self->param('id'); + + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + + my @objs; + if ( defined $entry ) { + push @objs, $entry; + } + else { + $self->stash( msg_type => 'danger', msg => "Entry $id does not exist." ); + } + $self->stash( entries => \@objs ); + $self->render( template => 'publications/all' ); } #################################################################################### sub single_read { - my $self = shift; - my $id = $self->param('id'); + my $self = shift; + my $id = $self->param('id'); - my @objs = (); + my @objs = (); - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - if ( defined $entry and $entry->is_hidden == 0 ) { - push @objs, $entry; - } - $self->stash( entries => \@objs ); - $self->render( template => 'publications/all_read' ); + if ( defined $entry and $entry->is_hidden == 0 ) { + push @objs, $entry; + } + $self->stash( entries => \@objs ); + $self->render( template => 'publications/all_read' ); } #################################################################################### sub fixMonths { - my $self = shift; + my $self = shift; - $self->app->logger->info("Fix months in all entries."); + $self->app->logger->info("Fix months in all entries."); - my @entries = $self->app->repo->entries_all; + my @entries = $self->app->repo->entries_all; - foreach my $entry (@entries) { - $entry->fix_month(); - } - $self->app->repo->entries_save(@entries); + foreach my $entry (@entries) { + $entry->fix_month(); + } + $self->app->repo->entries_save(@entries); - $self->flash( - msg => 'Fixing entries month field finished.', - msg_type => 'info' - ); - $self->redirect_to( $self->get_referrer ); + $self->flash( + msg => 'Fixing entries month field finished.', + msg_type => 'info' + ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub toggle_hide { - my $self = shift; - my $id = $self->param('id'); + my $self = shift; + my $id = $self->param('id'); - $self->app->logger->info("Toggle hide entry '$id'."); + $self->app->logger->info("Toggle hide entry '$id'."); - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - if ( defined $entry ) { - $entry->toggle_hide; - $self->app->repo->entries_update($entry); - } - else { - $self->flash( msg => "There is no entry with id $id" ); - } + if ( defined $entry ) { + $entry->toggle_hide; + $self->app->repo->entries_update($entry); + } + else { + $self->flash( msg => "There is no entry with id $id" ); + } - $self->redirect_to( $self->get_referrer ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub make_paper { - my $self = shift; - my $id = $self->param('id'); + my $self = shift; + my $id = $self->param('id'); - $self->app->logger->info("Make entry '$id' 'paper'."); + $self->app->logger->info("Make entry '$id' 'paper'."); - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - if ( defined $entry ) { - $entry->make_paper(); - $self->app->repo->entries_update($entry); - } - else { - $self->flash( msg => "There is no entry with id $id" ); - } + if ( defined $entry ) { + $entry->make_paper(); + $self->app->repo->entries_update($entry); + } + else { + $self->flash( msg => "There is no entry with id $id" ); + } - $self->redirect_to( $self->get_referrer ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub make_talk { - my $self = shift; - my $id = $self->param('id'); + my $self = shift; + my $id = $self->param('id'); - $self->app->logger->info("Make entry '$id' 'talk'."); + $self->app->logger->info("Make entry '$id' 'talk'."); - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - if ( defined $entry ) { - $entry->make_talk(); - $self->app->repo->entries_update($entry); - } - else { - $self->flash( msg => "There is no entry with id $id" ); - } + if ( defined $entry ) { + $entry->make_talk(); + $self->app->repo->entries_update($entry); + } + else { + $self->flash( msg => "There is no entry with id $id" ); + } - $self->redirect_to( $self->get_referrer ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub delete_orphaned { - my $self = shift; - - my @entries = $self->app->repo->entries_filter( - sub { scalar( $_->get_authors ) == 0 } ); - - foreach my $entry (@entries){ - my @au = $entry->authorships_all; - $self->app->repo->authorships_delete(@au); - my @ex = $entry->exceptions_all; - $self->app->repo->exceptions_delete(@ex); - my @la = $entry->labelings_all; - $self->app->repo->labelings_delete(@la); - } + my $self = shift; - my $num_deleted = $self->app->repo->entries_delete(@entries); + my @entries = $self->app->repo->entries_filter( + sub { scalar( $_->get_authors ) == 0 } ); + + foreach my $entry (@entries) { + my @au = $entry->authorships_all; + $self->app->repo->authorships_delete(@au); + my @ex = $entry->exceptions_all; + $self->app->repo->exceptions_delete(@ex); + my @la = $entry->labelings_all; + $self->app->repo->labelings_delete(@la); + } + + my $num_deleted = $self->app->repo->entries_delete(@entries); + + my $msg = "$num_deleted entries have been removed"; + $self->flash( msg => $msg, msg_type => 'info' ); + $self->redirect_to('all_orphaned'); - my $msg - = "$num_deleted entries have been removed"; - $self->flash( msg => $msg, msg_type => 'info' ); - $self->redirect_to( 'all_orphaned' ); - } #################################################################################### sub fix_file_urls { - my $self = shift; - my $id = $self->param('id'); + my $self = shift; + my $id = $self->param('id'); + + $self->app->logger->info("Fixing file urls for all entries."); - $self->app->logger->info("Fixing file urls for all entries."); + my @all_entries; - my @all_entries; + if ($id) { + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + push @all_entries, $entry if $entry; + } + else { + @all_entries = $self->app->repo->entries_all; + } + + my $big_str = ".\n"; + my $num_fixes = 0; + my $num_checks = 0; - if ($id) { - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - push @all_entries, $entry if $entry; + for my $entry (@all_entries) { + + ++$num_checks; + my $str; + $str .= "Entry " . $entry->id . ": "; + $entry->discover_attachments( $self->app->get_upload_dir ); + my @discovered_types = $entry->attachments_keys; + + + $str .= "has types: ("; + foreach (@discovered_types) { + $str .= " $_, "; } - else { - @all_entries = $self->app->repo->entries_all; + $str .= "). Fixed: "; + + # say $str; + my $fixed; + my $file = $entry->get_attachment('paper'); + my $file_url = $self->url_for( + 'download_publication_pdf', + filetype => "paper", + id => $entry->id + )->to_abs; + + if ( $file and $file->exists ) { + $entry->remove_bibtex_fields( ['pdf'] ); + $str .= "\n\t"; + $entry->add_bibtex_field( "pdf", "$file_url" ); + $fixed = 1; + $str .= "Added Bibtex filed PDF " . $file_url; } - my $big_str = ".\n"; - my $num_fixes = 0; - my $num_checks = 0; - - for my $entry (@all_entries) { - - ++$num_checks; - my $str; - $str .= "Entry " . $entry->id . ": "; - $entry->discover_attachments( $self->app->get_upload_dir ); - my @discovered_types = $entry->attachments_keys; - - - - $str .= "has types: ("; - foreach (@discovered_types) { - $str .= " $_, "; - } - $str .= "). Fixed: "; - - # say $str; - my $fixed; - my $file = $entry->get_attachment('paper'); - my $file_url = $self->url_for( - 'download_publication_pdf', - filetype => "paper", - id => $entry->id - )->to_abs; - - if ( $file and $file->exists ) { - $entry->remove_bibtex_fields( ['pdf'] ); - $str .= "\n\t"; - $entry->add_bibtex_field( "pdf", "$file_url" ); - $fixed = 1; - $str .= "Added Bibtex filed PDF " . $file_url; - } - - $file = $entry->get_attachment('slides'); - $file_url = $self->url_for( - 'download_publication', - filetype => "slides", - id => $entry->id - )->to_abs; - - if ( $file and $file->exists ) { - $entry->remove_bibtex_fields( ['slides'] ); - $str .= "\n\t"; - $entry->add_bibtex_field( "slides", "$file_url" ); - $fixed = 1; - $str .= "Added Bibtex filed SLIDES " . $file_url; - } - $str .= "\n"; - - if ($fixed) { - $big_str .= $str; - ++$num_fixes; - $entry->regenerate_html( 0, $self->app->bst, - $self->app->bibtexConverter ); - } + $file = $entry->get_attachment('slides'); + $file_url = $self->url_for( + 'download_publication', + filetype => "slides", + id => $entry->id + )->to_abs; + + if ( $file and $file->exists ) { + $entry->remove_bibtex_fields( ['slides'] ); + $str .= "\n\t"; + $entry->add_bibtex_field( "slides", "$file_url" ); + $fixed = 1; + $str .= "Added Bibtex filed SLIDES " . $file_url; } + $str .= "\n"; - $self->app->logger->info("Url fix results $big_str."); + if ($fixed) { + $big_str .= $str; + ++$num_fixes; + $entry->regenerate_html( 0, $self->app->bst, + $self->app->bibtexConverter ); + } + } - $self->flash( - msg_type => 'info', - msg => - "Checked $num_checks and regenerated $num_fixes entries. You may need to run regenerate HTML force now. Detailed fix results have been saved to log." - ); - $self->redirect_to( $self->get_referrer ); + $self->app->logger->info("Url fix results $big_str."); + + $self->flash( + msg_type => 'info', + msg => + "Checked $num_checks and regenerated $num_fixes entries. You may need to run regenerate HTML force now. Detailed fix results have been saved to log." + ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub remove_attachment { - my $self = shift; - my $id = $self->param('id'); # entry ID - my $filetype = $self->param('filetype') // 'paper'; # paper, slides - - $self->app->logger->info( - "Requested to remove attachment of type '$filetype'."); - - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - my ( $msg, $msg_type ); + my $self = shift; + my $id = $self->param('id'); # entry ID + my $filetype = $self->param('filetype') // 'paper'; # paper, slides - $entry->discover_attachments( $self->app->get_upload_dir ); + $self->app->logger->info( + "Requested to remove attachment of type '$filetype'."); + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + my ( $msg, $msg_type ); - if ( $entry->attachments_has($filetype) ) { - $self->app->logger->debug( - "Entry has attachment of type '$filetype'."); + $entry->discover_attachments( $self->app->get_upload_dir ); - if ( $filetype eq 'paper' ) { - $entry->remove_bibtex_fields( ['pdf'] ); - } - elsif ( $filetype eq 'slides' ) { - $entry->remove_bibtex_fields( ['slides'] ); - } - $entry->delete_attachment($filetype); - $entry->regenerate_html( 1, $self->app->bst, - $self->app->bibtexConverter ); - $self->app->repo->entries_save($entry); + if ( $entry->attachments_has($filetype) ) { + $self->app->logger->debug("Entry has attachment of type '$filetype'."); - $msg = "The attachment has been removed for entry '$id'."; - $msg_type = 'success'; - $self->app->logger->info($msg); + if ( $filetype eq 'paper' ) { + $entry->remove_bibtex_fields( ['pdf'] ); } - else { - $self->app->logger->debug( - "Entry has NO attachment of type '$filetype'."); - - $msg - = "File not found. Cannot remove attachment. Filetype '$filetype', entry '$id'."; - $msg_type = 'danger'; - $self->app->logger->error($msg); + elsif ( $filetype eq 'slides' ) { + $entry->remove_bibtex_fields( ['slides'] ); } + $entry->delete_attachment($filetype); - $self->flash( msg_type => $msg_type, msg => $msg ); - $self->redirect_to( $self->get_referrer ); + $entry->regenerate_html( 1, $self->app->bst, + $self->app->bibtexConverter ); + $self->app->repo->entries_save($entry); + + $msg = "The attachment has been removed for entry '$id'."; + $msg_type = 'success'; + $self->app->logger->info($msg); + } + else { + $self->app->logger->debug("Entry has NO attachment of type '$filetype'."); + + $msg + = "File not found. Cannot remove attachment. Filetype '$filetype', entry '$id'."; + $msg_type = 'danger'; + $self->app->logger->error($msg); + } + + $self->flash( msg_type => $msg_type, msg => $msg ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub discover_attachments { - my $self = shift; - my $id = $self->param('id'); - my $do = $self->param('do'); + my $self = shift; + my $id = $self->param('id'); + my $do = $self->param('do'); - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - $self->app->logger->info("Discovery of attachments for entry ID '$id'." ); - - my $msg; - my $msg_type = 'info'; - if ( $entry and $do and $do == 1 ) { - $entry->discover_attachments( $self->app->get_upload_dir ); - $msg .= "Discovery was run for dir '" - . $self->app->get_upload_dir . "'."; - } - elsif( $entry ) { - $msg .= "Just displaying information. "; - $msg + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + $self->app->logger->info("Discovery of attachments for entry ID '$id'."); + + my $msg; + my $msg_type = 'info'; + if ( $entry and $do and $do == 1 ) { + $entry->discover_attachments( $self->app->get_upload_dir ); + $msg .= "Discovery was run for dir '" . $self->app->get_upload_dir . "'."; + } + elsif ($entry) { + $msg .= "Just displaying information. "; + $msg .= "Attachments debug:
"
         . $entry->get_attachments_debug_string
         . "
"; - } - else{ - $msg = "Cannot discover, entry '$id' not found."; - $msg_type = 'danger'; - $self->app->logger->error( $msg ); - } - + } + else { + $msg = "Cannot discover, entry '$id' not found."; + $msg_type = 'danger'; + $self->app->logger->error($msg); + } - $self->flash( msg_type => $msg_type, msg => $msg ); - $self->redirect_to( $self->get_referrer ); + + $self->flash( msg_type => $msg_type, msg => $msg ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub download { - my $self = shift; - my $id = $self->param('id'); # entry ID - my $filetype = $self->param('filetype'); + my $self = shift; + my $id = $self->param('id'); # entry ID + my $filetype = $self->param('filetype'); - $self->app->logger->info( - "Requested to download attachment of type '$filetype' for entry ID '" - . $id - . "'." ); - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - my $file; + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + my $file; - if ($entry) { - $entry->discover_attachments( $self->app->get_upload_dir ); - $file = $entry->get_attachment($filetype); - } - else { - $self->app->logger->error("Cannot download - entry '$id' not found."); - $self->render( status => 404, text => "File not found." ); - return; - } - - if ( $file and -e $file ) { - $self->app->logger->info( - "Downloading file download '$filetype' for entry '$id'."); - $self->render_file( 'filepath' => $file ); - return; - } - $self->app->logger->error( - "File not found. Requested download for entry '$id', filetype '$filetype'." - ); - $self->render( text => "File not found.", status => 404 ); + if ($entry) { + $entry->discover_attachments( $self->app->get_upload_dir ); + $file = $entry->get_attachment($filetype); + } + else { + $self->app->logger->error("Cannot download - entry '$id' not found."); + $self->render( status => 404, text => "File not found." ); + return; + } + + if ( $file and -e $file ) { + $self->render_file( 'filepath' => $file ); + return; + } + $self->app->logger->error( + "File not found. Requested download for entry '$id', filetype '$filetype'." + ); + $self->render( text => "File not found.", status => 404 ); } #################################################################################### sub add_pdf { - my $self = shift; - my $id = $self->param('id'); - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + my $self = shift; + my $id = $self->param('id'); + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - if ( !defined $entry ) { - $self->flash( msg_type => 'danger', msg => "Entry '$id' not found." ); - $self->redirect_to( $self->get_referrer ); - return; - } - $entry->populate_from_bib(); - $entry->generate_html( $self->app->bst, $self->app->bibtexConverter ); + if ( !defined $entry ) { + $self->flash( msg_type => 'danger', msg => "Entry '$id' not found." ); + $self->redirect_to( $self->get_referrer ); + return; + } + $entry->populate_from_bib(); + $entry->generate_html( $self->app->bst, $self->app->bibtexConverter ); - $self->stash( mentry => $entry ); - $self->render( template => 'publications/pdf_upload' ); + $self->stash( mentry => $entry ); + $self->render( template => 'publications/pdf_upload' ); } #################################################################################### sub add_pdf_post { - my $self = shift; - my $id = $self->param('id'); - my $filetype = $self->param('filetype'); - my $uploaded_file = $self->param('uploaded_file'); - - my $uploads_directory - = Path::Tiny->new( $self->app->get_upload_dir ); - - $self->app->logger->info("Saving attachment for entry '$id'"); - - # Check file size - if ( $self->req->is_limit_exceeded ) { - my $curr_limit_B = $ENV{MOJO_MAX_MESSAGE_SIZE}; - $curr_limit_B ||= 16777216; - my $curr_limit_MB = $curr_limit_B / 1024 / 1024; - $self->app->logger->info( - "Saving attachment for paper id '$id': limit exceeded. Current limit: $curr_limit_MB MB." - ); - $self->flash( - msg => "The File is too big and cannot be saved!", - msg_type => "danger" - ); - $self->redirect_to( $self->get_referrer ); - return; - } - - - if ( !$uploaded_file ) { - $self->flash( - msg => "File upload unsuccessful!", - msg_type => "danger" - ); - $self->app->logger->info( - "Saving attachment for paper id '$id' FAILED. Unknown reason"); - $self->redirect_to( $self->get_referrer ); - return; - } - - my $size = $uploaded_file->size; - my $sizeKB = int( $size / 1024 ); - if ( $size == 0 ) { - $self->flash( - msg => "No file was selected or file has 0 bytes! Not saving!", - msg_type => "danger" - ); - $self->app->logger->info( - "Saving attachment for paper id '$id' FAILED. File size is 0."); - $self->redirect_to( $self->get_referrer ); - return; - } + my $self = shift; + my $id = $self->param('id'); + my $filetype = $self->param('filetype'); + my $uploaded_file = $self->param('uploaded_file'); - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - - if ( !defined $entry ) { - $self->flash( - msg_type => 'danger', - msg => "Entry '$id' does not exist." - ); - $self->redirect_to( $self->get_referrer ); - return; - } + my $uploads_directory = Path::Tiny->new( $self->app->get_upload_dir ); + $self->app->logger->info("Saving attachment for entry '$id'"); - my $name = $uploaded_file->filename; - my @dot_arr = split( /\./, $name ); - my $extension = $dot_arr[-1]; - + # Check file size + if ( $self->req->is_limit_exceeded ) { + my $curr_limit_B = $ENV{MOJO_MAX_MESSAGE_SIZE}; + $curr_limit_B ||= 16777216; + my $curr_limit_MB = $curr_limit_B / 1024 / 1024; + $self->app->logger->info( + "Saving attachment for paper id '$id': limit exceeded. Current limit: $curr_limit_MB MB." + ); + $self->flash( + msg => "The File is too big and cannot be saved!", + msg_type => "danger" + ); + $self->redirect_to( $self->get_referrer ); + return; + } - my $file_url; - my $destination; - if ( $filetype eq 'paper' ) { - $entry->delete_attachment('paper'); - $destination - = $uploads_directory->path( "papers", "paper-$id.$extension" ); - $uploaded_file->move_to($destination); - $self->app->logger->debug( - "Attachments file has been moved to: $destination."); - - $entry->add_attachment( 'paper', $destination ); - $file_url = $self->url_for( - 'download_publication_pdf', - filetype => "paper", - id => $entry->id - )->to_abs; - $entry->add_bibtex_field( 'pdf', "$file_url" ); - } - elsif ( $filetype eq 'slides' ) { - $entry->delete_attachment('slides'); - $destination = $uploads_directory->path( "slides", - "slides-paper-$id.$extension" ); - $uploaded_file->move_to($destination); - $self->app->logger->debug( - "Attachments file has been moved to: $destination."); - - $entry->add_attachment( 'slides', $destination ); - $file_url = $self->url_for( - 'download_publication', - filetype => "slides", - id => $entry->id - )->to_abs; - $entry->add_bibtex_field( 'slides', "$file_url" ); - } - else { - # ignore - we support only pdf and slides so far - } + if ( !$uploaded_file ) { + $self->flash( msg => "File upload unsuccessful!", msg_type => "danger" ); + $self->app->logger->info( + "Saving attachment for paper id '$id' FAILED. Unknown reason"); + $self->redirect_to( $self->get_referrer ); + return; + } + my $size = $uploaded_file->size; + my $sizeKB = int( $size / 1024 ); + if ( $size == 0 ) { + $self->flash( + msg => "No file was selected or file has 0 bytes! Not saving!", + msg_type => "danger" + ); $self->app->logger->info( - "Saving attachment for entry '$id' under: '$destination'."); + "Saving attachment for paper id '$id' FAILED. File size is 0."); + $self->redirect_to( $self->get_referrer ); + return; + } - my $msg - = "Successfully uploaded the $sizeKB KB file as $filetype. + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + + if ( !defined $entry ) { + $self->flash( + msg_type => 'danger', + msg => "Entry '$id' does not exist." + ); + $self->redirect_to( $self->get_referrer ); + return; + } + + + my $name = $uploaded_file->filename; + my @dot_arr = split( /\./, $name ); + my $extension = $dot_arr[-1]; + + + my $file_url; + my $destination; + + if ( $filetype eq 'paper' ) { + $entry->delete_attachment('paper'); + $destination + = $uploads_directory->path( "papers", "paper-$id.$extension" ); + $uploaded_file->move_to($destination); + $self->app->logger->debug( + "Attachments file has been moved to: $destination."); + + $entry->add_attachment( 'paper', $destination ); + $file_url = $self->url_for( + 'download_publication_pdf', + filetype => "paper", + id => $entry->id + )->to_abs; + $entry->add_bibtex_field( 'pdf', "$file_url" ); + } + elsif ( $filetype eq 'slides' ) { + $entry->delete_attachment('slides'); + $destination + = $uploads_directory->path( "slides", "slides-paper-$id.$extension" ); + $uploaded_file->move_to($destination); + $self->app->logger->debug( + "Attachments file has been moved to: $destination."); + + $entry->add_attachment( 'slides', $destination ); + $file_url = $self->url_for( + 'download_publication', + filetype => "slides", + id => $entry->id + )->to_abs; + $entry->add_bibtex_field( 'slides', "$file_url" ); + } + else { + # ignore - we support only pdf and slides so far + } + + $self->app->logger->info( + "Saving attachment for entry '$id' under: '$destination'."); + + my $msg + = "Successfully uploaded the $sizeKB KB file as $filetype. The file was renamed to: " - . $destination->basename . ""; + . $file_url . "\">" . $destination->basename . ""; - $entry->regenerate_html( 1, $self->app->bst, - $self->app->bibtexConverter ); - $self->app->repo->entries_save($entry); + $entry->regenerate_html( 1, $self->app->bst, $self->app->bibtexConverter ); + $self->app->repo->entries_save($entry); - $self->flash( msg_type => 'success', msg => $msg ); - $self->redirect_to( $self->get_referrer ); + $self->flash( msg_type => 'success', msg => $msg ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub mark_author_to_regenerate { - my $self = shift; - my $author_id = $self->param('author_id'); - my $converter = $self->app->bibtexConverter; + my $self = shift; + my $author_id = $self->param('author_id'); + my $converter = $self->app->bibtexConverter; - my $author = $self->app->repo->authors_find( sub{$_->id == $author_id} ); + my $author = $self->app->repo->authors_find( sub { $_->id == $author_id } ); - my @entries; + my @entries; - if($author){ - $self->app->logger->info("Marking entries of author '".$author->uid."' for HTML regeneration."); + if ($author) { + $self->app->logger->info( "Marking entries of author '" + . $author->uid + . "' for HTML regeneration." ); - @entries = $author->get_entries; - foreach my $entry (@entries){ - $entry->need_html_regen(1); - } - $self->app->repo->entries_save(@entries); + @entries = $author->get_entries; + foreach my $entry (@entries) { + $entry->need_html_regen(1); } - - my $msg = "".scalar(@entries). " entries have been MARKED for regeneration. "; - $msg .= "Now you may run 'regenerate all' or 'regenerate in chunks'. "; - $msg .= "Regenration in chunks is useful for large set of entries. "; - - $self->app->logger->info($msg); - $self->flash( msg_type => 'info', msg => $msg ); - $self->redirect_to( $self->get_referrer ); + $self->app->repo->entries_save(@entries); + } + + my $msg + = "" + . scalar(@entries) + . " entries have been MARKED for regeneration. "; + $msg .= "Now you may run 'regenerate all' or 'regenerate in chunks'. "; + $msg .= "Regenration in chunks is useful for large set of entries. "; + + $self->app->logger->info($msg); + $self->flash( msg_type => 'info', msg => $msg ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub regenerate_html_for_all { - my $self = shift; - my $converter = $self->app->bibtexConverter; + my $self = shift; + my $converter = $self->app->bibtexConverter; - $self->inactivity_timeout(3000); + $self->inactivity_timeout(3000); - $self->app->logger->info("regenerate_html_for_all is running"); + $self->app->logger->info("regenerate_html_for_all is running"); - my @entries = $self->app->repo->entries_filter( sub{$_->need_html_regen == 1} ); - my $num_regen = Fregenerate_html_for_array($self->app, 0, $converter, \@entries); - my $left_todo = scalar(@entries) - $num_regen; + my @entries + = $self->app->repo->entries_filter( sub { $_->need_html_regen == 1 } ); + my $num_regen + = Fregenerate_html_for_array( $self->app, 0, $converter, \@entries ); + my $left_todo = scalar(@entries) - $num_regen; - my $msg = "$num_regen entries have been regenerated. "; - $msg .= "$left_todo furter entries still require regeneration."; - $self->app->logger->info($msg); - $self->flash( msg_type => 'info', msg => $msg ); - $self->redirect_to( $self->get_referrer ); + my $msg = "$num_regen entries have been regenerated. "; + $msg .= "$left_todo furter entries still require regeneration."; + $self->app->logger->info($msg); + $self->flash( msg_type => 'info', msg => $msg ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub regenerate_html_in_chunk { - my $self = shift; - my $chunk_size = $self->param('chunk_size') // 30; + my $self = shift; + my $chunk_size = $self->param('chunk_size') // 30; - my $converter = $self->app->bibtexConverter; + my $converter = $self->app->bibtexConverter; - $self->inactivity_timeout(3000); + $self->inactivity_timeout(3000); - $self->app->logger->info("regenerate_html_in_chunk is running, chunk size $chunk_size "); + $self->app->logger->info( + "regenerate_html_in_chunk is running, chunk size $chunk_size "); - my @entries = $self->app->repo->entries_filter( sub{ $_->need_html_regen == 1} ); + my @entries + = $self->app->repo->entries_filter( sub { $_->need_html_regen == 1 } ); - my $last_entry_index = $chunk_size-1; - $last_entry_index = scalar(@entries)-1 if scalar(@entries) < $chunk_size; + my $last_entry_index = $chunk_size - 1; + $last_entry_index = scalar(@entries) - 1 if scalar(@entries) < $chunk_size; - my @portion_of_entries = @entries[ 0 .. $last_entry_index ]; - @portion_of_entries = grep {defined $_} @portion_of_entries; + my @portion_of_entries = @entries[ 0 .. $last_entry_index ]; + @portion_of_entries = grep { defined $_ } @portion_of_entries; - my $num_regen = Fregenerate_html_for_array($self->app, 1, $converter, \@portion_of_entries); - my $left_todo = scalar(@entries) - $num_regen; + my $num_regen = Fregenerate_html_for_array( $self->app, 1, $converter, + \@portion_of_entries ); + my $left_todo = scalar(@entries) - $num_regen; - my $msg = "$num_regen entries have been regenerated. "; - $msg .= "$left_todo furter entries still require regeneration."; - $self->app->logger->info($msg); - $self->flash( msg_type => 'info', msg => $msg ); - $self->redirect_to( $self->get_referrer() ); + my $msg = "$num_regen entries have been regenerated. "; + $msg .= "$left_todo furter entries still require regeneration."; + $self->app->logger->info($msg); + $self->flash( msg_type => 'info', msg => $msg ); + $self->redirect_to( $self->get_referrer() ); } #################################################################################### sub mark_all_to_regenerate { - my $self = shift; - my $converter = $self->app->bibtexConverter; + my $self = shift; + my $converter = $self->app->bibtexConverter; - $self->app->logger->info("Marking all entries for HTML regeneration."); + $self->app->logger->info("Marking all entries for HTML regeneration."); - my @entries = $self->app->repo->entries_all; - foreach my $entry (@entries){ - $entry->need_html_regen(1); - # $self->app->repo->entries_save($entry); - } - $self->app->repo->entries_save(@entries); + my @entries = $self->app->repo->entries_all; + foreach my $entry (@entries) { + $entry->need_html_regen(1); - my $msg = "".scalar(@entries). " entries have been MARKED for regeneration. "; - $msg .= "Now you may run 'regenerate all' or 'regenerate in chunks'. "; - $msg .= "Regenration in chunks is useful for large set of entries. "; - $self->app->logger->info($msg); - $self->flash( msg_type => 'info', msg => $msg ); - $self->redirect_to( $self->get_referrer() ); + # $self->app->repo->entries_save($entry); + } + $self->app->repo->entries_save(@entries); + + my $msg + = "" + . scalar(@entries) + . " entries have been MARKED for regeneration. "; + $msg .= "Now you may run 'regenerate all' or 'regenerate in chunks'. "; + $msg .= "Regenration in chunks is useful for large set of entries. "; + $self->app->logger->info($msg); + $self->flash( msg_type => 'info', msg => $msg ); + $self->redirect_to( $self->get_referrer() ); } #################################################################################### sub regenerate_html { - my $self = shift; - my $converter = $self->app->bibtexConverter; - my $id = $self->param('id'); - - - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + my $self = shift; + my $converter = $self->app->bibtexConverter; + my $id = $self->param('id'); - if ( !defined $entry ) { - $self->flash( - msg => "There is no entry with id $id", - msg_type => 'danger' - ); - $self->redirect_to( $self->get_referrer ); - return; - } - my @entries = ($entry); - my $num_regen = Fregenerate_html_for_array($self->app, 1, $converter, \@entries); - my $msg; - if($num_regen == 1){ - $msg = "$num_regen entry has been regenerated."; - } - else{ - $msg = "$num_regen entries have been regenerated."; - } - $self->app->logger->info($msg); - $self->flash( msg_type => 'info', msg => $msg ); + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + if ( !defined $entry ) { + $self->flash( + msg => "There is no entry with id $id", + msg_type => 'danger' + ); $self->redirect_to( $self->get_referrer ); + return; + } + my @entries = ($entry); + my $num_regen + = Fregenerate_html_for_array( $self->app, 1, $converter, \@entries ); + + my $msg; + if ( $num_regen == 1 ) { + $msg = "$num_regen entry has been regenerated."; + } + else { + $msg = "$num_regen entries have been regenerated."; + } + $self->app->logger->info($msg); + $self->flash( msg_type => 'info', msg => $msg ); + + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub delete_sure { - my $self = shift; - my $id = $self->param('id'); + my $self = shift; + my $id = $self->param('id'); - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); - if ( !defined $entry ) { - $self->app->logger->warn( - "Entry '$id' does not exist and thus can't be deleted."); - $self->flash( - mgs_type => 'danger', - msg => "There is no entry with id $id" - ); - $self->redirect_to( $self->get_referrer ); - return; - } - - $entry->delete_all_attachments; - my @entry_authorships = $entry->authorships_all; - my @entry_labelings = $entry->labelings_all; - my @entry_exceptions = $entry->exceptions_all; - $self->app->repo->authorships_delete(@entry_authorships); - $self->app->repo->labelings_delete(@entry_labelings); - $self->app->repo->exceptions_delete(@entry_exceptions); - $self->app->repo->entries_delete($entry); - - $self->app->logger->info("Entry '$id' has been deleted."); + if ( !defined $entry ) { + $self->app->logger->warn( + "Entry '$id' does not exist and thus can't be deleted."); + $self->flash( + mgs_type => 'danger', + msg => "There is no entry with id $id" + ); $self->redirect_to( $self->get_referrer ); + return; + } + + $entry->delete_all_attachments; + my @entry_authorships = $entry->authorships_all; + my @entry_labelings = $entry->labelings_all; + my @entry_exceptions = $entry->exceptions_all; + $self->app->repo->authorships_delete(@entry_authorships); + $self->app->repo->labelings_delete(@entry_labelings); + $self->app->repo->exceptions_delete(@entry_exceptions); + $self->app->repo->entries_delete($entry); + + $self->app->logger->info("Entry '$id' has been deleted."); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub show_authors_of_entry { - my $self = shift; - my $id = $self->param('id'); - $self->app->logger->info("Showing authors of entry id $id"); + my $self = shift; + my $id = $self->param('id'); + $self->app->logger->info("Showing authors of entry id $id"); - my $entry = $self->app->repo->entries_find( sub { $_->{id} == $id } ); + my $entry = $self->app->repo->entries_find( sub { $_->{id} == $id } ); - if ( !defined $entry ) { - $self->flash( msg => "There is no entry with id $id" ); - $self->redirect_to( $self->get_referrer ); - return; - } + if ( !defined $entry ) { + $self->flash( msg => "There is no entry with id $id" ); + $self->redirect_to( $self->get_referrer ); + return; + } - my @authors = map { $_->author } $entry->authorships_all; - my @teams = $entry->get_teams; + my @authors = map { $_->author } $entry->authorships_all; + my @teams = $entry->get_teams; - $self->stash( entry => $entry, authors => \@authors, teams => \@teams ); - $self->render( template => 'publications/show_authors' ); + $self->stash( entry => $entry, authors => \@authors, teams => \@teams ); + $self->render( template => 'publications/show_authors' ); } #################################################################################### #################################################################################### #################################################################################### sub manage_tags { - my $self = shift; - my $id = $self->param('id'); + my $self = shift; + my $id = $self->param('id'); - $self->app->logger->info("Manage tags of entry id $id"); + $self->app->logger->info("Manage tags of entry id $id"); - my $entry = $self->app->repo->entries_find( sub { $_->{id} == $id } ); + my $entry = $self->app->repo->entries_find( sub { $_->{id} == $id } ); - if ( !defined $entry ) { - $self->flash( msg => "There is no entry with id $id" ); - $self->redirect_to( $self->get_referrer ); - return; - } + if ( !defined $entry ) { + $self->flash( msg => "There is no entry with id $id" ); + $self->redirect_to( $self->get_referrer ); + return; + } - my @tags = $entry->get_tags; - my @tag_types = $self->app->repo->tagTypes_all; + my @tags = $entry->get_tags; + my @tag_types = $self->app->repo->tagTypes_all; - $self->stash( entry => $entry, tags => \@tags, tag_types => \@tag_types ); - $self->render( template => 'publications/manage_tags' ); + $self->stash( entry => $entry, tags => \@tags, tag_types => \@tag_types ); + $self->render( template => 'publications/manage_tags' ); } #################################################################################### sub remove_tag { - my $self = shift; - my $entry_id = $self->param('eid'); - my $tag_id = $self->param('tid'); + my $self = shift; + my $entry_id = $self->param('eid'); + my $tag_id = $self->param('tid'); - my $entry = $self->app->repo->entries_find( sub { $_->id == $entry_id } ); - my $tag = $self->app->repo->tags_find( sub { $_->id == $tag_id } ); + my $entry = $self->app->repo->entries_find( sub { $_->id == $entry_id } ); + my $tag = $self->app->repo->tags_find( sub { $_->id == $tag_id } ); - if ( defined $entry and defined $tag ) { + if ( defined $entry and defined $tag ) { - my $search_label = Labeling->new( - entry => $entry, - tag => $tag, - entry_id => $entry->id, - tag_id => $tag->id + my $search_label = Labeling->new( + entry => $entry, + tag => $tag, + entry_id => $entry->id, + tag_id => $tag->id + ); + + my $label + = $self->app->repo->labelings_find( sub { $_->equals($search_label) } ); - my $label = $self->app->repo->labelings_find( - sub { $_->equals($search_label) } ); + if ($label) { - if ($label) { + ## you should always execute all those three commands together - smells like command pattern... + $entry->remove_labeling($label); + $tag->remove_labeling($label); + $self->app->repo->labelings_delete($label); - ## you should always execute all those three commands together - smells like command pattern... - $entry->remove_labeling($label); - $tag->remove_labeling($label); - $self->app->repo->labelings_delete($label); + $self->app->logger->info( + "Removed tag " . $tag->name . " from entry ID " . $entry->id . ". " ); + } + else { + # this paper does not have this tag - do nothing + $self->app->logger->warn( "Cannot remove tag " + . $tag->name + . " from entry ID " + . $entry->id + . " - reason: labeling not found. " ); + } - $self->app->logger->info( "Removed tag " - . $tag->name - . " from entry ID " - . $entry->id - . ". " ); - } - else { - # this paper does not have this tag - do nothing - $self->app->logger->warn( "Cannot remove tag " - . $tag->name - . " from entry ID " - . $entry->id - . " - reason: labeling not found. " ); - } + } - } - - $self->redirect_to( $self->get_referrer ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub add_tag { - my $self = shift; - my $entry_id = $self->param('eid'); - my $tag_id = $self->param('tid'); - - my $entry = $self->app->repo->entries_find( sub { $_->id == $entry_id } ); - my $tag = $self->app->repo->tags_find( sub { $_->id == $tag_id } ); - - if ( defined $entry and defined $tag ) { - my $label = Labeling->new( - entry => $entry, - tag => $tag, - entry_id => $entry->id, - tag_id => $tag->id - ); - ## you should always execute all those three commands together - smells like command pattern... - - $self->app->repo->labelings_save($label); - $entry->add_labeling($label); - $tag->add_labeling($label); - } - else { - # this paper does not have this tag - do nothing - $self->app->logger->warn( - "Cannot add tag $tag_id to entry ID $entry_id - reason: tag or entry not found. " - ); - } + my $self = shift; + my $entry_id = $self->param('eid'); + my $tag_id = $self->param('tid'); + + my $entry = $self->app->repo->entries_find( sub { $_->id == $entry_id } ); + my $tag = $self->app->repo->tags_find( sub { $_->id == $tag_id } ); + + if ( defined $entry and defined $tag ) { + my $label = Labeling->new( + entry => $entry, + tag => $tag, + entry_id => $entry->id, + tag_id => $tag->id + ); + ## you should always execute all those three commands together - smells like command pattern... + + $self->app->repo->labelings_save($label); + $entry->add_labeling($label); + $tag->add_labeling($label); + } + else { + # this paper does not have this tag - do nothing + $self->app->logger->warn( + "Cannot add tag $tag_id to entry ID $entry_id - reason: tag or entry not found. " + ); + } - $self->redirect_to( $self->get_referrer ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### #################################################################################### #################################################################################### sub manage_exceptions { - my $self = shift; - my $id = $self->param('id'); + my $self = shift; + my $id = $self->param('id'); - my $entry = $self->app->repo->entries_find( sub { $_->{id} == $id } ); + my $entry = $self->app->repo->entries_find( sub { $_->{id} == $id } ); - if ( !defined $entry ) { - $self->flash( msg => "There is no entry with id $id" ); - $self->redirect_to( $self->get_referrer ); - return; - } + if ( !defined $entry ) { + $self->flash( msg => "There is no entry with id $id" ); + $self->redirect_to( $self->get_referrer ); + return; + } - my @exceptions = $entry->exceptions_all; - my @all_teams = $self->app->repo->teams_all; - my @teams = $entry->get_teams; - my @authors = $entry->get_authors; + my @exceptions = $entry->exceptions_all; + my @all_teams = $self->app->repo->teams_all; + my @teams = $entry->get_teams; + my @authors = $entry->get_authors; - # cannot use objects as keysdue to stringification! - my %exceptions_hash = map { $_->team->id => 1 } @exceptions; - my @unassigned_teams = grep { not $exceptions_hash{ $_->id } } @all_teams; + # cannot use objects as keysdue to stringification! + my %exceptions_hash = map { $_->team->id => 1 } @exceptions; + my @unassigned_teams = grep { not $exceptions_hash{ $_->id } } @all_teams; - $self->stash( - entry => $entry, - exceptions => \@exceptions, - teams => \@teams, - all_teams => \@all_teams, - authors => \@authors, - unassigned_teams => \@unassigned_teams - ); - $self->render( template => 'publications/manage_exceptions' ); + $self->stash( + entry => $entry, + exceptions => \@exceptions, + teams => \@teams, + all_teams => \@all_teams, + authors => \@authors, + unassigned_teams => \@unassigned_teams + ); + $self->render( template => 'publications/manage_exceptions' ); } #################################################################################### sub add_exception { - my $self = shift; - my $entry_id = $self->param('eid'); - my $team_id = $self->param('tid'); + my $self = shift; + my $entry_id = $self->param('eid'); + my $team_id = $self->param('tid'); - my $msg; - my $entry = $self->app->repo->entries_find( sub { $_->id == $entry_id } ); - my $team = $self->app->repo->teams_find( sub { $_->id == $team_id } ); + my $msg; + my $entry = $self->app->repo->entries_find( sub { $_->id == $entry_id } ); + my $team = $self->app->repo->teams_find( sub { $_->id == $team_id } ); - if ( defined $entry and defined $team ) { + if ( defined $entry and defined $team ) { - my $exception = Exception->new( - entry => $entry, - team => $team, - entry_id => $entry->id, - team_id => $team->id - ); - - $entry->add_exception($exception); - $team->add_exception($exception); - $self->app->repo->exceptions_save($exception); - - $msg - = "Exception added! Entry ID " - . $entry->id - . " will be now listed under team '" - . $team->name . "'."; - } - else { - $msg - = "Cannot find entry or team to create exception. Searched team ID: " - . $team_id - . " entry ID: " - . $entry_id . "."; - } + my $exception = Exception->new( + entry => $entry, + team => $team, + entry_id => $entry->id, + team_id => $team->id + ); - $self->flash( msg => $msg ); - $self->app->logger->info($msg); - $self->redirect_to( $self->get_referrer ); + $entry->add_exception($exception); + $team->add_exception($exception); + $self->app->repo->exceptions_save($exception); + + $msg + = "Exception added! Entry ID " + . $entry->id + . " will be now listed under team '" + . $team->name . "'."; + } + else { + $msg + = "Cannot find entry or team to create exception. Searched team ID: " + . $team_id + . " entry ID: " + . $entry_id . "."; + } + + $self->flash( msg => $msg ); + $self->app->logger->info($msg); + $self->redirect_to( $self->get_referrer ); } #################################################################################### sub remove_exception { - my $self = shift; - my $entry_id = $self->param('eid'); - my $team_id = $self->param('tid'); + my $self = shift; + my $entry_id = $self->param('eid'); + my $team_id = $self->param('tid'); - my $entry = $self->app->repo->entries_find( sub { $_->id == $entry_id } ); - my $team = $self->app->repo->teams_find( sub { $_->id == $team_id } ); + my $entry = $self->app->repo->entries_find( sub { $_->id == $entry_id } ); + my $team = $self->app->repo->teams_find( sub { $_->id == $team_id } ); - my $msg; + my $msg; - if ( defined $entry and defined $team ) { + if ( defined $entry and defined $team ) { - my $ex = Exception->new( - team_id => $team_id, - entry_id => $entry_id, - team => $team, - entry => $entry - ); + my $ex = Exception->new( + team_id => $team_id, + entry_id => $entry_id, + team => $team, + entry => $entry + ); - my $exception - = $self->app->repo->exceptions_find( sub { $_->equals($ex) } ); - - if ( defined $exception ) { - $entry->remove_exception($exception); - $team->remove_exception($exception); - $self->app->repo->exceptions_delete($exception); - - $msg - = "Removed exception team '" - . $team->name - . "' from entry ID " - . $entry->id . ". "; - } - else { - $msg - = "Cannot find exception to remove. Searched team '" - . $team->name - . "' entry ID: " - . $entry->id . "."; - } + my $exception + = $self->app->repo->exceptions_find( sub { $_->equals($ex) } ); + + if ( defined $exception ) { + $entry->remove_exception($exception); + $team->remove_exception($exception); + $self->app->repo->exceptions_delete($exception); + + $msg + = "Removed exception team '" + . $team->name + . "' from entry ID " + . $entry->id . ". "; } else { - $msg - = "Cannot find exception to remove. Searched team ID: " - . $team_id - . " entry ID: " - . $entry_id . "."; + $msg + = "Cannot find exception to remove. Searched team '" + . $team->name + . "' entry ID: " + . $entry->id . "."; } + } + else { + $msg + = "Cannot find exception to remove. Searched team ID: " + . $team_id + . " entry ID: " + . $entry_id . "."; + } - $self->flash( msg => $msg ); - $self->app->logger->info($msg); + $self->flash( msg => $msg ); + $self->app->logger->info($msg); - $self->redirect_to( $self->get_referrer ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### #################################################################################### #################################################################################### sub get_adding_editing_message_for_error_code { - my $self = shift; - my $exit_code = shift; - my $existing_id = shift || -1; - - # -1 You have bibtex errors! Not saving!"; - # -2 Displaying preview'; - # 0 Entry added successfully'; - # 1 Entry updated successfully'; - # 2 The proposed key is OK. - # 3 Proposed key exists already - HTML message - - if ( $exit_code eq 'ERR_BIBTEX' ) { - return - "You have bibtex errors! No changes were written to the database."; - } - elsif ( $exit_code eq 'PREVIEW' ) { - return 'Displaying preview. No changes were written to the database.'; - } - elsif ( $exit_code eq 'ADD_OK' ) { - return 'Entry added successfully. Switched to editing mode.'; - } - elsif ( $exit_code eq 'EDIT_OK' ) { - return 'Entry updated successfully.'; - } - elsif ( $exit_code eq 'KEY_OK' ) { - return - 'The proposed key is OK. You may continue with your edits. No changes were written to the database.'; - } - elsif ( $exit_code eq 'KEY_TAKEN' ) { - return - 'The proposed key exists already in DB under ID . + my $self = shift; + my $exit_code = shift; + my $existing_id = shift || -1; + + # -1 You have bibtex errors! Not saving!"; + # -2 Displaying preview'; + # 0 Entry added successfully'; + # 1 Entry updated successfully'; + # 2 The proposed key is OK. + # 3 Proposed key exists already - HTML message + + if ( $exit_code eq 'ERR_BIBTEX' ) { + return "You have bibtex errors! No changes were written to the database."; + } + elsif ( $exit_code eq 'PREVIEW' ) { + return 'Displaying preview. No changes were written to the database.'; + } + elsif ( $exit_code eq 'ADD_OK' ) { + return 'Entry added successfully. Switched to editing mode.'; + } + elsif ( $exit_code eq 'EDIT_OK' ) { + return 'Entry updated successfully.'; + } + elsif ( $exit_code eq 'KEY_OK' ) { + return + 'The proposed key is OK. You may continue with your edits. No changes were written to the database.'; + } + elsif ( $exit_code eq 'KEY_TAKEN' ) { + return + 'The proposed key exists already in DB under ID .
Show me the existing entry ID ' - . $existing_id - . ' in a new window + . $self->url_for( 'edit_publication', id => $existing_id ) + . '" target="_blank">Show me the existing entry ID ' + . $existing_id + . ' in a new window
Entry has not been saved. Please pick another BibTeX key. No changes were written to the database.'; - } - elsif ( defined $exit_code and $exit_code ne '' ) { - return "Unknown exit code: $exit_code"; - } + } + elsif ( defined $exit_code and $exit_code ne '' ) { + return "Unknown exit code: $exit_code"; + } } #################################################################################### sub publications_add_get { - my $self = shift; - $self->app->logger->info("Open Add Publication"); + my $self = shift; + $self->app->logger->info("Open Add Publication"); - my $msg = "Adding mode You operate on an unsaved entry!"; + my $msg = "Adding mode You operate on an unsaved entry!"; - my $bib = '@article{key' . get_current_year() . ', + my $bib = '@article{key' . get_current_year() . ', author = {Johny Example}, journal = {Journal of this and that}, publisher = {Printer-at-home publishing}, @@ -1243,229 +1245,231 @@ sub publications_add_get { day = {1--31}, }'; - my $e_dummy = $self->app->entityFactory->new_Entry( bib => $bib ); + my $e_dummy = $self->app->entityFactory->new_Entry( bib => $bib ); - $e_dummy->populate_from_bib(); - $e_dummy->generate_html( $self->app->bst, $self->app->bibtexConverter ); + $e_dummy->populate_from_bib(); + $e_dummy->generate_html( $self->app->bst, $self->app->bibtexConverter ); - $self->stash( entry => $e_dummy, msg => $msg ); - $self->render( template => 'publications/add_entry' ); + $self->stash( entry => $e_dummy, msg => $msg ); + $self->render( template => 'publications/add_entry' ); } #################################################################################### sub publications_add_post { - my $self = shift; - my $new_bib = $self->param('new_bib'); - my $param_prev = $self->param('preview'); - my $param_save = $self->param('save'); - my $param_check_key = $self->param('check_key'); - - my $action = 'default'; - $action = 'save' if $param_save; # user clicks save - $action = 'preview' if $param_prev; # user clicks preview - $action = 'check_key' if $param_check_key; # user clicks check key - - $self->app->logger->info("Adding publication. Action: > $action <."); - - $new_bib =~ s/^\s+|\s+$//g; - $new_bib =~ s/^\t//g; - - my $status_code_str; - my $existing_id = -1; - my $added_under_id = -1; - - # status_code_strings - # -2 => PREVIEW - # -1 => ERR_BIBTEX - # 0 => ADD_OK - # 1 => EDIT_OK - # 2 => KEY_OK - # 3 => KEY_TAKEN - - - my $entry = $self->app->entityFactory->new_Entry( bib => $new_bib ); - - # any action - if ( !$entry->has_valid_bibtex ) { - $status_code_str = 'ERR_BIBTEX'; - my $msg = get_adding_editing_message_for_error_code( $self, - $status_code_str, $existing_id ); - my $msg_type = 'danger'; - - $self->app->logger->info( - "Adding publication. Action: > $action <. Status code: $status_code_str." - ); - $self->stash( entry => $entry, msg => $msg, msg_type => $msg_type ); - $self->render( template => 'publications/add_entry' ); - return; - } + my $self = shift; + my $new_bib = $self->param('new_bib'); + my $param_prev = $self->param('preview'); + my $param_save = $self->param('save'); + my $param_check_key = $self->param('check_key'); - $entry->generate_html( $self->app->bst, $self->app->bibtexConverter ); - my $bibtex_warnings = FprintBibtexWarnings( $entry->warnings ); - - # any action - my $existing_entry = $self->app->repo->entries_find( - sub { $_->bibtex_key eq $entry->bibtex_key } ); - if ($existing_entry) { - $status_code_str = 'KEY_TAKEN'; - my $msg_type = 'danger'; - $existing_id = $existing_entry->id; - my $msg = get_adding_editing_message_for_error_code( $self, - $status_code_str, $existing_id ); - - $self->app->logger->info( - "Adding publication. Action: > $action <. Status code: $status_code_str." - ); - $self->stash( entry => $entry, msg => $msg, msg_type => $msg_type ); - $self->render( template => 'publications/add_entry' ); - return; - } + my $action = 'default'; + $action = 'save' if $param_save; # user clicks save + $action = 'preview' if $param_prev; # user clicks preview + $action = 'check_key' if $param_check_key; # user clicks check key + $self->app->logger->info("Adding publication. Action: > $action <."); - if ( $action eq 'preview' or $action eq 'check_key' ) { - my $status_code_str = 'PREVIEW'; - my $msg_type = 'info'; - $msg_type = 'warning' if $bibtex_warnings; - my $msg = get_adding_editing_message_for_error_code( $self, - $status_code_str, $existing_id ); - $msg .= $bibtex_warnings; + $new_bib =~ s/^\s+|\s+$//g; + $new_bib =~ s/^\t//g; - $self->app->logger->info( - "Adding publication. Action: > $action <. Status code: $status_code_str." - ); - $self->stash( entry => $entry, msg => $msg, msg_type => $msg_type ); - $self->render( template => 'publications/add_entry' ); - return; - } + my $status_code_str; + my $existing_id = -1; + my $added_under_id = -1; + # status_code_strings + # -2 => PREVIEW + # -1 => ERR_BIBTEX + # 0 => ADD_OK + # 1 => EDIT_OK + # 2 => KEY_OK + # 3 => KEY_TAKEN - if ( $action eq 'save' ) { - $status_code_str = 'ADD_OK'; - $entry->fix_month(); - $entry->generate_html( $self->app->bst, $self->app->bibtexConverter ); + my $entry = $self->app->entityFactory->new_Entry( bib => $new_bib ); - $self->app->repo->entries_save($entry); - $added_under_id = $entry->id; - - ## !!! the entry must be added before executing Freassign_authors_to_entries_given_by_array - ## why? beacuse authorship will be unable to map existing entry to the author - Freassign_authors_to_entries_given_by_array( $self->app, 1, - [$entry] ); + # any action + if ( !$entry->has_valid_bibtex ) { + $status_code_str = 'ERR_BIBTEX'; + my $msg + = get_adding_editing_message_for_error_code( $self, $status_code_str, + $existing_id ); + my $msg_type = 'danger'; + $self->app->logger->info( + "Adding publication. Action: > $action <. Status code: $status_code_str." + ); + $self->stash( entry => $entry, msg => $msg, msg_type => $msg_type ); + $self->render( template => 'publications/add_entry' ); + return; + } + + $entry->generate_html( $self->app->bst, $self->app->bibtexConverter ); + my $bibtex_warnings = FprintBibtexWarnings( $entry->warnings ); + + # any action + my $existing_entry = $self->app->repo->entries_find( + sub { $_->bibtex_key eq $entry->bibtex_key } ); + if ($existing_entry) { + $status_code_str = 'KEY_TAKEN'; + my $msg_type = 'danger'; + $existing_id = $existing_entry->id; + my $msg + = get_adding_editing_message_for_error_code( $self, $status_code_str, + $existing_id ); - my $msg_type = 'success'; - $msg_type = 'warning' if $bibtex_warnings; - my $msg = get_adding_editing_message_for_error_code( $self, - $status_code_str, $existing_id ); - $msg .= $bibtex_warnings; + $self->app->logger->info( + "Adding publication. Action: > $action <. Status code: $status_code_str." + ); + $self->stash( entry => $entry, msg => $msg, msg_type => $msg_type ); + $self->render( template => 'publications/add_entry' ); + return; + } - $self->app->logger->info( - "Adding publication. Action: > $action <. Status code: $status_code_str." - ); - $self->flash( msg => $msg, msg_type => $msg_type ); - $self->redirect_to( - $self->url_for( 'edit_publication', id => $added_under_id ) ); - return; - } + if ( $action eq 'preview' or $action eq 'check_key' ) { + my $status_code_str = 'PREVIEW'; + my $msg_type = 'info'; + $msg_type = 'warning' if $bibtex_warnings; + my $msg + = get_adding_editing_message_for_error_code( $self, $status_code_str, + $existing_id ); + $msg .= $bibtex_warnings; -} -#################################################################################### -sub publications_edit_get { - my $self = shift; - my $id = $self->param('id') || -1; + $self->app->logger->info( + "Adding publication. Action: > $action <. Status code: $status_code_str." + ); + $self->stash( entry => $entry, msg => $msg, msg_type => $msg_type ); + $self->render( template => 'publications/add_entry' ); + return; + } - $self->app->logger->info("Editing publication entry id $id"); - my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + if ( $action eq 'save' ) { - if ( !defined $entry ) { - $self->flash( msg => "There is no entry with id $id" ); - $self->redirect_to( $self->get_referrer ); - return; - } - $entry->populate_from_bib(); + $status_code_str = 'ADD_OK'; + $entry->fix_month(); $entry->generate_html( $self->app->bst, $self->app->bibtexConverter ); - $self->stash( entry => $entry ); - $self->render( template => 'publications/edit_entry' ); -} -#################################################################################### -sub publications_edit_post { - my $self = shift; - my $id = $self->param('id') // -1; - my $new_bib = $self->param('new_bib'); - my $param_prev = $self->param('preview'); - my $param_save = $self->param('save'); - my $param_check_key = $self->param('check_key'); - - my $action = 'save'; # user clicks save - $action = 'preview' if $self->param('preview'); # user clicks preview - $action = 'check_key' - if $self->param('check_key'); # user clicks check key - - $self->app->logger->info( - "Editing publication id $id. Action: > $action <."); + $self->app->repo->entries_save($entry); + $added_under_id = $entry->id; - $new_bib =~ s/^\s+|\s+$//g; - $new_bib =~ s/^\t//g; + ## !!! the entry must be added before executing Freassign_authors_to_entries_given_by_array + ## why? beacuse authorship will be unable to map existing entry to the author + Freassign_authors_to_entries_given_by_array( $self->app, 1, [$entry] ); - my ( $mentry, $status_code_str, $existing_id, $added_under_id ) - = Fhandle_add_edit_publication( $self->app, $new_bib, $id, $action, - $self->app->bst ); - my $adding_msg + my $msg_type = 'success'; + $msg_type = 'warning' if $bibtex_warnings; + my $msg = get_adding_editing_message_for_error_code( $self, $status_code_str, - $existing_id ); + $existing_id ); + $msg .= $bibtex_warnings; $self->app->logger->info( - "Editing publication id $id. Action: > $action <. Status code: $status_code_str." + "Adding publication. Action: > $action <. Status code: $status_code_str." ); + $self->flash( msg => $msg, msg_type => $msg_type ); + $self->redirect_to( + $self->url_for( 'edit_publication', id => $added_under_id ) ); + return; + } + - # status_code_strings - # -2 => PREVIEW - # -1 => ERR_BIBTEX - # 0 => ADD_OK - # 1 => EDIT_OK - # 2 => KEY_OK - # 3 => KEY_TAKEN - - my $bibtex_warnings = FprintBibtexWarnings( $mentry->warnings ); - my $msg = $adding_msg . $bibtex_warnings; - my $msg_type = 'success'; - $msg_type = 'warning' if $bibtex_warnings =~ m/Warning/; - $msg_type = 'danger' - if $status_code_str eq 'ERR_BIBTEX' - or $status_code_str eq 'KEY_TAKEN' - or $bibtex_warnings =~ m/Error/; - - $self->stash( entry => $mentry, msg => $msg, msg_type => $msg_type ); - $self->render( template => 'publications/edit_entry' ); +} +#################################################################################### +sub publications_edit_get { + my $self = shift; + my $id = $self->param('id') || -1; + + $self->app->logger->info("Editing publication entry id $id"); + + my $entry = $self->app->repo->entries_find( sub { $_->id == $id } ); + + if ( !defined $entry ) { + $self->flash( msg => "There is no entry with id $id" ); + $self->redirect_to( $self->get_referrer ); + return; + } + $entry->populate_from_bib(); + $entry->generate_html( $self->app->bst, $self->app->bibtexConverter ); + + $self->stash( entry => $entry ); + $self->render( template => 'publications/edit_entry' ); +} +#################################################################################### +sub publications_edit_post { + my $self = shift; + my $id = $self->param('id') // -1; + my $new_bib = $self->param('new_bib'); + my $param_prev = $self->param('preview'); + my $param_save = $self->param('save'); + my $param_check_key = $self->param('check_key'); + + my $action = 'save'; # user clicks save + $action = 'preview' if $self->param('preview'); # user clicks preview + $action = 'check_key' if $self->param('check_key'); # user clicks check key + + $self->app->logger->info( + "Editing publication id $id. Action: > $action <."); + + $new_bib =~ s/^\s+|\s+$//g; + $new_bib =~ s/^\t//g; + + + my ( $mentry, $status_code_str, $existing_id, $added_under_id ) + = Fhandle_add_edit_publication( $self->app, $new_bib, $id, $action, + $self->app->bst ); + my $adding_msg + = get_adding_editing_message_for_error_code( $self, $status_code_str, + $existing_id ); + + $self->app->logger->info( + "Editing publication id $id. Action: > $action <. Status code: $status_code_str." + ); + + # status_code_strings + # -2 => PREVIEW + # -1 => ERR_BIBTEX + # 0 => ADD_OK + # 1 => EDIT_OK + # 2 => KEY_OK + # 3 => KEY_TAKEN + + my $bibtex_warnings = FprintBibtexWarnings( $mentry->warnings ); + my $msg = $adding_msg . $bibtex_warnings; + my $msg_type = 'success'; + $msg_type = 'warning' if $bibtex_warnings =~ m/Warning/; + $msg_type = 'danger' + if $status_code_str eq 'ERR_BIBTEX' + or $status_code_str eq 'KEY_TAKEN' + or $bibtex_warnings =~ m/Error/; + + $self->stash( entry => $mentry, msg => $msg, msg_type => $msg_type ); + $self->render( template => 'publications/edit_entry' ); } #################################################################################### sub clean_ugly_bibtex { - my $self = shift; + my $self = shift; - # TODO: put this into config or preferences! - my @fields_to_clean - = qw(bdsk-url-1 bdsk-url-2 bdsk-url-3 date-added date-modified owner tags); + # TODO: put this into config or preferences! + my @fields_to_clean + = qw(bdsk-url-1 bdsk-url-2 bdsk-url-3 date-added date-modified owner tags); - $self->app->logger->info("Cleaning ugly Bibtex fields for all entries"); + $self->app->logger->info("Cleaning ugly Bibtex fields for all entries"); - my @entries = $self->app->repo->entries_all; - my $num_removed = 0; - foreach my $entry (@entries) { - $num_removed = $num_removed - + $entry->clean_ugly_bibtex_fields( \@fields_to_clean ); - } + my @entries = $self->app->repo->entries_all; + my $num_removed = 0; + foreach my $entry (@entries) { + $num_removed = $num_removed + + $entry->clean_ugly_bibtex_fields( \@fields_to_clean ); + } - $self->flash( - msg_type => 'info', - msg => - "All entries have now their Bibtex cleaned. I have removed $num_removed fields." - ); + $self->flash( + msg_type => 'info', + msg => + "All entries have now their Bibtex cleaned. I have removed $num_removed fields." + ); - $self->redirect_to( $self->get_referrer ); + $self->redirect_to( $self->get_referrer ); } #################################################################################### 1; diff --git a/lib/BibSpace/Controller/PublicationsExperimental.pm b/lib/BibSpace/Controller/PublicationsExperimental.pm index 4595e93..c4ee017 100644 --- a/lib/BibSpace/Controller/PublicationsExperimental.pm +++ b/lib/BibSpace/Controller/PublicationsExperimental.pm @@ -4,7 +4,6 @@ use Data::Dumper; use utf8; use Text::BibTeX; # parsing bib files use DateTime; -# use File::Slurp; # should be replaced in the future use Path::Tiny; # for creating directories use Try::Tiny; diff --git a/lib/BibSpace/Controller/PublicationsLanding.pm b/lib/BibSpace/Controller/PublicationsLanding.pm index 500d892..224eaab 100644 --- a/lib/BibSpace/Controller/PublicationsLanding.pm +++ b/lib/BibSpace/Controller/PublicationsLanding.pm @@ -5,7 +5,6 @@ use utf8; use Text::BibTeX; # parsing bib files use DateTime; -# use File::Slurp; # should be replaced in the future use Path::Tiny; # for creating directories use Try::Tiny; diff --git a/lib/BibSpace/Functions/Core.pm b/lib/BibSpace/Functions/Core.pm index e84718e..38a2ace 100644 --- a/lib/BibSpace/Functions/Core.pm +++ b/lib/BibSpace/Functions/Core.pm @@ -6,6 +6,7 @@ use Data::Dumper; use utf8; use Text::BibTeX; # parsing bib files use DateTime; + # use File::Slurp; use File::Find; @@ -17,7 +18,9 @@ use warnings; ### Security use Crypt::Eksblowfish::Bcrypt qw(bcrypt bcrypt_hash en_base64); -use Crypt::Random; + +# not crypto secure, but causes less problems than Crypt::Random; +use Bytes::Random; use Session::Token; ### Posting to Mailgun @@ -39,266 +42,271 @@ use List::MoreUtils qw(any uniq); # these are exported by default. our @EXPORT = qw( - sort_publications - fix_bibtex_national_characters - get_dir_size - validate_registration_data - check_password_policy - generate_token - encrypt_password - salt - check_password - send_email - split_bibtex_entries - decodeLatex - official_bibtex_types - random_string - create_user_id - uniqlc - get_generic_type_description - nohtml - clean_tag_name - get_month_numeric - get_current_year - get_current_month + sort_publications + fix_bibtex_national_characters + get_dir_size + validate_registration_data + check_password_policy + generate_token + encrypt_password + salt + check_password + send_email + split_bibtex_entries + decodeLatex + official_bibtex_types + random_string + create_user_id + uniqlc + get_generic_type_description + nohtml + clean_tag_name + get_month_numeric + get_current_year + get_current_month ); #################################################################################################### sub sort_publications { my (@pubs) = @_; - return reverse sort{ - $a->year <=> $b->year || - $a->month <=> $b->month || - $a->bibtex_key cmp $b->bibtex_key || - $a->id cmp $b->id + return reverse sort { + $a->year <=> $b->year + || $a->month <=> $b->month + || $a->bibtex_key cmp $b->bibtex_key + || $a->id cmp $b->id } @pubs; } #################################################################################################### + =item fix_bibtex_national_characters This function should help to avoid bibtex=>html warnings of BibStyle, like this: line 5, warning: found " at brace-depth zero in string (TeX accents in BibTeX should be inside braces) =cut + sub fix_bibtex_national_characters { - my $str = shift; - - # matches / not followed by bob: /^\/(?!bob\/)/ - # matches a word that follows a tab /(?<=\t)\w+/ + my $str = shift; - # s/(foo)bar/$1/g; - removes bar after foo - # s/foo\Kbar//g; - removes bar after foo + # matches / not followed by bob: /^\/(?!bob\/)/ + # matches a word that follows a tab /(?<=\t)\w+/ - # /(? sth {\'x} sth - $str =~ s/(? sth {\'x} sth - $str =~ s/\\'\{(\w+)\}/\{\\'$1\}/g; + # makes sth \'x sth --> sth {\'x} sth + $str =~ s/(? sth {\"x} sth - $str =~ s/\\"\{(\w+)\}/\{\\"$1\}/g; + # makes sth \'{x} sth --> sth {\'x} sth + $str =~ s/\\'\{(\w+)\}/\{\\'$1\}/g; - # makes sth \"x sth --> sth {\"x} sth - $str =~ s/(? sth {\"x} sth + $str =~ s/\\"\{(\w+)\}/\{\\"$1\}/g; - # makes sth \^x sth --> sth {\^x} sth - $str =~ s/(? sth {\"x} sth + $str =~ s/(? sth {\~x} sth - $str =~ s/(? sth {\^x} sth + $str =~ s/(? sth {\aa} sth - $str =~ s/(? sth {\~x} sth + $str =~ s/(? sth {\l} sth - $str =~ s/(? sth {\aa} sth + $str =~ s/(? sth {\ss} sth - $str =~ s/(? sth {\l} sth + $str =~ s/(? sth {\ss} sth + $str =~ s/(? 3; - return; + my $pass = shift; + return 1 if length($pass) > 3; + return; } #################################################################################################### sub generate_token { - my $self = shift; - my $token = Session::Token->new( length => 32 )->get; - return $token + my $self = shift; + my $token = Session::Token->new( length => 32 )->get; + return $token; } #################################################################################################### sub encrypt_password { - my $password = shift; - my $salt = shift || salt(); - # Generate a salt if one is not passed - - # Set the cost to 8 and append a NULL - my $settings = '$2a$08$' . $salt; - # Encrypt it - return Crypt::Eksblowfish::Bcrypt::bcrypt( $password, $settings ); + my $password = shift; + my $salt = shift || salt(); + + # Generate a salt if one is not passed + + # Set the cost to 8 and append a NULL + my $settings = '$2a$08$' . $salt; + + # Encrypt it + return Crypt::Eksblowfish::Bcrypt::bcrypt( $password, $settings ); } #################################################################################################### sub salt { - return Crypt::Eksblowfish::Bcrypt::en_base64( - Crypt::Random::makerandom_octet( Length => 16 ) ); + return Crypt::Eksblowfish::Bcrypt::en_base64( random_bytes(16) ); } #################################################################################################### sub check_password { - my $plain_password = shift; - my $hashed_password = shift; - - return if !defined $plain_password or $plain_password eq ''; - - # Regex to extract the salt - if ( $hashed_password =~ m!^\$2a\$\d{2}\$([A-Za-z0-9+\\.\/]{22})! ) { - # Use a letter by letter match rather than a complete string match to avoid timing attacks - my $match = encrypt_password( $plain_password, $1 ); - for ( my $n = 0; $n < length $match; $n++ ) { - if( substr( $match, $n, 1 ) ne substr( $hashed_password, $n, 1 ) ){ - return; - } - } - return 1; + my $plain_password = shift; + my $hashed_password = shift; + + return if !defined $plain_password or $plain_password eq ''; + + # Regex to extract the salt + if ( $hashed_password =~ m!^\$2a\$\d{2}\$([A-Za-z0-9+\\.\/]{22})! ) { + +# Use a letter by letter match rather than a complete string match to avoid timing attacks + my $match = encrypt_password( $plain_password, $1 ); + for ( my $n = 0; $n < length $match; $n++ ) { + if ( substr( $match, $n, 1 ) ne substr( $hashed_password, $n, 1 ) ) + { + return; + } } - return; + return 1; + } + return; } #################################################################################################### #################################################################################################### -sub send_email { - my $config = shift; - - - - my $uri = "https://api.mailgun.net/v3/".$config->{mailgun_domain}."/messages"; - - my $mech = WWW::Mechanize->new( ssl_opts => { SSL_version => 'TLSv1' } ); - $mech->credentials( api => $config->{mailgun_key} ); - $mech->ssl_opts( verify_hostname => 0 ); - $mech->post( $uri, - [ from => $config->{from}, - to => $config->{to}, - subject => $config->{subject}, - html => $config->{content} - ] - ); +sub send_email { + my $config = shift; + + + my $uri + = "https://api.mailgun.net/v3/" + . $config->{mailgun_domain} + . "/messages"; + + my $mech = WWW::Mechanize->new( ssl_opts => { SSL_version => 'TLSv1' } ); + $mech->credentials( api => $config->{mailgun_key} ); + $mech->ssl_opts( verify_hostname => 0 ); + $mech->post( + $uri, + [ from => $config->{from}, + to => $config->{to}, + subject => $config->{subject}, + html => $config->{content} + ] + ); } #################################################################################### sub split_bibtex_entries { - my $input = shift; - - my @bibtex_codes = (); - $input =~ s/^\s*$//g; - $input =~ s/^\s+|\s+$//g; - $input =~ s/^\t+//g; - - - for my $b_code ( split /@/, $input ) { - # skip bad splitting :P - next if length($b_code) < 10; - my $entry_code = "@".$b_code; - - push @bibtex_codes, $entry_code; - } + my $input = shift; + + my @bibtex_codes = (); + $input =~ s/^\s*$//g; + $input =~ s/^\s+|\s+$//g; + $input =~ s/^\t+//g; + - return @bibtex_codes; + for my $b_code ( split /@/, $input ) { + + # skip bad splitting :P + next if length($b_code) < 10; + my $entry_code = "@" . $b_code; + + push @bibtex_codes, $entry_code; + } + + return @bibtex_codes; } ################################################################################ sub decodeLatex { - my $str = shift; - - use TeX::Encode; - $str = decode( 'latex', $str ); - - $str =~ s/\{(\w)\}/$1/g; # makes {x} -> x - $str =~ s/\{\\\"(u)\}/ü/g; # makes {\"x} -> xe - $str =~ s/\{\\\"(U)\}/Ü/g; # makes {\"x} -> xe - $str =~ s/\{\\\"(o)\}/ö/g; # makes {\"x} -> xe - $str =~ s/\{\\\"(O)\}/Ö/g; # makes {\"x} -> xe - $str =~ s/\{\\\"(a)\}/ä/g; # makes {\"x} -> xe - $str =~ s/\{\\\"(A)\}/Ä/g; # makes {\"x} -> xe - - $str =~ s/\{\"(u)\}/ü/g; # makes {"x} -> xe - $str =~ s/\{\"(U)\}/Ü/g; # makes {"x} -> xe - $str =~ s/\{\"(o)\}/ö/g; # makes {"x} -> xe - $str =~ s/\{\"(O)\}/Ö/g; # makes {"x} -> xe - $str =~ s/\{\"(a)\}/ä/g; # makes {"x} -> xe - $str =~ s/\{\"(A)\}/Ä/g; # makes {"x} -> xe - - $str =~ s/\\\"(u)/ü/g; # makes \"{x} -> xe - $str =~ s/\\\"(U)/Ü/g; # makes \"{x} -> xe - $str =~ s/\\\"(o)/ö/g; # makes \"{x} -> xe - $str =~ s/\\\"(O)/Ö/g; # makes \"{x} -> xe - $str =~ s/\\\"(a)/ä/g; # makes \"{x} -> xe - $str =~ s/\\\"(A)/Ä/g; # makes \"{x} -> xe - - - $str =~ s/\{\\\'(\w)\}/$1/g; # makes {\'x} -> x - $str =~ s/\\\'(\w)/$1/g; # makes \'x -> x - $str =~ s/\'\'(\w)/$1/g; # makes ''x -> x - $str =~ s/\"(\w)/$1e/g; # makes "x -> xe - $str =~ s/\{\\ss\}/ss/g; # makes {\ss}-> ss - $str =~ s/\{(.*)\}/$1/g; # makes {abc..def}-> abc..def - $str =~ s/\\\^(\w)(\w)/$1$2/g; # makes \^xx-> xx - $str =~ s/\\\^(\w)/$1/g; # makes \^x-> x - $str =~ s/\\\~(\w)/$1/g; # makes \~x-> x - $str =~ s/\\//g; # removes \ - - - - $str =~ s/\{+//g; - $str =~ s/\}+//g; - return $str; + my $str = shift; + + use TeX::Encode; + $str = decode( 'latex', $str ); + + $str =~ s/\{(\w)\}/$1/g; # makes {x} -> x + $str =~ s/\{\\\"(u)\}/ü/g; # makes {\"x} -> xe + $str =~ s/\{\\\"(U)\}/Ü/g; # makes {\"x} -> xe + $str =~ s/\{\\\"(o)\}/ö/g; # makes {\"x} -> xe + $str =~ s/\{\\\"(O)\}/Ö/g; # makes {\"x} -> xe + $str =~ s/\{\\\"(a)\}/ä/g; # makes {\"x} -> xe + $str =~ s/\{\\\"(A)\}/Ä/g; # makes {\"x} -> xe + + $str =~ s/\{\"(u)\}/ü/g; # makes {"x} -> xe + $str =~ s/\{\"(U)\}/Ü/g; # makes {"x} -> xe + $str =~ s/\{\"(o)\}/ö/g; # makes {"x} -> xe + $str =~ s/\{\"(O)\}/Ö/g; # makes {"x} -> xe + $str =~ s/\{\"(a)\}/ä/g; # makes {"x} -> xe + $str =~ s/\{\"(A)\}/Ä/g; # makes {"x} -> xe + + $str =~ s/\\\"(u)/ü/g; # makes \"{x} -> xe + $str =~ s/\\\"(U)/Ü/g; # makes \"{x} -> xe + $str =~ s/\\\"(o)/ö/g; # makes \"{x} -> xe + $str =~ s/\\\"(O)/Ö/g; # makes \"{x} -> xe + $str =~ s/\\\"(a)/ä/g; # makes \"{x} -> xe + $str =~ s/\\\"(A)/Ä/g; # makes \"{x} -> xe + + + $str =~ s/\{\\\'(\w)\}/$1/g; # makes {\'x} -> x + $str =~ s/\\\'(\w)/$1/g; # makes \'x -> x + $str =~ s/\'\'(\w)/$1/g; # makes ''x -> x + $str =~ s/\"(\w)/$1e/g; # makes "x -> xe + $str =~ s/\{\\ss\}/ss/g; # makes {\ss}-> ss + $str =~ s/\{(.*)\}/$1/g; # makes {abc..def}-> abc..def + $str =~ s/\\\^(\w)(\w)/$1$2/g; # makes \^xx-> xx + $str =~ s/\\\^(\w)/$1/g; # makes \^x-> x + $str =~ s/\\\~(\w)/$1/g; # makes \~x-> x + $str =~ s/\\//g; # removes \ + + + $str =~ s/\{+//g; + $str =~ s/\}+//g; + return $str; } ################################################################################ sub official_bibtex_types { @@ -306,9 +314,10 @@ sub official_bibtex_types { ## defined by bibtex and constant return ( - 'article', 'book', 'booklet', 'conference', 'inbook', - 'incollection', 'inproceedings', 'manual', 'mastersthesis', 'misc', - 'phdthesis', 'proceedings', 'techreport', 'unpublished' + 'article', 'book', 'booklet', 'conference', + 'inbook', 'incollection', 'inproceedings', 'manual', + 'mastersthesis', 'misc', 'phdthesis', 'proceedings', + 'techreport', 'unpublished' ); } #################################################################################### @@ -321,12 +330,14 @@ sub random_string { } ################################################################################ sub get_current_month { - my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime(); + my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) + = localtime(); return ( $mon + 1 ); } ################################################################################ sub get_current_year { - my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime(); + my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) + = localtime(); return ( $year + 1900 ); } @@ -372,13 +383,14 @@ sub nohtml { my $key = shift // "key-unknown"; my $type = shift // "no-type"; return - "" - . "NO HTML " - . "" - . "($type) $key" . "
"; + "" + . "NO HTML " + . "" + . "($type) $key" . "
"; } + # ################################################################################ -sub get_generic_type_description { +sub get_generic_type_description { my $type_desc = shift; return "Talks " if $type_desc eq 'talk'; return "Publications of type " . $type_desc; @@ -389,7 +401,7 @@ sub create_user_id { my ($name) = @_; my @first_arr = $name->part('first'); - @first_arr = grep {defined $_ } @first_arr; + @first_arr = grep { defined $_ } @first_arr; my $first = join( ' ', @first_arr ); my @von_arr = $name->part('von'); @@ -408,32 +420,33 @@ sub create_user_id { $userID .= $jr if defined $jr; - $userID =~ s/\\k\{a\}/a/g; # makes \k{a} -> a $userID =~ s/\\l/l/g; # makes \l -> l - $userID =~ s/\\r\{u\}/u/g; # makes \r{u} -> u # FIXME: make sure that the letter is caught - # $userID =~ s/\\r{u}/u/g; # makes \r{u} -> u # the same but not escaped - - $userID =~ s/\{(\w)\}/$1/g; # makes {x} -> x - $userID =~ s/\{\\\"(\w)\}/$1e/g; # makes {\"x} -> xe - $userID =~ s/\{\"(\w)\}/$1e/g; # makes {"x} -> xe - $userID =~ s/\\\"(\w)/$1e/g; # makes \"{x} -> xe - $userID =~ s/\{\\\'(\w)\}/$1/g; # makes {\'x} -> x - $userID =~ s/\\\'(\w)/$1/g; # makes \'x -> x - $userID =~ s/\'\'(\w)/$1/g; # makes ''x -> x - $userID =~ s/\"(\w)/$1e/g; # makes "x -> xe - $userID =~ s/\{\\ss\}/ss/g; # makes {\ss}-> ss - $userID =~ s/\{(\w*)\}/$1/g; # makes {abc..def}-> abc..def + $userID =~ s/\\r\{u\}/u/g + ; # makes \r{u} -> u # FIXME: make sure that the letter is caught + # $userID =~ s/\\r{u}/u/g; # makes \r{u} -> u # the same but not escaped + + $userID =~ s/\{(\w)\}/$1/g; # makes {x} -> x + $userID =~ s/\{\\\"(\w)\}/$1e/g; # makes {\"x} -> xe + $userID =~ s/\{\"(\w)\}/$1e/g; # makes {"x} -> xe + $userID =~ s/\\\"(\w)/$1e/g; # makes \"{x} -> xe + $userID =~ s/\{\\\'(\w)\}/$1/g; # makes {\'x} -> x + $userID =~ s/\\\'(\w)/$1/g; # makes \'x -> x + $userID =~ s/\'\'(\w)/$1/g; # makes ''x -> x + $userID =~ s/\"(\w)/$1e/g; # makes "x -> xe + $userID =~ s/\{\\ss\}/ss/g; # makes {\ss}-> ss + $userID =~ s/\{(\w*)\}/$1/g; # makes {abc..def}-> abc..def $userID =~ s/\\\^(\w)(\w)/$1$2/g; # makes \^xx-> xx - # I am not sure if the next one is necessary - $userID =~ s/\\\^(\w)/$1/g; # makes \^x-> x - $userID =~ s/\\\~(\w)/$1/g; # makes \~x-> x - $userID =~ s/\\//g; # removes \ + # I am not sure if the next one is necessary + $userID =~ s/\\\^(\w)/$1/g; # makes \^x-> x + $userID =~ s/\\\~(\w)/$1/g; # makes \~x-> x + $userID =~ s/\\//g; # removes \ - $userID =~ s/\{//g; # removes { - $userID =~ s/\}//g; # removes } + $userID =~ s/\{//g; # removes { + $userID =~ s/\}//g; # removes } - $userID =~ s/\(.*\)//g; # removes everything between the brackets and the brackets also + $userID =~ s/\(.*\)//g + ; # removes everything between the brackets and the brackets also # print "$userID \n"; return $userID; diff --git a/lib/BibSpace/Model/Backup.pm b/lib/BibSpace/Model/Backup.pm index ab28f64..742f908 100644 --- a/lib/BibSpace/Model/Backup.pm +++ b/lib/BibSpace/Model/Backup.pm @@ -3,7 +3,7 @@ package Backup; use Data::Dumper; use utf8; -use v5.16; +use v5.16; use List::MoreUtils qw(any uniq); use List::Util qw(first); @@ -20,9 +20,9 @@ class_has 'date_format_pattern' => has 'uuid' => ( - is => 'rw', - isa => 'Str', - default => sub { create_uuid_as_string(UUID_V4) } + is => 'rw', + isa => 'Str', + default => sub { create_uuid_as_string(UUID_V4) } ); has 'name' => ( is => 'rw', isa => 'Str', default => 'normal' ); has 'type' => ( is => 'rw', isa => 'Str', default => 'storable' ); @@ -30,159 +30,153 @@ has 'filename' => ( is => 'rw', isa => 'Maybe[Str]' ); has 'dir' => ( is => 'rw', isa => 'Maybe[Str]' ); has 'allow_delete' => ( is => 'rw', isa => 'Bool', default => 1 ); has 'date' => ( - is => 'rw', - isa => 'Str', - default => sub { - my $now = DateTime->now( - formatter => DateTime::Format::Strptime->new( - pattern => Backup->date_format_pattern - ) - ); - return "$now"; - }, + is => 'rw', + isa => 'Str', + default => sub { + my $now = DateTime->now( + formatter => DateTime::Format::Strptime->new( + pattern => Backup->date_format_pattern + ) + ); + return "$now"; + }, ); #################################################################################### sub id { - shift->uuid; + shift->uuid; } #################################################################################### sub get_size { - my $self = shift; - my $size = -s $self->get_path; - $size = 0 + $size; - $size = $size / 1024 / 1024; - $size = sprintf( "%.2f", $size ); - return $size; + my $self = shift; + my $size = -s $self->get_path; + $size = 0 + $size; + $size = $size / 1024 / 1024; + $size = sprintf( "%.2f", $size ); + return $size; } #################################################################################### sub get_path { - my $self = shift; - - warn "backup->dir not set!" unless defined $self->dir; + my $self = shift; - my $file_path = $self->dir . $self->filename; - return $file_path; + warn "backup->dir not set!" unless defined $self->dir; + my $dir = $self->dir; + $dir =~ s!/*$!/!; + my $file_path = $dir . $self->filename; + return $file_path; } #################################################################################### sub is_healthy { - my $self = shift; - my $dir = $self->dir; - $dir =~ s!/*$!/!; - my $file_path = $dir . $self->filename; - return -e $file_path; + my $self = shift; + my $dir = $self->dir; + $dir =~ s!/*$!/!; + my $file_path = $dir . $self->filename; + return -e $file_path; } #################################################################################### sub get_date_readable { - my $self = shift; - - # parses from our format to default format - my $date - = DateTime::Format::Strptime->new( - pattern => Backup->date_format_pattern ) - ->parse_datetime( $self->date ); - - # sets readable format for serialization - $date->set_formatter( - DateTime::Format::Strptime->new( pattern => '%d.%m.%Y %H:%M:%S' ) ); - return "$date"; + my $self = shift; + + # parses from our format to default format + my $date = DateTime::Format::Strptime->new( + pattern => Backup->date_format_pattern )->parse_datetime( $self->date ); + + # sets readable format for serialization + $date->set_formatter( + DateTime::Format::Strptime->new( pattern => '%d.%m.%Y %H:%M:%S' ) ); + return "$date"; } #################################################################################### sub get_age { - my $self = shift; - - my $now = DateTime->now( - formatter => DateTime::Format::Strptime->new( - pattern => Backup->date_format_pattern - ) - ); - my $then - = DateTime::Format::Strptime->new( - pattern => Backup->date_format_pattern ) - ->parse_datetime( $self->date ); - - my $diff = $now->subtract_datetime($then); - return $diff; + my $self = shift; + + my $now = DateTime->now( + formatter => DateTime::Format::Strptime->new( + pattern => Backup->date_format_pattern + ) + ); + my $then = DateTime::Format::Strptime->new( + pattern => Backup->date_format_pattern )->parse_datetime( $self->date ); + + my $diff = $now->subtract_datetime($then); + return $diff; } #################################################################################### sub create { - my $self = shift; - my $name = shift; - my $type = shift // 'storable'; - - my $ext = '.dat'; - $ext = '.sql' if $type eq 'mysql'; - - my $uuid = create_uuid_as_string(UUID_V4); - - my $now = "" - . DateTime->now( - formatter => DateTime::Format::Strptime->new( - pattern => Backup->date_format_pattern - ) - ); - my $now_str = "$now"; - - my $filename = "backup_$uuid" . "_$name" . "_$type" . "_$now" . $ext; - - return Backup->new( - filename => $filename, - uuid => $uuid, - name => $name, - type => $type, - date => $now_str - ); + my $self = shift; + my $name = shift; + my $type = shift // 'storable'; + + my $ext = '.dat'; + $ext = '.sql' if $type eq 'mysql'; + + my $uuid = create_uuid_as_string(UUID_V4); + + my $now = "" + . DateTime->now( + formatter => DateTime::Format::Strptime->new( + pattern => Backup->date_format_pattern + ) + ); + my $now_str = "$now"; + + my $filename = "backup_$uuid" . "_$name" . "_$type" . "_$now" . $ext; + + return Backup->new( + filename => $filename, + uuid => $uuid, + name => $name, + type => $type, + date => $now_str + ); } #################################################################################### sub parse { - my $self = shift; - my $filename = shift; + my $self = shift; + my $filename = shift; - # say "Backup->parse: $filename"; + # say "Backup->parse: $filename"; - my @tokens = split( '_', $filename ); - die - "Parse exception: wrong filename format. Probably not BibSpace backup." - unless scalar(@tokens) == 5; - my $prefix = shift @tokens; - my $uuid = shift @tokens; - my $name = shift @tokens; - my $type = shift @tokens; - my $date = shift @tokens; + my @tokens = split( '_', $filename ); + die "Parse exception: wrong filename format. Probably not BibSpace backup." + unless scalar(@tokens) == 5; + my $prefix = shift @tokens; + my $uuid = shift @tokens; + my $name = shift @tokens; + my $type = shift @tokens; + my $date = shift @tokens; - $date =~ s/\.dat//g; - $date =~ s/\.sql//g; + $date =~ s/\.dat//g; + $date =~ s/\.sql//g; # my $now = DateTime->now(formatter => DateTime::Format::Strptime->new( pattern => Backup->date_format_pattern )); - my $now = DateTime::Format::Strptime->new( - pattern => Backup->date_format_pattern )->parse_datetime($date); - $now->set_formatter( - DateTime::Format::Strptime->new( - pattern => Backup->date_format_pattern - ) - ); - my $now_str = "$now"; - - return Backup->new( - filename => $filename, - uuid => $uuid, - name => $name, - type => $type, - date => $now_str - ); + my $now = DateTime::Format::Strptime->new( + pattern => Backup->date_format_pattern )->parse_datetime($date); + $now->set_formatter( + DateTime::Format::Strptime->new( pattern => Backup->date_format_pattern ) + ); + my $now_str = "$now"; + + return Backup->new( + filename => $filename, + uuid => $uuid, + name => $name, + type => $type, + date => $now_str + ); } #################################################################################### sub toString { - my $self = shift; - return "Backup filename '" . $self->filename . "'"; + my $self = shift; + return "Backup filename '" . $self->filename . "'"; } #################################################################################### sub equals { - my $self = shift; - my $obj = shift; - die "Comparing apples to peaches! " . ref($self) . " against " . ref($obj) - unless ref($self) eq ref($obj); - return $self->filename eq $obj->filename; + my $self = shift; + my $obj = shift; + die "Comparing apples to peaches! " . ref($self) . " against " . ref($obj) + unless ref($self) eq ref($obj); + return $self->filename eq $obj->filename; } #################################################################################### diff --git a/lib/BibSpace/TestManager.pm b/lib/BibSpace/TestManager.pm index 77227c3..73e26f4 100644 --- a/lib/BibSpace/TestManager.pm +++ b/lib/BibSpace/TestManager.pm @@ -14,8 +14,9 @@ sub apply_fixture { my $self = shift; my $app = shift; ## THIS SHOULD BE REPEATED FOR EACH TEST! - my $fixture_name = "bibspace_fixture.dat"; - my $fixture_dir = "./fixture/"; + my $fixture_file = $app->home->rel_file('fixture/bibspace_fixture.dat'); + my $fixture_name = ''.$fixture_file->basename; + my $fixture_dir = ''.$fixture_file->dirname; my $fixture = Backup->new(dir => $fixture_dir, filename =>$fixture_name); restore_storable_backup($fixture, $app); } diff --git a/lib/BibSpace/Util/Preferences.pm b/lib/BibSpace/Util/Preferences.pm index d5b61ec..e9aac83 100644 --- a/lib/BibSpace/Util/Preferences.pm +++ b/lib/BibSpace/Util/Preferences.pm @@ -1,7 +1,8 @@ package Preferences; -use v5.16; +use v5.16; use Try::Tiny; +use Path::Tiny; use Data::Dumper; use namespace::autoclean; @@ -17,30 +18,60 @@ use Moose::Util::TypeConstraints; use MooseX::Storage; with Storage( 'format' => 'JSON', 'io' => 'File' ); +has 'filename' => ( + is => 'rw', + isa => 'Str', + default => "bibspace_preferences.json", + traits => ['DoNotSerialize'] +); # I can't name it load due to deep recursion (direct or indirect) sub load_maybe { my $self = shift; - if ( -e 'bibspace_preferences.json' ) { - say "Loading prefeerences from file 'bibspace_preferences.json'."; - return Preferences->load('bibspace_preferences.json'); + my $obj = undef; + try { + $obj = Preferences->load( $self->filename ); + $obj->filename( $self->filename ); } - return $self; + catch { + $obj = $self; + warn "Cannot load preferences form file " + . $self->filename + . ". Creating new file.\n"; + Path::Tiny->new( $self->filename )->touchpath; + }; + return $obj; } + has 'run_in_demo_mode' => - ( is => 'rw', isa => 'Int', default => 0, trigger => \&_pref_changed ); + ( is => 'rw', isa => 'Int', default => 0, trigger => \&_pref_changed ); -has 'bibitex_html_converter' => - ( is => 'rw', isa => 'Str', default => 'BibStyleConverter', trigger => \&_pref_changed ); +has 'bibitex_html_converter' => ( + is => 'rw', + isa => 'Str', + default => 'BibStyleConverter', + trigger => \&_pref_changed +); # important for Preferences form to set flag "(default)" by the right list item -has 'default_bibitex_html_converter' => ( is => 'ro', isa => 'Str', default => 'BibStyleConverter' ); +has 'default_bibitex_html_converter' => + ( is => 'ro', isa => 'Str', default => 'BibStyleConverter' ); -has 'local_time_zone' => ( is => 'rw', isa => 'Str', default => 'Europe/Berlin', trigger => \&_pref_changed ); +has 'local_time_zone' => ( + is => 'rw', + isa => 'Str', + default => 'Europe/Berlin', + trigger => \&_pref_changed +); # http://search.cpan.org/~drolsky/DateTime-1.42/lib/DateTime.pm#strftime_Patterns -has 'output_time_format' => ( is => 'rw', isa => 'Str', default => '%a %d %b %T, %Y', trigger => \&_pref_changed ); +has 'output_time_format' => ( + is => 'rw', + isa => 'Str', + default => '%a %d %b %T, %Y', + trigger => \&_pref_changed +); # cron_level => last_call has 'cron' => ( @@ -68,7 +99,15 @@ sub _pref_changed { if ( $prev_val and $curr_val ne $prev_val ) { say "A preference changed to '$curr_val'."; - $self->store('bibspace_preferences.json'); + try { + Path::Tiny->new( $self->filename )->touchpath; + $self->store( $self->filename ); + } + catch { + warn "Cannot touch path " + . $self->filename + . ". Preferences will not be saved.\n"; + }; } } diff --git a/lib/BibSpace/Util/Statistics.pm b/lib/BibSpace/Util/Statistics.pm index 0bb6086..3a708d9 100644 --- a/lib/BibSpace/Util/Statistics.pm +++ b/lib/BibSpace/Util/Statistics.pm @@ -3,52 +3,87 @@ use namespace::autoclean; use feature qw( state say ); +use Path::Tiny; +use Try::Tiny; use Moose; - +use MooseX::Storage; +with Storage( 'format' => 'JSON', 'io' => 'File' ); has 'url_history' => ( - traits => ['Hash'], - is => 'ro', - isa => 'HashRef[Int]', - default => sub { {} }, - handles => { - set => 'set', - get => 'get', - has => 'exists', - defined => 'defined', - keys => 'keys', - # values => 'values', - num => 'count', - pairs => 'kv', - _clear => 'clear', - }, + traits => ['Hash'], + is => 'ro', + isa => 'HashRef[Int]', + default => sub { {} }, + handles => { + set => 'set', + get => 'get', + has => 'exists', + defined => 'defined', + keys => 'keys', + + # values => 'values', + num => 'count', + pairs => 'kv', + _clear => 'clear', + }, ); +has 'filename' => ( is => 'rw', isa => 'Str', traits => ['DoNotSerialize'] ); + +sub load_maybe { + my $self = shift; + my $obj = undef; + try { + $obj = Statistics->load( $self->filename ); + $obj->filename( $self->filename ); + } + catch { + $obj = $self; + warn "Cannot load statistics form file " + . $self->filename + . ". Creating new file.\n"; + Path::Tiny->new( $self->filename )->touchpath; + }; + + return $obj; +} + sub log_url { - my $self = shift; - my $url = shift; + my $self = shift; + my $url = shift; - if( !$self->defined($url) ){ - $self->set($url, 1); + if ( !$self->defined($url) ) { + $self->set( $url, 1 ); + } + else { + my $num = $self->get($url); + $self->set( $url, $num + 1 ); } - else{ - my $num = $self->get($url); - $self->set($url, $num+1); + try { + Path::Tiny->new( $self->filename )->touchpath; + $self->store( $self->filename ); } + catch { + warn "Cannot touch path " + . $self->filename + . ". Statistics will not be saved.\n"; + }; } sub toString { - my $self = shift; - return join("\n", $self->toLines); + my $self = shift; + return join( "\n", $self->toLines ); } sub toLines { - my $self = shift; + my $self = shift; my @lines; - my @keys = reverse sort { $self->url_history->{$a} <=> $self->url_history->{$b} } keys(%{ $self->url_history }); - foreach my $key (@keys){ + my @keys + = reverse sort { $self->url_history->{$a} <=> $self->url_history->{$b} } + keys( %{ $self->url_history } ); + foreach my $key (@keys) { my $str; my $num_calls = $self->get($key); $str .= sprintf " %-5s ", $num_calls; @@ -60,4 +95,4 @@ sub toLines { __PACKAGE__->meta->make_immutable; no Moose; -1; +1; \ No newline at end of file diff --git a/lib/BibSpace/files/templates/display/log.html.ep b/lib/BibSpace/files/templates/display/log.html.ep index 41f5bbf..ff3dcfc 100644 --- a/lib/BibSpace/files/templates/display/log.html.ep +++ b/lib/BibSpace/files/templates/display/log.html.ep @@ -25,11 +25,11 @@ @@ -58,15 +58,12 @@ $(function () { }; var log_ws = new WebSocket("<%= url_for('show_log_websocket', num => $num )->to_abs %>"); - var stats_ws = new WebSocket("<%= url_for('show_stats_websocket', num => $num )->to_abs %>"); log_ws.onopen = function () { $('#log_lines_pre').text(""); log_ws.send('.*'); }; - stats_ws.onopen = function () { - $('#log_lines_pre').text(""); - }; + log_ws.onmessage = function (msg) { var res = JSON.parse(msg.data); @@ -77,22 +74,9 @@ $(function () { log(lines); }; - stats_ws.onmessage = function (msg) { - var res = JSON.parse(msg.data); - var lines =''; - $.each(res, function(i,o) { - if(o){ lines += o+'\n';} - }); - log(lines); - }; $('#filterexpr').keyup(function (e) { - if(mode == 'log'){ - log_ws.send($('#filterexpr').val()); - } - else{ - stats_ws.send($('#filterexpr').val()); - } + log_ws.send($('#filterexpr').val()); }); $('#log_button').click(function (e) { @@ -102,13 +86,6 @@ $(function () { log_ws.send($('#filterexpr').val()); mode = 'log'; }); - $('#statistics_button').click(function (e) { - e.preventDefault(e); - $('#log_tab').removeClass("active"); - $('#statistics_tab').addClass("active"); - stats_ws.send($('#filterexpr').val()); - mode = 'stats'; - }); }); diff --git a/lib/BibSpace/files/templates/display/stats.html.ep b/lib/BibSpace/files/templates/display/stats.html.ep new file mode 100644 index 0000000..006c23a --- /dev/null +++ b/lib/BibSpace/files/templates/display/stats.html.ep @@ -0,0 +1,47 @@ +% layout 'admin'; +
+
+
+

Statistics

+
+
+ + Newer entries are at the bottom + +
+
+ + +
+
+
+
+ + + + +
+
+ + +
+
+
+
+
+% foreach my $line (@{$lines}){
+<%= $line %>
+% }
+
+
+
+
+ + diff --git a/t/000_prepare.t b/t/000_prepare.t index a3a400c..6ed2dad 100644 --- a/t/000_prepare.t +++ b/t/000_prepare.t @@ -10,7 +10,7 @@ use BibSpace; use BibSpace::Model::Backup; use BibSpace::Functions::BackupFunctions qw(restore_storable_backup); -use BibSpace::Functions::FDB; # TODO: purge DB etc. +use BibSpace::Functions::FDB; # TODO: purge DB etc. `rm log/*.log`; @@ -24,48 +24,55 @@ $t_logged_in->post_ok( form => { user => 'pub_admin', pass => 'asdf' } ); -my $self = $t_logged_in->app; -my $dbh = $self->app->db; +my $self = $t_logged_in->app; +my $dbh = $self->app->db; my $app_config = $t_logged_in->app->config; -my $db_host = $self->config->{db_host}; -my $db_user = $self->config->{db_user}; -my $db_database = $self->config->{db_database}; -my $db_pass = $self->config->{db_pass}; +my $db_host = $ENV{BIBSPACE_DB_HOST} || $self->app->config->{db_host}; +my $db_user = $ENV{BIBSPACE_DB_USER} || $self->app->config->{db_user}; +my $db_database + = $ENV{BIBSPACE_DB_DATABASE} || $self->app->config->{db_database}; +my $db_pass = $ENV{BIBSPACE_DB_PASS} || $self->app->config->{db_pass}; + note "Check if we can talk to MySQL and proper database exists."; -ok(db_connect($db_host, $db_user, $db_database, $db_pass), "Can connect to database"); +ok( db_connect( $db_host, $db_user, $db_database, $db_pass ), + "Can connect to database" ); $dbh = $self->app->db; -my $fixture_name = "bibspace_fixture.dat"; -my $fixture_dir = "./fixture/"; -SKIP: { - note "Drop database and recreate tables"; - skip "System is running in production mode!! Do not test on production!", 1 if $self->mode eq 'production'; - ok( reset_db_data($dbh), "reset_db_data"); -}; +my $fixture_file = $self->app->home->rel_file('fixture/bibspace_fixture.dat'); +my $fixture_name = ''.$fixture_file->basename; +my $fixture_dir = ''.$fixture_file->dirname; +SKIP: { + note "Drop database and recreate tables"; + skip "System is running in production mode!! Do not test on production!", + 1 + if $self->mode eq 'production'; + ok( reset_db_data($dbh), "reset_db_data" ); +} SKIP: { - note "============ APPLY DATABASE FIXTURE ============"; - skip "Directory $fixture_dir does not exist", 1 if !-e $fixture_dir.$fixture_name; + note "============ APPLY DATABASE FIXTURE ============"; + skip "Directory $fixture_dir does not exist", 1 + if !-e $fixture_dir . $fixture_name; - note "Find backup file"; - my $fixture = Backup->new(dir => $fixture_dir, filename =>$fixture_name); - - note "restore_storable_backup - read data into all layers"; - # this restores data to all layers! - restore_storable_backup($fixture, $self->app); + note "Find backup file"; + my $fixture + = Backup->new( dir => $fixture_dir, filename => $fixture_name ); + note "restore_storable_backup - read data into all layers"; -}; + # this restores data to all layers! + restore_storable_backup( $fixture, $self->app ); +} + ok(1); done_testing(); - diff --git a/t/100-unit/Author.t b/t/100-unit/Author.t index 39a59fd..4724fef 100644 --- a/t/100-unit/Author.t +++ b/t/100-unit/Author.t @@ -16,14 +16,6 @@ my $self = $t_anyone->app; use BibSpace::TestManager; TestManager->apply_fixture($self->app); -# ## THIS SHOULD BE REPEATED FOR EACH TEST! -# my $fixture_name = "bibspace_fixture.dat"; -# my $fixture_dir = "./fixture/"; -# use BibSpace::Model::Backup; -# use BibSpace::Functions::BackupFunctions qw(restore_storable_backup); -# my $fixture = Backup->new(dir => $fixture_dir, filename =>$fixture_name); -# restore_storable_backup($fixture, $self->app); - my $repo = $self->app->repo; diff --git a/util/init.d-script.sh b/util/init.d-script.sh new file mode 100644 index 0000000..fca42ea --- /dev/null +++ b/util/init.d-script.sh @@ -0,0 +1,166 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: bibspace +# Required-Start: $remote_fs $syslog mysql +# Required-Stop: $remote_fs $syslog mysql +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: BibSpace +# Description: Publication management system +### END INIT INFO + +# Author: Piotr + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="Description of the service" +NAME=bibspace +DAEMON="/home/piotr/perl/bibspace/bin/$NAME" +DAEMON_ARGS="daemon -m production -l http://*:8083" +PIDFILE=/home/piotr/perl/bibspace/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME +USER=piotr + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + + +VERBOSE=yes +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.2-14) to ensure that this file is present +# and status_of_proc is working. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + # su piotr -c "BIBSPACE_CONFIG=/etc/bibspace.conf $DAEMON $DAEMON_ARGS &" + + export BIBSPACE_CONFIG=/etc/bibspace.conf + export BIBSPACE_USE_DUMP=0 + # echo "$DAEMON $DAEMON_ARGS &" + # $DAEMON $DAEMON_ARGS & + + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --background --chuid $USER --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ + || return 1 + start-stop-daemon --start --background --chuid $USER --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 + # Add code here, if necessary, that waits for the process to be ready + # to handle requests from services started subsequently which depend + # on this one. As a last resort, sleep for some time. +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + kill -s TERM `pidof perl $DAEMON` + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --chuid $USER --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --chuid $USER --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + echo "Reload on BibSpace is not supported" + #start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + #return 0 +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + ps aux | grep "$DAEMON" + status_of_proc "perl $DAEMON" "$NAME" && exit 0 || exit $? + ;; + #reload|force-reload) + # + # If do_reload() is not implemented then leave this commented out + # and leave 'force-reload' as an alias for 'restart'. + # + #log_daemon_msg "Reloading $DESC" "$NAME" + #do_reload + #log_end_msg $? + #;; + restart|force-reload) + # + # If the "reload" option is implemented then remove the + # 'force-reload' alias + # + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 + echo "Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}" >&2 + exit 3 + ;; +esac diff --git a/util/publiste_watchdog.sh b/util/publiste_watchdog.sh index e65a7ce..d562d26 100755 --- a/util/publiste_watchdog.sh +++ b/util/publiste_watchdog.sh @@ -15,6 +15,7 @@ fi if [ "$RESTART" = true ]; then pkill -9 -f "$DIR/bin/bibspace" export BIBSPACE_CONFIG=/etc/bibspace.conf + # start-stop-daemon --start --chuid piotr --pidfile /home/piotr/perl/bibspace/bibspace.pid --exec /home/piotr/perl/bibspace/bin/bibspace -- daemon -m production -l http:/:8083 /usr/bin/hypnotoad "$DIR/bin/bibspace" fi diff --git a/util/test_server_OK.sh b/util/test_server_OK.sh index aef98c1..2adcc43 100755 --- a/util/test_server_OK.sh +++ b/util/test_server_OK.sh @@ -1,4 +1,4 @@ #!/bin/bash -response=$(curl --write-out %{http_code} --silent -k --output /dev/null https://se2.informatik.uni-wuerzburg.de/pa/test) +response=$(curl --write-out %{http_code} --silent -k --output /dev/null https://se2.informatik.uni-wuerzburg.de/pa/system_status) echo $response