Browse code

Add backend permissions for booking view

Benjamin Roth authored on03/09/2025 23:04:39
Showing8 changed files
... ...
@@ -37,6 +37,8 @@ ArrayUtil::arrayInsert($GLOBALS['BE_MOD'],1,[
37 37
     ]
38 38
 ]);
39 39
 
40
+$GLOBALS['TL_PERMISSIONS'][] = 'standorts';
41
+$GLOBALS['TL_PERMISSIONS'][] = 'reservationp';
40 42
 
41 43
 $GLOBALS['TL_MODELS']['tl_vr_wa_units'] = WeinanlieferungUnitsModel::class;
42 44
 $GLOBALS['TL_MODELS']['tl_vr_wa_slottypes'] = WeinanlieferungSlottypesModel::class;
... ...
@@ -20,7 +20,6 @@ PaletteManipulator::create()
20 20
 // Add fields to tl_member_group
21 21
 $GLOBALS['TL_DCA']['tl_member_group']['fields']['standorts'] = array
22 22
 (
23
-    'label'                   => &$GLOBALS['TL_LANG']['tl_member_group']['standorts'],
24 23
     'exclude'                 => true,
25 24
     'inputType'               => 'checkbox',
26 25
     'foreignKey'              => 'tl_vr_wa_standort.title',
27 26
new file mode 100644
... ...
@@ -0,0 +1,40 @@
1
+<?php
2
+
3
+/**
4
+ * This file is part of contao-weinanlieferung-bundle.
5
+ *
6
+ * (c) vonRotenberg
7
+ *
8
+ * @license commercial
9
+ */
10
+
11
+use Contao\CoreBundle\DataContainer\PaletteManipulator;
12
+
13
+// Extend the default palette
14
+PaletteManipulator::create()
15
+    ->addLegend('luumicore_legend', 'imageSizes_legend', PaletteManipulator::POSITION_AFTER)
16
+    ->addField(array('standorts','reservationp'), 'luumicore_legend', PaletteManipulator::POSITION_APPEND)
17
+    ->applyToPalette('default', 'tl_user_group')
18
+;
19
+
20
+// Add fields to tl_user_group
21
+$GLOBALS['TL_DCA']['tl_user_group']['fields']['standorts'] = array
22
+(
23
+    'exclude'                 => true,
24
+    'inputType'               => 'checkbox',
25
+    'foreignKey'              => 'tl_vr_wa_standort.title',
26
+    'eval'                    => array('multiple'=>true),
27
+    'sql'                     => "blob NULL"
28
+);
29
+
30
+$GLOBALS['TL_DCA']['tl_user_group']['fields']['reservationp'] = array
31
+(
32
+    'exclude'               => true,
33
+    'filter'                => true,
34
+    'options'               => array('edit', 'delete'),
35
+    'eval'                  => array('multiple'=>true),
36
+    'reference'             => &$GLOBALS['TL_LANG']['MSC'],
37
+    'inputType'             => 'checkbox',
38
+    'sql'                   => "blob NULL"
39
+
40
+);
0 41
new file mode 100644
... ...
@@ -0,0 +1,16 @@
1
+<?php
2
+
3
+/**
4
+ * This file is part of contao-weinanlieferung-bundle.
5
+ *
6
+ * (c) vonRotenberg
7
+ *
8
+ * @license commercial
9
+ */
10
+
11
+// Legends
12
+$GLOBALS['TL_LANG']['tl_user_group']['luumicore_legend'] = 'luumiCORE-Berechtigungen';
13
+
14
+// Fields
15
+$GLOBALS['TL_LANG']['tl_user_group']['standorts'] = ['Erlaubte Standorte', 'Hier können Sie den Zugriff auf einen oder mehrere Standorte erlauben.'];
16
+$GLOBALS['TL_LANG']['tl_user_group']['reservationp'] = ['Buchung-Rechte', 'Hier können Sie die Buchungsrechte festlegen.'];
... ...
@@ -93,16 +93,20 @@
93 93
                                                     {{ booking.amount }} x {{ booking.unit }}
94 94
                                                 </div>
95 95
                                                 <div class="col u-text-right action">
96
-                                                    <a
97
-                                                        href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=edit&id={{ booking.id }}&rt={{ request_token }}&ref={{ ref }}"
98
-                                                        title="Element ID {{ booking.id }} bearbeiten"
99
-                                                        onclick="event.stopPropagation()"
100
-                                                    ><img src="/system/themes/flexible/icons/edit.svg" width="16" height="16" alt="Element ID {{ booking.id }} bearbeiten"></a>
101
-                                                    <a
102
-                                                        href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=delete&id={{ booking.id }}&rt={{ request_token }}"
103
-                                                        onclick="event.stopPropagation(); if(!confirm('Soll das Element ID {{ booking.id }} wirklich gelöscht werden?'))return false;Backend.getScrollOffset()"
104
-                                                        title="Element ID {{ booking.id }} löschen"
105
-                                                    ><img src="/system/themes/flexible/icons/delete.svg" width="16" height="16" alt="Element ID {{ booking.id }} löschen"></a>
96
+                                                    {% if permissions.edit %}
97
+                                                        <a
98
+                                                            href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=edit&id={{ booking.id }}&rt={{ request_token }}&ref={{ ref }}"
99
+                                                            title="Element ID {{ booking.id }} bearbeiten"
100
+                                                            onclick="event.stopPropagation()"
101
+                                                        ><img src="/system/themes/flexible/icons/edit.svg" width="16" height="16" alt="Element ID {{ booking.id }} bearbeiten"></a>
102
+                                                    {% endif %}
103
+                                                    {% if permissions.delete %}
104
+                                                        <a
105
+                                                            href="/contao?do=weinanlieferung&table=tl_vr_wa_reservation&act=delete&id={{ booking.id }}&rt={{ request_token }}"
106
+                                                            onclick="event.stopPropagation(); if(!confirm('Soll das Element ID {{ booking.id }} wirklich gelöscht werden?'))return false;Backend.getScrollOffset()"
107
+                                                            title="Element ID {{ booking.id }} löschen"
108
+                                                        ><img src="/system/themes/flexible/icons/delete.svg" width="16" height="16" alt="Element ID {{ booking.id }} löschen"></a>
109
+                                                    {% endif %}
106 110
                                                 </div>
107 111
                                             </div>
108 112
 
... ...
@@ -13,8 +13,10 @@ declare(strict_types=1);
13 13
 namespace vonRotenberg\WeinanlieferungBundle\Controller\Backend;
14 14
 
15 15
 use Contao\Backend;
16
+use Contao\BackendUser;
16 17
 use Contao\CoreBundle\Controller\AbstractController;
17 18
 use Contao\CoreBundle\Csrf\ContaoCsrfTokenManager;
19
+use Contao\Database;
18 20
 use Contao\Date;
19 21
 use Contao\Environment;
20 22
 use Contao\FrontendUser;
... ...
@@ -33,6 +35,7 @@ use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungRebsorteModel;
33 35
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungReservationModel;
34 36
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungSlotsModel;
35 37
 use vonRotenberg\WeinanlieferungBundle\Model\WeinanlieferungAttributeModel;
38
+use vonRotenberg\WeinanlieferungBundle\Security\WeinanlieferungPermissions;
36 39
 
37 40
 /**
38 41
  * @Route("contao/weinanlieferung/buchungsliste", name=WeinanlieferungBookingsController::class, defaults={"_scope" = "backend"})
... ...
@@ -103,6 +106,10 @@ class WeinanlieferungBookingsController extends AbstractController
103 106
             ->select('id')
104 107
             ->from(WeinanlieferungSlotsModel::getTable());
105 108
 
109
+        // Allowed standorts
110
+        $allowedStandortIds = $this->getAllowedStandortIds();
111
+        $queryBuilder->andWhere('pid IN ('.implode(',',$allowedStandortIds).')');
112
+
106 113
         if (!empty($session['tl_vr_wa_reservation']['tl_day']) && is_numeric($session['tl_vr_wa_reservation']['tl_day']))
107 114
         {
108 115
             $Day = new Date($session['tl_vr_wa_reservation']['tl_day']);
... ...
@@ -157,7 +164,7 @@ class WeinanlieferungBookingsController extends AbstractController
157 164
         }*/
158 165
 
159 166
         $arrStandortOptions = [];
160
-        $StandortRequest = $this->db->executeQuery("SELECT l.id, l.title FROM tl_vr_wa_reservation r INNER JOIN tl_vr_wa_slot s ON s.id = r.pid INNER JOIN tl_vr_wa_standort l ON l.id = s.pid GROUP BY l.id ORDER BY l.title ASC");
167
+        $StandortRequest = $this->db->executeQuery("SELECT l.id, l.title FROM tl_vr_wa_reservation r INNER JOIN tl_vr_wa_slot s ON s.id = r.pid INNER JOIN tl_vr_wa_standort l ON l.id = s.pid WHERE s.pid IN (".implode(',',$allowedStandortIds).") GROUP BY l.id ORDER BY l.title ASC");
161 168
         foreach ($StandortRequest->iterateAssociative() as $standort)
162 169
         {
163 170
             $arrStandortOptions[$standort['id']] = $standort['title'];
... ...
@@ -326,6 +333,13 @@ class WeinanlieferungBookingsController extends AbstractController
326 333
             }
327 334
         }
