diff options
author | Tom Needham <needham.thomas@gmail.com> | 2013-03-09 16:59:13 -0800 |
---|---|---|
committer | Tom Needham <needham.thomas@gmail.com> | 2013-03-09 16:59:13 -0800 |
commit | dfbf57207d2d47a843b514728b7254e76930b20c (patch) | |
tree | e1c2037a39247d5e170dac90d2ce8d708ef13441 | |
parent | 6bdb84ab288a2ef2087c8daa2255071cf45d26b4 (diff) | |
parent | e58dbd46fc4648ca6f33b83e7ce7745f07217477 (diff) | |
download | nextcloud-server-dfbf57207d2d47a843b514728b7254e76930b20c.tar.gz nextcloud-server-dfbf57207d2d47a843b514728b7254e76930b20c.zip |
Merge pull request #1584 from owncloud/ocs_multiple_methods
Allow registering of multiple methods on each api route. Add /cloud/capabilities route.
-rw-r--r-- | apps/files/appinfo/app.php | 2 | ||||
-rw-r--r-- | apps/files/appinfo/routes.php | 5 | ||||
-rw-r--r-- | apps/files/lib/capabilities.php | 24 | ||||
-rw-r--r-- | apps/files_encryption/appinfo/app.php | 1 | ||||
-rw-r--r-- | apps/files_encryption/appinfo/routes.php | 9 | ||||
-rw-r--r-- | apps/files_encryption/lib/capabilities.php | 23 | ||||
-rw-r--r-- | apps/files_versions/appinfo/app.php | 1 | ||||
-rw-r--r-- | apps/files_versions/appinfo/routes.php | 9 | ||||
-rw-r--r-- | apps/files_versions/lib/capabilities.php | 23 | ||||
-rw-r--r-- | lib/api.php | 150 | ||||
-rw-r--r-- | lib/ocs/cloud.php | 60 | ||||
-rw-r--r-- | lib/ocs/result.php | 48 | ||||
-rw-r--r-- | ocs/routes.php | 3 |
13 files changed, 264 insertions, 94 deletions
diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php index da17a7f2ccd..6535a9b7baa 100644 --- a/apps/files/appinfo/app.php +++ b/apps/files/appinfo/app.php @@ -1,4 +1,6 @@ <?php +OC::$CLASSPATH['OCA\Files\Capabilities'] = 'apps/files/lib/capabilities.php'; + $l = OC_L10N::get('files'); OCP\App::registerAdmin('files', 'admin'); diff --git a/apps/files/appinfo/routes.php b/apps/files/appinfo/routes.php index 043782a9c04..fcd5f4b2608 100644 --- a/apps/files/appinfo/routes.php +++ b/apps/files/appinfo/routes.php @@ -8,4 +8,7 @@ $this->create('download', 'download{file}') ->requirements(array('file' => '.*')) - ->actionInclude('files/download.php');
\ No newline at end of file + ->actionInclude('files/download.php'); + +// Register with the capabilities API +OC_API::register('get', '/cloud/capabilities', array('OCA\Files\Capabilities', 'getCapabilities'), 'files', OC_API::USER_AUTH);
\ No newline at end of file diff --git a/apps/files/lib/capabilities.php b/apps/files/lib/capabilities.php new file mode 100644 index 00000000000..90a5e2f4eb9 --- /dev/null +++ b/apps/files/lib/capabilities.php @@ -0,0 +1,24 @@ +<?php +/** + * Copyright (c) 2013 Tom Needham <tom@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\Files; + +class Capabilities { + + public static function getCapabilities() { + return new \OC_OCS_Result(array( + 'capabilities' => array( + 'files' => array( + 'bigfilechunking' => true, + 'undelete' => true, + ), + ), + )); + } + +}
\ No newline at end of file diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index f7b2140b580..bf16fec3aea 100644 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -7,6 +7,7 @@ OC::$CLASSPATH['OCA\Encryption\Keymanager'] = 'files_encryption/lib/keymanager.p OC::$CLASSPATH['OCA\Encryption\Stream'] = 'files_encryption/lib/stream.php'; OC::$CLASSPATH['OCA\Encryption\Proxy'] = 'files_encryption/lib/proxy.php'; OC::$CLASSPATH['OCA\Encryption\Session'] = 'files_encryption/lib/session.php'; +OC::$CLASSPATH['OCA\Encryption\Capabilities'] = 'files_encryption/lib/capabilities.php'; OC_FileProxy::register( new OCA\Encryption\Proxy() ); diff --git a/apps/files_encryption/appinfo/routes.php b/apps/files_encryption/appinfo/routes.php new file mode 100644 index 00000000000..ab83432a4b2 --- /dev/null +++ b/apps/files_encryption/appinfo/routes.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright (c) 2013, Tom Needham <tom@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + +// Register with the capabilities API +OC_API::register('get', '/cloud/capabilities', array('OCA\Encryption\Capabilities', 'getCapabilities'), 'files_encryption', OC_API::USER_AUTH);
\ No newline at end of file diff --git a/apps/files_encryption/lib/capabilities.php b/apps/files_encryption/lib/capabilities.php new file mode 100644 index 00000000000..72baddcd049 --- /dev/null +++ b/apps/files_encryption/lib/capabilities.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright (c) 2013 Tom Needham <tom@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\Encryption; + +class Capabilities { + + public static function getCapabilities() { + return new \OC_OCS_Result(array( + 'capabilities' => array( + 'files' => array( + 'encryption' => true, + ), + ), + )); + } + +}
\ No newline at end of file diff --git a/apps/files_versions/appinfo/app.php b/apps/files_versions/appinfo/app.php index 44d01f5cd5e..9be1c889682 100644 --- a/apps/files_versions/appinfo/app.php +++ b/apps/files_versions/appinfo/app.php @@ -3,6 +3,7 @@ //require_once 'files_versions/versions.php'; OC::$CLASSPATH['OCA\Files_Versions\Storage'] = 'files_versions/lib/versions.php'; OC::$CLASSPATH['OCA\Files_Versions\Hooks'] = 'files_versions/lib/hooks.php'; +OC::$CLASSPATH['OCA\Files_Versions\Capabilities'] = 'files_versions/lib/capabilities.php'; OCP\Util::addscript('files_versions', 'versions'); diff --git a/apps/files_versions/appinfo/routes.php b/apps/files_versions/appinfo/routes.php new file mode 100644 index 00000000000..8cef57c9e4d --- /dev/null +++ b/apps/files_versions/appinfo/routes.php @@ -0,0 +1,9 @@ +<?php +/** + * Copyright (c) 2013, Tom Needham <tom@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or later. + * See the COPYING-README file. + */ + +// Register with the capabilities API +OC_API::register('get', '/cloud/capabilities', array('OCA\Files_Versions\Capabilities', 'getCapabilities'), 'files_versions', OC_API::USER_AUTH);
\ No newline at end of file diff --git a/apps/files_versions/lib/capabilities.php b/apps/files_versions/lib/capabilities.php new file mode 100644 index 00000000000..3251a07b6ae --- /dev/null +++ b/apps/files_versions/lib/capabilities.php @@ -0,0 +1,23 @@ +<?php +/** + * Copyright (c) 2013 Tom Needham <tom@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OCA\Files_Versions; + +class Capabilities { + + public static function getCapabilities() { + return new \OC_OCS_Result(array( + 'capabilities' => array( + 'files' => array( + 'versioning' => true, + ), + ), + )); + } + +}
\ No newline at end of file diff --git a/lib/api.php b/lib/api.php index 70e3028b68a..8d6bbb7cc09 100644 --- a/lib/api.php +++ b/lib/api.php @@ -33,21 +33,20 @@ class OC_API { const USER_AUTH = 1; const SUBADMIN_AUTH = 2; const ADMIN_AUTH = 3; - - private static $server; - + /** - * initialises the OAuth store and server + * API Response Codes */ - private static function init() { - self::$server = new OC_OAuth_Server(new OC_OAuth_Store()); - } - + const RESPOND_UNAUTHORISED = 997; + const RESPOND_SERVER_ERROR = 996; + const RESPOND_NOT_FOUND = 998; + const RESPOND_UNKNOWN_ERROR = 999; + /** * api actions */ protected static $actions = array(); - + /** * registers an api call * @param string $method the http method @@ -58,7 +57,7 @@ class OC_API { * @param array $defaults * @param array $requirements */ - public static function register($method, $url, $action, $app, + public static function register($method, $url, $action, $app, $authLevel = OC_API::USER_AUTH, $defaults = array(), $requirements = array()) { @@ -71,9 +70,9 @@ class OC_API { ->action('OC_API', 'call'); self::$actions[$name] = array(); } - self::$actions[$name] = array('app' => $app, 'action' => $action, 'authlevel' => $authLevel); + self::$actions[$name][] = array('app' => $app, 'action' => $action, 'authlevel' => $authLevel); } - + /** * handles an api call * @param array $parameters @@ -86,29 +85,97 @@ class OC_API { parse_str(file_get_contents("php://input"), $parameters['_delete']); } $name = $parameters['_route']; - // Check authentication and availability - if(self::isAuthorised(self::$actions[$name])) { - if(is_callable(self::$actions[$name]['action'])) { - $response = call_user_func(self::$actions[$name]['action'], $parameters); - if(!($response instanceof OC_OCS_Result)) { - $response = new OC_OCS_Result(null, 996, 'Internal Server Error'); - } - } else { - $response = new OC_OCS_Result(null, 998, 'Api method not found'); + // Foreach registered action + $responses = array(); + foreach(self::$actions[$name] as $action) { + // Check authentication and availability + if(!self::isAuthorised(self::$actions[$name])) { + $responses[] = array( + 'app' => $action['app'], + 'response' => new OC_OCS_Result(null, OC_API::RESPOND_UNAUTHORISED, 'Unauthorised'), + ); + continue; } - } else { - header('WWW-Authenticate: Basic realm="Authorization Required"'); - header('HTTP/1.0 401 Unauthorized'); - $response = new OC_OCS_Result(null, 997, 'Unauthorised'); + if(!is_callable($action['action'])) { + $responses[] = array( + 'app' => $action['app'], + 'response' => new OC_OCS_Result(null, OC_API::RESPOND_NOT_FOUND, 'Api method not found'), + ); + continue; + } + // Run the action + $responses[] = array( + 'app' => $action['app'], + 'response' => call_user_func($action['action'], $parameters), + ); } - // Send the response + $response = self::mergeResponses($responses); $formats = array('json', 'xml'); $format = !empty($_GET['format']) && in_array($_GET['format'], $formats) ? $_GET['format'] : 'xml'; - self::respond($response, $format); - // logout the user to be stateless + self::respond($response); OC_User::logout(); } + + /** + * merge the returned result objects into one response + * @param array $responses + */ + private static function mergeResponses($responses) { + $response = array(); + // Sort into shipped and thirdparty + $shipped = array( + 'succeeded' => array(), + 'failed' => array(), + ); + $thirdparty = array( + 'succeeded' => array(), + 'failed' => array(), + ); + foreach($responses as $response) { + if(OC_App::isShipped($response['app']) || ($response['app'] === 'core')) { + if($response['response']->succeeded()) { + $shipped['succeeded'][$response['app']] = $response['response']; + } else { + $shipped['failed'][$response['app']] = $response['response']; + } + } else { + if($response['response']->succeeded()) { + $thirdparty['succeeded'][$response['app']] = $response['response']; + } else { + $thirdparty['failed'][$response['app']] = $response['response']; + } + } + } + // Remove any error responses if there is one shipped response that succeeded + if(!empty($shipped['succeeded'])) { + $responses = array_merge($shipped['succeeded'], $thirdparty['succeeded']); + } else if(!empty($shipped['failed'])) { + // Which shipped response do we use if they all failed? + // They may have failed for different reasons (different status codes) + // Which reponse code should we return? + // Maybe any that are not OC_API::RESPOND_SERVER_ERROR + $response = $shipped['failed'][0]; + return $response; + } else { + // Return the third party failure result + $response = $thirdparty['failed'][0]; + return $response; + } + // Merge the successful responses + $meta = array(); + $data = array(); + foreach($responses as $app => $response) { + if(OC_App::isShipped($app)) { + $data = array_merge_recursive($response->getData(), $data); + } else { + $data = array_merge_recursive($data, $response->getData()); + } + } + $result = new OC_OCS_Result($data, 100); + return $result; + } + /** * authenticate the api call * @param array $action the action details as supplied to OC_API::register() @@ -132,7 +199,8 @@ class OC_API { return false; } else { $subAdmin = OC_SubAdmin::isSubAdmin($user); - if($subAdmin) { + $admin = OC_User::isAdminUser($user); + if($subAdmin || $admin) { return true; } else { return false; @@ -153,25 +221,35 @@ class OC_API { return false; break; } - } - + } + /** * http basic auth * @return string|false (username, or false on failure) */ - private static function loginUser(){ + private static function loginUser(){ $authUser = isset($_SERVER['PHP_AUTH_USER']) ? $_SERVER['PHP_AUTH_USER'] : ''; $authPw = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; return OC_User::login($authUser, $authPw) ? $authUser : false; } - + /** * respond to a call - * @param int|array $result the result from the api method + * @param OC_OCS_Result $result * @param string $format the format xml|json */ private static function respond($result, $format='xml') { - $response = array('ocs' => $result->getResult()); + // Send 401 headers if unauthorised + if($result->getStatusCode() === self::RESPOND_UNAUTHORISED) { + header('WWW-Authenticate: Basic realm="Authorisation Required"'); + header('HTTP/1.0 401 Unauthorized'); + } + $response = array( + 'ocs' => array( + 'meta' => $result->getMeta(), + 'data' => $result->getData(), + ), + ); if ($format == 'json') { OC_JSON::encodedPrint($response); } else if ($format == 'xml') { @@ -203,5 +281,5 @@ class OC_API { } } } - + } diff --git a/lib/ocs/cloud.php b/lib/ocs/cloud.php index 5553ae38215..132d923d960 100644 --- a/lib/ocs/cloud.php +++ b/lib/ocs/cloud.php @@ -24,49 +24,23 @@ class OC_OCS_Cloud { - public static function getSystemWebApps() { - OC_Util::checkLoggedIn(); - $apps = OC_App::getEnabledApps(); - $values = array(); - foreach($apps as $app) { - $info = OC_App::getAppInfo($app); - if(isset($info['standalone'])) { - $newValue = array('name'=>$info['name'], 'url'=>OC_Helper::linkToAbsolute($app, ''), 'icon'=>''); - $values[] = $newValue; - } - } - return new OC_OCS_Result($values); - } - - public static function getUserQuota($parameters) { - $user = OC_User::getUser(); - if(OC_User::isAdminUser($user) or ($user==$parameters['user'])) { - - if(OC_User::userExists($parameters['user'])) { - // calculate the disc space - $userDir = '/'.$parameters['user'].'/files'; - \OC\Files\Filesystem::init($parameters['user'], $userDir); - $rootInfo = \OC\Files\Filesystem::getFileInfo(''); - $sharedInfo = \OC\Files\Filesystem::getFileInfo('/Shared'); - $used = $rootInfo['size'] - $sharedInfo['size']; - $free = \OC\Files\Filesystem::free_space(); - $total = $free + $used; - if($total===0) $total = 1; // prevent division by zero - $relative = round(($used/$total)*10000)/100; - - $xml = array(); - $xml['quota'] = $total; - $xml['free'] = $free; - $xml['used'] = $used; - $xml['relative'] = $relative; - - return new OC_OCS_Result($xml); - } else { - return new OC_OCS_Result(null, 300); - } - } else { - return new OC_OCS_Result(null, 300); - } + public static function getCapabilities($parameters) { + $result = array(); + list($major, $minor, $micro) = OC_Util::getVersion(); + $result['version'] = array( + 'major' => $major, + 'minor' => $minor, + 'micro' => $micro, + 'string' => OC_Util::getVersionString(), + 'edition' => OC_Util::getEditionString(), + ); + + $result['capabilities'] = array( + 'core' => array( + 'pollinterval' => OC_Config::getValue('pollinterval', 60), + ), + ); + return new OC_OCS_Result($result); } public static function getUserPublickey($parameters) { diff --git a/lib/ocs/result.php b/lib/ocs/result.php index 65b2067fc3f..8ab378d79c5 100644 --- a/lib/ocs/result.php +++ b/lib/ocs/result.php @@ -49,26 +49,48 @@ class OC_OCS_Result{ public function setItemsPerPage(int $items) { $this->perPage = $items; } - + + /** + * get the status code + * @return int + */ + public function getStatusCode() { + return $this->statusCode; + } + /** - * returns the data associated with the api result + * get the meta data for the result * @return array */ - public function getResult() { - $return = array(); - $return['meta'] = array(); - $return['meta']['status'] = ($this->statusCode === 100) ? 'ok' : 'failure'; - $return['meta']['statuscode'] = $this->statusCode; - $return['meta']['message'] = $this->message; + public function getMeta() { + $meta = array(); + $meta['status'] = ($this->statusCode === 100) ? 'ok' : 'failure'; + $meta['statuscode'] = $this->statusCode; + $meta['message'] = $this->message; if(isset($this->items)) { - $return['meta']['totalitems'] = $this->items; + $meta['totalitems'] = $this->items; } if(isset($this->perPage)) { - $return['meta']['itemsperpage'] = $this->perPage; + $meta['itemsperpage'] = $this->perPage; } - $return['data'] = $this->data; - // Return the result data. - return $return; + return $meta; + + } + + /** + * get the result data + * @return array|string|int + */ + public function getData() { + return $this->data; + } + + /** + * return bool if the method succedded + * @return bool + */ + public function succeeded() { + return (substr($this->statusCode, 0, 1) === '1'); } diff --git a/ocs/routes.php b/ocs/routes.php index d6ee589df6f..81beae2f881 100644 --- a/ocs/routes.php +++ b/ocs/routes.php @@ -17,4 +17,5 @@ OC_API::register('get', '/privatedata/getattribute/{app}', array('OC_OCS_Private OC_API::register('get', '/privatedata/getattribute/{app}/{key}', array('OC_OCS_Privatedata', 'get'), 'ocs', OC_API::USER_AUTH); OC_API::register('post', '/privatedata/setattribute/{app}/{key}', array('OC_OCS_Privatedata', 'set'), 'ocs', OC_API::USER_AUTH); OC_API::register('post', '/privatedata/deleteattribute/{app}/{key}', array('OC_OCS_Privatedata', 'delete'), 'ocs', OC_API::USER_AUTH); - +// cloud +OC_API::register('get', '/cloud/capabilities', array('OC_OCS_Cloud', 'getCapabilities'), 'core', OC_API::USER_AUTH);
\ No newline at end of file |