I was wondering if it was possible to extend or replace the php artisan tinker
command so it first asks for authentication as a way to gatekeep who can use it.
I tried the following:
<?php
namespace App\Console\Commands;
use Laravel\Tinker\Console\TinkerCommand;
use Illuminate\Support\Facades\Auth;
class Tinker extends TinkerCommand
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'tinker';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$email = $this->ask('Login (email)');
$password = $this->secret('Password for '.$email);
if (!Auth::attempt(compact('email', 'password'))) {
$this->error('Invalid Credentials.');
return;
}
if (Auth::user()->cannot('use-tinker')) {
$this->error('Unauthorized.');
return;
}
parent::handle();
}
}
But I get an error because I have not included the 'include' parameter used by TinkerCommand@handle
public function handle()
{
$this->getApplication()->setCatchExceptions(false);
$config = new Configuration([
'updateCheck' => 'never',
]);
$config->getPresenter()->addCasters(
$this->getCasters()
);
$shell = new Shell($config);
$shell->addCommands($this->getCommands());
$shell->setIncludes($this->argument('include')); # <-------- include argument
if (isset($_ENV['COMPOSER_VENDOR_DIR'])) {
$path = $_ENV['COMPOSER_VENDOR_DIR'];
} else {
$path = $this->getLaravel()->basePath().DIRECTORY_SEPARATOR.'vendor';
}
$path .= '/composer/autoload_classmap.php';
$loader = ClassAliasAutoloader::register($shell, $path);
try {
$shell->run();
} finally {
$loader->unregister();
}
}
I'm not sure what the include argument is about. I tried dumping it and it's an empty array. At this point I'm wondering if there's a better way.
If an user is able to run php artisan tinker
, he is also able to:
See the source code of your project. He probably can edit it too, but it may not be the case with proper file permissions
See your .env
, containing your database credentials and other sensitive information such as api keys
I'm not sure it is actually useful to restrict access inside tinker to an user that already has so many privilegies and possibilities. He could edit your database users
table to grant access to a user controlled by himself for example, or he could edit the source code to allow access.
Here is a little visualization of the problem:
If you want to do that anyway, instead of extending the TinkerCommand I would extend the base Command
and then run the tinker comman after authentication.
public function handle() {
// Do your own verification
$this->runCommand(TinkerCommand::class, [], $this->output);
return;
}