partdigital → created an issue.
FWIW on our project we had to build an entity duplication service. We were originally using entity_clone but had to refactor the work because, unfortunately, entity_clone was not quite flexible enough. We ended up creating our own API which made it very flexible to define a duplication task. I’m happy to contribute in this (or another issue) if anyone is interested. (Note that we also have test coverage).
To summarize these are the parts of our API.
DuplicationStrategy
This defines how we want our duplication to run. This is where we define which fields, entity types, bundles and even individual entities we want to include in the duplication process.
DuplicationProcess
This generates duplication process based on the entity and strategy that is passed to it. It essentially generates an array that details every step that needs to happen for successful duplication. We’ve used to this diagnose any issues before the duplication actually happens.
DuplicationExecutable
This actually executes the duplication process. It does this by reading the duplication process array and executing each step along the way. Because the duplication process is an array it’s very easy to perform it as a batch.
Some remaining work:
We need to add a way to undo/rollback the duplication process if there is an error. Doing it in a single request it’s very easy but doing it as a batch can be a bit trickier.
Here is an example of the API:
<?php
// This defines a strategy that will duplicate nodes found in the “related_content” field but will exclude articles.
$strategy = DuplicationStrategy::create($entity);
$strategy->setEntityTypes(['node']);
$strategy->addField(‘related_content’);
$strategy->excludeBundles([‘article’]);
// Pass the strategy to DuplicationProcess object. This will generate the array of all necessary steps.
$process = new DuplicationProcess($entity, $strategy);
$process->build();
// Pass the process to the executable. This will execute all the steps in the process and return the duplicated entity.
$executable = new DuplicationExecutable($process);
$executable->execute();
return $executable->getDuplicate();
Just food for thought :D
I pushed up one change that makes it slightly easier to work with the hook. Now you can enable/disable fields like this.
function mymodule_entity_clone_entity_clone_clonable_fields_alter(array &$fields) {
// Mark the field as cloneable.
$fields['node']['page']['field_node_reference'] = TRUE;
// Mark the field as not cloneable.
$fields['node']['page']['field_node_reference'] = FALSE;
unset($fields['node']['page']['field_node_reference']);
}
Hi @rajeshreeputra, thanks for adding the dependency injection. I had noticed that last night!
https://www.drupal.org/project/entity_clone/issues/3350358 ✨ Option to update entity data before cloning - UI Improvements Active is not quite the same thing as this issue. This ticket is to allow you to specify which fields you want included/excluded in the cloning process. This would not be set by an author. Consider for example a node that has a "featured content" field. When we clone the node we wouldn't want to clone the content referenced in "featured content", this issue allows us to always exclude that field without requiring author input.
This ticket is primarily an API change but expressed in terms of Field UI it would look something like this.
I was running into this issue as well. The entity_clone module does not make it very easy to customize which fields you want to include in the cloning process and which ones you want to exclude. I've created a new MR which introduces a new hook hook_entity_clone_clonable_fields_alter().
How this works is that it scans and caches all the "cloneable" fields. Before that cache is saved though you can manipulate that array of fields with this hook.
function mymodule_entity_clone_entity_clone_clonable_fields_alter(array &$fields) {
// entity_clone will populate this array, you can modify it before it's cached.
unset($fields['node']['page']['field_node_reference']);
}
Additional changes:
This required refactoring EntitycloneClonableField
, I have added more automated tests to support this refactoring effort. I can also confirm that all existing automated tests are still working.
partdigital → changed the visibility of the branch 2953641-possibility-to-set to hidden.
partdigital → made their first commit to this issue’s fork.
partdigital → changed the visibility of the branch 3399716-add-a-method to hidden.
PirateDayAccessPolicy::calculatePermissions
returns incorrect interface.PirateDayAccessPolicy::getPersistentCacheContexts()
has$scope
argument though it is missing from the base class and Interface.- Minor typo fixes.
We're doing something like this on our project. However it is out of the scope of Access Policy so it's not something that will be supported here. With that said, Access Policy is a field so you could try this module https://www.drupal.org/project/field_inheritance → .
I've opened an MR with part of that code removed. (It's what we're using on our project). But I'm open to other approaches as well. For example, perhaps we could be inclusive instead of exclusive. This would be a safer approach.
$override_routes = [
'entity.node.canonical',
'entity.node.preview',
'entity.node.version_history',
];
if ($node->isDefaultTranslation() && n_array($matches[0], $override_routes) {
$variables['title'] = $node->getTitle();
}
partdigital → changed the visibility of the branch 3443218-gin-is-overriding to hidden.
The behavior is as expected here as the tabs are part of that entity.
Won't this break the messaging for other contrib modules that add custom tabs to the entity? It is a feature that works in Claro, Seven and other admin themes.
Regarding the message: From a UX POV it should appear right before (above) the action buttons in the content area.
It's currently rendering the message the same way as the "Delete" action, it just doesn't have the "This cannot be undone" message. (see screen shot for comparison).
FWIW I think the MR is not the right approach. Do we know exactly which routes we want to only render the title?
Hi Problue Solutions,
It's going to be a guessing game until I'm able to reproduce it. Are you able to determine at which point in the code the functionality is not working? For example as part of access_policy_entity_presave()
? Are you available to connect on Slack? It think it will be easier to diagnose this in real time.
Thanks for sharing. I noticed that the language is set to en-gb, is that the default language? The "First available" setting will only work for content created in the default language.
You can check that setting here: /admin/config/regional/language
You can see more details here: https://www.drupal.org/project/access_policy/issues/3438598 🐛 Access policy updates get ignored when not using default language Active
If you have multiple policies, another issue that I've occasionally run into is when the weights of all the access policies are set to 0, sometimes their assignment doesn't behave predictably (still under investigation).
As a quick workaround you can:
- Go to /admin/people/access-policies/node/settings
- Sort the access policies by dragging the handles (it doesn't matter which order).
- Click save
- Go back to /admin/people/access-policies/node/settings
- Sort the access policies in the order that you want.
- Click save, this should properly set the weight on the policies.
Would you be willing to share an export of your access policy?
Were you able to resolve your issue?
partdigital → created an issue.
I would need to see what settings you set for your access policy and permissions. However, make sure that the roles have the "Assign access policy" permission and that "First available" is selected under default policy. Otherwise it won't assign an access policy. This functionality has test coverage so it should all be working as expected.
Feel free to reach out on Slack if you have any questions.
Hi PhilY,
We're not supporting Search API at this time while we focus on getting 1.0 out. Definitely open to any contributions though!
Hi Problue Solutions, thanks for reaching out!
Most access rules should work across all entity types that support display modes. Take a look at this documentation → to make sure your entity type is fully supported.
Also, if you're having any issues with access rules you can also create your own. Take a look at this documentation → for an overview.
I spent some more time investigating this I noticed is that, in some cases, the field controlling access can still be visible on translated pages, even if that field isn't translatable. When authors change the value of that field that can cause that field and access policy to become out of sync.
For example:
- Create a new paragraph
- Click the "Private" checkbox, this will make the content private. The "Private" field is not translatable.
- Create a new French version of that paragraph.
- The "Private" checkbox is still visible on the translation.
- When an author clicks the checkbox the access policy is not updated.
Does this sound similar to the issue that you're running in to?
I'll add a change so that fields controlling access are only visisble on the default language. In the meantime, a quick fix for this is to make sure that "Hide non translatable fields on translation forms" is checked.
- Go to /admin/config/regional/content-language
- Scroll down until you see translation settings for paragraphs.
- Click "Hide non translatable fields on translation forms"
Would you be willing to share some more details about your policy and steps to reproduce? I'd like to see if I can reproduce it as well.
One thing I should mention is the way that access policy handles assignment. The "Dynamic" selection mode will only assign the policy if the field value has changed between revisions. Do you think that could be a factor as well?
If so, in the latest dev version I've added the ability assign policies "on save" instead of "on change", to try it out do the following:
- Update to the latest dev version.
- Create a new selection strategy plugin (see below).
- Enable that Selection mode for paragraphs
<?php
namespace Drupal\access_policy\Plugin\access_policy\SelectionStrategy;
use Drupal\Core\Entity\EntityTypeInterface;
/**
* On save selection strategy.
*
* @SelectionStrategy(
* id = "on_save",
* label = @Translation("On save"),
* description = @Translation("On save, access policies are dynamically assigned to entities based on selection rules."),
* weight = 0,
* )
*/
class OnSaveSelection extends SelectionStrategyBase {
/**
* {@inheritdoc}
*/
public function defaultOptions() {
return [
'dynamic_assignment' => 'on_save',
'enable_selection_page' => FALSE,
'show_operations_link' => FALSE,
'enable_policy_field' => FALSE,
'allow_empty' => FALSE,
];
}
/**
* {@inheritdoc}
*/
public static function isApplicable(EntityTypeInterface $entity_type) {
return TRUE;
}
}
Hi gmarus, thanks for reaching out!
There a few assumptions that access policy makes:
- The access_policy field is not translatable.
- It will only determine the policy based on the Default translation.
This is to prevent translations from having different policies.
The condition $entity->language()->isDefault()
was added to prevent selecting a policy against translated field values. For example, let's say the original language has the "Sales" department, but the French translation doesn't have a department. Because the access_policy field is not translatable that would remove the policy entirely.
You can see a test case here covering this use case: https://git.drupalcode.org/project/access_policy/-/blob/1.0.x/tests/src/...
To use access policy predictably I recommend only using non-translatable fields with selection rules. I'm definitely open to investigating language specific policies in future versions.
partdigital → created an issue.
Glad to hear you were able to update the module!
Since it doesn't seem any code changes are necessary I'll close this as "Works as designed."
Ah ok I hadn't realized that you weren't using drush. That's good to know for future updates. I just it ran the update against update.php and it seemed to work as well.
In regards to the composer update did you try it with:
composer update drupal/access_policy --with-all-dependencies
In some cases I might also do it like this:
composer require drupal/access_policy:1.0.0-beta7
Note that I've never seen composer used like composer update drupal.access_policy
. When I ran composer update drupal/access_policy
it updated successfully.
Here is a comparison of the messages between the two commands:
composer update drupal.access_policy --with-all-dependencies
Gathering patches from patch file.
> DrupalProject\composer\ScriptHandler::checkComposerVersion
Loading composer repositories with package information
Package "drupal.access_policy" listed for update is not locked.
Updating dependencies
Nothing to modify in lock file
Writing lock file
Installing dependencies from lock file (including require-dev)
Nothing to install, update or remove
Package nabil1337/case-helper is abandoned, you should avoid using it. Use marcusball/case-helper instead.
Package webmozart/path-util is abandoned, you should avoid using it. Use symfony/filesystem instead.
Generating autoload files
Skipped installation of bin artifact for package lastcall/artifact.sh: file not found in package
96 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> DrupalProject\composer\ScriptHandler::createRequiredFiles
> DrupalProject\composer\ScriptHandler::compileComposerServices
Run "composer audit" for a full list of advisories
composer update drupal/access_policy --with-all-dependencies
Gathering patches from patch file.
> DrupalProject\composer\ScriptHandler::checkComposerVersion
Loading composer repositories with package information
Updating dependencies
Lock file operations: 0 installs, 28 updates, 0 removals
- Upgrading doctrine/lexer (2.1.0 => 2.1.1)
- Upgrading drupal/access_policy (dev-1.0.x ba6a7ee => dev-1.0.x 3582651)
- Upgrading egulias/email-validator (3.2.6 => 4.0.2)
- Upgrading mck89/peast (v1.16.0 => v1.16.1)
- Upgrading phpdocumentor/type-resolver (1.8.0 => 1.8.2)
- Upgrading phpstan/phpdoc-parser (1.25.0 => 1.26.0)
- Upgrading symfony/console (v6.4.3 => v6.4.4)
- Upgrading symfony/dependency-injection (v6.4.3 => v6.4.4)
- Upgrading symfony/error-handler (v6.4.3 => v6.4.4)
- Upgrading symfony/http-foundation (v6.4.3 => v6.4.4)
- Upgrading symfony/http-kernel (v6.4.3 => v6.4.4)
- Upgrading symfony/mailer (v6.4.3 => v6.4.4)
- Upgrading symfony/polyfill-ctype (v1.28.0 => v1.29.0)
- Upgrading symfony/polyfill-iconv (v1.28.0 => v1.29.0)
- Upgrading symfony/polyfill-intl-grapheme (v1.28.0 => v1.29.0)
- Upgrading symfony/polyfill-intl-idn (v1.28.0 => v1.29.0)
- Upgrading symfony/polyfill-intl-normalizer (v1.28.0 => v1.29.0)
- Upgrading symfony/polyfill-mbstring (v1.28.0 => v1.29.0)
- Upgrading symfony/polyfill-php72 (v1.28.0 => v1.29.0)
- Upgrading symfony/polyfill-php80 (v1.28.0 => v1.29.0)
- Upgrading symfony/polyfill-php81 (v1.28.0 => v1.29.0)
- Upgrading symfony/polyfill-php83 (v1.28.0 => v1.29.0)
- Upgrading symfony/process (v6.4.3 => v6.4.4)
- Upgrading symfony/serializer (v6.4.3 => v6.4.4)
- Upgrading symfony/string (v6.4.3 => v6.4.4)
- Upgrading symfony/validator (v6.4.3 => v6.4.4)
- Upgrading symfony/var-dumper (v6.4.3 => v6.4.4)
- Upgrading symfony/var-exporter (v6.4.3 => v6.4.4)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 0 installs, 28 updates, 0 removals
- Syncing drupal/access_policy (dev-1.0.x 3582651) into cache
Gathering patches from patch file.
Gathering patches for dependencies. This might take a minute.
- Upgrading symfony/polyfill-ctype (v1.28.0 => v1.29.0): Extracting archive
- Upgrading symfony/polyfill-php80 (v1.28.0 => v1.29.0): Extracting archive
- Upgrading symfony/polyfill-php83 (v1.28.0 => v1.29.0): Extracting archive
- Upgrading symfony/polyfill-mbstring (v1.28.0 => v1.29.0): Extracting archive
- Upgrading symfony/http-foundation (v6.4.3 => v6.4.4): Extracting archive
- Upgrading symfony/var-dumper (v6.4.3 => v6.4.4): Extracting archive
- Upgrading symfony/error-handler (v6.4.3 => v6.4.4): Extracting archive
- Upgrading symfony/http-kernel (v6.4.3 => v6.4.4): Extracting archive
- Upgrading symfony/polyfill-intl-normalizer (v1.28.0 => v1.29.0): Extracting archive
- Upgrading symfony/polyfill-intl-grapheme (v1.28.0 => v1.29.0): Extracting archive
- Upgrading symfony/string (v6.4.3 => v6.4.4): Extracting archive
- Upgrading symfony/console (v6.4.3 => v6.4.4): Extracting archive
- Upgrading doctrine/lexer (2.1.0 => 2.1.1): Extracting archive
- Upgrading symfony/validator (v6.4.3 => v6.4.4): Extracting archive
- Upgrading symfony/serializer (v6.4.3 => v6.4.4): Extracting archive
- Upgrading symfony/process (v6.4.3 => v6.4.4): Extracting archive
- Upgrading symfony/polyfill-iconv (v1.28.0 => v1.29.0): Extracting archive
- Upgrading symfony/polyfill-php72 (v1.28.0 => v1.29.0): Extracting archive
- Upgrading symfony/polyfill-intl-idn (v1.28.0 => v1.29.0): Extracting archive
- Upgrading symfony/var-exporter (v6.4.3 => v6.4.4): Extracting archive
- Upgrading symfony/dependency-injection (v6.4.3 => v6.4.4): Extracting archive
- Upgrading mck89/peast (v1.16.0 => v1.16.1): Extracting archive
- Upgrading egulias/email-validator (3.2.6 => 4.0.2): Extracting archive
- Upgrading drupal/access_policy (dev-1.0.x ba6a7ee => dev-1.0.x 3582651): Checking out 3582651d47 from cache
- Upgrading phpstan/phpdoc-parser (1.25.0 => 1.26.0): Extracting archive
- Upgrading symfony/mailer (v6.4.3 => v6.4.4): Extracting archive
- Upgrading symfony/polyfill-php81 (v1.28.0 => v1.29.0): Extracting archive
- Upgrading phpdocumentor/type-resolver (1.8.0 => 1.8.2): Extracting archive
Package nabil1337/case-helper is abandoned, you should avoid using it. Use marcusball/case-helper instead.
Package webmozart/path-util is abandoned, you should avoid using it. Use symfony/filesystem instead.
Generating autoload files
Skipped installation of bin artifact for package lastcall/artifact.sh: file not found in package
96 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
> DrupalProject\composer\ScriptHandler::createRequiredFiles
> DrupalProject\composer\ScriptHandler::compileComposerServices
@gilbertdelyon one thing I forgot to ask earlier. Did you run drush updb
? That will update all your access policies with the new operations.
Here are the steps that I went through to upgrade one of our projects to beta7.
composer update drupal/access_policy
drush cr
drush updb
@rishabjasrotia which tests are you referring too? All tests are currently passing.
Thank you.
Unfortunately I still can't reproduce it.
It's a very odd error because nothing changed in regards to the 403 http response. It sounds like it may be another issue with a mysterious cause unique to your environment (similar to #3419046 🐛 Undefined context error when user resets password Fixed ). Perhaps it's conflicting with a contrib module? Are you able to reproduce the error on a vanilla Drupal 10 site?
Would you mind sharing any access policies that you have?
Hi gilbertdelyon, did you clear the cache?
partdigital → created an issue.
The MR has been merged. To add support for a custom entity type, your entity type must:
- Be a content entity type
- Have a valid entity id key
- Have a view builder class
- Have a route for the field_ui_base_route property
- Support Bundles
Here is an example expressed in terms of annotation:
/**
* @ContentEntityType(
* id = "example",
* label = @Translation("Example"),
* handlers = {
* "view_builder" = "Drupal\example\ExampleViewBuilder",
* },
* entity_keys = {
* "id" = "id",
* },
* bundle_entity_type = "example_type",
* field_ui_base_route = "entity.example.edit_form",
* )
*/
class ExampleEntity extends ContentEntityBase {
}
I've opened an MR. I still want to add some automated tests but this will probably be the final production code.
To summarize the changes, in order to Integrate with access policy, your entity type must
- Be a content entity type
- Support Bundles
- Have a view builder class
- Have a route for the
field_ui_base_route
property
If you want to support Manual selection mode:
- You need to have a
canonical
link template. - Have a local task defined for the route associated with that link template.
I tested this on core and contrib including:
- Node
- Content Block
- Taxonomy
- Media
- Comments (see note)
- Paragraphs →
- Profile → (see note)
- Entity Registration →
Comments
Unfortunately I had to disable support for comments because of this issue:
https://www.drupal.org/project/drupal/issues/2879087
📌
Use comment access handler instead of hardcoding permissions
Needs work
Profile
This supports access policy, however it only supports Dynamic mode because no local tasks have been defined for that entity. There is an issue to address it:
https://www.drupal.org/project/profile/issues/3139127 →
partdigital → changed the visibility of the branch 3421025-how-to-use to hidden.
I spent some more time investigating this, specifically finding a way to relax the entity type constraints while also avoiding unpredictable behavior caused by entity types provided by contrib. The original culprit was the Crop module which triggered fatal errors. You can see the issue here: https://www.drupal.org/project/access_policy/issues/3384483 🐛 Unable to run access_policy_update_9001 Fixed .
Here is a patch with some changes that opens up access policy to other entity types. I removed the revision requirement and copied some logic from the Display modes pages. This seemed to make a lot of sense in this context. All my automated tests passed and the crop entity was still excluded. Yay!
I still need to add tests for non-revisionable entity types but this is the direction that I would go in. Please feel free to give it a try and let me know if you run into any issues.
I had considered adding a hook like hook_access_policy_entity_types_alter($entity_types)
. However, I decided against it (for the time being) because Access Policy makes assumptions based on those features and allowing developers to bypass those could lead to some unpredictable bugs which I just don't have the bandwidth to support.
I can say that for your use case, it's safe to add a canonical link to your entity type. You could even just have it point to the edit form. For example, this is how media does it.
* links = {
* "canonical" = "/media/{media}/edit",
* }
To give some context, I added that requirement so that it would support both Dynamic and Manual selection modes. If want to use Manual selection mode you'll need to have a canonical link.
In regards to making revisions (and bundles) optional by adding an API. That is unexplored territory and each will need its own issue and test coverage. The access_policy field for example is a base field that supports revisions; would it still behave properly if it was added to an entity without revisions?
So while I completely understand the motivation to add a hook of some kind, there's simply a lot more that needs to be investigated first.
But definitely apply a local patch to the module and let me know what issues you run into. I'd be very curious to learn what you find.
Correct, the type
property on the Access policy entity doesn't do anything anymore. However, it was left in to support the upgrade process. For example, we have projects with their own access policy type and it would have broken all those sites if that was removed.
That property, along with all the AccessPolicyType plugins, will be removed in the next release.
Hi frob!
In order to support a custom entity type, make sure that your entity type has the following:
- Is a content entity type
- Has a numeric id key
- Supports bundles
- Has a canonical link template
- Is revisionable
Expressed in terms of the annotation these are the keys that you need to integrate with access policy. (Note: other keys have been removed for brevity).
/**
* @ContentEntityType(
* id = "example",
* label = @Translation("Example"),
* revision_data_table = "example_field_revision",
* entity_keys = {
* "revision" = "vid",
* },
* bundle_entity_type = "example_type",
* links = {
* "canonical" = "/example/{entity_id}",
* }
* )
*/
class ExampleEntity extends ContentEntityBase {
}
Glad to hear the patch worked! I'll commit that and then mark this as resolved :D
I was referring to something along the lines of Step #7 of the Restrict Content by Department tutorial → . However, it sounds like you're not doing that.
Are you by chance restricting taxonomy terms with an Access Policy? In particular, Groupes Utilisateurs? If so, that may explain why CurrentUser:;getValue();
is being called in the first place.
I appreciate the feedback.
I'm definitely going to write some more tutorials. One or two more for common use cases as well as a collection of tutorials on how to use the API. There is also a slack channel #access-policy-module where anyone can submit questions. I'm also available on #support.
I'd say let's leave this issue open as a general discussion where anyone can talk about the pain points of learning Access Policy. So some general questions I might have (for anyone reading this).
- Do you use the Tours module? Would that be helpful?
- What use cases in particular would you like to see a tutorial on?
- Is there anything in the UI that is particularly confusing?
Here is a patch to address the fatal error. I'm still curious why this would be called in this context but AccessRuleArguments are designed to work without the context so it's a good thing to add anyway.
Let me know if this resolves your issue.
I added a new subtheme based on bartik but unfortunately I still couldn't reproduce it. Very mysterious.
My hunch is that it's related somehow to hiding the fields on the user's profile. I would try disabling the code and see if it stops happening.
Start with access_policy_entity_field_access()
in access_policy.module
and work from there.
Also, what over fields do you have on the user?
Thanks for the step-by-step, that is very helpful!
Unfortunately I still can't reproduce it. Would you be willing to share an export of the access policies? Maybe there's something about the configuration that I'm not thinking of.
1. Go to /admin/config/development/configuration/single/export
2. Select Configuration Type > Access Policy
3. Select the access policy you want to export.
H gilbertdelyon
Nice catch! Unfortunately I haven't been able to reproduce it either. Though, looking at some code I can see how theoretically it could happen.
This can happen when AccessRule::getValue(); is called before the context is set.
For example, it should happen like this:
$access_rule->setContext(ExecutionContext::create('view', ['user' => $this->currentUser]);
$access_rule->getValue();
If it never calls setContextExecutoinContext
it could trigger that error. Are you able to do some debugging and isolate where $access_rule->getValue();
is being called?
partdigital → created an issue.
I've opened a discussion thread around groups, I've received a few related requests so I thought it might be useful to consolidate ideas into something cohesive.
https://www.drupal.org/project/access_policy/issues/3419012 🌱 Discussion: Access policy group enhancements Active
I've opened a discussion thread around groups, I've received a few related requests so I thought it might be useful to consolidate ideas into something cohesive.
https://www.drupal.org/project/access_policy/issues/3419012 🌱 Discussion: Access policy group enhancements Active
I've opened a discussion thread around groups, I've received a few related requests so I thought it might be useful to consolidate ideas into something cohesive.
https://www.drupal.org/project/access_policy/issues/3419012 🌱 Discussion: Access policy group enhancements Active
I think one of the biggest issues we're are running into is that Taxonomy terms are a bit of a misfit for creating groups of users. They are great for categorizing content but miss some workflow features for handling users.
I had been considering a few approaches for this.
Access Policy Group module.
This is probably the most work but also has the most potential. For the sake of purity it might make sense to make it as another contrib module since Access Policy itself doesn't have much of an opinion.
- It would be a new "Group" content entity type.
- It would very simple and share a lot of features with Taxonomy terms such as nesting and weights. It's essentially just another entity that access policy can talk to.
- You use it by adding entity reference fields to the Node and User like with taxonomy terms.
- The group would come with some operations like Manage members, Add member etc. These essentially are just forms for setting field values on the user.
- The Access Policy Group module would ship with its own access rules so in that way it can be more more prescriptive than taxonomy terms.
- The access part of this would already be mostly handled by access policy. This would primarily be a module with workflow enhancements.
- A new Group content entity type would clear the runway for features more geared to user enrollment.
Contribute to Views bulk edit
Using views to create group management pages could be very powerful. The main limitation is how to add members to that group from within that context. Perhaps
Views bulk edit →
could help?
partdigital → created an issue.
HI MegaKeegMan,
I agree, the UI can be tricky to comprehend when first using it. Definitely open to feedback on how to improve it. Feel free to suggest any other changes and submit a patch to get credit.
I had interpreted checkmarks to mean that rules CANNOT apply to those operations.
This is very interesting and you raise a good point; a checkmark might mean something else for different people. Could you elaborate more? I'd be very interested to hear how you came to that assumption. Do you think another symbol may be more appropriate?
One feature that I'm currently working on is the ability to configure operations for each access policy. This means that the concepts of "Group", "Private" etc will be going away and you can configure it any way you want. This should help with the discoverability/learnability of the user interface as well as provide a useful feature. This will be with released with beta7.
Here is a sneak peak.
I'm also considering using Drupal tours which can guide users through the user interface right from within Drupal.
In the meantime, if you haven't seen it yet, I highly recommend watching this video. It gives a demo of the UI as well discusses some high level concepts which should help contextualize everything.
Hi mlncn!
This kind of functionality has come up a few times in slightly different versions. You can see these issues here:
- https://www.drupal.org/project/access_policy/issues/3402529 🐛 Taxonomy access policy for terms with depth only works when parent terms are included Active
- https://www.drupal.org/project/access_policy/issues/3410624 💬 Many groups to many users Active
I think one of the biggest issues we're are running into is that Taxonomy terms are a bit of a misfit for creating groups of users. They are great for categorizing content but miss some workflow features for handling users.
I had been considering a few approaches for this. The one that I like the most is a kind of "Access Policy Group" module. However, that is also the most work.
- It would be a new "Group" content entity type.
- It would very simple and share a lot of features with Taxonomy terms such as nesting and weights. It's essentially just another entity that access policy can talk to.
- You use it by adding entity reference fields to the Node and User like with taxonomy terms.
- The group would come with some operations like Manage members, Add member etc. These essentially are just forms for setting field values on the user.
- The Access Policy Group module would ship with its own access rules so in that way it can be more more prescriptive than taxonomy terms.
- The access part of this would already be mostly handled by access policy. This would primarily be a module with workflow enhancements.
A new Group content entity type would clear the runway for features more geared to user enrollment.
On a related note; I'm currently working on making operations (view, edit, delete) pluggable. So with an "Access Policy Group" module we could also add operations like "Add member" and it would easily integrate with access policy. In fact, each operation is context aware so it will only show operations that are applicable to their respective entity type.
What do you think?
Did you try something like this?
Department policy
- Access rule: Department taxonomy term, empty value is set to deny
- Selection rule: Department field is not empty
- Selection set: Restricted
Location policy
- Access rule: Location taxonomy term, empty value is set to deny
- Selection rule: Location field is not empty
- Selection set: Restricted
If no value is provided for the Location field or the Department field it won’t assign any policy and it will be accessible to everyone.
Yes, but for the node fields I used "filter by an entity reference view" to apply some restrictions so I think this breaks the rules in the access policy.
I've been able to reproduce this and will open a new ticket to address it.
I've upgraded the module to dev, but I'm facing another issue, now I can't see all needed rules for all fields. I just can find 2 of them.
I pushed up a change in beta6 that limited entity reference access rules to only fields that configured identically. For example, the Department taxonomy term field needs to have the same bundles selected for both the user and node fields. I added this in because it was adding a lot of fields that didn't do anything otherwise. Did you take a look at your entity reference fields to make sure they had the same bundles selected?
The ignore issue will require some more investigation. In the meantime there are a few workarounds that you can try.
- Break up your access rules across two access policies and group them into a Selection set. This allows you to assign two policies at the same time using OR logic. This is will have the same effect and should resolve the issue.
- You can create your own AccessRuleQueryHandler and modify the query.
For example, you can modify the annotation of the access rule and replace it with your own handler.
function mymodule_access_rule_alter(&$definitions). {
$definitions['entity_field_entity_reference']['handlers']['query_alter'] = '\Drupal\mymodule\AccessRuleQueryHandler\MyQueryHandler';
}
Hi Odai,
This sounds relatively similar to a fix that was pushed last week. Does it still happen if you upgrade to the latest dev version?
Change "Apply policy to listing pages" to "Apply access policy to queries"
Changed "apply policy to listing pages" to "Apply access policy to queries"
Hi MegaKeegMan
This is by design. Public policies are limited to just permissions and not access rules. The idea being that, in most cases, only internal users will be allowed to create public content and they will have their own role (e.g Employee).
Each policy type (Public, Private, Group etc) is a plugin so you can define your own if you like. In your case it might look like this:
/**
* Public access policy type with access rules.
*
* @AccessPolicyType(
* id = "public_with_rules",
* label = @Translation("Public with access rules"),
* weight = -3,
* operations = {
* "view" = { }
* "view all revisions" = {
* "permission" = true,
* "rules" = true,
* },
* "update" = {
* "permission" = true,
* "rules" = true,
* },
* "delete" = {
* "permission" = true,
* "rules" = true,
* },
* "view unpublished" = {
* "permission" = true,
* "rules" = true,
* },
* "manage access" = { }
* "rules" = true,
* },
* }
* )
*/
class PublicWithAccessRules extends AccessPolicyTypeBase {
}
Note that for each operation you can define how you want to restrict it. You can use permissions or rules or both (or neither).
Another approach you can do is to simply use the Group policy type, grant all users the view operation and exclude the View operation from the access rules.
kristiaanvandeneynde, I was attempting to try out the Access Policy API in Drupal 11 as part of an investigation into integrating it into the
Access Policy module →
. Even though the service collector is defined in core.services.yml
I noticed that addAccessPolicy
is never actually called. It looks like this is because it's never retrieved by the container except in the automated tests. I assume that's what this issue is for?
Is this API currently dormant in Drupal 11? If so, would it be worth mentioning that in the documentation → This way developers don't go down a rabbit hole only to discover it's not ready?
Unless of course I'm missing something entirely which in that case, open to any suggestions.
Glad you were able to resolve the issue!
For other questions like this feel free to reach out in slack as well. I'm active in #support and #access-policy-module.