Answers.Body: <p>Hi extending permissions on a group level is a first approach, here is a piece of code that create group permissions for each entry, it would be easy to customize it to allow only top level entries. It is based on cvraft cms extending permissions tutorial <a href="https://craftcms.com/docs/4.x/extend/user-permissions.html#requiring-permissions" rel="nofollow noreferrer">https://craftcms.com/docs/4.x/extend/user-permissions.html#requiring-permissions</a></p>
  <pre><code>   
          $entries = \craft\elements\Entry::find() -&gt;all();
  
  Event::on(
                  UserPermissions::class,
                  UserPermissions::EVENT_REGISTER_PERMISSIONS,
                  function (RegisterUserPermissionsEvent $event) use ($entries) {
  
  
                   $entryPerms=[];
                      foreach ($entries as $entry) {
                      if ($entry-&gt;title)    $entryPerms[  'WaveEntryAccess' . $entry-&gt;id]=
                             [
                                  'label' =&gt; $entry-&gt;title
                              ] ;
                   }
              $arrPerm = array(
                  'permissionName' =&gt; [
                      'label' =&gt; &quot;Wave Member access&quot;,
                      'nested' =&gt; $entryPerms
                  ],
              );
                      $event-&gt;permissions['Member restricted access'  ]  =
                          $arrPerm ;
                  }
              );
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-05-14T09:49:25.540Z
Answers.LastActivityDate: 2022-05-14T09:49:25.540Z
Answers.UserDisplayName: erwanpia
Answers.Body: <p>I've done this! Let me try to explain without writing a small novel. There were a lot of bits, but it works.</p>
  
  <p>Start by creating a user group for every client. As you create these, write down the group <em>handle</em>. (Note: doesn't need any permissions other than logging in.)</p>
  
  <p>Make a channel containing your clients as individual entries, and in the fields for each entry, add a text field called "Client Portal Handle" - and copy the handle from the user groups to that field.</p>
  
  <p>Then, in my the templates, I'm setting up the page urls to be /portal// - and I set a field (I called it 'associatedClient') on entry, so each entry goes to that client.</p>
  
  <p>And, here's the bit that makes it all work, in a template, it's got code that says:</p>
  
  <pre><code>{% set client = entry.associatedClient.one() %}
  {% set cg = client.portalGroup %}
  
  {% if currentUser.admin or currentUser.isInGroup(cg) %}
    {# document template goes here #}
  {% else %}
    {# back to the login page #}
  {% endif %}
  </code></pre>
  
  <p>Line 1 gets the client attached to the doc. Line 2 gets the <em>handle</em> attached to the client.</p>
  
  <p>Then the if-check sees if the logged-in user is in that group or they're an admin.</p>
  
  <p>Does that all make sense?</p>
  
  <hr>
  
  <p>Edit: redirecting to the company page.</p>
  
  <p>I've got a generic /portal/ page, and it shows a "Take me to my portal" link, that shows content based on which group a user is in. And then there's some generic contact info and stuff that applies to everyone. This could be better, but it was our solution for the first config.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-05T20:16:04.073Z
Answers.Text: Thanks SamC this looks very interesting- is that just one page per client? Not sure where 'associatedClient' fits in. It also feels like I'd be assigning the permission per content each time and make it hard for super admins to administer different company content. But happy for further illumination / explanation :)
Answers.UserDisplayName: joomkit
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-06T14:22:28.453Z
Answers.Text: Oh, skipped an item. I added a relationship field to each doc entry. So when add an entry, you select which client it goes to. When someone visits, page gets the client info and the client handle. Then checks permissions against the handle. The magic bit is that you've got a handle in a regular entry field that matches against the handle in the groups.
Answers.UserDisplayName: SamC
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-05T19:22:49.523Z
Answers.LastActivityDate: 2020-02-06T14:18:46.133Z
Answers.LastEditDate: 2020-02-06T14:18:46.133Z
Answers.UserDisplayName: SamC
Answers.Body: <p>If you setup a User Group with the same handle as the Site you want them to have access to, this could be fairly easy.</p>
  <p>Let's say you have a site called &quot;Acme&quot; setup in the Sites settings. You also created a corresponding User Group called &quot;Acme.&quot; The handles for the Acme Site and Acme User Group are both &quot;acme.&quot;</p>
  <p>When you're on the Acme site's front-end, possibly <code>example.com/acme</code> depending on how <a href="https://docs.craftcms.com/v3/sites.html#site-url" rel="nofollow noreferrer">you set up your site URLs</a>, the <code>{{ currentSite.handle }}</code> tag will return <code>acme</code>.</p>
  <p>To test if a user has access to content in your template you can use something like <code>{% if currentUser.isInGroup(currentSite.handle) %}</code>.</p>
  <p>Adding this to any template will prevent unauthorized access if a user is not in a group:</p>
  <pre><code>{% if not currentUser.isInGroup(currentSite.handle) %}  
    {% exit 403 %}
  {% endif %}
  </code></pre>
  <p>You would also probably want to allow admins or users groups who can access the control panel:</p>
  <pre><code>allow admins:
  
  {% if not currentUser.isInGroup(currentSite.handle) or not currentUser.admin %}  
    {% exit 403 %}
  {% endif %}
  
  ... or allow any user that can access the control panel:
  
  {% if not currentUser.isInGroup(currentSite.handle) or not currentUser.can('accessCp') %}  
    {% exit 403 %}
  {% endif %}
  </code></pre>
  <p>Redirecting to the correct site after a login page is a little trickier because users can belong to more than one group.</p>
  <p>But assuming that users only belong to one group you could redirect users to a sort of &quot;routing&quot; template that's only job is to send you to the right place.</p>
  <pre><code>{% set firstGroup = currentUser.getGroups()[0] ?? null %}
  
  {% if firstGroup %}
    {% redirect firstGroup.handle %}
  {% else %}
    ... default redirect or error 
  {% endif %}
  </code></pre>
  <p>Also, here's a list of permission you can use with the <code>currentUser.can()</code> method:</p>
  <p><a href="https://docs.craftcms.com/v3/users.html#permissions" rel="nofollow noreferrer">https://docs.craftcms.com/v3/users.html#permissions</a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-06T14:48:25.703Z
Answers.Text: Thanks Alex. Your reply is a good reminder to spell out the scenario, and is a most welcome creative addition/solution to the problem.I need to support other languages within a company but i think i can see how this will work. I'm going to implement the above and jump on discord if I find problems. Thanks again
Answers.UserDisplayName: joomkit
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-05T20:17:09.287Z
Answers.LastActivityDate: 2020-06-29T09:07:16.217Z
Answers.LastEditDate: 2020-06-29T09:07:16.217Z
Answers.UserDisplayName: Alex Roper
Body: <p>How can I restrict content frontend to specific user groups?
  There seems no sensible way to do this out of the box.
  For example group permissions in CP are all about CP - there is no view option.</p>
  
  <p>Never had a use case for this before today but have one now and finding Craft3 coming up short :(</p>
  
  <p>Scenario is a support portal where different companies can provide user specific content. Idea is login with company id (done that ok via a plugin) but then once logged in they get redirected to content for that specific company.</p>
  
  <p>So I have two probs now: redirect to company 'home page', and restrict access to content. I've considered splitting content into sites and pairing users with sites. I've considered section root parent and checking permissions for top of tree in twig. I'm thinking restricting per section is best and adding company homepage as entry field in user field or user group field and managing access via plugin + twig but its all feeling very heavy handed....</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-02-04T21:00:11.577Z
Comments.Text: Have you tried the answers to this question "Check user is in User Group / Custom User Permissions?" https://craftcms.stackexchange.com/questions/1087/check-user-is-in-user-group-custom-user-permissions
Comments.UserDisplayName: Alex Roper
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-02-05T11:41:33.657Z
Comments.Text: Thanks Alex - hadn't seen it looks useful. But cant believe there is no front end permission view and having to roll a plugin for what should be core is annoying++
Comments.UserDisplayName: joomkit
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2020-02-05T18:51:01.700Z
Comments.Text: Also, it might be helpful to talk thru the problem on the Craft CMS Discord channel: https://craftcms.com/discord
Comments.UserDisplayName: Alex Roper
Tags: <permissions><user-groups>
Title: Restrict viewing front end to specific group permissions
ThreadText: # Restrict viewing front end to specific group permissions
  
  (Asked by: username_0 on 2020-02-04)
  
  How can I restrict content frontend to specific user groups?
  There seems no sensible way to do this out of the box.
  For example group permissions in CP are all about CP - there is no view option.
  
  Never had a use case for this before today but have one now and finding Craft3 coming up short :(
  
  Scenario is a support portal where different companies can provide user specific content. Idea is login with company id (done that ok via a plugin) but then once logged in they get redirected to content for that specific company.
  
  So I have two probs now: redirect to company 'home page', and restrict access to content. I've considered splitting content into sites and pairing users with sites. I've considered section root parent and checking permissions for top of tree in twig. I'm thinking restricting per section is best and adding company homepage as entry field in user field or user group field and managing access via plugin + twig but its all feeling very heavy handed....
  
  **Tags:** permissions, user-groups
  
  > **Comments:**
  > **username_1**: Have you tried the answers to this question "Check user is in User Group / Custom User Permissions?" https://craftcms.stackexchange.com/questions/1087/check-user-is-in-user-group-custom-user-permissions  
  > **username_0**: Thanks username_1 - hadn't seen it looks useful. But cant believe there is no front end permission view and having to roll a plugin for what should be core is annoying++  
  > **username_1**: Also, it might be helpful to talk thru the problem on the Craft CMS Discord channel: https://craftcms.com/discord  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_1 on 2020-02-05. Score: 4 | Accepted answer
  
  If you setup a User Group with the same handle as the Site you want them to have access to, this could be fairly easy.
  
  Let's say you have a site called "Acme" setup in the Sites settings. You also created a corresponding User Group called "Acme." The handles for the Acme Site and Acme User Group are both "acme."
  
  When you're on the Acme site's front-end, possibly `example.com/acme` depending on how [you set up your site URLs](https://docs.craftcms.com/v3/sites.html#site-url), the `{{ currentSite.handle }}` tag will return `acme`.
  
  To test if a user has access to content in your template you can use something like `{% if currentUser.isInGroup(currentSite.handle) %}`.
  
  Adding this to any template will prevent unauthorized access if a user is not in a group:
  
  ```
  {% if not currentUser.isInGroup(currentSite.handle) %}  
    {% exit 403 %}
  {% endif %}
  
  ```
  
  You would also probably want to allow admins or users groups who can access the control panel:
  
  ```
  allow admins:
  
  {% if not currentUser.isInGroup(currentSite.handle) or not currentUser.admin %}  
    {% exit 403 %}
  {% endif %}
  
  ... or allow any user that can access the control panel:
  
  {% if not currentUser.isInGroup(currentSite.handle) or not currentUser.can('accessCp') %}  
    {% exit 403 %}
  {% endif %}
  
  ```
  
  Redirecting to the correct site after a login page is a little trickier because users can belong to more than one group.
  
  But assuming that users only belong to one group you could redirect users to a sort of "routing" template that's only job is to send you to the right place.
  
  ```
  {% set firstGroup = currentUser.getGroups()[0] ?? null %}
  
  {% if firstGroup %}
    {% redirect firstGroup.handle %}
  {% else %}
    ... default redirect or error 
  {% endif %}
  
  ```
  
  Also, here's a list of permission you can use with the `currentUser.can()` method:
  
  <https://docs.craftcms.com/v3/users.html#permissions>
  
  > **Comments:**
  > **username_0**: Thanks username_1. Your reply is a good reminder to spell out the scenario, and is a most welcome creative addition/solution to the problem.I need to support other languages within a company but i think i can see how this will work. I'm going to implement the above and jump on discord if I find problems. Thanks again  
  
  ---
  
  ### Answer by username_2 on 2022-05-14. Score: 1
  
  Hi extending permissions on a group level is a first approach, here is a piece of code that create group permissions for each entry, it would be easy to customize it to allow only top level entries. It is based on cvraft cms extending permissions tutorial <https://craftcms.com/docs/4.x/extend/user-permissions.html#requiring-permissions>
  
  ```
     
          $entries = \craft\elements\Entry::find() ->all();
  
  Event::on(
                  UserPermissions::class,
                  UserPermissions::EVENT_REGISTER_PERMISSIONS,
                  function (RegisterUserPermissionsEvent $event) use ($entries) {
  
                   $entryPerms=[];
                      foreach ($entries as $entry) {
                      if ($entry->title)    $entryPerms[  'WaveEntryAccess' . $entry->id]=
                             [
                                  'label' => $entry->title
                              ] ;
                   }
              $arrPerm = array(
                  'permissionName' => [
                      'label' => "Wave Member access",
                      'nested' => $entryPerms
                  ],
              );
                      $event->permissions['Member restricted access'  ]  =
                          $arrPerm ;
                  }
              );
  
  ```
  
  
  ---
  
  ### Answer by username_3 on 2020-02-05. Score: 1
  
  I've done this! Let me try to explain without writing a small novel. There were a lot of bits, but it works.
  
  Start by creating a user group for every client. As you create these, write down the group *handle*. (Note: doesn't need any permissions other than logging in.)
  
  Make a channel containing your clients as individual entries, and in the fields for each entry, add a text field called "Client Portal Handle" - and copy the handle from the user groups to that field.
  
  Then, in my the templates, I'm setting up the page urls to be /portal// - and I set a field (I called it 'associatedClient') on entry, so each entry goes to that client.
  
  And, here's the bit that makes it all work, in a template, it's got code that says:
  
  ```
  {% set client = entry.associatedClient.one() %}
  {% set cg = client.portalGroup %}
  
  {% if currentUser.admin or currentUser.isInGroup(cg) %}
    {# document template goes here #}
  {% else %}
    {# back to the login page #}
  {% endif %}
  
  ```
  
  Line 1 gets the client attached to the doc. Line 2 gets the *handle* attached to the client.
  
  Then the if-check sees if the logged-in user is in that group or they're an admin.
  
  Does that all make sense?
  
  ---
  
  Edit: redirecting to the company page.
  
  I've got a generic /portal/ page, and it shows a "Take me to my portal" link, that shows content based on which group a user is in. And then there's some generic contact info and stuff that applies to everyone. This could be better, but it was our solution for the first config.
  
  > **Comments:**
  > **username_0**: Thanks username_3 this looks very interesting- is that just one page per client? Not sure where 'associatedClient' fits in. It also feels like I'd be assigning the permission per content each time and make it hard for super admins to administer different company content. But happy for further illumination / explanation :)  
  > **username_3**: Oh, skipped an item. I added a relationship field to each doc entry. So when add an entry, you select which client it goes to. When someone visits, page gets the client info and the client handle. Then checks permissions against the handle. The magic bit is that you've got a handle in a regular entry field that matches against the handle in the groups.  
  
  ---
  
  