Skip to content

Commit 5acf59a

Browse files
authored
Merge pull request mautic#277 from OfficialJhimmy/wth-roles-and-permission
docs:migrating roles and permisison components to the latest docs
2 parents 6a64eac + dd8759a commit 5acf59a

1 file changed

Lines changed: 286 additions & 5 deletions

File tree

docs/plugins/permissions.rst

Lines changed: 286 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,295 @@
11
Roles and permissions
22
#####################
33

4-
.. vale off
4+
Mautic defines custom Role permissions through Permission objects.
5+
6+
How permissions work
7+
********************
8+
9+
Mautic calculates permissions based on bits assigned to a Plugin level and permission. Bits are integers that increase by doubling the value - 1, 2, 4, 8, 16, 32, 64, 128, 512, 1024, and so forth. Avoid assigning numbers in between, such as 3 or 5, because the permission won't calculate correctly.
10+
11+
For example, if ``HelloWorldBundle`` manages access to a ``worlds`` entity, the permission set for ``plugin:helloWorld:worlds`` resembles this setup:
12+
13+
.. list-table::
14+
:widths: 50 50
15+
:header-rows: 1
16+
17+
* - Permission
18+
- Bit
19+
* - view
20+
- 1
21+
* - edit
22+
- 2
23+
* - create
24+
- 4
25+
* - delete
26+
- 8
27+
* - full
28+
- 16
29+
30+
.. note::
31+
32+
The notation ``plugin:helloWorld:worlds:view`` typically requests permission in Mautic. This notation tells Mautic to verify the ``view`` permission for the Plugin ``HelloWorldBundle`` at the ``worlds`` level. Levels allow Plugins to set permissions for multiple areas.
33+
34+
Mautic sums the bits for the permissions granted to a Role and stores the result in the database. For example, if a Role has ``view`` and ``edit`` access, the stored bit is 3. If given ``view`` and ``create`` access, the stored bit is 5.
35+
36+
When permission verification is necessary - for instance ``plugin:helloWorld:worlds:create`` - Mautic verifies if the Role's generated bit for ``plugin:helloWorld:worlds`` includes bit 4. If so, Mautic grants permission.
537

638
.. note::
739

