From fd95c57ed045068c894d13ebe607f6d8f824e6c4 Mon Sep 17 00:00:00 2001 From: Roy Johnson Date: Wed, 11 Oct 2006 21:46:51 +0000 Subject: [PATCH] More 7.1 features --- docs/changelog/7.x.x.txt | 5 + docs/upgrades/upgrade_7.0.9-7.1.0.pl | 32 +- lib/WebGUI/Auth/LDAP.pm | 337 ++++++++++++------ lib/WebGUI/Operation/Settings.pm | 8 + .../Workflow/Activity/SyncProfileToLdap.pm | 152 ++++++++ 5 files changed, 427 insertions(+), 107 deletions(-) create mode 100644 lib/WebGUI/Workflow/Activity/SyncProfileToLdap.pm diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 2cead9696..15ab292e0 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -24,6 +24,11 @@ - Added option to WebGUI Auth module to require strong passwords. Admins can now require users to enter a specific combination of characters, etc. - Added skeleton code for writing WebGUI utility scripts. + - Added auto-registration via LDAP. This allows users to simply login and + have a WebGUI account created if their credentials are validated by the + directory. + - Added a Sync Profile to LDAP workflow activity that will grab a single user + profile from LDAP instead of all of them. 7.0.9 - Removed the need for DateTime::Cron::Simple, which also added the ability diff --git a/docs/upgrades/upgrade_7.0.9-7.1.0.pl b/docs/upgrades/upgrade_7.0.9-7.1.0.pl index 0ea244c2f..27a601ddb 100755 --- a/docs/upgrades/upgrade_7.0.9-7.1.0.pl +++ b/docs/upgrades/upgrade_7.0.9-7.1.0.pl @@ -12,7 +12,7 @@ use lib "../../lib"; use strict; use Getopt::Long; use WebGUI::Session; - +use WebGUI::Workflow; my $toVersion = "7.1.0"; # make this match what version you're going to my $quiet; # this line required @@ -25,9 +25,34 @@ updateProductsTable($session); makeLdapRecursiveFiltersText($session); addImageStuffToCs($session); addNewAuthSettings($session); +addAutoLDAPRegistration($session); finish($session); # this line required +#------------------------------------------------- +sub addAutoLDAPRegistration { + my $session = shift; + print "\tAdding new feature that allows autoregistration of WebGUI users from LDAP directories.\n" unless $quiet; + + # Put an entry in the settings table to turn this thing on and off + $session->db-write("insert into settings (name,value) values ('automaticLDAPRegistration',0)"); + + # Enable our new workflow activity in the config file + my $activities = $session->config->get("workflowActivities"); + push (@{$activities->{'WebGUI::User'}}, 'WebGUI::Workflow::Activity::SyncProfileToLdap'); + $session->config->set("workflowActivities", $activities); + + # Add a workflow that the LDAP auth module can kick off to pull the users info from LDAP to their wG user profile. + my $workflow = WebGUI::Workflow->create($session, { + type=>"WebGUI::User", + enabled=>1, + description=>"Synchronizes a users LDAP information to their WebGUI User Profile", + title=>"Synchronize Profile To LDAP" + }, "AuthLDAPworkflow000001"); + my $activity = $workflow->addActivity("WebGUI::Workflow::Activity::SyncProfileToLdap"); + $activity->set("title","Synchronize Profile To LDAP"); +} + #------------------------------------------------- sub addNewAuthSettings { my $session = shift; @@ -65,20 +90,21 @@ sub recalculateProjectCompletion { } } - +#------------------------------------------------- sub updateSqlReportTable { my $session = shift; print "\tUpdating SQLReport table structure.\n" unless ($quiet); $session->db->write("alter table `SQLReport` ADD COLUMN ( downloadType varchar(255), downloadFilename varchar(255), downloadTemplateId varchar(22), downloadMimeType varchar(255), downloadUserGroup varchar(22))"); } - +#------------------------------------------------- sub updateProductsTable { my $session = shift; print "\tUpdating products table structure.\n" unless ($quiet); $session->db->write("alter table products add column (groupId varchar(22), groupExpiresOffset varchar(16))"); } +#------------------------------------------------- sub makeLdapRecursiveFiltersText { my $session = shift; print "\tMaking LDAP recursive filters text fields.\n" unless $quiet; diff --git a/lib/WebGUI/Auth/LDAP.pm b/lib/WebGUI/Auth/LDAP.pm index 7206b9539..75aa33e67 100644 --- a/lib/WebGUI/Auth/LDAP.pm +++ b/lib/WebGUI/Auth/LDAP.pm @@ -16,6 +16,7 @@ use WebGUI::HTMLForm; use WebGUI::Form; use WebGUI::LDAPLink; use WebGUI::Utility; +use WebGUI::Workflow; use WebGUI::Operation::Shared; use WebGUI::Asset::Template; use URI; @@ -25,103 +26,184 @@ our @ISA = qw(WebGUI::Auth); #------------------------------------------------------------------- +=head2 sub _isValidLDAPUser ( ) + +Private method that gets username and password supplied by a user attempting to +login and then attempts to bind to the LDAP server using credentials provided. +If the bind is successful, the user is considered valid and authenticated as far +as LDAP is concerned. + +Note: This method does not ensure that the user is valid in WebGUI. +i.e., it does not validate their username or ensure their account is active. + +=cut + sub _isValidLDAPUser { my $self = shift; - my ($uri, $error, $ldap, $search, $auth, $connectDN); - my $i18n = WebGUI::International->new($self->session); - my $connection = $self->{_connection}; + my ($uri, $error, $ldap, $search, $auth, $connectDN, $username, $password); + my $i18n = WebGUI::International->new($self->session); + my $connection = $self->getLDAPConnection; + + $username = $self->session->form->get("authLDAP_ldapId") || $self->session->form->get("username"); + $password = $self->session->form->get("authLDAP_identifier") || $self->session->form->get("identifier"); + $uri = URI->new($connection->{ldapUrl}) or $error = $i18n->get(2,'AuthLDAP'); + if($error ne ""){ $self->error($error); - return 0; + return 0; } + # Create an LDAP object if ($ldap = Net::LDAP->new($uri->host, (port=>$uri->port))) { + + # Bind as a proxy user to search for the user trying to login if($connection->{connectDn}) { - $auth = $ldap->bind(dn=>$connection->{connectDn}, password=>$connection->{identifier}); - }else{ - $auth = $ldap->bind; - } + $auth = $ldap->bind(dn=>$connection->{connectDn}, password=>$connection->{identifier}); + } + else { # No proxy user specified, try to bind anonymously for the search + $auth = $ldap->bind; + } + + # If we were able to bind if ($auth) { - $search = $ldap->search ( base=>$uri->dn, filter=>$connection->{ldapIdentity}."=".$self->session->form->process('authLDAP_ldapId')); - if (defined $search->entry(0)) { - if ($connection->{ldapUserRDN} eq 'dn') { - $connectDN = $search->entry(0)->dn; - } else { - $connectDN = $search->entry(0)->get_value($connection->{ldapUserRDN}); - } - $ldap->unbind; - $ldap = Net::LDAP->new($uri->host, (port=>$uri->port)) or $error .= $i18n->get(2,'AuthLDAP'); - $auth = $ldap->bind(dn=>$connectDN, password=>$self->session->form->process('authLDAP_identifier')); - if ($auth->code == 48 || $auth->code == 49) { - $error .= '
  • '.$i18n->get(68).'
  • '; - $self->session->errorHandler->warn("Invalid LDAP information for registration of LDAP ID: ".$self->session->form->process('authLDAP_ldapId')); - } elsif ($auth->code > 0) { - $error .= '
  • LDAP error "'.$self->ldapStatusCode($auth->code).'" occured. '.$i18n->get(69).'
  • '; - $self->session->errorHandler->error("LDAP error: ".$self->ldapStatusCode($auth->code)); - } - $ldap->unbind; - } else { - $error .= '
  • '.$i18n->get(68).'
  • '; - $self->session->errorHandler->warn("Invalid LDAP information for registration of LDAP ID: ".$self->session->form->process("authLDAP_ldapId")); + + # Search for the user trying to login + $search = $ldap->search(base=>$uri->dn, filter=>$connection->{ldapIdentity}.'='.$username); + + # If we found a match + if (defined $search->entry(0)) { + + # Determine the users distinguished name using dn + if ($connection->{ldapUserRDN} eq 'dn') { + $connectDN = $search->entry(0)->dn; } - } else { - $error = $i18n->get(2,'AuthLDAP'); - $self->session->errorHandler->error("Couldn't bind to LDAP server: ".$connection->{ldapUrl}); - } - } else { - $error = $i18n->get(2,'AuthLDAP'); - $self->session->errorHandler->error("Couldn't create LDAP object: ".$uri->host); - } - $self->error($error); - return $error eq ""; + else { # or... use a releative distinguished name instead + $connectDN = $search->entry(0)->get_value($connection->{ldapUserRDN}); + } + + # Remember the users DN so we can use it later. + $self->setConnectDN($connectDN); + $ldap->unbind; + + # Create a new LDAP object + $ldap = Net::LDAP->new($uri->host, (port=>$uri->port)) or $error .= $i18n->get(2,'AuthLDAP'); + + # Try to bind to the directory using the users dn and password + $auth = $ldap->bind(dn=>$connectDN, password=>$password); + + # Invalid login credentials, directory did not authenticate the user + if ($auth->code == 48 || $auth->code == 49) { + $error .= '
  • '.$i18n->get(68).'
  • '; + $self->session->errorHandler->warn("Invalid LDAP information for registration of LDAP ID: ".$self->session->form->process('authLDAP_ldapId')); + } + elsif ($auth->code > 0) { # Some other LDAP error occured + $error .= '
  • LDAP error "'.$self->ldapStatusCode($auth->code).'" occured. '.$i18n->get(69).'
  • '; + $self->session->errorHandler->error("LDAP error: ".$self->ldapStatusCode($auth->code)); + } + $ldap->unbind; + } + else { # Could not find the user in the directory to build a DN + $error .= '
  • '.$i18n->get(68).'
  • '; + $self->session->errorHandler->warn("Invalid LDAP information for registration of LDAP ID: ".$self->session->form->process("authLDAP_ldapId")); + } + } + else { # Unable to bind with proxy user credentials or anonymously for our search + $error = $i18n->get(2,'AuthLDAP'); + $self->session->errorHandler->error("Couldn't bind to LDAP server: ".$connection->{ldapURL}); + } + } + else { # Could not create our LDAP object + $error = $i18n->get(2,'AuthLDAP'); + $self->session->errorHandler->error("Couldn't create LDAP object: ".$uri->host); + } + + $self->error($error); + + # Return 1 on successful authentication + return $error eq ""; } #------------------------------------------------------------------- +=head2 sub authenticate ( $username, $password ) + +This method checks a given username and password for the following: + +1) Is there a WebGUI user account for the user and is it active +2) Does the user account have the properties set necessary to authenticate using + LDAP. +3) Can we bind to the LDAP server using their account information + +Returns 1 on success. + +=cut + sub authenticate { - my $self = shift; - my ($uri, $ldap, $auth, $result, $error); - return 0 if !$self->SUPER::authenticate($_[0]); #authenticate that the username entered actually exists and is active - my $userId = $self->userId; - my $identifier = $_[1]; - my $userData = $self->getParams; + my $self = shift; + my ($uri, $ldap, $auth, $result, $error); + my $i18n = WebGUI::International->new($self->session); + return 0 if !$self->SUPER::authenticate($_[0]); #see that the username entered actually exists and is active in webgui + + my $userId = $self->userId; + my $identifier = $_[1]; + my $userData = $self->getParams; + $error .= $i18n->get(12,'AuthLDAP') if ($userData->{ldapUrl} eq ""); + $error .= $i18n->get(11,'AuthLDAP') if ($userData->{connectDN} eq ""); + $self->error($error); + + if($error ne ""){ + $self->user(WebGUI::User->new($self->session,1)); + return 0 ; + } - my $i18n = WebGUI::International->new($self->session); - $error .= $i18n->get(12,'AuthLDAP') if ($userData->{ldapUrl} eq ""); - $error .= $i18n->get(11,'AuthLDAP') if ($userData->{connectDN} eq ""); + if($uri = URI->new($userData->{ldapUrl})) { + + # Create an LDAP object + $ldap = Net::LDAP->new($uri->host, (port=>$uri->port)) or $error .= $i18n->get(2,'AuthLDAP'); + + if($error ne ""){ + $self->user(WebGUI::User->new($self->session,1)); + return 0 ; + } + + # Try to bind using the users dn and password + $auth = $ldap->bind(dn=>$userData->{connectDN}, password=>$identifier); + + # Authentication failed + if ($auth->code == 48 || $auth->code == 49){ + $error .= $i18n->get(68); + } + elsif ($auth->code > 0) { # Some other LDAP error happened + $error .= 'LDAP error "'.$self->ldapStatusCode($auth->code).'" occured.'.$i18n->get(69); + $self->session->errorHandler->error("LDAP error: ".$self->ldapStatusCode($auth->code)); + } + + $ldap->unbind; + } + else { + $error .= $i18n->get(13,'AuthLDAP'); + $self->session->errorHandler->error("Could not process this LDAP URL: ".$userData->{ldapUrl}); + } - $self->error($error); - if($error ne ""){ - $self->user(WebGUI::User->new($self->session,1)); - return 0 ; - } - - if($uri = URI->new($userData->{ldapUrl})) { - $ldap = Net::LDAP->new($uri->host, (port=>$uri->port)) or $error .= $i18n->get(2,'AuthLDAP'); - if($error ne ""){ - $self->user(WebGUI::User->new($self->session,1)); - return 0 ; - } - $auth = $ldap->bind(dn=>$userData->{connectDN}, password=>$identifier); - if ($auth->code == 48 || $auth->code == 49){ - $error .= $i18n->get(68); - }elsif($auth->code > 0){ - $error .= 'LDAP error "'.$self->ldapStatusCode($auth->code).'" occured.'.$i18n->get(69); - $self->session->errorHandler->error("LDAP error: ".$self->ldapStatusCode($auth->code)); - } - $ldap->unbind; - }else{ - $error .= $i18n->get(13,'AuthLDAP'); - $self->session->errorHandler->error("Could not process this LDAP URL: ".$userData->{ldapUrl}); - } - if($error ne ""){ - $self->error($error); - $self->user(WebGUI::User->new($self->session,1)); - } - return $error eq ""; + if($error ne ""){ + $self->error($error); + $self->user(WebGUI::User->new($self->session,1)); + } + + return $error eq ""; } +#------------------------------------------------------------------- +sub connectToLDAP { + my $self = shift; + my $connectionId = $self->session->form->process("connection") || $self->session->setting->get("ldapConnection"); + my $ldapLink = WebGUI::LDAPLink->new($self->session,$connectionId); + my $connection = $ldapLink->get; + + $self->{_connection} = $connection; + return $connection; +} #------------------------------------------------------------------- sub createAccount { @@ -135,11 +217,8 @@ sub createAccount { return $self->displayLogin; } - if($self->session->form->process("connection")) { - $self->session->scratch->set("ldapConnection",$self->session->form->process("connection")); - $self->{_connection} = WebGUI::LDAPLink->new($self->session,$self->session->form->process("connection"))->get; - } - my $connection = $self->{_connection}; + + my $connection = $self->getLDAPConnection; $vars->{'create.message'} = $message if ($message); my $i18n = WebGUI::International->new($self->session,"AuthLDAP"); $vars->{'create.form.ldapConnection.label'} = $i18n->get("ldapConnection"); @@ -173,9 +252,9 @@ sub createAccountSave { return $self->createAccount("

    ".$i18n->get(70)."

    ".$self->error); } - my $connection = $self->{_connection}; + my $connection = $self->getLDAPConnection; #Get connectDN from settings - my $uri = URI->new($connection->{ldapUrl}); + my $uri = URI->new($connection->{ldapURL}); my $ldap = Net::LDAP->new($uri->host, (port=>$uri->port)); my $auth; if($connection->{connectDn}) { @@ -209,7 +288,7 @@ sub createAccountSave { my $properties; $properties->{connectDN} = $connectDN; - $properties->{ldapUrl} = $connection->{ldapUrl}; + $properties->{ldapUrl} = $connection->{ldapURL}; return $self->SUPER::createAccountSave($username,$properties,$password,$profile); } @@ -264,8 +343,8 @@ sub displayLogin { sub editUserForm { my $self = shift; my $userData = $self->getParams; - my $connection = $self->{_connection}; - my $ldapUrl = $self->session->form->process('authLDAP_ldapUrl') || $userData->{ldapUrl} || $connection->{ldapUrl}; + my $connection = $self->getLDAPConnection; + my $ldapUrl = $self->session->form->process('authLDAP_ldapUrl') || $userData->{ldapUrl} || $connection->{ldapURL}; my $connectDN = $self->session->form->process('authLDAP_connectDN') || $userData->{connectDN}; my $ldapConnection = $self->session->form->process('authLDAP_ldapConnection') || $userData->{ldapConnection}; my $ldapLinks = $self->session->db->buildHashRef("select ldapLinkId,ldapUrl from ldapLink"); @@ -355,40 +434,83 @@ sub editUserSettingsForm { #------------------------------------------------------------------- sub editUserSettingsFormSave { - my $self = shift; - my $f = $self->session->form; - my $s = $self->session->setting; - $s->set("ldapConnection", $f->process("ldapConnection","selectBox")); + my $self = shift; + my $f = $self->session->form; + my $s = $self->session->setting; + $s->set("ldapConnection", $f->process("ldapConnection","selectBox")); } #------------------------------------------------------------------- sub getAccountTemplateId { my $self = shift; - return ($self->{_connection}->{ldapAccountTemplate} || "PBtmpl0000000000000004"); + return ($self->getLDAPConnection->{ldapAccountTemplate} || "PBtmpl0000000000000004"); +} + +#------------------------------------------------------------------- +sub getConnectDN { + my $self = shift; + return $self->{_connectDN}; } #------------------------------------------------------------------- sub getCreateAccountTemplateId { my $self = shift; - return ($self->{_connection}->{ldapCreateAccountTemplate} || "PBtmpl0000000000000005"); + return ($self->getLDAPConnection->{ldapCreateAccountTemplate} || "PBtmpl0000000000000005"); +} + +#------------------------------------------------------------------- +sub getLDAPConnection { + my $self = shift; + + return $self->{_connection} if $self->{_connection}; + return $self->connectToLDAP; } #------------------------------------------------------------------- sub getLoginTemplateId { my $self = shift; - return ($self->{_connection}->{ldapLoginTemplate} || "PBtmpl0000000000000006"); + return ($self->getLDAPConnection->{ldapLoginTemplate} || "PBtmpl0000000000000006"); } #------------------------------------------------------------------- sub login { my $self = shift; - if(!$self->authenticate($self->session->form->process("username"),$self->session->form->process("identifier"))){ - $self->session->errorHandler->security("login to account ".$self->session->form->process("username")." with invalid information."); - my $i18n = WebGUI::International->new($self->session); - return $self->displayLogin("

    ".$i18n->get(70)."

    ".$self->error); + my $i18n = WebGUI::International->new($self->session); + my $username = $self->session->form->process("username"); + my $identifier = $self->session->form->process("identifier"); + my $autoRegistration = $self->session->setting->get("automaticLDAPRegistration"); + my $hasAuthenticated = 0; + + $hasAuthenticated = 1 if ( $self->authenticate($username,$identifier) ); + + # Autoregistration is on and they didn't authenticate yet + if ($autoRegistration && !$hasAuthenticated) { + # See if they are in LDAP and if so that they can bind with the password given. + if($self->_isValidLDAPUser()) { + + # Create a WebGUI Account + if ($self->validUsername($username)) { + $self->SUPER::createAccountSave($username, { + connectDN => $self->getConnectDN, + ldapUrl => $self->getLDAPConnection->{ldapUrl} + },$identifier); + $hasAuthenticated = 1; + + # Pull the users profile from LDAP to WebGUI + WebGUI::Workflow::Instance->create($self->session, { + workflowId=>'AuthLDAPworkflow000001', + methodName=>"new", + className=>"WebGUI::User", + parameters=>$self->session->user->userId, + priority=>3 + }); + } + } } - $self->session->scratch->delete("ldapConnection"); - return $self->SUPER::login(); #Standard login routine for login + return $self->SUPER::login() if $hasAuthenticated; #Standard login routine for login + + $self->session->errorHandler->security("login to account ".$self->session->form->process("username")." with invalid information."); + return $self->displayLogin("

    ".$i18n->get(70)."

    ".$self->error); } #------------------------------------------------------------------- @@ -399,9 +521,10 @@ sub new { my $userId = $_[1]; my @callable = ('createAccount','deactivateAccount','displayAccount','displayLogin','login','logout','createAccountSave','deactivateAccountConfirm'); my $self = WebGUI::Auth->new($session,$authMethod,$userId,\@callable); - my $connection = $session->scratch->get("ldapConnection") || $session->setting->get("ldapConnection"); - my $ldaplink = WebGUI::LDAPLink->new($session,$connection); - $self->{_connection} = $ldaplink->get if $ldaplink; + #my $connection = $session->scratch->get("ldapConnection") || $session->setting->get("ldapConnection"); + #my $ldaplink = WebGUI::LDAPLink->new($session,$connection); + #$self->{_connection} = $ldaplink->get if $ldaplink; + my $i18n = WebGUI::International->new($session, "AuthLDAP"); my %ldapStatusCode = map { $_ => $i18n->get("LDAPLink_".$_) } (0..21, 32,33,34,36, 48..54, 64..71, 80); @@ -413,8 +536,14 @@ sub new { sub ldapStatusCode { my ($self, $code) = @_; return $self->{_statusCode}->{$code}; - } +#------------------------------------------------------------------- +sub setConnectDN { + my $self = shift; + $self->{_connectDN} = $_[0]; +} + + 1; diff --git a/lib/WebGUI/Operation/Settings.pm b/lib/WebGUI/Operation/Settings.pm index 2efc6de1f..3debf661c 100644 --- a/lib/WebGUI/Operation/Settings.pm +++ b/lib/WebGUI/Operation/Settings.pm @@ -256,6 +256,14 @@ sub definition { hoverHelp=>$i18n->get('118 description'), defaultValue=>$session->setting->get("anonymousRegistration") }); + push(@fields, { + tab=>"user", + fieldType=>"yesNo", + name=>"automaticLDAPRegistration", + label=>$i18n->echo("Automatic LDAP Registration"), + hoverHelp=>$i18n->echo('When set to yes, a WebGUI user account will be created and the user logged in, if the credentials entered are validated by LDAP.'), + defaultValue=>$session->setting->get("automaticLDAPRegistration") + }); push(@fields, { tab=>"user", fieldType=>"workflow", diff --git a/lib/WebGUI/Workflow/Activity/SyncProfileToLdap.pm b/lib/WebGUI/Workflow/Activity/SyncProfileToLdap.pm new file mode 100644 index 000000000..4fd75ae7f --- /dev/null +++ b/lib/WebGUI/Workflow/Activity/SyncProfileToLdap.pm @@ -0,0 +1,152 @@ +package WebGUI::Workflow::Activity::SyncProfileToLdap; + + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2006 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use base 'WebGUI::Workflow::Activity'; +use Net::LDAP; +use WebGUI::Auth; +use WebGUI::User; + +=head1 NAME + +Package WebGUI::Workflow::Activity::SyncProfileToLdap + +=head1 DESCRIPTION + +Synchoronizes the data for one user in your LDAP directory with the WebGUI user's profile. This is a one way sync, so data comes from LDAP to WebGUI, not the other way around. + +=head1 SYNOPSIS + +See WebGUI::Workflow::Activity for details on how to use any activity. + +=head1 METHODS + +These methods are available from this class: + +=cut + + +#------------------------------------------------------------------- + +=head2 definition ( session, definition ) + +See WebGUI::Workflow::Activity::defintion() for details. + +=cut + +sub definition { + my $class = shift; + my $session = shift; + my $definition = shift; + my $i18n = WebGUI::International->new($session, "AuthLDAP"); + push(@{$definition}, { + name=>$i18n->echo("Synchronize Profile To LDAP"), + properties=> { } + }); + return $class->SUPER::definition($session,$definition); +} + + + +my %ldapStatusCode = ( 0=>'success (0)', 1=>'Operations Error (1)', 2=>'Protocol Error (2)', + 3=>'Time Limit Exceeded (3)', 4=>'Size Limit Exceeded (4)', 5=>'Compare False (5)', + 6=>'Compare True (6)', 7=>'Auth Method Not Supported (7)', 8=>'Strong Auth Required (8)', + 10=>'Referral (10)', 11=>'Admin Limit Exceeded (11)', 12=>'Unavailable Critical Extension (12)', + 13=>'Confidentiality Required (13)', 14=>'Sasl Bind In Progress (14)', + 15=>'No Such Attribute (16)', 17=>'Undefined Attribute Type (17)', + 18=>'Inappropriate Matching (18)', 19=>'Constraint Violation (19)', + 20=>'Attribute Or Value Exists (20)', 21=>'Invalid Attribute Syntax (21)', 32=>'LDAP Entry Does Not Exist (32)', + 33=>'Alias Problem (33)', 34=>'Invalid DN Syntax (34)', 36=>'Alias Dereferencing Problem (36)', + 48=>'Inappropriate Authentication (48)', 49=>'Invalid Credentials (49)', + 50=>'Insufficient Access Rights (50)', 51=>'Busy (51)', 52=>'Unavailable (52)', + 53=>'Unwilling To Perform (53)', 54=>'Loop Detect (54)', 64=>'Naming Violation (64)', + 65=>'Object Class Violation (65)', 66=>'Not Allowed On Non Leaf (66)', 67=>'Not Allowed On RDN (67)', + 68=>'Entry Already Exists (68)', 69=>'Object Class Mods Prohibited (69)',70=>'The results of the request are to large (70)', + 71=>'Affects Multiple DSAs (71)', 80=>'other (80)',81=>'Net::LDAP cannot establish a connection or the connection has been lost (81)', + 85=>'Net::LDAP timeout while waiting for a response from the server (85)', + 86=>'The method of authentication requested in a bind request is unknown to the server (86)', + 87=>'An error occurred while encoding the given search filter. (87)', + 89=>'An invalid parameter was specified (89)',90=>'Out of Memory (90)',91=>'A connection to the server could not be established (91)', + 92=>'An attempt has been made to use a feature not supported by Net::LDAP (92)'); + +#------------------------------------------------------------------- +sub _alias { + my %alias = ( + firstName=>"cn", + lastName=>"sn", + email=>"mail", + companyName=>"o" + ); + return $alias{$_[0]} || $_[0]; +} + +#------------------------------------------------------------------- + +=head2 execute ( ) + +See WebGUI::Workflow::Activity::execute() for details. + +=cut + +sub execute { + my $self = shift; + my $userObject = shift; # Set to the current user by the instance + my ($userId, $u, $userData, $uri, $port, %args, $fieldName, $ldap, $search, $a, $b); + + $userId = $userObject->userId; + my $auth = WebGUI::Auth->new($self->session, "LDAP",$userId); + $userData = $auth->getParams; + $uri = URI->new($userData->{ldapUrl}); + if ($uri->port < 1) { + $port = 389; + } else { + $port = $uri->port; + } + + %args = (port => $port); + $ldap = Net::LDAP->new($uri->host, %args); + if ($ldap) { + my $result = $ldap->bind; + if ($result->code == 0) { + $search = $ldap->search( base=>$userData->{connectDN}, filter=>"&(objectClass=*)" ); + if($search->code) { + $self->session->errorHandler->warn("Couldn't search LDAP ".$uri->host." to find user ".$u->username." (".$userId.").\nError Message from LDAP: ".$ldapStatusCode{$search->code}); + } + elsif ($search->count == 0) { + $self->session->errorHandler->warn("No results returned for user with dn ".$userData->{connectDN}); + } + else { + $b = $self->session->db->read("select fieldName from userProfileField where profileCategoryId<>4"); + while (($fieldName) = $b->array) { + if ($search->entry(0)->get_value(_alias($fieldName)) ne "") { + $userObject->profileField($fieldName,$search->entry(0)->get_value(_alias($fieldName))); + } + } + $b->finish; + } + $ldap->unbind; + } + else { + $self->session->errorHandler->warn("Couldn't bind to LDAP host ".$uri->host."\nError Message from LDAP: ".$ldapStatusCode{$result->code}); + } + + } + $a->finish; + return $self->COMPLETE; +} + +1;