From cfa90dc368a1ac3441185c94d287829d3985ef6d Mon Sep 17 00:00:00 2001
From: David Phillips <david@sighup.nz>
Date: Fri, 21 Sep 2018 14:10:58 +1200
Subject: Validate configuration parameter presence and type

---
 IdaliusConfig.pm    | 87 ++++++++++++++++++++++++++++++++++++++---------------
 Plugin/Admin.pm     |  6 ++++
 Plugin/Timezone.pm  |  3 ++
 Plugin/Titillate.pm |  5 +++
 Plugin/URL_Title.pm |  6 ++++
 5 files changed, 82 insertions(+), 25 deletions(-)

diff --git a/IdaliusConfig.pm b/IdaliusConfig.pm
index 5827209..4a8b42f 100644
--- a/IdaliusConfig.pm
+++ b/IdaliusConfig.pm
@@ -6,33 +6,68 @@ use Config::Tiny;
 
 use ListParser;
 
+sub config_describe {
+	my ($plugin, $parm) = @_;
+
+	# Plugin "_" is the root config
+	return $parm unless $plugin ne "_";
+	return "$plugin -> $parm";
+}
+
+sub assert_scalar {
+	my ($config, $plugin, $parm) = @_;
+	my $ref = $config->{$parm};
+	my $name = config_describe($plugin, $parm);
+
+	die "Error: Configuration \"$name\" must be scalar" unless
+		defined $ref
+		and ref($ref) eq "";
+}
+
+sub assert_list {
+	my ($config, $plugin, $parm) = @_;
+	my $ref = $config->{$parm};
+	my $name = config_describe($plugin, $parm);
+
+	die "Error: Configuration \"$name\" must be list" unless
+		defined $ref
+		and ref($ref) eq "ARRAY";
+}
+
+sub assert_dict {
+	my ($config, $plugin, $parm) = @_;
+	my $ref = $config->{$parm};
+	my $name = config_describe($plugin, $parm);
+
+	die "Error: Configuration \"$name\" must be dictionary" unless
+		defined $ref
+		and ref($ref) eq "HASH";
+
+}
+
+# Check presence and/or sanity of config parameters for the bot's core
+# I.e. it is up to each module to ensure its own config is there and sane,
+# normally in sub configure.
 sub check_config
 {
-	# FIXME to do: check that passed config is sane for core config vars
-	my @scalar_configs = (
-		'nick',
-		'username',
-		'ircname',
-		'server',
-		'port',
-		'usessl',
-		'sslcert',
-		'sslkey',
-		'password',
-		'must_id',
-		'quit_msg',
-		'user',
-		'group',
-		'url_len',
-		'prefix_nick',
-		'prefix');
-	my @list_configs = (
-		'channels',
-		'ignore',
-		'admins',
-		'plugins');
-	my @optional_configs = (
-		'password');
+	my ($config) = @_;
+
+	# Lists of mandatory config variables 
+	my @scalars = qw/nick username ircname server port usessl sslcert sslkey user group prefix_nick prefix/;
+	my @lists   = qw/plugins channels ignore/;
+
+	foreach my $name (@scalars) {
+		assert_scalar($config->{_}, "_", $name);
+	}
+
+	foreach my $name (@lists) {
+		assert_list($config->{_}, "_", $name);
+	}
+
+	# Special case: password is optional scalar
+	if (defined $config->{_}->{password}) {
+		assert_scalar($config->{_}, "_", "password");
+	}
 
 }
 
@@ -68,6 +103,8 @@ sub parse_config
 	$config->{_}->{gid} = getgrnam($config->{_}->{group})
 		or die "Cannot get gid of $config->{_}->{group}: $!\n";
 
+	check_config($config);
+
 	return $config;
 }
 1;
diff --git a/Plugin/Admin.pm b/Plugin/Admin.pm
index 9313110..ff64d83 100644
--- a/Plugin/Admin.pm
+++ b/Plugin/Admin.pm
@@ -3,6 +3,8 @@ package Plugin::Admin;
 use strict;
 use warnings;
 
+use IdaliusConfig qw/assert_scalar assert_list/;
+
 my $config;
 
 sub configure {
@@ -11,6 +13,10 @@ sub configure {
 	shift; # run_command
 	$config = shift;
 
+	IdaliusConfig::assert_list($config, $self, "admins");
+	IdaliusConfig::assert_scalar($config, $self, "must_id");
+	IdaliusConfig::assert_scalar($config, $self, "quit_msg");
+
 	$cmdref->("say", sub { $self->say(@_); } );
 	$cmdref->("action", sub { $self->do_action(@_); } );
 
diff --git a/Plugin/Timezone.pm b/Plugin/Timezone.pm
index c679340..5e649b1 100644
--- a/Plugin/Timezone.pm
+++ b/Plugin/Timezone.pm
@@ -4,6 +4,7 @@ use strict;
 use warnings;
 
 use DateTime;
+use IdaliusConfig qw/assert_dict/;
 
 my $config;
 
@@ -13,6 +14,8 @@ sub configure {
 	shift; # run_command
 	$config = shift;
 
+	IdaliusConfig::assert_dict($config, $self, "timezone");
+
 	$cmdref->("time", sub { $self->time(@_); } );
 
 	return $self;
diff --git a/Plugin/Titillate.pm b/Plugin/Titillate.pm
index 5ce5eeb..a113fc0 100644
--- a/Plugin/Titillate.pm
+++ b/Plugin/Titillate.pm
@@ -3,6 +3,8 @@ package Plugin::Titillate;
 use strict;
 use warnings;
 
+use IdaliusConfig qw/assert_dict/;
+
 my $config;
 
 sub configure {
@@ -10,6 +12,9 @@ sub configure {
 	my $cmdref = shift;
 	shift; # run_command
 	$config = shift;
+
+	IdaliusConfig::assert_dict($config, $self, "triggers");
+
 	return $self;
 }
 
diff --git a/Plugin/URL_Title.pm b/Plugin/URL_Title.pm
index 9d20cd6..e93de26 100644
--- a/Plugin/URL_Title.pm
+++ b/Plugin/URL_Title.pm
@@ -6,6 +6,8 @@ use HTTP::Tiny;
 use HTML::Parser;
 use utf8;
 
+use IdaliusConfig qw/assert_scalar/;
+
 my $config;
 
 sub configure {
@@ -13,6 +15,10 @@ sub configure {
 	my $cmdref = shift;
 	shift; # run_command
 	$config = shift;
+
+	IdaliusConfig::assert_scalar($config, $self, "url_len");
+	die "url_len must be positive" if $config->{url_len} <= 0;
+
 	return $self;
 }
 
-- 
cgit v1.1