diff --git a/src/PHPCouchDB/Server.php b/src/PHPCouchDB/Server.php index 0b8a67c..756877b 100644 --- a/src/PHPCouchDB/Server.php +++ b/src/PHPCouchDB/Server.php @@ -28,9 +28,9 @@ class Server * * See also: \PHPCouchDB\Server:createFromURL() * - * @param array $options Supply either a string "url" parameter OR a - * \GuzzleHttp\ClientInterface "client" parameter if more configuration - * is required + * @param array $options Supply either a string "url" parameter OR a + * \GuzzleHttp\ClientInterface "client" parameter if more configuration + * is required * @throws \PHPCouchDB\Exception\ServerException if there's a problem * with parsing arguments or connecting to the database */ @@ -43,13 +43,16 @@ public function __construct(array $options) } if (isset($options[self::OPTION_CLIENT]) - && $options[self::OPTION_CLIENT] instanceof \GuzzleHttp\ClientInterface) { + && $options[self::OPTION_CLIENT] instanceof \GuzzleHttp\ClientInterface + ) { $client = $options[self::OPTION_CLIENT]; } elseif (isset($options[self::OPTION_URL])) { // set a descriptive user agent $user_agent = \GuzzleHttp\default_user_agent(); - $client = new \GuzzleHttp\Client(["base_uri" => $options[self::OPTION_URL], - "headers" => ["User-Agent" => "PHPCouchDB/" . VERSION . " " . $user_agent]]); + $client = new \GuzzleHttp\Client( + ["base_uri" => $options[self::OPTION_URL], + "headers" => ["User-Agent" => "PHPCouchDB/" . VERSION . " " . $user_agent]] + ); } else { throw new Exception\ServerException( 'Failed to parse $options, array should contain either a url or a client' @@ -113,7 +116,7 @@ public function getAllDbs() : array /** * Create and return a Database object to work with * - * @param $options Supply the "name" (required) and an optional boolean + * @param $options Supply the "name" (required) and an optional boolean * "create_if_not_exists" value (default is false) * @return \CouchDB\Database represents the named database * @throws \PHPCouchDB\Exception\ServerException if there's a problem @@ -164,6 +167,99 @@ public function useDb($options) : Database 'Database doesn\'t exist, include "create_if_not_exists" parameter to create it' ); } + /** + * Create a database user and return the revision of the user record (for later updating) + * + * @param $username the new username + * @param $password the password to setup for the user + * @param optional $roles if you want to specify the roles on the server for the user. defaults to [] + * @return string revision string + * @throws \PHPCouchDB\Exception\ServerException if there's a problem + */ + public function createUser($username, $password, $roles = []) + { + $doc = [ + 'name' => $username, + 'password' => $password, + 'roles' => $roles, + 'type' => 'user', + ]; + try { + $response = $this->client->request("PUT", "/_users/org.couchdb.user:" . $username, ['json' => $doc]); + if ($response->getStatusCode() == 201 && $response_data = json_decode($response->getBody(), true)) { + return $response_data['_rev']; + } else { + throw new Exception\ServerException( + 'Problem creating user' + ); + } + } catch (\GuzzleHttp\Exception\ClientException $e) { + return false; + } + } + + /** + * Update a database user and return the revision of the user record (for further updating) + * + * @param $username the new username + * @param $password the new password + * @param optional $rev the revision of the current record (saves a query if you can specify this) + * @param optional $roles if you want to specify the roles on the server for the user. defaults to [] + * @return string revision string + * @throws \PHPCouchDB\Exception\ServerException if there's a problem + */ + public function updateUser($username, $password, $rev = false, $roles = []) + { + $doc = [ + 'password' => $password, + 'type' => 'user', + 'name' => $username, + 'roles' => $roles, + ]; + if (!$rev) { + try { + $response = $this->client->request("GET", "/_users/org.couchdb.user:" . $username); + if ($response->getStatusCode() == 200 && $response_data = json_decode($response->getBody(), true)) { + $rev = $response_data['_rev']; + } else { + if ($response->getStatusCode() == 404) { + throw new Exception\ServerException( + "Your connection doesn't have privileges to confirm the user, or the user does not exist" + ); + } + throw new Exception\ServerException("Something went wrong: " . $response->getStatusCode()); + } + } catch (\GuzzleHttp\Exception\ClientException $e) { + throw new Exception\ServerException( + 'Could not retrieve the username provided' + ); + } + } + try { + $response = $this->client->request( + "PUT", + "/_users/org.couchdb.user:" . $username, + [ + 'json' => $doc, + 'headers' => [ + 'If-Match' => $rev + ], + ] + ); + if ($response->getStatusCode() == 201 && $response_data = json_decode($response->getBody(), true)) { + return $response_data['_rev']; + } else { + if ($response->getStatusCode() == 409) { + throw new Exception\ServerException("Bad permissions"); + } + throw new Exception\ServerException("Something went wrong: " . $response->getStatusCode()); + } + } catch (\GuzzleHttp\Exception\ClientException $e) { + throw new Exception\ServerException( + "Failing Updating User: " . $e->getMessage() . "REV: $rev" + ); + } + } /** * If you need to make a request that isn't supported by this library,