Skip to content

Conversation

@woodseowl
Copy link
Collaborator

@woodseowl woodseowl commented Oct 17, 2023

A helper for retrieving Cornell University LDAP data. Based on the legacy App\Helpers\LDAP::data() class that exists on various Cornell Laravel sites.

This PR does the following

  • Adds src\Ldap\LdapSearch for retrieving data from LDAP
  • Adds src\Ldap\LdapData for normalizing data from LDAP
  • Adds src\Ldap\LdapDataServiceProvider to provide default configuration
  • Updates .env.example with required LDAP variables
  • Documentation and rudimentary testing

To Review:

  • Review README file additions to assess usage
  • Review how the LDAP data is normalized in src\Ldap\LdapData::make(). This was based on a comparison of approaches applied in DailyCheck, IT Gov, and EMNPhone. (Improvements and alternate use case requirements welcome!)

Notes
The testing fixtures are real data from LDAP that I scrubbed of personal identifiers. I felt that this rudimentary testing was necessary to assure that we don't break how we retrieve this data that users will see as very personal.

@woodseowl woodseowl changed the base branch from main to phone-library October 17, 2023 17:35
Base automatically changed from phone-library to main December 18, 2023 19:44
# Conflicts:
#	README.md
#	composer.json
#	project/.env.example
#	src/StarterKitServiceProvider.php
#	tests/Feature/InstallStarterKitTest.php
#	tests/TestCase.php
@woodseowl woodseowl marked this pull request as ready for review April 4, 2025 19:32
@woodseowl woodseowl requested a review from Copilot September 9, 2025 18:02
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new LDAP helper library for retrieving Cornell University LDAP data, providing a standardized way to query and parse LDAP information with caching capabilities.

Key Changes

  • Adds complete LDAP data retrieval system with LdapSearch and LdapData classes
  • Implements service provider for configuration management and installation
  • Updates installation process to include LDAP configuration options

Reviewed Changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Ldap/LdapSearch.php Core LDAP search functionality with caching and connection handling
src/Ldap/LdapData.php Immutable data object for normalized LDAP user information
src/Ldap/LdapDataServiceProvider.php Service provider for LDAP configuration
config/ldap.php LDAP configuration file with Cornell-specific defaults
tests/Unit/Ldap/LdapDataTest.php Unit tests for LDAP data parsing and normalization
src/StarterKitServiceProvider.php Updates installation process to include LDAP configuration
composer.json Adds ext-ldap dependency and registers new service provider

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +84 to +85
'previousemplids' => $data['cornelledupreviousemplids'] ?? null,
];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need to return all these data from LDAP? Most of the time we just need to get a name and netid. I think the BindID must have special permissions to return some of these data (like emplid) and usually we do not have and do not need those permissions.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to return all the data from LDAP: No and most queries won't, which is fine and the code requires only 'uid' to be populated in the results. (And even that can be made optional.)

The attribute list in here was meant as a starter list, merging what is in DailyCheck, IT Gov, and EMN phone, which happened to be three place I was working at the time I was putting this together. Looking at the LDAP names in Confluence, I see that indeed emplid is not public, so you are right about special permission on that.

'emplid' => $data['cornelleduemplid'] ?? '',
'firstname' => $firstName ?? '',
'lastname' => $lastName ?? '',
'name' => trim("$firstName $lastName"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think full name must include middle name or at least it should be an option for both options. Also name formatting is usually application task: some applications need to display last name fist, some - first name first

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The array that is being populated is only there to match the LDAP::data() function that this is intended to replace.

This $ldapData = [... chunk could be removed entirely if we don't want to use the library for supporting existing applications.


campusPhone: $data['cornelleducampusphone'] ?? null,
deptName: $data['cornelledudeptname1'] ?? null,
workingTitle: $data['cornelleduwrkngtitle1'] ?? null,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if an application needs department name and working title, then these data should be coming from Workday not from LDAP

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you are bringing up a good question about the source of the data. I can see that the attribute documentation indicates the those fields come from "HR" (i.e., Workday), but I don't know much else.

Do we have reason to be concerned about some of these pass-through fields? Looking at the sources for the attributes, lots of them come from Workday and Peoplesoft.

public function email(): string
{
return $this->email ?: $this->principalName;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how can alias email exists without primary email?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! The doc comment is backwards 🤦🏻‍♂️

I think this confusion (mine, yours) highlights that we should be very clear about the function names. Maybe:

  • emailAlias() : hopefully obvious, and should be null if there isn't one
  • mail(): which is simply the direct value from LDAP (alias if it exists, or [email protected], if user has email)
  • principalEmail(): just making this name up... but meant to be the edupersonprincipalname attribute which looks like [email protected] for Ithaca people

Copy link

@inaydich inaydich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked through the LDAP PR. I think it is too complicated and we do not need most of that. At the same time it, I think it is missing some functionality. We usually use LDAP to look up the person by full or partial netid or name. I suggest to discuss the requirements before writing the code.

@woodseowl
Copy link
Collaborator Author

I looked through the LDAP PR. I think it is too complicated and we do not need most of that. At the same time it, I think it is missing some functionality. We usually use LDAP to look up the person by full or partial netid or name. I suggest to discuss the requirements before writing the code.

I like the suggestion to review the requirements together before proceeding.

I have two current use case that are applicable (one in WA Reviews, another that came up for EMN Phone), but you've got a lot more experience with Cornell LDAP use cases than I do. I'm not sure on timing for when to have the discussion, but maybe the FCS project will have a task that needs LDAP and we can catch it there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants