Skip to content

Commit

Permalink
EZP-29101: Implement permissions for Content Types
Browse files Browse the repository at this point in the history
  • Loading branch information
mikadamczyk committed Jun 28, 2018
1 parent 144397d commit 940986d
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 99 deletions.
19 changes: 10 additions & 9 deletions src/bundle/Controller/ContentTypeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,15 @@
use Pagerfanta\Adapter\ArrayAdapter;
use Pagerfanta\Pagerfanta;
use eZ\Publish\API\Repository\Exceptions\BadStateException;
use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException;
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
use Symfony\Component\Translation\Exception\InvalidArgumentException as TranslationInvalidArgumentException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Translation\TranslatorInterface;
use eZ\Publish\API\Repository\UserService;
use eZ\Publish\Core\MVC\Symfony\Security\Authorization\Attribute;

class ContentTypeController extends Controller
{
Expand Down Expand Up @@ -138,6 +137,9 @@ public function listAction(ContentTypeGroup $group, string $routeName, int $page
'form_content_types_delete' => $deleteContentTypesForm->createView(),
'group' => $group,
'route_name' => $routeName,
'can_create' => $this->isGranted(new Attribute('class', 'create')),
'can_update' => $this->isGranted(new Attribute('class', 'update')),
'can_delete' => $this->isGranted(new Attribute('class', 'delete')),
]);
}

