ibm-watson-data-lab / php-couchdb

PHP Library for PHP 7 and CouchDB 2
Apache License 2.0
11 stars 8 forks source link

database class : editing security settings #13

Open seductiveapps opened 6 years ago

seductiveapps commented 6 years ago

i'm going to use CouchDB 2.2.0, Fauxton (/_utils) and the chrome debugger to build functionality into the php-couchdb database class that allows you to set security settings on databases, over the next few days/weeks.

the thing is, i read about how unit tests are required for a merge, and i could use some tips on how to quickly write the proper unit tests, and how to submit the changes..

actually, i'd rather not spend days reading manuals about this and that to become an expert on your particular source-code version control and unit testing code stacks..

can i simply submit the changed php-couchdb code to someone by email or adding them into this issue report even, along with example code that would get put into my https://gitlab.com/seductiveapps/seductiveapps/blob/master/seductiveapps/siteData/reInit.php ? pretty please? :)

seductiveapps commented 6 years ago

someone did the homework already : https://medium.com/@eiri/couchdb-authorization-in-nutshell-5ae697fe9a

all i have to do is build it into php-couchdb, and verify that it all works of course. luckily my CMS is in it's toddler stage, so i don't mind running the tests over and over again :)

seductiveapps commented 6 years ago

i'm stuck :(

public function getAdmins() {
    $endpoint = "/_node/couchdb@127.0.0.1/_config/admins";
    $verb = "GET";

    $response = $this->client->request($verb, $endpoint);
    return $response->getBody();        
}

returns

object(GuzzleHttp\Psr7\Stream)#211 (7) { ["stream":"GuzzleHttp\Psr7\Stream":private]=> resource(36) of type (stream) ["size":"GuzzleHttp\Psr7\Stream":private]=> NULL ["seekable":"GuzzleHttp\Psr7\Stream":private]=> bool(true) ["readable":"GuzzleHttp\Psr7\Stream":private]=> bool(true) ["writable":"GuzzleHttp\Psr7\Stream":private]=> bool(true) ["uri":"GuzzleHttp\Psr7\Stream":private]=> string(10) "php://temp" ["customMetadata":"GuzzleHttp\Psr7\Stream":private]=> array(0) { } }

and the call to $client->getAllDbs() works just fine, so does commandline : rene@hummingbird:~/data1/htdocs/localhost$ curl -X GET http://admin:validpass@127.0.0.1:5984/_node/couchdb@127.0.0.1/_config/admins {"admin":"-pbkdf2-038c8f1ce50359e72e90ee81810efd5a9ad06f6b,76a581df5845bd309e1ceffbf3fc9701,10"}

i'm no expert on GuzzleHTTP.. anyone got an idea why i can't get to the JSON listed as output for the curl commandline command?

akrabat commented 6 years ago

Cast the returned value from getAdmins() to a string and then json_decode it.

seductiveapps commented 6 years ago

cool! sorry i didn't get back to you earlier, i was busy with other code tasks.

i'll get onto implementing low-level and basic functionality to assign permissions to specific users on databases, hopefully to be included in future versions of your library.

i'll try to follow your code conventions where-ever possible, and will provide an example usage script as well.

i have some other tasks on my desk as well, but i'll update this thread with a link to my copy of this library (i host it at github.com and will fork it into php-couchdb-sa for the necessary flexibility in developing these extensions), as soon as i have something worth-while. that could take a few weeks, but no more than 2 months i think.

seductiveapps commented 6 years ago

i've run into another snag..

thread for php-couchdb upgrade : https://github.com/ibm-watson-data-lab/php-couchdb/issues/13 source-codes of my fork of couchdb : https://gitlab.com/seductiveapps/seductiveapps/tree/master/seductiveapps/lib/vendor/ibm-watson-data-lab/php-couchdb source-code for the script with which i use php-couchdb to (re-)initialize my couchdb from PHP (which allows me to do it from anywhere, and that's handy sometimes) : https://gitlab.com/seductiveapps/seductiveapps/blob/master/seductiveapps/siteData/reInit.php (starts at about line 190)

the two articles i found on couchdb permissions management : (server-wide admins) : https://medium.com/@eiri/couchdb-authorization-in-nutshell-5ae697fe9a (database permissions) : https://medium.com/@eiri/couchdb-authorization-in-a-database-58c8ee633c96

now, from the articles by @eiri, i can get and set the server-wide admins, i can enter users into the _users couchdb database, but i can't link these users to become the sole admin of a database in couchdb.

that error that is mentioned in the database permissions article, i can't overcome it as described in the article... here's the log:

CouchDB adding a couchdb admin user "rene" : string(84) "-pbkdf2-6d09918465d152e239bc57148d4817f0920a0f6b,ae5c5e8f805aae5bf48ff2d5e15bb845,10" requesting a list of couchdb admin users: array(2) { ["rene"]=> string(84) "-pbkdf2-9998f2b619af596e3184ea6766363bcbcb9ea6a7,a5f756a7a92ae6b232838af87f2607e5,10" ["admin"]=> string(84) "-pbkdf2-f309a6606c72f3a7977f427444bc0567379bcd3e,7a26b7ca5de19992686fdb9b2bd61e9f,10" } deleting any old databases entirely so they can be re-initialized deleting db sa_tree deleting db sa_treeadministrator creating couchdb+seductiveapps user "Administrator" creating couchdb+seductiveapps user "Guest" creating and populating couchdb database sa_tree creating and populating couchdb database sa_treeadministrator

