Last active
November 7, 2021 10:22
-
-
Save bencroker/87a4b9337543f9c2b232225936e3920b to your computer and use it in GitHub Desktop.
Securing Front-End User Profile and Entry Forms in Craft (https://putyourlightson.com/articles/securing-front-end-user-profile-and-entry-forms-in-craft).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use craft\helpers\App; | |
return [ | |
'id' => App::env('APP_ID') ?: 'CraftCMS', | |
'modules' => [ | |
'field-permissions' => \modules\FieldPermissions::class, | |
], | |
'bootstrap' => [ | |
'field-permissions', | |
], | |
]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace modules; | |
use Craft; | |
use craft\controllers\EntriesController; | |
use craft\controllers\UsersController; | |
use yii\base\ActionEvent; | |
use yii\base\Event; | |
use yii\base\Module; | |
use yii\web\ForbiddenHttpException; | |
/** | |
* Prevents disallowed custom fields from being saved in front-end user profile and entry forms. | |
*/ | |
class FieldPermissions extends Module | |
{ | |
const DISALLOWED_CUSTOM_FIELDS = ['subscriptionStatus', 'subscriptionExpiry']; | |
public function init() | |
{ | |
/** | |
* Protects the `users/save-user` controller action. | |
*/ | |
Event::on(UsersController::class, UsersController::EVENT_BEFORE_ACTION, | |
function(ActionEvent $event) { | |
if ($event->action->id == 'save-user' && Craft::$app->request->isSiteRequest) { | |
// The UsersController looks for custom fields in a param called `fields`, unless one is provided in a param called `fieldsLocation`. | |
$fieldsLocation = Craft::$app->request->getBodyParam('fieldsLocation', 'fields'); | |
// Craft versions below 3.6.13 only allowed fields to be submitted via the `fields` param, so we force set this to avoid our checks from being bypassed. | |
if (version_compare(Craft::$app->version, '3.6.13', '<')) { | |
$fieldsLocation = 'fields'; | |
} | |
$fields = Craft::$app->request->getBodyParam($fieldsLocation, []); | |
foreach ($fields as $key => $value) { | |
// Throw an exception if the field is disallowed. | |
if (in_array($key, self::DISALLOWED_CUSTOM_FIELDS)) { | |
throw new ForbiddenHttpException('One or more disallowed fields were submitted.'); | |
} | |
} | |
} | |
} | |
); | |
/** | |
* Protects the `entries/save-entry` controller action. | |
*/ | |
Event::on(EntriesController::class, EntriesController::EVENT_BEFORE_ACTION, | |
function(ActionEvent $event) { | |
if ($event->action->id == 'save-entry' && Craft::$app->request->isSiteRequest) { | |
// The EntriesController looks for custom fields in a param called `fields`, unless one is provided in a param called `fieldsLocation`. | |
$fieldsLocation = Craft::$app->request->getBodyParam('fieldsLocation', 'fields'); | |
$fields = Craft::$app->request->getBodyParam($fieldsLocation, []); | |
foreach ($fields as $key => $value) { | |
// Throw an exception if the field is disallowed. | |
if (in_array($key, self::DISALLOWED_CUSTOM_FIELDS)) { | |
throw new ForbiddenHttpException('One or more disallowed fields were submitted.'); | |
} | |
} | |
} | |
} | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment