Changeset View
Changeset View
Standalone View
Standalone View
src/app/User.php
<?php | <?php | ||||
namespace App; | namespace App; | ||||
use Illuminate\Notifications\Notifiable; | use Illuminate\Notifications\Notifiable; | ||||
use Illuminate\Contracts\Auth\MustVerifyEmail; | use Illuminate\Contracts\Auth\MustVerifyEmail; | ||||
use Illuminate\Database\Eloquent\SoftDeletes; | |||||
use Illuminate\Foundation\Auth\User as Authenticatable; | use Illuminate\Foundation\Auth\User as Authenticatable; | ||||
use Iatstuti\Database\Support\NullableFields; | use Iatstuti\Database\Support\NullableFields; | ||||
use Tymon\JWTAuth\Contracts\JWTSubject; | use Tymon\JWTAuth\Contracts\JWTSubject; | ||||
use App\Traits\UserSettingsTrait; | use App\Traits\UserSettingsTrait; | ||||
/** | /** | ||||
* The eloquent definition of a User. | * The eloquent definition of a User. | ||||
* | |||||
* @property integer $id | |||||
* @property integer $status | |||||
*/ | */ | ||||
class User extends Authenticatable implements JWTSubject | class User extends Authenticatable implements JWTSubject | ||||
{ | { | ||||
use Notifiable; | use Notifiable; | ||||
use NullableFields; | use NullableFields; | ||||
use UserSettingsTrait; | use UserSettingsTrait; | ||||
use SoftDeletes; | |||||
// a new user, default on creation | // a new user, default on creation | ||||
public const STATUS_NEW = 1 << 0; | public const STATUS_NEW = 1 << 0; | ||||
// it's been activated | // it's been activated | ||||
public const STATUS_ACTIVE = 1 << 1; | public const STATUS_ACTIVE = 1 << 1; | ||||
// user has been suspended | // user has been suspended | ||||
public const STATUS_SUSPENDED = 1 << 2; | public const STATUS_SUSPENDED = 1 << 2; | ||||
// user has been deleted | // user has been deleted | ||||
▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | class User extends Authenticatable implements JWTSubject | ||||
*/ | */ | ||||
protected $casts = [ | protected $casts = [ | ||||
'email_verified_at' => 'datetime', | 'email_verified_at' => 'datetime', | ||||
]; | ]; | ||||
/** | /** | ||||
* Any wallets on which this user is a controller. | * Any wallets on which this user is a controller. | ||||
* | * | ||||
* @return Wallet[] | * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | ||||
*/ | */ | ||||
public function accounts() | public function accounts() | ||||
{ | { | ||||
return $this->belongsToMany( | return $this->belongsToMany( | ||||
'App\Wallet', // The foreign object definition | 'App\Wallet', // The foreign object definition | ||||
'user_accounts', // The table name | 'user_accounts', // The table name | ||||
'user_id', // The local foreign key | 'user_id', // The local foreign key | ||||
'wallet_id' // The remote 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 The package to assign. | |||||
* @param \App\User|null $user Assign the package to another user. | |||||
machniak: The $user argument can be a domain object too. And I see the method body is still not aware of… | |||||
* | |||||
* @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; | |||||
} | |||||
public function assignPlan($plan, $domain = null) | |||||
{ | |||||
$this->setSetting('plan_id', $plan->id); | |||||
foreach ($plan->packages as $package) { | |||||
if ($package->isDomain()) { | |||||
$domain->assignPackage($package, $this); | |||||
} else { | |||||
$this->assignPackage($package); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* List the domains to which this user is entitled. | * List the domains to which this user is entitled. | ||||
* | * | ||||
* @return Domain[] | * @return Domain[] | ||||
*/ | */ | ||||
public function domains() | public function domains() | ||||
{ | { | ||||
$domains = Domain::whereRaw( | $dbdomains = Domain::whereRaw( | ||||
sprintf( | sprintf( | ||||
'(type & %s) AND (status & %s)', | '(type & %s) AND (status & %s)', | ||||
Domain::TYPE_PUBLIC, | Domain::TYPE_PUBLIC, | ||||
Domain::STATUS_ACTIVE | Domain::STATUS_ACTIVE | ||||
) | ) | ||||
)->get(); | )->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) { | if ($entitlement->entitleable instanceof Domain) { | ||||
$domain = Domain::find($entitlement->entitleable_id); | $domain = $entitlement->entitleable; | ||||
\Log::info("Found domain {$domain->namespace}"); | \Log::info("Found domain for {$this->email}: {$domain->namespace} (owned)"); | ||||
$domains[] = $domain; | $domains[] = $domain; | ||||
} | } | ||||
} | } | ||||
foreach ($this->accounts()->get() as $wallet) { | foreach ($this->accounts as $wallet) { | ||||
foreach ($wallet->entitlements()->get() as $entitlement) { | foreach ($wallet->entitlements as $entitlement) { | ||||
if ($entitlement->entitleable instanceof Domain) { | if ($entitlement->entitleable instanceof Domain) { | ||||
$domain = Domain::find($entitlement->entitleable_id); | $domain = $entitlement->entitleable; | ||||
\Log::info("Found domain {$domain->namespace}"); | \Log::info("Found domain {$this->email}: {$domain->namespace} (charged)"); | ||||
$domains[] = $domain; | $domains[] = $domain; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
return $domains; | return $domains; | ||||
} | } | ||||
public function entitlement() | public function entitlement() | ||||
{ | { | ||||
return $this->morphOne('App\Entitlement', 'entitleable'); | return $this->morphOne('App\Entitlement', 'entitleable'); | ||||
} | } | ||||
/** | /** | ||||
* Entitlements for this user. | * 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() | public function entitlements() | ||||
{ | { | ||||
return $this->hasMany('App\Entitlement', 'owner_id', 'id'); | return $this->hasMany('App\Entitlement', 'entitleable_id', 'id'); | ||||
Not Done Inline ActionsWithout checking entitleable_type this may return wrong results, I guess. Also, that method might end up to be not that useful if it does not return the domain entitlement. Something's looking fishy or just unfinished here. machniak: Without checking entitleable_type this may return wrong results, I guess. Also, that method… | |||||
} | } | ||||
public function addEntitlement($entitlement) | public function addEntitlement($entitlement) | ||||
{ | { | ||||
// FIXME: This contains() check looks fishy | if (!$this->entitlements->contains($entitlement)) { | ||||
if (!$this->entitlements()->get()->contains($entitlement)) { | |||||
return $this->entitlements()->save($entitlement); | return $this->entitlements()->save($entitlement); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Helper to find user by email address, whether it is | * Helper to find user by email address, whether it is | ||||
* main email address, alias or external email | * main email address, alias or external email | ||||
* | * | ||||
Show All 26 Lines | class User extends Authenticatable implements JWTSubject | ||||
/** | /** | ||||
* Returns whether this domain is active. | * Returns whether this domain is active. | ||||
* | * | ||||
* @return bool | * @return bool | ||||
*/ | */ | ||||
public function isActive(): bool | public function isActive(): bool | ||||
{ | { | ||||
return $this->status & self::STATUS_ACTIVE; | return ($this->status & self::STATUS_ACTIVE) == true; | ||||
} | } | ||||
/** | /** | ||||
* Returns whether this domain is deleted. | * Returns whether this domain is deleted. | ||||
* | * | ||||
* @return bool | * @return bool | ||||
*/ | */ | ||||
public function isDeleted(): bool | public function isDeleted(): bool | ||||
{ | { | ||||
return $this->status & self::STATUS_DELETED; | return ($this->status & self::STATUS_DELETED) == true; | ||||
} | } | ||||
/** | /** | ||||
* Returns whether this (external) domain has been verified | * Returns whether this (external) domain has been verified | ||||
Done Inline ActionsReally? One-liner looked much better. machniak: Really? One-liner looked much better. | |||||
Done Inline ActionsYeah, I did the one-liner for app/Domain.php. vanmeeuwen: Yeah, I did the one-liner for `app/Domain.php`. | |||||
* to exist in DNS. | * to exist in DNS. | ||||
* | * | ||||
* @return bool | * @return bool | ||||
*/ | */ | ||||
public function isImapReady(): bool | public function isImapReady(): bool | ||||
{ | { | ||||
return $this->status & self::STATUS_IMAP_READY; | return ($this->status & self::STATUS_IMAP_READY) == true; | ||||
} | } | ||||
/** | /** | ||||
* Returns whether this user is registered in LDAP. | * Returns whether this user is registered in LDAP. | ||||
* | * | ||||
* @return bool | * @return bool | ||||
*/ | */ | ||||
public function isLdapReady(): bool | public function isLdapReady(): bool | ||||
{ | { | ||||
return $this->status & self::STATUS_LDAP_READY; | return ($this->status & self::STATUS_LDAP_READY) == true; | ||||
} | } | ||||
/** | /** | ||||
* Returns whether this user is new. | * Returns whether this user is new. | ||||
* | * | ||||
* @return bool | * @return bool | ||||
*/ | */ | ||||
public function isNew(): bool | public function isNew(): bool | ||||
{ | { | ||||
return $this->status & self::STATUS_NEW; | return ($this->status & self::STATUS_NEW) == true; | ||||
} | } | ||||
/** | /** | ||||
* Returns whether this domain is suspended. | * Returns whether this domain is suspended. | ||||
* | * | ||||
* @return bool | * @return bool | ||||
*/ | */ | ||||
public function isSuspended(): bool | public function isSuspended(): bool | ||||
{ | { | ||||
return $this->status & self::STATUS_SUSPENDED; | return ($this->status & self::STATUS_SUSPENDED) == true; | ||||
} | } | ||||
/** | /** | ||||
* Any (additional) properties of this user. | * Any (additional) properties of this user. | ||||
* | * | ||||
* @return \App\UserSetting[] | * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
*/ | */ | ||||
public function settings() | public function settings() | ||||
{ | { | ||||
return $this->hasMany('App\UserSetting', 'user_id'); | return $this->hasMany('App\UserSetting', 'user_id'); | ||||
} | } | ||||
/** | /** | ||||
* Verification codes for this user. | * Verification codes for this user. | ||||
* | * | ||||
* @return VerificationCode[] | * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
*/ | */ | ||||
public function verificationcodes() | public function verificationcodes() | ||||
{ | { | ||||
return $this->hasMany('App\VerificationCode', 'user_id', 'id'); | return $this->hasMany('App\VerificationCode', 'user_id', 'id'); | ||||
} | } | ||||
/** | /** | ||||
* Wallets this user owns. | * Wallets this user owns. | ||||
* | * | ||||
* @return Wallet[] | * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
*/ | */ | ||||
public function wallets() | public function wallets() | ||||
{ | { | ||||
return $this->hasMany('App\Wallet'); | return $this->hasMany('App\Wallet'); | ||||
} | } | ||||
/** | |||||
* User password mutator | |||||
* | |||||
* @param string $password The password in plain text. | |||||
* | |||||
* @return void | |||||
*/ | |||||
public function setPasswordAttribute($password) | public function setPasswordAttribute($password) | ||||
{ | { | ||||
if (!empty($password)) { | if (!empty($password)) { | ||||
$this->attributes['password'] = bcrypt($password, [ "rounds" => 12 ]); | $this->attributes['password'] = bcrypt($password, [ "rounds" => 12 ]); | ||||
$this->attributes['password_ldap'] = '{SSHA512}' . base64_encode( | $this->attributes['password_ldap'] = '{SSHA512}' . base64_encode( | ||||
pack('H*', hash('sha512', $password)) | pack('H*', hash('sha512', $password)) | ||||
); | ); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* User LDAP password mutator | |||||
* | |||||
* @param string $password The password in plain text. | |||||
* | |||||
* @return void | |||||
*/ | |||||
public function setPasswordLdapAttribute($password) | public function setPasswordLdapAttribute($password) | ||||
{ | { | ||||
if (!empty($password)) { | if (!empty($password)) { | ||||
$this->attributes['password'] = bcrypt($password, [ "rounds" => 12 ]); | $this->attributes['password'] = bcrypt($password, [ "rounds" => 12 ]); | ||||
$this->attributes['password_ldap'] = '{SSHA512}' . base64_encode( | $this->attributes['password_ldap'] = '{SSHA512}' . base64_encode( | ||||
pack('H*', hash('sha512', $password)) | pack('H*', hash('sha512', $password)) | ||||
); | ); | ||||
} | } | ||||
Show All 34 Lines |
The $user argument can be a domain object too. And I see the method body is still not aware of that.