<p>There isn't an officially-supported way of gating read-access like this, so it's up to the template or view layer (or potentially a custom Module) to implement the logic.</p>
<p>I believe the behavior you're looking for is most closely associated with PHP's <a href="https://www.php.net/array_intersect" rel="nofollow noreferrer"><code>array_intersect</code></a> function, which returns an array of values that are present in all the passed arrays. Checking that the length of the return value is greater than zero would indicate that at least one of the User’s Groups’ handles are in the Entry’s <code>access</code> values.</p>
<p>However, because there is no equivalent functionality in Twig (unless you want to <a href="https://craftcms.com/docs/3.x/extend/extending-twig.html" rel="nofollow noreferrer">add it via a Twig extension</a>!), we're left with having to implement it directly in the template. This might look something like:</p>
<pre><code>{% set groupHandles = currentUser.getGroups() | column('handle') %}
{% set isPermitted = entry.access | reduce((allowed, level) =&gt; allowed or (level.value in groupHandles), false) %}
</code></pre>
<p>This basically takes the access &quot;levels&quot; declared by the Entry and compares it to the list of the user's Group handles.</p>
<p>In greater detail:</p>
<ol>
<li>Capture the User's groups, and take the <code>handle</code> of each;</li>
<li>Take the Entry's allowed access levels (Technically this is a <code>MultiOptionsData</code> object), and &quot;reduce&quot; it:
<ul>
<li>Start with <code>false</code>, to suggest &quot;not allowed&quot; by default (second argument to the <code>| reduce(fn, initial)</code> filter);</li>
<li>Iterate over the access levels, calling the closure each time. The closure is provided the previous value (or the default we set, above, for the first item) and the current value, and returns a new &quot;allowed&quot; value—which is used in the next iteration.</li>
<li>Test the &quot;current&quot; level to see if it's among the group handles we stashed in step #1;</li>
<li>The <code>or</code> makes sure we either return <code>true</code> if something has already passed an access check, or if the current item is in the list;</li>
<li>The process repeats until all items in <code>entry.access</code> have been processed;</li>
</ul>
</li>
<li>The final result of the reduce operation is stored in <code>isPermitted</code>.</li>
</ol>
<hr />
<p>Alternatively, here's a one-line check that makes use of some special methods on the <code>currentUser</code>:</p>
<pre><code>{% set isPermitted = entry.access | reduce((allowed, level) =&gt; allowed or currentUser.isInGroup(level), false) %}
</code></pre>
<p>The same <code>reduce</code> logic still applies, except we're asking the User object whether or not it's in a group with the passed handle, rather than comparing the handles ourselves.</p>

CC BY-SA 4.0
2021-12-07T06:19:44.547Z
Wow, this is amazing. Thanks so much! I quickly dropped in the first code and things look great! A lot to learn from this so thanks again for the extremely detailed answer.
supazu
CC BY-SA 4.0
2021-12-07T04:18:07.457Z
2021-12-07T04:18:07.457Z
August Miller
<p>I have a 3 levels of membership with a field on my entries matching those groups to restrict access.</p>
<p>I know I can get a user's groups with <code>currentUser.getGroups()</code>, but how can I compare that with my <code>entry.access</code> field? Basically, I want to do something like:</p>
<pre><code>{% set userGroups = currentUser.getGroups() %}
{% set access = entry.access %}
{% if userGroups in access %}
   Grant access
{% else %}
   Access denied
{% endif %}
</code></pre>
<p>I'm just not quite sure how to compare the group handles with checkbox values...</p>

<users>
Compare entry checkboxes with user groups to give access
# Compare entry checkboxes with user groups to give access

(Asked by: username_0 on 2021-12-07)

I have a 3 levels of membership with a field on my entries matching those groups to restrict access.
I know I can get a user's groups with currentUser.getGroups(), but how can I compare that with my entry.access field? Basically, I want to do something like:
{% set userGroups = currentUser.getGroups() %}
{% set access = entry.access %}
{% if userGroups in access %}
   Grant access
{% else %}
   Access denied
{% endif %}

I'm just not quite sure how to compare the group handles with checkbox values...

**Tags:** users

---

## 1 answers

### Answer by username_1 on 2021-12-07. Score: 2 | Accepted answer

There isn't an officially-supported way of gating read-access like this, so it's up to the template or view layer (or potentially a custom Module) to implement the logic.
I believe the behavior you're looking for is most closely associated with PHP's array_intersect function, which returns an array of values that are present in all the passed arrays. Checking that the length of the return value is greater than zero would indicate that at least one of the User’s Groups’ handles are in the Entry’s access values.
However, because there is no equivalent functionality in Twig (unless you want to add it via a Twig extension!), we're left with having to implement it directly in the template. This might look something like:
{% set groupHandles = currentUser.getGroups() | column('handle') %}
{% set isPermitted = entry.access | reduce((allowed, level) => allowed or (level.value in groupHandles), false) %}

This basically takes the access "levels" declared by the Entry and compares it to the list of the user's Group handles.
In greater detail:

Capture the User's groups, and take the handle of each;
Take the Entry's allowed access levels (Technically this is a MultiOptionsData object), and "reduce" it:

Start with false, to suggest "not allowed" by default (second argument to the | reduce(fn, initial) filter);
Iterate over the access levels, calling the closure each time. The closure is provided the previous value (or the default we set, above, for the first item) and the current value, and returns a new "allowed" value—which is used in the next iteration.
Test the "current" level to see if it's among the group handles we stashed in step #1;
The or makes sure we either return true if something has already passed an access check, or if the current item is in the list;
The process repeats until all items in entry.access have been processed;


The final result of the reduce operation is stored in isPermitted.


Alternatively, here's a one-line check that makes use of some special methods on the currentUser:
{% set isPermitted = entry.access | reduce((allowed, level) => allowed or currentUser.isInGroup(level), false) %}

The same reduce logic still applies, except we're asking the User object whether or not it's in a group with the passed handle, rather than comparing the handles ourselves.

> **Comments:**
> **username_0**: Wow, this is amazing. Thanks so much! I quickly dropped in the first code and things look great! A lot to learn from this so thanks again for the extremely detailed answer.  

---

