Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Delete and Restore not soft-deleting/restoring users #678

Open
dereknutile opened this issue Dec 19, 2024 · 5 comments
Open

[Bug] Delete and Restore not soft-deleting/restoring users #678

dereknutile opened this issue Dec 19, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@dereknutile
Copy link

Environment:

  • LDAP Server Type: ActiveDirectory
  • LdapRecord-Laravel Major Version: v3.3.5
  • PHP Version: 8.3.7
  • Laravel Framework: v11.34.2

Recently I upgraded both Laravel (9 to 11) and LdapRecord (v2 to v3). Since then the --delete and --restore functionality stopped. All the other synchronization works fine. I'm not sure how to capture verbosely what is happening with those functions, but the logs state the user is being synchronized. I set this user to disabled in AD and syncronized, here's the log output:

[2024-12-19 20:59:55] local.INFO: LDAP (ldap://my.domain:389) - Operation: Binding - Username: myserviceaccount
[2024-12-19 20:59:55] local.INFO: LDAP (ldap://my.domain:389) - Operation: Bound - Username: myserviceaccount
[2024-12-19 20:59:55] local.INFO: LDAP (ldap://my.domain:389) - Operation: Paginate - Base DN: DC=xxx,DC=xxx,DC=xxx,DC=xxx - Filter: (&(samAccountName=adent)(objectclass=\75\73\65\72)(objectclass=\50\65\72\73\6f\6e)) - Selected: (objectguid,*) - Time Elapsed: 91.61
[2024-12-19 20:59:55] local.INFO: Starting import of [1] LDAP objects.
[2024-12-19 20:59:55] local.INFO: Object with name [Dent, Arthur] is being synchronized.
[2024-12-19 20:59:56] local.INFO: Object with name [Dent, Arthur] has been successfully synchronized.
[2024-12-19 20:59:56] local.INFO: Completed import. Imported [0] new LDAP objects. Synchronized [1] existing LDAP objects.

The local user database no longer soft-deletes the user.
image

@dereknutile dereknutile added the bug Something isn't working label Dec 19, 2024
@stevebauman
Copy link
Member

Hi @dereknutile, apologies for the late reply.

The import logic between v2 and v3 are functionally the same.

Does your users database table contain a domain column?

@stevebauman
Copy link
Member

Also, can you please post the whole command you are running?

@dereknutile
Copy link
Author

Hi @stevebauman, thank you for the reply. Yes, my users table does have a domain column. The command I'm using for my test user is as follows:

php artisan ldap:import ccso --delete --restore --filter "(samAccountName=adent)"

Found user [CN=Dent\2c Arthur].
Would you like to display the user(s) to be imported / synchronized? (yes/no) [no]: yes
+------------------------------------------------------------------------------+--------------------+
| Name | Distinguished Name |
+------------------------------------------------------------------------------+--------------------+
| CN=Dent, Arthur,OU=gptest,OU=Users,OU=xxx,DC=xxx,DC=ds,DC=xxx,DC=us | CN=Dent\2c Arthur |
+------------------------------------------------------------------------------+--------------------+
Would you like these users to be imported / synchronized? (yes/no) [yes]: yes
1/1 [============================] 100%
Successfully imported / synchronized [1] user(s).

It finds and synchronizes the user, but no longer flips the deleted_at flag.

image

@stevebauman
Copy link
Member

stevebauman commented Jan 13, 2025

Thanks for the reply @dereknutile.

Do you also have a guid column? I'd recommend dumping the output from the queries in this file to debug further:

protected function softDeleteMissing(LdapRecord $ldap, Eloquent $eloquent): void
{
if (! $this->isUsingSoftDeletes($eloquent)) {
return;
}
if ($this->objects->isEmpty()) {
return;
}
$domain = $ldap->getConnectionName() ?? Config::get('ldap.default');
$existing = $eloquent->newQuery()
->whereNotNull($eloquent->getLdapGuidColumn())
->where($eloquent->getLdapDomainColumn(), '=', $domain)
->pluck($eloquent->getLdapGuidColumn());
$toDelete = $existing->diff(
$this->imported->pluck($eloquent->getLdapGuidColumn())
);
if ($toDelete->isEmpty()) {
return;
}
$deleted = $eloquent->newQuery()
->whereNotNull($eloquent->getLdapGuidColumn())
->where($eloquent->getLdapDomainColumn(), '=', $domain)
->whereIn($eloquent->getLdapGuidColumn(), $toDelete->toArray())
->update([$eloquent->getDeletedAtColumn() => now()]);
if ($deleted > 0) {
event(new DeletedMissing($ldap, $eloquent, $toDelete));
}
}

Add dd() calls to the script and then re-run your import script with a deleted user to see where it's missing the user account.

@dereknutile
Copy link
Author

Hey @stevebauman , yes, I have a guid column in the users table named objectguid.

The account is found in AD. If I dd($object, $eloquent) on vendor\directorytree\ldaprecord-laravel\src\Import\Importer.php (line 271), I believe I'm capturing the two objects 1) the LDAP object and 2) the Users table object right before the synchronize(). If I understand how AD flags a user as disabled (https://learn.microsoft.com/en-us/troubleshoot/windows-server/active-directory/useraccountcontrol-manipulate-account-properties), the useraccountcontrol property will be set to 514 (512 for enabled).

What the dd() output shows below is the LDAP object retrieved from AD is disabled, and the User object retrieved from the table is not soft-deleted. The synchronize() that follows I would expect to soft-delete the user.

Found user [CN =Dent\2c Arthur].
App\Ldap\Ccso\User {#2234
+exists: true
+wasRecentlyCreated: false
+wasRecentlyRenamed: false
#dn: "CN=Dent, Arthur,OU=gptest,OU=Users,OU=CCSO,DC=ccso,DC=ds,DC=clackamas,DC=us"
#in: null
#connection: "ccso"
#guidKey: "objectguid"
#modifications: []
#changes: []
#attributes: array:79 [
"objectclass" => array:4 [
0 => "top"
1 => "person"
2 => "organizationalPerson"
3 => "user"
]
"cn" => array:1 [
0 => "Dent, Arthur"
]
# ATTRIBUTES REMOVED FOR BREVITY
# This account is disabled in AD...
"useraccountcontrol" => array:1 [
0 => "514"
]
]
#dates: []
#casts: []
#appends: []
#dateFormat: null
#defaultDates: array:2 [
"createtimestamp" => "ldap"
"modifytimestamp" => "ldap"
]
#hidden: []
#visible: []
}
App\Models\User\User {#3235
#connection: "application"
#table: "users"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
+preventsLazyLoading: false
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#escapeWhenCastingToString: false
#attributes: array:54 [
"id" => "2718"
"name" => "Dent, Arthur"
"username" => "ADent"
# ATTRIBUTES REMOVED FOR BREVITY
# This account is not soft-deleted in the users table ...
"deleted_at" => null
"created_at" => "2018-10-30 18:49:24.503"
"updated_at" => "2025-01-14 14:07:06.023"
]
#changes: []
#casts: array:1 [
"deleted_at" => "datetime"
]
#classCastCache: []
#attributeCastCache: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
+usesUniqueIds: false
#hidden: array:1 [
0 => "password"
]
#visible: []
#guarded: array:1 [
0 => "*"
]
#authPasswordName: "password"
#rememberTokenName: "remember_token"
+mediaConversions: []
+mediaCollections: []
#deletePreservingMedia: false
#unAttachedMediaLibraryItems: []
#forceDeleting: false
} // vendor\directorytree\ldaprecord-laravel\src\Import\Importer.php:271

If I'm understanding this properly, I think I should next walk through the LdapRecord\Laravel\Import\Synchronizer::synchronize method to see if there is data not being seen or handled. Thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants