├── README.md ├── composer.json └── src ├── Api.php ├── ApiServiceProvider.php ├── Exceptions ├── CurlException.php └── XMLParseException.php ├── Facade └── Api.php ├── Response.php └── Status.php /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Nextcloud API User Management 2 | manage your nextcloud users via laravel 3 | 4 | # Setup: 5 | 1. Use following command in your terminal to install this library. (Currently the library is in development mode): 6 | 7 | `composer require masterzero/nextcloud dev-master` 8 | 9 | 2. Update the poviders in config/app.php 10 | 11 | 'providers' => [ 12 | // ... 13 | MasterZero\Nextcloud\ApiServiceProvider::class, 14 | ] 15 | 16 | 3. Update the aliases in config/app.php 17 | 18 | 'aliases' => [ 19 | // ... 20 | 'NextcloudApi' => MasterZero\Nextcloud\Facade\Api::class, 21 | ] 22 | 23 | 4. Create `config/nextcloud.php` with content: 24 | 25 | ```php 26 | 27 | return [ 28 | 'login'=> env('NEXTCLOUD_LOGIN', 'admin'), 29 | 'password'=> env('NEXTCLOUD_PASSWORD', '12345678'), 30 | 'baseUrl'=> env('NEXTCLOUD_BASEURL', 'http://localhost'), 31 | ]; 32 | 33 | ``` 34 | 35 | 5. Add these params to `.env` (optional): 36 | 37 | ```sh 38 | NEXTCLOUD_LOGIN=admin 39 | NEXTCLOUD_PASSWORD=12345678 40 | NEXTCLOUD_BASEURL=http://localhost 41 | 42 | ``` 43 | 44 | # Usage: 45 | ### create user: 46 | ```php 47 | // reqeust to API 48 | $data = NextcloudApi::createUser($username, $password); 49 | 50 | // do something with it 51 | if ($data['success']) { 52 | 53 | // do something ... 54 | 55 | } else { 56 | 57 | // do something else ... 58 | 59 | echo $data['message']; 60 | 61 | } 62 | ``` 63 | 64 | ### user list: 65 | ```php 66 | // reqeust to API 67 | $data = NextcloudApi::getUserList(); 68 | 69 | // do something with it 70 | if ($data['success']) { 71 | 72 | foreach ($data['users'] as $userid) { 73 | // do something with $userid 74 | } 75 | 76 | } else { 77 | 78 | // do something else ... 79 | 80 | } 81 | 82 | ``` 83 | 84 | ### edit user param: 85 | ```php 86 | // reqeust to API 87 | $data = NextcloudApi::editUser('rabbit','quota', '200 MB'); 88 | 89 | if ($data['success']) { 90 | 91 | // do something ... 92 | 93 | } else { 94 | 95 | // do something else ... 96 | 97 | } 98 | ``` 99 | 100 | 101 | ### enable/disable user: 102 | ```php 103 | // reqeust to API 104 | $data = NextcloudApi::enableUser('bird'); 105 | //$data = NextcloudApi::disableUser('turtle'); 106 | 107 | if ($data['success']) { 108 | 109 | // do something ... 110 | 111 | } else { 112 | 113 | // do something else ... 114 | 115 | } 116 | ``` 117 | 118 | # exceptions 119 | 120 | ```php 121 | 122 | use MasterZero\Nextcloud\Exceptions\XMLParseException; 123 | use MasterZero\Nextcloud\Exceptions\CurlException; 124 | 125 | // ... 126 | 127 | try { 128 | // reqeust to API 129 | NextcloudApi::editUser('rabbit','quota', '200 MB'); 130 | } catch (XMLParseException $e) { 131 | // bad nextcloud answer 132 | } catch (CurlException $e) { 133 | // bad connection 134 | } catch (\Exception $e) { 135 | // bad something else 136 | } 137 | 138 | ``` 139 | 140 | 141 | # multi-server usage 142 | 143 | ```php 144 | 145 | use MasterZero\Nextcloud\Api; 146 | 147 | // ... 148 | 149 | $api = new Api([ 150 | 'baseUrl' => 'http://develop.localhost:3500', 151 | 'login' => 'admin', 152 | 'password' => '12345678', 153 | 'sslVerify' => false, 154 | 155 | 156 | // use default value 157 | // 'apiPath' => 'custom/path/to/api.php', 158 | // 'userPath' => '', 159 | // 'enablePath' => '', 160 | // 'disablePath' => '', 161 | ]); 162 | 163 | 164 | $api->createUser( 'dummy', 'qwerty'); 165 | 166 | ``` -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "masterzero/nextcloud", 3 | "description": "library for nextcloud user management", 4 | "type": "library", 5 | "license": "MIT", 6 | "keywords": ["laravel", "nextcloud"], 7 | "authors": [ 8 | { 9 | "name": "masterzero", 10 | "email": "masterzerno@gmail.com" 11 | } 12 | ], 13 | "minimum-stability": "stable", 14 | "require": { 15 | "php": ">=7.0.0" 16 | }, 17 | "autoload": { 18 | "psr-4": { 19 | "MasterZero\\Nextcloud\\":"src/" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Api.php: -------------------------------------------------------------------------------- 1 | login = $params['login'] ?? config("nextcloud.login"); 78 | $this->password = $params['password'] ?? config("nextcloud.password"); 79 | $this->baseUrl = $params['baseUrl'] ?? config("nextcloud.baseUrl"); 80 | 81 | 82 | $initialParam = [ 83 | 'apiPath', 84 | 'sslVerify', 85 | 86 | 'userPath', 87 | 'enablePath', 88 | 'disablePath', 89 | ]; 90 | 91 | foreach ($initialParam as $param) { 92 | 93 | if (isset($params[$param])) { 94 | $this->$param = $params[$param]; 95 | } 96 | 97 | } 98 | 99 | } 100 | 101 | 102 | /** 103 | * method to get nextcloud user list 104 | * 105 | * @param $search | string: string to search users by userid 106 | * @param $limit | int 107 | * @param $offset | int 108 | * @return array [ 109 | * success: is success request 110 | * message: comment message from nextcloud server 111 | * users: array of userid's 112 | * response | MasterZero\Nextcloud\Response: response object with details of nextcloud answer 113 | * ] 114 | * @throws MasterZero\Nextcloud\Exceptions\XMLParseException 115 | * @throws MasterZero\Nextcloud\Exceptions\CurlException 116 | */ 117 | public function getUserList(string $search = '', int $limit = 0, int $offset = 0) : array 118 | { 119 | 120 | $url = $this->baseUrl . '/' . $this->apiPath . '/' . $this->userPath; 121 | $method = static::METHOD_GET; 122 | 123 | $params = []; 124 | 125 | if (strlen($search)) { 126 | $params['search'] = $search; 127 | } 128 | 129 | if ($limit) { 130 | $params['limit'] = $limit; 131 | } 132 | 133 | if ($offset) { 134 | $params['offset'] = $offset; 135 | } 136 | 137 | 138 | if (!empty($params)) { 139 | $url .= '?' . $this->serializeParams($params); 140 | } 141 | 142 | $response = $this->request($url, $method); 143 | 144 | $userData = $response->getData('users'); 145 | 146 | $ret = [ 147 | 'success' => $response->getStatus() === Status::USERLIST_OK, 148 | 'message' => $response->getMessage(), 149 | 'users' => $userData['element'], 150 | 'response' => $response, 151 | ]; 152 | 153 | return $ret; 154 | } 155 | 156 | 157 | /** 158 | * method to create nextcloud user 159 | * 160 | * @param $userid | string: username for create. must be unique. 161 | * @param $password | string 162 | * @return array [ 163 | * success: is success request 164 | * message: comment message from nextcloud server 165 | * response | MasterZero\Nextcloud\Response: response object with details of nextcloud answer 166 | * ] 167 | * @throws MasterZero\Nextcloud\Exceptions\XMLParseException 168 | * @throws MasterZero\Nextcloud\Exceptions\CurlException 169 | */ 170 | public function createUser(string $userid, string $password) : array 171 | { 172 | 173 | $url = $this->baseUrl . '/' . $this->apiPath . '/' . $this->userPath; 174 | $method = static::METHOD_POST; 175 | 176 | $params = $this->serializeParams([ 177 | 'userid' => $userid, 178 | 'password' => $password, 179 | ]); 180 | 181 | $response = $this->request($url, $method, $params); 182 | 183 | 184 | $ret = [ 185 | 'success' => $response->getStatus() === Status::CREATEUSER_OK, 186 | 'message' => $response->getMessage(), 187 | 'response' => $response, 188 | ]; 189 | 190 | 191 | return $ret; 192 | } 193 | 194 | 195 | /** 196 | * method to edit nextcloud user parameters 197 | * 198 | * @param $userid | string 199 | * @param $key | string: parameter to edit (email | quota | display | password) 200 | * @param $value | string 201 | * @return array [ 202 | * success: is success request 203 | * message: comment message from nextcloud server 204 | * response | MasterZero\Nextcloud\Response: response object with details of nextcloud answer 205 | * ] 206 | * @throws MasterZero\Nextcloud\Exceptions\XMLParseException 207 | * @throws MasterZero\Nextcloud\Exceptions\CurlException 208 | */ 209 | public function editUser(string $userid, string $key, string $value) : array 210 | { 211 | 212 | $url = $this->baseUrl . '/' . $this->apiPath . '/' . $this->userPath . '/' . $userid; 213 | $method = static::METHOD_PUT; 214 | 215 | $params = $this->serializeParams([ 216 | 'key' => $key, 217 | 'value' => $value, 218 | ]); 219 | 220 | $response = $this->request($url, $method, $params); 221 | 222 | 223 | $ret = [ 224 | 'success' => $response->getStatus() === Status::EDITUSER_OK, 225 | 'message' => $response->getMessage(), 226 | 'response' => $response, 227 | ]; 228 | 229 | return $ret; 230 | } 231 | 232 | 233 | /** 234 | * method to disable nextcloud user 235 | * 236 | * @param $userid | string 237 | * @return array [ 238 | * success: is success request 239 | * message: comment message from nextcloud server 240 | * response | MasterZero\Nextcloud\Response: response object with details of nextcloud answer 241 | * ] 242 | * @throws MasterZero\Nextcloud\Exceptions\XMLParseException 243 | * @throws MasterZero\Nextcloud\Exceptions\CurlException 244 | */ 245 | public function disableUser(string $userid) : array 246 | { 247 | 248 | $url = $this->baseUrl . '/' . $this->apiPath . '/' . $this->userPath . '/' . $userid . '/' . $this->disablePath; 249 | $method = static::METHOD_PUT; 250 | 251 | $response = $this->request($url, $method); 252 | 253 | $ret = [ 254 | 'success' => $response->getStatus() === Status::DISABLEUSER_OK, 255 | 'message' => $response->getMessage(), 256 | 'response' => $response, 257 | ]; 258 | 259 | return $ret; 260 | } 261 | 262 | 263 | 264 | /** 265 | * method to enable nextcloud user 266 | * 267 | * @param $userid | string 268 | * @return array [ 269 | * success: is success request 270 | * message: comment message from nextcloud server 271 | * response | MasterZero\Nextcloud\Response: response object with details of nextcloud answer 272 | * ] 273 | * @throws MasterZero\Nextcloud\Exceptions\XMLParseException 274 | * @throws MasterZero\Nextcloud\Exceptions\CurlException 275 | */ 276 | public function enableUser(string $userid) : array 277 | { 278 | $url = $this->baseUrl . '/' . $this->apiPath . '/' . $this->userPath . '/' . $userid . '/' . $this->enablePath; 279 | $method = static::METHOD_PUT; 280 | 281 | $response = $this->request($url, $method); 282 | 283 | $ret = [ 284 | 'success' => $response->getStatus() === Status::ENABLEUSER_OK, 285 | 'message' => $response->getMessage(), 286 | 'response' => $response, 287 | ]; 288 | 289 | return $ret; 290 | } 291 | 292 | 293 | 294 | /** 295 | * method to delete nextcloud user 296 | * 297 | * @param $userid | string 298 | * @return array [ 299 | * success: is success request 300 | * message: comment message from nextcloud server 301 | * response | MasterZero\Nextcloud\Response: response object with details of nextcloud answer 302 | * ] 303 | * @throws MasterZero\Nextcloud\Exceptions\XMLParseException 304 | * @throws MasterZero\Nextcloud\Exceptions\CurlException 305 | */ 306 | public function deleteUser(string $userid) : array 307 | { 308 | $url = $this->baseUrl . '/' . $this->apiPath . '/' . $this->userPath . '/' . $userid; 309 | $method = static::METHOD_DELETE; 310 | 311 | $response = $this->request($url, $method); 312 | 313 | $ret = [ 314 | 'success' => $response->getStatus() === Status::DELETEUSER_OK, 315 | 'message' => $response->getMessage(), 316 | 'response' => $response, 317 | ]; 318 | 319 | return $ret; 320 | } 321 | 322 | 323 | /** 324 | * get default required headers 325 | * 326 | * @return array 327 | */ 328 | protected function defaultHeaders(): array 329 | { 330 | return [ 331 | 'Content-Type: application/x-www-form-urlencoded', 332 | 'OCS-APIRequest: true' 333 | ]; 334 | } 335 | 336 | /** 337 | * serialize array [key1 => value1, key2 => value2] to string key1=value1&key2=value2 338 | * 339 | * @return string 340 | */ 341 | protected function serializeParams(array $params): string 342 | { 343 | 344 | if (!count($params)) { 345 | return ''; 346 | } 347 | 348 | $expressions = []; 349 | 350 | foreach ($params as $key => $value) { 351 | $expressions[] = urlencode($key) . '=' . urlencode($value); 352 | } 353 | 354 | return implode('&', $expressions); 355 | } 356 | 357 | 358 | /** 359 | * do request 360 | * 361 | * @param $url | string 362 | * @param $method | string 363 | * @param $headers | array of strings 364 | * @return MasterZero\Nextcloud\Response 365 | * @throws MasterZero\Nextcloud\Exceptions\XMLParseException 366 | * @throws MasterZero\Nextcloud\Exceptions\CurlException 367 | */ 368 | protected function request(string $url, string $method = 'GET', $data = '', array $headers = []) : Response 369 | { 370 | $ch = curl_init(); 371 | 372 | curl_setopt($ch, CURLOPT_URL, $url); 373 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 374 | 375 | if($method === static::METHOD_POST) { 376 | curl_setopt($ch, CURLOPT_POST, 1); 377 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 378 | } elseif ($method === static::METHOD_PUT || $method === static::METHOD_DELETE) { 379 | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); 380 | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 381 | } 382 | 383 | $userowd = $this->login . ':' . $this->password; 384 | curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); 385 | curl_setopt($ch, CURLOPT_USERPWD, $userowd); 386 | 387 | 388 | $headers = array_merge($this->defaultHeaders(), $headers); 389 | 390 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 391 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->sslVerify);// this should be set to true in production 392 | 393 | $responseData = curl_exec($ch); 394 | 395 | if(curl_errno($ch)) { 396 | throw new CurlException('[Nextcloud] ' . curl_error($ch), 1); 397 | } 398 | 399 | $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 400 | 401 | curl_close($ch); 402 | 403 | return new Response($responseData, $httpcode); 404 | } 405 | } 406 | 407 | -------------------------------------------------------------------------------- /src/ApiServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->singleton('NextcloudApi',function(){ 26 | return new Api(); 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Exceptions/CurlException.php: -------------------------------------------------------------------------------- 1 | answer = $answer; 46 | $this->code = $code; 47 | $this->xml = $this->stringToXmlArray($answer); 48 | 49 | 50 | if(!isset($this->xml['meta']) 51 | || !isset($this->xml['meta']['statuscode']) 52 | || !isset($this->xml['meta']['message']) 53 | ) { 54 | throw new XMLParseException("Error on parsing xml response from nextcloud.", 1); 55 | } 56 | 57 | $this->status = (int)$this->xml['meta']['statuscode']; 58 | $this->message = $this->xml['meta']['message']; 59 | } 60 | 61 | /** 62 | * get http code 63 | * 64 | * @return int 65 | */ 66 | public function getCode() 67 | { 68 | return $this->code; 69 | } 70 | 71 | /** 72 | * get http content 73 | * 74 | * @return string 75 | */ 76 | public function getAnswer() 77 | { 78 | return $this->answer; 79 | } 80 | 81 | /** 82 | * get nextcloud status 83 | * 84 | * @return int 85 | */ 86 | public function getStatus() 87 | { 88 | return $this->status; 89 | } 90 | 91 | /** 92 | * get nextcloud message 93 | * 94 | * @return string 95 | */ 96 | public function getMessage() 97 | { 98 | return $this->message; 99 | } 100 | 101 | /** 102 | * get custom parameter of xml answer 103 | * 104 | * @param $offset | string|null 105 | * @param $ret_on_unset | any 106 | * @return any 107 | */ 108 | public function getData($offset = null, $ret_on_unset = '') 109 | { 110 | if(is_null($offset)) { 111 | return $this->xml; 112 | } 113 | 114 | if(!isset($this->xml['data'][$offset])) { 115 | return $ret_on_unset; 116 | } else { 117 | return $this->xml['data'][$offset]; 118 | } 119 | } 120 | 121 | /** 122 | * xml => array convertation method 123 | * 124 | * @param $str | string 125 | * @return array 126 | */ 127 | protected function stringToXmlArray(string $str) 128 | { 129 | return json_decode(json_encode(simplexml_load_string($str)),1); 130 | } 131 | } 132 | 133 | -------------------------------------------------------------------------------- /src/Status.php: -------------------------------------------------------------------------------- 1 |