Changeset View
Changeset View
Standalone View
Standalone View
src/app/User.php
<?php | <?php | ||||
namespace App; | namespace App; | ||||
use App\Entitlement; | |||||
use App\UserAlias; | use App\UserAlias; | ||||
use App\Traits\UserAliasesTrait; | use App\Traits\UserAliasesTrait; | ||||
use App\Traits\UserSettingsTrait; | use App\Traits\UserSettingsTrait; | ||||
use App\Wallet; | |||||
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\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; | ||||
/** | /** | ||||
▲ Show 20 Lines • Show All 68 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. | ||||
* | * | ||||
* This does not include wallets owned by the user. | |||||
* | |||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | * @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 | ||||
Show All 40 Lines | public function assignPackage($package, $user = null) | ||||
] | ] | ||||
); | ); | ||||
} | } | ||||
} | } | ||||
return $user; | 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); | |||||
} | |||||
} | |||||
} | |||||
/** | /** | ||||
* Returns user controlling the current user (or self when it's the account owner) | * Check if current user can delete another object. | ||||
* | |||||
* @param \App\User|\App\Domain $object A user|domain object | |||||
* | * | ||||
* @return \App\User A user object | * @return bool True if he can, False otherwise | ||||
*/ | */ | ||||
public function controller(): User | public function canDelete($object): bool | ||||
{ | { | ||||
// FIXME: This is most likely not the best way to do this | if (!method_exists($object, 'wallet')) { | ||||
$entitlement = \App\Entitlement::where([ | return false; | ||||
'entitleable_id' => $this->id, | |||||
'entitleable_type' => User::class | |||||
])->first(); | |||||
if ($entitlement && $entitlement->owner_id != $this->id) { | |||||
return $entitlement->owner; | |||||
} | } | ||||
return $this; | $wallet = $object->wallet(); | ||||
// TODO: For now controller can delete/update the account owner, | |||||
// this may change in future, controllers are not 0-regression feature | |||||
return $this->wallets->contains($wallet) || $this->accounts->contains($wallet); | |||||
} | } | ||||
public function assignPlan($plan, $domain = null) | /** | ||||
* Check if current user can read data of another object. | |||||
* | |||||
* @param \App\User|\App\Domain $object A user|domain object | |||||
* | |||||
* @return bool True if he can, False otherwise | |||||
*/ | |||||
public function canRead($object): bool | |||||
{ | { | ||||
$this->setSetting('plan_id', $plan->id); | if (!method_exists($object, 'wallet')) { | ||||
return false; | |||||
} | |||||
foreach ($plan->packages as $package) { | if ($object instanceof User && $this->id == $object->id) { | ||||
if ($package->isDomain()) { | return true; | ||||
$domain->assignPackage($package, $this); | |||||
} else { | |||||
$this->assignPackage($package); | |||||
} | } | ||||
$wallet = $object->wallet(); | |||||
return $this->wallets->contains($wallet) || $this->accounts->contains($wallet); | |||||
} | } | ||||
/** | |||||
* Check if current user can update data of another object. | |||||
* | |||||
* @param \App\User|\App\Domain $object A user|domain object | |||||
* | |||||
* @return bool True if he can, False otherwise | |||||
*/ | |||||
public function canUpdate($object): bool | |||||
{ | |||||
if (!method_exists($object, 'wallet')) { | |||||
return false; | |||||
} | |||||
if ($object instanceof User && $this->id == $object->id) { | |||||
return true; | |||||
} | |||||
return $this->canDelete($object); | |||||
} | } | ||||
/** | /** | ||||
* 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() | ||||
▲ Show 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | class User extends Authenticatable implements JWTSubject | ||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany | * @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'); | ||||
} | } | ||||
/** | /** | ||||
* Return users controlled by the current user. | |||||
* | |||||
* Users assigned to wallets the current user controls or owns. | |||||
* | |||||
* @return \Illuminate\Database\Eloquent\Builder Query builder | |||||
*/ | |||||
public function users() | |||||
{ | |||||
$wallets = array_merge( | |||||
vanmeeuwen: This should really be:
```
return $this->select(['users.*', 'entitlements.wallet_id'])
```… | |||||
$this->wallets()->pluck('id')->all(), | |||||
$this->accounts()->pluck('wallet_id')->all() | |||||
); | |||||
return $this->select(['users.*', 'entitlements.wallet_id']) | |||||
->distinct() | |||||
->leftJoin('entitlements', 'entitlements.entitleable_id', '=', 'users.id') | |||||
->whereIn('entitlements.wallet_id', $wallets) | |||||
->where('entitlements.entitleable_type', 'App\User'); | |||||
} | |||||
/** | |||||
* Verification codes for this user. | * Verification codes for this user. | ||||
* | * | ||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany | * @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'); | ||||
} | } | ||||
/** | /** | ||||
* Returns the wallet by which the user is controlled | |||||
* | |||||
* @return \App\Wallet A wallet object | |||||
*/ | |||||
public function wallet(): Wallet | |||||
{ | |||||
$entitlement = $this->entitlement()->first(); | |||||
// TODO: No entitlement should not happen, but in tests we have | |||||
// such cases, so we fallback to the user's wallet in this case | |||||
return $entitlement ? $entitlement->wallet : $this->wallets()->first(); | |||||
} | |||||
/** | |||||
* Wallets this user owns. | * Wallets this user owns. | ||||
* | * | ||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany | * @return \Illuminate\Database\Eloquent\Relations\HasMany | ||||
*/ | */ | ||||
public function wallets() | public function wallets() | ||||
{ | { | ||||
return $this->hasMany('App\Wallet'); | return $this->hasMany('App\Wallet'); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 67 Lines • Show Last 20 Lines |
This should really be:
because Query\Builder::select() only supports 0-1 parameters (see phpstan output).