Skip to content
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

[UI] Displaying elements based on user permissions in Twig #212

Open
wants to merge 1 commit into
base: 5.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions docs/design/displaying_elements_based_on_user_permissions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
Displaying elements based on user permissions

Check warning on line 1 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 1, "column": 30}}}, "severity": "INFO"}
=============================================

In Mautic, it's possible to control the visibility of elements on the user interface based on the user's permissions. This allows for showing or hiding certain features, links, or sections depending on the user's role and the permissions associated with that role.

Check warning on line 4 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 4, "column": 71}}}, "severity": "INFO"}

Check warning on line 4 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 4, "column": 99}}}, "severity": "INFO"}

Check warning on line 4 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 4, "column": 207}}}, "severity": "INFO"}

Check warning on line 4 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Role' instead of 'role'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Role' instead of 'role'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 4, "column": 214}}}, "severity": "INFO"}

Check warning on line 4 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Role' instead of 'role'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Role' instead of 'role'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 4, "column": 260}}}, "severity": "INFO"}

This approach enhances security and provides a tailored experience for each user based on their role and access level.

Check warning on line 6 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 6, "column": 77}}}, "severity": "INFO"}

Check warning on line 6 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Role' instead of 'role'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'Role' instead of 'role'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 6, "column": 97}}}, "severity": "INFO"}

Using the securityIsGranted function

