Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EZP-29101: Implement permissions for Content Types #549

Merged
merged 1 commit into from
Jun 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
61 changes: 38 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,36 @@
<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 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 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 +60,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 +78,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