diff --git a/src/app/Console/Command.php b/src/app/Console/Command.php --- a/src/app/Console/Command.php +++ b/src/app/Console/Command.php @@ -27,10 +27,18 @@ */ public function getObject($objectClass, $objectIdOrTitle, $objectTitle) { - $object = $objectClass::find($objectIdOrTitle); + if ($this->option('with-deleted')) { + $object = $objectClass::withTrashed()->find($objectIdOrTitle); + } else { + $object = $objectClass::find($objectIdOrTitle); + } if (!$object && !empty($objectTitle)) { - $object = $objectClass::where($objectTitle, $objectIdOrTitle)->first(); + if ($this->option('with-deleted')) { + $object = $objectClass::withTrashed()->where($objectTitle, $objectIdOrTitle)->first(); + } else { + $object = $objectClass::where($objectTitle, $objectIdOrTitle)->first(); + } } return $object; diff --git a/src/app/Console/Commands/DBPing.php b/src/app/Console/Commands/DB/PingCommand.php rename from src/app/Console/Commands/DBPing.php rename to src/app/Console/Commands/DB/PingCommand.php --- a/src/app/Console/Commands/DBPing.php +++ b/src/app/Console/Commands/DB/PingCommand.php @@ -1,11 +1,11 @@ info( + sprintf( + "%s %02d %d %d", + $transaction->{'year'}, + $transaction->{'month'}, + $transaction->{'amount'} + ) + ); + } + } +} diff --git a/src/app/Console/Commands/Data/Export/VATCommand.php b/src/app/Console/Commands/Data/Export/VATCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/Data/Export/VATCommand.php @@ -0,0 +1,59 @@ +info( + sprintf( + "%s %02d %d %d", + $transaction->{'year'}, + $transaction->{'month'}, + $transaction->{'amount'}, + $transaction->{'vat'} + ) + ); + } + } +} diff --git a/src/app/Console/Commands/Data/ImportCommand.php b/src/app/Console/Commands/Data/ExportCommand.php copy from src/app/Console/Commands/Data/ImportCommand.php copy to src/app/Console/Commands/Data/ExportCommand.php --- a/src/app/Console/Commands/Data/ImportCommand.php +++ b/src/app/Console/Commands/Data/ExportCommand.php @@ -4,31 +4,21 @@ use Illuminate\Console\Command; -class ImportCommand extends Command +class ExportCommand extends Command { /** * The name and signature of the console command. * * @var string */ - protected $signature = 'data:import'; + protected $signature = 'data:export'; /** * The console command description. * * @var string */ - protected $description = 'Command description'; - - /** - * Create a new command instance. - * - * @return void - */ - public function __construct() - { - parent::__construct(); - } + protected $description = 'Export data to external sources'; /** * Execute the console command. @@ -38,9 +28,8 @@ public function handle() { $commands = [ - Import\CountriesCommand::class, - Import\IP4NetsCommand::class, - Import\IP6NetsCommand::class + Export\BalanceCommand::class, + Export\VATCommand::class ]; foreach ($commands as $command) { @@ -48,7 +37,5 @@ $execution->output = $this->output; $execution->handle(); } - - return 0; } } diff --git a/src/app/Console/Commands/Data/ImportCommand.php b/src/app/Console/Commands/Data/ImportCommand.php --- a/src/app/Console/Commands/Data/ImportCommand.php +++ b/src/app/Console/Commands/Data/ImportCommand.php @@ -18,7 +18,7 @@ * * @var string */ - protected $description = 'Command description'; + protected $description = 'Import data from external sources'; /** * Create a new command instance. @@ -48,7 +48,5 @@ $execution->output = $this->output; $execution->handle(); } - - return 0; } } diff --git a/src/app/Console/Commands/Discount/CreateCommand.php b/src/app/Console/Commands/Discount/CreateCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/Discount/CreateCommand.php @@ -0,0 +1,12 @@ +orderBy('discount')->get()->each( - function ($discount) { - $name = $discount->description; - - if ($discount->code) { - $name .= " [{$discount->code}]"; - } - - $this->info( - sprintf( - "%s %3d%% %s", - $discount->id, - $discount->discount, - $name - ) - ); - } - ); - } -} diff --git a/src/app/Console/Commands/DiscountsCommand.php b/src/app/Console/Commands/DiscountsCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/DiscountsCommand.php @@ -0,0 +1,12 @@ +argument('domain'))->first(); + $domain = $this->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/Domain/ListDomains.php rename from src/app/Console/Commands/DomainList.php rename to src/app/Console/Commands/Domain/ListDomains.php --- a/src/app/Console/Commands/DomainList.php +++ b/src/app/Console/Commands/Domain/ListDomains.php @@ -1,11 +1,11 @@ argument('domain'))->first(); + $domain = $this->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/SetWallet.php rename from src/app/Console/Commands/DomainSetWallet.php rename to src/app/Console/Commands/Domain/SetWallet.php --- a/src/app/Console/Commands/DomainSetWallet.php +++ b/src/app/Console/Commands/Domain/SetWallet.php @@ -1,15 +1,15 @@ argument('domain'))->first(); + $domain = $this->getDomain($this->argument('domain')); if (!$domain) { $this->error("Domain not found."); diff --git a/src/app/Console/Commands/DomainStatus.php b/src/app/Console/Commands/Domain/Status.php rename from src/app/Console/Commands/DomainStatus.php rename to src/app/Console/Commands/Domain/Status.php --- a/src/app/Console/Commands/DomainStatus.php +++ b/src/app/Console/Commands/Domain/Status.php @@ -1,11 +1,11 @@ argument('domain'))->first(); + $domain = $this->getDomain($this->argument('domain')); if (!$domain) { + $this->error("Domain not found."); return 1; } @@ -48,15 +39,15 @@ 'active' => Domain::STATUS_ACTIVE, 'suspended' => Domain::STATUS_SUSPENDED, 'deleted' => Domain::STATUS_DELETED, - 'ldapReady' => Domain::STATUS_LDAP_READY, - 'verified' => Domain::STATUS_VERIFIED, 'confirmed' => Domain::STATUS_CONFIRMED, + 'verified' => Domain::STATUS_VERIFIED, + 'ldapReady' => Domain::STATUS_LDAP_READY, ]; foreach ($statuses as $text => $bit) { $func = 'is' . \ucfirst($text); - $this->info(sprintf("%d %s: %s", $bit, $text, $domain->$func())); + $this->info(sprintf("%d %s: %s", $bit, $text, $domain->$func() ? "yes" : "no")); } $this->info("In total: {$domain->status}"); diff --git a/src/app/Console/Commands/DomainSuspend.php b/src/app/Console/Commands/Domain/Suspend.php rename from src/app/Console/Commands/DomainSuspend.php rename to src/app/Console/Commands/Domain/Suspend.php --- a/src/app/Console/Commands/DomainSuspend.php +++ b/src/app/Console/Commands/Domain/Suspend.php @@ -1,11 +1,11 @@ argument('domain'))->first(); + $domain = $this->getDomain($this->argument('domain')); if (!$domain) { + $this->error("Domain not found."); return 1; } - $this->info("Found domain: {$domain->id}"); - $domain->suspend(); } } diff --git a/src/app/Console/Commands/DomainUnsuspend.php b/src/app/Console/Commands/Domain/Unsuspend.php rename from src/app/Console/Commands/DomainUnsuspend.php rename to src/app/Console/Commands/Domain/Unsuspend.php --- a/src/app/Console/Commands/DomainUnsuspend.php +++ b/src/app/Console/Commands/Domain/Unsuspend.php @@ -1,11 +1,11 @@ argument('domain'))->first(); + $domain = $this->getDomain($this->argument('domain')); if (!$domain) { + $this->error("Domain not found."); return 1; } - $this->info("Found domain {$domain->id}"); - $domain->unsuspend(); } } diff --git a/src/app/Console/Commands/Domain/UsersCommand.php b/src/app/Console/Commands/Domain/UsersCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/Domain/UsersCommand.php @@ -0,0 +1,13 @@ +argument('domain'))->first(); - - if (!$domain) { - return 1; - } - - if ($domain->isPublic()) { - $this->error("This domain is a public registration domain."); - return 1; - } - - // TODO: actually implement listing users - $wallet = $domain->wallet(); - - if (!$wallet) { - $this->error("This domain isn't billed to a wallet."); - return 1; - } - - $mailboxSKU = \App\Sku::where('title', 'mailbox')->first(); - - if (!$mailboxSKU) { - $this->error("No mailbox SKU available."); - } - - $entitlements = $wallet->entitlements() - ->where('entitleable_type', \App\User::class) - ->where('sku_id', $mailboxSKU->id)->get(); - - $users = []; - - foreach ($entitlements as $entitlement) { - $users[] = $entitlement->entitleable; - } - - usort($users, function ($a, $b) { - return $a->email > $b->email; - }); - - foreach ($users as $user) { - $this->info($user->email); - } - } -} diff --git a/src/app/Console/Commands/DomainsCommand.php b/src/app/Console/Commands/DomainsCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/DomainsCommand.php @@ -0,0 +1,12 @@ +argument('domain'))->first(); + $domain = $this->getDomain($this->argument('domain')); if (!$domain) { + $this->error("Domain not found"); return 1; } diff --git a/src/app/Console/Commands/Job/DomainUpdate.php b/src/app/Console/Commands/Job/DomainUpdate.php --- a/src/app/Console/Commands/Job/DomainUpdate.php +++ b/src/app/Console/Commands/Job/DomainUpdate.php @@ -2,8 +2,7 @@ namespace App\Console\Commands\Job; -use App\Domain; -use Illuminate\Console\Command; +use App\Console\Command; class DomainUpdate extends Command { @@ -28,9 +27,10 @@ */ public function handle() { - $domain = Domain::where('namespace', $this->argument('domain'))->first(); + $domain = $this->getDomain($this->argument('domain')); if (!$domain) { + $this->error("Domain not found"); return 1; } diff --git a/src/app/Console/Commands/Job/UserCreate.php b/src/app/Console/Commands/Job/UserCreate.php --- a/src/app/Console/Commands/Job/UserCreate.php +++ b/src/app/Console/Commands/Job/UserCreate.php @@ -2,8 +2,7 @@ namespace App\Console\Commands\Job; -use App\User; -use Illuminate\Console\Command; +use App\Console\Command; class UserCreate extends Command { @@ -28,9 +27,10 @@ */ public function handle() { - $user = User::where('email', $this->argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("User not found"); return 1; } diff --git a/src/app/Console/Commands/Job/UserUpdate.php b/src/app/Console/Commands/Job/UserUpdate.php --- a/src/app/Console/Commands/Job/UserUpdate.php +++ b/src/app/Console/Commands/Job/UserUpdate.php @@ -2,8 +2,7 @@ namespace App\Console\Commands\Job; -use App\User; -use Illuminate\Console\Command; +use App\Console\Command; class UserUpdate extends Command { @@ -28,9 +27,10 @@ */ public function handle() { - $user = User::where('email', $this->argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("User not found"); return 1; } diff --git a/src/app/Console/Commands/Job/WalletCheck.php b/src/app/Console/Commands/Job/WalletCheck.php --- a/src/app/Console/Commands/Job/WalletCheck.php +++ b/src/app/Console/Commands/Job/WalletCheck.php @@ -2,8 +2,8 @@ namespace App\Console\Commands\Job; +use App\Console\Command; use App\Wallet; -use Illuminate\Console\Command; class WalletCheck extends Command { @@ -31,6 +31,7 @@ $wallet = Wallet::find($this->argument('wallet')); if (!$wallet) { + $this->error("Wallet not found"); return 1; } diff --git a/src/app/Console/Commands/MollieInfo.php b/src/app/Console/Commands/MollieInfo.php --- a/src/app/Console/Commands/MollieInfo.php +++ b/src/app/Console/Commands/MollieInfo.php @@ -2,8 +2,7 @@ namespace App\Console\Commands; -use App\User; -use Illuminate\Console\Command; +use App\Console\Command; class MollieInfo extends Command { @@ -29,14 +28,13 @@ public function handle() { if ($this->argument('user')) { - $user = User::where('email', $this->argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("Wallet not found"); return 1; } - $this->info("Found user: {$user->id}"); - $wallet = $user->wallets->first(); $provider = new \App\Providers\Payment\Mollie(); diff --git a/src/app/Console/Commands/Package/ReadCommand.php b/src/app/Console/Commands/Package/ReadCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/Package/ReadCommand.php @@ -0,0 +1,12 @@ +option('package')) { + $packages = Package::where('title', $this->option('package'))->get(); + } else { + $packages = Package::all(); + } + + foreach ($packages as $package) { + $this->info("{$package->title}"); + + foreach ($package->skus as $sku) { + $this->info(sprintf(" %s (%d)", $sku->title, $sku->pivot->qty)); + } + } + } +} diff --git a/src/app/Console/Commands/PackageSkus.php b/src/app/Console/Commands/PackageSkus.php deleted file mode 100644 --- a/src/app/Console/Commands/PackageSkus.php +++ /dev/null @@ -1,51 +0,0 @@ -info(sprintf("Package: %s", $package->title)); - - foreach ($package->skus as $sku) { - $this->info(sprintf(" SKU: %s (%d)", $sku->title, $sku->pivot->qty)); - } - } - } -} diff --git a/src/app/Console/Commands/PackagesCommand.php b/src/app/Console/Commands/PackagesCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/PackagesCommand.php @@ -0,0 +1,12 @@ +properties = $this->getProperties(); + + $entitleable = call_user_func_array( + [$this->properties['entitleable_type'], 'find'], + [$this->properties['entitleable_id']] + ); + + if (!$entitleable) { + $this->error("No such {$this->properties['entitleable_type']}"); + return 1; + } + + if (!array_key_exists('entitleable_id', $this->properties)) { + $this->error("Specify --entitleable_id"); + } + + if (array_key_exists('sku_id', $this->properties)) { + $sku = \App\Sku::find($this->properties['sku_id']); + + if (!$sku) { + $this->error("No such SKU {$this->properties['sku_id']}"); + return 1; + } + + if ($this->properties['cost'] == null) { + $this->properties['cost'] = $sku->cost; + } + } + + if (array_key_exists('wallet_id', $this->properties)) { + $wallet = \App\Wallet::find($this->properties['wallet_id']); + + if (!$wallet) { + $this->error("No such wallet {$this->properties['wallet_id']}"); + return 1; + } + } + + parent::handle(); + } +} diff --git a/src/app/Console/Commands/Scalpel/Entitlement/ReadCommand.php b/src/app/Console/Commands/Scalpel/Entitlement/ReadCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/Scalpel/Entitlement/ReadCommand.php @@ -0,0 +1,13 @@ +argument('user')) { - $user = User::where('email', $this->argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("User not found"); return 1; } - $this->info("Found user: {$user->id}"); - $wallet = $user->wallets->first(); $provider = PaymentProvider::factory('stripe'); diff --git a/src/app/Console/Commands/Transaction/ReadCommand.php b/src/app/Console/Commands/Transaction/ReadCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/Transaction/ReadCommand.php @@ -0,0 +1,12 @@ +argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("User not found."); return 1; } diff --git a/src/app/Console/Commands/User/AliasesCommand.php b/src/app/Console/Commands/User/AliasesCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/User/AliasesCommand.php @@ -0,0 +1,13 @@ +argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("User not found."); return 1; } diff --git a/src/app/Console/Commands/UserDiscount.php b/src/app/Console/Commands/User/Discount.php rename from src/app/Console/Commands/UserDiscount.php rename to src/app/Console/Commands/User/Discount.php --- a/src/app/Console/Commands/UserDiscount.php +++ b/src/app/Console/Commands/User/Discount.php @@ -1,10 +1,10 @@ argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("User not found."); return 1; } - $this->info("Found user {$user->id}"); - if ($this->argument('discount') === '0') { $discount = null; } else { $discount = \App\Discount::find($this->argument('discount')); if (!$discount) { + $this->error("Discount not found."); return 1; } } diff --git a/src/app/Console/Commands/User/DomainsCommand.php b/src/app/Console/Commands/User/DomainsCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/User/DomainsCommand.php @@ -0,0 +1,13 @@ +where('email', $this->argument('user'))->first(); + $id = $this->argument('user'); + + if (is_numeric($id)) { + $user = \App\User::find($id); + } else { + $user = \App\User::withTrashed()->where('email', $id)->first(); + } if (!$user) { + $this->error("User not found."); return 1; } if (!$user->trashed()) { - $this->error('The user is not yet deleted'); + $this->error("The user is not yet deleted"); return 1; } diff --git a/src/app/Console/Commands/User/ReadCommand.php b/src/app/Console/Commands/User/ReadCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/User/ReadCommand.php @@ -0,0 +1,12 @@ +argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("User not found."); return 1; } @@ -55,7 +46,7 @@ foreach ($statuses as $text => $bit) { $func = 'is' . \ucfirst($text); - $this->info(sprintf("%d %s: %s", $bit, $text, $user->$func())); + $this->info(sprintf("%d %s: %s", $bit, $text, $user->$func() ? "yes" : "no")); } $this->info("In total: {$user->status}"); diff --git a/src/app/Console/Commands/UserSuspend.php b/src/app/Console/Commands/User/Suspend.php rename from src/app/Console/Commands/UserSuspend.php rename to src/app/Console/Commands/User/Suspend.php --- a/src/app/Console/Commands/UserSuspend.php +++ b/src/app/Console/Commands/User/Suspend.php @@ -1,11 +1,11 @@ argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("User not found."); return 1; } - $this->info("Found user: {$user->id}"); - $user->suspend(); } } diff --git a/src/app/Console/Commands/UserUnsuspend.php b/src/app/Console/Commands/User/Unsuspend.php rename from src/app/Console/Commands/UserUnsuspend.php rename to src/app/Console/Commands/User/Unsuspend.php --- a/src/app/Console/Commands/UserUnsuspend.php +++ b/src/app/Console/Commands/User/Unsuspend.php @@ -1,11 +1,11 @@ argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("User not found."); return 1; } - $this->info("Found user {$user->id}"); - $user->unsuspend(); } } diff --git a/src/app/Console/Commands/UserVerify.php b/src/app/Console/Commands/User/Verify.php rename from src/app/Console/Commands/UserVerify.php rename to src/app/Console/Commands/User/Verify.php --- a/src/app/Console/Commands/UserVerify.php +++ b/src/app/Console/Commands/User/Verify.php @@ -1,10 +1,10 @@ argument('user'))->first(); + $user = $this->getUser($this->argument('user')); if (!$user) { + $this->error("User not found."); return 1; } - $this->info("Found user: {$user->id}"); - $job = new \App\Jobs\User\VerifyJob($user->id); $job->handle(); } diff --git a/src/app/Console/Commands/User/WalletCommand.php b/src/app/Console/Commands/User/WalletCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/User/WalletCommand.php @@ -0,0 +1,13 @@ +argument('userid'))->first(); - - if (!$user) { - return 1; - } - - foreach ($user->domains() as $domain) { - $this->info("{$domain->namespace}"); - } - } -} diff --git a/src/app/Console/Commands/UserEntitlements.php b/src/app/Console/Commands/UserEntitlements.php deleted file mode 100644 --- a/src/app/Console/Commands/UserEntitlements.php +++ /dev/null @@ -1,65 +0,0 @@ -argument('userid'))->first(); - - if (!$user) { - return 1; - } - - $this->info("Found user: {$user->id}"); - - $skus_counted = []; - - foreach ($user->entitlements as $entitlement) { - if (!array_key_exists($entitlement->sku_id, $skus_counted)) { - $skus_counted[$entitlement->sku_id] = 1; - } else { - $skus_counted[$entitlement->sku_id] += 1; - } - } - - foreach ($skus_counted as $id => $qty) { - $sku = Sku::find($id); - $this->info("SKU: {$sku->title} ({$qty})"); - } - } -} diff --git a/src/app/Console/Commands/UserSetting/ReadCommand.php b/src/app/Console/Commands/UserSetting/ReadCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/UserSetting/ReadCommand.php @@ -0,0 +1,12 @@ +argument('user'))->first(); - - if (!$user) { - return 1; - } - - foreach ($user->wallets as $wallet) { - $this->info("{$wallet->id} {$wallet->description}"); - } - } -} diff --git a/src/app/Console/Commands/UsersCommand.php b/src/app/Console/Commands/UsersCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/UsersCommand.php @@ -0,0 +1,12 @@ +argument('wallet')); if (!$wallet) { + $this->error("Wallet not found"); return 1; } diff --git a/src/app/Console/Commands/WalletBalances.php b/src/app/Console/Commands/Wallet/Balances.php rename from src/app/Console/Commands/WalletBalances.php rename to src/app/Console/Commands/Wallet/Balances.php --- a/src/app/Console/Commands/WalletBalances.php +++ b/src/app/Console/Commands/Wallet/Balances.php @@ -1,10 +1,10 @@ owner) { + $this->error("Wallet not found (or account deleted)."); return 1; } diff --git a/src/app/Console/Commands/Wallet/ControllersCommand.php b/src/app/Console/Commands/Wallet/ControllersCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/Wallet/ControllersCommand.php @@ -0,0 +1,13 @@ +option('user')) { - $user = \App\User::where('email', $this->option('user')) - ->orWhere('id', $this->option('user'))->first(); + $user = $this->getUser($this->option('user')); if (!$user) { + $this->error("User not found"); return 1; } diff --git a/src/app/Console/Commands/WalletGetBalance.php b/src/app/Console/Commands/Wallet/GetBalance.php rename from src/app/Console/Commands/WalletGetBalance.php rename to src/app/Console/Commands/Wallet/GetBalance.php --- a/src/app/Console/Commands/WalletGetBalance.php +++ b/src/app/Console/Commands/Wallet/GetBalance.php @@ -1,10 +1,10 @@ argument('wallet')); if (!$wallet) { + $this->error("Wallet not found"); return 1; } diff --git a/src/app/Console/Commands/WalletGetDiscount.php b/src/app/Console/Commands/Wallet/GetDiscount.php rename from src/app/Console/Commands/WalletGetDiscount.php rename to src/app/Console/Commands/Wallet/GetDiscount.php --- a/src/app/Console/Commands/WalletGetDiscount.php +++ b/src/app/Console/Commands/Wallet/GetDiscount.php @@ -1,10 +1,10 @@ argument('wallet')); if (!$wallet) { + $this->error("Wallet not found"); return 1; } diff --git a/src/app/Console/Commands/WalletMandate.php b/src/app/Console/Commands/Wallet/Mandate.php rename from src/app/Console/Commands/WalletMandate.php rename to src/app/Console/Commands/Wallet/Mandate.php --- a/src/app/Console/Commands/WalletMandate.php +++ b/src/app/Console/Commands/Wallet/Mandate.php @@ -1,11 +1,11 @@ argument('wallet')); if (!$wallet) { + $this->error("Wallet not found"); return 1; } diff --git a/src/app/Console/Commands/Wallet/OwnerCommand.php b/src/app/Console/Commands/Wallet/OwnerCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/Wallet/OwnerCommand.php @@ -0,0 +1,13 @@ +argument('wallet')); if (!$wallet) { + $this->error("Wallet not found"); return 1; } diff --git a/src/app/Console/Commands/WalletSetDiscount.php b/src/app/Console/Commands/Wallet/SetDiscount.php rename from src/app/Console/Commands/WalletSetDiscount.php rename to src/app/Console/Commands/Wallet/SetDiscount.php --- a/src/app/Console/Commands/WalletSetDiscount.php +++ b/src/app/Console/Commands/Wallet/SetDiscount.php @@ -1,10 +1,10 @@ argument('wallet'))->first(); + $wallet = \App\Wallet::find($this->argument('wallet')); if (!$wallet) { + $this->error("Wallet not found"); return 1; } @@ -51,6 +42,7 @@ $discount = \App\Discount::find($this->argument('discount')); if (!$discount) { + $this->error("Discount not found"); return 1; } diff --git a/src/app/Console/Commands/WalletTransactions.php b/src/app/Console/Commands/Wallet/Transactions.php rename from src/app/Console/Commands/WalletTransactions.php rename to src/app/Console/Commands/Wallet/Transactions.php --- a/src/app/Console/Commands/WalletTransactions.php +++ b/src/app/Console/Commands/Wallet/Transactions.php @@ -1,10 +1,10 @@ argument('wallet'))->first(); + $wallet = \App\Wallet::find($this->argument('wallet')); if (!$wallet) { + $this->error("Wallet not found"); return 1; } diff --git a/src/app/Console/Commands/WalletUntil.php b/src/app/Console/Commands/Wallet/Until.php rename from src/app/Console/Commands/WalletUntil.php rename to src/app/Console/Commands/Wallet/Until.php --- a/src/app/Console/Commands/WalletUntil.php +++ b/src/app/Console/Commands/Wallet/Until.php @@ -1,10 +1,10 @@ argument('wallet')); if (!$wallet) { + $this->error("Wallet not found"); return 1; } diff --git a/src/app/Console/Commands/WalletDiscount.php b/src/app/Console/Commands/WalletDiscount.php deleted file mode 100644 --- a/src/app/Console/Commands/WalletDiscount.php +++ /dev/null @@ -1,62 +0,0 @@ -argument('wallet'))->first(); - - if (!$wallet) { - return 1; - } - - // FIXME: Using '0' for delete might be not that obvious - - if ($this->argument('discount') === '0') { - $wallet->discount()->dissociate(); - } else { - $discount = \App\Discount::find($this->argument('discount')); - - if (!$discount) { - return 1; - } - - $wallet->discount()->associate($discount); - } - - $wallet->save(); - } -} diff --git a/src/app/Console/Commands/WalletSetting/ReadCommand.php b/src/app/Console/Commands/WalletSetting/ReadCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/Commands/WalletSetting/ReadCommand.php @@ -0,0 +1,12 @@ +argument('domain'))->firstOrFail(); - - $this->info("Found domain: {$domain->id}"); - - $statuses = [ - 'active' => Domain::STATUS_ACTIVE, - 'suspended' => Domain::STATUS_SUSPENDED, - 'deleted' => Domain::STATUS_DELETED, - 'ldapReady' => Domain::STATUS_LDAP_READY, - 'verified' => Domain::STATUS_VERIFIED, - 'confirmed' => Domain::STATUS_CONFIRMED, - ]; - - // I'd prefer "-state" and "+state" syntax, but it's not possible - $delete = false; - if ($update = $this->option('del')) { - $delete = true; - } elseif ($update = $this->option('add')) { - // do nothing - } - - if (!empty($update)) { - $map = \array_change_key_case($statuses); - $update = \strtolower($update); - - if (isset($map[$update])) { - if ($delete && $domain->status & $map[$update]) { - $domain->status ^= $map[$update]; - $domain->save(); - } elseif (!$delete && !($domain->status & $map[$update])) { - $domain->status |= $map[$update]; - $domain->save(); - } - } - } - - $domain_state = []; - foreach (\array_keys($statuses) as $state) { - $func = 'is' . \ucfirst($state); - if ($domain->$func()) { - $domain_state[] = $state; - } - } - - $this->info("Status: " . \implode(',', $domain_state)); - } -} diff --git a/src/app/Console/Development/UserStatus.php b/src/app/Console/Development/UserStatus.php deleted file mode 100644 --- a/src/app/Console/Development/UserStatus.php +++ /dev/null @@ -1,86 +0,0 @@ -argument('userid'))->firstOrFail(); - - $this->info("Found user: {$user->id}"); - - $statuses = [ - 'active' => User::STATUS_ACTIVE, - 'suspended' => User::STATUS_SUSPENDED, - 'deleted' => User::STATUS_DELETED, - 'ldapReady' => User::STATUS_LDAP_READY, - 'imapReady' => User::STATUS_IMAP_READY, - ]; - - // I'd prefer "-state" and "+state" syntax, but it's not possible - $delete = false; - if ($update = $this->option('del')) { - $delete = true; - } elseif ($update = $this->option('add')) { - // do nothing - } - - if (!empty($update)) { - $map = \array_change_key_case($statuses); - $update = \strtolower($update); - - if (isset($map[$update])) { - if ($delete && $user->status & $map[$update]) { - $user->status ^= $map[$update]; - $user->save(); - } elseif (!$delete && !($user->status & $map[$update])) { - $user->status |= $map[$update]; - $user->save(); - } - } - } - - $user_state = []; - foreach (\array_keys($statuses) as $state) { - $func = 'is' . \ucfirst($state); - if ($user->$func()) { - $user_state[] = $state; - } - } - - $this->info("Status: " . \implode(',', $user_state)); - } -} diff --git a/src/app/Console/ObjectCreateCommand.php b/src/app/Console/ObjectCreateCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/ObjectCreateCommand.php @@ -0,0 +1,86 @@ +description = "Create a {$this->objectName}"; + $this->signature = sprintf( + "%s%s:create", + $this->commandPrefix ? $this->commandPrefix . ":" : "", + $this->objectName + ); + + $class = new $this->objectClass(); + + foreach ($class->getFillable() as $fillable) { + $this->signature .= " {--{$fillable}=}"; + } + + parent::__construct(); + } + + public function getProperties() + { + if (!empty($this->properties)) { + return $this->properties; + } + + $class = new $this->objectClass(); + + $this->properties = []; + + foreach ($class->getFillable() as $fillable) { + $this->properties[$fillable] = $this->option($fillable); + } + + return $this->properties; + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + $class = new $this->objectClass(); + + $object = $this->objectClass::create($this->properties); + + $objectKey = $object->{$class->getKeyName()}; + + $savedObject = $this->objectClass::find($objectKey); + + if ($savedObject) { + $this->info($savedObject->{$class->getKeyName()}); + } else { + $this->error("Object could not be created."); + } + + return $savedObject; + } +} diff --git a/src/app/Console/ObjectListCommand.php b/src/app/Console/ObjectListCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/ObjectListCommand.php @@ -0,0 +1,75 @@ +description = "List {$this->objectName}s"; + + $classes = class_uses_recursive($this->objectClass); + + if (in_array(SoftDeletes::class, $classes)) { + $this->signature = sprintf( + "%s%ss {--with-deleted : Include deleted %ss}", + $this->commandPrefix ? $this->commandPrefix . ":" : "", + $this->objectName, + $this->objectName + ); + } else { + $this->signature = "{$this->objectName}s"; + } + + $this->signature .= " {--attr=* : Attributes other than the primary unique key to include}"; + + parent::__construct(); + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + $classes = class_uses_recursive($this->objectClass); + + if (in_array(SoftDeletes::class, $classes) && $this->option('with-deleted')) { + $objects = $this->objectClass::withTrashed(); + } else { + $objects = new $this->objectClass(); + } + + $objects->each( + function ($object) { + if ($object->deleted_at) { + $this->info("{$this->toString($object)} (deleted at {$object->deleted_at}"); + } else { + $this->info("{$this->toString($object)}"); + } + } + ); + } +} diff --git a/src/app/Console/ObjectReadCommand.php b/src/app/Console/ObjectReadCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/ObjectReadCommand.php @@ -0,0 +1,58 @@ +description = "Read a {$this->objectName}"; + $this->signature = sprintf( + "%s%s:read {%s}", + $this->commandPrefix ? $this->commandPrefix . ":" : "", + $this->objectName, + $this->objectName + ); + + $this->signature .= " {--attr=* : Attributes other than the primary unique key to include}"; + + parent::__construct(); + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + $argument = $this->argument($this->objectName); + + $object = $this->getObject($this->objectClass, $argument, $this->objectTitle); + + if (!$object) { + return 1; + } + + $this->info($this->toString($object)); + } +} diff --git a/src/app/Console/ObjectRelationListCommand.php b/src/app/Console/ObjectRelationListCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/ObjectRelationListCommand.php @@ -0,0 +1,125 @@ +description = "List {$this->objectRelation} for a {$this->objectName}"; + $this->signature = sprintf( + "%s%s:%s {%s}", + $this->commandPrefix ? $this->commandPrefix . ":" : "", + $this->objectName, + $this->objectRelation, + $this->objectName + ); + + $this->signature .= " {--attr=* : Attributes other than the primary unique key to include}"; + + parent::__construct(); + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + $argument = $this->argument($this->objectName); + + $object = $this->getObject( + $this->objectClass, + $argument, + $this->objectTitle + ); + + if (!$object) { + $this->error("No such {$this->objectName} {$argument}"); + return 1; + } + + if (method_exists($object, $this->objectRelation)) { + $result = call_user_func([$object, $this->objectRelation]); + } elseif (property_exists($object, $this->objectRelation)) { + $result = $object->{"{$this->objectRelation}"}; + } else { + $this->error("No such relation {$this->objectRelation}"); + return 1; + } + + if ($result instanceof \Illuminate\Database\Eloquent\Collection) { + $result->each( + function ($entry) { + $this->info($this->toString($entry)); + } + ); + } elseif ($result instanceof \Illuminate\Database\Eloquent\Relations\Relation) { + $result->each( + function ($entry) { + $this->info($this->toString($entry)); + } + ); + } elseif (is_array($result)) { + foreach ($result as $entry) { + $this->info($this->toString($entry)); + } + } else { + $this->info($this->toString($result)); + } + } +} diff --git a/src/app/Console/ObjectUpdateCommand.php b/src/app/Console/ObjectUpdateCommand.php new file mode 100644 --- /dev/null +++ b/src/app/Console/ObjectUpdateCommand.php @@ -0,0 +1,106 @@ +description = "Update a {$this->objectName}"; + $this->signature = sprintf( + "%s%s:update {%s}", + $this->commandPrefix ? $this->commandPrefix . ":" : "", + $this->objectName, + $this->objectName + ); + + $class = new $this->objectClass(); + + foreach (Schema::getColumnListing($class->getTable()) as $column) { + if ($column == "id") { + continue; + } + + $this->signature .= " {--{$column}=}"; + } + + $this->signature .= sprintf( + " {--with-deleted : Include deleted %ss}", + $this->objectName + ); + + parent::__construct(); + } + + public function getProperties() + { + if (!empty($this->properties)) { + return $this->properties; + } + + $class = new $this->objectClass(); + + $this->properties = []; + + foreach (Schema::getColumnListing($class->getTable()) as $column) { + if ($column == "id") { + continue; + } + + if (($value = $this->option($column)) !== null) { + $this->properties[$column] = $value; + } + } + + return $this->properties; + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + $argument = $this->argument($this->objectName); + + $object = $this->getObject($this->objectClass, $argument, $this->objectTitle); + + if (!$object) { + return 1; + } + + foreach ($this->getProperties() as $property => $value) { + if ($property == "deleted_at" && $value == "null") { + $value = null; + } + + $object->{$property} = $value; + } + + $object->save(['timestamps' => false]); + } +} diff --git a/src/app/Domain.php b/src/app/Domain.php --- a/src/app/Domain.php +++ b/src/app/Domain.php @@ -96,8 +96,75 @@ return $this; } + /** + * Ownership verification by checking for a TXT (or CNAME) record + * in the domain's DNS (that matches the verification hash). + * + * @return bool True if verification was successful, false otherwise + * @throws \Exception Throws exception on DNS or DB errors + */ + public function confirm(): bool + { + if ($this->isConfirmed()) { + return true; + } + + $hash = $this->hash(self::HASH_TEXT); + $confirmed = false; + + // Get DNS records and find a matching TXT entry + $records = \dns_get_record($this->namespace, DNS_TXT); + + if ($records === false) { + throw new \Exception("Failed to get DNS record for {$this->namespace}"); + } + + foreach ($records as $record) { + if ($record['txt'] === $hash) { + $confirmed = true; + break; + } + } + + // Get DNS records and find a matching CNAME entry + // Note: some servers resolve every non-existing name + // so we need to define left and right side of the CNAME record + // i.e.: kolab-verify IN CNAME .domain.tld. + if (!$confirmed) { + $cname = $this->hash(self::HASH_CODE) . '.' . $this->namespace; + $records = \dns_get_record('kolab-verify.' . $this->namespace, DNS_CNAME); + + if ($records === false) { + throw new \Exception("Failed to get DNS record for {$this->namespace}"); + } + + foreach ($records as $records) { + if ($records['target'] === $cname) { + $confirmed = true; + break; + } + } + } + + if ($confirmed) { + $this->status |= Domain::STATUS_CONFIRMED; + $this->save(); + } + + return $confirmed; + } + + /** + * Return the entitlement for this domain. + * + * @return \App\Entitlement|null + */ public function entitlement() { + if ($this->isPublic()) { + return null; + } + return $this->morphOne('App\Entitlement', 'entitleable'); } @@ -111,6 +178,26 @@ return self::whereRaw($where)->get(['namespace'])->pluck('namespace')->toArray(); } + /** + * Generate a verification hash for this domain + * + * @param int $mod One of: HASH_CNAME, HASH_CODE (Default), HASH_TEXT + * + * @return string Verification hash + */ + public function hash($mod = null): string + { + $cname = 'kolab-verify'; + + if ($mod === self::HASH_CNAME) { + return $cname; + } + + $hash = \md5('hkccp-verify-' . $this->namespace); + + return $mod === self::HASH_TEXT ? "$cname=$hash" : $hash; + } + /** * Returns whether this domain is active. * @@ -278,84 +365,6 @@ $this->attributes['status'] = $new_status; } - /** - * Ownership verification by checking for a TXT (or CNAME) record - * in the domain's DNS (that matches the verification hash). - * - * @return bool True if verification was successful, false otherwise - * @throws \Exception Throws exception on DNS or DB errors - */ - public function confirm(): bool - { - if ($this->isConfirmed()) { - return true; - } - - $hash = $this->hash(self::HASH_TEXT); - $confirmed = false; - - // Get DNS records and find a matching TXT entry - $records = \dns_get_record($this->namespace, DNS_TXT); - - if ($records === false) { - throw new \Exception("Failed to get DNS record for {$this->namespace}"); - } - - foreach ($records as $record) { - if ($record['txt'] === $hash) { - $confirmed = true; - break; - } - } - - // Get DNS records and find a matching CNAME entry - // Note: some servers resolve every non-existing name - // so we need to define left and right side of the CNAME record - // i.e.: kolab-verify IN CNAME .domain.tld. - if (!$confirmed) { - $cname = $this->hash(self::HASH_CODE) . '.' . $this->namespace; - $records = \dns_get_record('kolab-verify.' . $this->namespace, DNS_CNAME); - - if ($records === false) { - throw new \Exception("Failed to get DNS record for {$this->namespace}"); - } - - foreach ($records as $records) { - if ($records['target'] === $cname) { - $confirmed = true; - break; - } - } - } - - if ($confirmed) { - $this->status |= Domain::STATUS_CONFIRMED; - $this->save(); - } - - return $confirmed; - } - - /** - * Generate a verification hash for this domain - * - * @param int $mod One of: HASH_CNAME, HASH_CODE (Default), HASH_TEXT - * - * @return string Verification hash - */ - public function hash($mod = null): string - { - $cname = 'kolab-verify'; - - if ($mod === self::HASH_CNAME) { - return $cname; - } - - $hash = \md5('hkccp-verify-' . $this->namespace); - - return $mod === self::HASH_TEXT ? "$cname=$hash" : $hash; - } - /** * Suspend this domain. * @@ -400,6 +409,49 @@ $this->save(); } + /** + * List user accounts for this domain. + * + * @return \App\User[] A list of users. + */ + public function users() + { + if ($this->isPublic()) { + $this->error("This domain is a public registration domain."); + return 1; + } + + // TODO: actually implement listing users + $wallet = $this->wallet(); + + if (!$wallet) { + $this->error("This domain isn't billed to a wallet."); + return 1; + } + + $mailboxSKU = \App\Sku::where('title', 'mailbox')->first(); + + if (!$mailboxSKU) { + $this->error("No mailbox SKU available."); + } + + $entitlements = $wallet->entitlements() + ->where('entitleable_type', \App\User::class) + ->where('sku_id', $mailboxSKU->id)->get(); + + $users = []; + + foreach ($entitlements as $entitlement) { + $users[] = $entitlement->entitleable; + } + + usort($users, function ($a, $b) { + return $a->email > $b->email; + }); + + return $users; + } + /** * Verify if a domain exists in DNS * diff --git a/src/app/User.php b/src/app/User.php --- a/src/app/User.php +++ b/src/app/User.php @@ -54,10 +54,8 @@ * @var array */ protected $fillable = [ - 'id', 'email', 'password', - 'password_ldap', 'status' ]; diff --git a/src/database/seeds/local/UserSeeder.php b/src/database/seeds/local/UserSeeder.php --- a/src/database/seeds/local/UserSeeder.php +++ b/src/database/seeds/local/UserSeeder.php @@ -108,7 +108,7 @@ $ned->assignSku(\App\Sku::where('title', 'activesync')->first(), 1); - // Ned is a controller on Jack's wallet + // Ned is a controller on John's wallet $john->wallets()->first()->addController($ned); // Ned is also our 2FA test user diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/Domain/AddTest.php rename from src/tests/Feature/Console/UserDiscountTest.php rename to src/tests/Feature/Console/Domain/AddTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/Domain/AddTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/Domain/DeleteTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/Domain/DeleteTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/Domain/DeleteTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/Domain/ListDomainsTest.php b/src/tests/Feature/Console/Domain/ListDomainsTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Domain/ListDomainsTest.php @@ -0,0 +1,19 @@ +artisan('domain:list') + ->assertExitCode(0); + + $this->markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/Domain/ListUsersTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/Domain/ListUsersTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/Domain/ListUsersTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/Domain/SetStatusTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/Domain/SetStatusTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/Domain/SetStatusTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/Domain/SetWalletTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/Domain/SetWalletTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/Domain/SetWalletTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); 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,19 @@ +artisan('domain:status kolab.org') + ->assertExitCode(0); + + $this->markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/Domain/SuspendTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/Domain/SuspendTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/Domain/SuspendTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/Domain/UnsuspendTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/Domain/UnsuspendTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/Domain/UnsuspendTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/User/AddAliasTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/User/AddAliasTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/User/AddAliasTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/WalletDiscountTest.php b/src/tests/Feature/Console/User/DeleteTest.php rename from src/tests/Feature/Console/WalletDiscountTest.php rename to src/tests/Feature/Console/User/DeleteTest.php --- a/src/tests/Feature/Console/WalletDiscountTest.php +++ b/src/tests/Feature/Console/User/DeleteTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/User/DiscountTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/User/DiscountTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/User/DiscountTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/UserDomainsTest.php b/src/tests/Feature/Console/User/DomainsTest.php rename from src/tests/Feature/Console/UserDomainsTest.php rename to src/tests/Feature/Console/User/DomainsTest.php --- a/src/tests/Feature/Console/UserDomainsTest.php +++ b/src/tests/Feature/Console/User/DomainsTest.php @@ -1,11 +1,14 @@ artisan('user:domains john@kolab.org') diff --git a/src/tests/Feature/Console/UserEntitlementsTest.php b/src/tests/Feature/Console/User/EntitlementsTest.php rename from src/tests/Feature/Console/UserEntitlementsTest.php rename to src/tests/Feature/Console/User/EntitlementsTest.php --- a/src/tests/Feature/Console/UserEntitlementsTest.php +++ b/src/tests/Feature/Console/User/EntitlementsTest.php @@ -1,11 +1,14 @@ artisan('user:entitlements john@kolab.org') diff --git a/src/tests/Feature/Console/UserForceDeleteTest.php b/src/tests/Feature/Console/User/ForceDeleteTest.php rename from src/tests/Feature/Console/UserForceDeleteTest.php rename to src/tests/Feature/Console/User/ForceDeleteTest.php --- a/src/tests/Feature/Console/UserForceDeleteTest.php +++ b/src/tests/Feature/Console/User/ForceDeleteTest.php @@ -1,11 +1,11 @@ artisan('user:status john@kolab.org') + ->assertExitCode(0); + + $this->markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/User/SuspendTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/User/SuspendTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/User/SuspendTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/User/UnsuspendTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/User/UnsuspendTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/User/UnsuspendTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/User/VerifyTest.php copy from src/tests/Feature/Console/UserDiscountTest.php copy to src/tests/Feature/Console/User/VerifyTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/User/VerifyTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/UserWalletsTest.php b/src/tests/Feature/Console/User/WalletsTest.php rename from src/tests/Feature/Console/UserWalletsTest.php rename to src/tests/Feature/Console/User/WalletsTest.php --- a/src/tests/Feature/Console/UserWalletsTest.php +++ b/src/tests/Feature/Console/User/WalletsTest.php @@ -1,11 +1,14 @@ artisan('user:wallets john@kolab.org') diff --git a/src/tests/Feature/Console/Wallet/AddTransactionTest.php b/src/tests/Feature/Console/Wallet/AddTransactionTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Wallet/AddTransactionTest.php @@ -0,0 +1,16 @@ +markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/Wallet/BalancesTest.php b/src/tests/Feature/Console/Wallet/BalancesTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Wallet/BalancesTest.php @@ -0,0 +1,19 @@ +artisan('wallet:balances') + ->assertExitCode(0); + + $this->markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/WalletChargeTest.php b/src/tests/Feature/Console/Wallet/ChargeTest.php rename from src/tests/Feature/Console/WalletChargeTest.php rename to src/tests/Feature/Console/Wallet/ChargeTest.php --- a/src/tests/Feature/Console/WalletChargeTest.php +++ b/src/tests/Feature/Console/Wallet/ChargeTest.php @@ -1,11 +1,11 @@ artisan('wallet:expected') + ->assertExitCode(0); + + $this->markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/Wallet/GetBalanceTest.php b/src/tests/Feature/Console/Wallet/GetBalanceTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Wallet/GetBalanceTest.php @@ -0,0 +1,16 @@ +markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/Wallet/GetDiscountTest.php b/src/tests/Feature/Console/Wallet/GetDiscountTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Wallet/GetDiscountTest.php @@ -0,0 +1,16 @@ +markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/UserDiscountTest.php b/src/tests/Feature/Console/Wallet/MandateTest.php rename from src/tests/Feature/Console/UserDiscountTest.php rename to src/tests/Feature/Console/Wallet/MandateTest.php --- a/src/tests/Feature/Console/UserDiscountTest.php +++ b/src/tests/Feature/Console/Wallet/MandateTest.php @@ -1,11 +1,14 @@ markTestIncomplete(); diff --git a/src/tests/Feature/Console/Wallet/SetBalanceTest.php b/src/tests/Feature/Console/Wallet/SetBalanceTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Wallet/SetBalanceTest.php @@ -0,0 +1,16 @@ +markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/Wallet/SetDiscountTest.php b/src/tests/Feature/Console/Wallet/SetDiscountTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Wallet/SetDiscountTest.php @@ -0,0 +1,16 @@ +markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/Wallet/TransactionsTest.php b/src/tests/Feature/Console/Wallet/TransactionsTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Wallet/TransactionsTest.php @@ -0,0 +1,16 @@ +markTestIncomplete(); + } +} diff --git a/src/tests/Feature/Console/Wallet/UntilTest.php b/src/tests/Feature/Console/Wallet/UntilTest.php new file mode 100644 --- /dev/null +++ b/src/tests/Feature/Console/Wallet/UntilTest.php @@ -0,0 +1,48 @@ +deleteTestUser('wallet-charge@kolabnow.com'); + } + + /** + * {@inheritDoc} + */ + public function tearDown(): void + { + $this->deleteTestUser('wallet-charge@kolabnow.com'); + + parent::tearDown(); + } + + /** + * Test command run for a specified wallet + */ + public function testHandleSingle(): void + { + $user = $this->getTestUser('wallet-charge@kolabnow.com'); + $wallet = $user->wallets()->first(); + + // Non-existing wallet + $this->artisan('wallet:until unknown') + ->expectsOutput("Wallet not found") + ->assertExitCode(1); + + // TODO + $this->artisan('wallet:until ' . $wallet->id) + ->assertExitCode(0); + + $this->markTestIncomplete(); + } +}