Commit fca652b7 authored by Yadd's avatar Yadd
Browse files

New portal in progress (#595)

parent d6cd2512
##@file
# Demo authentication backend file
##@class
# Demo authentication backend class
package Lemonldap::NG::Portal::Auth::Demo;
use strict;
use Mouse;
extends qw(Lemonldap::NG::Portal::Auth::_WebForm);
our $VERSION = '2.0.0';
use constant AuthnLevel => 0;
## @apmethod int authInit()
# Initialize demo accounts
# @return Lemonldap::NG::Portal constant
sub init {
my $self = shift;
# Sample accounts from Doctor Who characters
$self->{_demoAccounts} = {
'rtyler' => {
'uid' => 'rtyler',
'cn' => 'Rose Tyler',
'mail' => 'rtyler@badwolf.org',
},
'msmith' => {
'uid' => 'msmith',
'cn' => 'Mickey Smith',
'mail' => 'msmith@badwolf.org',
},
'dwho' => {
'uid' => 'dwho',
'cn' => 'Doctor Who',
'mail' => 'dwho@badwolf.org',
},
};
# Add warning in log
$self->lmLog(
"Using demonstration mode, go in Manager to edit the configuration",
'warn' );
PE_OK;
}
## @apmethod int authenticate()
# Does nothing.
# @return Lemonldap::NG::Portal constant
sub authenticate {
my ($self,$req) = @_;
return PE_BADCREDENTIALS unless ( $req->{user} eq $req->{password} );
PE_OK;
}
## @apmethod int authFinish()
# Does nothing.
# @return Lemonldap::NG::Portal constant
sub authFinish {
PE_OK;
}
## @apmethod int authLogout()
# Does nothing
# @return Lemonldap::NG::Portal constant
sub authLogout {
PE_OK;
}
## @apmethod boolean authForce()
# Does nothing
# @return result
sub authForce {
return 0;
}
## @method string getDisplayType
# @return display type
sub getDisplayType {
return "standardform";
}
1;
__END__
=head1 NAME
=encoding utf8
Lemonldap::NG::Portal::AuthDemo - Perl extension for building Lemonldap::NG
compatible portals with built-in authentication.
=head1 SYNOPSIS
=head1 DESCRIPTION
This library just overload few methods of Lemonldap::NG::Portal::Simple to
create sessions for sample users.
See L<Lemonldap::NG::Portal::Simple> for usage and other methods.
=head1 SEE ALSO
L<Lemonldap::NG::Portal>, L<Lemonldap::NG::Portal::Simple>,
L<http://lemonldap-ng.org/>
=head1 AUTHOR
=over
=item Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
=back
=head1 BUG REPORT
Use OW2 system to report bug or ask for features:
L<http://jira.ow2.org>
=head1 DOWNLOAD
Lemonldap::NG is available at
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
=head1 COPYRIGHT AND LICENSE
=over
=item Copyright (C) 2012 by Clement Oudot, E<lt>clem.oudot@gmail.comE<gt>
=back
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see L<http://www.gnu.org/licenses/>.
=cut
##@file
# Web form authentication backend file
##@class
# Web form authentication backend class
package Lemonldap::NG::Portal::Auth::_WebForm;
use strict;
use Mouse;
our $VERSION = '2.0.0';
sub AuthnLevel {
return $_[0]->https ? 1 : 0;
}
## @apmethod int authInit()
# Does nothing.
sub init {
1;
}
## @apmethod int extractFormInfo()
# Read username and password from POST datas
# @return Lemonldap::NG::Portal constant
sub extractFormInfo {
my ($self,$req) = @_;
# Init captcha
if ( $self->conf->{captcha_login_enabled} ) {
eval { $self->initCaptcha(); };
$self->lmLog( "Can't init captcha: $@", "error" ) if $@;
}
# Detect first access and empty forms
my $defUser = defined $req->param('user');
my $defPassword = defined $req->param('password');
my $defOldPassword = defined $req->param('oldpassword');
# 1. No user defined at all -> first access
return PE_FIRSTACCESS unless $defUser;
# 2. If user and password defined -> login form
if ( $defUser && $defPassword ) {
return PE_FORMEMPTY
unless ( ( $req->{user} = $req->param('user') )
&& ( $req->{password} = $req->param('password') ) );
}
# 3. If user and oldpassword defined -> password form
if ( $defUser && $defOldPassword ) {
return PE_PASSWORDFORMEMPTY
unless ( ( $req->{user} = $req->param('user') )
&& ( $req->{oldpassword} = $req->param('oldpassword') )
&& ( $req->{newpassword} = $req->param('newpassword') )
&& ( $req->{confirmpassword} = $req->param('confirmpassword') ) );
}
# 4. Captcha for login form
if ( $self->conf->{captcha_login_enabled} && $defUser && $defPassword ) {
$req->{captcha_user_code} = $req->param('captcha_user_code');
$req->{captcha_check_code} = $req->param('captcha_code');
unless ( $req->{captcha_user_code} && $req->{captcha_check_code} ) {
$self->lmLog( "Captcha not filled", 'warn' );
return PE_CAPTCHAEMPTY;
}
$self->lmLog(
"Captcha data received: "
. $req->{captcha_user_code} . " and "
. $req->{captcha_check_code},
'debug'
);
# Check captcha
my $captcha_result = $self->checkCaptcha( $req->{captcha_user_code},
$req->{captcha_check_code} );
if ( $captcha_result != 1 ) {
if ( $captcha_result == -3
or $captcha_result == -2 )
{
$self->lmLog( "Captcha failed: wrong code", 'warn' );
return PE_CAPTCHAERROR;
}
elsif ( $captcha_result == 0 ) {
$self->lmLog( "Captcha failed: code not checked (file error)",
'warn' );
return PE_CAPTCHAERROR;
}
elsif ( $captcha_result == -1 ) {
$self->lmLog( "Captcha failed: code has expired", 'warn' );
return PE_CAPTCHAERROR;
}
}
$self->lmLog( "Captcha code verified", 'debug' );
}
# Other parameters
$req->{timezone} = $req->param('timezone');
# Check user
return PE_MALFORMEDUSER unless $self->get_user;
PE_OK;
}
## @apmethod int setAuthSessionInfo()
# Set password in session datas if wanted.
# @return Lemonldap::NG::Portal constant
sub setAuthSessionInfo {
my $self = shift;
# authenticationLevel
# +1 for user/password with HTTPS
$self->{_authnLevel} ||= 0;
$self->{_authnLevel} += 1 if $self->https();
$self->{sessionInfo}->{authenticationLevel} = $self->{_authnLevel};
# Store user submitted login for basic rules
$self->{sessionInfo}->{'_user'} = $self->{'user'};
# Store submitted password if set in configuration
# WARNING: it can be a security hole
if ( $self->conf->{storePassword} ) {
$self->{sessionInfo}->{'_password'} = $self->{'newpassword'}
|| $self->{'password'};
}
# Store user timezone
$self->{sessionInfo}->{'_timezone'} = $self->{'timezone'};
PE_OK;
}
1;
......@@ -48,86 +48,92 @@ sub init {
return 0 unless ( $self->SUPER::init( { conf => $args } ) );
$self->localConfig(
{ %{ HANDLER->confAcc->getLocalConf('portal') }, %$args } );
return $self->checkConf($args);
return $self->reloadConf($args);
}
sub checkConf {
my $self = shift;
return (
$self->conf->{cfgNum}
and $self->conf->{cfgNum} eq HANDLER->lmConf->{cfgNum}
? 1
: $self->reloadConf(@_)
);
}
sub reloadConf {
my ( $self, $args ) = @_;
# If handler configuration has changed, apply it
if ( !$self->conf->{cfgNum}
or $self->conf->{cfgNum} ne ( my $conf = HANDLER->lmConf->{cfgNum} ) )
my $conf = HANDLER->lmConf->{cfgNum};
# Delete keys that will be generated
foreach my $key (
qw(persistentStorage samlStorage casStorage captchaStorage oidcStorage)
)
{
delete $self->conf->{$key};
}
# Delete keys that will be generated
foreach my $key (
qw(persistentStorage samlStorage casStorage captchaStorage oidcStorage)
)
{
delete $self->conf->{$key};
}
# Load conf in portal object
foreach my $key ( keys %$conf ) {
$self->conf->{$key} =
$self->localConfig->{$key} // $conf->{$key};
}
# Load conf in portal object
foreach my $key ( keys %$conf ) {
$self->conf->{$key} = $self->localConfig->{$key} // $conf->{$key};
}
# Initialize session DBs
unless ( $self->conf->{globalStorage} ) {
$self->error(
'globalStorage not defined (perhaps configuration can not be read)'
);
return 0;
}
# Initialize session DBs
unless ( $self->conf->{globalStorage} ) {
$self->error(
'globalStorage not defined (perhaps configuration can not be read)'
);
return 0;
}
# Initialize cookie domain
unless ( $self->conf->{domain} ) {
$self->error('Configuration error: no domain');
return 0;
}
$self->conf->{domain} =~ s/^([^\.])/.$1/;
# Initialize cookie domain
unless ( $self->conf->{domain} ) {
$self->error('Configuration error: no domain');
# Load authentication/userDB
# --------------------------
for my $type (qw(authentication userDB)) {
unless ( $self->conf->{$type} ) {
$self->error("$type is not set");
return 0;
}
$self->conf->{domain} =~ s/^([^\.])/.$1/;
# Load authentication/userDB
# --------------------------
for my $type (qw(authentication userDB)) {
unless ( $self->conf->{$type} ) {
$self->error("$type is not set");
return 0;
}
my $module = ucfirst($type) . $self->conf->{$type};
$module =~ s/\s.*$//;
$module =~ s/^Authentication/Auth/;
$module = "Lemonldap::NG::Portal::$module";
# $self->conf->{authentication} and $self->conf->{userDB} can
# contains arguments (key1 = scalar_value; key2 = ...)
my ( $tmp, %h ) = split( /\s*[=;]\s*/, $self->conf->{$type} );
%{ $self->{conf} } = ( %h, %{ $self->{conf} } ) if (%h);
# Launch and initialize module
return 0
unless ( $self->{"_$type"} = $self->loadModule($module)
and $self->{"_$type"}->init );
}
my $module = ucfirst($type) . $self->conf->{$type};
$module =~ s/\s.*$//;
$module =~ s/^Authentication/Auth/;
$module = "Lemonldap::NG::Portal::$module";
# $self->conf->{authentication} and $self->conf->{userDB} can
# contains arguments (key1 = scalar_value; key2 = ...)
my ( $tmp, %h ) = split( /\s*[=;]\s*/, $self->conf->{$type} );
%{ $self->{conf} } = ( %h, %{ $self->{conf} } ) if (%h);
# Launch and initialize module
return 0
unless ( $self->{"_$type"} = $self->loadModule($module)
and $self->{"_$type"}->init );
}
# Initialize trusted domain list
$self->conf->{trustedDomains} ||= "";
$self->conf->{trustedDomains} = "*"
if ( $self->conf->{trustedDomains} =~ /(^|\s)\*(\s|$)/ );
if ( $self->conf->{trustedDomains}
and $self->conf->{trustedDomains} ne "*" )
{
$self->conf->{trustedDomains} =~ s#(^|\s+)\.#${1}[^/]+.#g;
$self->conf->{trustedDomains} = '('
. join( '|', split( /\s+/, $self->conf->{trustedDomains} ) )
. ')';
$self->conf->{trustedDomains} =~ s/\./\\./g;
}
# Initialize trusted domain list
$self->conf->{trustedDomains} ||= "";
$self->conf->{trustedDomains} = "*"
if ( $self->conf->{trustedDomains} =~ /(^|\s)\*(\s|$)/ );
if ( $self->conf->{trustedDomains}
and $self->conf->{trustedDomains} ne "*" )
{
$self->conf->{trustedDomains} =~ s#(^|\s+)\.#${1}[^/]+.#g;
$self->conf->{trustedDomains} = '('
. join( '|', split( /\s+/, $self->conf->{trustedDomains} ) ) . ')';
$self->conf->{trustedDomains} =~ s/\./\\./g;
}
# Load plugins
foreach my $plugin ( $self->enabledPlugins ) {
$self->loadPlugin($plugin) or return 0;
}
# Load plugins
foreach my $plugin ( $self->enabledPlugins ) {
$self->loadPlugin($plugin) or return 0;
}
1;
}
......
......@@ -5,5 +5,7 @@ use Mouse;
# TODO in run
# - mustRedirect
# - store AuthnLevel in session (setSessionInfo)
# $self->{sessionInfo}->{authenticationLevel} = $self->_authentication->AuthnLevel
1;
## @file
# Demo userDB mechanism
## @class
# Demo userDB mechanism class
package Lemonldap::NG::Portal::UserDB::Demo;
use strict;
use Lemonldap::NG::Portal::Simple;
our $VERSION = '2.0.0';
## @apmethod int userDBInit()
# Check AuthDemo use
# @return Lemonldap::NG::Portal constant
sub userDBInit {
my $self = shift;
unless ( $self->get_module('auth') =~ /^Demo/ ) {
$self->lmLog( "Use UserDBDemo only with AuthDemo", 'error' );
return PE_ERROR;
}
# Sample accounts from Doctor Who characters
$self->{_demoAccounts} = {
'rtyler' => {
'uid' => 'rtyler',
'cn' => 'Rose Tyler',
'mail' => 'rtyler@badwolf.org',
},
'msmith' => {
'uid' => 'msmith',
'cn' => 'Mickey Smith',
'mail' => 'msmith@badwolf.org',
},
'dwho' => {
'uid' => 'dwho',
'cn' => 'Doctor Who',
'mail' => 'dwho@badwolf.org',
},
};
PE_OK;
}
## @apmethod int getUser()
# Check known accounts
# @return Lemonldap::NG::Portal constant
sub getUser {
my ( $self, $req ) = @_;
# Search by login
if ( $req->{user} ) {
return PE_OK
if ( defined $self->{_demoAccounts}->{ $req->{user} } );
}
# Search by mail
if ( $req->{mail} ) {
return PE_OK
if (
my $req->{user} =
grep { $self->{_demoAccounts}->{$_}->{mail} eq $req->{mail} }
keys %{ $self->{_demoAccounts} }
);
}
PE_USERNOTFOUND;
}
## @apmethod int setSessionInfo()
# Get sample data
# @return Lemonldap::NG::Portal constant
sub setSessionInfo {
my ( $self, $req ) = @_;
my %vars = ( %{ $self->conf->{exportedVars} },
%{ $self->conf->{demoExportedVars} } );
while ( my ( $k, $v ) = each %vars ) {
$req->{sessionInfo}->{$k} =
$self->{_demoAccounts}->{ $req->{user} }->{$v}
|| "";
}
PE_OK;
}
## @apmethod int setGroups()
# Do nothing
# @return Lemonldap::NG::Portal constant
sub setGroups {
PE_OK;
}
1;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment