From 90984ea305fafd6bac7e24157b5c11a44be38f27 Mon Sep 17 00:00:00 2001
From: Guillaume Rousse <guillaume.rousse@renater.fr>
Date: Fri, 24 Nov 2017 15:24:36 +0100
Subject: [PATCH] switch to INI-format configuration file

---
 bin/account-manager.cgi.in             |  7 ++-
 bin/account-manager.pl.in              | 30 +++++------
 conf/manager.conf.in                   | 73 +++++++++-----------------
 lib/IdPAccountManager/Configuration.pm | 33 ------------
 lib/IdPAccountManager/WebRequest.pm    | 64 +++++++++++-----------
 lib/Makefile.am                        |  1 -
 6 files changed, 73 insertions(+), 135 deletions(-)
 delete mode 100644 lib/IdPAccountManager/Configuration.pm

diff --git a/bin/account-manager.cgi.in b/bin/account-manager.cgi.in
index c35180c..b57bf93 100755
--- a/bin/account-manager.cgi.in
+++ b/bin/account-manager.cgi.in
@@ -5,12 +5,11 @@ use warnings;
 use utf8;
 use lib qw(@modulesdir@);
 
-use IdPAccountManager::Configuration;
+use Config::Tiny;
+
 use IdPAccountManager::WebRequest;
 
