[Rt-commit] rt branch 5.0/load-by-user-cf created. rt-5.0.3-146-gda989f9a70

BPS Git Server git at git.bestpractical.com
Tue Nov 15 22:28:49 UTC 2022


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt".

The branch, 5.0/load-by-user-cf has been created
        at  da989f9a70522caa64ea0eb5369138c0511072f2 (commit)

- Log -----------------------------------------------------------------
commit da989f9a70522caa64ea0eb5369138c0511072f2
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Mon Nov 14 15:44:35 2022 -0500

    Tests for loading users via UserCFs

diff --git a/t/externalauth/ldap.t b/t/externalauth/ldap.t
index ad304a7319..7ec21081c3 100644
--- a/t/externalauth/ldap.t
+++ b/t/externalauth/ldap.t
@@ -214,6 +214,54 @@ diag "test user update via login";
     );
 }
 
+diag 'Login with UserCF as username';
+
+RT::Test->stop_server();
+
+RT->Config->Set(
+    ExternalSettings => {    # AN EXAMPLE DB SERVICE
+        'My_LDAP' => {
+            'type'            => 'ldap',
+            'server'          => "127.0.0.1:$ldap_port",
+            'base'            => $base,
+            'filter'          => '(objectClass=*)',
+            'd_filter'        => '()',
+            'tls'             => 0,
+            'net_ldap_args'   => [ version => 3 ],
+            'attr_match_list' => [ 'UserCF.Employee ID', 'EmailAddress' ],
+            'attr_map'        => {
+                'Name'                 => 'uid',
+                'EmailAddress'         => 'mail',
+                'FreeformContactInfo'  => [ 'uid', 'mail' ],
+                'CF.Employee Type'     => 'employeeType',
+                'UserCF.Employee Type' => 'employeeType',
+                'UserCF.Employee ID'   => 'employeeID',
+            }
+        },
+    }
+);
+RT->Config->PostLoadCheck;
+
+( $baseurl, $m ) = RT::Test->started_ok();
+
+diag "test uri login";
+{
+    my $testuser = RT::User->new($RT::SystemUser);
+    my ($ok,$msg) = $testuser->Load( 'testuser' );
+    ok($ok,$msg);
+
+    # Reset employee ID to just id
+    $testuser->AddCustomFieldValue( Field => 'Employee ID', Value => '234' );
+    is( $testuser->FirstCustomFieldValue('Employee ID'), 234, 'Employee ID set to 234');
+
+    # Can't use usual login method because it checks for username and for this test,
+    # the username is not the user CF value we are sending
+
+    $m->get($baseurl . "?user=234;pass=password");
+    ok( $m->content =~ m/Logout/i, 'Logged in' );
+    ok( $m->logged_in_as('testuser'), 'Logged in as testuser' );
+}
+
 $ldap->unbind();
 
 done_testing;

commit 1a96dd703e336524372dfce9f751c57473592085
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Mon Nov 14 15:42:40 2022 -0500

    Support loading users via user custom fields
    
    External auth allows admins to provide a list of attributes
    for users to use in the username box on login, like 'Name'
    or 'EmailAddress' and it will try both. 566b8fa1 added support
    for using UserCFs in mappings, but not as login attributes.
    
    This commit adds support for loading users with UserCFs, so
    configurations like this can now be used:
    
        'attr_match_list' => [
            'UserCF.Employee ID',
            'EmailAddress',
        ],

