-
Notifications
You must be signed in to change notification settings - Fork 5
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
Caching of decrypted data #46
Changes from all commits
47ce238
66c2035
7db135c
6856066
d287f43
3586edb
df03c07
a1cae40
f59c44c
a4e2fb9
7d5e055
342bb7e
f8af20e
8ffc5da
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,8 +4,12 @@ | |
* Contains module hooks for field_encrypt. | ||
*/ | ||
|
||
use Drupal\Core\Entity\ContentEntityTypeInterface; | ||
use Drupal\Core\Entity\Display\EntityViewDisplayInterface; | ||
use Drupal\Core\Entity\DynamicallyFieldableEntityStorageInterface; | ||
use Drupal\Core\Entity\EntityInterface; | ||
use Drupal\Core\Form\FormStateInterface; | ||
use Drupal\field\Entity\FieldStorageConfig; | ||
|
||
/** | ||
* Implements hook_form_alter(). | ||
|
@@ -84,6 +88,19 @@ function field_encrypt_form_alter(&$form, FormStateInterface $form_state, $form_ | |
], | ||
); | ||
|
||
// Add setting to decide if field should be excluded from cache. | ||
$form['field_encrypt']['field_encrypt']['uncacheable'] = [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Awesome! |
||
'#type' => 'checkbox', | ||
'#title' => t('Uncacheable'), | ||
'#description' => t('Mark this field as uncacheable. This will make sure your unencrypted data will not be exposed in the cache, but will have a negative impact on your performance.'), | ||
'#default_value' => $field->getThirdPartySetting('field_encrypt', 'uncacheable', TRUE), | ||
'#states' => [ | ||
'visible' => [ | ||
':input[name="field_encrypt[encrypt]"]' => array('checked' => TRUE), | ||
], | ||
], | ||
]; | ||
|
||
// We add functions to process the form when it is saved. | ||
$form['#entity_builders'][] = 'field_encrypt_form_field_add_form_builder'; | ||
} | ||
|
@@ -105,7 +122,6 @@ function field_encrypt_form_alter(&$form, FormStateInterface $form_state, $form_ | |
function field_encrypt_form_field_add_form_builder($entity_type, \Drupal\field\Entity\FieldStorageConfig $field_storage_config, &$form, \Drupal\Core\Form\FormStateInterface $form_state) { | ||
$field_encryption_settings = $form_state->getValue('field_encrypt'); | ||
$field_encryption_settings['encrypt'] = (bool) $field_encryption_settings['encrypt']; | ||
$original_encryption = $field_storage_config->getThirdPartySettings('field_encrypt'); | ||
|
||
// If the form has the value, we set it. | ||
if ($field_encryption_settings['encrypt']) { | ||
|
@@ -118,6 +134,16 @@ function field_encrypt_form_field_add_form_builder($entity_type, \Drupal\field\E | |
$field_storage_config->unsetThirdPartySetting('field_encrypt', 'encrypt'); | ||
$field_storage_config->unsetThirdPartySetting('field_encrypt', 'properties'); | ||
$field_storage_config->unsetThirdPartySetting('field_encrypt', 'encryption_profile'); | ||
$field_storage_config->unsetThirdPartySetting('field_encrypt', 'uncacheable'); | ||
} | ||
} | ||
|
||
/** | ||
* Implements hook_entity_view(). | ||
*/ | ||
function field_encrypt_entity_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) { | ||
if (field_encrypt_allow_encryption($entity)) { | ||
\Drupal::service('field_encrypt.process_entities')->entitySetCacheTags($entity, $build); | ||
} | ||
} | ||
|
||
|
@@ -207,3 +233,21 @@ function field_encrypt_allow_encryption(EntityInterface $entity) { | |
} | ||
return $allowed; | ||
} | ||
|
||
/** | ||
* Implements hook_entity_type_alter(). | ||
*/ | ||
function field_encrypt_entity_type_alter(array &$entity_types) { | ||
$uncacheable_types = \Drupal::state()->get('uncacheable_entity_types'); | ||
if ($uncacheable_types) { | ||
// Mark entity types uncacheable if they contain an encrypted field | ||
// that has been marked uncacheable. | ||
// See Drupal\field_encrypt\EventSubscriber\ConfigSubscriber | ||
// setUncacheableEntityTypes(). | ||
foreach ($uncacheable_types as $uncacheable_type) { | ||
$entity_types[$uncacheable_type]->set('static_cache', FALSE); | ||
$entity_types[$uncacheable_type]->set('render_cache', FALSE); | ||
$entity_types[$uncacheable_type]->set('persistent_cache', FALSE); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -338,4 +338,41 @@ public function updateStoredField($field_name, $field_entity_type, $original_enc | |
} | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function entitySetCacheTags(ContentEntityInterface $entity, &$build) { | ||
$uncacheable_fields = $this->getUncacheableFields($entity); | ||
foreach ($uncacheable_fields as $field_name) { | ||
$build[$field_name]['#cache']['max-age'] = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This only helps for render arrays, not for any caches where entities are being used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IOW: this should not even be necessary, given changes elsewhere. Furthermore, the function name doesn't match what it does. |
||
} | ||
} | ||
|
||
/** | ||
* Get field names for an entity that are set to be excluded from cache. | ||
* | ||
* @param \Drupal\Core\Entity\ContentEntityInterface $entity | ||
* The entity to check. | ||
* | ||
* @return array | ||
* List of field names that are excluded from cache. | ||
*/ | ||
protected function getUncacheableFields(ContentEntityInterface $entity) { | ||
$uncacheable_fields = []; | ||
foreach ($entity->getFields() as $field) { | ||
if ($this->checkField($field)) { | ||
/* @var $definition \Drupal\Core\Field\BaseFieldDefinition */ | ||
$definition = $field->getFieldDefinition(); | ||
/* @var $storage \Drupal\Core\Field\FieldConfigStorageBase */ | ||
$storage = $definition->get('fieldStorage'); | ||
|
||
// If uncacheable is set, set caching max-age to 0. | ||
if ($storage->getThirdPartySetting('field_encrypt', 'uncacheable', FALSE) == TRUE) { | ||
$uncacheable_fields[] = $field->getName(); | ||
} | ||
} | ||
} | ||
return $uncacheable_fields; | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit ambiguous. We're only focusing on render cache, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's broader than just render cache. When caching the entity object itself, unencrypted field data also shouldn't be stored in the (database) cache...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
uncacheable
would be a better name. It'd also fit in better with the terminology in Drupal core.