diff --git a/src/app/Console/Commands/UserRestore.php b/src/app/Console/Commands/UserRestore.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/UserRestore.php @@ -0,0 +1,47 @@ +where('email', $this->argument('user'))->first(); + + if (!$user) { + $this->error('User not found'); + return 1; + } + + if (!$user->trashed()) { + $this->error('The user is not yet deleted'); + return 1; + } + + DB::beginTransaction(); + $user->restore(); + DB::commit(); + } +} diff --git a/src/app/Domain.php b/src/app/Domain.php --- a/src/app/Domain.php +++ b/src/app/Domain.php @@ -267,6 +267,8 @@ $new_status |= self::STATUS_ACTIVE; } + // FIXME: Should we remove STATUS_LDAP_READY when setting STATUS_DELETED? + if ($new_status & self::STATUS_DELETED && $new_status & self::STATUS_ACTIVE) { $new_status ^= self::STATUS_ACTIVE; } diff --git a/src/app/Jobs/Domain/CreateJob.php b/src/app/Jobs/Domain/CreateJob.php --- a/src/app/Jobs/Domain/CreateJob.php +++ b/src/app/Jobs/Domain/CreateJob.php @@ -15,6 +15,9 @@ { $domain = $this->getDomain(); + // FIXME: I think we should also ignore domains marked as DELETED here, + // similar to what we do in User\CreateJob + if (!$domain->isLdapReady()) { \App\Backends\LDAP::createDomain($domain); diff --git a/src/app/Observers/DomainObserver.php b/src/app/Observers/DomainObserver.php --- a/src/app/Observers/DomainObserver.php +++ b/src/app/Observers/DomainObserver.php @@ -92,7 +92,37 @@ */ public function restored(Domain $domain) { - // + // Restore entitlements + + // FIXME: This will become problematic when we have other type of per-domain + // entitlements that shouldn't be restored with the domain + // Should we filter by SKU? + // Should we restore only these deleted last? + \App\Entitlement::withTrashed() + ->where('entitleable_id', $domain->id) + ->where('entitleable_type', Domain::class) + ->update(['updated_at' => now(), 'deleted_at' => null]); + + // Make sure it's not DELETED/LDAP_READY + if ($domain->isDeleted()) { + $domain->status ^= Domain::STATUS_DELETED; + } + if ($domain->isLdapReady()) { + $domain->status ^= Domain::STATUS_LDAP_READY; + } + + /* FIXME: Should we also unsuspend the domain? + if ($domain->isSuspended()) { + $domain->status ^= Domain::STATUS_SUSPENDED; + } + */ + + // FIXME: Should we modify created_at/updated_at? + + $domain->save(); + + // Create the domain in LDAP again + \App\Jobs\Domain\CreateJob::dispatch($domain->id); } /** diff --git a/src/app/Observers/UserObserver.php b/src/app/Observers/UserObserver.php --- a/src/app/Observers/UserObserver.php +++ b/src/app/Observers/UserObserver.php @@ -233,6 +233,70 @@ ->delete(); } + /** + * Handle the user "restored" event. + * + * @param \App\User $user The user + * + * @return void + */ + public function restored(User $user) + { + $wallets = $user->wallets()->pluck('id')->all(); + + // Restore all domains (domain entitlements will be restored + // by DomainObserver) + $domains = Entitlement::whereIn('wallet_id', $wallets)->withTrashed() + ->where('entitleable_type', Domain::class) + ->pluck('entitleable_id') + ->unique() + ->all(); + + if (!empty($domains)) { + Domain::withTrashed()->find($domains) + ->each(function ($domain, $key) { + $domain->restore(); + }); + } + + // Restore user entitlements + // FIXME: entitlements that shouldn't be recovered when a domain is to be restored + // Should we filter by SKU? + // Should we restore only these deleted last? + \App\Entitlement::withTrashed() + ->where('entitleable_id', $user->id) + ->where('entitleable_type', User::class) + ->update(['updated_at' => now(), 'deleted_at' => null]); + + + // Make sure it's not DELETED/LDAP_READY/IMAP_READY anymore + if ($user->isDeleted()) { + $user->status ^= User::STATUS_DELETED; + } + if ($user->isLdapReady()) { + $user->status ^= User::STATUS_LDAP_READY; + } + if ($user->isImapReady()) { + $user->status ^= User::STATUS_IMAP_READY; + } + + /* FIXME: Should we also unsuspend the user? + if ($user->isSuspended()) { + $user->status ^= User::STATUS_SUSPENDED; + } + */ + + // FIXME: Should we modify created_at/updated_at? + $user->save(); + + // Create user record in LDAP, then check if the account is created in IMAP + $chain = [ + new \App\Jobs\User\VerifyJob($user->id), + ]; + + \App\Jobs\User\CreateJob::withChain($chain)->dispatch($user->id); + } + /** * Handle the "retrieving" event. * diff --git a/src/app/User.php b/src/app/User.php --- a/src/app/User.php +++ b/src/app/User.php @@ -729,6 +729,9 @@ throw new \Exception("Invalid user status: {$status}"); } + // FIXME: Should we remove STATUS_LDAP_READY/STATUS_IMAP_READY + // when setting STATUS_DELETED? + $this->attributes['status'] = $new_status; } }