/** * Returns an array of REST permissions. * * @return array */ public function permissions() { $permissions = []; $resources = $this->configFactory->get('rest.settings')->get('resources'); if ($resources && ($enabled = array_intersect_key($this->restPluginManager->getDefinitions(), $resources))) { foreach ($enabled as $key => $resource) { $plugin = $this->restPluginManager->getInstance(['id' => $key]); $permissions = array_merge($permissions, $plugin->permissions()); } } return $permissions; }
/** * Returns an administrative overview of all REST resources. * * @return string * A HTML-formatted string with the administrative page content. * */ public function listResources() { // Get the list of enabled and disabled resources. $config = \Drupal::config('rest.settings')->get('resources') ?: array(); // Strip out the nested method configuration, we are only interested in the // plugin IDs of the resources. $enabled_resources = array_combine(array_keys($config), array_keys($config)); $available_resources = array('enabled' => array(), 'disabled' => array()); $resources = $this->resourcePluginManager->getDefinitions(); foreach ($resources as $id => $resource) { $status = in_array($id, $enabled_resources) ? 'enabled' : 'disabled'; $available_resources[$status][$id] = $resource; } // Sort the list of resources by label. $sort_resources = function ($resource_a, $resource_b) { return strcmp($resource_a['label'], $resource_b['label']); }; if (!empty($available_resources['enabled'])) { uasort($available_resources['enabled'], $sort_resources); } if (!empty($available_resources['disabled'])) { uasort($available_resources['disabled'], $sort_resources); } // Heading. $list['resources_title'] = array('#markup' => '<h2>' . t('REST resources') . '</h2>'); $list['resources_help'] = array('#markup' => '<p>' . t('Here you can enable and disable available resources. Once a resource ' . 'has been enabled, you can restrict its formats and authentication by ' . 'clicking on its "Edit" link.') . '</p>'); $list['enabled']['heading']['#markup'] = '<h2>' . t('Enabled') . '</h2>'; $list['disabled']['heading']['#markup'] = '<h2>' . t('Disabled') . '</h2>'; // List of resources. foreach (array('enabled', 'disabled') as $status) { $list[$status]['#type'] = 'container'; $list[$status]['#attributes'] = array('class' => array('rest-ui-list-section', $status)); $list[$status]['table'] = array('#theme' => 'table', '#header' => array('resource_name' => array('data' => t('Resource name'), 'class' => array('rest-ui-name')), 'path' => array('data' => t('Path'), 'class' => array('views-ui-path')), 'description' => array('data' => t('Description'), 'class' => array('rest-ui-description')), 'operations' => array('data' => t('Operations'), 'class' => array('rest-ui-operations'))), '#rows' => array()); foreach ($available_resources[$status] as $id => $resource) { $uri_paths = '<code>' . $resource['uri_paths']['canonical'] . '</code>'; $list[$status]['table']['#rows'][$id] = array('data' => array('name' => $resource['label'], 'path' => array('data' => array('#type' => 'inline_template', '#template' => $uri_paths)), 'description' => array(), 'operations' => array())); if ($status == 'disabled') { $list[$status]['table']['#rows'][$id]['data']['operations']['data'] = array('#type' => 'operations', '#links' => array('enable' => array('title' => t('Enable'), 'url' => Url::fromRoute('restui.edit', array('resource_id' => $id))))); } else { $list[$status]['table']['#rows'][$id]['data']['operations']['data'] = array('#type' => 'operations', '#links' => array('edit' => array('title' => t('Edit'), 'url' => Url::fromRoute('restui.edit', array('resource_id' => $id))), 'disable' => array('title' => t('Disable'), 'url' => Url::fromRoute('restui.disable', array('resource_id' => $id), array('query' => array('token' => \Drupal::csrfToken()->get('restui_disable'))))))); $list[$status]['table']['#rows'][$id]['data']['description']['data'] = array('#theme' => 'restui_resource_info', '#resource' => $config[$id]); } } } $list['enabled']['table']['#empty'] = t('There are no enabled resources.'); $list['disabled']['table']['#empty'] = t('There are no disabled resources.'); $list['#title'] = t('REST resources'); return $list; }
/** * Alters existing routes for a specific collection. * * @param \Symfony\Component\Routing\RouteCollection $collection * The route collection for adding routes. * @return array */ protected function alterRoutes(RouteCollection $collection) { $routes = array(); // Silently ignore resources that are in the settings but are not defined on // the plugin manager currently. That avoids exceptions when REST module is // enabled before another module that provides the resource plugin specified // in the settings. // @todo Remove in https://www.drupal.org/node/2308745 $resources = $this->config->get('rest.settings')->get('resources') ?: array(); $enabled_resources = array_intersect_key($resources, $this->manager->getDefinitions()); if (count($resources) != count($enabled_resources)) { trigger_error('rest.settings lists resources relying on the following missing plugins: ' . implode(', ', array_keys(array_diff_key($resources, $enabled_resources)))); } // Iterate over all enabled resource plugins. foreach ($enabled_resources as $id => $enabled_methods) { $plugin = $this->manager->getInstance(array('id' => $id)); foreach ($plugin->routes() as $name => $route) { // @todo: Are multiple methods possible here? $methods = $route->getMethods(); // Only expose routes where the method is enabled in the configuration. if ($methods && ($method = $methods[0]) && $method && isset($enabled_methods[$method])) { $route->setRequirement('_access_rest_csrf', 'TRUE'); // Check that authentication providers are defined. if (empty($enabled_methods[$method]['supported_auth']) || !is_array($enabled_methods[$method]['supported_auth'])) { $this->logger->error('At least one authentication provider must be defined for resource @id', array(':id' => $id)); continue; } // Check that formats are defined. if (empty($enabled_methods[$method]['supported_formats']) || !is_array($enabled_methods[$method]['supported_formats'])) { $this->logger->error('At least one format must be defined for resource @id', array(':id' => $id)); continue; } // If the route has a format requirement, then verify that the // resource has it. $format_requirement = $route->getRequirement('_format'); if ($format_requirement && !in_array($format_requirement, $enabled_methods[$method]['supported_formats'])) { continue; } // The configuration seems legit at this point, so we set the // authentication provider and add the route. $route->setOption('_auth', $enabled_methods[$method]['supported_auth']); $routes["rest.{$name}"] = $route; $collection->add("rest.{$name}", $route); } } } }