duxet / laravel-rethinkdb

RethinkDB adapter for Laravel (with Eloquent support)
MIT License
148 stars 37 forks source link

Does not support RethinkDb connections with username/password #40

Open SlyDave opened 7 years ago

SlyDave commented 7 years ago

The package doesn't support connecting to Rethink that uses a username and password.

r/connect has really odd usage (and lets not talk about the global namespace functions...)

Simple connection: r\connect($host, $port, $database, $apiKey);

With username/password:

$opts = [];
$opts['host'] = 'localhost';
$opts['user'] = 'test';
$opts['password'] = 'example';
r\connect($opts, $port, $database, $apiKey);

duxet's constructor doesn't support this: (it also confuses authkey for apikey)

    public function __construct(array $config)
    {
        $this->config = $config;
        $this->database = $config['database'];

        $port = isset($config['port']) ? $config['port'] : 28015;
        $authKey = isset($config['authKey']) ? $config['authKey'] : null;

        // Create the connection
        $this->connection = r\connect($config['host'], $port, $this->database, $authKey);

        ...

For now I've done the following:

Updated the 'connections' entry in config/database.php and added in username and password:

e.g.:

        'rethinkdb' => [
            'driver' => 'rethinkdb',
            'host' => env('RETHINK_HOST', 'localhost'),
            'port' => env('RETHINK_PORT', 28015),
            'database' => env('RETHINK_DATABASE', null),
            'username' => env('RETHINK_USERNAME', null),
            'password' => env('RETHINK_PASSWORD', null)
        ]

Then I've created a ugly new class app\RethinkDb\Connection, extending \duxet\Rethinkdb\Connection overloading __construct and handling the extra config data (note the lack of any real validation :P):

e.g.:

declare(strict_types=1);
namespace App\RethinkDb;

use r;

class Connection extends \duxet\Rethinkdb\Connection
{
    /**
     * duxet\Rethinkdb\Connection doesn't support connecting with username/password, this resolves that.
     *
     * @param array $config
     */
    public function __construct(array $config)
    {
        $this->config = $config;
        $this->database = $config['database'];

        // Map Laravel to PHP-RQL
        if ($config['username']) {
            $config['user'] = $config['username'];
        }
        if ($config['database']) {
            $config['db'] = $config['database'];
        }

        // Create the connection
        $this->connection = r\connect($config);

        // We need to initialize a query grammar and the query post processors,
        // which are both very important parts of the database abstractions -
        // so we initialize these to their default values when starting.
        $this->useDefaultQueryGrammar();
        $this->useDefaultPostProcessor();
    }
}

This then required a new ServiceProvider to replace the resolving of db:rethinkdb with the custom Connection rather than the package provided one (note the use statement which replaces which Connection is being used rather than the one in the Rethinkdb namespace, we use our custom one, other than that, there are no changes)

App\Providers\RethinkdbServiceProvider::class,

<?php
declare(strict_types=1);
namespace App\Providers;

use App\RethinkDb\Connection;

class RethinkdbServiceProvider extends \duxet\Rethinkdb\RethinkdbServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        parent::register();

        // Replace the resolver with our Connection which supports username/password
        $this->app->resolving('db', function ($db) {
            $db->extend('rethinkdb', function ($config) {
                return new Connection($config);
            });
        });
    }
}

It'd be great if the package would support the full range of connectivity offered by rethink...

mauritskorse commented 6 years ago

Thanks. That's not as ugly as the quick fix I used: editing the vendor file (\duxet\Rethinkdb\Connection):

- $this->connection = r\connect($config['host'], $port, $this->database, $authKey); + $this->connection = r\connect($config, $port, $this->database, $authKey);