[Bps-public-commit] r16701 - in RT-Authen-ExternalAuth/trunk: html/Callbacks/ExternalAuth/autohandler lib/RT/Authen lib/RT/Authen/ExternalAuth
zordrak at bestpractical.com
zordrak at bestpractical.com
Thu Nov 6 06:15:25 EST 2008
Author: zordrak
Date: Thu Nov 6 06:15:24 2008
New Revision: 16701
Modified:
RT-Authen-ExternalAuth/trunk/html/Callbacks/ExternalAuth/autohandler/Auth
RT-Authen-ExternalAuth/trunk/lib/RT/Authen/ExternalAuth.pm
RT-Authen-ExternalAuth/trunk/lib/RT/Authen/ExternalAuth/LDAP.pm
RT-Authen-ExternalAuth/trunk/lib/RT/User_Vendor.pm
Log:
zordrak | 2008-11-06 11:15:00 +0000
* User_Vendor.pm reduced to absolute minimum
* Primary refactoring complete
Modified: RT-Authen-ExternalAuth/trunk/html/Callbacks/ExternalAuth/autohandler/Auth
==============================================================================
--- RT-Authen-ExternalAuth/trunk/html/Callbacks/ExternalAuth/autohandler/Auth (original)
+++ RT-Authen-ExternalAuth/trunk/html/Callbacks/ExternalAuth/autohandler/Auth Thu Nov 6 06:15:24 2008
@@ -1,5 +1,7 @@
<%init>
+use RT::Authen::ExternalAuth;
+
# If the RT::User::UpdateFromExternal method is not available, then we are in
# RT-3.8.0 or RT-3.8.1 and we need to work around a bug in the plugin system:
# Temporarily force RT to reload RT::User, since it isn't being loaded
@@ -37,22 +39,8 @@
# Unless we have loaded a valid user with a UserID
unless ($session{'CurrentUser'}->Id) {
# Check if user exists externally - autocreate user if it does
- my $user_exists_externally = 0;
- my @auth_services = @$RT::ExternalAuthPriority;
- foreach my $service (@auth_services) {
- my $config = $RT::Settings->{$service};
- if ($config->{'type'} eq 'db') {
- $user_exists_externally = RT::Authen::ExternalAuth::DBI->UserExists($service,$user);
- last if $user_exists_externally;
- } elsif ($config->{'type'} eq 'ldap') {
- $user_exists_externally = RT::Authen::ExternalAuth::LDAP->UserExists($service,$user);
- last if $user_exists_externally;
- } else {
- $RT::Logger->error("Invalid type specification in config for service:",$service);
- }
- }
-
- if($user_exists_externally){
+
+ if(RT::Authen::ExternalAuth->UserExists($user)){
my ($val, $msg) =
$UserObj->Create(%{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
Name => $user,
@@ -99,7 +87,7 @@
# the database, but more importantly, UpdateFromExternal will check
# whether the user is disabled or not which we have not been able to
# do during auto-create
- $session{'CurrentUser'}->UserObj->UpdateFromExternal();
+ RT::Authen::ExternalAuth->UpdateUserInfo($session{'CurrentUser'}->UserObj->Name);
# Now that we definitely have up-to-date user information,
# if the user is disabled, kick them out. Now!
Modified: RT-Authen-ExternalAuth/trunk/lib/RT/Authen/ExternalAuth.pm
==============================================================================
--- RT-Authen-ExternalAuth/trunk/lib/RT/Authen/ExternalAuth.pm (original)
+++ RT-Authen-ExternalAuth/trunk/lib/RT/Authen/ExternalAuth.pm Thu Nov 6 06:15:24 2008
@@ -18,7 +18,323 @@
=begin testing
ok(require RT::Authen::ExternalAuth);
+ok(require RT::Authen::ExternalAuth::LDAP);
+ok(require RT::Authen::ExternalAuth::DBI);
=end testing
+
+use RT::Authen::ExternalAuth::LDAP;
+use RT::Authen::ExternalAuth::DBI;
+sub UpdateUserInfo {
+ my $username = shift;
+
+ # Prepare for the worst...
+ my $found = 0;
+ my $updated = 0;
+ my $msg = "User NOT updated";
+
+ my $user_disabled = RT::Authen::ExternalAuth->UserDisabled($username);
+
+ my $UserObj = RT::User->new($RT::SystemUser);
+ $UserObj->Load($username);
+
+ # If user is disabled, set the RT::Principle to disabled and return out of the function.
+ # I think it's a waste of time and energy to update a user's information if they are disabled
+ # and it could be a security risk if they've updated their external information with some
+ # carefully concocted code to try to break RT - worst case scenario, but they have been
+ # denied access after all, don't take any chances.
+
+ # If someone gives me a good enough reason to do it,
+ # then I'll update all the info for disabled users
+
+ if ($user_disabled) {
+ # Make sure principle is disabled in RT
+ my ($val, $message) = $UserObj->SetDisabled(1);
+ # Log what has happened
+ $RT::Logger->info("User marked as DISABLED (",
+ $username,
+ ") per External Service",
+ "($val, $message)\n");
+ $msg = "User Disabled";
+
+ return ($updated, $msg);
+ }
+
+ # Make sure principle is not disabled in RT
+ my ($val, $message) = $UserObj->SetDisabled(0);
+ # Log what has happened
+ $RT::Logger->info("User marked as ENABLED (",
+ $username,
+ ") per External Service",
+ "($val, $message)\n");
+
+ # Update their info from external service using the username as the lookup key
+ # CanonicalizeUserInfo will work out for itself which service to use
+ # Passing it a service instead could break other RT code
+ my %args = (Name => $username);
+ $UserObj->CanonicalizeUserInfo(\%args);
+
+ # For each piece of information returned by CanonicalizeUserInfo,
+ # run the Set method for that piece of info to change it for the user
+ foreach my $key (sort(keys(%args))) {
+ next unless $args{$key};
+ my $method = "Set$key";
+ # We do this on the UserObj from above, not self so that there
+ # are no permission restrictions on setting information
+ my ($method_success,$method_msg) = $UserObj->$method($args{$key});
+
+ # If your user information is not getting updated,
+ # uncomment the following logging statements
+ if ($method_success) {
+ # At DEBUG level, log that method succeeded
+ # $RT::Logger->debug((caller(0))[3],"$method Succeeded. $method_msg");
+ } else {
+ # At DEBUG level, log that method failed
+ # $RT::Logger->debug((caller(0))[3],"$method Failed. $method_msg");
+ }
+ }
+
+ # Confirm update success
+ $updated = 1;
+ $RT::Logger->debug( "UPDATED user (",
+ $username,
+ ") from External Service\n");
+ $msg = 'User updated';
+
+ return ($updated, $msg);
+}
+
+sub UserExists {
+
+ my $username = shift;
+ my $user_exists_externally = 0;
+
+ my @auth_services = @$RT::ExternalAuthPriority;
+ foreach my $service (@auth_services) {
+ my $config = $RT::Settings->{$service};
+ if ($config->{'type'} eq 'db') {
+ $user_exists_externally = RT::Authen::ExternalAuth::DBI->UserExists($service,$user);
+ last if $user_exists_externally;
+ } elsif ($config->{'type'} eq 'ldap') {
+ $user_exists_externally = RT::Authen::ExternalAuth::LDAP->UserExists($service,$user);
+ last if $user_exists_externally;
+ } else {
+ $RT::Logger->error("Invalid type specification in config for service:",$service);
+ }
+ }
+
+ return $user_exists_externally;
+}
+
+sub GetAuth {
+
+ my ($username,$password) = @_;
+
+ # Get the prioritised list of external authentication services
+ my @auth_services = @$RT::ExternalAuthPriority;
+
+ # For each of those services..
+ foreach my $service (@auth_services) {
+
+ # Get the full configuration for that service as a hashref
+ my $config = $RT::ExternalSettings->{$service};
+ $RT::Logger->debug( "Attempting to use external auth service:",
+ $service);
+
+ # And then act accordingly depending on what type of service it is.
+ # Right now, there is only code for DBI and LDAP services
+ if ($config->{'type'} eq 'db') {
+ my $success = RT::Authen::ExternalAuth::DBI->GetAuth($service,$username,$password);
+ return 1 if $success;
+ next;
+
+ } elsif ($config->{'type'} eq 'ldap') {
+ my $success = RT::Authen::ExternalAuth::LDAP->GetAuth($service,$username,$password);
+ return 1 if $success;
+ next;
+
+ } else {
+ $RT::Logger->error("Invalid type specification in config for service:",
+ $service,
+ "- Skipping...");
+ }
+ }
+
+ # No success by now = failure.
+ return 0;
+
+}
+
+sub UserDisabled {
+
+ my $username = shift;
+ my $user_disabled = 0;
+
+ my @info_services = $RT::ExternalInfoPriority ? @{$RT::ExternalInfoPriority} : undef;
+
+ # For each named service in the list
+ # Check to see if the user is found in the external service
+ # If not found, jump to next service
+ # If found, check to see if user is considered disabled by the service
+ # Then update the user's info in RT and return
+ foreach my $service (@info_services) {
+
+ # Get the external config for this service as a hashref
+ my $config = $RT::ExternalSettings->{$service};
+
+ # If the config doesn't exist, don't bother doing anything, skip to next in list.
+ unless(defined($config)) {
+ $RT::Logger->debug("You haven't defined a configuration for the service named \"",
+ $service,
+ "\" so I'm not going to try to get user information from it. Skipping...");
+ next;
+ }
+
+ # If it's a DBI config:
+ if ($config->{'type'} eq 'db') {
+
+ unless(RT::Authen::ExternalAuth::DBI->UserExists($username,$service)) {
+ $RT::Logger->debug("User (",
+ $username,
+ ") doesn't exist in service (",
+ $service,
+ ") - Cannot update information - Skipping...");
+ next;
+ }
+ $user_disabled = RT::Authen::ExternalAuth::DBI->UserDisabled($username,$service);
+
+ } elsif ($config->{'type'} eq 'ldap') {
+
+ unless(RT::Authen::ExternalAuth::LDAP->UserExists($username,$service)) {
+ $RT::Logger->debug("User (",
+ $username,
+ ") doesn't exist in service (",
+ $service,
+ ") - Cannot update information - Skipping...");
+ next;
+ }
+ $user_disabled = RT::Authen::ExternalAuth::LDAP->UserDisabled($username,$service);
+
+ } else {
+ # The type of external service doesn't currently have any methods associated with it. Or it's a typo.
+ RT::Logger->error("Invalid type specification for config %config->{'name'}");
+ # Drop out to next service in list
+ next;
+ }
+
+ return $user_disabled;
+}
+
+sub CanonicalizeUserInfo {
+
+ # Careful, this $args hashref was given to RT::User::CanonicalizeUserInfo and
+ # then transparently passed on to this function. The whole purpose is to update
+ # the original hash as whatever passed it to RT::User is expecting to continue its
+ # code with an update args hash.
+
+ my $UserObj = shift;
+ my $args = shift;
+
+ my $found = 0;
+ my %params = (Name => undef,
+ EmailAddress => undef,
+ RealName => undef);
+
+ $RT::Logger->debug( (caller(0))[3],
+ "called by",
+ caller,
+ "with:",
+ join(", ", map {sprintf("%s: %s", $_, $args->{$_})}
+ sort(keys(%$args))));
+
+ # Get the list of defined external services
+ my @info_services = $RT::ExternalInfoPriority ? @{$RT::ExternalInfoPriority} : undef;
+ # For each external service...
+ foreach my $service (@info_services) {
+
+ $RT::Logger->debug( "Attempting to get user info using this external service:",
+ $service);
+
+ # Get the config for the service so that we know what attrs we can canonicalize
+ my $config = $RT::ExternalSettings->{$service};
+
+ # For each attr we've been told to canonicalize in the match list
+ foreach my $rt_attr (@{$config->{'attr_match_list'}}) {
+ # Jump to the next attr in $args if this one isn't in the attr_match_list
+ $RT::Logger->debug( "Attempting to use this canonicalization key:",$rt_attr);
+ unless(defined($args->{$rt_attr})) {
+ $RT::Logger->debug("This attribute (",
+ $rt_attr,
+ ") is not defined in the attr_match_list for this service (",
+ $service,
+ ")");
+ next;
+ }
+
+ # Else, use it as a canonicalization key and lookup the user info
+ my $key = $config->{'attr_map'}->{$rt_attr};
+ my $value = $args->{$rt_attr};
+
+ # Check to see that the key being asked for is defined in the config's attr_map
+ my $valid = 0;
+ my ($attr_key, $attr_value);
+ my $attr_map = $config->{'attr_map'};
+ while (($attr_key, $attr_value) = each %$attr_map) {
+ $valid = 1 if ($key eq $attr_value);
+ }
+ unless ($valid){
+ $RT::Logger->debug( "This key (",
+ $key,
+ "is not a valid attribute key (",
+ $service,
+ ")");
+ next;
+ }
+
+ # Use an if/elsif structure to do a lookup with any custom code needed
+ # for any given type of external service, or die if no code exists for
+ # the service requested.
+
+ if($config->{'type'} eq 'ldap'){
+ ($found, %params) = RT::Authen::ExternalAuth::LDAP->CanonicalizeUserInfo($service,$key,$value);
+ } elsif ($config->{'type'} eq 'db') {
+ ($found, %params) = RT::Authen::ExternalAuth::DBI->CanonicalizeUserInfo($service,$key,$value);
+ } else {
+ $RT::Logger->debug( (caller(0))[3],
+ "does not consider",
+ $service,
+ "a valid information service");
+ }
+
+ # Don't Check any more attributes
+ last if $found;
+ }
+ # Don't Check any more services
+ last if $found;
+ }
+
+ # If found, Canonicalize Email Address and
+ # update the args hash that we were given the hashref for
+ if ($found) {
+ # It's important that we always have a canonical email address
+ if ($params{'EmailAddress'}) {
+ $params{'EmailAddress'} = $self->CanonicalizeEmailAddress($params{'EmailAddress'});
+ }
+ %$args = (%$args, %params);
+ }
+
+ $RT::Logger->info( (caller(0))[3],
+ "returning",
+ join(", ", map {sprintf("%s: %s", $_, $args->{$_})}
+ sort(keys(%$args))));
+
+ ### HACK: The config var below is to overcome the (IMO) bug in
+ ### RT::User::Create() which expects this function to always
+ ### return true or rejects the user for creation. This should be
+ ### a different config var (CreateUncanonicalizedUsers) and
+ ### should be honored in RT::User::Create()
+ return($found || $RT::AutoCreateNonExternalUsers);
+
+}
1;
Modified: RT-Authen-ExternalAuth/trunk/lib/RT/Authen/ExternalAuth/LDAP.pm
==============================================================================
--- RT-Authen-ExternalAuth/trunk/lib/RT/Authen/ExternalAuth/LDAP.pm (original)
+++ RT-Authen-ExternalAuth/trunk/lib/RT/Authen/ExternalAuth/LDAP.pm Thu Nov 6 06:15:24 2008
@@ -2,6 +2,7 @@
use Net::LDAP qw(LDAP_SUCCESS LDAP_PARTIAL_RESULTS);
use Net::LDAP::Util qw(ldap_error_name);
use Net::LDAP::Filter;
+require Net::SSLeay if $RT::ExternalServiceUsesSSLorTLS;
sub GetAuth {
Modified: RT-Authen-ExternalAuth/trunk/lib/RT/User_Vendor.pm
==============================================================================
--- RT-Authen-ExternalAuth/trunk/lib/RT/User_Vendor.pm (original)
+++ RT-Authen-ExternalAuth/trunk/lib/RT/User_Vendor.pm Thu Nov 6 06:15:24 2008
@@ -7,64 +7,40 @@
no warnings qw(redefine);
use strict;
-use RT::Authen::ExternalAuth::LDAP;
-use RT::Authen::ExternalAuth::DBI;
+use RT::Authen::ExternalAuth;
-# We only need Net::SSLeay if one of our external services requires
-# OpenSSL because it plans to use SSL or TLS to encrypt connections
-require Net::SSLeay if $RT::ExternalServiceUsesSSLorTLS;
-
-sub IsExternalPassword {
- my $self = shift;
+# {{{ sub IsPassword
- my $name_to_auth = $self->Name;
- my $pass_to_auth = shift;
+sub IsPassword {
+ my $self = shift;
+ my $value = shift;
- $RT::Logger->debug( (caller(0))[3],
- "Trying External authentication");
-
- # Get the prioritised list of external authentication services
- my @auth_services = @$RT::ExternalAuthPriority;
-
- # For each of those services..
- foreach my $service (@auth_services) {
+ # TODO there isn't any apparent way to legitimately ACL this
- # Get the full configuration for that service as a hashref
- my $config = $RT::ExternalSettings->{$service};
- $RT::Logger->debug( "Attempting to use external auth service:",
- $service);
-
- # And then act accordingly depending on what type of service it is.
- # Right now, there is only code for DBI and LDAP services
- if ($config->{'type'} eq 'db') {
- my $success = RT::Authen::ExternalAuth::DBI->GetAuth($service,$name_to_auth,$pass_to_auth);
- return 1 if $success;
- next;
-
- } elsif ($config->{'type'} eq 'ldap') {
- my $success = RT::Authen::ExternalAuth::LDAP->GetAuth($service,$name_to_auth,$pass_to_auth);
- return 1 if $success;
- next;
-
- } else {
- $RT::Logger->error("Invalid type specification in config for service:",$service);
- }
- }
+ # RT does not allow null passwords
+ if ( ( !defined($value) ) or ( $value eq '' ) ) {
+ return (undef);
+ }
- # If we still haven't returned, we must have been unsuccessful
- $RT::Logger->info( (caller(0))[3],
- "External Auth Failed:",
- $name_to_auth);
- return 0;
-}
+ if ( $self->PrincipalObj && $self->PrincipalObj->Disabled ) {
+ $RT::Logger->info("Disabled user " . $self->Name .
+ " tried to log in" );
+ return (undef);
+ }
-sub IsInternalPassword {
- my $self = shift;
- my $value = shift;
+ if(RT::Authen::ExternalAuth->GetAuth($self->Name,$value)) {
+ $RT::Logger->debug( (caller(0))[3],
+ "EXTERNAL AUTH OKAY");
+ return(1);
+ } else {
+ $RT::Logger->debug( (caller(0))[3],
+ "EXTERNAL AUTH FAILED");
+ }
+
unless ($self->HasPassword) {
$RT::Logger->info( (caller(0))[3],
- "AUTH FAILED (no passwd):",
+ "INTERNAL AUTH FAILED (no passwd):",
$self->Name);
return(undef);
}
@@ -72,7 +48,7 @@
# generate an md5 password
if ($self->_GeneratePassword($value) eq $self->__Value('Password')) {
$RT::Logger->info( (caller(0))[3],
- "AUTH OKAY:",
+ "INTERNAL AUTH OKAY:",
$self->Name);
return(1);
}
@@ -84,52 +60,17 @@
# ...but upgrade the legacy password inplace.
$self->SUPER::SetPassword( $self->_GeneratePassword($value) );
$RT::Logger->info((caller(0))[3],
- "AUTH OKAY:",
+ "INTERNAL AUTH OKAY:",
$self->Name);
return(1);
}
$RT::Logger->info( (caller(0))[3],
- "AUTH FAILED:",
+ "INTERNAL AUTH FAILED:",
$self->Name);
- return(undef);
-}
-
-# {{{ sub IsPassword
-
-sub IsPassword {
- my $self = shift;
- my $value = shift;
-
- # TODO there isn't any apparent way to legitimately ACL this
-
- # RT does not allow null passwords
- if ( ( !defined($value) ) or ( $value eq '' ) ) {
- return (undef);
- }
-
- if ( $self->PrincipalObj && $self->PrincipalObj->Disabled ) {
- $RT::Logger->info("Disabled user " . $self->Name .
- " tried to log in" );
- return (undef);
- }
-
- my $success = undef;
-
- $success = $self->IsExternalPassword($value);
- $RT::Logger->debug( (caller(0))[3],
- "External auth",
- ($success ? 'SUCCEEDED' : 'FAILED'));
-
- unless ($success) {
- $success = $self->IsInternalPassword($value);
- $RT::Logger->debug( (caller(0))[3],
- "Internal auth",
- ($success ? 'SUCCEEDED' : 'FAILED'));
- }
- # We either got it or we didn't
- return ($success);
+ # If we haven't succeeded by now, fail.
+ return (undef);
}
# }}}
@@ -150,261 +91,10 @@
sub CanonicalizeUserInfo {
my $self = shift;
my $args = shift;
-
- my $found = 0;
- my %params = (Name => undef,
- EmailAddress => undef,
- RealName => undef);
-
- $RT::Logger->debug( (caller(0))[3],
- "called by",
- caller,
- "with:",
- join(", ", map {sprintf("%s: %s", $_, $args->{$_})}
- sort(keys(%$args))));
-
- # Get the list of defined external services
- my @info_services = $RT::ExternalInfoPriority ? @{$RT::ExternalInfoPriority} : undef;
- # For each external service...
- foreach my $service (@info_services) {
-
- $RT::Logger->debug( "Attempting to get user info using this external service:",
- $service);
-
- # Get the config for the service so that we know what attrs we can canonicalize
- my $config = $RT::ExternalSettings->{$service};
-
- # For each attr we've been told to canonicalize in the match list
- foreach my $rt_attr (@{$config->{'attr_match_list'}}) {
- # Jump to the next attr in $args if this one isn't in the attr_match_list
- $RT::Logger->debug( "Attempting to use this canonicalization key:",$rt_attr);
- unless(defined($args->{$rt_attr})) {
- $RT::Logger->debug("This attribute (",
- $rt_attr,
- ") is not defined in the attr_match_list for this service (",
- $service,
- ")");
- next;
- }
-
- # Else, use it as a canonicalization key and lookup the user info
- my $key = $config->{'attr_map'}->{$rt_attr};
- my $value = $args->{$rt_attr};
-
- # Check to see that the key being asked for is defined in the config's attr_map
- my $valid = 0;
- my ($attr_key, $attr_value);
- my $attr_map = $config->{'attr_map'};
- while (($attr_key, $attr_value) = each %$attr_map) {
- $valid = 1 if ($key eq $attr_value);
- }
- unless ($valid){
- $RT::Logger->debug( "This key (",
- $key,
- "is not a valid attribute key (",
- $service,
- ")");
- next;
- }
-
- # Use an if/elsif structure to do a lookup with any custom code needed
- # for any given type of external service, or die if no code exists for
- # the service requested.
-
- if($config->{'type'} eq 'ldap'){
- ($found, %params) = RT::Authen::ExternalAuth::LDAP->CanonicalizeUserInfo($service,$key,$value);
- } elsif ($config->{'type'} eq 'db') {
- ($found, %params) = RT::Authen::ExternalAuth::DBI->CanonicalizeUserInfo($service,$key,$value);
- } else {
- $RT::Logger->debug( (caller(0))[3],
- "does not consider",
- $service,
- "a valid information service");
- }
-
- # Don't Check any more attributes
- last if $found;
- }
- # Don't Check any more services
- last if $found;
- }
-
- # If found, Canonicalize Email Address and
- # update the args hash that we were given the hashref for
- if ($found) {
- # It's important that we always have a canonical email address
- if ($params{'EmailAddress'}) {
- $params{'EmailAddress'} = $self->CanonicalizeEmailAddress($params{'EmailAddress'});
- }
- %$args = (%$args, %params);
- }
-
- $RT::Logger->info( (caller(0))[3],
- "returning",
- join(", ", map {sprintf("%s: %s", $_, $args->{$_})}
- sort(keys(%$args))));
-
- ### HACK: The config var below is to overcome the (IMO) bug in
- ### RT::User::Create() which expects this function to always
- ### return true or rejects the user for creation. This should be
- ### a different config var (CreateUncanonicalizedUsers) and
- ### should be honored in RT::User::Create()
- return($found || $RT::AutoCreateNonExternalUsers);
-
+ return($RT::Authen::ExternalAuth->CanonicalizeUserInfo($self,$args));
}
# }}}
-sub UpdateFromExternal {
- my $self = shift;
-
- # Prepare for the worst...
- my $found = 0;
- my $updated = 0;
- my $msg = "User NOT updated";
-
- my $username = $self->Name;
- my $user_disabled = 0;
-
- # Get the list of information service names requested by user.
- my @info_services = $RT::ExternalInfoPriority ? @{$RT::ExternalInfoPriority} : undef;
-
- # For each named service in the list
- # Check to see if the user is found in the external service
- # If not found, jump to next service
- # If found, check to see if user is considered disabled by the service
- # Then update the user's info in RT and return
- foreach my $service (@info_services) {
-
- # Get the external config for this service as a hashref
- my $config = $RT::ExternalSettings->{$service};
-
- # If the config doesn't exist, don't bother doing anything, skip to next in list.
- unless(defined($config)) {
- $RT::Logger->debug("You haven't defined a configuration for the service named \"",
- $service,
- "\" so I'm not going to try to get user information from it. Skipping...");
- next;
- }
-
- # If it's a DBI config:
- if ($config->{'type'} eq 'db') {
-
- unless(RT::Authen::ExternalAuth::DBI->UserExists($username,$service)) {
- $RT::Logger->debug("User (",
- $username,
- ") doesn't exist in service (",
- $service,
- ") - Cannot update information - Skipping...");
- next;
- }
- $user_disabled = RT::Authen::ExternalAuth::DBI->UserDisabled($username,$service);
-
- } elsif ($config->{'type'} eq 'ldap') {
-
- unless(RT::Authen::ExternalAuth::LDAP->UserExists($username,$service)) {
- $RT::Logger->debug("User (",
- $username,
- ") doesn't exist in service (",
- $service,
- ") - Cannot update information - Skipping...");
- next;
- }
- $user_disabled = RT::Authen::ExternalAuth::LDAP->UserDisabled($username,$service);
-
- } else {
- # The type of external service doesn't currently have any methods associated with it. Or it's a typo.
- RT::Logger->error("Invalid type specification for config %config->{'name'}");
- # Drop out to next service in list
- next;
- }
-
- # We are now going to update the user's information from the authoritative source
- # Although we are in a foreach, the statements below will only be executed once.
- # The external services have been checked in the priority order specified by the config.
- # If the user wasn't found in an individual service, we will already have jumped to the next one,
- # or we will have dropped out to the return statement at the base of the function if the user wasn't
- # found in ANY external services.
-
- # The user must have been found in a service to get here so we run the update code
- # and then "last" out of the foreach so that we only update from one source.
- # and then return out of the function
-
- # So, breathe, and on we go...
-
- # Load the user inside an RT::SystemUser so you can set their
- # information no matter who they are or what permissions they have
- my $UserObj = RT::User->new($RT::SystemUser);
- $UserObj->Load($username);
-
- # If user is disabled, set the RT::Principle to disabled and return out of the function.
- # I think it's a waste of time and energy to update a user's information if they are disabled
- # and it could be a security risk if they've updated their external information with some
- # carefully concocted code to try to break RT - worst case scenario, but they have been
- # denied access after all, don't take any chances.
-
- # If someone gives me a good enough reason to do it,
- # then I'll update all the info for disabled users
-
- if ($user_disabled) {
- # Make sure principle is disabled in RT
- my ($val, $message) = $UserObj->SetDisabled(1);
- # Log what has happened
- $RT::Logger->info("User marked as DISABLED (",
- $username,
- ") per External Service",
- "($val, $message)\n");
- $msg = "User disabled";
- } else {
- # Make sure principle is not disabled in RT
- my ($val, $message) = $UserObj->SetDisabled(0);
- # Log what has happened
- $RT::Logger->info("User marked as ENABLED (",
- $username,
- ") per External Service",
- "($val, $message)\n");
-
- # Update their info from external service using the username as the lookup key
- # CanonicalizeUserInfo will work out for itself which service to use
- # Passing it a service instead could break other RT code
- my %args = (Name => $username);
- $self->CanonicalizeUserInfo(\%args);
-
- # For each piece of information returned by CanonicalizeUserInfo,
- # run the Set method for that piece of info to change it for the user
- foreach my $key (sort(keys(%args))) {
- next unless $args{$key};
- my $method = "Set$key";
- # We do this on the UserObj from above, not self so that there
- # are no permission restrictions on setting information
- my ($method_success,$method_msg) = $UserObj->$method($args{$key});
-
- # If your user information is not getting updated,
- # uncomment the following logging statements
- if ($method_success) {
- # At DEBUG level, log that method succeeded
- # $RT::Logger->debug((caller(0))[3],"$method Succeeded. $method_msg");
- } else {
- # At DEBUG level, log that method failed
- # $RT::Logger->debug((caller(0))[3],"$method Failed. $method_msg");
- }
- }
-
- # Confirm update success
- $updated = 1;
- $RT::Logger->debug( "UPDATED user (",
- $username,
- ") from External Service\n");
- $msg = 'User updated';
-
- # Just in case we're not the last iteration of the foreach,
- # drop out to the return statement now.
- last;
-
- }
- }
-
- return ($updated, $msg);
-}
More information about the Bps-public-commit
mailing list