From d6cd2512d89be688624b59e330b18d00616387db Mon Sep 17 00:00:00 2001 From: Xavier Guimard Date: Tue, 29 Mar 2016 21:09:55 +0000 Subject: [PATCH] New portal in progress (#595) --- .../lib/Lemonldap/NG/Portal/Main.pm | 25 +-- .../lib/Lemonldap/NG/Portal/Main/Init.pm | 142 ++++++++---------- .../lib/Lemonldap/NG/Portal/Main/Module.pm | 21 +++ .../lib/Lemonldap/NG/Portal/Main/Plugins.pm | 59 ++++++++ .../lib/Lemonldap/NG/Portal/Main/Run.pm | 9 ++ 5 files changed, 154 insertions(+), 102 deletions(-) create mode 100644 lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Module.pm create mode 100644 lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Plugins.pm create mode 100644 lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main.pm index 22cff3ee2..ba1b703cd 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main.pm @@ -5,25 +5,10 @@ use Mouse; our $VERSION = '2.0.0'; -extends qw(Lemonldap::NG::Handler::PSGI::Try Lemonldap::NG::Portal::Main::Init); - -has stack => ( is => 'rw' ); - -# ENTRY POINT METHODS -# ------------------- - -# All methods below have been declared as Lemonldap::NG::Common::PSGI::Router -# routes (see Lemonldap::NG::Portal::Main::Init) - -sub issuerForAuthUser { - my ( $self, $type, $req ) = @_; -} - -sub issuerForUnauthUser { - my ( $self, $type, $req ) = @_; -} - -# TODO in run -# - mustRedirect +extends( + 'Lemonldap::NG::Handler::PSGI::Try', + 'Lemonldap::NG::Portal::Main::Init', + 'Lemonldap::NG::Portal::Main::Run', +); 1; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm index 138e7d4a1..809912169 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Init.pm @@ -1,14 +1,12 @@ -##@file -# FastCGI package for Lemonldap::NG portal -# ##@class Lemonldap::NG::Portal::Main::Init -# FastCGI class for Lemonldap::NG portal +# Initialization part of Lemonldap::NG portal package Lemonldap::NG::Portal::Main::Init; use strict; use Mouse; use Lemonldap::NG::Common::Conf::Constants; use Lemonldap::NG::Handler::Main::Reload qw/keepConf/; +use Lemonldap::NG::Portal::Main::Plugins; our $VERSION = '2.0.0'; @@ -21,15 +19,33 @@ has conf => ( is => 'rw', default => sub { {} } ); # Sub modules has _authentication => ( is => 'rw' ); has _userDB => ( is => 'rw' ); -has _passwordDB => ( is => 'rw' ); -has _registerDB => ( is => 'rw' ); -has _issuers => ( is => 'rw' ); +# Lists to store plugins entry-points +has beforeAuthProcess => ( + is => 'rw', + isa => 'ArrayRef', + default => sub { [] } +); +has addSessionData => ( + is => 'rw', + isa => 'ArrayRef', + default => sub { [] } +); +has afterAuthProcess => ( + is => 'rw', + isa => 'ArrayRef', + default => sub { [] } +); +has forAuthUser => ( + is => 'rw', + isa => 'ArrayRef', + default => sub { [] } +); sub init { my ( $self, $args ) = @_; $args ||= {}; - return 0 unless ( $self->SUPER::init($args) ); + return 0 unless ( $self->SUPER::init( { conf => $args } ) ); $self->localConfig( { %{ HANDLER->confAcc->getLocalConf('portal') }, %$args } ); return $self->checkConf($args); @@ -63,16 +79,6 @@ sub checkConf { ); return 0; } - foreach my $key ( - qw(persistentStorage samlStorage casStorage captchaStorage oidcStorage) - ) - { - unless ( $self->conf->{$key} ) { - $self->conf->{$key} = $self->conf->{globalStorage}; - $self->conf->{ $key . 'Options' } = - $self->conf->{globalStorageOptions}; - } - } # Initialize cookie domain unless ( $self->conf->{domain} ) { @@ -81,9 +87,9 @@ sub checkConf { } $self->conf->{domain} =~ s/^([^\.])/.$1/; - # Load authentication/userDB/passwordDB modules - # --------------------------------------------- - for my $type (qw(authentication userDB passwordDB registerDB)) { + # Load authentication/userDB + # -------------------------- + for my $type (qw(authentication userDB)) { unless ( $self->conf->{$type} ) { $self->error("$type is not set"); return 0; @@ -97,56 +103,14 @@ sub checkConf { # contains arguments (key1 = scalar_value; key2 = ...) my ( $tmp, %h ) = split( /\s*[=;]\s*/, $self->conf->{$type} ); %{ $self->{conf} } = ( %h, %{ $self->{conf} } ) if (%h); - return 0 unless ( $self->loadModule( $module, "_$type" ) ); + + # Launch and initialize module + return 0 + unless ( $self->{"_$type"} = $self->loadModule($module) + and $self->{"_$type"}->init ); } - # Load issuer modules - # ------------------- - foreach my $issuerDBtype (qw(SAML OpenID CAS OpenIDConnect)) { - my $module = 'Lemonldap::NG::Portal::IssuerDB' . $issuerDBtype; - $self->lmLog( - "[IssuerDB activation] Try issuerDB module $issuerDBtype", - 'debug' ); - unless ( $self->conf->{"issuerDB${issuerDBtype}Activation"} ) { - $self->lmLog( -"[IssuerDB activation] Activation flag set to off, trying next", - 'debug' - ); - next; - } - - #TODO: regexp ? - my $path = $self->conf->{"issuerDB${issuerDBtype}Path"}; - unless ($path) { - $self->lmLog( -"[IssuerDB activation] no path found for ${issuerDBtype}. Skipping", - 'notice' - ); - next; - } - - return 0 unless ( $self->loadModule( $module, 'tmp' ) ); - $self->{issuers}->{$issuerDBtype} = $self->{tmp}; - delete $self->{tmp}; - $self->addAuthRoute( - $path, - sub { - my $self = shift; - return $self->issuerForAuthUser( $issuerDBtype, @_ ); - }, - [qw(GET POST PUT DELETE)] - ); - $self->addUnauthRoute( - $path, - sub { - my $self = shift; - return $self->issuerForUnauthUser( $issuerDBtype, @_ ); - }, - [qw(GET POST PUT DELETE)] - ); - - # TODO "check the path" - } + # Initialize trusted domain list $self->conf->{trustedDomains} ||= ""; $self->conf->{trustedDomains} = "*" if ( $self->conf->{trustedDomains} =~ /(^|\s)\*(\s|$)/ ); @@ -159,35 +123,49 @@ sub checkConf { . ')'; $self->conf->{trustedDomains} =~ s/\./\\./g; } + + # Load plugins + foreach my $plugin ( $self->enabledPlugins ) { + $self->loadPlugin($plugin) or return 0; + } } 1; } -##@method boolean loadModule(string module, boolean ignoreError) -# Load a module into portal namespace -# @param module module name -# @param ignoreError set to 1 if error should not appear in logs -# @return boolean -sub loadModule { - my ( $self, $module, $keyname ) = @_; +sub loadPlugin { + my ( $self, $plugin ) = @_; + my $obj; + return 0 + unless ( $obj = + $self->loadModule("Lemonldap::NG::Portal::Plugins::$plugin") ); + foreach my $sub ( + qw(beforeAuthProcess addSessionData afterAuthProcess forAuthUser)) + { + if ( $obj->can($sub) ) { + push @{ $self->{$sub} }, $obj->$sub; + } + } + return $obj->init; +} + +sub loadModule { + my ( $self, $module ) = @_; + my $obj; - # Load module test eval "require $module"; if ($@) { $self->error("$module load error: $@"); return 0; } eval { - $self->{$keyname} = $module->new( { p => $self, conf => $self->conf } ); + $obj = $module->new( { p => $self, conf => $self->conf } ); + $self->lmLog( "Module $module loaded", 'debug' ); }; if ($@) { $self->error("Unable to build $module object: $@"); return 0; } - return 0 unless ( $self->{$keyname} ); - $self->lmLog( "Module $module loaded", 'debug' ); - - return 1; + return $obj; } 1; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Module.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Module.pm new file mode 100644 index 000000000..b42d7f25a --- /dev/null +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Module.pm @@ -0,0 +1,21 @@ +package Lemonldap::NG::Portal::Main::Module; + +use strict; +use Mouse; + +our $VERSION = '2.0.0'; + +has p => ( is => 'rw', weak_ref => 1 ); +has conf => ( is => 'rw', weak_ref => 1 ); + +sub lmLog { + my $self = shift; + return $self->p->lmLog(@_); +} + +sub error { + my $self = shift; + return $self->p->error(@_); +} + +1; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Plugins.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Plugins.pm new file mode 100644 index 000000000..1dd2d1f2e --- /dev/null +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Plugins.pm @@ -0,0 +1,59 @@ +# This module loads known enabled plugins. To add custom modules, just add them +# into "plugins" list in lemonldap-ng.ini, section "portal" +package Lemonldap::NG::Portal::Main::Plugins; + +use strict; +use Mouse; + +our $VERSION = '2.0.0'; + +##@method list enabledPlugins +# +#@return list of enabled plugins +sub enabledPlugins { + my ($self) = @_; + my @res; + + # Search for IssuerDB* modules enabled + foreach my $key (qw(SAML OpenID CAS OpenIDConnect)) { + if ( $self->conf->{"issuerDB${key}Activation"} ) { + $self->lmlog( "IssuerDB${key} enabled", 'debug' ); + push @res, "IssuerDB$key"; + } + } + + # Check if captcha is required + # TODO: verify if this list is OK + foreach my $key ( + qw(captcha_login_enabled captcha_mail_enabled captcha_register_enabled)) + { + if ( $self->conf->{$key} ) { + $self->lmLog( 'Captcha enabled', 'debug' ); + push @res, 'Captcha'; + last; + } + } + + # Check if SOAP is enabled + # TODO: REST + push @res, 'SOAP' if ( $self->conf->{Soap} ); + + # Check if notification is enabled + push @res, 'Notifications' if ( $self->conf->{notification} ); + foreach my $type (qw(password register)) { + my $tmp = $self->conf->{$type}; + if ( $tmp and $tmp ne 'Null' ) { + $tmp = ucfirst($type) . "DB$tmp"; + $self->lmLog("$tmp enabled"); + push @res, $tmp; + } + } + + # Check if custom plugins are required + if ( $self->conf->{plugins} ) { + $self->lmLog( 'Custom plugins: ' . $self->conf->{plugins}, 'debug' ); + push @res, grep ( /\w/, split( /,\s*/, $self->conf->{plugins} ) ); + } +} + +1; diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm new file mode 100644 index 000000000..98ea83a8e --- /dev/null +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Run.pm @@ -0,0 +1,9 @@ +package Lemonldap::NG::Portal::Main::Run; + +use strict; +use Mouse; + +# TODO in run +# - mustRedirect + +1;