diff --git a/modules/lemonldap-ng-portal/example/index_skin.pl b/modules/lemonldap-ng-portal/example/index_skin.pl
index 61f0d5b66..66700fb05 100755
--- a/modules/lemonldap-ng-portal/example/index_skin.pl
+++ b/modules/lemonldap-ng-portal/example/index_skin.pl
@@ -75,41 +75,26 @@ if ( $portal->process() ) {
# 1.3 Case : display menu
else {
- $skinfile = 'menu.tpl';
- # Menu creation
- use Lemonldap::NG::Portal::Menu;
- my $menu = Lemonldap::NG::Portal::Menu->new(
- {
- portalObject => $portal,
- modules => {
- appslist => $portal->{portalDisplayAppslist},
- password => $portal->{portalDisplayChangePassword},
- logout => $portal->{portalDisplayLogout},
- },
- }
- );
+ # Initialize menu elements
+ $portal->_sub('menuInit');
+
+ $skinfile = 'menu2.tpl';
+
%templateParams = (
AUTH_USER => $portal->{sessionInfo}->{ $portal->{portalUserAttr} },
AUTOCOMPLETE => $portal->{portalAutocomplete},
SKIN => $skin,
- AUTH_ERROR => $portal->error,
- AUTH_ERROR_TYPE => $portal->error_type,
- DISPLAY_APPSLIST => $menu->displayModule("appslist"),
- DISPLAY_PASSWORD => $menu->displayModule("password"),
- DISPLAY_LOGOUT => $menu->displayModule("logout"),
- DISPLAY_TAB => $menu->displayTab,
+ AUTH_ERROR => $portal->error( undef, $portal->{menuError} ),
+ AUTH_ERROR_TYPE => $portal->error_type( $portal->{menuError} ),
+ DISPLAY_TAB => $portal->{menuDisplayTab},
LOGOUT_URL => "$ENV{SCRIPT_NAME}?logout=1",
REQUIRE_OLDPASSWORD => $portal->{portalRequireOldPassword},
+ DISPLAY_MODULES => $portal->{menuDisplayModules},
+ APPSLIST_MENU => $portal->{menuAppslistMenu},
+ APPSLIST_DESC => $portal->{menuAppslistDesc},
);
- if ( $menu->displayModule("appslist") ) {
- %templateParams = (
- %templateParams,
- APPSLIST_MENU => $menu->appslistMenu,
- APPSLIST_DESC => $menu->appslistDescription
- );
- }
}
}
diff --git a/modules/lemonldap-ng-portal/example/skins/pastel/login.tpl b/modules/lemonldap-ng-portal/example/skins/pastel/login.tpl
index e5d03ef21..aa1084b7d 100644
--- a/modules/lemonldap-ng-portal/example/skins/pastel/login.tpl
+++ b/modules/lemonldap-ng-portal/example/skins/pastel/login.tpl
@@ -101,8 +101,12 @@
+
+
+
+
diff --git a/modules/lemonldap-ng-portal/example/skins/pastel/menu.tpl b/modules/lemonldap-ng-portal/example/skins/pastel/menu.tpl
index 96f2d8a3e..dce94888f 100644
--- a/modules/lemonldap-ng-portal/example/skins/pastel/menu.tpl
+++ b/modules/lemonldap-ng-portal/example/skins/pastel/menu.tpl
@@ -8,30 +8,47 @@
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
diff --git a/modules/lemonldap-ng-portal/example/skins/pastel/password.tpl b/modules/lemonldap-ng-portal/example/skins/pastel/password.tpl
index e629ccbfa..b32ca5f6c 100644
--- a/modules/lemonldap-ng-portal/example/skins/pastel/password.tpl
+++ b/modules/lemonldap-ng-portal/example/skins/pastel/password.tpl
@@ -1,4 +1,3 @@
-
-
diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Menu.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Menu.pm
index 86f72f99a..79fef1bbf 100644
--- a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Menu.pm
+++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Menu.pm
@@ -7,143 +7,48 @@ package Lemonldap::NG::Portal::Menu;
use strict;
use warnings;
-require Lemonldap::NG::Common::CGI;
-use Lemonldap::NG::Portal::SharedConf;
+use Lemonldap::NG::Portal::Simple;
use Lemonldap::NG::Common::Safelib; #link protected safe Safe object
use Safe;
use constant SAFEWRAP => ( Safe->can("wrap_code_ref") ? 1 : 0 );
-#inherits Net::LDAP::Control::PasswordPolicy
+our $VERSION = '0.4';
-our $VERSION = '0.3';
+# Global variables
+our ( $defaultCondition, $locationCondition, $locationRegexp, $cfgNum,
+ $catlevel ) = ( undef, undef, undef, 0, 0 );
-### ACCESS CONTROL DISPLAY SYSTEM
-
-our ( $defaultCondition, $locationCondition, $locationRegexp, $cfgNum, $path ) =
- ( undef, undef, undef, 0 );
-
-## @method private Safe _safe()
-# Build and returns security jail.
-# Includes custom functions
-# @return Safe object
-sub _safe {
+## @method void menuInit()
+# Prepare menu template elements
+# @return nothing
+sub menuInit {
my $self = shift;
- return $self->{_safe} if ( $self->{_safe} );
- $self->{_safe} = new Safe;
- $self->{customFunctions} ||= $self->{portalObject}->{customFunctions};
- my @t =
- $self->{customFunctions} ? split( /\s+/, $self->{customFunctions} ) : ();
- foreach (@t) {
- my $sub = $_;
- unless (/::/) {
- $sub = "$self->{caller}::$_";
- }
- else {
- s/^.*:://;
- }
- next if ( __PACKAGE__->can($_) );
- eval "sub $_ {
- return $sub(\$path,\@_);
- }";
- $self->{portalObject}->lmLog( $@, 'error' ) if ($@);
- }
- $self->{_safe}->share_from( 'main', ['%ENV'] );
- $self->{_safe}->share_from( 'Lemonldap::NG::Common::Safelib',
- $Lemonldap::NG::Common::Safelib::functions );
- $self->{_safe}->share( '&encode_base64', @t );
- return $self->{_safe};
-}
-
-my $catlevel = 0;
-
-##@cmethod Lemonldap::NG::Portal::Menu new(hashRef args)
-# Constructor.
-# $args->{portalObject} is required.
-#@param $args hash reference
-#@return new object
-sub new {
- my $class = shift;
- my $self = {};
- bless( $self, $class );
-
- # Get configuration
- $self->Lemonldap::NG::Portal::Simple::getConf(@_)
- or Lemonldap::NG::Common::CGI->abort(
- "Unable to read $class->new() parameters");
-
- # Portal is required
- Lemonldap::NG::Common::CGI->abort("Portal object required")
- unless ( $self->{portalObject} );
-
- # Fill sessionInfo (yet done in portal...)
- #&Lemonldap::NG::Portal::Simple::getSessionInfo( $self->{portalObject} );
-
- # Default values
$self->{apps}->{imgpath} ||= '/apps/';
- $self->{modules}->{appslist} = 0
- unless defined $self->{modules}->{appslist};
- $self->{modules}->{password} = 0
- unless defined $self->{modules}->{password};
- $self->{modules}->{logout} = 1 unless defined $self->{modules}->{logout};
- $self->{'caller'} = caller;
- # Store POST data in $self->{portalObject}
- $self->{portalObject}->{'newpassword'} =
- $self->{portalObject}->param('newpassword');
- $self->{portalObject}->{'confirmpassword'} =
- $self->{portalObject}->param('confirmpassword');
- $self->{portalObject}->{'oldpassword'} =
- $self->{portalObject}->param('oldpassword');
- $self->{portalObject}->{'dn'} =
- $self->{portalObject}->{sessionInfo}->{'dn'};
- $self->{portalObject}->{'user'} =
- $self->{portalObject}->{sessionInfo}->{'_user'};
+ # Modules to display
+ $self->{menuModules} ||= "Appslist ChangePassword Logout";
+ $self->{menuDisplayModules} = $self->displayModules();
- # Change password (only if newpassword submitted)
- $self->{portalObject}->{error} =
- $self->{portalObject}->_subProcess(qw(passwordDBInit modifyPassword))
- if $self->{portalObject}->{'newpassword'};
+ # Extract password from POST data
+ $self->{oldpassword} = $self->param('oldpassword');
+ $self->{newpassword} = $self->param('newpassword');
+ $self->{confirmpassword} = $self->param('confirmpassword');
+ $self->{dn} = $self->{sessionInfo}->{dn};
+ $self->{user} = $self->{sessionInfo}->{_user};
- return $self;
-}
+ # Try to change password
+ $self->{menuError} = $self->_subProcess(qw(passwordDBInit modifyPassword));
-## @method boolean displayModule(string modulename)
-# Return true if the user can see the module.
-# Use for HTML::Template variable.
-# @param $modulename string
-# @return boolean
-sub displayModule {
- my ( $self, $modulename ) = splice @_;
+ # Default menu error code
+ $self->{menuError} ||= $self->{error};
- # Manage "0" and "1" rules
- return 1 if ( $self->{modules}->{$modulename} eq "1" );
- return 0 if ( $self->{modules}->{$modulename} eq "0" );
-
- # Else parse display condition
- my $cond = $self->{modules}->{$modulename};
- $cond =~ s/\$(\w+)/$self->{portalObject}->{sessionInfo}->{$1}/g;
- return (
- SAFEWRAP
- ? $self->_safe->wrap_code_ref(
- $self->_safe->reval("sub{return($cond)}")
- )
- : $self->_safe->reval("sub{return($cond)}")
- );
-}
-
-## @method string displayTab()
-# Tells which tab should be selected.
-# Design for Jquery tabs.
-# @return password, appslist or logout
-sub displayTab {
- my $self = shift;
-
- # Display password tab if password change is needed or failed
- return "password"
+ # Tab to display
+ $self->{menuDisplayTab} = "appslist";
+ $self->{menuDisplayTab} = "password"
if (
(
scalar(
- grep { $_ == $self->{portalObject}->{error} } (
+ grep { $_ == $self->{menuError} } (
25, #PE_PP_CHANGE_AFTER_RESET
27, #PE_PP_MUST_SUPPLY_OLD_PASSWORD
28, #PE_PP_INSUFFICIENT_PASSWORD_QUALITY
@@ -157,11 +62,40 @@ sub displayTab {
)
)
)
- && $self->displayModule("password")
);
- return "appslist" if ( $self->displayModule("appslist") );
- return "logout";
+ # Application list
+ $self->{menuAppslistMenu} = $self->appslistMenu();
+ $self->{menuAppslistDesc} = $self->appslistDescription();
+
+ return;
+}
+
+## @method arrayref displayModules()
+# List modules that can be displayed in Menu
+# @return modules list
+sub displayModules {
+ my $self = shift;
+ my $displayModules = [];
+
+ # Modules list
+ my @modules = split( /\s/, $self->{menuModules} );
+
+ # Foreach module, eval condition
+ # Store module in result if condition is valid
+ foreach my $module (@modules) {
+ my $cond = $self->{ 'portalDisplay' . $module };
+ $cond = 1 unless defined $cond;
+ $cond =~ s/\$(\w+)/$self->{sessionInfo}->{$1}/g;
+
+ $self->lmLog( "Evaluate condition $cond for module $module", 'debug' );
+
+ if ( $self->safe->reval($cond) ) {
+ push @$displayModules, { $module => 1 };
+ }
+ }
+
+ return $displayModules;
}
## @method string appslistMenu()
@@ -171,15 +105,15 @@ sub appslistMenu {
my $self = shift;
# We no more use XML file for menu configuration
- unless ( defined $self->{portalObject}->{applicationList} ) {
- $self->{portalObject}->abort(
+ unless ( defined $self->{applicationList} ) {
+ $self->abort(
"XML menu configuration is deprecated",
"Please use lmMigrateConfFiles2ini to migrate your menu configuration"
);
}
# Use configuration to get menu parameters
- my $applicationList = $self->{portalObject}->{applicationList};
+ my $applicationList = $self->{applicationList};
my $filteredList = $self->_filter($applicationList);
return $self->_displayConfCategory( "", $applicationList, $catlevel );
}
@@ -191,8 +125,8 @@ sub appslistDescription {
my $self = shift;
# We no more use XML file for menu configuration
- unless ( defined $self->{portalObject}->{applicationList} ) {
- $self->{portalObject}->lmLog(
+ unless ( defined $self->{applicationList} ) {
+ $self->lmLog(
"XML menu configuration is deprecated. Please use lmMigrateConfFiles2ini to migrate your menu configuration",
'error'
);
@@ -200,7 +134,7 @@ sub appslistDescription {
}
# Use configuration to get menu parameters
- my $applicationList = $self->{portalObject}->{applicationList};
+ my $applicationList = $self->{applicationList};
return $self->_displayConfDescription( "", $applicationList );
}
@@ -257,16 +191,6 @@ sub _displayConfCategory {
return $html;
}
-## @method private string _userParam(string arg)
-# Returns value of $arg variable stored in session.
-# @param $arg string to modify
-# @return string modified
-sub _userParam {
- my ( $self, $arg ) = splice @_;
- $arg =~ s/\$([\w]+)/$self->{portalObject}->{sessionInfo}->{$1}/g;
- return $arg;
-}
-
## @method private string _displayConfApplication()
# Creates HTML code for an application.
# @param $appid Application ID
@@ -475,11 +399,11 @@ sub _isCategoryEmpty {
sub _grant {
my ( $self, $uri ) = splice @_;
$uri =~ m{(\w+)://([^/:]+)(:\d+)?(/.*)?$} or return 0;
- my ( $protocol, $vhost, $port );
+ my ( $protocol, $vhost, $port, $path );
( $protocol, $vhost, $port, $path ) = ( $1, $2, $3, $4 );
$path ||= '/';
$self->_compileRules()
- if ( $cfgNum != $self->{portalObject}->{cfgNum} );
+ if ( $cfgNum != $self->{cfgNum} );
return -1 unless ( defined( $defaultCondition->{$vhost} ) );
if ( defined $locationRegexp->{$vhost} ) { # Not just a default rule
@@ -490,8 +414,8 @@ sub _grant {
}
}
unless ( $defaultCondition->{$vhost} ) {
- $self->{portalObject}
- ->lmLog( "Application $uri did not match any configured virtual host",
+ $self->lmLog(
+ "Application $uri did not match any configured virtual host",
'warn' );
return 0;
}
@@ -504,18 +428,18 @@ sub _grant {
# @return True
sub _compileRules {
my $self = shift;
- foreach my $vhost ( keys %{ $self->{portalObject}->{locationRules} } ) {
+ foreach my $vhost ( keys %{ $self->{locationRules} } ) {
my $i = 0;
- foreach ( keys %{ $self->{portalObject}->{locationRules}->{$vhost} } ) {
+ foreach ( keys %{ $self->{locationRules}->{$vhost} } ) {
if ( $_ eq 'default' ) {
$defaultCondition->{$vhost} =
$self->_conditionSub(
- $self->{portalObject}->{locationRules}->{$vhost}->{$_} );
+ $self->{locationRules}->{$vhost}->{$_} );
}
else {
$locationCondition->{$vhost}->[$i] =
$self->_conditionSub(
- $self->{portalObject}->{locationRules}->{$vhost}->{$_} );
+ $self->{locationRules}->{$vhost}->{$_} );
$locationRegexp->{$vhost}->[$i] = qr/$_/;
$i++;
}
@@ -524,7 +448,7 @@ sub _compileRules {
# Default policy
$defaultCondition->{$vhost} ||= $self->_conditionSub('accept');
}
- $cfgNum = $self->{portalObject}->{cfgNum};
+ $cfgNum = $self->{cfgNum};
1;
}
@@ -539,12 +463,12 @@ sub _conditionSub {
return sub { 0 }
if ( $cond =~ /^(?:deny$|logout)/i );
$cond =~ s/\$date/&POSIX::strftime("%Y%m%d%H%M%S",localtime())/e;
- $cond =~ s/\$(\w+)/\$self->{portalObject}->{sessionInfo}->{$1}/g;
+ $cond =~ s/\$(\w+)/\$self->{sessionInfo}->{$1}/g;
my $sub = "sub {my \$self = shift; return ( $cond )}";
$sub = (
SAFEWRAP
- ? $self->_safe->wrap_code_ref( $self->_safe->reval($sub) )
- : $self->_safe->reval($sub)
+ ? $self->safe->wrap_code_ref( $self->safe->reval($sub) )
+ : $self->safe->reval($sub)
);
return $sub;
}
@@ -557,45 +481,23 @@ __END__
=encoding utf8
-Lemonldap::NG::Portal::Menu - Enhanced menu to display to authenticated users
+Lemonldap::NG::Portal::Menu - Portal menu functions
=head1 SYNOPSIS
- use Lemonldap::NG::Portal::Menu;
- my $menu = Lemonldap::NG::Portal::Menu->new(
+ use Lemonldap::NG::Portal::Simple;
+ my $portal = Lemonldap::NG::Portal::Simple->new(
{
- portalObject => $portal,
- apps => {
- xmlfile => "/var/lib/lemonldap-ng/conf/apps-list.xml",
- imgpath => "apps/",
- },
- modules => {
- appslist => 1,
- password => 1,
- logout => 1,
- },
}
);
- # Print HTML code of authorized applications list
- print $menu->appslistMenu;
+ # Init portal menu
+ $portal->menuInit();
+
=head1 DESCRIPTION
-Lemonldap::NG::Portal::Menu provides these web modules:
-
-=over
-
-=item * Application list: display a full menu with all authorized applications
-
-=item * Password: allow the user to change its password (with LDAP auth only)
-
-=item * Logout: display a simple logout confirmation page
-
-=back
-
-These web modules are designed to be used in HTML::Template, with the help of
-Jquery scripts. Without that, this will only output raw HTML code.
+Lemonldap::NG::Portal::Menu is used to build menu.
=head1 SEE ALSO
diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm
index 4c7c98db8..1897d88c6 100644
--- a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm
+++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm
@@ -362,6 +362,9 @@ sub new {
. ')';
}
+ # Load Menu functions
+ $self->loadModule('Lemonldap::NG::Portal::Menu');
+
return $self;
}
@@ -644,9 +647,10 @@ _RETURN $string Error string
=cut
-##@method string error(string lang)
+##@method string error(string lang, int code)
# error calls Portal/_i18n.pm to display error in the wanted language.
#@param $lang optional (browser language is used instead)
+#@param $code optional error code
#@return error message
sub error {
my $self = shift;
@@ -1904,7 +1908,7 @@ sub issuerForAuthUser {
sub autoRedirect {
my $self = shift;
- # default redirection URL
+ # Default redirection URL
$self->{urldc} ||= $self->{portal}
if ( $self->{mustRedirect} or $self->info() );
diff --git a/modules/lemonldap-ng-portal/t/50-Lemonldap-NG-Portal-Menu.t b/modules/lemonldap-ng-portal/t/50-Lemonldap-NG-Portal-Menu.t
index ac6e6a2b2..e2b060221 100644
--- a/modules/lemonldap-ng-portal/t/50-Lemonldap-NG-Portal-Menu.t
+++ b/modules/lemonldap-ng-portal/t/50-Lemonldap-NG-Portal-Menu.t
@@ -5,7 +5,7 @@
# change 'tests => 1' to 'tests => last_test_to_print';
-use Test::More tests => 3;
+use Test::More tests => 2;
BEGIN { use_ok('Lemonldap::NG::Portal::Menu') }
#########################
@@ -13,14 +13,19 @@ BEGIN { use_ok('Lemonldap::NG::Portal::Menu') }
# Insert your test code below, the Test::More module is use()ed here so read
# its man page ( perldoc Test::More ) for help writing this test script.
-my $tmp;
+$ENV{REQUEST_METHOD} = 'GET';
-my ( $m, $p );
+# Build portal
+my $p = Lemonldap::NG::Portal::Simple->new({
+ globalStorage => 'Apache::Session::File',
+ domain => 'example.com',
+ error => 0,
+ applicationList => {},
+});
-$p = bless { cookieName => 'lemonldap', }, 'Lemonldap::NG::Portal::SharedConf';
+# Init menu
+$p->menuInit();
-ok( $m = Lemonldap::NG::Portal::Menu->new( { portalObject => $p } ),
- 'constructor' );
-
-ok( $m->isa('Lemonldap::NG::Portal::Menu'), 'object returned' );
+ok( ref $p->{menuDisplayModules} eq 'ARRAY' ,
+ 'Modules displayed' );