Fatal error: Uncaught GuzzleHttp\Exception\ServerException: Server error: PUT http://admin:****@localhost:5984/sa_tree__administrator/_security resulted in a 500 Internal Server Error response: {"error":"error","reason":"no_majority"}

in /home/rene/data1/htdocs/localhost/seductiveapps/lib/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113 Stack trace:

0 /home/rene/data1/htdocs/localhost/seductiveapps/lib/vendor/guzzlehttp/guzzle/src/Middleware.php(66): GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request), Object(GuzzleHttp\Psr7\Response))

1 /home/rene/data1/htdocs/localhost/seductiveapps/lib/vendor/guzzlehttp/promises/src/Promise.php(203): GuzzleHttp\Middleware::GuzzleHttp{closure}(Object(GuzzleHttp\Psr7\Response))

2 /home/rene/data1/htdocs/localhost/seductiveapps/lib/vendor/guzzlehttp/promises/src/Promise.php(156): GuzzleHttp\Promise\Promise::callHandler(1, Object(GuzzleHttp\Psr7\Response), Array)

3 /home/rene/data1/htdocs/localhost/seductiveapps/lib/vendor/guzzlehttp/p in /home/rene/data1/htdocs/localhost/seductiveapps/lib/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php on line 113

in the article, it's mentioned that this error message ("no_majority") is wrong (somebody ought to fix that imho), but that one can set these _security settings by using the credentials of a couchdb admin.

that appears not to be the case, on my test system that is the latest ubuntu.com with the latest couchdb (installed per instructions found on couchdb.apache.org)

as you can see, it's already using a couchdb admin's credentials to do all of these calls.

i've spied on Fauxton (localhost:5984/_utils), and even using less JSON ([2] instead of [1]) like Fauxton does, gets me the same results in PHP.

[1] $json = '{ "admins" : { "names" : [], "roles" : [] }, "members" : { "names" : ["Administrator"], "roles" : [] } }'; [2] $json = '{ "members" : { "names" : ["Administrator"] } }';

this could be caused by couchdb, or by the PHP stack i use to get to couchdb. so i'm filing it both with the couchdb mailinglist and that thread for the upgrade of php-couchdb (linked at the start of this thread), so that hopefully someone can figure out what is causing this. personally, i've run out of things to try. :(

seductiveapps commented 5 years ago

did work from the command-line : rene@crow:~$ curl -X PUT $db/sa_tree__administrator/_security -d @- { "admins": { "names": [], "roles": [] }, "members": { "names": ["Administrator"], "roles": [] } } {"ok":true}

i don't really have the time to dig into this right now, guzzle's code conventions are a bit cryptic to me.

seductiveapps commented 5 years ago

fixed it :)

i was using the wrong parameter into one of the components used by php-couchdb. very happy i was able to solve this one in just a few minutes of course.

i've uploaded my improved sources to gitlab. links are listed earlier in this thread.

seductiveapps commented 4 years ago

UPDATE : CouchDB has been upgraded to version 3.0.0 now, and with that comes 1 vital change that all users of php-couchdb who desire real user management at their couchdb layer..

it's that adding security settings is now compulsory if you want to access a database at all as 'a normal user'.

i've found that the easiest way for me to add this into php-couchdb is for me to edit ibm-watson-data-lab/php-couchdb/src/PHPCouchDB/Server.php and change the function useDb a little..

before $exist = false, add : if (isset($options['_security'])) { $security = $options['_security']; } else { $security = false; } after if ($create_response->getStatusCode() == 201) {, add : if ($security) $sec_response = $this->client->request('PUT', '/'.$db_name.'/_security', Array('json'=>$security));

now you can do, in your client code aimed into php-couchdb, the following : ` $security = Array( 'members'=>Array( 'users'=>Array('_admin',$_REQUEST['saRegistration_loginname']) ), 'admins'=>Array( 'users'=>Array('_admin',$_REQUEST['saRegistration_loginname']) ) );

try {
$client = couchdb_client('_users'); 
$db = $client->useDb(["name" => '_users', 'create_if_not_exists' => true, '_security' => $security]);
    $db->create([
        'id' => 'org.couchdb.user:'.$_REQUEST['saRegistration_loginname'], 
        'name' => $_REQUEST['saRegistration_loginname'], 
        'password' => $_REQUEST['saRegistration_password_1'], 
        'realname' => $_REQUEST['saRegistration_realname'], 
        'email' => $_REQUEST['saRegistration_email'], 
        'registeringIP' => $_SERVER['REMOTE_ADDR'],
        'roles' => [ "guests" ], 
        'type' => "user"
    ]);
} catch (Exception $e) { 
    echo $e->getMessage();
}
try {
    $db = $client->useDb(["name" => $serverHTTPhost.'___sa_url_themes__user__'.$un, 'create_if_not_exists' => true, '_security' => $security]);
} catch (Exception $e) { 
    echo $e->getMessage();
}

`