<?php
namespace Laravel\Passport;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Laravel\Passport\Database\Factories\ClientFactory;
class Client extends Model
{
use HasFactory;
use ResolvesInheritedScopes;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'oauth_clients';
/**
* The guarded attributes on the model.
*
* @var array
*/
protected $guarded = [];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = [
'secret',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'grant_types' => 'array',
'scopes' => 'array',
'personal_access_client' => 'bool',
'password_client' => 'bool',
'revoked' => 'bool',
];
/**
* The temporary plain-text client secret.
*
* @var string|null
*/
protected $plainSecret;
/**
* Bootstrap the model and its traits.
*
* @return void
*/
public static function boot()
{
parent::boot();
static::creating(function ($model) {
if (Passport::clientUuids()) {
$model->{$model->getKeyName()} = $model->{$model->getKeyName()} ?: (string) Str::orderedUuid();
}
});
}
/**
* Get the user that the client belongs to.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
$provider = $this->provider ?: config('auth.guards.api.provider');
return $this->belongsTo(
config("auth.providers.{$provider}.model")
);
}
/**
* Get all of the authentication codes for the client.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function authCodes()
{
return $this->hasMany(Passport::authCodeModel(), 'client_id');
}
/**
* Get all of the tokens that belong to the client.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function tokens()
{
return $this->hasMany(Passport::tokenModel(), 'client_id');
}
/**
* Get the grant types the client can use.
*
* @return array|null
*/
public function getGrantTypesAttribute()
{
return $this->attributes['grant_types'] ?? null;
}
/**
* Get the scopes for the client.
*
* @return array|null
*/
public function getScopesAttribute()
{
return $this->attributes['scopes'] ?? null;
}
/**
* Set the scopes for the client.
*
* @param array|null $scopes
* @return void
*/
public function setScopesAttribute(?array $scopes)
{
$this->attributes['scopes'] = $scopes;
}
/**
* The temporary non-hashed client secret.
*
* This is only available once during the request that created the client.
*
* @return string|null
*/
public function getPlainSecretAttribute()
{
return $this->plainSecret;
}
/**
* Set the value of the secret attribute.
*
* @param string|null $value
* @return void
*/
public function setSecretAttribute($value)
{
$this->plainSecret = $value;
if (is_null($value) || ! Passport::$hashesClientSecrets) {
$this->attributes['secret'] = $value;
return;
}
$this->attributes['secret'] = password_hash($value, PASSWORD_BCRYPT);
}
/**
* Determine if the client is a "first party" client.
*
* @return bool
*/
public function firstParty()
{
return $this->personal_access_client || $this->password_client;
}
/**
* Determine if the client should skip the authorization prompt.
*
* @return bool
*/
public function skipsAuthorization()
{
return false;
}
/**
* Determine whether the client has the given scope.
*
* @param string $scope
* @return bool
*/
public function hasScope($scope)
{
if (! is_array($this->scopes)) {
return true;
}
$scopes = Passport::$withInheritedScopes
? $this->resolveInheritedScopes($scope)
: [$scope];
foreach ($scopes as $scope) {
if (in_array($scope, $this->scopes)) {
return true;
}
}
return false;
}
/**
* Determine if the client is a confidential client.
*
* @return bool
*/
public function confidential()
{
return ! empty($this->secret);
}
/**
* Get the auto-incrementing key type.
*
* @return string
*/
public function getKeyType()
{
return Passport::clientUuids() ? 'string' : $this->keyType;
}
/**
* Get the value indicating whether the IDs are incrementing.
*
* @return bool
*/
public function getIncrementing()
{
return Passport::clientUuids() ? false : $this->incrementing;
}
/**
* Create a new factory instance for the model.
*
* @return \Illuminate\Database\Eloquent\Factories\Factory
*/
public static function newFactory()
{
return ClientFactory::new();
}
}