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

Element authorization improvements #11808

Merged
merged 6 commits into from
Aug 21, 2022
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
25 changes: 25 additions & 0 deletions CHANGELOG-WIP.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# Release Notes for Craft CMS 4.3 (WIP)

### Added
- Added the `canCreateDrafts()` Twig function. ([#11797](https://github.com/craftcms/cms/discussions/11797), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added the `canDelete()` Twig function. ([#11797](https://github.com/craftcms/cms/discussions/11797), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added the `canDeleteForSite()` Twig function. ([#11797](https://github.com/craftcms/cms/discussions/11797), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added the `canDuplicate()` Twig function. ([#11797](https://github.com/craftcms/cms/discussions/11797), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added the `canSave()` Twig function. ([#11797](https://github.com/craftcms/cms/discussions/11797), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added the `canView()` Twig function. ([#11797](https://github.com/craftcms/cms/discussions/11797), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added the `|boolean` Twig filter. ([#11792](https://github.com/craftcms/cms/pull/11792))
- Added the `|float` Twig filter. ([#11792](https://github.com/craftcms/cms/pull/11792))
- Added the `|integer` Twig filter. ([#11792](https://github.com/craftcms/cms/pull/11792))
- Added the `|string` Twig filter. ([#11792](https://github.com/craftcms/cms/pull/11792))
- Added `craft\elements\actions\Restore::$restorableElementsOnly`.
- Added `craft\events\AuthorizationCheckEvent::$element`.
- Added `craft\events\CreateTwigEvent`.
- Added `craft\events\DefineAddressFieldLabelEvent`.
- Added `craft\events\DefineAddressFieldsEvent`.
Expand All @@ -20,6 +27,18 @@
- Added `craft\services\Addresses::getFieldLabel()`.
- Added `craft\services\Addresses::getUsedFields()`.
- Added `craft\services\Addresses::getUsedSubdivisionFields()`.
- Added `craft\services\Elements::EVENT_AUTHORIZE_CREATE_DRAFTS`. ([#11759](https://github.com/craftcms/cms/discussions/11759), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added `craft\services\Elements::EVENT_AUTHORIZE_DELETE_FOR_SITE`. ([#11759](https://github.com/craftcms/cms/discussions/11759), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added `craft\services\Elements::EVENT_AUTHORIZE_DELETE`. ([#11759](https://github.com/craftcms/cms/discussions/11759), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added `craft\services\Elements::EVENT_AUTHORIZE_DUPLICATE`. ([#11759](https://github.com/craftcms/cms/discussions/11759), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added `craft\services\Elements::EVENT_AUTHORIZE_SAVE`. ([#11759](https://github.com/craftcms/cms/discussions/11759), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added `craft\services\Elements::EVENT_AUTHORIZE_VIEW`. ([#11759](https://github.com/craftcms/cms/discussions/11759), [#11808](https://github.com/craftcms/cms/pull/11808))
- Added `craft\services\Elements::canCreateDrafts()`.
- Added `craft\services\Elements::canDelete()`.
- Added `craft\services\Elements::canDeleteForSite()`.
- Added `craft\services\Elements::canDuplicate()`.
- Added `craft\services\Elements::canSave()`.
- Added `craft\services\Elements::canView()`.
- Added `craft\web\Controller::getCurrentUser()`. ([#11754](https://github.com/craftcms/cms/pull/11754))
- Added `craft\web\View::EVENT_AFTER_CREATE_TWIG`. ([#11774](https://github.com/craftcms/cms/pull/11774))
- Added the `Craft.useMobileStyles()` JavaScript method. ([#11636](https://github.com/craftcms/cms/pull/11636))
Expand All @@ -36,4 +55,10 @@
- `checkboxSelect` inputs without `showAllOption: true` now post an empty value if no options were selected. ([#11748](https://github.com/craftcms/cms/issues/11748))

### Deprecated
- Deprecated `craft\base\Element::EVENT_AUTHORIZE_CREATE_DRAFTS`. `craft\services\Elements::EVENT_AUTHORIZE_CREATE_DRAFTS` should be used instead.
- Deprecated `craft\base\Element::EVENT_AUTHORIZE_DELETE_FOR_SITE`. `craft\services\Elements::EVENT_AUTHORIZE_DELETE_FOR_SITE` should be used instead.
- Deprecated `craft\base\Element::EVENT_AUTHORIZE_DELETE`. `craft\services\Elements::EVENT_AUTHORIZE_DELETE` should be used instead.
- Deprecated `craft\base\Element::EVENT_AUTHORIZE_DUPLICATE`. `craft\services\Elements::EVENT_AUTHORIZE_DUPLICATE` should be used instead.
- Deprecated `craft\base\Element::EVENT_AUTHORIZE_SAVE`. `craft\services\Elements::EVENT_AUTHORIZE_SAVE` should be used instead.
- Deprecated `craft\base\Element::EVENT_AUTHORIZE_VIEW`. `craft\services\Elements::EVENT_AUTHORIZE_VIEW` should be used instead.
- Deprecated `craft\elements\Address::addressAttributeLabel()`. `craft\services\Addresses::getFieldLabel()` should be used instead.
32 changes: 31 additions & 1 deletion src/base/Element.php
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ abstract class Element extends Component implements ElementInterface
*
* @see canView()
* @since 4.0.0
* @deprecated in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_VIEW]] should be used instead.
*/
public const EVENT_AUTHORIZE_VIEW = 'authorizeView';

Expand All @@ -390,6 +391,7 @@ abstract class Element extends Component implements ElementInterface
*
* @see canSave()
* @since 4.0.0
* @deprecated in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_SAVE]] should be used instead.
*/
public const EVENT_AUTHORIZE_SAVE = 'authorizeSave';

Expand All @@ -410,6 +412,7 @@ abstract class Element extends Component implements ElementInterface
*
* @see canCreateDrafts()
* @since 4.0.0
* @deprecated in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_CREATE_DRAFTS]] should be used instead.
*/
public const EVENT_AUTHORIZE_CREATE_DRAFTS = 'authorizeCreateDrafts';

Expand All @@ -430,6 +433,7 @@ abstract class Element extends Component implements ElementInterface
*
* @see canDuplicate()
* @since 4.0.0
* @deprecated in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_DUPLICATE]] should be used instead.
*/
public const EVENT_AUTHORIZE_DUPLICATE = 'authorizeDuplicate';

Expand All @@ -450,6 +454,7 @@ abstract class Element extends Component implements ElementInterface
*
* @see canDelete()
* @since 4.0.0
* @deprecated in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_DELETE]] should be used instead.
*/
public const EVENT_AUTHORIZE_DELETE = 'authorizeDelete';

Expand All @@ -468,8 +473,9 @@ abstract class Element extends Component implements ElementInterface
* );
* ```
*
* @see canDelete()
* @see canDeleteForSite()
* @since 4.0.0
* @deprecated in 4.3.0. [[\craft\services\Elements::EVENT_AUTHORIZE_DELETE_FOR_SITE]] should be used instead.
*/
public const EVENT_AUTHORIZE_DELETE_FOR_SITE = 'authorizeDeleteForSite';

Expand Down Expand Up @@ -2820,6 +2826,10 @@ public function createAnother(): ?ElementInterface
*/
public function canView(User $user): bool
{
if (!$this->hasEventHandlers(self::EVENT_AUTHORIZE_VIEW)) {
return false;
}

$event = new AuthorizationCheckEvent($user);
$this->trigger(self::EVENT_AUTHORIZE_VIEW, $event);
return $event->authorized;
Expand All @@ -2830,6 +2840,10 @@ public function canView(User $user): bool
*/
public function canSave(User $user): bool
{
if (!$this->hasEventHandlers(self::EVENT_AUTHORIZE_SAVE)) {
return false;
}

$event = new AuthorizationCheckEvent($user);
$this->trigger(self::EVENT_AUTHORIZE_SAVE, $event);
return $event->authorized;
Expand All @@ -2840,6 +2854,10 @@ public function canSave(User $user): bool
*/
public function canDuplicate(User $user): bool
{
if (!$this->hasEventHandlers(self::EVENT_AUTHORIZE_DUPLICATE)) {
return false;
}

$event = new AuthorizationCheckEvent($user);
$this->trigger(self::EVENT_AUTHORIZE_DUPLICATE, $event);
return $event->authorized;
Expand All @@ -2850,6 +2868,10 @@ public function canDuplicate(User $user): bool
*/
public function canDelete(User $user): bool
{
if (!$this->hasEventHandlers(self::EVENT_AUTHORIZE_DELETE)) {
return false;
}

$event = new AuthorizationCheckEvent($user);
$this->trigger(self::EVENT_AUTHORIZE_DELETE, $event);
return $event->authorized;
Expand All @@ -2860,6 +2882,10 @@ public function canDelete(User $user): bool
*/
public function canDeleteForSite(User $user): bool
{
if (!$this->hasEventHandlers(self::EVENT_AUTHORIZE_DELETE_FOR_SITE)) {
return false;
}

$event = new AuthorizationCheckEvent($user);
$this->trigger(self::EVENT_AUTHORIZE_DELETE_FOR_SITE, $event);
return $event->authorized;
Expand All @@ -2870,6 +2896,10 @@ public function canDeleteForSite(User $user): bool
*/
public function canCreateDrafts(User $user): bool
{
if (!$this->hasEventHandlers(self::EVENT_AUTHORIZE_CREATE_DRAFTS)) {
return false;
}

$event = new AuthorizationCheckEvent($user);
$this->trigger(self::EVENT_AUTHORIZE_CREATE_DRAFTS, $event);
return $event->authorized;
Expand Down
8 changes: 0 additions & 8 deletions src/base/ElementInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -770,8 +770,6 @@ public function canView(User $user): bool;
/**
* Returns whether the given user is authorized to save this element in its current form.
*
* This will only be called if the element can be [[canView()|viewed]].
*
* @param User $user
* @return bool
* @since 4.0.0
Expand All @@ -781,8 +779,6 @@ public function canSave(User $user): bool;
/**
* Returns whether the given user is authorized to duplicate this element.
*
* This will only be called if the element can be [[canSave()|viewed]] and [[canSave()|saved]].
*
* @param User $user
* @return bool
* @since 4.0.0
Expand All @@ -803,8 +799,6 @@ public function canDelete(User $user): bool;
/**
* Returns whether the given user is authorized to delete this element for its current site.
*
* This will only be called if the element can be [[canView()|viewed]] and [[canDelete()|deleted]].
*
* @param User $user
* @return bool
* @since 4.0.0
Expand All @@ -814,8 +808,6 @@ public function canDeleteForSite(User $user): bool;
/**
* Returns whether the given user is authorized to create drafts for this element.
*
* This will only be called if the element can be [[canView()|viewed]].
*
* @param User $user
* @return bool
* @since 4.0.0
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/AddressesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function actionCardHtml(): Response
throw new BadRequestHttpException("Invalid address ID: $addressId");
}

if (!$address->canView($this->getCurrentUser())) {
if (!Craft::$app->getElements()->canView($address)) {
throw new ForbiddenHttpException('User not authorized to view this address.');
}

Expand Down
16 changes: 8 additions & 8 deletions src/controllers/BaseEntriesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ protected function enforceEditEntryPermissions(Entry $entry, bool $duplicate = f
$entry->id = null;
}

try {
if (!$entry->canSave($this->getCurrentUser())) {
throw new ForbiddenHttpException('User is not authorized to perform this action.');
}
} finally {
if ($duplicate) {
$entry->id = $id;
}
$canSave = Craft::$app->getElements()->canSave($entry);

if ($duplicate) {
$entry->id = $id;
}

if (!$canSave) {
throw new ForbiddenHttpException('User is not authorized to perform this action.');
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/controllers/CategoriesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,6 @@ public function actionCreate(string $groupHandle): ?Response
throw new ForbiddenHttpException('User not authorized to edit content in any sites.');
}

$user = $this->getCurrentUser();

// Create & populate the draft
$category = Craft::createObject(Category::class);
$category->siteId = $site->id;
Expand All @@ -268,7 +266,7 @@ public function actionCreate(string $groupHandle): ?Response
}

// Make sure the user is allowed to create this category
if (!$category->canSave($user)) {
if (!Craft::$app->getElements()->canSave($category)) {
throw new ForbiddenHttpException('User not authorized to save this category.');
}

Expand Down
Loading