feat: listen to user life cycle events
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace KTXM\ProviderLocalDocuments\Listeners;
|
||||||
|
|
||||||
|
use KTXC\User\Event\UserCreatedEvent;
|
||||||
|
use KTXC\User\Event\UserDeletingEvent;
|
||||||
|
use KTXM\ProviderLocalDocuments\Providers\Personal\PersonalService;
|
||||||
|
use KTXM\ProviderLocalDocuments\Providers\Provider;
|
||||||
|
|
||||||
|
final class UserEventListener
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly Provider $provider,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onUserCreated(UserCreatedEvent $event): void
|
||||||
|
{
|
||||||
|
// Fetching initializes the virtual root and creates its disk location.
|
||||||
|
$this->provider->serviceFetch($event->tenantIdentifier(), $event->userIdentifier(), 'personal');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onUserDeleting(UserDeletingEvent $event): void
|
||||||
|
{
|
||||||
|
$service = $this->provider->serviceFetch($event->tenantIdentifier(), $event->userIdentifier(), 'personal');
|
||||||
|
if (!($service instanceof PersonalService)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$service->destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,9 +3,14 @@
|
|||||||
namespace KTXM\ProviderLocalDocuments;
|
namespace KTXM\ProviderLocalDocuments;
|
||||||
|
|
||||||
use KTXC\Resource\ProviderManager;
|
use KTXC\Resource\ProviderManager;
|
||||||
|
use KTXC\User\Event\UserCreatedEvent;
|
||||||
|
use KTXC\User\Event\UserDeletingEvent;
|
||||||
|
use KTXF\Event\DeliveryMode;
|
||||||
|
use KTXF\Event\EventListenerRegistrarInterface;
|
||||||
use KTXF\Module\ModuleBrowserInterface;
|
use KTXF\Module\ModuleBrowserInterface;
|
||||||
use KTXF\Module\ModuleInstanceAbstract;
|
use KTXF\Module\ModuleInstanceAbstract;
|
||||||
use KTXF\Resource\Provider\ProviderInterface;
|
use KTXF\Resource\Provider\ProviderInterface;
|
||||||
|
use KTXM\ProviderLocalDocuments\Listeners\UserEventListener;
|
||||||
use KTXM\ProviderLocalDocuments\Providers\Provider;
|
use KTXM\ProviderLocalDocuments\Providers\Provider;
|
||||||
|
|
||||||
class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
|
class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
|
||||||
@@ -19,6 +24,7 @@ class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
|
|||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private readonly ProviderManager $providerManager,
|
private readonly ProviderManager $providerManager,
|
||||||
|
private readonly EventListenerRegistrarInterface $events,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function handle(): string
|
public function handle(): string
|
||||||
@@ -59,6 +65,10 @@ class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
|
|||||||
|
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
|
// Register listeners
|
||||||
|
$this->events->listen($this->handle(), UserCreatedEvent::class, UserEventListener::class, 'onUserCreated', DeliveryMode::Deferred);
|
||||||
|
$this->events->listen($this->handle(), UserDeletingEvent::class, UserEventListener::class, 'onUserDeleting', DeliveryMode::Deferred);
|
||||||
|
// Register providers
|
||||||
$this->providerManager->register(ProviderInterface::TYPE_DOCUMENT, 'default', Provider::class);
|
$this->providerManager->register(ProviderInterface::TYPE_DOCUMENT, 'default', Provider::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -335,6 +335,41 @@ class PersonalService implements ServiceBaseInterface, ServiceCollectionMutableI
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permanently remove all document data owned by the initialized user.
|
||||||
|
*/
|
||||||
|
public function destroy(): void {
|
||||||
|
foreach ($this->entityListBulk(null) as $entity) {
|
||||||
|
$identifier = $entity->identifier();
|
||||||
|
if ($identifier === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->entityDelete(new EntityIdentifier(
|
||||||
|
$entity->provider(),
|
||||||
|
(string) $entity->service(),
|
||||||
|
(string) $entity->collection(),
|
||||||
|
(string) $identifier,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->collectionList(null) as $collection) {
|
||||||
|
$identifier = $collection->identifier();
|
||||||
|
if ($identifier === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->collectionDelete(new CollectionIdentifier(
|
||||||
|
$collection->provider(),
|
||||||
|
(string) $collection->service(),
|
||||||
|
(string) $identifier,
|
||||||
|
), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->metaStore->chronicleExpungeByUser($this->serviceTenantId, $this->serviceUserId);
|
||||||
|
$this->blobStore->rootDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
public function collectionCopy(CollectionIdentifierInterface|null $target, CollectionIdentifierInterface $source): CollectionResource {
|
public function collectionCopy(CollectionIdentifierInterface|null $target, CollectionIdentifierInterface $source): CollectionResource {
|
||||||
$identifier = $source->collection();
|
$identifier = $source->collection();
|
||||||
// Protect root collection
|
// Protect root collection
|
||||||
|
|||||||
@@ -268,6 +268,34 @@ class BlobStore {
|
|||||||
return $blobDeleted && $metaDeleted;
|
return $blobDeleted && $metaDeleted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permanently remove the configured user storage root.
|
||||||
|
*/
|
||||||
|
public function rootDestroy(): void {
|
||||||
|
if ($this->rootPath === null || !is_dir($this->rootPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$root = realpath($this->rootPath);
|
||||||
|
if ($root === false || $root === DIRECTORY_SEPARATOR) {
|
||||||
|
throw new RuntimeException('Refusing to destroy an invalid blob root');
|
||||||
|
}
|
||||||
|
|
||||||
|
$iterator = new \RecursiveIteratorIterator(
|
||||||
|
new \RecursiveDirectoryIterator($root, \FilesystemIterator::SKIP_DOTS),
|
||||||
|
\RecursiveIteratorIterator::CHILD_FIRST,
|
||||||
|
);
|
||||||
|
foreach ($iterator as $entry) {
|
||||||
|
if ($entry->isDir() && !$entry->isLink()) {
|
||||||
|
rmdir($entry->getPathname());
|
||||||
|
} else {
|
||||||
|
unlink($entry->getPathname());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rmdir($root);
|
||||||
|
$this->rootPath = null;
|
||||||
|
}
|
||||||
|
|
||||||
// ========== Blob Existence Check ==========
|
// ========== Blob Existence Check ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -796,4 +796,14 @@ class MetaStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete every chronicle entry owned by a user.
|
||||||
|
*/
|
||||||
|
public function chronicleExpungeByUser(string $tenantId, string $userId): void {
|
||||||
|
$this->_store->selectCollection($this->_ChronicleTable)->deleteMany([
|
||||||
|
'tid' => $tenantId,
|
||||||
|
'uid' => $userId,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user