Merge pull request #400 from nextcloud/ocs_appframework

OCS routes use AppFramework
This commit is contained in:
Roeland Douma 2016-07-19 12:21:14 +02:00 committed by GitHub
commit 13a25535d2
5 changed files with 224 additions and 1 deletions

View file

@ -905,7 +905,7 @@ class OC {
* @param OCP\IRequest $request
* @return boolean
*/
private static function handleLogin(OCP\IRequest $request) {
static function handleLogin(OCP\IRequest $request) {
$userSession = self::$server->getUserSession();
if (OC_User::handleApacheAuth()) {
return true;

View file

@ -62,6 +62,61 @@ class RouteConfig {
// parse resources
$this->processResources($this->routes);
/*
* OCS routes go into a different collection
*/
$oldCollection = $this->router->getCurrentCollection();
$this->router->useCollection($oldCollection.'.ocs');
// parse ocs simple routes
$this->processOCS($this->routes);
$this->router->useCollection($oldCollection);
}
private function processOCS(array $routes) {
$ocsRoutes = isset($routes['ocs']) ? $routes['ocs'] : [];
foreach ($ocsRoutes as $ocsRoute) {
$name = $ocsRoute['name'];
$postfix = '';
if (isset($ocsRoute['postfix'])) {
$postfix = $ocsRoute['postfix'];
}
$url = $ocsRoute['url'];
$verb = isset($ocsRoute['verb']) ? strtoupper($ocsRoute['verb']) : 'GET';
$split = explode('#', $name, 2);
if (count($split) != 2) {
throw new \UnexpectedValueException('Invalid route name');
}
$controller = $split[0];
$action = $split[1];
$controllerName = $this->buildControllerName($controller);
$actionName = $this->buildActionName($action);
// register the route
$handler = new RouteActionHandler($this->container, $controllerName, $actionName);
$router = $this->router->create('ocs.'.$this->appName.'.'.$controller.'.'.$action . $postfix, $url)
->method($verb)
->action($handler);
// optionally register requirements for route. This is used to
// tell the route parser how url parameters should be matched
if(array_key_exists('requirements', $ocsRoute)) {
$router->requirements($ocsRoute['requirements']);
}
// optionally register defaults for route. This is used to
// tell the route parser how url parameters should be default valued
if(array_key_exists('defaults', $ocsRoute)) {
$router->defaults($ocsRoute['defaults']);
}
}
}
/**

View file

@ -150,6 +150,11 @@ class Router implements IRouter {
$collection = $this->getCollection($app);
$collection->addPrefix('/apps/' . $app);
$this->root->addCollection($collection);
// Also add the OCS collection
$collection = $this->getCollection($app.'.ocs');
$collection->addPrefix('/ocsapp/apps/' . $app);
$this->root->addCollection($collection);
}
}
if (!isset($this->loadedApps['core'])) {
@ -238,6 +243,13 @@ class Router implements IRouter {
// empty string / 'apps' / $app / rest of the route
list(, , $app,) = explode('/', $url, 4);
$app = \OC_App::cleanAppId($app);
\OC::$REQUESTEDAPP = $app;
$this->loadRoutes($app);
} else if (substr($url, 0, 13) === '/ocsapp/apps/') {
// empty string / 'ocsapp' / 'apps' / $app / rest of the route
list(, , , $app,) = explode('/', $url, 5);
$app = \OC_App::cleanAppId($app);
\OC::$REQUESTEDAPP = $app;
$this->loadRoutes($app);

View file

@ -42,6 +42,10 @@ if (\OCP\Util::needUpgrade()
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
/*
* Try old routes first
* We first try the old routes since the appframework triggers more login stuff.
*/
try {
OC_App::loadApps(['session']);
OC_App::loadApps(['authentication']);
@ -52,6 +56,24 @@ try {
\OC::$server->getL10NFactory()->setLanguageFromRequest();
OC::$server->getRouter()->match('/ocs'.\OC::$server->getRequest()->getRawPathInfo());
return;
} catch (ResourceNotFoundException $e) {
// Fall through the not found
} catch (MethodNotAllowedException $e) {
OC_API::setContentType();
OC_Response::setStatus(405);
} catch (\OC\OCS\Exception $ex) {
OC_API::respond($ex->getResult(), OC_API::requestedFormat());
}
/*
* Try the appframework routes
*/
try {
if(!\OC::$server->getUserSession()->isLoggedIn()) {
OC::handleLogin(\OC::$server->getRequest());
}
OC::$server->getRouter()->match('/ocsapp'.\OC::$server->getRequest()->getRawPathInfo());
} catch (ResourceNotFoundException $e) {
OC_API::setContentType();
OC_OCS::notFound();
@ -60,5 +82,8 @@ try {
OC_Response::setStatus(405);
} catch (\OC\OCS\Exception $ex) {
OC_API::respond($ex->getResult(), OC_API::requestedFormat());
} catch (\Exception $e) {
OC_API::setContentType();
OC_OCS::notFound();
}

View file

@ -18,6 +18,15 @@ class RoutingTest extends \Test\TestCase
$this->assertSimpleRoute($routes, 'folders.open', 'GET', '/folders/{folderId}/open', 'FoldersController', 'open');
}
public function testSimpleOCSRoute() {
$routes = ['ocs' => [
['name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'GET']
]
];
$this->assertSimpleOCSRoute($routes, 'folders.open', 'GET', '/folders/{folderId}/open', 'FoldersController', 'open');
}
public function testSimpleRouteWithMissingVerb()
{
$routes = array('routes' => array(
@ -27,6 +36,15 @@ class RoutingTest extends \Test\TestCase
$this->assertSimpleRoute($routes, 'folders.open', 'GET', '/folders/{folderId}/open', 'FoldersController', 'open');
}
public function testSimpleOCSRouteWithMissingVerb() {
$routes = ['ocs' => [
['name' => 'folders#open', 'url' => '/folders/{folderId}/open']
]
];
$this->assertSimpleOCSRoute($routes, 'folders.open', 'GET', '/folders/{folderId}/open', 'FoldersController', 'open');
}
public function testSimpleRouteWithLowercaseVerb()
{
$routes = array('routes' => array(
@ -36,6 +54,15 @@ class RoutingTest extends \Test\TestCase
$this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open');
}
public function testSimpleOCSRouteWithLowercaseVerb() {
$routes = ['ocs' => [
['name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete']
]
];
$this->assertSimpleOCSRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open');
}
public function testSimpleRouteWithRequirements()
{
$routes = array('routes' => array(
@ -45,6 +72,15 @@ class RoutingTest extends \Test\TestCase
$this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open', array('something'));
}
public function testSimpleOCSRouteWithRequirements() {
$routes = ['ocs' => [
['name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete', 'requirements' => ['something']]
]
];
$this->assertSimpleOCSRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open', ['something']);
}
public function testSimpleRouteWithDefaults()
{
$routes = array('routes' => array(
@ -54,6 +90,16 @@ class RoutingTest extends \Test\TestCase
$this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open', array(), array('param' => 'foobar'));
}
public function testSimpleOCSRouteWithDefaults() {
$routes = ['ocs' => [
['name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete', 'defaults' => ['param' => 'foobar']]
]
];
$this->assertSimpleOCSRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open', [], ['param' => 'foobar']);
}
public function testSimpleRouteWithPostfix()
{
$routes = array('routes' => array(
@ -63,6 +109,14 @@ class RoutingTest extends \Test\TestCase
$this->assertSimpleRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open', array(), array(), '_something');
}
public function testSimpleOCSRouteWithPostfix() {
$routes = ['ocs' => [
['name' => 'folders#open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete', 'postfix' => '_something']
]
];
$this->assertSimpleOCSRoute($routes, 'folders.open', 'DELETE', '/folders/{folderId}/open', 'FoldersController', 'open', [], [], '_something');
}
/**
* @expectedException \UnexpectedValueException
@ -86,6 +140,27 @@ class RoutingTest extends \Test\TestCase
$config->register();
}
/**
* @expectedException \UnexpectedValueException
*/
public function testSimpleOCSRouteWithBrokenName() {
$routes = ['ocs' => [
['name' => 'folders_open', 'url' => '/folders/{folderId}/open', 'verb' => 'delete']
]];
// router mock
$router = $this->getMockBuilder('\OC\Route\Router')
->setMethods(['create'])
->setConstructorArgs([$this->getMockBuilder('\OCP\ILogger')->getMock()])
->getMock();
// load route configuration
$container = new DIContainer('app1');
$config = new RouteConfig($container, $router, $routes);
$config->register();
}
public function testSimpleRouteWithUnderScoreNames()
{
$routes = array('routes' => array(
@ -95,6 +170,14 @@ class RoutingTest extends \Test\TestCase
$this->assertSimpleRoute($routes, 'admin_folders.open_current', 'DELETE', '/folders/{folderId}/open', 'AdminFoldersController', 'openCurrent');
}
public function testSimpleOCSRouteWithUnderScoreNames() {
$routes = ['ocs' => [
['name' => 'admin_folders#open_current', 'url' => '/folders/{folderId}/open', 'verb' => 'delete']
]];
$this->assertSimpleOCSRoute($routes, 'admin_folders.open_current', 'DELETE', '/folders/{folderId}/open', 'AdminFoldersController', 'openCurrent');
}
public function testResource()
{
$routes = array('resources' => array('account' => array('url' => '/accounts')));
@ -145,6 +228,54 @@ class RoutingTest extends \Test\TestCase
$config->register();
}
/**
* @param $routes
* @param string $name
* @param string $verb
* @param string $url
* @param string $controllerName
* @param string $actionName
* @param array $requirements
* @param array $defaults
* @param string $postfix
*/
private function assertSimpleOCSRoute($routes,
$name,
$verb,
$url,
$controllerName,
$actionName,
array $requirements=array(),
array $defaults=array(),
$postfix='')
{
if ($postfix) {
$name .= $postfix;
}
// route mocks
$container = new DIContainer('app1');
$route = $this->mockRoute($container, $verb, $controllerName, $actionName, $requirements, $defaults);
// router mock
$router = $this->getMockBuilder('\OC\Route\Router')
->setMethods(['create'])
->setConstructorArgs([$this->getMockBuilder('\OCP\ILogger')->getMock()])
->getMock();
// we expect create to be called once:
$router
->expects($this->once())
->method('create')
->with($this->equalTo('ocs.app1.' . $name), $this->equalTo($url))
->will($this->returnValue($route));
// load route configuration
$config = new RouteConfig($container, $router, $routes);
$config->register();
}
/**
* @param string $resourceName
* @param string $url