diff --git a/src/AuthCode.php b/src/AuthCode.php index 5a98ea19e..783b75950 100644 --- a/src/AuthCode.php +++ b/src/AuthCode.php @@ -38,6 +38,13 @@ class AuthCode extends Model 'expires_at', ]; + /** + * The client relation model. + * + * @var string + */ + protected static $clientModel = Client::class; + /** * Get the client that owns the authentication code. * @@ -45,6 +52,29 @@ class AuthCode extends Model */ public function client() { - return $this->hasMany(Client::class); + return $this->hasMany(static::$clientModel); + } + + /** + * Get the client model. + * + * @return mixed + */ + public static function getClientModel() + { + return static::$clientModel; + } + + /** + * Set the client model. + * + * @param mixed $clientModel + * @return static + */ + public static function setClientModel($clientModel) + { + static::$clientModel = $clientModel; + + return new static; } } diff --git a/src/AuthCodeRepository.php b/src/AuthCodeRepository.php new file mode 100644 index 000000000..2ad521dc0 --- /dev/null +++ b/src/AuthCodeRepository.php @@ -0,0 +1,86 @@ +createModel()->find($id); + } + + /** + * Store a new auth code. + * + * @param array $attributes + * @return AuthCode + */ + public function create(array $attributes) + { + $authCode = $this->createModel()->forceFill($attributes); + + $authCode->save(); + + return $authCode; + } + + /** + * Revoke an auth code. + * + * @param string $id + * @return bool|int + */ + public function revoke($id) + { + return $this->find($id)->update(['revoked' => true]); + } + + /** + * Determine if the given auth code is revoked. + * + * @param int $id + * @return bool + */ + public function revoked($id) + { + return $this->createModel() + ->where('id', $id) + ->where('revoked', true) + ->exists(); + } + + /** + * {@inheritdoc} + */ + public static function getModel() + { + return static::$model; + } + + /** + * {@inheritdoc} + */ + public static function setModel($model) + { + static::$model = $model; + + return new static; + } +} diff --git a/src/Bridge/AuthCodeRepository.php b/src/Bridge/AuthCodeRepository.php index 23cbe5bd0..36e519ad2 100644 --- a/src/Bridge/AuthCodeRepository.php +++ b/src/Bridge/AuthCodeRepository.php @@ -2,7 +2,7 @@ namespace Laravel\Passport\Bridge; -use Illuminate\Database\Connection; +use Laravel\Passport\AuthCodeRepository as AuthCodeModelRepository; use League\OAuth2\Server\Entities\AuthCodeEntityInterface; use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface; @@ -11,21 +11,21 @@ class AuthCodeRepository implements AuthCodeRepositoryInterface use FormatsScopesForStorage; /** - * The database connection. + * The auth code model repository. * - * @var \Illuminate\Database\Connection + * @var \Laravel\Passport\AuthCodeRepository */ - protected $database; + protected $authCodes; /** * Create a new repository instance. * - * @param \Illuminate\Database\Connection $database + * @param \Laravel\Passport\AuthCodeRepository $authCodes * @return void */ - public function __construct(Connection $database) + public function __construct(AuthCodeModelRepository $authCodes) { - $this->database = $database; + $this->authCodes = $authCodes; } /** @@ -41,7 +41,7 @@ public function getNewAuthCode() */ public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity) { - $this->database->table('oauth_auth_codes')->insert([ + $this->authCodes->create([ 'id' => $authCodeEntity->getIdentifier(), 'user_id' => $authCodeEntity->getUserIdentifier(), 'client_id' => $authCodeEntity->getClient()->getIdentifier(), @@ -56,8 +56,7 @@ public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity) */ public function revokeAuthCode($codeId) { - $this->database->table('oauth_auth_codes') - ->where('id', $codeId)->update(['revoked' => true]); + $this->authCodes->revoke($codeId); } /** @@ -65,7 +64,6 @@ public function revokeAuthCode($codeId) */ public function isAuthCodeRevoked($codeId) { - return $this->database->table('oauth_auth_codes') - ->where('id', $codeId)->where('revoked', 1)->exists(); + return $this->authCodes->revoked($codeId); } } diff --git a/src/Bridge/RefreshTokenRepository.php b/src/Bridge/RefreshTokenRepository.php index bd51e513c..b6b5237c0 100644 --- a/src/Bridge/RefreshTokenRepository.php +++ b/src/Bridge/RefreshTokenRepository.php @@ -2,28 +2,28 @@ namespace Laravel\Passport\Bridge; -use Illuminate\Database\Connection; +use Laravel\Passport\RefreshTokenRepository as RefreshTokenModelRepository; use League\OAuth2\Server\Entities\RefreshTokenEntityInterface; use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface; class RefreshTokenRepository implements RefreshTokenRepositoryInterface { /** - * The database connection. + * The refresh token model repository. * - * @var \Illuminate\Database\Connection + * @var \Laravel\Passport\RefreshTokenRepository */ - protected $database; + protected $refreshTokens; /** * Create a new repository instance. * - * @param \Illuminate\Database\Connection $database + * @param \Laravel\Passport\RefreshTokenRepository $refreshTokens * @return void */ - public function __construct(Connection $database) + public function __construct(RefreshTokenModelRepository $refreshTokens) { - $this->database = $database; + $this->refreshTokens = $refreshTokens; } /** @@ -39,7 +39,7 @@ public function getNewRefreshToken() */ public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity) { - $this->database->table('oauth_refresh_tokens')->insert([ + $this->refreshTokens->create([ 'id' => $refreshTokenEntity->getIdentifier(), 'access_token_id' => $refreshTokenEntity->getAccessToken()->getIdentifier(), 'revoked' => false, @@ -52,8 +52,7 @@ public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshToken */ public function revokeRefreshToken($tokenId) { - $this->database->table('oauth_refresh_tokens') - ->where('id', $tokenId)->update(['revoked' => true]); + $this->refreshTokens->revoke($tokenId); } /** @@ -61,7 +60,6 @@ public function revokeRefreshToken($tokenId) */ public function isRefreshTokenRevoked($tokenId) { - return $this->database->table('oauth_refresh_tokens') - ->where('id', $tokenId)->where('revoked', 1)->exists(); + return $this->refreshTokens->revoked($tokenId); } } diff --git a/src/Client.php b/src/Client.php index 00dbad2fa..41be68e32 100644 --- a/src/Client.php +++ b/src/Client.php @@ -40,6 +40,20 @@ class Client extends Model 'revoked' => 'bool', ]; + /** + * The auth code relation model. + * + * @var string + */ + protected static $authCodeModel = AuthCode::class; + + /** + * The access token relation model. + * + * @var string + */ + protected static $tokenModel = Token::class; + /** * Get all of the authentication codes for the client. * @@ -47,7 +61,7 @@ class Client extends Model */ public function authCodes() { - return $this->hasMany(AuthCode::class); + return $this->hasMany(static::$authCodeModel); } /** @@ -57,7 +71,7 @@ public function authCodes() */ public function tokens() { - return $this->hasMany(Token::class); + return $this->hasMany(static::$tokenModel); } /** @@ -69,4 +83,50 @@ public function firstParty() { return $this->personal_access_client || $this->password_client; } + + /** + * Get the auth code model. + * + * @return mixed + */ + public static function getAuthCodeModel() + { + return static::$authCodeModel; + } + + /** + * Set the auth code model. + * + * @param mixed $authCodeModel + * @return static + */ + public static function setAuthCodeModel($authCodeModel) + { + static::$authCodeModel = $authCodeModel; + + return new static; + } + + /** + * Get the token model. + * + * @return mixed + */ + public static function getTokenModel() + { + return static::$tokenModel; + } + + /** + * Set the token model. + * + * @param mixed $tokenModel + * @return static + */ + public static function setTokenModel($tokenModel) + { + static::$tokenModel = $tokenModel; + + return new static; + } } diff --git a/src/ClientRepository.php b/src/ClientRepository.php index 2be5a0754..bcffba47d 100644 --- a/src/ClientRepository.php +++ b/src/ClientRepository.php @@ -4,6 +4,22 @@ class ClientRepository { + use RepositoryHelper; + + /** + * The client model. + * + * @var string + */ + protected static $model = Client::class; + + /** + * The personal access client model. + * + * @var mixed + */ + protected static $personalAccessClientModel = PersonalAccessClient::class; + /** * Get a client by the given ID. * @@ -12,7 +28,7 @@ class ClientRepository */ public function find($id) { - return Client::find($id); + return $this->createModel()->find($id); } /** @@ -36,8 +52,10 @@ public function findActive($id) */ public function forUser($userId) { - return Client::where('user_id', $userId) - ->orderBy('name', 'desc')->get(); + return $this->createModel() + ->where('user_id', $userId) + ->orderBy('name', 'desc') + ->get(); } /** @@ -61,9 +79,9 @@ public function activeForUser($userId) public function personalAccessClient() { if (Passport::$personalAccessClient) { - return Client::find(Passport::$personalAccessClient); + return $this->find(Passport::$personalAccessClient); } else { - return PersonalAccessClient::orderBy('id', 'desc')->first()->client; + return $this->createPersonalAccessClientModel()->orderBy('id', 'desc')->first()->client; } } @@ -79,7 +97,7 @@ public function personalAccessClient() */ public function create($userId, $name, $redirect, $personalAccess = false, $password = false) { - $client = (new Client)->forceFill([ + $client = $this->createModel()->forceFill([ 'user_id' => $userId, 'name' => $name, 'secret' => str_random(40), @@ -160,8 +178,10 @@ public function regenerateSecret(Client $client) */ public function revoked($id) { - return Client::where('id', $id) - ->where('revoked', true)->exists(); + return $this->createModel() + ->where('id', $id) + ->where('revoked', true) + ->exists(); } /** @@ -176,4 +196,64 @@ public function delete(Client $client) $client->forceFill(['revoked' => true])->save(); } + + /** + * {@inheritdoc} + */ + public static function getModel() + { + return static::$model; + } + + /** + * {@inheritdoc} + */ + public static function setModel($model) + { + static::$model = $model; + + return new static; + } + + /** + * Get the personal access client model. + * + * @return mixed + */ + public static function getPersonalAccessClientModel() + { + return static::$personalAccessClientModel; + } + + /** + * Set the personal access client model. + * + * @param mixed $personalAccessClientModel + * @return static + */ + public static function setPersonalAccessClientModel($personalAccessClientModel) + { + static::$personalAccessClientModel = $personalAccessClientModel; + + return new static; + } + + /** + * Create a new personal access client model instance. + * + * @param array $attributes Optional array of model attributes. + * @return mixed + */ + public function createPersonalAccessClientModel(array $attributes = []) + { + if (is_string($model = $this->getPersonalAccessClientModel())) { + if (! class_exists($class = '\\'.ltrim($model, '\\'))) { + throw new RuntimeException("Class {$model} does not exist!"); + } + + $model = new $model($attributes); + } + + return $model; + } } diff --git a/src/PersonalAccessClient.php b/src/PersonalAccessClient.php index 03a672b5b..c07fe29df 100644 --- a/src/PersonalAccessClient.php +++ b/src/PersonalAccessClient.php @@ -20,6 +20,13 @@ class PersonalAccessClient extends Model */ protected $guarded = []; + /** + * The client relation model. + * + * @var string + */ + protected static $clientModel = Client::class; + /** * Get all of the authentication codes for the client. * @@ -27,6 +34,29 @@ class PersonalAccessClient extends Model */ public function client() { - return $this->belongsTo(Client::class); + return $this->belongsTo(static::$clientModel); + } + + /** + * Get the client model. + * + * @return mixed + */ + public static function getClientModel() + { + return static::$clientModel; + } + + /** + * Set the client model. + * + * @param mixed $clientModel + * @return static + */ + public static function setClientModel($clientModel) + { + static::$clientModel = $clientModel; + + return new static; } } diff --git a/src/RefreshToken.php b/src/RefreshToken.php new file mode 100644 index 000000000..df4a17603 --- /dev/null +++ b/src/RefreshToken.php @@ -0,0 +1,114 @@ + 'bool', + ]; + + /** + * The attributes that should be mutated to dates. + * + * @var array + */ + protected $dates = [ + 'expires_at', + ]; + + /** + * Indicates if the model should be timestamped. + * + * @var bool + */ + public $timestamps = false; + + /** + * The access token relation model. + * + * @var string + */ + protected static $tokenModel = Token::class; + + /** + * Get the access token that the refresh token belongs to. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function accessToken() + { + return $this->belongsTo(static::$tokenModel); + } + + /** + * Revoke the token instance. + * + * @return void + */ + public function revoke() + { + $this->forceFill(['revoked' => true])->save(); + } + + /** + * Determine if the token is a transient JWT token. + * + * @return bool + */ + public function transient() + { + return false; + } + + /** + * Get the token model. + * + * @return mixed + */ + public static function getTokenModel() + { + return static::$tokenModel; + } + + /** + * Set the token model. + * + * @param mixed $tokenModel + * @return static + */ + public static function setTokenModel($tokenModel) + { + static::$tokenModel = $tokenModel; + + return new static; + } +} diff --git a/src/RefreshTokenRepository.php b/src/RefreshTokenRepository.php new file mode 100644 index 000000000..429b0eeb5 --- /dev/null +++ b/src/RefreshTokenRepository.php @@ -0,0 +1,84 @@ +createModel()->find($id); + } + + /** + * Creates a new Access Token + * + * @param array $attributes + * @return RefreshToken + */ + public function create(array $attributes) + { + $authCode = $this->createModel() + ->forceFill($attributes) + ->save(); + + return $authCode; + } + + /** + * Revoke a refresh token. + * + * @param string $id + * @return bool|int + */ + public function revoke($id) + { + return $this->find($id)->update(['revoked' => true]); + } + + /** + * Check if the given refresh token has been revoked. + * + * @param string $id + * @return bool + */ + public function revoked($id) + { + return $this->createModel() + ->where('id', $id) + ->where('revoked', 1) + ->exists(); + } + + /** + * {@inheritdoc} + */ + public static function getModel() + { + return static::$model; + } + + /** + * {@inheritdoc} + */ + public static function setModel($model) + { + static::$model = $model; + + return new static; + } +} diff --git a/src/RepositoryHelper.php b/src/RepositoryHelper.php new file mode 100644 index 000000000..80beff457 --- /dev/null +++ b/src/RepositoryHelper.php @@ -0,0 +1,27 @@ +getModel())) { + if (! class_exists($class = '\\'.ltrim($model, '\\'))) { + throw new RuntimeException("Class {$model} does not exist!"); + } + + $model = new $model($attributes); + } + + return $model; + } +} diff --git a/src/Token.php b/src/Token.php index 3064a130f..80e71138d 100644 --- a/src/Token.php +++ b/src/Token.php @@ -53,6 +53,13 @@ class Token extends Model */ public $timestamps = false; + /** + * The client relation model. + * + * @var string + */ + protected static $clientModel = Client::class; + /** * Get the client that the token belongs to. * @@ -60,7 +67,7 @@ class Token extends Model */ public function client() { - return $this->belongsTo(Client::class); + return $this->belongsTo(static::$clientModel); } /** @@ -105,4 +112,27 @@ public function transient() { return false; } + + /** + * Get the client model. + * + * @return mixed + */ + public static function getClientModel() + { + return static::$clientModel; + } + + /** + * Set the client model. + * + * @param mixed $clientModel + * @return static + */ + public static function setClientModel($clientModel) + { + static::$clientModel = $clientModel; + + return new static; + } } diff --git a/src/TokenRepository.php b/src/TokenRepository.php index b07005725..b92af6556 100644 --- a/src/TokenRepository.php +++ b/src/TokenRepository.php @@ -4,6 +4,15 @@ class TokenRepository { + use RepositoryHelper; + + /** + * The access token model. + * + * @var string + */ + protected static $model = Token::class; + /** * Creates a new Access Token * @@ -12,7 +21,7 @@ class TokenRepository */ public function create($attributes) { - return Token::create($attributes); + return $this->createModel()->create($attributes); } /** @@ -23,7 +32,7 @@ public function create($attributes) */ public function find($id) { - return Token::find($id); + return $this->createModel()->find($id); } /** @@ -56,7 +65,7 @@ public function revokeAccessToken($id) */ public function isAccessTokenRevoked($id) { - return Token::where('id', $id)->where('revoked', 1)->exists(); + return $this->createModel()->where('id', $id)->where('revoked', 1)->exists(); } /** @@ -69,8 +78,9 @@ public function isAccessTokenRevoked($id) */ public function revokeOtherAccessTokens($clientId, $userId, $except = null, $prune = false) { - $query = Token::where('user_id', $userId) - ->where('client_id', $clientId); + $query = $this->createModel() + ->where('user_id', $userId) + ->where('client_id', $clientId); if ($except) { $query->where('id', '<>', $except); @@ -82,4 +92,22 @@ public function revokeOtherAccessTokens($clientId, $userId, $except = null, $pru $query->update(['revoked' => true]); } } + + /** + * {@inheritdoc} + */ + public static function getModel() + { + return static::$model; + } + + /** + * {@inheritdoc} + */ + public static function setModel($model) + { + static::$model = $model; + + return new static; + } }