diff -u b/core/modules/image/css/editors/image.theme.css b/core/modules/image/css/editors/image.theme.css --- b/core/modules/image/css/editors/image.theme.css +++ b/core/modules/image/css/editors/image.theme.css @@ -62,6 +62,8 @@ font-family: "Droid sans", "Lucida Grande", sans-serif; font-size: 16px; -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; } .quickedit-image-field-info { diff -u b/core/modules/image/src/Controller/QuickEditImageController.php b/core/modules/image/src/Controller/QuickEditImageController.php --- b/core/modules/image/src/Controller/QuickEditImageController.php +++ b/core/modules/image/src/Controller/QuickEditImageController.php @@ -2,6 +2,7 @@ namespace Drupal\image\Controller; +use Drupal\Core\Cache\CacheableJsonResponse; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Entity\ContentEntityInterface; use Drupal\Core\Entity\EntityInterface; @@ -20,7 +21,7 @@ class QuickEditImageController extends ControllerBase { /** - * Stores the Quick Edit tempstore. + * Stores The Quick Edit tempstore. * * @var \Drupal\user\PrivateTempStore */ @@ -145,7 +146,7 @@ } /** - * Returns a JSON object representing an image field's metadata. + * Returns JSON representing an image field's metadata. * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity of which an image field is being rendered. @@ -156,8 +157,8 @@ * @param string $view_mode_id * The view mode of the field that is being rendered. * - * @return \Symfony\Component\HttpFoundation\JsonResponse - * The Ajax response. + * @return \Drupal\Core\Cache\CacheableJsonResponse + * The JSON response. */ public function getInfo(EntityInterface $entity, $field_name, $langcode, $view_mode_id) { $field = $this->getField($entity, $field_name, $langcode); @@ -170,11 +171,13 @@ 'alt_field_required' => $settings['alt_field_required'], 'title_field_required' => $settings['title_field_required'], ]; - return new JsonResponse($info); + $response = new CacheableJsonResponse($info); + $response->addCacheableDependency($entity); + return $response; } /** - * Returns a JSON object representing the current state of the field. + * Returns JSON representing the current state of the field. * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity of which an image field is being rendered. @@ -182,6 +185,7 @@ * The name of the (image) field that is being rendered * @param string $langcode * The language code of the field that is being rendered. + * * @return \Drupal\image\Plugin\Field\FieldType\ImageItem * The field for this request. * diff -u b/core/modules/image/src/Tests/QuickEditImageControllerTest.php b/core/modules/image/src/Tests/QuickEditImageControllerTest.php --- b/core/modules/image/src/Tests/QuickEditImageControllerTest.php +++ b/core/modules/image/src/Tests/QuickEditImageControllerTest.php @@ -2,12 +2,16 @@ namespace Drupal\image\Tests; +use Drupal\simpletest\WebTestBase; + /** * Tests the endpoints used by the "image" in-place editor. * * @group image */ -class QuickEditImageControllerTest extends ImageFieldTestBase { +class QuickEditImageControllerTest extends WebTestBase { + + use ImageFieldCreationTrait; /** * {@inheritdoc} @@ -22,15 +26,31 @@ protected $fieldName; /** + * A user with permissions to edit articles and use Quick Edit. + * + * @var \Drupal\user\UserInterface + */ + protected $contentAuthorUser; + + /** * {@inheritdoc} */ protected function setUp() { parent::setUp(); - // Grant Quick Edit access to the current admin user. - $rid = $this->createRole(['access in-place editing']); - $this->adminUser->addRole($rid); - $this->adminUser->save(); + // Create the Article node type. + $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); + + // Log in as a content author who can use Quick Edit and edit Articles. + $this->contentAuthorUser = $this->drupalCreateUser([ + 'access contextual links', + 'access in-place editing', + 'access content', + 'create article content', + 'edit any article content', + 'delete any article content', + ]); + $this->drupalLogin($this->contentAuthorUser); // Create a field with basic resolution validators. $this->fieldName = strtolower($this->randomMachineName()); @@ -42,6 +62,25 @@ } /** + * Tests that routes restrict access for un-privileged users. + */ + function testAccess() { + // Create an anonymous user. + $user = $this->createUser(); + $this->drupalLogin($user); + + // Create a test Node. + $node = $this->drupalCreateNode([ + 'type' => 'article', + 'title' => t('Test Node'), + ]); + $this->drupalGet('quickedit/image/info/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default'); + $this->assertResponse('403'); + $this->drupalPost('quickedit/image/upload/node/' . $node->id() . '/' . $this->fieldName . '/' . $node->language()->getId() . '/default', 'application/json', []); + $this->assertResponse('403'); + } + + /** * Tests that the field info route returns expected data. */ function testFieldInfo() { diff -u b/core/modules/image/tests/src/FunctionalJavascript/QuickEditImageTest.php b/core/modules/image/tests/src/FunctionalJavascript/QuickEditImageTest.php --- b/core/modules/image/tests/src/FunctionalJavascript/QuickEditImageTest.php +++ b/core/modules/image/tests/src/FunctionalJavascript/QuickEditImageTest.php @@ -23,11 +23,11 @@ public static $modules = ['node', 'image', 'field_ui', 'contextual', 'quickedit']; /** - * A user with permissions to administer content types and use Quick Edit. + * A user with permissions to edit Articles and use Quick Edit. * * @var \Drupal\user\UserInterface */ - protected $adminUser; + protected $contentAuthorUser; /** * {@inheritdoc} @@ -38,9 +38,16 @@ // Create the Article node type. $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']); - // Login as an admin user who can use Quick Edit and edit Articles. - $this->adminUser = $this->drupalCreateUser(['access contextual links', 'access in-place editing', 'access content', 'access administration pages', 'administer site configuration', 'administer content types', 'administer node fields', 'administer nodes', 'create article content', 'edit any article content', 'delete any article content', 'administer node display']); - $this->drupalLogin($this->adminUser); + // Log in as a content author who can use Quick Edit and edit Articles. + $this->contentAuthorUser = $this->drupalCreateUser([ + 'access contextual links', + 'access in-place editing', + 'access content', + 'create article content', + 'edit any article content', + 'delete any article content', + ]); + $this->drupalLogin($this->contentAuthorUser); } /** @@ -74,7 +81,7 @@ // Create a File entity for the initial image. $file = File::create([ 'uri' => $valid_images[0]->uri, - 'uid' => $this->adminUser->id(), + 'uid' => $this->contentAuthorUser->id(), 'status' => FILE_STATUS_PERMANENT, ]); $file->save(); @@ -143,7 +150,7 @@ // Wait for the dropzone element to be removed (i.e. loading is done). $condition = "jQuery('" . $field_selector . " .quickedit-image-dropzone').length == 0"; - $this->assertJsCondition($condition, 10000); + $this->assertJsCondition($condition, 20000); // To prevent 403s on save, we re-set our request (cookie) state. $this->prepareRequest(); diff -u b/core/themes/stable/css/image/editors/image.theme.css b/core/themes/stable/css/image/editors/image.theme.css --- b/core/themes/stable/css/image/editors/image.theme.css +++ b/core/themes/stable/css/image/editors/image.theme.css @@ -62,6 +62,8 @@ font-family: "Droid sans", "Lucida Grande", sans-serif; font-size: 16px; -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; } .quickedit-image-field-info {