diff --git a/config/passport.php b/config/passport.php index a4565f372..95a48923d 100644 --- a/config/passport.php +++ b/config/passport.php @@ -17,4 +17,17 @@ 'public_key' => env('PASSPORT_PUBLIC_KEY'), + /* + |-------------------------------------------------------------------------- + | Client UUIDs + |-------------------------------------------------------------------------- + | + | By default, Passport uses auto-incrementing primary keys when assigning + | IDs to clients. However, if Passport is installed using the provided + | --uuids switch, this will be set to "true" and UUIDs will be used. + | + */ + + 'client_uuids' => false, + ]; diff --git a/src/Client.php b/src/Client.php index 51b2b7013..baa92acc3 100644 --- a/src/Client.php +++ b/src/Client.php @@ -3,6 +3,7 @@ namespace Laravel\Passport; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Str; class Client extends Model { @@ -41,6 +42,22 @@ class Client extends Model 'revoked' => 'bool', ]; + /** + * Bootstrap the model and its traits. + * + * @return void + */ + public static function boot() + { + parent::boot(); + + static::creating(function ($model) { + if (config('passport.client_uuids')) { + $model->{$model->getKeyName()} = $model->{$model->getKeyName()} ?: (string) Str::orderedUuid(); + } + }); + } + /** * Get the user that the client belongs to. * @@ -102,4 +119,24 @@ 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; + } } diff --git a/src/Console/InstallCommand.php b/src/Console/InstallCommand.php index 89b80440d..e8eb2f588 100644 --- a/src/Console/InstallCommand.php +++ b/src/Console/InstallCommand.php @@ -3,6 +3,7 @@ namespace Laravel\Passport\Console; use Illuminate\Console\Command; +use Laravel\Passport\Passport; class InstallCommand extends Command { @@ -12,6 +13,7 @@ class InstallCommand extends Command * @var string */ protected $signature = 'passport:install + {--uuids : Use UUIDs for all client IDs} {--force : Overwrite keys they already exist} {--length=4096 : The length of the private key}'; @@ -30,7 +32,54 @@ class InstallCommand extends Command public function handle() { $this->call('passport:keys', ['--force' => $this->option('force'), '--length' => $this->option('length')]); + + if ($this->option('uuids')) { + $this->configureUuids(); + } + $this->call('passport:client', ['--personal' => true, '--name' => config('app.name').' Personal Access Client']); $this->call('passport:client', ['--password' => true, '--name' => config('app.name').' Password Grant Client']); } + + /** + * Configure Passport for client UUIDs. + * + * @return void + */ + protected function configureUuids() + { + $this->call('vendor:publish', ['--tag' => 'passport-config']); + $this->call('vendor:publish', ['--tag' => 'passport-migrations']); + + config(['passport.client_uuids' => true]); + Passport::setClientUuids(true); + + $this->replaceInFile(config_path('passport.php'), 'false', 'true'); + $this->replaceInFile(database_path('migrations/2016_06_01_000001_create_oauth_auth_codes_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');'); + $this->replaceInFile(database_path('migrations/2016_06_01_000002_create_oauth_access_tokens_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');'); + $this->replaceInFile(database_path('migrations/2016_06_01_000004_create_oauth_clients_table.php'), '$table->bigIncrements(\'id\');', '$table->uuid(\'id\')->primary();'); + $this->replaceInFile(database_path('migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php'), '$table->unsignedBigInteger(\'client_id\');', '$table->uuid(\'client_id\');'); + + if ($this->confirm('In order to finish configuring client UUIDs, we need to rebuild the Passport database tables. Would you like to rollback and re-run your last migration?')) { + $this->call('migrate:rollback'); + $this->call('migrate'); + $this->line(''); + } + } + + /** + * Replace a given string in a given file. + * + * @param string $path + * @param string $search + * @param string $replace + * @return void + */ + protected function replaceInFile($path, $search, $replace) + { + file_put_contents( + $path, + str_replace($search, $replace, file_get_contents($path)) + ); + } } diff --git a/src/Passport.php b/src/Passport.php index 992f4333b..f00d55e01 100644 --- a/src/Passport.php +++ b/src/Passport.php @@ -112,6 +112,13 @@ class Passport */ public static $clientModel = 'Laravel\Passport\Client'; + /** + * Indicates if client's are identified by UUIDs. + * + * @var bool + */ + public static $clientUuids = false; + /** * The personal access client model class name. * @@ -534,6 +541,27 @@ public static function client() return new static::$clientModel; } + /** + * Determine if clients are identified using UUIDs. + * + * @return bool + */ + public static function clientUuids() + { + return static::$clientUuids; + } + + /** + * Specify if clients are identified using UUIDs. + * + * @param bool $value + * @return void + */ + public static function setClientUuids($value) + { + static::$clientUuids = $value; + } + /** * Set the personal access client model class name. * diff --git a/src/PassportServiceProvider.php b/src/PassportServiceProvider.php index 1f3bd4040..b4f649935 100644 --- a/src/PassportServiceProvider.php +++ b/src/PassportServiceProvider.php @@ -75,7 +75,7 @@ public function boot() */ protected function registerMigrations() { - if (Passport::$runsMigrations) { + if (Passport::$runsMigrations && ! config('passport.client_uuids')) { return $this->loadMigrationsFrom(__DIR__.'/../database/migrations'); } } @@ -89,6 +89,8 @@ public function register() { $this->mergeConfigFrom(__DIR__.'/../config/passport.php', 'passport'); + Passport::setClientUuids($this->app->make(Config::class)->get('passport.client_uuids', false)); + $this->registerAuthorizationServer(); $this->registerResourceServer(); $this->registerGuard();