328 335
 
336
+        // Security
337
+        $security = System::getContainer()->get('security.helper');
338
+        $arrData['permissions'] = [
339
+            'edit' => $security->isGranted(WeinanlieferungPermissions::USER_CAN_EDIT_RESERVATIONS),
340
+            'delete' => $security->isGranted(WeinanlieferungPermissions::USER_CAN_DELETE_RESERVATIONS),
341
+        ];
342
+
329 343
         return new Response(
330 344
             $this->twig->render(
331 345
                 '@Contao_VonrotenbergWeinanlieferungBundle/be_wa_buchungsliste.html.twig',
... ...
@@ -333,4 +347,34 @@ class WeinanlieferungBookingsController extends AbstractController
333 347
             )
334 348
         );
335 349
     }
350
+
351
+    protected function getAllowedStandortIds(): array
352
+    {
353
+        // If no frontend user is logged in, return empty array
354
+        if (!BackendUser::getInstance()->id) {
355
+            return [];
356
+        }
357
+
358
+        // Get member groups
359
+        $userGroups = StringUtil::deserialize(BackendUser::getInstance()->groups, true);
360
+        if (empty($userGroups)) {
361
+            return [];
362
+        }
363
+
364
+        // Get allowed standorts from member groups
365
+        $db = Database::getInstance();
366
+        $allowedStandorts = [];
367
+
368
+        foreach ($userGroups as $groupId) {
369
+            $group = $db->prepare("SELECT standorts FROM tl_user_group WHERE id=?")
370
+                ->execute($groupId);
371
+
372
+            if ($group->standorts) {
373
+                $groupStandorts = StringUtil::deserialize($group->standorts, true);
374
+                $allowedStandorts = array_merge($allowedStandorts, $groupStandorts);
375
+            }
376
+        }
377
+
378
+        return array_unique($allowedStandorts);
379
+    }
336 380
 }
... ...
@@ -48,7 +48,8 @@ use vonRotenberg\WeinanlieferungBundle\Controller\Backend\WeinanlieferungSlotAss
48 48
 
49 49
          if (($contentNode = $tree->getChild('weinanlieferung')) === null)
50 50
          {
51
-             $contentNode = $tree->addChild('weinanlieferung');
51
+             $contentNode = $tree->addChild('weinanlieferung')
52
+             ->setLabel('Weinanlieferung');
52 53
          }
53 54
 
54 55
          $node = $factory
55 56
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+<?php
2
+
3
+declare(strict_types=1);
4
+
5
+/*
6
+ * This file is part of Contao.
7
+ *
8
+ * (c) Leo Feyer
9
+ *
10
+ * @license LGPL-3.0-or-later
11
+ */
12
+
13
+namespace vonRotenberg\WeinanlieferungBundle\Security;
14
+
15
+final class WeinanlieferungPermissions
16
+{
17
+    public const USER_CAN_EDIT_STANDORTE = 'contao_user.standorts';
18
+    public const USER_CAN_EDIT_RESERVATIONS = 'contao_user.reservationp.edit';
19
+    public const USER_CAN_DELETE_RESERVATIONS = 'contao_user.reservationp.delete';
20
+}