-my $configuration = IdPAccountManager::Configuration->new(
-    file => '@sysconfdir@/manager.conf'
-);
+my $configuration = Config::Tiny->read('@sysconfdir@/manager.conf');
 
 my $request = IdPAccountManager::WebRequest->new(
     configuration => $configuration
diff --git a/bin/account-manager.pl.in b/bin/account-manager.pl.in
index 8675967..4a06378 100755
--- a/bin/account-manager.pl.in
+++ b/bin/account-manager.pl.in
@@ -7,6 +7,7 @@ use lib qw(@modulesdir@);
 use feature "switch";
 no warnings 'experimental::smartmatch';
 
+use Config::Tiny;
 use Data::Dumper;
 use English qw(-no_match_vars);
 use Getopt::Long qw(:config auto_help);
@@ -19,7 +20,6 @@ use IdPAccountManager::ServiceProvider;
 use IdPAccountManager::ServiceProvider::Manager;
 use IdPAccountManager::TestAccount;
 use IdPAccountManager::TestAccount::Manager;
-use IdPAccountManager::Configuration;
 use IdPAccountManager::SAMLMetadata;
 use IdPAccountManager::Tools;
 
@@ -46,16 +46,14 @@ pod2usage(
     -verbose => 0
 ) unless $action;
 
-my $configuration = IdPAccountManager::Configuration->new(
-    file => '@sysconfdir@/manager.conf'
-);
+my $configuration = Config::Tiny->read('@sysconfdir@/manager.conf');
 
 IdPAccountManager::DB->register_db(
-    driver   => $configuration->{database_type},
-    database => $configuration->{database_name},
-    host     => $configuration->{database_host},
-    password => $configuration->{database_password},
-    username => $configuration->{database_user}
+    driver   => $configuration->{database}->{type},
+    database => $configuration->{database}->{name},
+    host     => $configuration->{database}->{host},
+    password => $configuration->{database}->{password},
+    username => $configuration->{database}->{user}
 );
 
 my $db = IdPAccountManager::DB->new();
@@ -92,7 +90,7 @@ sub add_account {
         db          => $db,
         profile     => $options{profile},
         sp_entityid => $options{sp_entityid},
-        scope       => $configuration->{idp_scope},
+        scope       => $configuration->{idp}->{scope},
     );
 
     die "Failed to create test account\n"
@@ -100,7 +98,7 @@ sub add_account {
 
     die "Failed to save test account\n"
         unless $test_account->save(
-            accounts_validity_period => $configuration->{accounts_validity_period}
+            accounts_validity_period => $configuration->{_}->{accounts_validity_period}
         );
 
     printf "Account created:\n\tuserid: user%d\n\tpassword: %s\n",
@@ -146,8 +144,8 @@ sub list_accounts {
 
         eval {
             IdPAccountManager::Tools::update_ssp_authsources(
-                $configuration->{templates_dir},
-                $configuration->{idp_accounts_file},
+                $configuration->{_}->{templates_dir},
+                $configuration->{idp}->{accounts_file},
                 $accounts
             );
         };
@@ -164,7 +162,7 @@ sub parse_metadata {
 
     eval {
         $federation_metadata = IdPAccountManager::SAMLMetadata->new(
-            file => $configuration->{federation_metadata_file}
+            file => $configuration->{_}->{federation_metadata_file}
         );
     };
     die "unable to load federation metadata: $EVAL_ERROR" if $EVAL_ERROR;
@@ -172,7 +170,7 @@ sub parse_metadata {
     my $data = $federation_metadata->parse(id => $options{sp_entityid});
 
     printf "Document %s parsed\n",
-      $configuration->{federation_metadata_file};
+      $configuration->{_}->{federation_metadata_file};
 
     ## List SAML entities
     printf "Hashref representing the metadata:\n";
@@ -251,7 +249,7 @@ sub list_tokens {
     }
     if ($options{filter_expired}) {
         push @{ $args{query} }, creation_date =>
-          { lt => time - ($configuration->{tokens_validity_period} * 3600) };
+          { lt => time - ($configuration->{_}->{tokens_validity_period} * 3600) };
     }
 
     my $tokens =
diff --git a/conf/manager.conf.in b/conf/manager.conf.in
index 54e69cb..077f32e 100644
--- a/conf/manager.conf.in
+++ b/conf/manager.conf.in
@@ -1,11 +1,3 @@
-# Code version
-version = open Beta 1
-
-# Name of the application used in web pages, mail notices
-app_name = eduGAIN Access Check
-
-# URL of the application
-app_url = https://my.fqdn/accountmanager
 
 # Validity period of test accounts, in days
 accounts_validity_period = 7
@@ -13,50 +5,9 @@ accounts_validity_period = 7
 # Token validity period, in hours
 tokens_validity_period = 2
 
-# Scope used by the associated IdP
-idp_scope = my.fqdn
-
-# EntityID of the IdP
-idp_entityid = https://my.fqdn/simplesaml/saml2/idp/metadata.php
-
-# Name of the IdP
-idp_displayname = eduGAIN Access Check
-
-# IdP test accounts file
-idp_accounts_file = = @sysconfdir@/accounts.php
-
 # Templates directory
 templates_dir = @templatesdir@
 
-# Database type refers to a Perl Database Driver name
-# However only a subset of existing DBDs are supported by Rose::DB::Object:
-# Pg, mysql, SQLite, Informix, Oracle (DBD names are case sensitives)
-database_type = mysql
-
-# Database hostname
-database_host = localhost
-
-# Database_name
-database_name = idp_account_manager
-
-# Database username
-database_user = idpadmin
-
-# Database user password
-database_password = secret
-
-# Log file for the manager
-log_file = /opt/testidp/IdPAccountManager/log/manager.log
-
-# Log level : debug, info, trace, notice, error
-log_level = info
-
-# email address to contact admins
-admin_email = john@my.fqdn
-
-# email address to ask for support
-support_email = support@my.fqdn
-
 # Development feature
 # hard-coded list of contactPersons
 # these email addresses will be added to the list of contacts for any SP
@@ -73,3 +24,27 @@ account_profiles = fullset1, limitedset1, generic1, student1, student2, teacher1
 
 # Path to sendmail executable
 sendmail_path = /usr/sbin/sendmail
+
+[app]
+version = open Beta 1
+name = eduGAIN Access Check
+url = https://my.fqdn/accountmanager
+admin_email = john@my.fqdn
+support_email = support@my.fqdn
+
+[log]
+file = /opt/testidp/IdPAccountManager/log/manager.log
+level = info
+
+[database]
+type = mysql
+host = localhost
+name = idp_account_manager
+user = idpadmin
+password = secret
+
+[idp]
+scope = my.fqdn
+entityid = https://my.fqdn/simplesaml/saml2/idp/metadata.php
+displayname = eduGAIN Access Check
+accounts_file = @sysconfdir@/accounts.php
diff --git a/lib/IdPAccountManager/Configuration.pm b/lib/IdPAccountManager/Configuration.pm
deleted file mode 100644
index 0e956b2..0000000
--- a/lib/IdPAccountManager/Configuration.pm
+++ /dev/null
@@ -1,33 +0,0 @@
-package IdPAccountManager::Configuration;
-
-use strict;
-use warnings;
-
-use English qw(-no_match_vars);
-
-sub new {
-    my ($pkg) = shift;
-    my %args = @_;
-
-    die "missing argument 'file'" unless $args{file};
-    die "non-existing file $args{file}" unless -f $args{file};
-    die "non-readable file $args{file}" unless -r $args{file};
-
-    my $self = {};
-    my $handle;
-    open($handle, '<', $args{file}) or die "Failed to open $args{file}: $ERRNO";
-
-    while (my $line = <$handle>) {
-        next unless $line =~ /^(\S+)\s*=\s*(.+)$/;
-        my $key = $1;
-        my $val = $2;
-        $self->{$1} = $2;
-    }
-    close $handle;
-
-    bless $self, $pkg;
-
-    return $self;
-}
-
-1;
diff --git a/lib/IdPAccountManager/WebRequest.pm b/lib/IdPAccountManager/WebRequest.pm
index 0856f62..502495d 100644
--- a/lib/IdPAccountManager/WebRequest.pm
+++ b/lib/IdPAccountManager/WebRequest.pm
@@ -45,18 +45,18 @@ sub new {
 
     Log::Any::Adapter->set(
         'File',
-        $self->{configuration}->{log_file},
-        log_level => $self->{configuration}->{log_level}
+        $self->{configuration}->{log}->{file},
+        log_level => $self->{configuration}->{log}->{level}
     );
 
     $self->{logger} = Log::Any->get_logger();
 
     IdPAccountManager::DB->register_db(
-        driver          => $self->{configuration}->{database_type},
-        database        => $self->{configuration}->{database_name},
-        host            => $self->{configuration}->{database_host},
-        password        => $self->{configuration}->{database_password},
-        username        => $self->{configuration}->{database_user}
+        driver          => $self->{configuration}->{database}->{type},
+        database        => $self->{configuration}->{database}->{name},
+        host            => $self->{configuration}->{database}->{host},
+        password        => $self->{configuration}->{database}->{password},
+        username        => $self->{configuration}->{database}->{user}
     );
 
     $self->{db} = IdPAccountManager::DB->new();
@@ -127,15 +127,15 @@ sub execute {
         },
         conf => {
             accounts_validity_period => $self->{configuration}->{accounts_validity_period},
-            app_name                 => $self->{configuration}->{app_name},
-            app_url                  => $self->{configuration}->{app_url},
-            idp_scope                => $self->{configuration}->{idp_scope},
-            idp_displayname          => $self->{configuration}->{idp_displayname},
-            support_email            => $self->{configuration}->{support_email},
-            version                  => $self->{configuration}->{version},
+            app_name                 => $self->{configuration}->{app}->{name},
+            app_url                  => $self->{configuration}->{app}->{url},
+            idp_scope                => $self->{configuration}->{idp}->{scope},
+            idp_displayname          => $self->{configuration}->{idp}->{displayname},
+            support_email            => $self->{configuration}->{app}->{support_email},
+            version                  => $self->{configuration}->{app}->{version},
         },
         action => $action,
-        title  => $self->{configuration}->{app_name}
+        title  => $self->{configuration}->{app}->{name}
     };
 
     # process requested action
@@ -158,7 +158,7 @@ sub respond {
 
     ## Parse template
     my $tt2 = Template->new({
-        INCLUDE_PATH => $self->{configuration}->{templates_dir}
+        INCLUDE_PATH => $self->{configuration}->{_}->{templates_dir}
     });
 
     my $template;
@@ -185,7 +185,7 @@ sub req_account_wizard {
 
     eval {
         $metadata = IdPAccountManager::SAMLMetadata->new(
-            file => $self->{configuration}->{federation_metadata_file}
+            file => $self->{configuration}->{_}->{federation_metadata_file}
         );
     };
     if ($EVAL_ERROR) {
@@ -226,7 +226,7 @@ sub req_select_sp {
 
         eval {
             $metadata = IdPAccountManager::SAMLMetadata->new(
-                file => $self->{configuration}->{federation_metadata_file}
+                file => $self->{configuration}->{_}->{federation_metadata_file}
             );
         };
         if ($EVAL_ERROR) {
@@ -258,10 +258,10 @@ sub req_select_sp {
         }
     }
 
-    if ($self->{configuration}->{dev_sp_contact}) {
+    if ($self->{configuration}->{_}->{dev_sp_contact}) {
         # replace SP contacts
         $provider->contacts(
-            split(/, */, $self->{configuration}->{dev_sp_contact})
+            split(/, */, $self->{configuration}->{_}->{dev_sp_contact})
         );
     }
 
@@ -299,10 +299,10 @@ sub req_generate_token {
         return;
     }
 
-    if ($self->{configuration}->{dev_sp_contact}) {
+    if ($self->{configuration}->{_}->{dev_sp_contact}) {
         # replace SP contacts
         $provider->contacts(
-            split(/, */, $self->{configuration}->{dev_sp_contact})
+            split(/, */, $self->{configuration}->{_}->{dev_sp_contact})
         );
     }
 
@@ -362,9 +362,9 @@ sub req_generate_token {
     $self->{out}->{sp_entityid}   = $self->{in}->{sp_entityid};
     $self->{out}->{subtitle}      = 'Generate an authentication token';
 
-    my $sender    = $self->{configuration}->{notice_from};
+    my $sender    = $self->{configuration}->{_}->{notice_from};
     my $recipient = $self->{in}->{email_address};
-    my $sendmail  = $self->{configuration}->{sendmail_path};
+    my $sendmail  = $self->{configuration}->{_}->{sendmail_path};
 
     open(my $handle, '|-', "$sendmail -f $sender $recipient") or do {
         push @{ $self->{out}->{errors} }, "mail_notification_error";
@@ -373,7 +373,7 @@ sub req_generate_token {
     };
 
     my $tt2 = Template->new({
-        INCLUDE_PATH => $self->{configuration}->{templates_dir}
+        INCLUDE_PATH => $self->{configuration}->{_}->{templates_dir}
     });
     my $template = 'mail/send_authentication_token.tt2.eml';
     my $data = {
@@ -382,9 +382,9 @@ sub req_generate_token {
             REMOTE_ADDR => $ENV{REMOTE_ADDR},
         },
         conf => {
-            app_name      => $self->{configuration}->{app_name},
-            app_url       => $self->{configuration}->{app_url},
-            support_email => $self->{configuration}->{support_email},
+            app_name      => $self->{configuration}->{app}->{name},
+            app_url       => $self->{configuration}->{app}->{url},
+            support_email => $self->{configuration}->{app}->{support_email},
         },
         from                 => $sender,
         to                   => $recipient,
@@ -464,16 +464,16 @@ sub req_validate_token {
     ## create test accounts
     my @accounts;
 
-    foreach my $profile (split(/, */, $self->{configuration}->{account_profiles})) {
+    foreach my $profile (split(/, */, $self->{configuration}->{_}->{account_profiles})) {
         my $account = IdPAccountManager::TestAccount->new(
             db          => $self->{db},
             profile     => $profile,
             sp_entityid => $self->{in}->{sp_entityid},
-            scope       => $self->{configuration}->{idp_scope},
+            scope       => $self->{configuration}->{idp}->{scope},
         );
         next unless $account;
         next unless $account->save(
-            accounts_validity_period => $self->{configuration}->{accounts_validity_period}
+            accounts_validity_period => $self->{configuration}->{_}->{accounts_validity_period}
         );
         push @accounts, $account;
     }
@@ -490,8 +490,8 @@ sub req_validate_token {
     ## Update simpleSAMLphp configuration to enable test accounts
     eval {
     IdPAccountManager::Tools::update_ssp_authsources(
-            $self->{configuration}->{templates_dir},
-            $self->{configuration}->{idp_accounts_file},
+            $self->{configuration}->{_}->{templates_dir},
+            $self->{configuration}->{idp}->{accounts_file},
             \@accounts,
         );
     };
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 5e72617..19f70c4 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -3,7 +3,6 @@ modulesdir = $(pkgdatadir)/lib
 nobase_modules_DATA = \
 	IdPAccountManager/AuthenticationToken.pm \
 	IdPAccountManager/AuthenticationToken/Manager.pm \
-	IdPAccountManager/Configuration.pm \
 	IdPAccountManager/DB.pm \
 	IdPAccountManager/DB/Object.pm \
 	IdPAccountManager/SAMLMetadata.pm \
-- 
GitLab