8-
The content for this page requires a major update. The legacy page contains outdated and potentially inaccurate information. You can still access it in the :xref:`legacy repository`.
40+
The ``full`` permission grants access to all prior permissions and should always be the highest bit.
41+
42+
Using permissions
43+
*****************
44+
45+
.. code-block:: php
46+
47+
<?php
48+
49+
$security = $this->get('mautic.security');
50+
51+
// Check if user is granted a single permission
52+
if ($security->isGranted('plugin:helloWorld:worlds:view')) {
53+
// do something
54+
}
55+
56+
// Check if user is granted multiple permissions (must be granted to all to be true)
57+
if ($security->isGranted(
58+
array(
59+
'plugin:helloWorld:worlds:view',
60+
'plugin:helloWorld:worlds:create',
61+
)
62+
)) {
63+
// do something
64+
}
65+
66+
// Check if user is granted to at least one permission
67+
if ($security->isGranted(
68+
array(
69+
'plugin:helloWorld:worlds:view',
70+
'plugin:helloWorld:worlds:edit',
71+
),
72+
'MATCH_ONE'
73+
)) {
74+
// do something
75+
}
76+
77+
// Get an array of user permissions
78+
$permissions = $security->isGranted(
79+
array(
80+
'plugin:helloWorld:worlds:view',
81+
'plugin:helloWorld:worlds:edit',
82+
),
83+
'RETURN_ARRAY'
84+
);
85+
86+
if ($permissions['plugin:helloWorld:worlds:view']) {
87+
// do something
88+
}
89+
90+
// Check if user has access to view leads
91+
if ($security->isGranted('lead:leads:viewother')) {
92+
// do something
93+
}
94+
95+
To determine if a User has a specific permission, use the Mautic security service, which you can obtain from the ``mautic.security`` service.
96+
97+
Mautic uses specific notation to identify permissions:
98+
99+
* **Core bundles**: use the format ``bundleName:permissionLevel:permission``.
100+
* **Plugins**: append the ``plugin:`` prefix. For example, ``plugin:bundleName:permissionLevel:permission``. Plugins require this prefix because it directs Mautic to search for the permission class within the ``plugins/`` directory and the ``MauticPlugin`` namespace.
101+
102+
Core bundles or Plugins set the permission level and permissions. For example, the core UserBundle has ``users`` and ``roles`` levels with ``view``, ``edit``, ``create``, ``delete``, and ``full`` permissions for each. To verify if a User has permission to edit Roles, use:
103+
104+
.. code-block:: php
105+
106+
$security->isGranted('user:roles:edit');
107+
108+
Creating custom permissions
109+
***************************
110+
111+
A Plugin creates its own set of permissions by defining a Permission class. Each permission class must extend ``Mautic\CoreBundle\Security\Permissions\AbstractPermissions``.
112+
113+
.. code-block:: php
114+
115+
<?php
116+
// plugins/HelloWorldBundle/Security/Permissions/HelloWorldPermissions.php
117+
118+
namespace MauticPlugin\HelloWorldBundle\Security\Permissions;
119+
120+
use Symfony\Component\Form\FormBuilderInterface;
121+
use Mautic\CoreBundle\Security\Permissions\AbstractPermissions;
122+
123+
class HelloWorldPermissions extends AbstractPermissions
124+
{
125+
public function __construct($params)
126+
{
127+
parent::__construct($params);
128+
129+
$this->permissions = array(
130+
'worlds' => array(
131+
'use_telescope' => 1,
132+
'send_probe' => 2,
133+
'visit' => 4,
134+
'full' => 1024
135+
)
136+
);
137+
138+
// Add standard category permissions
139+
$this->addStandardPermissions('categories');
140+
}
141+
142+
public function buildForm(FormBuilderInterface &$builder, array $options, array $data)
143+
{
144+
// Add standard category form fields
145+
$this->addStandardFormFields('helloWorld', 'categories', $builder, $data);
146+
147+
// Add custom 'worlds' level form fields
148+
$builder->add(
149+
'helloWorld:worlds',
150+
'permissionlist',
151+
array(
152+
'choices' => array(
153+
'use_telescope' => 'plugin.helloworld.permissions.use_telescope',
154+
'send_probe' => 'plugin.helloworld.permissions.send_probe',
155+
'visit' => 'plugin.helloworld.permissions.visit',
156+
'full' => 'mautic.core.permissions.full',
157+
),
158+
'label' => 'plugin.helloworld.permissions',
159+
'data' => (!empty($data['worlds']) ? $data['worlds'] : array()),
160+
'bundle' => 'helloWorld',
161+
'level' => 'worlds'
162+
)
163+
);
164+
}
165+
166+
public function getName()
167+
{
168+
return 'helloWorld';
169+
}
170+
}
171+
172+
Most permission classes require three methods: ``__construct()``, ``buildForm()``, and ``getName()``.
173+
174+
``__construct()``
175+
=================
176+
177+
The constructor performs two tasks. It calls ``parent::__construct($params)`` or sets ``$this->params = $params;``. It then defines the ``$this->permissions`` array. This array organizes permissions into levels, where each level contains specific permissions assigned to bits.
178+
179+
For example, in the code sample, a custom level of ``worlds`` includes ``use_telescope``, ``send_probe``, ``visit``, and ``full``. To verify if a User has the ``send_probe`` permission for the ``worlds`` level, use:
180+
181+
.. code-block:: php
182+
183+
$mauticSecurity->isGranted('plugin:helloWorld:worlds:send_probe');
184+
185+
Mautic provides helper methods for common permission sets:
186+
187+
.. list-table::
188+
:widths: 30 70
189+
:header-rows: 1
190+
191+
* - Method
192+
- Description
193+
* - ``addStandardPermissions()``
194+
- Sets ``view``, ``edit``, ``create``, ``delete``, ``publish`` - with an option to exclude - and ``full`` permissions.
195+
* - ``addExtendedPermissions()``
196+
- Sets creator-level restrictions - ``viewown``, ``viewother``, ``editown``, ``editother``, ``create``, ``deleteown``, ``deleteother``, ``publishown``, ``publishother``, and ``full``.
197+
* - ``addManagePermission()``
198+
- Sets a single ``manage`` permission.
199+
200+
``buildForm()``
201+
===============
202+
203+
.. vale off
204+
205+
The ``buildForm()`` method appends permission toggles to the Role's Form. See :doc:`/plugin_extensions/forms` for details on Form builders and review the comments in the code sample for implementation details.
206+
207+
.. vale on
208+
209+
Mautic provides complementary helper methods for common permission sets:
210+
211+
.. list-table::
212+
:widths: 30 70
213+
:header-rows: 1
214+
215+
* - Method
216+
- Description
217+
* - ``addStandardFormFields()``
218+
- Appends the standard permission sets to the Form.
219+
* - ``addExtendedFormFields()``
220+
- Appends the extended - creator restricted - permissions to the Form.
221+
* - ``addManageFormFields()``
222+
- Appends the single manager element to the Form.
223+
224+
``getName()``
225+
=============
226+
227+
This method is mandatory. The return value must match the ``bundleName`` and the filename. For example, if the bundle name is ``HelloWorldBundle``, this method returns ``helloWorld`` and the file is ``HelloWorldPermissions.php``.
228+
229+
Permission aliases
230+
******************
231+
232+
.. code-block:: php
233+
234+
<?php
235+
236+
protected function getSynonym($name, $level)
237+
{
238+
if ($name == 'send_satellite') {
239+
$name = 'send_probe';
240+
}
241+
242+
return array($name, $level);
243+
}
244+
245+
To add a permission alias, use the ``getSynonym()`` method. Mautic calls this method before determining each requested permission, giving an opportunity to change the permission level or name as needed.
246+
247+
For example, ``parent::getSynonym()`` recognizes ``editown`` as ``edit`` if the ``$this->permissions`` property for that level doesn't define ``editown``.
248+
249+
Manipulating permissions before saving
250+
**************************************
251+
252+
.. code-block:: php
253+
254+
<?php
255+
256+
public function analyzePermissions(array &$permissions, $allPermissions, $isSecondRound = false)
257+
{
258+
foreach ($permissions as $level => &$perms) {
259+
foreach ($perms as $perm) {
260+
$include = array();
261+
switch ($perm) {
262+
case 'send_probe':
263+
$include = array('use_telescope');
264+
break;
265+
case 'visit':
266+
$include = array('use_telescope', 'send_probe');
267+
break;
268+
}
269+
if (!empty($include)) {
270+
foreach ($include as $r) {
271+
list($ignore, $r) = $this->getSynonym($level, $r);
272+
if ($this->isSupported($level, $r) && !in_array($r, $perms)) {
273+
$perms[] = $r;
274+
}
275+
}
276+
}
277+
}
278+
}
279+
280+
return false;
281+
}
282+
283+
Plugins can adjust permissions based on other selections to prevent User error. For example, if a User has ``edit`` permission, they also require ``view`` permission. Use the ``analyzePermissions()`` method to modify permissions before Mautic persists them to the database.
284+
285+
To re-adjust permissions based on factors outside the Plugin's control, return ``true`` from ``analyzePermissions()``. This triggers a second round of analysis after all other bundles and Plugins finish their processing. During this round, the ``$isSecondRound`` argument is ``true``.
286+
287+
Advanced ``isGranted()`` logic
288+
==============================
9289

10-
If you're interested in helping develop the new content for this page and others, consider joining the documentation efforts.
290+
Override the parent method - ``public function isGranted($userPermissions, $name, $level)`` - to run custom logic rather than simple bit comparisons. Use this to define unique behavior for the class's own levels and individual permissions.
11291

12-
Please read the :xref:`dev docs contributing guidelines` and :xref:`Contributing to Mautic’s documentation` to get started.
292+
Advanced ``isSupported()`` logic
293+
================================
13294

14-
.. vale on
295+
The same rules apply to the ``isSupported()`` method. This method determines if a bundle or Plugin includes the requested permission and permission level. Use this to provide backward compatibility - BC - support.

0 commit comments

Comments
 (0)