diff --git a/src/app/Console/Commands/Domain/CreateCommand.php b/src/app/Console/Commands/Domain/CreateCommand.php --- a/src/app/Console/Commands/Domain/CreateCommand.php +++ b/src/app/Console/Commands/Domain/CreateCommand.php @@ -38,7 +38,7 @@ } if ($domain) { - if ($domain->deleted_at) { + if ($domain->trashed()) { // set the status back to new $domain->status = \App\Domain::STATUS_NEW; $domain->save(); diff --git a/src/app/Console/Commands/Domain/DeleteCommand.php b/src/app/Console/Commands/Domain/DeleteCommand.php --- a/src/app/Console/Commands/Domain/DeleteCommand.php +++ b/src/app/Console/Commands/Domain/DeleteCommand.php @@ -15,12 +15,10 @@ public function handle() { - $argument = $this->argument('domain'); - - $domain = $this->getDomain($argument); + $domain = $this->getDomain($this->argument('domain')); if (!$domain) { - $this->error("No such domain {$argument}"); + $this->error("Domain not found."); return 1; } diff --git a/src/app/Console/Commands/DomainRestore.php b/src/app/Console/Commands/Domain/RestoreCommand.php rename from src/app/Console/Commands/DomainRestore.php rename to src/app/Console/Commands/Domain/RestoreCommand.php --- a/src/app/Console/Commands/DomainRestore.php +++ b/src/app/Console/Commands/Domain/RestoreCommand.php @@ -1,11 +1,11 @@ getDomain($this->argument('domain')); if (!$domain) { + $this->error("Domain not found."); return 1; } diff --git a/src/app/Console/Commands/DomainSetWallet.php b/src/app/Console/Commands/Domain/SetWalletCommand.php rename from src/app/Console/Commands/DomainSetWallet.php rename to src/app/Console/Commands/Domain/SetWalletCommand.php --- a/src/app/Console/Commands/DomainSetWallet.php +++ b/src/app/Console/Commands/Domain/SetWalletCommand.php @@ -1,15 +1,14 @@ first(); + $sku = Sku::withObjectTenantContext($domain)->where('title', 'domain-hosting')->first(); Queue::fake(); // ignore LDAP for now (note: adding entitlements updates the domain) diff --git a/src/app/Console/Commands/DomainStatus.php b/src/app/Console/Commands/Domain/StatusCommand.php rename from src/app/Console/Commands/DomainStatus.php rename to src/app/Console/Commands/Domain/StatusCommand.php --- a/src/app/Console/Commands/DomainStatus.php +++ b/src/app/Console/Commands/Domain/StatusCommand.php @@ -1,11 +1,11 @@ getDomain($this->argument('domain')); if (!$domain) { + $this->error("Domain not found."); return 1; } diff --git a/src/app/Console/Commands/DomainSuspend.php b/src/app/Console/Commands/Domain/SuspendCommand.php rename from src/app/Console/Commands/DomainSuspend.php rename to src/app/Console/Commands/Domain/SuspendCommand.php --- a/src/app/Console/Commands/DomainSuspend.php +++ b/src/app/Console/Commands/Domain/SuspendCommand.php @@ -1,11 +1,10 @@ getDomain($this->argument('domain')); if (!$domain) { + $this->error("Domain not found."); return 1; } - $this->info("Found domain: {$domain->id}"); + $this->info("Found domain {$domain->id}"); $domain->suspend(); } diff --git a/src/app/Console/Commands/DomainUnsuspend.php b/src/app/Console/Commands/Domain/UnsuspendCommand.php rename from src/app/Console/Commands/DomainUnsuspend.php rename to src/app/Console/Commands/Domain/UnsuspendCommand.php --- a/src/app/Console/Commands/DomainUnsuspend.php +++ b/src/app/Console/Commands/Domain/UnsuspendCommand.php @@ -1,11 +1,10 @@ getDomain($this->argument('domain')); if (!$domain) { + $this->error("Domain not found."); return 1; } diff --git a/src/app/Console/Commands/DomainList.php b/src/app/Console/Commands/DomainList.php deleted file mode 100644 --- a/src/app/Console/Commands/DomainList.php +++ /dev/null @@ -1,49 +0,0 @@ -option('deleted')) { - $domains = Domain::withTrashed()->orderBy('namespace'); - } else { - $domains = Domain::orderBy('namespace'); - } - - $domains->withEnvTenantContext()->each( - function ($domain) { - $msg = $domain->namespace; - - if ($domain->deleted_at) { - $msg .= " (deleted at {$domain->deleted_at})"; - } - - $this->info($msg); - } - ); - } -} diff --git a/src/app/Console/Kernel.php b/src/app/Console/Kernel.php --- a/src/app/Console/Kernel.php +++ b/src/app/Console/Kernel.php @@ -48,7 +48,7 @@ { $this->load(__DIR__ . '/Commands'); - if (\app('env') != 'production') { + if (\app('env') == 'local') { $this->load(__DIR__ . '/Development'); } diff --git a/src/tests/Feature/Console/Domain/CreateTest.php b/src/tests/Feature/Console/Domain/CreateTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Domain/CreateTest.php @@ -0,0 +1,86 @@ +deleteTestDomain('domain-delete.com'); + } + + /** + * {@inheritDoc} + */ + public function tearDown(): void + { + $this->deleteTestDomain('domain-delete.com'); + + parent::tearDown(); + } + + /** + * Test the command + */ + public function testHandle(): void + { + Queue::fake(); + + // Existing domain + $ns = \config('app.domain'); + $code = \Artisan::call("domain:create $ns"); + $output = trim(\Artisan::output()); + $this->assertSame(1, $code); + $this->assertSame("Domain $ns already exists.", $output); + + // Existing domain (with --force param) + $code = \Artisan::call("domain:create $ns --force"); + $output = trim(\Artisan::output()); + $this->assertSame(1, $code); + $this->assertSame("Domain $ns not marked as deleted... examine more closely", $output); + + // A new domain + $code = \Artisan::call("domain:create domain-delete.com"); + $output = trim(\Artisan::output()); + $this->assertSame(0, $code); + + $domain = \App\Domain::where('namespace', 'domain-delete.com')->first(); + + $this->assertSame("Domain domain-delete.com created with ID {$domain->id}. " + . "Remember to assign it to a wallet with 'domain:set-wallet'", $output); + + $this->assertTrue($domain->isExternal()); + $this->assertNull($domain->wallet()); + $this->assertSame('domain-delete.com', $domain->namespace); + + $domain->status |= \App\Domain::STATUS_ACTIVE; + $domain->save(); + $domain->delete(); + + $domain->refresh(); + + $this->assertTrue($domain->trashed()); + $this->assertTrue($domain->isActive()); + + // Deleted domain + $code = \Artisan::call("domain:create domain-delete.com --force"); + $output = trim(\Artisan::output()); + $this->assertSame(0, $code); + $this->assertSame("Domain domain-delete.com with ID {$domain->id} revived. " + . "Remember to assign it to a wallet with 'domain:set-wallet'", $output); + + $domain->refresh(); + + $this->assertTrue($domain->isNew()); + $this->assertFalse($domain->isActive()); + $this->assertFalse($domain->trashed()); + } +} diff --git a/src/tests/Feature/Console/DomainRestoreTest.php b/src/tests/Feature/Console/Domain/DeleteTest.php rename from src/tests/Feature/Console/DomainRestoreTest.php rename to src/tests/Feature/Console/Domain/DeleteTest.php --- a/src/tests/Feature/Console/DomainRestoreTest.php +++ b/src/tests/Feature/Console/Domain/DeleteTest.php @@ -1,11 +1,11 @@ deleteTestUser('user@force-delete.com'); - $this->deleteTestDomain('force-delete.com'); + $this->deleteTestUser('user@domain-delete.com'); + $this->deleteTestDomain('domain-delete.com'); } /** @@ -23,8 +23,8 @@ */ public function tearDown(): void { - $this->deleteTestUser('user@force-delete.com'); - $this->deleteTestDomain('force-delete.com'); + $this->deleteTestUser('user@domain-delete.com'); + $this->deleteTestDomain('domain-delete.com'); parent::tearDown(); } @@ -37,14 +37,20 @@ Queue::fake(); // Non-existing domain - $code = \Artisan::call("domain:restore unknown.org"); + $code = \Artisan::call("domain:delete unknown.org"); $output = trim(\Artisan::output()); $this->assertSame(1, $code); $this->assertSame("Domain not found.", $output); + // Public domain + $code = \Artisan::call("domain:delete " . \config('app.domain')); + $output = trim(\Artisan::output()); + $this->assertSame(1, $code); + $this->assertSame("This domain is a public registration domain.", $output); + // Create a user account for delete - $user = $this->getTestUser('user@force-delete.com'); - $domain = $this->getTestDomain('force-delete.com', [ + $user = $this->getTestUser('user@domain-delete.com'); + $domain = $this->getTestDomain('domain-delete.com', [ 'status' => \App\Domain::STATUS_NEW, 'type' => \App\Domain::TYPE_HOSTED, ]); @@ -52,40 +58,20 @@ $package_domain = \App\Package::where('title', 'domain-hosting')->first(); $user->assignPackage($package_kolab); $domain->assignPackage($package_domain, $user); - $wallet = $user->wallets()->first(); - $entitlements = $wallet->entitlements->pluck('id')->all(); - - $this->assertCount(8, $entitlements); // Non-deleted domain - $code = \Artisan::call("domain:restore force-delete.com"); - $output = trim(\Artisan::output()); - $this->assertSame(1, $code); - $this->assertSame("The domain is not yet deleted.", $output); - - $domain->delete(); - - $this->assertTrue($domain->fresh()->trashed()); - - // Deleted domain - $code = \Artisan::call("domain:restore force-delete.com"); + $code = \Artisan::call("domain:delete domain-delete.com"); $output = trim(\Artisan::output()); $this->assertSame(0, $code); $this->assertSame("", $output); - $this->assertFalse($domain->fresh()->trashed()); - - $user->delete(); - $this->assertTrue($domain->fresh()->trashed()); - $this->assertTrue($user->fresh()->trashed()); + $this->assertFalse($user->fresh()->trashed()); - // Deleted domain, deleted owner - $code = \Artisan::call("domain:restore force-delete.com"); + // Deleted domain + $code = \Artisan::call("domain:delete domain-delete.com"); $output = trim(\Artisan::output()); $this->assertSame(1, $code); - $this->assertSame("The domain owner is deleted.", $output); - - $this->assertTrue($domain->fresh()->trashed()); + $this->assertSame("Domain not found.", $output); } } diff --git a/src/tests/Feature/Console/DomainRestoreTest.php b/src/tests/Feature/Console/Domain/RestoreTest.php rename from src/tests/Feature/Console/DomainRestoreTest.php rename to src/tests/Feature/Console/Domain/RestoreTest.php --- a/src/tests/Feature/Console/DomainRestoreTest.php +++ b/src/tests/Feature/Console/Domain/RestoreTest.php @@ -1,11 +1,11 @@ deleteTestDomain('domain-delete.com'); + } + + /** + * {@inheritDoc} + */ + public function tearDown(): void + { + $this->deleteTestDomain('domain-delete.com'); + + parent::tearDown(); + } + + /** + * Test the command + */ + public function testHandle(): void + { + Queue::fake(); + + // Non-existing domain + $code = \Artisan::call("domain:set-status unknown.org 1"); + $output = trim(\Artisan::output()); + $this->assertSame(1, $code); + $this->assertSame("Domain not found.", $output); + + $domain = $this->getTestDomain('domain-delete.com', [ + 'status' => \App\Domain::STATUS_NEW, + 'type' => \App\Domain::TYPE_HOSTED, + ]); + + $code = \Artisan::call("domain:set-status domain-delete.com " . \App\Domain::STATUS_LDAP_READY); + $output = trim(\Artisan::output()); + $this->assertSame(0, $code); + $this->assertSame((string) \App\Domain::STATUS_LDAP_READY, $output); + + $domain->refresh(); + + $this->assertSame(\App\Domain::STATUS_LDAP_READY, $domain->status); + } +} diff --git a/src/tests/Feature/Console/Domain/SetWalletTest.php b/src/tests/Feature/Console/Domain/SetWalletTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Domain/SetWalletTest.php @@ -0,0 +1,75 @@ +deleteTestDomain('domain-delete.com'); + } + + /** + * {@inheritDoc} + */ + public function tearDown(): void + { + $this->deleteTestDomain('domain-delete.com'); + + parent::tearDown(); + } + + /** + * Test the command + */ + public function testHandle(): void + { + Queue::fake(); + + // Non-existing domain + $code = \Artisan::call("domain:set-wallet unknown.org 12345"); + $output = trim(\Artisan::output()); + $this->assertSame(1, $code); + $this->assertSame("Domain not found.", $output); + + $domain = $this->getTestDomain('domain-delete.com', [ + 'status' => \App\Domain::STATUS_NEW, + 'type' => \App\Domain::TYPE_HOSTED, + ]); + + // Non-existing wallet + $code = \Artisan::call("domain:set-wallet domain-delete.com 12345"); + $output = trim(\Artisan::output()); + $this->assertSame(1, $code); + $this->assertSame("Wallet not found.", $output); + + $john = $this->getTestUser('john@kolab.org'); + $wallet = $john->wallets->first(); + + $code = \Artisan::call("domain:set-wallet domain-delete.com " . $wallet->id); + $output = trim(\Artisan::output()); + $this->assertSame(0, $code); + $this->assertSame('', $output); + + $domain->refresh(); + $sku = \App\Sku::withObjectTenantContext($domain) + ->where('title', 'domain-hosting')->first(); + + $this->assertSame($sku->id, $domain->entitlement->sku_id); + $this->assertSame($wallet->id, $domain->entitlement->wallet_id); + + // Already assigned to a wallet + $code = \Artisan::call("domain:set-wallet domain-delete.com " . $wallet->id); + $output = trim(\Artisan::output()); + $this->assertSame(1, $code); + $this->assertSame("Domain already assigned to a wallet: {$wallet->id}.", $output); + } +} diff --git a/src/tests/Feature/Console/Domain/StatusTest.php b/src/tests/Feature/Console/Domain/StatusTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Domain/StatusTest.php @@ -0,0 +1,30 @@ +assertSame(1, $code); + $this->assertSame("Domain not found.", $output); + + + // Existing domain + $code = \Artisan::call("domain:status kolab.org"); + $output = trim(\Artisan::output()); + $this->assertSame(0, $code); + + $this->assertTrue(strpos($output, "In total: 114") !== false); + + // TODO: More precise output testing + } +} diff --git a/src/tests/Feature/Console/Domain/SuspendTest.php b/src/tests/Feature/Console/Domain/SuspendTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Domain/SuspendTest.php @@ -0,0 +1,55 @@ +deleteTestDomain('domain-delete.com'); + } + + /** + * {@inheritDoc} + */ + public function tearDown(): void + { + $this->deleteTestDomain('domain-delete.com'); + + parent::tearDown(); + } + + /** + * Test the command + */ + public function testHandle(): void + { + Queue::fake(); + + // Non-existing domain + $code = \Artisan::call("domain:suspend unknown.org"); + $output = trim(\Artisan::output()); + $this->assertSame(1, $code); + $this->assertSame("Domain not found.", $output); + + $domain = $this->getTestDomain('domain-delete.com', [ + 'status' => \App\Domain::STATUS_NEW, + 'type' => \App\Domain::TYPE_HOSTED, + ]); + + $code = \Artisan::call("domain:suspend {$domain->namespace}"); + $output = trim(\Artisan::output()); + $this->assertSame(0, $code); + $this->assertSame("Found domain {$domain->id}", $output); + + $this->assertTrue($domain->fresh()->isSuspended()); + } +} diff --git a/src/tests/Feature/Console/Domain/UnsuspendTest.php b/src/tests/Feature/Console/Domain/UnsuspendTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Domain/UnsuspendTest.php @@ -0,0 +1,57 @@ +deleteTestDomain('domain-delete.com'); + } + + /** + * {@inheritDoc} + */ + public function tearDown(): void + { + $this->deleteTestDomain('domain-delete.com'); + + parent::tearDown(); + } + + /** + * Test the command + */ + public function testHandle(): void + { + Queue::fake(); + + // Non-existing domain + $code = \Artisan::call("domain:unsuspend unknown.org"); + $output = trim(\Artisan::output()); + $this->assertSame(1, $code); + $this->assertSame("Domain not found.", $output); + + $domain = $this->getTestDomain('domain-delete.com', [ + 'status' => \App\Domain::STATUS_NEW | \App\Domain::STATUS_SUSPENDED, + 'type' => \App\Domain::TYPE_HOSTED, + ]); + + $this->assertTrue($domain->isSuspended()); + + $code = \Artisan::call("domain:unsuspend {$domain->namespace}"); + $output = trim(\Artisan::output()); + $this->assertSame(0, $code); + $this->assertSame("Found domain {$domain->id}", $output); + + $this->assertFalse($domain->fresh()->isSuspended()); + } +} diff --git a/src/tests/Feature/Console/Domain/UsersTest.php b/src/tests/Feature/Console/Domain/UsersTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Domain/UsersTest.php @@ -0,0 +1,25 @@ +assertSame(0, $code); + + $john = \App\User::where('email', 'john@kolab.org')->first(); + + $this->assertTrue(strpos($output, (string) $john->id) !== false); + + // TODO: Test output format and additional attributes + } +} diff --git a/src/tests/Feature/Console/DomainsTest.php b/src/tests/Feature/Console/DomainsTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/DomainsTest.php @@ -0,0 +1,27 @@ +first(); + + // Existing domain + $code = \Artisan::call("domains"); + $output = trim(\Artisan::output()); + $this->assertSame(0, $code); + + $this->assertTrue(strpos($output, (string) $domain->id) !== false); + + // TODO: Test --deleted argument + // TODO: Test output format and other attributes + // TODO: Test tenant context + } +}