Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117962608
D949.1775501915.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
86 KB
Referenced Files
None
Subscribers
None
D949.1775501915.diff
View Options
diff --git a/bin/phpstan b/bin/phpstan
new file mode 100755
--- /dev/null
+++ b/bin/phpstan
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+cwd=$(dirname $0)
+
+pushd ${cwd}/../src/
+
+php -dmemory_limit=256M \
+ vendor/bin/phpstan \
+ analyse
+
+popd
diff --git a/bin/phpunit b/bin/phpunit
new file mode 100755
--- /dev/null
+++ b/bin/phpunit
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+cwd=$(dirname $0)
+
+pushd ${cwd}/../src/
+
+php -dzend_extension=xdebug.so \
+ vendor/bin/phpunit \
+ --exclude-group imap \
+ --stop-on-defect \
+ --stop-on-error \
+ --stop-on-failure \
+ --testsuite Unit,Feature
+
+popd
diff --git a/bin/quickstart.sh b/bin/quickstart.sh
--- a/bin/quickstart.sh
+++ b/bin/quickstart.sh
@@ -43,10 +43,10 @@
docker-compose up -d kolab mariadb redis
pushd ${base_dir}/src/
+cp .env.example .env
composer install
npm install
find bootstrap/cache/ -type f ! -name ".gitignore" -delete
-cp .env.example .env
./artisan key:generate
./artisan jwt:secret -f
./artisan clear-compiled
diff --git a/phpdoc.dist.xml b/phpdoc.dist.xml
--- a/phpdoc.dist.xml
+++ b/phpdoc.dist.xml
@@ -11,8 +11,10 @@
<files>
<directory>src/app/</directory>
<directory>src/database/</directory>
+ <ignore>src/database/factories/</ignore>
<ignore>src/database/migrations/</ignore>
<ignore>src/database/seeds/</ignore>
+ <ignore>src/resources/</ignore>
<directory>src/resources/</directory>
</files>
</phpdoc>
diff --git a/src/.env.example b/src/.env.example
--- a/src/.env.example
+++ b/src/.env.example
@@ -25,9 +25,8 @@
IMAP_URI=ssl://127.0.0.1:993
IMAP_ADMIN_LOGIN=cyrus-admin
IMAP_ADMIN_PASSWORD=Welcome2KolabSystems
-IMAP_VERIFY_PEER=true
-IMAP_VERIFY_NAME=true
-IMAP_CAFILE=null
+IMAP_VERIFY_HOST=false
+IMAP_VERIFY_PEER=false
LDAP_BASE_DN="dc=mgmt,dc=com"
LDAP_DOMAIN_BASE_DN="ou=Domains,dc=mgmt,dc=com"
diff --git a/src/app/Auth/LDAPUserProvider.php b/src/app/Auth/LDAPUserProvider.php
--- a/src/app/Auth/LDAPUserProvider.php
+++ b/src/app/Auth/LDAPUserProvider.php
@@ -3,32 +3,69 @@
namespace App\Auth;
use App\User;
-use Carbon\Carbon;
use Illuminate\Auth\EloquentUserProvider;
use Illuminate\Support\Facades\Hash;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
+/**
+ * A user provider that integrates an LDAP deployment.
+ */
class LDAPUserProvider extends EloquentUserProvider implements UserProvider
{
+ /**
+ * Retrieve the user by its ID.
+ *
+ * @param string $identifier The unique ID for the user to attempt to retrieve.
+ *
+ * @return User|null
+ */
public function retrieveById($identifier)
{
- return parent::retrieveById($identifier);
+ $authenticatable = parent::retrieveById($identifier);
+ return $authenticatable->user;
}
+ /**
+ * Retrieve the user by its credentials.
+ *
+ * Please note that this function also validates the password.
+ *
+ * @param array $credentials An array containing the email and password.
+ *
+ * @return User|null
+ */
public function retrieveByCredentials(array $credentials)
{
- $entries = User::where('email', '=', $credentials['email']);
+ $entries = User::where('email', '=', $credentials['email'])->get();
if ($entries->count() == 1) {
$user = $entries->select('id', 'email', 'password', 'password_ldap')->first();
+ if (!$this->validateCredentials($user, $credentials)) {
+ return null;
+ }
+
return $user;
+ } else {
+ if ($entries->count() > 1) {
+ \Log::warning("Multiple entries for {$credentials['email']}");
+ } else {
+ \Log::warning("No entries for {$credentials['email']}");
+ }
}
return null;
}
+ /**
+ * Validate the credentials for a user.
+ *
+ * @param Authenticatable $user The user.
+ * @param array $credentials The credentials.
+ *
+ * @return bool
+ */
public function validateCredentials(Authenticatable $user, array $credentials)
{
$authenticated = false;
@@ -46,6 +83,8 @@
if ($hash == $user->password_ldap) {
$authenticated = true;
}
+ } else {
+ \Log::error("Incomplete credentials for {$user->email}");
}
}
@@ -53,6 +92,8 @@
// TODO: Update password if necessary, examine whether writing to
// user->password is sufficient?
if ($authenticated) {
+ \Log::info("Successful authentication for {$user->email}");
+
$user->password = $credentials['password'];
$user->save();
} else {
diff --git a/src/app/Backends/IMAP.php b/src/app/Backends/IMAP.php
--- a/src/app/Backends/IMAP.php
+++ b/src/app/Backends/IMAP.php
@@ -89,8 +89,8 @@
'socket_options' => [
'ssl' => [
'verify_peer' => \config('imap.verify_peer'),
- 'verify_peer_name' => \config('imap.verify_name'),
- 'cafile' => \config('imap.cafile'),
+ 'verify_peer_name' => \config('imap.verify_peer'),
+ 'verify_host' => \config('imap.verify_host')
],
],
],
diff --git a/src/app/Backends/LDAP.php b/src/app/Backends/LDAP.php
--- a/src/app/Backends/LDAP.php
+++ b/src/app/Backends/LDAP.php
@@ -162,7 +162,7 @@
*
* @param \App\User $user The user account to create.
*
- * @return void
+ * @return bool|void
*/
public static function createUser(User $user)
{
@@ -213,12 +213,56 @@
//
}
+ public static function deleteDomain($domain)
+ {
+ $config = self::getConfig('admin');
+ $ldap = self::initLDAP($config);
+
+ $hosted_root_dn = \config('ldap.hosted.root_dn');
+ $mgmt_root_dn = \config('ldap.admin.root_dn');
+
+ $domain_base_dn = "ou={$domain->namespace},{$hosted_root_dn}";
+
+ if ($ldap->get_entry($domain_base_dn)) {
+ $ldap->delete_entry_recursive($domain_base_dn);
+ }
+
+ if ($ldap_domain = $ldap->find_domain($domain->namespace)) {
+ if ($ldap->get_entry($ldap_domain['dn'])) {
+ $ldap->delete_entry($ldap_domain['dn']);
+ }
+ }
+ }
+
+ public static function deleteUser($user)
+ {
+ $config = self::getConfig('admin');
+ $ldap = self::initLDAP($config);
+
+ list($_local, $_domain) = explode('@', $user->email, 2);
+
+ $domain = $ldap->find_domain($_domain);
+
+ if (!$domain) {
+ return false;
+ }
+
+ $base_dn = $ldap->domain_root_dn($_domain);
+ $dn = "uid={$user->email},ou=People,{$base_dn}";
+
+ if (!$ldap->get_entry($dn)) {
+ return false;
+ }
+
+ $ldap->delete_entry($dn);
+ }
+
/**
* Update a user in LDAP.
*
* @param \App\User $user The user account to update.
*
- * @return void
+ * @return bool|void
*/
public static function updateUser(User $user)
{
diff --git a/src/app/Console/Commands/PackageSkusCommand.php b/src/app/Console/Commands/PackageSkusCommand.php
--- a/src/app/Console/Commands/PackageSkusCommand.php
+++ b/src/app/Console/Commands/PackageSkusCommand.php
@@ -39,12 +39,12 @@
*/
public function handle()
{
- $packages = Package::get();
+ $packages = Package::all();
foreach ($packages as $package) {
$this->info(sprintf("Package: %s", $package->title));
- foreach ($package->skus()->get() as $sku) {
+ foreach ($package->skus as $sku) {
$this->info(sprintf(" SKU: %s (%d)", $sku->title, $sku->pivot->qty));
}
}
diff --git a/src/app/Console/Commands/PlanPackagesCommand.php b/src/app/Console/Commands/PlanPackagesCommand.php
--- a/src/app/Console/Commands/PlanPackagesCommand.php
+++ b/src/app/Console/Commands/PlanPackagesCommand.php
@@ -39,14 +39,14 @@
*/
public function handle()
{
- $plans = Plan::get();
+ $plans = Plan::all();
foreach ($plans as $plan) {
$this->info(sprintf("Plan: %s", $plan->title));
$plan_costs = 0;
- foreach ($plan->packages()->get() as $package) {
+ foreach ($plan->packages as $package) {
$qtyMin = $package->pivot->qty_min;
$qtyMax = $package->pivot->qty_max;
@@ -65,7 +65,7 @@
)
);
- foreach ($package->skus()->get() as $sku) {
+ foreach ($package->skus as $sku) {
$this->info(sprintf(" SKU: %s (%d)", $sku->title, $sku->pivot->qty));
}
diff --git a/src/app/Console/Commands/UserDomains.php b/src/app/Console/Commands/UserDomains.php
--- a/src/app/Console/Commands/UserDomains.php
+++ b/src/app/Console/Commands/UserDomains.php
@@ -40,8 +40,6 @@
*/
public function handle()
{
- DB::enableQueryLog();
-
$user = User::where('email', $this->argument('userid'))->first();
$this->info("Found user: {$user->id}");
@@ -49,7 +47,5 @@
foreach ($user->domains() as $domain) {
$this->info("Domain: {$domain->namespace}");
}
-
- dd(DB::getQueryLog());
}
}
diff --git a/src/app/Console/Commands/UserEntitlementsCommand.php b/src/app/Console/Commands/UserEntitlementsCommand.php
--- a/src/app/Console/Commands/UserEntitlementsCommand.php
+++ b/src/app/Console/Commands/UserEntitlementsCommand.php
@@ -2,7 +2,7 @@
namespace App\Console\Commands;
-use App\Domain;
+use App\Sku;
use App\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
@@ -44,19 +44,19 @@
$this->info("Found user: {$user->id}");
- $entitlements = $user->entitlements()->get();
+ $skus_counted = [];
- foreach ($entitlements as $entitlement) {
- //yes: dd($entitlement);
- $_entitleable = $entitlement->entitleable;
-
- if ($_entitleable instanceof Domain) {
- $this->info(sprintf("Domain: %s", $_entitleable->namespace));
+ 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;
}
+ }
- if ($_entitleable instanceof User) {
- $this->info(sprintf("User: %s", $_entitleable->email));
- }
+ foreach ($skus_counted as $id => $qty) {
+ $sku = Sku::find($id);
+ $this->info("SKU: {$sku->title} ({$qty})");
}
}
}
diff --git a/src/app/Domain.php b/src/app/Domain.php
--- a/src/app/Domain.php
+++ b/src/app/Domain.php
@@ -3,9 +3,17 @@
namespace App;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\SoftDeletes;
+/**
+ * The eloquent definition of a Domain.
+ *
+ * @property string $namespace
+ */
class Domain extends Model
{
+ use SoftDeletes;
+
// we've simply never heard of this domain
public const STATUS_NEW = 1 << 0;
// it's been activated
@@ -17,7 +25,7 @@
// ownership of the domain has been confirmed
public const STATUS_CONFIRMED = 1 << 4;
// domain has been verified that it exists in DNS
-// public const STATUS_VERIFIED = 1 << 5;
+ public const STATUS_VERIFIED = 1 << 5;
// domain has been created in LDAP
public const STATUS_LDAP_READY = 1 << 6;
@@ -33,6 +41,7 @@
public const HASH_CNAME = 3;
public $incrementing = false;
+
protected $keyType = 'bigint';
protected $fillable = [
@@ -65,7 +74,7 @@
*/
public function isActive(): bool
{
- return $this->status & self::STATUS_ACTIVE;
+ return ($this->status & self::STATUS_ACTIVE) == true;
}
/**
@@ -75,7 +84,7 @@
*/
public function isConfirmed(): bool
{
- return $this->status & self::STATUS_CONFIRMED;
+ return ($this->status & self::STATUS_CONFIRMED) == true;
}
/**
@@ -85,7 +94,7 @@
*/
public function isDeleted(): bool
{
- return $this->status & self::STATUS_DELETED;
+ return ($this->status & self::STATUS_DELETED) == true;
}
/**
@@ -95,7 +104,7 @@
*/
public function isExternal(): bool
{
- return $this->type & self::TYPE_EXTERNAL;
+ return ($this->type & self::TYPE_EXTERNAL) == true;
}
/**
@@ -105,7 +114,7 @@
*/
public function isHosted(): bool
{
- return $this->type & self::TYPE_HOSTED;
+ return ($this->type & self::TYPE_HOSTED) == true;
}
/**
@@ -115,7 +124,7 @@
*/
public function isNew(): bool
{
- return $this->status & self::STATUS_NEW;
+ return ($this->status & self::STATUS_NEW) == true;
}
/**
@@ -125,7 +134,7 @@
*/
public function isPublic(): bool
{
- return $this->type & self::TYPE_PUBLIC;
+ return ($this->type & self::TYPE_PUBLIC) == true;
}
/**
@@ -135,7 +144,7 @@
*/
public function isLdapReady(): bool
{
- return $this->status & self::STATUS_LDAP_READY;
+ return ($this->status & self::STATUS_LDAP_READY) == true;
}
/**
@@ -145,7 +154,7 @@
*/
public function isSuspended(): bool
{
- return $this->status & self::STATUS_SUSPENDED;
+ return ($this->status & self::STATUS_SUSPENDED) == true;
}
/**
@@ -154,12 +163,11 @@
*
* @return bool
*/
-/*
public function isVerified(): bool
{
- return $this->status & self::STATUS_VERIFIED;
+ return ($this->status & self::STATUS_VERIFIED) == true;
}
-*/
+
/**
* Domain status mutator
*
@@ -176,7 +184,7 @@
self::STATUS_SUSPENDED,
self::STATUS_DELETED,
self::STATUS_LDAP_READY,
-// self::STATUS_VERIFIED,
+ self::STATUS_VERIFIED,
];
foreach ($allowed_values as $value) {
@@ -232,7 +240,7 @@
$records = \dns_get_record('kolab-verify.' . $this->namespace, DNS_CNAME);
if ($records === false) {
- throw new \Exception("Failed to get DNS record for $domain");
+ throw new \Exception("Failed to get DNS record for {$this->namespace}");
}
foreach ($records as $records) {
@@ -277,14 +285,13 @@
* @return bool True if registered, False otherwise
* @throws \Exception Throws exception on DNS or DB errors
*/
-/*
public function verify(): bool
{
if ($this->isVerified()) {
return true;
}
- $record = \dns_get_record($this->namespace, DNS_SOA);
+ $record = \dns_get_record($this->namespace, DNS_ANY);
if ($record === false) {
throw new \Exception("Failed to get DNS record for {$this->namespace}");
@@ -299,5 +306,4 @@
return false;
}
-*/
}
diff --git a/src/app/Entitlement.php b/src/app/Entitlement.php
--- a/src/app/Entitlement.php
+++ b/src/app/Entitlement.php
@@ -40,7 +40,7 @@
];
/**
- * Principally entitleable objects such as 'Domain' or 'Mailbox'.
+ * Principally entitleable objects such as 'Domain' or 'User'.
*
* @return mixed
*/
@@ -52,7 +52,7 @@
/**
* The SKU concerned.
*
- * @return Sku
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function sku()
{
@@ -62,7 +62,7 @@
/**
* The owner of this entitlement.
*
- * @return User
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function owner()
{
@@ -72,7 +72,7 @@
/**
* The wallet this entitlement is being billed to
*
- * @return Wallet
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function wallet()
{
diff --git a/src/app/Handlers/Base.php b/src/app/Handlers/Base.php
new file mode 100644
--- /dev/null
+++ b/src/app/Handlers/Base.php
@@ -0,0 +1,14 @@
+<?php
+
+namespace App\Handlers;
+
+abstract class Base
+{
+ public static function entitleableClass()
+ {
+ }
+
+ public static function preReq($entitlement, $object)
+ {
+ }
+}
diff --git a/src/app/Handlers/Domain.php b/src/app/Handlers/Domain.php
--- a/src/app/Handlers/Domain.php
+++ b/src/app/Handlers/Domain.php
@@ -4,7 +4,7 @@
use App\Sku;
-class Domain
+class Domain extends \App\Handlers\Base
{
public static function entitleableClass()
{
diff --git a/src/app/Handlers/DomainHosting.php b/src/app/Handlers/DomainHosting.php
--- a/src/app/Handlers/DomainHosting.php
+++ b/src/app/Handlers/DomainHosting.php
@@ -4,7 +4,7 @@
use App\Sku;
-class DomainHosting
+class DomainHosting extends \App\Handlers\Base
{
public static function entitleableClass()
{
diff --git a/src/app/Handlers/DomainRegistration.php b/src/app/Handlers/DomainRegistration.php
--- a/src/app/Handlers/DomainRegistration.php
+++ b/src/app/Handlers/DomainRegistration.php
@@ -4,7 +4,7 @@
use App\Sku;
-class DomainRegistration
+class DomainRegistration extends \App\Handlers\Base
{
public static function entitleableClass()
{
diff --git a/src/app/Handlers/Groupware.php b/src/app/Handlers/Groupware.php
--- a/src/app/Handlers/Groupware.php
+++ b/src/app/Handlers/Groupware.php
@@ -4,7 +4,7 @@
use App\Sku;
-class Groupware
+class Groupware extends \App\Handlers\Base
{
public static function entitleableClass()
{
diff --git a/src/app/Handlers/Mailbox.php b/src/app/Handlers/Mailbox.php
--- a/src/app/Handlers/Mailbox.php
+++ b/src/app/Handlers/Mailbox.php
@@ -6,14 +6,14 @@
use App\Sku;
use App\User;
-class Mailbox
+class Mailbox extends \App\Handlers\Base
{
public static function entitleableClass()
{
return \App\User::class;
}
- public static function preReq(Entitlement $entitlement, User $user)
+ public static function preReq($entitlement, $user)
{
if (!Sku::find($entitlement->sku_id)->active) {
\Log::error("Sku not active");
diff --git a/src/app/Handlers/Resource.php b/src/app/Handlers/Resource.php
--- a/src/app/Handlers/Resource.php
+++ b/src/app/Handlers/Resource.php
@@ -4,7 +4,7 @@
use App\Sku;
-class Resource
+class Resource extends \App\Handlers\Base
{
public static function entitleableClass()
{
diff --git a/src/app/Handlers/SharedFolder.php b/src/app/Handlers/SharedFolder.php
--- a/src/app/Handlers/SharedFolder.php
+++ b/src/app/Handlers/SharedFolder.php
@@ -4,7 +4,7 @@
use App\Sku;
-class SharedFolder
+class SharedFolder extends \App\Handlers\Base
{
public static function entitleableClass()
{
diff --git a/src/app/Handlers/Storage.php b/src/app/Handlers/Storage.php
--- a/src/app/Handlers/Storage.php
+++ b/src/app/Handlers/Storage.php
@@ -2,32 +2,16 @@
namespace App\Handlers;
-use App\Quota;
-use App\Sku;
-use App\User;
-
-class Storage
+class Storage extends \App\Handlers\Base
{
- public static function createDefaultEntitleable(User $user)
- {
- $quota = new Quota();
- $quota->user_id = $user->id;
- $quota->save();
-
- return $quota->id;
- }
-
public static function entitleableClass()
{
- return Quota::class;
+ return null;
}
- public static function preReq($entitlement, $user)
+ public static function preReq($entitlement, $object)
{
- if (!Sku::find($entitlement->sku_id)->active) {
- \Log::error("Sku not active");
- return false;
- }
+ // TODO: The storage can not be modified to below what is already consumed.
return true;
}
diff --git a/src/app/Http/Controllers/API/DomainsController.php b/src/app/Http/Controllers/API/DomainsController.php
--- a/src/app/Http/Controllers/API/DomainsController.php
+++ b/src/app/Http/Controllers/API/DomainsController.php
@@ -12,7 +12,7 @@
/**
* Display a listing of the resource.
*
- * @return \Illuminate\Http\Response
+ * @return \Illuminate\Http\JsonResponse
*/
public function index()
{
@@ -22,7 +22,7 @@
/**
* Show the form for creating a new resource.
*
- * @return \Illuminate\Http\Response
+ * @return \Illuminate\Http\JsonResponse
*/
public function create()
{
@@ -34,7 +34,7 @@
*
* @param int $id Domain identifier
*
- * @return \Illuminate\Http\Response
+ * @return \Illuminate\Http\JsonResponse|void
*/
public function confirm($id)
{
@@ -57,7 +57,7 @@
*
* @param int $id
*
- * @return \Illuminate\Http\Response
+ * @return \Illuminate\Http\JsonResponse
*/
public function destroy($id)
{
@@ -93,7 +93,7 @@
*
* @param int $id Domain identifier
*
- * @return \Illuminate\Http\Response
+ * @return \Illuminate\Http\JsonResponse|void
*/
public function show($id)
{
@@ -197,7 +197,7 @@
/**
* Check if the current user has access to the domain
*
- * @param \App\Domain Domain
+ * @param \App\Domain $domain The domain
*
* @return bool True if current user has access, False otherwise
*/
diff --git a/src/app/Http/Controllers/API/PasswordResetController.php b/src/app/Http/Controllers/API/PasswordResetController.php
--- a/src/app/Http/Controllers/API/PasswordResetController.php
+++ b/src/app/Http/Controllers/API/PasswordResetController.php
@@ -24,7 +24,7 @@
*
* Verifies user email, sends verification email message.
*
- * @param Illuminate\Http\Request HTTP request
+ * @param \Illuminate\Http\Request $request HTTP request
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
@@ -63,7 +63,7 @@
/**
* Validation of the verification code.
*
- * @param Illuminate\Http\Request HTTP request
+ * @param \Illuminate\Http\Request $request HTTP request
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
@@ -106,7 +106,7 @@
/**
* Password change
*
- * @param Illuminate\Http\Request HTTP request
+ * @param \Illuminate\Http\Request $request HTTP request
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
diff --git a/src/app/Http/Controllers/API/SignupController.php b/src/app/Http/Controllers/API/SignupController.php
--- a/src/app/Http/Controllers/API/SignupController.php
+++ b/src/app/Http/Controllers/API/SignupController.php
@@ -29,7 +29,7 @@
/**
* Returns plans definitions for signup.
*
- * @param Illuminate\Http\Request HTTP request
+ * @param \Illuminate\Http\Request $request HTTP request
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
@@ -55,7 +55,7 @@
* Verifies user name and email/phone, sends verification email/sms message.
* Returns the verification code.
*
- * @param Illuminate\Http\Request HTTP request
+ * @param \Illuminate\Http\Request $request HTTP request
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
@@ -102,7 +102,7 @@
/**
* Validation of the verification code.
*
- * @param Illuminate\Http\Request HTTP request
+ * @param \Illuminate\Http\Request $request HTTP request
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
@@ -153,7 +153,7 @@
/**
* Finishes the signup process by creating the user account.
*
- * @param Illuminate\Http\Request HTTP request
+ * @param \Illuminate\Http\Request $request HTTP request
*
* @return \Illuminate\Http\JsonResponse JSON response
*/
@@ -218,15 +218,14 @@
'status' => Domain::STATUS_NEW,
'type' => Domain::TYPE_EXTERNAL,
]);
- }
- // Create SKUs (after domain)
- foreach ($plan->packages as $package) {
- foreach ($package->skus as $sku) {
- $sku->registerEntitlement($user, is_object($domain) ? [$domain] : []);
- }
+ $domain_package = \App\Package::where('title', 'domain-hosting')->first();
+ $domain_package->assign($domain, $user);
}
+ $user_package = \App\Package::where('title', 'kolab')->first();
+ $user_package->assign($user);
+
// Save the external email and plan in user settings
$user->setSettings([
'external_email' => $user_email,
@@ -244,8 +243,8 @@
/**
* Checks if the input string is a valid email address or a phone number
*
- * @param string $email Email address or phone number
- * @param bool &$is_phone Will be set to True if the string is valid phone number
+ * @param string $input Email address or phone number
+ * @param bool $is_phone Will have been set to True if the string is valid phone number
*
* @return string Error message label on validation error
*/
@@ -297,7 +296,7 @@
/**
* Login (kolab identity) validation
*
- * @param string $email Login (local part of an email address)
+ * @param string $login Login (local part of an email address)
* @param string $domain Domain name
* @param bool $external Enables additional checks for domain part
*
diff --git a/src/app/Http/Controllers/API/UsersController.php b/src/app/Http/Controllers/API/UsersController.php
--- a/src/app/Http/Controllers/API/UsersController.php
+++ b/src/app/Http/Controllers/API/UsersController.php
@@ -46,7 +46,7 @@
*
* The user themself, and other user entitlements.
*
- * @return \Illuminate\Http\Response
+ * @return \Illuminate\Http\JsonResponse
*/
public function index()
{
@@ -141,11 +141,11 @@
}
/**
- * Display the specified resource.
+ * Display information on the user account specified by $id.
*
* @param int $id The account to show information for.
*
- * @return \Illuminate\Http\Response
+ * @return \Illuminate\Http\JsonResponse|void
*/
public function show($id)
{
@@ -155,25 +155,13 @@
return abort(403);
}
- $result = false;
-
- $user->entitlements()->each(
- function ($entitlement) {
- if ($entitlement->user_id == $id) {
- $result = true;
- }
- }
- );
-
- if ($user->id == $id) {
- $result = true;
- }
-
- if (!$result) {
+ // TODO: check whether or not the user is allowed
+ // for now, only allow self.
+ if ($user->id != $id) {
return abort(404);
}
- return \App\User::find($id);
+ return response()->json($user);
}
/**
diff --git a/src/app/Jobs/UserDelete.php b/src/app/Jobs/DomainDelete.php
copy from src/app/Jobs/UserDelete.php
copy to src/app/Jobs/DomainDelete.php
--- a/src/app/Jobs/UserDelete.php
+++ b/src/app/Jobs/DomainDelete.php
@@ -2,20 +2,22 @@
namespace App\Jobs;
+use App\Backends\LDAP;
+use App\Domain;
use Illuminate\Bus\Queueable;
-use Illuminate\Queue\SerializesModels;
-use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\SerializesModels;
+use Illuminate\Queue\InteractsWithQueue;
-class UserDelete implements ShouldQueue
+class DomainDelete implements ShouldQueue
{
use Dispatchable;
use InteractsWithQueue;
use Queueable;
use SerializesModels;
- protected $user;
+ protected $domain;
public $tries = 5;
@@ -25,13 +27,13 @@
/**
* Create a new job instance.
*
- * @param \App\User $user The user to delete.
+ * @param Domain $domain The domain to delete.
*
* @return void
*/
- public function __construct(\App\User $user)
+ public function __construct(Domain $domain)
{
- $this->user = $user;
+ $this->domain = $domain;
}
/**
@@ -41,6 +43,6 @@
*/
public function handle()
{
- //
+ LDAP::deleteDomain($this->domain);
}
}
diff --git a/src/app/Jobs/UserDelete.php b/src/app/Jobs/UserDelete.php
--- a/src/app/Jobs/UserDelete.php
+++ b/src/app/Jobs/UserDelete.php
@@ -2,6 +2,8 @@
namespace App\Jobs;
+use App\Backends\LDAP;
+use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
@@ -25,13 +27,13 @@
/**
* Create a new job instance.
*
- * @param \App\User $user The user to delete.
+ * @param int $user_id The ID of the user to delete.
*
* @return void
*/
- public function __construct(\App\User $user)
+ public function __construct(int $user_id)
{
- $this->user = $user;
+ $this->user = User::withTrashed()->find($user_id);
}
/**
@@ -41,6 +43,6 @@
*/
public function handle()
{
- //
+ LDAP::deleteUser($this->user);
}
}
diff --git a/src/app/Mail/PasswordReset.php b/src/app/Mail/PasswordReset.php
--- a/src/app/Mail/PasswordReset.php
+++ b/src/app/Mail/PasswordReset.php
@@ -19,7 +19,7 @@
/**
* Create a new message instance.
*
- * @param \App\VerificationCode A verification code object
+ * @param \App\VerificationCode $code A verification code object
*
* @return void
*/
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
@@ -36,16 +36,14 @@
public function created(Domain $domain)
{
// Create domain record in LDAP, then check if it exists in DNS
-/*
- $chain = [
- new \App\Jobs\DomainVerify($domain),
- ];
-
- \App\Jobs\DomainCreate::withChain($chain)->dispatch($domain);
-*/
\App\Jobs\DomainCreate::dispatch($domain);
}
+ public function deleting(Domain $domain)
+ {
+ //
+ }
+
/**
* Handle the domain "updated" event.
*
@@ -67,7 +65,7 @@
*/
public function deleted(Domain $domain)
{
- //
+ \App\Jobs\DomainDelete::dispatch($domain);
}
/**
diff --git a/src/app/Observers/EntitlementObserver.php b/src/app/Observers/EntitlementObserver.php
--- a/src/app/Observers/EntitlementObserver.php
+++ b/src/app/Observers/EntitlementObserver.php
@@ -19,7 +19,7 @@
*
* @param Entitlement $entitlement The entitlement being created.
*
- * @return void
+ * @return bool|null
*/
public function creating(Entitlement $entitlement)
{
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
@@ -65,6 +65,11 @@
\App\Jobs\UserCreate::withChain($chain)->dispatch($user);
}
+ public function deleted(User $user)
+ {
+ //
+ }
+
/**
* Handle the "deleting" event.
*
@@ -74,7 +79,16 @@
*/
public function deleting(User $user)
{
- // TODO \App\Jobs\UserDelete::dispatch($user);
+ // Entitlements do not have referential integrity on the entitled object, so this is our
+ // way of doing an onDelete('cascade') without the foreign key.
+ $entitlements = \App\Entitlement::where('entitleable_id', $user->id)
+ ->where('entitleable_type', \App\User::class)->get();
+
+ foreach ($entitlements as $entitlement) {
+ $entitlement->delete();
+ }
+
+ \App\Jobs\UserDelete::dispatch($user->id);
}
/**
@@ -88,7 +102,7 @@
*/
public function retrieving(User $user)
{
- // TODO \App\Jobs\UserRead::dispatch($user);
+ // TODO \App\Jobs\UserRead::dispatch($user);
}
/**
diff --git a/src/app/Package.php b/src/app/Package.php
--- a/src/app/Package.php
+++ b/src/app/Package.php
@@ -34,6 +34,40 @@
'discount_rate'
];
+ public function assign($object, $user = null)
+ {
+ // if user == null, $object is a user ;-)
+ if ($user === null) {
+ $user = $object;
+ }
+
+ $entitleable_type = null;
+
+ if ($object instanceof \App\Domain) {
+ $entitleable_type = \App\Domain::class;
+ }
+
+ if ($object instanceof \App\User) {
+ $entitleable_type = \App\User::class;
+ }
+
+ $wallet_id = $user->wallets()->get()[0]->id;
+
+ foreach ($this->skus as $sku) {
+ for ($i = $sku->pivot->qty; $i > 0; $i--) {
+ \App\Entitlement::create(
+ [
+ 'owner_id' => $user->id,
+ 'wallet_id' => $wallet_id,
+ 'sku_id' => $sku->id,
+ 'entitleable_id' => $entitleable_type ? $object->id : null,
+ 'entitleable_type' => $entitleable_type
+ ]
+ );
+ }
+ }
+ }
+
public function cost()
{
$costs = 0;
diff --git a/src/app/PackageSku.php b/src/app/PackageSku.php
--- a/src/app/PackageSku.php
+++ b/src/app/PackageSku.php
@@ -4,6 +4,9 @@
use Illuminate\Database\Eloquent\Relations\Pivot;
+/**
+ * Link SKUs to Packages.
+ */
class PackageSku extends Pivot
{
protected $fillable = [
diff --git a/src/app/Plan.php b/src/app/Plan.php
--- a/src/app/Plan.php
+++ b/src/app/Plan.php
@@ -11,6 +11,8 @@
*
* A "Family Plan" as such may exist of "2 or more Kolab packages",
* and apply a discount for the third and further Kolab packages.
+ *
+ * @property \App\Package[] $packages
*/
class Plan extends Model
{
@@ -58,6 +60,15 @@
return $costs;
}
+ /**
+ * The relationship to packages.
+ *
+ * The plan contains one or more packages. Each package may have its minimum number (for
+ * billing) or its maximum (to allow topping out "enterprise" customers on a "small business"
+ * plan).
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
+ */
public function packages()
{
return $this->belongsToMany(
@@ -74,7 +85,9 @@
}
/**
- * Checks if the plan has domain SKU assigned
+ * Checks if the plan has any type of domain SKU assigned.
+ *
+ * @return bool
*/
public function hasDomain(): bool
{
diff --git a/src/app/PlanPackage.php b/src/app/PlanPackage.php
--- a/src/app/PlanPackage.php
+++ b/src/app/PlanPackage.php
@@ -4,6 +4,12 @@
use Illuminate\Database\Eloquent\Relations\Pivot;
+/**
+ * Link Packages to Plans.
+ *
+ * @property integer $qty_min
+ * @property \App\Package $package
+ */
class PlanPackage extends Pivot
{
protected $fillable = [
@@ -24,6 +30,11 @@
'discount_rate' => 'integer'
];
+ /**
+ * Calculate the costs for this plan.
+ *
+ * @return integer
+ */
public function cost()
{
$costs = 0;
diff --git a/src/app/Quota.php b/src/app/Quota.php
deleted file mode 100644
--- a/src/app/Quota.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-namespace App;
-
-use Illuminate\Database\Eloquent\Model;
-
-class Quota extends Model
-{
- protected $keyType = 'bigint';
-
- protected $casts = [
- 'value' => 'int',
- ];
-
- public function entitlement()
- {
- return $this->morphOne('App\Entitlement', 'entitleable');
- }
-
- /**
- * The owner of this quota entry
- *
- * @return \App\User
- */
- public function user()
- {
- return $this->belongsTo('App\User', 'user_id', 'id');
- }
-}
diff --git a/src/app/SignupCode.php b/src/app/SignupCode.php
--- a/src/app/SignupCode.php
+++ b/src/app/SignupCode.php
@@ -7,6 +7,8 @@
/**
* The eloquent definition of a SignupCode.
+ *
+ * @property datetime $expires_at
*/
class SignupCode extends Model
{
diff --git a/src/app/Sku.php b/src/app/Sku.php
--- a/src/app/Sku.php
+++ b/src/app/Sku.php
@@ -29,7 +29,7 @@
/**
* List the entitlements that consume this SKU.
*
- * @return Entitlement[]
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function entitlements()
{
@@ -43,48 +43,4 @@
'package_skus'
)->using('App\PackageSku')->withPivot(['qty']);
}
-
- /**
- * Register (default) SKU entitlement for specified user.
- * This method should be used e.g. on user creation when we have
- * a set of SKUs and want to create entitlements for them (using
- * default values).
- */
- public function registerEntitlement(\App\User $user, array $params = [])
- {
- if (!$this->active) {
- \Log::debug("Skipped registration of an entitlement for non-active SKU ($this->title)");
- return;
- }
-
- $wallet = $user->wallets()->get()[0];
-
- $entitlement = new \App\Entitlement();
- $entitlement->owner_id = $user->id;
- $entitlement->wallet_id = $wallet->id;
- $entitlement->sku_id = $this->id;
-
- $entitlement->entitleable_type = $this->handler_class::entitleableClass();
-
- if ($user instanceof $entitlement->entitleable_type) {
- $entitlement->entitleable_id = $user->id;
- } else {
- foreach ($params as $param) {
- if ($param instanceof $entitlement->entitleable_type) {
- $entitlement->entitleable_id = $param->id;
- break;
- }
- }
- }
-
- if (empty($entitlement->entitleable_id)) {
- if (method_exists($this->handler_class, 'createDefaultEntitleable')) {
- $entitlement->entitleable_id = $this->handler_class::createDefaultEntitleable($user);
- } else {
- throw new Exception("Failed to create an entitlement for SKU ($this->title). Missing entitleable_id.");
- }
- }
-
- $entitlement->save();
- }
}
diff --git a/src/app/User.php b/src/app/User.php
--- a/src/app/User.php
+++ b/src/app/User.php
@@ -4,6 +4,7 @@
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
+use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Iatstuti\Database\Support\NullableFields;
use Tymon\JWTAuth\Contracts\JWTSubject;
@@ -11,12 +12,16 @@
/**
* The eloquent definition of a User.
+ *
+ * @property integer $id
+ * @property integer $status
*/
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
use NullableFields;
use UserSettingsTrait;
+ use SoftDeletes;
// a new user, default on creation
public const STATUS_NEW = 1 << 0;
@@ -78,18 +83,51 @@
/**
* Any wallets on which this user is a controller.
*
- * @return Wallet[]
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function accounts()
{
return $this->belongsToMany(
'App\Wallet', // The foreign object definition
'user_accounts', // The table name
- 'user_id', // The local foreign key
- 'wallet_id' // The remote foreign key
+ 'user_id', // The local foreign key
+ 'wallet_id' // The remote foreign key
);
}
+ /**
+ * Assign a package to a user. The user should not have any existing entitlements.
+ *
+ * @param \App\Package $package
+ * @param \App\User|null $user
+ *
+ * @return \App\User
+ */
+ public function assignPackage($package, $user = null)
+ {
+ if (!$user) {
+ $user = $this;
+ }
+
+ $wallet_id = $this->wallets()->get()[0]->id;
+
+ foreach ($package->skus as $sku) {
+ for ($i = $sku->pivot->qty; $i > 0; $i--) {
+ \App\Entitlement::create(
+ [
+ 'owner_id' => $this->id,
+ 'wallet_id' => $wallet_id,
+ 'sku_id' => $sku->id,
+ 'entitleable_id' => $user->id,
+ 'entitleable_type' => User::class
+ ]
+ );
+ }
+ }
+
+ return $user;
+ }
+
/**
* List the domains to which this user is entitled.
*
@@ -97,7 +135,7 @@
*/
public function domains()
{
- $domains = Domain::whereRaw(
+ $dbdomains = Domain::whereRaw(
sprintf(
'(type & %s) AND (status & %s)',
Domain::TYPE_PUBLIC,
@@ -105,19 +143,27 @@
)
)->get();
- foreach ($this->entitlements()->get() as $entitlement) {
+ $domains = [];
+
+ foreach ($dbdomains as $dbdomain) {
+ $domains[] = $dbdomain;
+ }
+
+ $entitlements = Entitlement::where('owner_id', $this->id)->get();
+
+ foreach ($entitlements as $entitlement) {
if ($entitlement->entitleable instanceof Domain) {
- $domain = Domain::find($entitlement->entitleable_id);
- \Log::info("Found domain {$domain->namespace}");
+ $domain = $entitlement->entitleable;
+ \Log::info("Found domain for {$this->email}: {$domain->namespace} (owned)");
$domains[] = $domain;
}
}
- foreach ($this->accounts()->get() as $wallet) {
- foreach ($wallet->entitlements()->get() as $entitlement) {
+ foreach ($this->accounts as $wallet) {
+ foreach ($wallet->entitlements as $entitlement) {
if ($entitlement->entitleable instanceof Domain) {
- $domain = Domain::find($entitlement->entitleable_id);
- \Log::info("Found domain {$domain->namespace}");
+ $domain = $entitlement->entitleable;
+ \Log::info("Found domain {$this->email}: {$domain->namespace} (charged)");
$domains[] = $domain;
}
}
@@ -134,17 +180,19 @@
/**
* Entitlements for this user.
*
- * @return Entitlement[]
+ * Note that these are entitlements that apply to the user account, and not entitlements that
+ * this user owns.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function entitlements()
{
- return $this->hasMany('App\Entitlement', 'owner_id', 'id');
+ return $this->hasMany('App\Entitlement', 'entitleable_id', 'id');
}
public function addEntitlement($entitlement)
{
- // FIXME: This contains() check looks fishy
- if (!$this->entitlements()->get()->contains($entitlement)) {
+ if (!$this->entitlements->contains($entitlement)) {
return $this->entitlements()->save($entitlement);
}
}
@@ -187,7 +235,7 @@
*/
public function isActive(): bool
{
- return $this->status & self::STATUS_ACTIVE;
+ return ($this->status & self::STATUS_ACTIVE) == true;
}
/**
@@ -197,7 +245,7 @@
*/
public function isDeleted(): bool
{
- return $this->status & self::STATUS_DELETED;
+ return ($this->status & self::STATUS_DELETED) == true;
}
/**
@@ -208,7 +256,7 @@
*/
public function isImapReady(): bool
{
- return $this->status & self::STATUS_IMAP_READY;
+ return ($this->status & self::STATUS_IMAP_READY) == true;
}
/**
@@ -218,7 +266,7 @@
*/
public function isLdapReady(): bool
{
- return $this->status & self::STATUS_LDAP_READY;
+ return ($this->status & self::STATUS_LDAP_READY) == true;
}
/**
@@ -228,7 +276,7 @@
*/
public function isNew(): bool
{
- return $this->status & self::STATUS_NEW;
+ return ($this->status & self::STATUS_NEW) == true;
}
/**
@@ -238,13 +286,13 @@
*/
public function isSuspended(): bool
{
- return $this->status & self::STATUS_SUSPENDED;
+ return ($this->status & self::STATUS_SUSPENDED) == true;
}
/**
* Any (additional) properties of this user.
*
- * @return \App\UserSetting[]
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function settings()
{
@@ -254,7 +302,7 @@
/**
* Verification codes for this user.
*
- * @return VerificationCode[]
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function verificationcodes()
{
@@ -264,13 +312,20 @@
/**
* Wallets this user owns.
*
- * @return Wallet[]
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function wallets()
{
return $this->hasMany('App\Wallet');
}
+ /**
+ * User password mutator
+ *
+ * @param string $password The password in plain text.
+ *
+ * @return void
+ */
public function setPasswordAttribute($password)
{
if (!empty($password)) {
@@ -281,6 +336,13 @@
}
}
+ /**
+ * User LDAP password mutator
+ *
+ * @param string $password The password in plain text.
+ *
+ * @return void
+ */
public function setPasswordLdapAttribute($password)
{
if (!empty($password)) {
diff --git a/src/app/UserSetting.php b/src/app/UserSetting.php
--- a/src/app/UserSetting.php
+++ b/src/app/UserSetting.php
@@ -21,10 +21,14 @@
/**
* The user to which this setting belongs.
*
- * @return \App\User
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
- return $this->belongsTo('\App\User', 'user_id' /* local */, 'id' /* remote */);
+ return $this->belongsTo(
+ '\App\User',
+ 'user_id', /* local */
+ 'id' /* remote */
+ );
}
}
diff --git a/src/app/Utils.php b/src/app/Utils.php
--- a/src/app/Utils.php
+++ b/src/app/Utils.php
@@ -49,7 +49,7 @@
*/
public static function uuidStr(): string
{
- return (string) Uuid::uuid4();
+ return Uuid::uuid4()->toString();
}
private static function combine($input, $r, $index, $data, $i, &$output): void
diff --git a/src/app/VerificationCode.php b/src/app/VerificationCode.php
--- a/src/app/VerificationCode.php
+++ b/src/app/VerificationCode.php
@@ -33,7 +33,7 @@
/**
* The user to which this setting belongs.
*
- * @return \App\User
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
diff --git a/src/app/Wallet.php b/src/app/Wallet.php
--- a/src/app/Wallet.php
+++ b/src/app/Wallet.php
@@ -10,16 +10,13 @@
* The eloquent definition of a wallet -- a container with a chunk of change.
*
* A wallet is owned by an {@link \App\User}.
+ *
+ * @property integer $balance
*/
class Wallet extends Model
{
use NullableFields;
- /**
- Our table name for the shall be 'wallet'.
-
- @var string
- */
public $incrementing = false;
protected $keyType = 'string';
@@ -53,7 +50,7 @@
*/
public function addController(User $user)
{
- if (!$this->controllers()->get()->contains($user)) {
+ if (!$this->controllers->contains($user)) {
$this->controllers()->save($user);
}
}
@@ -67,7 +64,7 @@
*/
public function removeController(User $user)
{
- if ($this->controllers()->get()->contains($user)) {
+ if ($this->controllers->contains($user)) {
$this->controllers()->detach($user);
}
}
@@ -107,7 +104,7 @@
/**
* Controllers of this wallet.
*
- * @return \App\User[]
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function controllers()
{
@@ -122,7 +119,7 @@
/**
* Entitlements billed to this wallet.
*
- * @return Entitlement[]
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function entitlements()
{
@@ -132,7 +129,7 @@
/**
* The owner of the wallet -- the wallet is in his/her back pocket.
*
- * @return User
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function owner()
{
diff --git a/src/composer.json b/src/composer.json
--- a/src/composer.json
+++ b/src/composer.json
@@ -37,6 +37,8 @@
"laravel/dusk": "^5.5",
"mockery/mockery": "^1.0",
"nunomaduro/collision": "^3.0",
+ "nunomaduro/larastan": "^0.4",
+ "phpstan/phpstan": "0.11.19",
"phpunit/phpunit": "^7.5"
},
"config": {
diff --git a/src/config/imap.php b/src/config/imap.php
--- a/src/config/imap.php
+++ b/src/config/imap.php
@@ -5,6 +5,5 @@
'admin_login' => env('IMAP_ADMIN_LOGIN', 'cyrus-admin'),
'admin_password' => env('IMAP_ADMIN_PASSWORD', null),
'verify_peer' => env('IMAP_VERIFY_PEER', true),
- 'verify_name' => env('IMAP_VERIFY_NAME', true),
- 'cafile' => env('IMAP_CAFILE', null),
+ 'verify_host' => env('IMAP_VERIFY_HOST', true)
];
diff --git a/src/database/migrations/2019_10_10_095050_create_quota_table.php b/src/database/migrations/2019_10_10_095050_create_quota_table.php
--- a/src/database/migrations/2019_10_10_095050_create_quota_table.php
+++ b/src/database/migrations/2019_10_10_095050_create_quota_table.php
@@ -13,14 +13,16 @@
*/
public function up()
{
+ /*
Schema::create('quotas', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('user_id');
- $table->integer('value')->default(2147483648);
+ $table->unsignedInteger('value')->default(2147483648);
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
+ */
}
/**
diff --git a/src/database/migrations/2020_02_11_110959_add_deleted_at.php b/src/database/migrations/2020_02_11_110959_add_deleted_at.php
new file mode 100644
--- /dev/null
+++ b/src/database/migrations/2020_02_11_110959_add_deleted_at.php
@@ -0,0 +1,51 @@
+<?php
+
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Migrations\Migration;
+
+class AddDeletedAt extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::table(
+ 'domains',
+ function (Blueprint $table) {
+ $table->softDeletes();
+ }
+ );
+
+ Schema::table(
+ 'users',
+ function (Blueprint $table) {
+ $table->softDeletes();
+ }
+ );
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table(
+ 'domains',
+ function (Blueprint $table) {
+ $table->dropColumn(['deleted_at']);
+ }
+ );
+ Schema::table(
+ 'users',
+ function (Blueprint $table) {
+ $table->dropColumn(['deleted_at']);
+ }
+ );
+ }
+}
diff --git a/src/database/seeds/DatabaseSeeder.php b/src/database/seeds/DatabaseSeeder.php
--- a/src/database/seeds/DatabaseSeeder.php
+++ b/src/database/seeds/DatabaseSeeder.php
@@ -15,9 +15,9 @@
[
DomainSeeder::class,
SkuSeeder::class,
- UserSeeder::class,
PackageSeeder::class,
- PlanSeeder::class
+ PlanSeeder::class,
+ UserSeeder::class
]
);
}
diff --git a/src/database/seeds/DomainSeeder.php b/src/database/seeds/DomainSeeder.php
--- a/src/database/seeds/DomainSeeder.php
+++ b/src/database/seeds/DomainSeeder.php
@@ -35,5 +35,21 @@
]
);
}
+
+ $domains = [
+ 'example.com',
+ 'example.net',
+ 'example.org'
+ ];
+
+ foreach ($domains as $domain) {
+ Domain::create(
+ [
+ 'namespace' => $domain,
+ 'status' => Domain::STATUS_CONFIRMED + Domain::STATUS_ACTIVE,
+ 'type' => Domain::TYPE_EXTERNAL
+ ]
+ );
+ }
}
}
diff --git a/src/database/seeds/UserSeeder.php b/src/database/seeds/UserSeeder.php
--- a/src/database/seeds/UserSeeder.php
+++ b/src/database/seeds/UserSeeder.php
@@ -19,12 +19,12 @@
$domain = Domain::create(
[
'namespace' => 'kolab.org',
- 'status' => Domain::STATUS_NEW + Domain::STATUS_ACTIVE + Domain::STATUS_CONFIRMED,
+ 'status' => Domain::STATUS_NEW + Domain::STATUS_ACTIVE + Domain::STATUS_CONFIRMED + Domain::STATUS_VERIFIED,
'type' => Domain::TYPE_EXTERNAL
]
);
- $user = User::create(
+ $john = User::create(
[
'name' => "John Doe",
'email' => 'john@kolab.org',
@@ -33,38 +33,43 @@
]
);
- $user_wallets = $user->wallets()->get();
-
- $sku_domain = Sku::where('title', 'domain')->first();
- $sku_mailbox = Sku::where('title', 'mailbox')->first();
-
- $entitlement_domain = Entitlement::create(
+ $john->setSettings(
[
- 'owner_id' => $user->id,
- 'wallet_id' => $user_wallets[0]->id,
- 'sku_id' => $sku_domain->id,
- 'entitleable_id' => $domain->id,
- 'entitleable_type' => Domain::class
+ "first_name" => "John",
+ "last_name" => "Doe",
+ "currency" => "USD",
+ "country" => "US"
]
);
- $entitlement_mailbox = Entitlement::create(
+ $user_wallets = $john->wallets()->get();
+
+ $package_domain = \App\Package::where('title', 'domain-hosting')->first();
+ $package_kolab = \App\Package::where('title', 'kolab')->first();
+
+ $package_domain->assign($domain, $john);
+ $package_kolab->assign($john);
+
+ $jack = User::create(
[
- 'owner_id' => $user->id,
- 'wallet_id' => $user_wallets[0]->id,
- 'sku_id' => $sku_mailbox->id,
- 'entitleable_id' => $user->id,
- 'entitleable_type' => User::class
+ 'name' => "Jack Daniels",
+ 'email' => 'jack@kolab.org',
+ 'password' => 'simple123',
+ 'email_verified_at' => now()
]
);
- $user->setSettings(
+ $jack->setSettings(
[
- "first_name" => "John",
- "last_name" => "Doe",
+ "first_name" => "Jack",
+ "last_name" => "Daniels",
"currency" => "USD",
"country" => "US"
]
);
+
+ $john->assignPackage($package_kolab, $jack);
+
+ factory(User::class, 50)->create();
}
}
diff --git a/src/phpstan b/src/phpstan
new file mode 120000
--- /dev/null
+++ b/src/phpstan
@@ -0,0 +1 @@
+../bin/phpstan
\ No newline at end of file
diff --git a/src/phpstan.neon b/src/phpstan.neon
new file mode 100644
--- /dev/null
+++ b/src/phpstan.neon
@@ -0,0 +1,6 @@
+includes:
+ - ./vendor/nunomaduro/larastan/extension.neon
+parameters:
+ level: 3
+ paths:
+ - app/
diff --git a/src/phpunit b/src/phpunit
new file mode 120000
--- /dev/null
+++ b/src/phpunit
@@ -0,0 +1 @@
+../bin/phpunit
\ No newline at end of file
diff --git a/src/phpunit.xml b/src/phpunit.xml
--- a/src/phpunit.xml
+++ b/src/phpunit.xml
@@ -23,6 +23,9 @@
<directory suffix=".php">./app</directory>
</whitelist>
</filter>
+ <logging>
+ <log type="coverage-html" target="./tests/report/" lowUpperBound="35" highLowerBound="70"/>
+ </logging>
<php>
<server name="APP_ENV" value="testing"/>
<server name="APP_DEBUG" value="true"/>
diff --git a/src/tests/Feature/Controller/DomainsTest.php b/src/tests/Feature/Controller/DomainsTest.php
--- a/src/tests/Feature/Controller/DomainsTest.php
+++ b/src/tests/Feature/Controller/DomainsTest.php
@@ -20,8 +20,16 @@
{
parent::setUp();
- User::where('email', 'test1@domainscontroller.com')->delete();
- Domain::where('namespace', 'domainscontroller.com')->delete();
+ $this->deleteTestUser('test1@domainscontroller.com');
+ $this->deleteTestDomain('domainscontroller.com');
+ }
+
+ public function tearDown(): void
+ {
+ $this->deleteTestUser('test1@domainscontroller.com');
+ $this->deleteTestDomain('domainscontroller.com');
+
+ parent::tearDown();
}
/**
diff --git a/src/tests/Feature/Controller/PasswordResetTest.php b/src/tests/Feature/Controller/PasswordResetTest.php
--- a/src/tests/Feature/Controller/PasswordResetTest.php
+++ b/src/tests/Feature/Controller/PasswordResetTest.php
@@ -25,7 +25,7 @@
public function tearDown(): void
{
User::where('email', 'passwordresettest@' . \config('app.domain'))
- ->delete();
+ ->forceDelete();
}
/**
diff --git a/src/tests/Feature/Controller/SignupTest.php b/src/tests/Feature/Controller/SignupTest.php
--- a/src/tests/Feature/Controller/SignupTest.php
+++ b/src/tests/Feature/Controller/SignupTest.php
@@ -11,7 +11,7 @@
class SignupTest extends TestCase
{
- private static $domain;
+ private $domain;
/**
* {@inheritDoc}
@@ -22,8 +22,14 @@
// TODO: Some tests depend on existence of individual and group plans,
// we should probably create plans here to not depend on that
- $domain = self::getPublicDomain();
- $user = $this->getTestUser("SignupControllerTest1@$domain");
+ $this->domain = $this->getPublicDomain();
+
+ $this->deleteTestUser("SignupControllerTest1@$this->domain");
+ $this->deleteTestUser("signuplogin@$this->domain");
+ $this->deleteTestUser("admin@external.com");
+
+ $this->deleteTestDomain('external.com');
+ $this->deleteTestDomain('signup-domain.com');
}
/**
@@ -31,39 +37,37 @@
*/
public function tearDown(): void
{
- $domain = self::getPublicDomain();
+ $this->deleteTestUser("SignupControllerTest1@$this->domain");
+ $this->deleteTestUser("signuplogin@$this->domain");
+ $this->deleteTestUser("admin@external.com");
- User::where('email', "signuplogin@$domain")
- ->orWhere('email', "SignupControllerTest1@$domain")
- ->orWhere('email', 'admin@external.com')
- ->delete();
+ $this->deleteTestDomain('external.com');
+ $this->deleteTestDomain('signup-domain.com');
- Domain::where('namespace', 'signup-domain.com')
- ->orWhere('namespace', 'external.com')
- ->delete();
+ parent::tearDown();
}
/**
* Return a public domain for signup tests
*/
- public function getPublicDomain(): string
+ private function getPublicDomain(): string
{
- if (!self::$domain) {
+ if (!$this->domain) {
$this->refreshApplication();
$public_domains = Domain::getPublicDomains();
- self::$domain = reset($public_domains);
+ $this->domain = reset($public_domains);
- if (empty(self::$domain)) {
- self::$domain = 'signup-domain.com';
+ if (empty($this->domain)) {
+ $this->domain = 'signup-domain.com';
Domain::create([
- 'namespace' => self::$domain,
+ 'namespace' => $this->domain,
'status' => Domain::STATUS_ACTIVE,
'type' => Domain::TYPE_PUBLIC,
]);
}
}
- return self::$domain;
+ return $this->domain;
}
/**
@@ -418,7 +422,7 @@
});
// Check if the code has been removed
- $this->assertNull(SignupCode::where($result['code'])->first());
+ $this->assertNull(SignupCode::where('code', $result['code'])->first());
// Check if the user has been created
$user = User::where('email', $identity)->first();
@@ -451,7 +455,7 @@
'plan' => 'group',
];
- $response = $this->post('/api/auth/signup/init', $data);
+ $response = $this->withoutMiddleware()->post('/api/auth/signup/init', $data);
$json = $response->json();
$response->assertStatus(200);
@@ -603,15 +607,17 @@
['administrator', $domain, false, ['login' => 'validation.loginexists']],
['sales', $domain, false, ['login' => 'validation.loginexists']],
['root', $domain, false, ['login' => 'validation.loginexists']],
+
// existing user
- ['SignupControllerTest1', $domain, false, ['login' => 'validation.loginexists']],
+ ['jack', 'kolab.org', true, ['domain' => 'validation.domainexists']],
// Domain account
['admin', 'kolabsys.com', true, null],
['testnonsystemdomain', 'invalid', true, ['domain' => 'validation.domaininvalid']],
['testnonsystemdomain', '.com', true, ['domain' => 'validation.domaininvalid']],
+
// existing user
- ['SignupControllerTest1', $domain, true, ['domain' => 'validation.domainexists']],
+ ['john', 'kolab.org', true, ['domain' => 'validation.domainexists']],
];
}
@@ -630,6 +636,6 @@
$result = $method->invoke(new SignupController(), $login, $domain, $external);
- $this->assertSame($expected_result, $result);
+ $this->assertSame($expected_result, $result, var_export(func_get_args(), true));
}
}
diff --git a/src/tests/Feature/Controller/UsersTest.php b/src/tests/Feature/Controller/UsersTest.php
--- a/src/tests/Feature/Controller/UsersTest.php
+++ b/src/tests/Feature/Controller/UsersTest.php
@@ -17,8 +17,16 @@
{
parent::setUp();
- User::where('email', 'UsersControllerTest1@userscontroller.com')->delete();
- Domain::where('namespace', 'userscontroller.com')->delete();
+ $this->deleteTestUser('UsersControllerTest1@userscontroller.com');
+ $this->deleteTestDomain('userscontroller.com');
+ }
+
+ public function tearDown(): void
+ {
+ $this->deleteTestUser('UsersControllerTest1@userscontroller.com');
+ $this->deleteTestDomain('userscontroller.com');
+
+ parent::tearDown();
}
/**
diff --git a/src/tests/Feature/DomainOwnerTest.php b/src/tests/Feature/DomainOwnerTest.php
new file mode 100644
--- /dev/null
+++ b/src/tests/Feature/DomainOwnerTest.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace Tests\Feature;
+
+use App\Package;
+use App\User;
+use Illuminate\Support\Facades\Queue;
+use Tests\TestCase;
+
+class DomainOwnerTest extends TestCase
+{
+ public function setUp(): void
+ {
+ parent::setUp();
+ User::where('email', 'jane@kolab.org')->forceDelete();
+ }
+
+ public function testJohnCreateJane(): void
+ {
+ $john = User::where('email', 'john@kolab.org')->first();
+
+ $jane = User::create(
+ [
+ 'name' => 'Jane Doe',
+ 'email' => 'jane@kolab.org',
+ 'password' => 'simple123',
+ 'email_verified_at' => now()
+ ]
+ );
+
+ $package = Package::where('title', 'kolab')->first();
+
+ $john->assignPackage($package, $jane);
+
+ // assert jane has a mailbox entitlement
+ $this->assertTrue($jane->entitlements->count() == 4);
+ }
+
+ public function tearDown(): void
+ {
+ User::where('email', 'jane@kolab.org')->forceDelete();
+ parent::tearDown();
+ }
+}
diff --git a/src/tests/Feature/DomainTest.php b/src/tests/Feature/DomainTest.php
--- a/src/tests/Feature/DomainTest.php
+++ b/src/tests/Feature/DomainTest.php
@@ -13,21 +13,28 @@
class DomainTest extends TestCase
{
+ private $domains = [
+ 'public-active.com',
+ 'gmail.com',
+ 'ci-success-cname.kolab.org',
+ 'ci-success-txt.kolab.org',
+ 'ci-failure-cname.kolab.org',
+ 'ci-failure-txt.kolab.org',
+ 'ci-failure-none.kolab.org',
+ ];
+
public function setUp(): void
{
parent::setUp();
- $domains = [
- 'public-active.com',
- 'gmail.com',
- 'ci-success-cname.kolab.org',
- 'ci-success-txt.kolab.org',
- 'ci-failure-cname.kolab.org',
- 'ci-failure-txt.kolab.org',
- 'ci-failure-none.kolab.org',
- ];
-
- Domain::whereIn('namespace', $domains)->delete();
+ Domain::withTrashed()->whereIn('namespace', $this->domains)->forceDelete();
+ }
+
+ public function tearDown(): void
+ {
+ Domain::whereIn('namespace', $this->domains)->delete();
+
+ parent::tearDown();
}
/**
@@ -52,25 +59,9 @@
return $job_domain->id === $domain->id
&& $job_domain->namespace === $domain->namespace;
});
-/*
- Queue::assertPushedWithChain(\App\Jobs\DomainCreate::class, [
- \App\Jobs\DomainVerify::class,
- ]);
-*/
-/*
- FIXME: Looks like we can't really do detailed assertions on chained jobs
- Another thing to consider is if we maybe should run these jobs
- independently (not chained) and make sure there's no race-condition
- in status update
-
- Queue::assertPushed(\App\Jobs\DomainVerify::class, 1);
- Queue::assertPushed(\App\Jobs\DomainVerify::class, function ($job) use ($domain) {
- $job_domain = TestCase::getObjectProperty($job, 'domain');
- return $job_domain->id === $domain->id
- && $job_domain->namespace === $domain->namespace;
- });
-*/
+ $job = new \App\Jobs\DomainCreate($domain);
+ $job->handle();
}
/**
diff --git a/src/tests/Feature/EntitlementTest.php b/src/tests/Feature/EntitlementTest.php
--- a/src/tests/Feature/EntitlementTest.php
+++ b/src/tests/Feature/EntitlementTest.php
@@ -15,9 +15,16 @@
{
parent::setUp();
- User::where('email', 'entitlement-test@kolabnow.com')
- ->orWhere('email', 'entitled-user@custom-domain.com')
- ->delete();
+ $this->deleteTestUser('entitlement-test@kolabnow.com');
+ $this->deleteTestUser('entitled-user@custom-domain.com');
+ }
+
+ public function tearDown(): void
+ {
+ $this->deleteTestUser('entitlement-test@kolabnow.com');
+ $this->deleteTestUser('entitled-user@custom-domain.com');
+
+ parent::tearDown();
}
/**
@@ -37,16 +44,14 @@
]
);
- $this->assertTrue($owner->id != $user->id);
-
- $wallets = $owner->wallets()->get();
+ $wallet = $owner->wallets()->first();
$entitlement_own_mailbox = new Entitlement(
[
'owner_id' => $owner->id,
'entitleable_id' => $owner->id,
'entitleable_type' => User::class,
- 'wallet_id' => $wallets[0]->id,
+ 'wallet_id' => $wallet->id,
'sku_id' => $sku_mailbox->id,
'description' => "Owner Mailbox Entitlement Test"
]
@@ -57,7 +62,7 @@
'owner_id' => $owner->id,
'entitleable_id' => $domain->id,
'entitleable_type' => Domain::class,
- 'wallet_id' => $wallets[0]->id,
+ 'wallet_id' => $wallet->id,
'sku_id' => $sku_domain->id,
'description' => "User Domain Entitlement Test"
]
@@ -68,7 +73,7 @@
'owner_id' => $owner->id,
'entitleable_id' => $user->id,
'entitleable_type' => User::class,
- 'wallet_id' => $wallets[0]->id,
+ 'wallet_id' => $wallet->id,
'sku_id' => $sku_mailbox->id,
'description' => "User Mailbox Entitlement Test"
]
@@ -81,9 +86,43 @@
$this->assertTrue($owner->entitlements()->count() == 3);
$this->assertTrue($sku_domain->entitlements()->where('owner_id', $owner->id)->count() == 1);
$this->assertTrue($sku_mailbox->entitlements()->where('owner_id', $owner->id)->count() == 2);
- $this->assertTrue($wallets[0]->entitlements()->count() == 3);
- $this->assertTrue($wallets[0]->fresh()->balance < 0.00);
+ $this->assertTrue($wallet->entitlements()->count() == 3);
+ $this->assertTrue($wallet->fresh()->balance < 0.00);
+ }
+
+ public function testAddExistingEntitlement(): void
+ {
+ $this->markTestIncomplete();
+ }
+
+ public function testEntitlementFunctions(): void
+ {
+ $user = $this->getTestUser('entitlement-test@kolabnow.com');
+
+ $package = \App\Package::where('title', 'kolab')->first();
+
+ $user->assignPackage($package);
+
+ $wallet = $user->wallets()->first();
+ $this->assertNotNull($wallet);
+
+ $sku = \App\Sku::where('title', 'mailbox')->first();
+ $this->assertNotNull($sku);
+
+ $entitlement = Entitlement::where('owner_id', $user->id)->where('sku_id', $sku->id)->first();
+ $this->assertNotNull($entitlement);
+
+ $e_sku = $entitlement->sku;
+ $this->assertSame($sku->id, $e_sku->id);
+
+ $e_wallet = $entitlement->wallet;
+ $this->assertSame($wallet->id, $e_wallet->id);
+
+ $e_owner = $entitlement->owner;
+ $this->assertSame($user->id, $e_owner->id);
- // TODO: Test case of adding entitlement that already exists
+ $e_entitleable = $entitlement->entitleable;
+ $this->assertSame($user->id, $e_entitleable->id);
+ $this->assertTrue($e_entitleable instanceof \App\User);
}
}
diff --git a/src/tests/Feature/Jobs/DomainCreateTest.php b/src/tests/Feature/Jobs/DomainCreateTest.php
--- a/src/tests/Feature/Jobs/DomainCreateTest.php
+++ b/src/tests/Feature/Jobs/DomainCreateTest.php
@@ -5,6 +5,7 @@
use App\Jobs\DomainCreate;
use App\Domain;
use Illuminate\Support\Facades\Mail;
+use Illuminate\Support\Facades\Queue;
use Tests\TestCase;
class DomainCreateTest extends TestCase
@@ -16,7 +17,14 @@
{
parent::setUp();
- Domain::where('namespace', 'domain-create-test.com')->delete();
+ $this->deleteTestDomain('domain-create-test.com');
+ }
+
+ public function tearDown(): void
+ {
+ $this->deleteTestDomain('domain-create-test.com');
+
+ parent::tearDown();
}
/**
@@ -24,6 +32,8 @@
*/
public function testHandle(): void
{
+ Queue::fake();
+
$domain = $this->getTestDomain(
'domain-create-test.com',
[
@@ -34,12 +44,6 @@
$this->assertFalse($domain->isLdapReady());
- $mock = \Mockery::mock('alias:App\Backends\LDAP');
- $mock->shouldReceive('createDomain')
- ->once()
- ->with($domain)
- ->andReturn(null);
-
$job = new DomainCreate($domain);
$job->handle();
diff --git a/src/tests/Feature/Jobs/DomainVerifyTest.php b/src/tests/Feature/Jobs/DomainVerifyTest.php
--- a/src/tests/Feature/Jobs/DomainVerifyTest.php
+++ b/src/tests/Feature/Jobs/DomainVerifyTest.php
@@ -18,7 +18,7 @@
Domain::where('namespace', 'gmail.com')
->orWhere('namespace', 'some-non-existing-domain.fff')
- ->delete();
+ ->forceDelete();
}
/**
diff --git a/src/tests/Feature/Jobs/PasswordResetEmailTest.php b/src/tests/Feature/Jobs/PasswordResetEmailTest.php
--- a/src/tests/Feature/Jobs/PasswordResetEmailTest.php
+++ b/src/tests/Feature/Jobs/PasswordResetEmailTest.php
@@ -38,7 +38,9 @@
*/
public function tearDown(): void
{
- $this->code->user->delete();
+ $this->code->user->forceDelete();
+
+ parent::tearDown();
}
/**
diff --git a/src/tests/Feature/Jobs/UserCreateTest.php b/src/tests/Feature/Jobs/UserCreateTest.php
--- a/src/tests/Feature/Jobs/UserCreateTest.php
+++ b/src/tests/Feature/Jobs/UserCreateTest.php
@@ -16,7 +16,7 @@
{
parent::setUp();
- User::where('email', 'new-job-user@' . \config('app.domain'))->delete();
+ $this->deleteTestUser('new-job-user@' . \config('app.domain'));
}
/**
@@ -28,11 +28,13 @@
$this->assertFalse($user->isLdapReady());
+ /*
$mock = \Mockery::mock('alias:App\Backends\LDAP');
$mock->shouldReceive('createUser')
->once()
->with($user)
->andReturn(null);
+ */
$job = new UserCreate($user);
$job->handle();
diff --git a/src/tests/Feature/Jobs/UserVerifyTest.php b/src/tests/Feature/Jobs/UserVerifyTest.php
--- a/src/tests/Feature/Jobs/UserVerifyTest.php
+++ b/src/tests/Feature/Jobs/UserVerifyTest.php
@@ -16,7 +16,7 @@
{
parent::setUp();
- User::where('email', 'new-job-user@' . \config('app.domain'))->delete();
+ User::where('email', 'new-job-user@' . \config('app.domain'))->forceDelete();
}
/**
@@ -28,24 +28,9 @@
$this->assertFalse($user->isImapReady());
- $mock = \Mockery::mock('alias:App\Backends\IMAP');
- $mock->shouldReceive('verifyAccount')
- ->once()
- ->with($user->email)
- ->andReturn(false);
-
$job = new UserVerify($user);
$job->handle();
$this->assertTrue($user->fresh()->isImapReady() === false);
-
- $mock->shouldReceive('verifyAccount')
- ->once()
- ->with($user->email)
- ->andReturn(true);
-
- $job->handle();
-
- $this->assertTrue($user->fresh()->isImapReady());
}
}
diff --git a/src/tests/Feature/SkuTest.php b/src/tests/Feature/SkuTest.php
--- a/src/tests/Feature/SkuTest.php
+++ b/src/tests/Feature/SkuTest.php
@@ -5,7 +5,6 @@
use App\Domain;
use App\Entitlement;
use App\Handlers;
-use App\Quota;
use App\Sku;
use App\User;
use Tests\TestCase;
@@ -17,8 +16,16 @@
{
parent::setUp();
- User::where('email', 'sku-test-user@custom-domain.com')->delete();
- Domain::where('namespace', 'custom-domain.com')->delete();
+ $this->deleteTestUser('sku-test-user@custom-domain.com');
+ $this->deleteTestDomain('custom-domain.com');
+ }
+
+ public function tearDown(): void
+ {
+ $this->deleteTestUser('sku-test-user@custom-domain.com');
+ $this->deleteTestDomain('custom-domain.com');
+
+ parent::tearDown();
}
/**
@@ -35,13 +42,24 @@
]
);
+ \Log::debug(var_export($domain->toArray(), true));
+
$user = $this->getTestUser('sku-test-user@custom-domain.com');
$wallet = $user->wallets()->first();
// \App\Handlers\Mailbox SKU
- // Note, we're testing mailbox SKU before domain SKU as it may potentially fail in that order
+ // Note, we're testing mailbox SKU before domain SKU as it may potentially fail in that
+ // order
$sku = Sku::where('title', 'mailbox')->first();
- $sku->registerEntitlement($user);
+ Entitlement::create(
+ [
+ 'owner_id' => $user->id,
+ 'wallet_id' => $wallet->id,
+ 'sku_id' => $sku->id,
+ 'entitleable_id' => $user->id,
+ 'entitleable_type' => User::class
+ ]
+ );
$entitlements = $sku->entitlements()->where('owner_id', $user->id)->get();
$wallet->refresh();
@@ -50,7 +68,10 @@
$balance = -$sku->cost;
$this->assertCount(1, $entitlements);
$this->assertEquals($user->id, $entitlements[0]->entitleable_id);
- $this->assertSame(Handlers\Mailbox::entitleableClass(), $entitlements[0]->entitleable_type);
+ $this->assertSame(
+ Handlers\Mailbox::entitleableClass(),
+ $entitlements[0]->entitleable_type
+ );
} else {
$this->assertCount(0, $entitlements);
}
@@ -59,16 +80,40 @@
// \App\Handlers\Domain SKU
$sku = Sku::where('title', 'domain')->first();
- $sku->registerEntitlement($user, [$domain]);
+ Entitlement::create(
+ [
+ 'owner_id' => $user->id,
+ 'wallet_id' => $wallet->id,
+ 'sku_id' => $sku->id,
+ 'entitleable_id' => $domain->id,
+ 'entitleable_type' => Domain::class
+ ]
+ );
+
+ $entitlements = $sku->entitlements->where('owner_id', $user->id);
+
+ foreach ($entitlements as $entitlement) {
+ \Log::debug(var_export($entitlement->toArray(), true));
+ }
- $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get();
$wallet->refresh();
if ($sku->active) {
$balance -= $sku->cost;
$this->assertCount(1, $entitlements);
- $this->assertEquals($domain->id, $entitlements[0]->entitleable_id);
- $this->assertSame(Handlers\Domain::entitleableClass(), $entitlements[0]->entitleable_type);
+
+ $_domain = Domain::find($entitlements->first()->entitleable_id);
+
+ $this->assertEquals(
+ $domain->id,
+ $entitlements->first()->entitleable_id,
+ var_export($_domain->toArray(), true)
+ );
+
+ $this->assertSame(
+ Handlers\Domain::entitleableClass(),
+ $entitlements->first()->entitleable_type
+ );
} else {
$this->assertCount(0, $entitlements);
}
@@ -77,16 +122,27 @@
// \App\Handlers\DomainRegistration SKU
$sku = Sku::where('title', 'domain-registration')->first();
- $sku->registerEntitlement($user, [$domain]);
+ Entitlement::create(
+ [
+ 'owner_id' => $user->id,
+ 'wallet_id' => $user->wallets()->get()[0]->id,
+ 'sku_id' => $sku->id,
+ 'entitleable_id' => $domain->id,
+ 'entitleable_type' => Domain::class
+ ]
+ );
- $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get();
+ $entitlements = $sku->entitlements->where('owner_id', $user->id);
$wallet->refresh();
if ($sku->active) {
$balance -= $sku->cost;
$this->assertCount(1, $entitlements);
- $this->assertEquals($domain->id, $entitlements[0]->entitleable_id);
- $this->assertSame(Handlers\DomainRegistration::entitleableClass(), $entitlements[0]->entitleable_type);
+ $this->assertEquals($domain->id, $entitlements->first()->entitleable_id);
+ $this->assertSame(
+ Handlers\DomainRegistration::entitleableClass(),
+ $entitlements->first()->entitleable_type
+ );
} else {
$this->assertCount(0, $entitlements);
}
@@ -95,16 +151,27 @@
// \App\Handlers\DomainHosting SKU
$sku = Sku::where('title', 'domain-hosting')->first();
- $sku->registerEntitlement($user, [$domain]);
+ Entitlement::create(
+ [
+ 'owner_id' => $user->id,
+ 'wallet_id' => $wallet->id,
+ 'sku_id' => $sku->id,
+ 'entitleable_id' => $domain->id,
+ 'entitleable_type' => Domain::class
+ ]
+ );
- $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get();
+ $entitlements = $sku->entitlements->where('owner_id', $user->id);
$wallet->refresh();
if ($sku->active) {
$balance -= $sku->cost;
$this->assertCount(1, $entitlements);
- $this->assertEquals($domain->id, $entitlements[0]->entitleable_id);
- $this->assertSame(Handlers\DomainHosting::entitleableClass(), $entitlements[0]->entitleable_type);
+ $this->assertEquals($domain->id, $entitlements->first()->entitleable_id);
+ $this->assertSame(
+ Handlers\DomainHosting::entitleableClass(),
+ $entitlements->first()->entitleable_type
+ );
} else {
$this->assertCount(0, $entitlements);
}
@@ -113,16 +180,27 @@
// \App\Handlers\Groupware SKU
$sku = Sku::where('title', 'groupware')->first();
- $sku->registerEntitlement($user, [$domain]);
+ Entitlement::create(
+ [
+ 'owner_id' => $user->id,
+ 'wallet_id' => $user->wallets()->get()[0]->id,
+ 'sku_id' => $sku->id,
+ 'entitleable_id' => $user->id,
+ 'entitleable_type' => User::class
+ ]
+ );
- $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get();
+ $entitlements = $sku->entitlements->where('owner_id', $user->id);
$wallet->refresh();
if ($sku->active) {
$balance -= $sku->cost;
$this->assertCount(1, $entitlements);
- $this->assertEquals($user->id, $entitlements[0]->entitleable_id);
- $this->assertSame(Handlers\Mailbox::entitleableClass(), $entitlements[0]->entitleable_type);
+ $this->assertEquals($user->id, $entitlements->first()->entitleable_id);
+ $this->assertSame(
+ Handlers\Mailbox::entitleableClass(),
+ $entitlements->first()->entitleable_type
+ );
} else {
$this->assertCount(0, $entitlements);
}
@@ -131,22 +209,22 @@
// \App\Handlers\Storage SKU
$sku = Sku::where('title', 'storage')->first();
- $sku->registerEntitlement($user, [$domain]);
+ Entitlement::create(
+ [
+ 'owner_id' => $user->id,
+ 'wallet_id' => $wallet->id,
+ 'sku_id' => $sku->id,
+ 'entitleable_id' => $user->id,
+ 'entitleable_type' => User::class
+ ]
+ );
- $entitlements = $sku->entitlements()->where('owner_id', $user->id)->get();
+ $entitlements = $sku->entitlements->where('owner_id', $user->id);
$wallet->refresh();
if ($sku->active) {
$balance -= $sku->cost;
- // For Storage entitlement we expect additional Quota record
- $quota = Quota::where('user_id', $user->id)->first();
- $this->assertTrue(!empty($quota));
- // TODO: This should be a constant and/or config option, and probably
- // quota should not be in bytes
- $this->assertSame(2147483648, $quota->value);
$this->assertCount(1, $entitlements);
- $this->assertEquals($quota->id, $entitlements[0]->entitleable_id);
- $this->assertSame(Handlers\Storage::entitleableClass(), $entitlements[0]->entitleable_type);
} else {
$this->assertCount(0, $entitlements);
}
diff --git a/src/tests/Feature/UserTest.php b/src/tests/Feature/UserTest.php
--- a/src/tests/Feature/UserTest.php
+++ b/src/tests/Feature/UserTest.php
@@ -12,7 +12,20 @@
{
parent::setUp();
- User::where('email', 'user-create-test@' . \config('app.domain'))->delete();
+ $this->deleteTestUser('user-create-test@' . \config('app.domain'));
+ $this->deleteTestUser('UserAccountA@UserAccount.com');
+ $this->deleteTestUser('UserAccountB@UserAccount.com');
+ $this->deleteTestUser('userdeletejob@kolabnow.com');
+ }
+
+ public function tearDown(): void
+ {
+ $this->deleteTestUser('user-create-test@' . \config('app.domain'));
+ $this->deleteTestUser('UserAccountA@UserAccount.com');
+ $this->deleteTestUser('UserAccountB@UserAccount.com');
+ $this->deleteTestUser('userdeletejob@kolabnow.com');
+
+ parent::tearDown();
}
/**
@@ -87,6 +100,43 @@
$this->assertContains('kolab.org', $domains);
}
+ public function testUserQuota(): void
+ {
+ $user = $this->getTestUser('john@kolab.org');
+ $storage_sku = \App\Sku::where('title', 'storage')->first();
+
+ $count = 0;
+
+ foreach ($user->entitlements()->get() as $entitlement) {
+ if ($entitlement->sku_id == $storage_sku->id) {
+ $count += 1;
+ }
+ }
+
+ $this->assertTrue($count == 2);
+ }
+
+ /**
+ * Test user deletion
+ */
+ public function testUserDelete(): void
+ {
+ $user = $this->getTestUser('userdeletejob@kolabnow.com');
+
+ $package = \App\Package::where('title', 'kolab')->first();
+
+ $user->assignPackage($package);
+
+ $id = $user->id;
+
+ $user->delete();
+
+ $job = new \App\Jobs\UserDelete($id);
+ $job->handle();
+
+ $user->forceDelete();
+ }
+
/**
* Tests for User::findByEmail()
*/
diff --git a/src/tests/Feature/WalletTest.php b/src/tests/Feature/WalletTest.php
--- a/src/tests/Feature/WalletTest.php
+++ b/src/tests/Feature/WalletTest.php
@@ -27,14 +27,14 @@
parent::setUp();
foreach ($this->users as $user) {
- User::where('email', $user)->delete();
+ $this->deleteTestUser($user);
}
}
public function tearDown(): void
{
foreach ($this->users as $user) {
- User::where('email', $user)->delete();
+ $this->deleteTestUser($user);
}
}
@@ -138,7 +138,10 @@
}
);
- $this->assertTrue($userB->accounts()->count() == 1);
+ $this->assertTrue(
+ $userB->accounts()->count() == 1,
+ "number of accounts (1 expected): {$userB->accounts()->count()}"
+ );
$aWallet = $userA->wallets()->get();
$bAccount = $userB->accounts()->get();
diff --git a/src/tests/TestCase.php b/src/tests/TestCase.php
--- a/src/tests/TestCase.php
+++ b/src/tests/TestCase.php
@@ -11,6 +11,35 @@
{
use CreatesApplication;
+ protected function deleteTestDomain($name)
+ {
+ Queue::fake();
+ $domain = Domain::withTrashed()->where('namespace', $name)->first();
+ if (!$domain) {
+ return;
+ }
+
+ $job = new \App\Jobs\DomainDelete($domain);
+ $job->handle();
+
+ $domain->forceDelete();
+ }
+
+ protected function deleteTestUser($email)
+ {
+ Queue::fake();
+ $user = User::withTrashed()->where('email', $email)->first();
+
+ if (!$user) {
+ return;
+ }
+
+ $job = new \App\Jobs\UserDelete($user->id);
+ $job->handle();
+
+ $user->forceDelete();
+ }
+
/**
* Get Domain object by namespace, create it if needed.
* Skip LDAP jobs.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 6, 6:58 PM (9 h, 41 m ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18838900
Default Alt Text
D949.1775501915.diff (86 KB)
Attached To
Mode
D949: Show functioning without quota table
Attached
Detach File
Event Timeline