Skip to content

Commit

Permalink
EZP-29744: Implement permissions for Content/Create in Sub-items table (
Browse files Browse the repository at this point in the history
#725)

* EZP-29744: Implement permissions for Content/Create in Sub-items table - backend

* Updated MFU config with permissions map

* EZP-29744: Implement permissions for Content/Create in Sub-items table - backend

* EZP-29744: Implement permissions for Content/Create in Sub-items table - change name of data attribute

* EZP-29744: Implement permissions for Content/Create in Sub-items table - move logic to another class
  • Loading branch information
mikadamczyk authored and Łukasz Serwatka committed Dec 10, 2018
1 parent 276b9a5 commit f5c89ec
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 40 deletions.
8 changes: 6 additions & 2 deletions src/bundle/Controller/ContentViewController.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ public function __construct(
*
* @return \eZ\Publish\Core\MVC\Symfony\View\ContentView
*
* @throws \EzSystems\EzPlatformAdminUi\Exception\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
*/
Expand Down Expand Up @@ -214,7 +216,9 @@ private function supplyContentType(ContentView $view): void
/**
* @param \eZ\Publish\Core\MVC\Symfony\View\ContentView $view
*
* @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException
* @throws \EzSystems\EzPlatformAdminUi\Exception\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
*/
private function supplyContentActionForms(ContentView $view): void
{
Expand Down Expand Up @@ -431,7 +435,7 @@ private function supplyPolicyPagination(ContentView $view, Request $request): vo
private function getContentCreateData(?Location $location): ContentCreateData
{
$languages = $this->languageService->loadLanguages();
$language = 1 === count($languages)
$language = 1 === \count($languages)
? array_shift($languages)
: null;

Expand Down
75 changes: 39 additions & 36 deletions src/bundle/Resources/public/js/scripts/admin.location.view.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
(function (global, doc, $) {
(function(global, doc, $, React, ReactDOM, eZ, Routing) {
const listContainers = [...doc.querySelectorAll('.ez-sil')];
const mfuContainer = doc.querySelector('#ez-mfu');
const token = doc.querySelector('meta[name="CSRF-Token"]').content;
Expand All @@ -7,24 +7,25 @@
const sortField = sortContainer.getAttribute('data-sort-field');
const sortOrder = sortContainer.getAttribute('data-sort-order');
const mfuAttrs = {
adminUiConfig: Object.assign({}, global.eZ.adminUiConfig, {
adminUiConfig: Object.assign({}, eZ.adminUiConfig, {
token,
siteaccess
siteaccess,
}),
parentInfo: {
contentTypeIdentifier: mfuContainer.dataset.parentContentTypeIdentifier,
contentTypeId: parseInt(mfuContainer.dataset.parentContentTypeId, 10),
locationPath: mfuContainer.dataset.parentLocationPath,
language: mfuContainer.dataset.parentContentLanguage
language: mfuContainer.dataset.parentContentLanguage,
},
};
const handleEditItem = (content) => {
const contentId = content._id;
const checkVersionDraftLink = window.Routing.generate('ezplatform.version_draft.has_no_conflict', { contentId });
const checkVersionDraftLink = Routing.generate('ezplatform.version_draft.has_no_conflict', { contentId });
const submitVersionEditForm = () => {
doc.querySelector('#form_subitems_content_edit_content_info').value = contentId;
doc.querySelector('#form_subitems_content_edit_version_info_content_info').value = contentId;
doc.querySelector('#form_subitems_content_edit_version_info_version_no').value = content.CurrentVersion.Version.VersionInfo.versionNo;
doc.querySelector('#form_subitems_content_edit_version_info_version_no').value =
content.CurrentVersion.Version.VersionInfo.versionNo;
doc.querySelector(`#form_subitems_content_edit_language_${content.mainLanguageCode}`).checked = true;
doc.querySelector('#form_subitems_content_edit_create').click();
};
Expand All @@ -40,12 +41,14 @@
if (addDraftButton) {
addDraftButton.addEventListener('click', addDraft, false);
}
[...wrapper.querySelectorAll('.ez-btn--prevented')].forEach(btn => btn.addEventListener('click', event => event.preventDefault(), false));
[...wrapper.querySelectorAll('.ez-btn--prevented')].forEach((btn) =>
btn.addEventListener('click', (event) => event.preventDefault(), false)
);
$('#version-draft-conflict-modal').modal('show');
};
fetch(checkVersionDraftLink, {
credentials: 'same-origin'
}).then(function (response) {
credentials: 'same-origin',
}).then(function(response) {
// Status 409 means that a draft conflict has occurred and the modal must be displayed.
// Otherwise we can go to Content Item edit page.
if (response.status === 409) {
Expand All @@ -55,13 +58,13 @@
}
});
};
const generateLink = (locationId) => window.Routing.generate('_ezpublishLocation', { locationId });
const generateLink = (locationId) => Routing.generate('_ezpublishLocation', { locationId });

listContainers.forEach(container => {
listContainers.forEach((container) => {
const subItemsList = JSON.parse(container.dataset.items).SubitemsList;
const items = subItemsList.SubitemsRow.map(item => ({
const items = subItemsList.SubitemsRow.map((item) => ({
content: item.Content,
location: item.Location
location: item.Location,
}));
const contentTypes = JSON.parse(container.dataset.contentTypes).ContentTypeInfoList.ContentType;
const contentTypesMap = contentTypes.reduce((total, item) => {
Expand All @@ -71,28 +74,28 @@
}, {});
const udwConfigBulkMoveItems = JSON.parse(container.dataset.udwConfigBulkMoveItems);

global.ReactDOM.render(global.React.createElement(global.eZ.modules.SubItems, {
handleEditItem,
generateLink,
parentLocationId: parseInt(container.dataset.location, 10),
sortClauses: {[sortField]: sortOrder},
restInfo: {token, siteaccess},
extraActions: [{
component: global.eZ.modules.MultiFileUpload,
attrs: Object.assign({}, mfuAttrs, {
onPopupClose: (itemsUploaded) => {
if (itemsUploaded.length) {
window.location.reload(true);
}
ReactDOM.render(
React.createElement(eZ.modules.SubItems, {
handleEditItem,
generateLink,
parentLocationId: parseInt(container.dataset.location, 10),
sortClauses: { [sortField]: sortOrder },
restInfo: { token, siteaccess },
extraActions: [
{
component: eZ.modules.MultiFileUpload,
attrs: Object.assign({}, mfuAttrs, {
onPopupClose: (itemsUploaded) => itemsUploaded.length && global.location.reload(true),
contentCreatePermissionsConfig: JSON.parse(container.dataset.mfuCreatePermissionsConfig),
}),
},
popupOnly: false,
asButton: true
})
}],
items,
contentTypesMap,
totalCount: subItemsList.ChildrenCount,
udwConfigBulkMoveItems,
}), container);
],
items,
contentTypesMap,
totalCount: subItemsList.ChildrenCount,
udwConfigBulkMoveItems,
}),
container
);
});
})(window, window.document, window.jQuery);
})(window, window.document, window.jQuery, window.React, window.ReactDOM, window.eZ, window.Routing);
5 changes: 3 additions & 2 deletions src/bundle/Resources/views/content/locationview.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@
<section class="ez-fieldgroup">
<h2 class="ez-fieldgroup__name">{{ 'content.view.subitems'|trans|desc('Sub-items') }}</h2>
<div class="ez-sil"
data-location="{{ location.id }}"
data-items="{{ subitems_module.items }}"
data-location="{{ location.id }}"
data-mfu-create-permissions-config="{{ subitems_module.content_create_permissions_for_mfu|json_encode() }}"
data-items="{{ subitems_module.items }}"
data-content-types="{{ subitems_module.content_type_info_list }}"
data-udw-config-bulk-move-items="{{ ez_udw_config('single_container', {}) }}"
></div>
Expand Down
55 changes: 55 additions & 0 deletions src/lib/UI/Module/Subitems/ContentViewParameterSupplier.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@
use eZ\Publish\API\Repository\ContentService;
use eZ\Publish\API\Repository\ContentTypeService;
use eZ\Publish\API\Repository\LocationService;
use eZ\Publish\API\Repository\PermissionResolver;
use eZ\Publish\API\Repository\Values\Content\Location;
use eZ\Publish\API\Repository\Values\Content\Content;
use eZ\Publish\API\Repository\Values\ContentType\ContentType;
use eZ\Publish\Core\MVC\Symfony\View\ContentView;
use eZ\Publish\Core\REST\Common\Output\Visitor;
use eZ\Publish\Core\REST\Server\Output\ValueObjectVisitor\ContentTypeInfoList as ContentTypeInfoListValueObjectVisitor;
use eZ\Publish\Core\REST\Server\Values\ContentTypeInfoList;
use eZ\Publish\Core\REST\Server\Values\RestContent;
use eZ\Publish\Core\REST\Server\Values\RestLocation;
use EzSystems\EzPlatformAdminUi\UI\Config\Provider\ContentTypeMappings;
use EzSystems\EzPlatformAdminUi\UI\Module\Subitems\ValueObjectVisitor\SubitemsList as SubitemsListValueObjectVisitor;
use EzSystems\EzPlatformAdminUi\UI\Module\Subitems\Values\SubitemsList;
use EzSystems\EzPlatformAdminUi\UI\Module\Subitems\Values\SubitemsRow;
Expand Down Expand Up @@ -50,6 +53,12 @@ class ContentViewParameterSupplier
/** @var \eZ\Publish\API\Repository\ContentTypeService */
private $contentTypeService;

/** @var \eZ\Publish\API\Repository\PermissionResolver */
private $permissionResolver;

/** @var \EzSystems\EzPlatformAdminUi\UI\Config\Provider\ContentTypeMappings */
private $contentTypeMappings;

/** @var int */
private $subitemsLimit;

Expand All @@ -61,6 +70,8 @@ class ContentViewParameterSupplier
* @param \eZ\Publish\API\Repository\LocationService $locationService
* @param \eZ\Publish\API\Repository\ContentService $contentService
* @param \eZ\Publish\API\Repository\ContentTypeService $contentTypeService
* @param \eZ\Publish\API\Repository\PermissionResolver $permissionResolver
* @param \EzSystems\EzPlatformAdminUi\UI\Config\Provider\ContentTypeMappings $contentTypeMappings
* @param int $subitemsLimit
*/
public function __construct(
Expand All @@ -71,6 +82,8 @@ public function __construct(
LocationService $locationService,
ContentService $contentService,
ContentTypeService $contentTypeService,
PermissionResolver $permissionResolver,
ContentTypeMappings $contentTypeMappings,
int $subitemsLimit
) {
$this->outputVisitor = $outputVisitor;
Expand All @@ -80,6 +93,8 @@ public function __construct(
$this->locationService = $locationService;
$this->contentService = $contentService;
$this->contentTypeService = $contentTypeService;
$this->permissionResolver = $permissionResolver;
$this->contentTypeMappings = $contentTypeMappings;
$this->subitemsLimit = $subitemsLimit;
}

Expand All @@ -94,6 +109,8 @@ public function __construct(
*
* @param \eZ\Publish\Core\MVC\Symfony\View\ContentView $view
*
* @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
*/
Expand Down Expand Up @@ -128,6 +145,7 @@ public function supply(ContentView $view)
/* @deprecated since version 2.2, to be removed in 3.0 */
'limit' => $this->subitemsLimit,
'content_type_info_list' => $contentTypeInfoListJson,
'content_create_permissions_for_mfu' => $this->getContentCreatePermissionsForMFU($view->getLocation(), $view->getContent()),
],
]);
}
Expand Down Expand Up @@ -213,4 +231,41 @@ private function visitContentTypeInfoList(ContentTypeInfoList $contentTypeInfoLi

return $this->outputGenerator->endDocument($contentTypeInfoList);
}

/**
* @param \eZ\Publish\API\Repository\Values\Content\Location $location
* @param \eZ\Publish\API\Repository\Values\Content\Content $content
*
* @return array
*
* @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException
*/
private function getContentCreatePermissionsForMFU(Location $location, Content $content): array
{
$createPermissionsInMfu = [];

$hasAccess = $this->permissionResolver->hasAccess('content', 'create');
$defaultContentTypeIdentifiers = array_column($this->contentTypeMappings->getConfig()['defaultMappings'], 'contentTypeIdentifier');
$defaultContentTypeIdentifiers[] = $this->contentTypeMappings->getConfig()['fallbackContentType']['contentTypeIdentifier'];
$contentTypeIdentifiers = array_unique($defaultContentTypeIdentifiers);

if (\is_bool($hasAccess)) {
foreach ($contentTypeIdentifiers as $contentTypeIdentifier) {
$createPermissionsInMfu[$contentTypeIdentifier] = $hasAccess;
}
} else {
$locationCreateStruct = $this->locationService->newLocationCreateStruct($location->id);
foreach ($contentTypeIdentifiers as $contentTypeIdentifier) {
// TODO: Change to `contentTypeService->loadContentTypeList($restrictedContentTypesIds)` after #2444 will be merged
$contentType = $this->contentTypeService->loadContentTypeByIdentifier($contentTypeIdentifier);
$contentCreateStruct = $this->contentService->newContentCreateStruct($contentType, $content->versionInfo->initialLanguageCode);
$contentCreateStruct->sectionId = $location->contentInfo->sectionId;
$createPermissionsInMfu[$contentTypeIdentifier] = $this->permissionResolver->canUser('content', 'create', $contentCreateStruct, [$locationCreateStruct]);
}
}

return $createPermissionsInMfu;
}
}

0 comments on commit f5c89ec

Please sign in to comment.