diff --git a/lib/RT/Authen/ExternalAuth.pm b/lib/RT/Authen/ExternalAuth.pm
index 7384c92a91..0093d143bd 100644
--- a/lib/RT/Authen/ExternalAuth.pm
+++ b/lib/RT/Authen/ExternalAuth.pm
@@ -418,8 +418,12 @@ sub DoAuth {
         # then we need to create the user in RT.
 
         # Does user already exist internally to RT?
-        $session->{'CurrentUser'} = RT::CurrentUser->new();
-        $session->{CurrentUser}->LoadByCols( $field || 'Name', $username );
+        my $load_user_obj = RT::CurrentUser->new();
+
+        $session->{'CurrentUser'} = RT::Authen::ExternalAuth::LoadUserObject(
+            UserObj => $load_user_obj,
+            Field => $field || 'Name',
+            Username => $username );
 
         # Unless we have loaded a valid user with a UserID create one.
         unless ($session->{'CurrentUser'}->Id) {
@@ -557,7 +561,10 @@ sub UpdateUserInfo {
     my $user_disabled   = RT::Authen::ExternalAuth::UserDisabled($username);
 
     my $UserObj = RT::User->new(RT->SystemUser);
-    $UserObj->LoadByCols($field => $username);
+    $UserObj = RT::Authen::ExternalAuth::LoadUserObject(
+        UserObj => $UserObj,
+        Field => $field,
+        Username => $username );
 
     # If user is disabled, set the RT::Principal 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
@@ -758,6 +765,31 @@ sub AddCustomFieldValue {
     return;
 }
 
+sub LoadUserObject {
+    my %args = (
+        UserObj => undef,
+        Field => 'Name',
+        Username => undef,
+        @_
+    );
+    my ( $ret, $msg );
+
+    if ( my ($cf_name) = $args{'Field'} =~ /^UserCF\.(.+)$/i ) {
+        ( $ret, $msg ) = $args{'UserObj'}->LoadObjectByCustomFieldValue(
+            CustomField => $cf_name,
+            Value => $args{'Username'},
+            ObjectType => $args{'UserObj'}->CustomFieldLookupType,
+        );
+    }
+    else {
+        # No user CF, normal load
+        ( $ret, $msg ) = $args{'UserObj'}->LoadByCols( $args{'Field'}, $args{'Username'} );
+    }
+
+    RT->Logger->debug("Unable to load user " . $args{'Username'} . " from field " . $args{'Field'}) unless $ret;
+    return $args{'UserObj'};
+}
+
 RT::Base->_ImportOverlays();
 
 1;

commit 2a47cb833baf30f5f95402ea0792ecba9af8c2c0
Author: Jim Brandt <jbrandt at bestpractical.com>
Date:   Tue Nov 15 17:21:59 2022 -0500

    Add method to load an object based on a custom field value

diff --git a/lib/RT/Record.pm b/lib/RT/Record.pm
index 13691bf1ad..914dcb4dac 100644
--- a/lib/RT/Record.pm
+++ b/lib/RT/Record.pm
@@ -2363,6 +2363,49 @@ sub LoadCustomFieldByIdentifier {
     return $cf;
 }
 
+=head2 LoadObjectByCustomFieldValue
+
+Load an object based on the value of a custom field applied to that
+object. Loads only one object. If the value isn't unique for that
+object type, the first found is returned.
+
+Accepts: CustomField => 'Foo', Value => 'Bar', ObjectType => 'RT::User'
+
+Returns: ($status, $message) and loads the object, if successful
+
+=cut
+
+sub LoadObjectByCustomFieldValue {
+    my $self = shift;
+    my %args = (
+        CustomField => undef,
+        Value => undef,
+        ObjectType => RT::Ticket->CustomFieldLookupType,
+        @_
+    );
+
+    my $cf_obj = RT::CustomField->new(RT->SystemUser);
+    my ($cf_ret, $cf_msg) = $cf_obj->LoadByName(
+        Name => $args{'CustomField'}, LookupType => $args{'ObjectType'} );
+    RT->Logger->warn("Unable to load custom field with name " . $args{'CustomField'} . ": $cf_msg") unless $cf_ret;
+
+    my $ocfv_obj = RT::ObjectCustomFieldValue->new(RT->SystemUser);
+    my ($ocfv_ret, $ocfv_msg) = $ocfv_obj->LoadByCols(
+        ObjectType  => $args{'ObjectType'},
+        CustomField => $cf_obj->Id,
+        Content     => $args{'Value'},
+        Disabled    => 0,
+    );
+
+    my ( $ret, $msg );
+    if ( $ocfv_ret && $ocfv_obj->Id ) {
+        # Found an object with that CF, so try to load it
+        ( $ret, $msg ) = $self->LoadById( $ocfv_obj->ObjectId );
+    }
+
+    return wantarray ? ( $ret, $msg ) : $ret;
+}
+
 sub ACLEquivalenceObjects { } 
 
 =head2 HasRight

-----------------------------------------------------------------------


hooks/post-receive
-- 
rt


More information about the rt-commit mailing list