Expand All @@ -152,6 +154,7 @@ public function listAction(ContentTypeGroup $group, string $routeName, int $page
*/
public function addAction(ContentTypeGroup $group): Response
{
$this->denyAccessUnlessGranted(new Attribute('class', 'create'));
$mainLanguageCode = reset($this->languages);

$createStruct = $this->contentTypeService->newContentTypeCreateStruct('__new__' . md5((string)microtime(true)));
Expand Down Expand Up @@ -195,6 +198,7 @@ public function addAction(ContentTypeGroup $group): Response
*/
public function editAction(ContentTypeGroup $group, ContentType $contentType): Response
{
$this->denyAccessUnlessGranted(new Attribute('class', 'update'));
// Kernel does not allow editing the same Content Type simultaneously by more than one user.
// So we need to catch 'BadStateException' and inform user about another user editing the Content Type
try {
Expand Down Expand Up @@ -302,12 +306,11 @@ public function updateAction(Request $request, ContentTypeGroup $group, ContentT
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
* @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
* @throws \Symfony\Component\Translation\Exception\InvalidArgumentException
*/
public function deleteAction(Request $request, ContentTypeGroup $group, ContentType $contentType): Response
{
$this->denyAccessUnlessGranted(new Attribute('class', 'delete'));
$form = $this->createDeleteForm($group, $contentType);
$form->handleRequest($request);

Expand Down Expand Up @@ -343,16 +346,13 @@ public function deleteAction(Request $request, ContentTypeGroup $group, ContentT
*
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws BadStateException
* @throws TranslationInvalidArgumentException
* @throws InvalidOptionsException
* @throws UnauthorizedException
* @throws InvalidArgumentException
* @throws NotFoundException
* @throws \InvalidArgumentException
*/
public function bulkDeleteAction(Request $request, ContentTypeGroup $group): Response
{
$this->denyAccessUnlessGranted(new Attribute('class', 'delete'));
$form = $this->formFactory->deleteContentTypes(
new ContentTypesDeleteData()
);
Expand Down Expand Up @@ -401,6 +401,7 @@ public function viewAction(ContentTypeGroup $group, ContentType $contentType): R
'content_type_group' => $group,
'content_type' => $contentType,
'field_definitions_by_group' => $fieldDefinitionsByGroup,
'can_update' => $this->isGranted(new Attribute('class', 'update')),
]);
}

Expand Down Expand Up @@ -455,7 +456,7 @@ protected function createDeleteForm(ContentTypeGroup $group, ContentType $conten
}

/**
* @param ContentType[] $contentTypes
* @param \eZ\Publish\API\Repository\Values\ContentType\ContentType[] $contentTypes
*
* @return array
*/
Expand Down
77 changes: 44 additions & 33 deletions src/bundle/Controller/ContentTypeGroupController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,28 +22,24 @@
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException;
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
use Symfony\Component\Translation\Exception\InvalidArgumentException as TranslationInvalidArgumentException;
use Symfony\Component\Translation\TranslatorInterface;
use eZ\Publish\Core\MVC\Symfony\Security\Authorization\Attribute;

class ContentTypeGroupController extends Controller
{
/** @var NotificationHandlerInterface */
/** @var \EzSystems\EzPlatformAdminUi\Notification\NotificationHandlerInterface */
private $notificationHandler;

/** @var TranslatorInterface */
/** @var \Symfony\Component\Translation\TranslatorInterface */
private $translator;

/** @var ContentTypeService */
/** @var \eZ\Publish\API\Repository\ContentTypeService */
private $contentTypeService;

/** @var FormFactory */
/** @var \EzSystems\EzPlatformAdminUi\Form\Factory\FormFactory */
private $formFactory;

/** @var SubmitHandler */
/** @var \EzSystems\EzPlatformAdminUi\Form\SubmitHandler */
private $submitHandler;

/** @var array */
Expand All @@ -53,13 +49,11 @@ class ContentTypeGroupController extends Controller
private $defaultPaginationLimit;

/**
* ContentTypeGroupController constructor.
*
* @param NotificationHandlerInterface $notificationHandler
* @param TranslatorInterface $translator
* @param ContentTypeService $contentTypeService
* @param FormFactory $formFactory
* @param SubmitHandler $submitHandler
* @param \EzSystems\EzPlatformAdminUi\Notification\NotificationHandlerInterface $notificationHandler
* @param \Symfony\Component\Translation\TranslatorInterface $translator
* @param \eZ\Publish\API\Repository\ContentTypeService $contentTypeService
* @param \EzSystems\EzPlatformAdminUi\Form\Factory\FormFactory $formFactory
* @param \EzSystems\EzPlatformAdminUi\Form\SubmitHandler $submitHandler
* @param array $languages
* @param int $defaultPaginationLimit
*/
Expand All @@ -82,9 +76,9 @@ public function __construct(
}

/**
* @param Request $request
* @param \Symfony\Component\HttpFoundation\Request $request
*
* @return Response
* @return \Symfony\Component\HttpFoundation\Response
*/
public function listAction(Request $request): Response
{
Expand All @@ -100,7 +94,7 @@ public function listAction(Request $request): Response
$pagerfanta->setMaxPerPage($this->defaultPaginationLimit);
$pagerfanta->setCurrentPage(min($page, $pagerfanta->getNbPages()));

/** @var ContentTypeGroup[] $contentTypeGroupList */
/** @var \eZ\Publish\API\Repository\Values\ContentType\ContentTypeGroup[] $contentTypeGroupList */
$contentTypeGroupList = $pagerfanta->getCurrentPageResults();

$deleteContentTypeGroupsForm = $this->formFactory->deleteContentTypeGroups(
Expand All @@ -118,11 +112,20 @@ public function listAction(Request $request): Response
'form_content_type_groups_delete' => $deleteContentTypeGroupsForm->createView(),
'deletable' => $deletableContentTypeGroup,
'content_types_count' => $count,
'can_create' => $this->isGranted(new Attribute('class', 'create')),
'can_update' => $this->isGranted(new Attribute('class', 'update')),
'can_delete' => $this->isGranted(new Attribute('class', 'delete')),
]);
}

/**
* @param \Symfony\Component\HttpFoundation\Request $request
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function createAction(Request $request): Response
{
$this->denyAccessUnlessGranted(new Attribute('class', 'create'));
$form = $this->formFactory->createContentTypeGroup(
new ContentTypeGroupCreateData()
);
Expand Down Expand Up @@ -159,8 +162,15 @@ public function createAction(Request $request): Response
]);
}

/**
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \eZ\Publish\API\Repository\Values\ContentType\ContentTypeGroup $group
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function updateAction(Request $request, ContentTypeGroup $group): Response
{
$this->denyAccessUnlessGranted(new Attribute('class', 'update'));
$form = $this->formFactory->updateContentTypeGroup(
new ContentTypeGroupUpdateData($group)
);
Expand Down Expand Up @@ -199,8 +209,15 @@ public function updateAction(Request $request, ContentTypeGroup $group): Respons
]);
}

/**
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \eZ\Publish\API\Repository\Values\ContentType\ContentTypeGroup $group
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function deleteAction(Request $request, ContentTypeGroup $group): Response
{
$this->denyAccessUnlessGranted(new Attribute('class', 'delete'));
$form = $this->formFactory->deleteContentTypeGroup(
new ContentTypeGroupDeleteData($group)
);
Expand Down Expand Up @@ -232,19 +249,13 @@ public function deleteAction(Request $request, ContentTypeGroup $group): Respons
/**
* Handles removing content type groups based on submitted form.
*
* @param Request $request
*
* @return Response
* @param \Symfony\Component\HttpFoundation\Request $request
*
* @throws TranslationInvalidArgumentException
* @throws InvalidOptionsException
* @throws UnauthorizedException
* @throws InvalidArgumentException
* @throws NotFoundException
* @throws \InvalidArgumentException
* @return \Symfony\Component\HttpFoundation\Response
*/
public function bulkDeleteAction(Request $request): Response
{
$this->denyAccessUnlessGranted(new Attribute('class', 'delete'));
$form = $this->formFactory->deleteContentTypeGroups(
new ContentTypeGroupsDeleteData()
);
Expand Down Expand Up @@ -276,11 +287,11 @@ public function bulkDeleteAction(Request $request): Response
}

/**
* @param Request $request
* @param ContentTypeGroup $group
* @param \Symfony\Component\HttpFoundation\Request $request
* @param \eZ\Publish\API\Repository\Values\ContentType\ContentTypeGroup $group
* @param int $page
*
* @return Response
* @return \Symfony\Component\HttpFoundation\Response
*/
public function viewAction(Request $request, ContentTypeGroup $group, int $page = 1): Response
{
Expand All @@ -292,7 +303,7 @@ public function viewAction(Request $request, ContentTypeGroup $group, int $page
}

/**
* @param ContentTypeGroup[] $contentTypeGroups
* @param \eZ\Publish\API\Repository\Values\ContentType\ContentTypeGroup[] $contentTypeGroups
*
* @return array
*/
Expand Down
63 changes: 40 additions & 23 deletions src/bundle/Resources/views/admin/content_type/list.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,38 @@
<div class="ez-table-header">
<div class="ez-table-header__headline">{{ 'content_type.view.list.title'|trans({ '%identifier%': content_type_group.identifier })|desc('Content Types in %identifier%') }}</div>
<div>
<a href="{{ path('ezplatform.content_type.add', {contentTypeGroupId: content_type_group.id}) }}"
title="{{ 'content_type.view.list.action.add'|trans|desc('Create a Content Type') }}"
class="btn btn-primary">
<svg class="ez-icon ez-icon-create">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="{{ asset('bundles/ezplatformadminui/img/ez-icons.svg') }}#create"></use>
</svg>
</a>
{% set modal_data_target = 'delete-content-types-modal' %}
<button id="delete-content-types" type="button" class="btn btn-danger" disabled data-toggle="modal"
data-target="#{{ modal_data_target }}" title="{{ 'content_type.view.list.action.delete'|trans|desc('Delete Content Type') }}">
<svg class="ez-icon ez-icon-trash">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="{{ asset('bundles/ezplatformadminui/img/ez-icons.svg') }}#trash"></use>
</svg>
</button>
{% include '@ezdesign/admin/bulk_delete_confirmation_modal.html.twig' with {
'id': modal_data_target,
'message': 'content_type.modal.message'|trans|desc('Do you want to delete Content Type?'),
'data_click': '#content_types_delete_delete',
}%}
{% if can_create %}
<a
href="{{ path('ezplatform.content_type.add', {contentTypeGroupId: content_type_group.id}) }}"
title="{{ 'content_type.view.list.action.add'|trans|desc('Create a Content Type') }}"
class="btn btn-primary">
<svg class="ez-icon ez-icon-create">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="{{ asset('bundles/ezplatformadminui/img/ez-icons.svg') }}#create"></use>
</svg>
</a>
{% endif %}
{% if can_delete %}
{% set modal_data_target = 'delete-content-types-modal' %}
<button
id="delete-content-types"
type="button"
class="btn btn-danger"
disabled
data-toggle="modal"
data-target="#{{ modal_data_target }}"
title="{{ 'content_type.view.list.action.delete'|trans|desc('Delete Content Type') }}">
<svg class="ez-icon ez-icon-trash">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="{{ asset('bundles/ezplatformadminui/img/ez-icons.svg') }}#trash"></use>
</svg>
</button>
{% include '@ezdesign/admin/bulk_delete_confirmation_modal.html.twig' with {
'id': modal_data_target,
'message': 'content_type.modal.message'|trans|desc('Do you want to delete Content Type?'),
'data_click': '#content_types_delete_delete',
}%}
{% endif %}
</div>
</div>

Expand All @@ -51,7 +62,11 @@
{% for content_type in pager.currentPageResults %}
<tr>
<td class="ez-checkbox-cell">
{{ form_widget(form_content_types_delete.content_types[content_type.id], {"disabled": not deletable[content_type.id]}) }}
{% if can_delete %}
{{ form_widget(form_content_types_delete.content_types[content_type.id], {"disabled": not deletable[content_type.id]}) }}
{% else %}
{% do form_content_types_delete.content_types.setRendered %}
{% endif %}
</td>
<td>
{% set view_url = path('ezplatform.content_type.view', {
Expand All @@ -65,7 +80,9 @@
<td>{{ content_type.id }}</td>
<td>{{ content_type.modificationDate | date }}</td>
<td class="text-right">
{{ macros.content_type_edit(content_type, content_type_group, 'btn btn-icon mx-3') }}
{% if can_update %}
{{ macros.content_type_edit(content_type, content_type_group, 'btn btn-icon mx-3') }}
{% endif %}
</td>
</tr>
{% endfor %}
Expand Down
4 changes: 3 additions & 1 deletion src/bundle/Resources/views/admin/content_type/view.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@
<td>{{ content_type.identifier }}</td>
<td>{{ content_type.descriptions[language_code]|default('') }}</td>
<td class="text-right">
{{ macros.content_type_edit(content_type, content_type_group, 'btn btn-icon mx-3') }}
{% if can_update %}
{{ macros.content_type_edit(content_type, content_type_group, 'btn btn-icon mx-3') }}
{% endif %}
</td>
</tr>
</tbody>
Expand Down
Loading

0 comments on commit 940986d

Please sign in to comment.