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

API Update API to reflect changes to CLI interaction #89

Merged
merged 1 commit into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions docs/en/developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,8 @@ See the [module docs](https://github.com/symbiote/silverstripe-queuedjobs) on ho

If you don't want to run a queued job, you can set a cronjob yourself by calling:

```
env php vendor/silverstripe/framework/cli-script.php dev/tasks/LDAPMemberSyncTask
```sh
vendor/bin/sake tasks:LDAPMemberSyncTask
```

### Syncing AD groups and users on a schedule
Expand All @@ -365,8 +365,8 @@ SilverStripe\LDAP\Jobs\LDAPAllSyncJob:
If you don't want to run a queued job, you can set a cronjob yourself by calling the two sync tasks (order is important, otherwise your group memberships might not get updated):

```sh
env php vendor/silverstripe/framework/cli-script.php dev/tasks/LDAPGroupSyncTask
env php vendor/silverstripe/framework/cli-script.php dev/tasks/LDAPMemberSyncTask
vendor/bin/sake tasks:LDAPGroupSyncTask
vendor/bin/sake tasks:LDAPMemberSyncTask
```

### Migrating existing users
Expand Down Expand Up @@ -438,9 +438,9 @@ The fallback authenticator will be used in the following conditions:

### Extending the member and group sync tasks with custom functionality

Both `LDAPMemberSyncTask` and `LDAPGroupSyncTask` provide extension points (`onAfterLDAPMemberSyncTask` and
`onAfterLDAPGroupSyncTask` respectively) after all members/groups have been synced and before the task exits. This is a
perfect time to set values that are dependent on a full sync - for example linking a user to their manager based on DNs.
Both `LDAPMemberSyncTask` and `LDAPGroupSyncTask` provide extension points (`onAfterLDAPMemberSyncTask` and
`onAfterLDAPGroupSyncTask` respectively) after all members/groups have been synced and before the task exits. This is a
perfect time to set values that are dependent on a full sync - for example linking a user to their manager based on DNs.
For example:

```yaml
Expand All @@ -462,7 +462,7 @@ use SilverStripe\Security\Member;
class LDAPMemberSyncExtension extends Extension
{
/**
* Assuming the `DN` and `ManagerDN` values are set by LDAP, this code will link a member with their manager and
* Assuming the `DN` and `ManagerDN` values are set by LDAP, this code will link a member with their manager and
* store the link in the `Manager` has_one.
*/
protected function onAfterLDAPMemberSyncTask()
Expand Down Expand Up @@ -505,19 +505,19 @@ This will allow users to change their AD password via the regular CMS "forgot pa

### Allow SilverStripe attributes to be reset (removed) by AD

By default if attributes are present, and then missing in subsequent requests, they are ignored (non-destructive) by
By default if attributes are present, and then missing in subsequent requests, they are ignored (non-destructive) by
this module. This can cause attributes to persist when they've been deliberately removed (attribute is no longer present)
in the LDAP source data.
in the LDAP source data.

If you wish a full two way sync to occur, then set the attribute on `LDAPService` for `reset_missing_attributes` to
enable a full sync.
If you wish a full two way sync to occur, then set the attribute on `LDAPService` for `reset_missing_attributes` to
enable a full sync.

*Note*: This will mean syncs are destructive, and data or attributes will be reset if missing from the master LDAP source
data.
data.

```yaml
SilverStripe\LDAP\Services\LDAPService:
reset_missing_attributes: true
reset_missing_attributes: true
```

### Writing LDAP data from SilverStripe
Expand Down
10 changes: 8 additions & 2 deletions src/Jobs/LDAPAllSyncJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
use SilverStripe\LDAP\Tasks\LDAPGroupSyncTask;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\PolyExecution\PolyOutput;
use SilverStripe\LDAP\Tasks\LDAPMemberSyncTask;
use Symbiote\QueuedJobs\Services\AbstractQueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJobService;
use Symfony\Component\Console\Input\ArrayInput;

/**
* Class LDAPAllSyncJob
Expand Down Expand Up @@ -84,11 +86,15 @@ public function process()
singleton(QueuedJobService::class)->queueJob($nextJob, date('Y-m-d H:i:s', time() + $regenerateTime));
}

$output = PolyOutput::create(PolyOutput::FORMAT_ANSI);
$input = new ArrayInput([]);
$input->setInteractive(false);

$task = Injector::inst()->create(LDAPGroupSyncTask::class);
$task->run(null);
$task->run($input, $output);

$task = Injector::inst()->create(LDAPMemberSyncTask::class);
$task->run(null);
$task->run($input, $output);

$this->isComplete = true;
}
Expand Down
7 changes: 6 additions & 1 deletion src/Jobs/LDAPMemberSyncJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
use SilverStripe\LDAP\Tasks\LDAPMemberSyncTask;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\PolyExecution\PolyOutput;
use Symbiote\QueuedJobs\Services\AbstractQueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJobService;
use Symfony\Component\Console\Input\ArrayInput;

/**
* Class LDAPMemberSyncJob
Expand Down Expand Up @@ -89,7 +91,10 @@ public function process()
}

$task = Injector::inst()->create(LDAPMemberSyncTask::class);
$task->run(null);
$output = PolyOutput::create(PolyOutput::FORMAT_ANSI);
$input = new ArrayInput([]);
$input->setInteractive(false);
$task->run($input, $output);

$this->isComplete = true;
}
Expand Down
101 changes: 33 additions & 68 deletions src/Tasks/LDAPGroupSyncTask.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@

use Exception;
use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Dev\BuildTask;
use SilverStripe\Dev\Deprecation;
use SilverStripe\PolyExecution\PolyOutput;
use SilverStripe\LDAP\Services\LDAPService;
use SilverStripe\ORM\DB;
use SilverStripe\Security\Group;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;

/**
* Class LDAPGroupSyncTask
Expand All @@ -18,11 +19,7 @@
*/
class LDAPGroupSyncTask extends BuildTask
{
/**
* {@inheritDoc}
* @var string
*/
private static $segment = 'LDAPGroupSyncTask';
protected static string $commandName = 'LDAPGroupSyncTask';

/**
* @var array
Expand All @@ -45,19 +42,12 @@ class LDAPGroupSyncTask extends BuildTask
*/
protected $ldapService;

/**
* @return string
*/
public function getTitle()
public function getTitle(): string
{
return _t(__CLASS__ . '.SYNCTITLE', 'Sync all groups from LDAP');
}

/**
* {@inheritDoc}
* @var HTTPRequest $request
*/
public function run($request)
protected function execute(InputInterface $input, PolyOutput $output): int
{
ini_set('max_execution_time', 900);

Expand All @@ -71,8 +61,6 @@ public function run($request)
'objectguid'
);

$start = time();

$created = 0;
$updated = 0;
$deleted = 0;
Expand All @@ -85,31 +73,27 @@ public function run($request)
$group = new Group();
$group->GUID = $data['objectguid'];

Deprecation::withSuppressedNotice(function () use ($data) {
$this->log(sprintf(
'Creating new Group (GUID: %s, sAMAccountName: %s)',
$data['objectguid'],
$data['samaccountname']
));
});
$output->writeln(sprintf(
'Creating new Group (GUID: %s, sAMAccountName: %s)',
$data['objectguid'],
$data['samaccountname']
));
$created++;
} else {
Deprecation::withSuppressedNotice(function () use ($group, $data) {
$this->log(sprintf(
'Updating existing Group "%s" (ID: %s, GUID: %s, sAMAccountName: %s)',
$group->getTitle(),
$group->ID,
$data['objectguid'],
$data['samaccountname']
));
});
$output->writeln(sprintf(
'Updating existing Group "%s" (ID: %s, GUID: %s, sAMAccountName: %s)',
$group->getTitle(),
$group->ID,
$data['objectguid'],
$data['samaccountname']
));
$updated++;
}

try {
$this->ldapService->updateGroupFromLDAP($group, $data);
} catch (Exception $e) {
Deprecation::withSuppressedNotice(fn() => $this->log($e->getMessage()));
$output->writeln('<error>' . $e->getMessage() . '</>');
continue;
}
}
Expand All @@ -121,13 +105,11 @@ public function run($request)
if (!isset($ldapGroups[$record['GUID']])) {
$group = Group::get()->byId($record['ID']);

Deprecation::withSuppressedNotice(function () use ($group) {
$this->log(sprintf(
'Removing Group "%s" (GUID: %s) that no longer exists in LDAP.',
$group->Title,
$group->GUID
));
});
$output->writeln(sprintf(
'Removing Group "%s" (GUID: %s) that no longer exists in LDAP.',
$group->Title,
$group->GUID
));

try {
// Cascade into mappings, just to clean up behind ourselves.
Expand All @@ -136,7 +118,7 @@ public function run($request)
}
$group->delete();
} catch (Exception $e) {
Deprecation::withSuppressedNotice(fn() => $this->log($e->getMessage()));
$output->writeln('<error>' . $e->getMessage() . '</>');
continue;
}

Expand All @@ -145,32 +127,15 @@ public function run($request)
}
}

$this->invokeWithExtensions('onAfterLDAPGroupSyncTask');

$end = time() - $start;

Deprecation::withSuppressedNotice(function () use ($created, $updated, $deleted, $end) {
$this->log(sprintf(
'Done. Created %s records. Updated %s records. Deleted %s records. Duration: %s seconds',
$created,
$updated,
$deleted,
round($end ?? 0.0, 0)
));
});
}
$this->invokeWithExtensions('onAfterLDAPGroupSyncTask', $output);

/**
* Sends a message, formatted either for the CLI or browser
*
* @param string $message
* @deprecated 2.3.0 Will be replaced with new $output parameter in the run() method
*/
protected function log($message)
{
Deprecation::notice('2.3.0', 'Will be replaced with new $output parameter in the run() method');
$message = sprintf('[%s] ', date('Y-m-d H:i:s')) . $message;
echo Director::is_cli() ? ($message . PHP_EOL) : ($message . '<br>');
$output->writeln(sprintf(
'Done. Created %s records. Updated %s records. Deleted %s records.',
$created,
$updated,
$deleted
));
return Command::SUCCESS;
}

/**
Expand Down
Loading
Loading