Skip to content

Commit

Permalink
API Update API to reflect changes to CLI interaction (#89)
Browse files Browse the repository at this point in the history
  • Loading branch information
GuySartorelli committed Sep 26, 2024
1 parent 4dc670c commit 61dfca8
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 237 deletions.
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

0 comments on commit 61dfca8

Please sign in to comment.