lemonldap-ng/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Api/Providers/CasApp.pm

455 lines
14 KiB
Perl
Raw Normal View History

package Lemonldap::NG::Manager::Api::Providers::CasApp;
our $VERSION = '2.0.9';
package Lemonldap::NG::Manager::Api;
use 5.10.0;
use utf8;
use Mouse;
use Lemonldap::NG::Manager::Conf::Parser;
extends 'Lemonldap::NG::Manager::Api::Common';
sub getCasAppByConfKey {
my ( $self, $req ) = @_;
my $confKey = $req->params('confKey')
or return $self->sendError( $req, 'confKey is missing', 400 );
$self->logger->debug("[API] CAS App $confKey configuration requested");
# Get latest configuration
my $conf = $self->_confAcc->getConf;
my $casApp = $self->_getCasAppByConfKey( $conf, $confKey );
# Return 404 if not found
return $self->sendError( $req,
"CAS application '$confKey' not found", 404 )
unless ( defined $casApp );
return $self->sendJSONresponse( $req, $casApp );
}
sub findCasAppByConfKey {
my ( $self, $req ) = @_;
my $pattern = (
defined $req->params('uPattern')
? $req->params('uPattern')
: ( defined $req->params('pattern') ? $req->params('pattern') : undef )
);
return $self->sendError( $req, 'Invalid input: pattern is missing', 400 )
unless ( defined $pattern );
unless ( $pattern = $self->_getRegexpFromPattern($pattern) ) {
return $self->sendError( $req, 'Invalid input: pattern is invalid',
400 );
}
$self->logger->debug(
"[API] Find CAS Apps by confKey regexp $pattern requested");
# Get latest configuration
my $conf = $self->_confAcc->getConf;
my @casApps =
map { $_ =~ $pattern ? $self->_getCasAppByConfKey( $conf, $_ ) : () }
keys %{ $conf->{casAppMetaDataOptions} };
return $self->sendJSONresponse( $req, [@casApps] );
}
sub findCasAppsByServiceUrl {
my ( $self, $req ) = @_;
my $serviceUrl = (
defined $req->params('uServiceUrl') ? $req->params('uServiceUrl')
: (
defined $req->params('serviceUrl') ? $req->params('serviceUrl')
: undef
)
);
return $self->sendError( $req, 'Invalid input: serviceUrl is missing', 400 )
unless ( defined $serviceUrl );
$self->logger->debug("[API] Find CAS Apps by service URL $serviceUrl requested");
# Get latest configuration
my $conf = $self->_confAcc->getConf;
my @casApps = $self->_getCasAppsByServiceUrl( $conf, $serviceUrl );
return $self->sendJSONresponse( $req, [@casApps] );
}
sub addCasApp {
my ( $self, $req ) = @_;
my $add = $req->jsonBodyToObj;
return $self->sendError( $req, "Invalid input: " . $req->error, 400 )
unless ($add);
return $self->sendError( $req, 'Invalid input: confKey is missing', 400 )
unless ( defined $add->{confKey} );
return $self->sendError( $req, 'Invalid input: confKey is not a string',
400 )
if ( ref $add->{confKey} );
# return $self->sendError( $req, 'Invalid input: clientId is missing', 400 )
# unless ( defined $add->{clientId} );
#
# return $self->sendError( $req, 'Invalid input: clientId is not a string',
# 400 )
# if ( ref $add->{clientId} );
#
# return $self->sendError( $req, 'Invalid input: redirectUris is missing',
# 400 )
# unless ( defined $add->{redirectUris} );
#
# return $self->sendError( $req,
# 'Invalid input: redirectUris must be an array', 400 )
# unless ( ref( $add->{redirectUris} ) eq "ARRAY" );
$self->logger->debug(
"[API] Add CAS App with confKey $add->{confKey} requested"
);
# Get latest configuration
my $conf = $self->_confAcc->getConf( { noCache => 1 } );
return $self->sendError(
$req,
"Invalid input: A CAS App with confKey $add->{confKey} already exists",
409
) if ( defined $self->_getCasAppByConfKey( $conf, $add->{confKey} ) );
# return $self->sendError(
# $req,
# "Invalid input: An OIDC RP with clientId $add->{clientId} already exists",
# 409
# ) if ( defined $self->_getOidcRpByClientId( $conf, $add->{clientId} ) );
# $add->{options} = {} unless ( defined $add->{options} );
# $add->{options}->{clientId} = $add->{clientId};
# $add->{options}->{redirectUris} = $add->{redirectUris};
my $res = $self->_pushCasApp( $conf, $add->{confKey}, $add, 1 );
return $self->sendError( $req, $res->{msg}, 400 )
unless ( $res->{res} eq 'ok' );
return $self->sendJSONresponse(
$req,
{ message => "Successful operation" },
code => 201
);
}
sub updateCasApp {
my ( $self, $req ) = @_;
my $confKey = $req->params('confKey')
or return $self->sendError( $req, 'confKey is missing', 400 );
my $update = $req->jsonBodyToObj;
return $self->sendError( $req, "Invalid input: " . $req->error, 400 )
unless ($update);
$self->logger->debug(
"[API] CAS App $confKey configuration update requested");
# Get latest configuration
my $conf = $self->_confAcc->getConf( { noCache => 1 } );
my $current = $self->_getCasAppByConfKey( $conf, $confKey );
# Return 404 if not found
return $self->sendError( $req,
"OIDC relying party '$confKey' not found", 404 )
unless ( defined $current );
# # check if new clientID exists already
# my $res = $self->_isNewOidcRpClientIdUnique( $conf, $confKey, $update );
# return $self->sendError( $req, $res->{msg}, 409 )
# unless ( $res->{res} eq 'ok' );
my $res = $self->_pushCasApp( $conf, $confKey, $update, 0 );
return $self->sendError( $req, $res->{msg}, 400 )
unless ( $res->{res} eq 'ok' );
return $self->sendJSONresponse( $req, undef, code => 204 );
}
sub replaceCasApp {
my ( $self, $req ) = @_;
my $confKey = $req->params('confKey')
or return $self->sendError( $req, 'confKey is missing', 400 );
my $replace = $req->jsonBodyToObj;
return $self->sendError( $req, "Invalid input: " . $req->error, 400 )
unless ($replace);
return $self->sendError( $req, 'Invalid input: confKey is missing', 400 )
unless ( defined $replace->{confKey} );
return $self->sendError( $req, 'Invalid input: confKey is not a string',
400 )
if ( ref $replace->{confKey} );
# return $self->sendError( $req, 'Invalid input: clientId is missing', 400 )
# unless ( defined $replace->{clientId} );
#
# return $self->sendError( $req, 'Invalid input: clientId is not a string',
# 400 )
# if ( ref $replace->{clientId} );
#
# return $self->sendError( $req, 'Invalid input: redirectUris is missing',
# 400 )
# unless ( defined $replace->{redirectUris} );
#
# return $self->sendError( $req,
# 'Invalid input: redirectUris must be an array', 400 )
# unless ( ref( $replace->{redirectUris} ) eq "ARRAY" );
$self->logger->debug(
"[API] CAS App $confKey configuration replace requested");
# Get latest configuration
my $conf = $self->_confAcc->getConf( { noCache => 1 } );
# Return 404 if not found
return $self->sendError( $req,
"OIDC relying party '$confKey' not found", 404 )
unless ( defined $self->_getCasAppByConfKey( $conf, $confKey ) );
# # check if new clientID exists already
# my $res = $self->_isNewOidcRpClientIdUnique( $conf, $confKey, $replace );
# return $self->sendError( $req, $res->{msg}, 409 )
# unless ( $res->{res} eq 'ok' );
# $replace->{options} = {} unless ( defined $replace->{options} );
# $replace->{options}->{clientId} = $replace->{clientId};
# $replace->{options}->{redirectUris} = $replace->{redirectUris};
my $res = $self->_pushCasApp( $conf, $confKey, $replace, 1 );
return $self->sendError( $req, $res->{msg}, 400 )
unless ( $res->{res} eq 'ok' );
return $self->sendJSONresponse( $req, undef, code => 204 );
}
sub deleteCasApp {
my ( $self, $req ) = @_;
my $confKey = $req->params('confKey')
or return $self->sendError( $req, 'confKey is missing', 400 );
$self->logger->debug(
"[API] CAS App $confKey configuration delete requested");
# Get latest configuration
my $conf = $self->_confAcc->getConf( { noCache => 1 } );
my $delete = $self->_getCasAppByConfKey( $conf, $confKey );
# Return 404 if not found
return $self->sendError( $req,
"OIDC relying party '$confKey' not found", 404 )
unless ( defined $delete );
delete $conf->{casAppMetaDataOptions}->{$confKey};
delete $conf->{casAppMetaDataExportedVars}->{$confKey};
delete $conf->{casAppMetaDataMacros}->{$confKey};
# Save configuration
$self->_confAcc->saveConf($conf);
return $self->sendJSONresponse( $req, undef, code => 204 );
}
sub _getCasAppByConfKey {
my ( $self, $conf, $confKey ) = @_;
# Check if confKey is defined
return undef unless ( defined $conf->{casAppMetaDataOptions}->{$confKey} );
# # Get Client ID
# my $clientId = $conf->{casAppMetaDataOptions}->{$confKey}
# ->{casAppMetaDataOptionsClientID};
# Get exported vars
my $exportedVars = $conf->{casAppMetaDataExportedVars}->{$confKey};
# # Get extra claim
# my $extraClaims = $conf->{casAppMetaDataOptionsExtraClaims}->{$confKey};
# Get macros
my $macros = $conf->{casAppMetaDataMacros}->{$confKey} || {};
# Get options
my $options = {};
for
my $configOption ( keys %{ $conf->{casAppMetaDataOptions}->{$confKey} } )
{
$options->{ $self->_translateOptionConfToApi($configOption) } =
$conf->{casAppMetaDataOptions}->{$confKey}->{$configOption};
}
return {
confKey => $confKey,
# clientId => $clientId,
exportedVars => $exportedVars,
# extraClaims => $extraClaims,
macros => $macros,
options => $options
};
}
sub _getCasAppsByServiceUrl {
my ( $self, $conf, $serviceUrl ) = @_;
my @casApps =
map { $conf->{casAppMetaDataOptions}->{$_}->{casAppMetaDataOptionsService} eq $serviceUrl ?
$self->_getCasAppByConfKey( $conf, $_ ) : () }
keys %{ $conf->{casAppMetaDataOptions} };
return @casApps;
}
sub _pushCasApp {
my ( $self, $conf, $confKey, $push, $replace ) = @_;
$self->logger->debug("PUSH");
my $translatedOptions = {};
if ($replace) {
$conf->{casAppMetaDataOptions}->{$confKey} = {};
$conf->{casAppMetaDataExportedVars}->{$confKey} = {};
# $conf->{oidcRPMetaDataOptionsExtraClaims}->{$confKey} = {};
$conf->{casAppMetaDataMacros}->{$confKey} = {};
$translatedOptions = $self->_getDefaultValues('casAppMetaDataNodes');
}
if ( defined $push->{options} ) {
foreach ( keys %{ $push->{options} } ) {
# # redirectUris is handled as an array
# if ( $_ eq 'redirectUris' ) {
# my $option = $push->{options}->{$_};
# return {
# res => 'ko',
# msg => "Invalid input: redirectUris is not an array"
# }
# unless ( ref($option) eq "ARRAY" );
#
# $translatedOptions->{ $self->_translateOptionApiToConf( $_,
# 'casApp' ) } = join( ' ', @{ $push->{options}->{$_} } );
# }
# else {
$translatedOptions->{ $self->_translateOptionApiToConf( $_,
'casApp' ) } = $push->{options}->{$_};
# }
$self->logger->debug("... translate " . $_ . " to " . $self->_translateOptionApiToConf( $_,
'casApp' ));
}
my $res = $self->_hasAllowedAttributes( $translatedOptions,
'casAppMetaDataNode' );
return $res unless ( $res->{res} eq 'ok' );
foreach ( keys %{$translatedOptions} ) {
$conf->{casAppMetaDataOptions}->{$confKey}->{$_} =
$translatedOptions->{$_};
}
}
# $conf->{casAppMetaDataOptions}->{$confKey}->{oidcRPMetaDataOptionsClientID}
# = $push->{clientId}
# if ( defined $push->{clientId} );
if ( defined $push->{exportedVars} ) {
if ( $self->_isSimpleKeyValueHash( $push->{exportedVars} ) ) {
foreach ( keys %{ $push->{exportedVars} } ) {
$conf->{casAppMetaDataExportedVars}->{$confKey}->{$_} =
$push->{exportedVars}->{$_};
}
}
else {
return {
res => 'ko',
msg =>
"Invalid input: exportedVars is not a hash object with \"key\":\"value\" attributes"
};
}
}
if ( defined $push->{macros} ) {
if ( $self->_isSimpleKeyValueHash( $push->{macros} ) ) {
foreach ( keys %{ $push->{macros} } ) {
$conf->{casAppMetaDataMacros}->{$confKey}->{$_} =
$push->{macros}->{$_};
}
}
else {
return {
res => 'ko',
msg =>
"Invalid input: macros is not a hash object with \"key\":\"value\" attributes"
};
}
}
# if ( defined $push->{extraClaims} ) {
# if ( $self->_isSimpleKeyValueHash( $push->{extraClaims} ) ) {
# foreach ( keys %{ $push->{extraClaims} } ) {
# $conf->{oidcRPMetaDataOptionsExtraClaims}->{$confKey}->{$_} =
# $push->{extraClaims}->{$_};
# }
# }
# else {
# return {
# res => 'ko',
# msg =>
# "Invalid input: extraClaims is not a hash object with \"key\":\"value\" attributes"
# };
# }
# }
# Test new configuration
my $parser = Lemonldap::NG::Manager::Conf::Parser->new( {
refConf => $self->_confAcc->getConf,
newConf => $conf,
req => {},
}
);
unless ( $parser->testNewConf( $self->p ) ) {
return {
res => 'ko',
code => 400,
msg => "Configuration error: "
. join( ". ", map { $_->{message} } @{ $parser->errors } ),
};
}
# Save configuration
$self->_confAcc->saveConf($conf);
return { res => 'ok' };
}
1;