Check warning on line 8 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Headings] 'Using the securityIsGranted function' should use sentence-style capitalization. Raw Output: {"message": "[Google.Headings] 'Using the securityIsGranted function' should use sentence-style capitalization.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 8, "column": 1}}}, "severity": "WARNING"}
------------------------------------

To display elements conditionally based on user permissions, use the securityIsGranted function in Twig templates. The securityIsGranted function checks if the current user has the specified permission and returns a boolean value indicating whether the permission is granted or not.

Check warning on line 11 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'. Raw Output: {"message": "[Mautic.FeatureList] Is this referring to a Mautic feature? If so, use 'User' instead of 'user'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 11, "column": 44}}}, "severity": "INFO"}

Here's the basic syntax:

.. code-block:: twig

{% if securityIsGranted('permission:string') %}
<!-- Content to display if the user has the specified permission -->
{% endif %}

In this structure, 'permission:string' represents the specific permission being checked for. Mautic uses a hierarchical permission system, in the format of 'bundle:level:permission'.

Displaying a user invitation link as example
--------------------------------------------

Let's examine a practical example of how to use this function to display a link for inviting new users to the platform. This link should only be visible to users who have the permission to create new user accounts.

In this example, we're using the securityIsGranted function to check if the current user has the 'user:users:create' permission. This permission string is structured to indicate that we're checking for the ability to create new users within the user management system.

.. code-block:: twig

{% if securityIsGranted('user:users:create') %}
<li>
<a href="{{ path('mautic_user_action', {objectAction: 'new'}) }}">
<i class="ri-team-line"></i>
<span>{{ 'mautic.user.profile.invite'|trans }}</span>
</a>
</li>
{% endif %}

If the current user has the user:users:create permission, the code inside the if block will be rendered, displaying the link to invite new users. The link is created using the path function, which generates a URL based on the specified route (mautic_user_action) and any additional parameters ({objectAction: 'new'}).

The 'mautic.user.profile.invite'|trans expression is used to translate the text "Invite your team" using Mautic's translation system. This ensures that the text is displayed in the appropriate language based on the user's locale settings.

Check failure on line 43 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Vale.Terms] Use 'Mautic' instead of 'mautic'. Raw Output: {"message": "[Vale.Terms] Use 'Mautic' instead of 'mautic'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 43, "column": 6}}}, "severity": "ERROR"}

This not only prevents unauthorized access but also keeps the interface clean and relevant for each user's role.

When implementing permission-based displays, it's essential to also secure the backend routes and actions that these interface elements might trigger. The frontend permission check should be considered an additional layer of security and user experience enhancement, not the sole method of access control.

Locating defined permissions
----------------------------

Mautic organizes its permissions on a per-bundle basis. Each bundle typically defines its own set of permissions in a dedicated PHP file. The standard location for these permission definitions is:

[BundleName]/Security/[BundleName]Permissions.php

Check failure on line 54 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Vale.Terms] Use 'PHP' instead of 'php'. Raw Output: {"message": "[Vale.Terms] Use 'PHP' instead of 'php'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 54, "column": 47}}}, "severity": "ERROR"}

For example:

- User permissions: UserBundle/Security/UserPermissions.php

Check failure on line 58 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Vale.Terms] Use 'PHP' instead of 'php'. Raw Output: {"message": "[Vale.Terms] Use 'PHP' instead of 'php'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 58, "column": 57}}}, "severity": "ERROR"}
- Email permissions: EmailBundle/Security/EmailPermissions.php

Check failure on line 59 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Vale.Terms] Use 'PHP' instead of 'php'. Raw Output: {"message": "[Vale.Terms] Use 'PHP' instead of 'php'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 59, "column": 60}}}, "severity": "ERROR"}
- SMS permissions: SmsBundle/Security/SmsPermissions.php

Check failure on line 60 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Vale.Terms] Use 'PHP' instead of 'php'. Raw Output: {"message": "[Vale.Terms] Use 'PHP' instead of 'php'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 60, "column": 54}}}, "severity": "ERROR"}

These PHP files contain classes that extend AbstractPermissions and define the specific permissions available for that bundle. They usually include methods for building the permission matrix and checking individual permissions.

Examining permission files
--------------------------

When opening one of these permission files, they'll typically find:

- A definePermissions method that outlines all available permissions for the bundle.

Check failure on line 69 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'definePermissions'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'definePermissions'?", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 69, "column": 5}}}, "severity": "ERROR"}
- Constants defining permission levels (e.g., LEVEL_VIEW, LEVEL_EDIT, LEVEL_FULL).

Check failure on line 70 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Latin] Use 'for example' instead of 'e.g.,'. Raw Output: {"message": "[Google.Latin] Use 'for example' instead of 'e.g.,'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 70, "column": 41}}}, "severity": "ERROR"}
- Methods for checking specific permissions (e.g., canViewUsers, canEditEmails).

Check failure on line 71 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Google.Latin] Use 'for example' instead of 'e.g.,'. Raw Output: {"message": "[Google.Latin] Use 'for example' instead of 'e.g.,'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 71, "column": 46}}}, "severity": "ERROR"}

For example, in the UserPermissions.php file, the UserPermissions class defines the available permissions for the UserBundle using a more structured approach. Let's go through the important parts:

Check failure on line 73 in docs/design/displaying_elements_based_on_user_permissions.rst

View workflow job for this annotation

GitHub Actions / prose

[vale] reported by reviewdog 🐶 [Vale.Terms] Use 'PHP' instead of 'php'. Raw Output: {"message": "[Vale.Terms] Use 'PHP' instead of 'php'.", "location": {"path": "docs/design/displaying_elements_based_on_user_permissions.rst", "range": {"start": {"line": 73, "column": 37}}}, "severity": "ERROR"}

.. code-block:: php

$this->permissions = [
'profile' => [
'editusername' => 1,
'editemail' => 2,
'editposition' => 4,
'editname' => 8,
'full' => 1024,
],
];

In this example, the profile key represents the permission category, and the nested array defines the specific permission levels for actions like editing the username, email, position, name, and having full access to the user profile.

To use these permission keys with the securityIsGranted function in Twig templates, construct the appropriate permission string. The permission string follows the format: [bundle]:[level]:[permission].

Map the permission keys from the UserPermissions class to the corresponding permission strings:

- editusername => user:profile:editusername
- editemail => user:profile:editemail
- editposition => user:profile:editposition
- editname => user:profile:editname
- full => user:profile:full

In each if statement, the securityIsGranted function is used with the corresponding permission string. If the current user has the specified permission, the code inside the if block will be executed, displaying the relevant form fields for editing the user profile information.

For more information, refer to the Security documentation.
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ There are several ways to support Mautic other than contributing with code.
:hidden:

design/retrieving_system_settings
design/displaying_elements_based_on_user_permissions

.. toctree::
:maxdepth: 2
Expand Down
Loading