Kaynağa Gözat

mustikas11: rollide õigused ja lehtede juurdepääs D7-ga vastavusse

ardo 1 gün önce
ebeveyn
işleme
c67764fc41

+ 50 - 0
third/drupal/mustikas11/LOEMIND.md

@@ -118,6 +118,56 @@ Skriptid (kordustäitmiseks):
 - `restore_footer.php` – footer blokid footer_top
 - `restrict_tools_sidebar.php` – tools_sidebar peidetud anonüümsele
 
+## Rollide ja õiguste vastavus (seis 2026-08)
+
+Rollide kaardistus D7 -> D11 on 1:1 (kasutajate jaotus säilis):
+
+| D7 roll | D11 roll | Õigused D11-s |
+|---------|----------|---------------|
+| anonymous | anonymous | contact form + filtered_html (access content EEMALDATUD) |
+| authenticated | authenticated | access content, view files, comments, contact form |
+| administrator | administrator | is_admin (kõik) |
+| EMAL liikmemaksud | emal_liikmemaksud | contact form |
+| EMAL juhatuse liige | emal_juhatuse_liige | **access filedepot**, contact form |
+| EMAL süsteemi administraator | emal_susteemi_administraator | 41+ õigust (admin pages, users, taxonomy, content create/edit/delete) + access filedepot + administer filedepot + contact form |
+| EMAL liige | emal_liige | contact form |
+| EMAL projektid | emal_projektid | contact form |
+| EMAL raamatupidamine | emal_raamatupidamine | contact form |
+| filedepot | filedepot | **access filedepot + administer filedepot** |
+| EMAL kutsekomisjon | emal_kutsekomisjon | **access filedepot** |
+
+### Lehtede juurdepääs (D7-ga vastavuses)
+
+| Leht | Juurdepääs |
+|------|------------|
+| `/liikmed`, `/projektid`, `/docs` | access content (kõik autenditud) |
+| `/filedepot` | **access filedepot** õigus |
+| `/kanded/liikmemaksud`, `/kanded/projektid`, `/kanded/tegevuskulud` | rollid admin, juhatus, süsteemi admin VÕI projekti juurdepääsu väljal olev kasutaja |
+| `/kanded/liikmemaksud/saldod` | rollid admin, juhatus, raamatupidamine, süsteemi admin |
+| `/kanded/projektid/saldod` | rollid admin, juhatus, raamatupidamine, süsteemi admin |
+| `/kanded/koik-kanded` | access content (kõik autenditud) |
+| `/liikmed/eksport` | rollid admin, süsteemi admin |
+| `/liikmed/synnipaevad` | access content |
+
+### Tehtud muudatused
+
+- Loodud custom permissionid: `access filedepot`, `administer filedepot` (mustikas_export.permissions.yml)
+- Loodud kanded Views access plugin `mustikas_kanded_access` + route access check
+  `mustikas_export.kanded_access` (src/Access/KandedAccessCheck.php)
+- Migreeritud `field_projekt_juurdepaas` (projekti juurdepääsu õigused) D7-st D11-sse
+  (11 rida, projektid 13550/13563/13565/13791/13885/13906)
+- Rakendatud kanded vaate display'dele D7-vastased access-id (defaults.access=false)
+- Liikmed CSV eksport piiratud admin+süsteemi admin rollidele
+- `/filedepot` vaade piiratud `access filedepot` õigusega
+- FileDownloadHooks nõuab nüüd `access filedepot` õigust (mitte ainult sisselogimist)
+
+Skriptid (kordustäitmiseks):
+- `migrate_projekt_juurdepaas.php` – projekti juurdepääsu andmete migratsioon
+- `grant_role_perms.php` – rollipõhiste õiguste andmine
+- `apply_kanded_access4.php` – kanded vaate access-ide seadistamine
+- `restrict_export.php` – CSV eksporti piiramine
+- `restrict_filedepot.php` – filedepot vaate piiramine
+
 ## Teadaolevad probleemid / edasiarendus
 
 1. **body "plain text" väli** – D7 body on konfigureeritud plain_text-iga, migrate

+ 69 - 0
third/drupal/mustikas11/apply_kanded_access4.php

@@ -0,0 +1,69 @@
+<?php
+use Drupal\views\Views;
+
+$view = Views::getView('kanded');
+if (!$view) {
+  echo "VIEW NOT FOUND\n";
+  exit;
+}
+
+$role_access = function (array $roles) {
+  $map = [];
+  foreach ($roles as $r) {
+    $map[$r] = $r;
+  }
+  return [
+    'type' => 'role',
+    'options' => ['role' => $map],
+  ];
+};
+
+$perm_access = [
+  'type' => 'perm',
+  'options' => ['perm' => 'access content'],
+];
+
+$kanded_access = [
+  'type' => 'mustikas_kanded_access',
+  'options' => [],
+];
+
+$config = [
+  'default' => $perm_access,
+  'page_1' => $perm_access,
+  'page_liikmemaksud' => $kanded_access,
+  'page_projektid' => $kanded_access,
+  'page_tegevuskulud' => $kanded_access,
+  'page_liikmemaksud_saldod' => $role_access([
+    'administrator', 'emal_juhatuse_liige', 'emal_raamatupidamine', 'emal_susteemi_administraator',
+  ]),
+  'page_projektid_saldod' => $role_access([
+    'emal_juhatuse_liige', 'emal_raamatupidamine', 'emal_susteemi_administraator',
+  ]),
+];
+
+$storage = $view->storage;
+$displays = $storage->get('display');
+foreach ($config as $display_id => $access) {
+  if (!isset($displays[$display_id])) {
+    echo "MISSING DISPLAY $display_id\n";
+    continue;
+  }
+  if (!isset($displays[$display_id]['display_options'])) {
+    $displays[$display_id]['display_options'] = [];
+  }
+  $displays[$display_id]['display_options']['access'] = $access;
+  // Peida "inherit default" access, et display kasutaks oma accessi.
+  if (!isset($displays[$display_id]['display_options']['defaults'])) {
+    $displays[$display_id]['display_options']['defaults'] = [];
+  }
+  if ($display_id === 'default') {
+    $displays[$display_id]['display_options']['defaults']['access'] = FALSE;
+  } else {
+    $displays[$display_id]['display_options']['defaults']['access'] = FALSE;
+  }
+  echo "SET $display_id -> " . $access['type'] . " (defaults.access=false)\n";
+}
+$storage->set('display', $displays);
+$storage->save();
+echo "STORAGE SAVED\n";

+ 15 - 0
third/drupal/mustikas11/custom_modules/mustikas_export/mustikas_export.permissions.yml

@@ -0,0 +1,15 @@
+access filedepot:
+  title: 'Juurdepääs filedepot kaustadele'
+  description: 'Võimaldab vaadata filedepot kaustu ja laadida faile alla.'
+administer filedepot:
+  title: 'Filedepot haldus'
+  description: 'Võimaldab hallata filedepot kaustu (lisada, muuta, kustutada, üles laadida).'
+view kanded:
+  title: 'Vaadata kandeid'
+  description: 'Võimaldab vaadata kanded lehti (liikmemaksud, projektide kanded, tegevuskulud) vastavalt projekti juurdepääsule.'
+view kanded saldod:
+  title: 'Vaadata kanded saldosid'
+  description: 'Võimaldab vaadata kanded saldode lehti.'
+export liikmed csv:
+  title: 'Liikmete CSV eksport'
+  description: 'Võimaldab eksportida liikmete nimekirja CSV-failina.'

+ 3 - 0
third/drupal/mustikas11/custom_modules/mustikas_export/mustikas_export.services.yml

@@ -0,0 +1,3 @@
+services:
+  mustikas_export.kanded_access:
+    class: Drupal\mustikas_export\Access\KandedAccessCheck

+ 49 - 0
third/drupal/mustikas11/custom_modules/mustikas_export/src/Access/KandedAccessCheck.php

@@ -0,0 +1,49 @@
+<?php
+
+namespace Drupal\mustikas_export\Access;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Session\AccountInterface;
+
+/**
+ * Kanded vaadete juurdepääsukontroll (D7 analogg).
+ *
+ * Lubab rollid: administrator, EMAL juhatuse liige, EMAL süsteemi administraator
+ * VÕI kasutaja, kes on mõne projekti field_projekt_juurdepaas väljas.
+ */
+class KandedAccessCheck {
+
+  /**
+   * Kontrollib kasutaja juurdepääsu kanded vaadetele.
+   */
+  public function access(AccountInterface $account) {
+    if ($account->hasPermission('bypass node access')) {
+      return AccessResult::allowed();
+    }
+
+    $allowed = [
+      'administrator',
+      'emal_juhatuse_liige',
+      'emal_susteemi_administraator',
+    ];
+    foreach ($allowed as $role) {
+      if ($account->hasRole($role)) {
+        return AccessResult::allowed();
+      }
+    }
+
+    $uid = (int) $account->id();
+    if ($uid > 0) {
+      $count = \Drupal::database()->query(
+        "SELECT COUNT(*) FROM {node__field_projekt_juurdepaas} WHERE field_projekt_juurdepaas_target_id = :uid",
+        [':uid' => $uid]
+      )->fetchField();
+      if ($count) {
+        return AccessResult::allowed();
+      }
+    }
+
+    return AccessResult::forbidden();
+  }
+
+}

+ 3 - 3
third/drupal/mustikas11/custom_modules/mustikas_export/src/Hook/FileDownloadHooks.php

@@ -12,13 +12,13 @@ class FileDownloadHooks {
   /**
    * Implements hook_file_download().
    *
-   * Keelab anonüümsele kasutajale filedepot failide allalaadimise
-   * (D7 analoogia: filedepot nõudis sisselogimist).
+   * Filedepot failide allalaadimine ainult access filedepot õigusega
+   * kasutajatele (D7 analogg: access filedepot permission).
    */
   #[Hook('file_download')]
   public function fileDownload($uri): int|array|null {
     if (str_starts_with($uri, 'private://filedepot/')) {
-      if (\Drupal::currentUser()->isAnonymous()) {
+      if (!\Drupal::currentUser()->hasPermission('access filedepot')) {
         return -1;
       }
     }

+ 77 - 0
third/drupal/mustikas11/custom_modules/mustikas_export/src/Plugin/views/access/KandedAccess.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace Drupal\mustikas_export\Plugin\views\access;
+
+use Drupal\Core\Session\AccountInterface;
+use Drupal\views\Plugin\views\access\AccessPluginBase;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Kanded vaadete juurdepääs (D7 analogg).
+ *
+ * Lubab rollid: administrator, EMAL juhatuse liige, EMAL süsteemi administraator
+ * VÕI kasutaja, kes on mõne projekti field_projekt_juurdepaas väljas.
+ *
+ * @ViewsAccess(
+ *   id = "mustikas_kanded_access",
+ *   title = @Translation("Kanded juurdepääs (rollid + projekti juurdepääs)"),
+ *   help = @Translation("Lubab admin/juhatus/süsteemi admin või projekti juurdepääsuga kasutajad.")
+ * )
+ */
+class KandedAccess extends AccessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access(AccountInterface $account) {
+    return $this->hasKandedAccess($account);
+  }
+
+  /**
+   * Kontrollib, kas kasutajal on kanded juurdepääs.
+   */
+  protected function hasKandedAccess(AccountInterface $account): bool {
+    if ($account->hasPermission('bypass node access')) {
+      return TRUE;
+    }
+
+    $allowed = [
+      'administrator',
+      'emal_juhatuse_liige',
+      'emal_susteemi_administraator',
+    ];
+    foreach ($allowed as $role) {
+      if ($account->hasRole($role)) {
+        return TRUE;
+      }
+    }
+
+    $uid = (int) $account->id();
+    if ($uid <= 0) {
+      return FALSE;
+    }
+    $count = \Drupal::database()->query(
+      "SELECT COUNT(*) FROM {node__field_projekt_juurdepaas} WHERE field_projekt_juurdepaas_target_id = :uid",
+      [':uid' => $uid]
+    )->fetchField();
+    return (bool) $count;
+  }
+
+  /**
+   * {@inheritdoc}
+   *
+   * Lisa route requirement, et route pole ilma access checksita
+   * (muidu Drupal keelab neutral-accessi korral).
+   */
+  public function alterRouteDefinition(Route $route) {
+    $route->setRequirement('_custom_access', 'mustikas_export.kanded_access:access');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCacheMaxAge() {
+    return 0;
+  }
+
+}

+ 40 - 0
third/drupal/mustikas11/grant_role_perms.php

@@ -0,0 +1,40 @@
+<?php
+use Drupal\user\Entity\Role;
+
+// D7 rollipõhiste õiguste ülekandmine D11-sse.
+// NB! access content / view files / comments on juba authenticated rollil.
+
+$role_perms = [
+  // EMAL liikmemaksud (D7: contact form + cookie)
+  'emal_liikmemaksud' => ['access site-wide contact form'],
+  // EMAL juhatuse liige (D7: access filedepot + contact form + cookie)
+  'emal_juhatuse_liige' => ['access filedepot', 'access site-wide contact form'],
+  // EMAL liige (D7: contact form + cookie)
+  'emal_liige' => ['access site-wide contact form'],
+  // EMAL projektid (D7: contact form + cookie)
+  'emal_projektid' => ['access site-wide contact form'],
+  // EMAL raamatupidamine (D7: contact form + cookie)
+  'emal_raamatupidamine' => ['access site-wide contact form'],
+  // filedepot (D7: access filedepot + administer filedepot)
+  'filedepot' => ['access filedepot', 'administer filedepot'],
+  // EMAL kutsekomisjon (D7: access filedepot)
+  'emal_kutsekomisjon' => ['access filedepot'],
+];
+
+foreach ($role_perms as $role_id => $perms) {
+  $role = Role::load($role_id);
+  if (!$role) {
+    echo "ROLE MISSING: $role_id\n";
+    continue;
+  }
+  foreach ($perms as $p) {
+    if (!$role->hasPermission($p)) {
+      $role->grantPermission($p);
+      echo "GRANT $role_id: $p\n";
+    } else {
+      echo "ALREADY $role_id: $p\n";
+    }
+  }
+  $role->save();
+}
+echo "done\n";

+ 45 - 0
third/drupal/mustikas11/migrate_projekt_juurdepaas.php

@@ -0,0 +1,45 @@
+<?php
+use Drupal\Core\Database\Database;
+use Drupal\node\Entity\Node;
+
+$src = Database::getConnection('default', 'migrate');
+$dst = Database::getConnection();
+
+// Migreeri field_projekt_juurdepaas (projekt -> kasutajad).
+// D7 tabel: field_data_field_projekt_juurdepaas (entity_id=projekt nid, target_id=user uid)
+// D11 tabel: node__field_projekt_juurdepaas
+
+$rows = $src->query(
+  "SELECT entity_id, field_projekt_juurdepaas_target_id, delta
+   FROM {field_data_field_projekt_juurdepaas}"
+);
+
+$count = 0;
+$by_node = [];
+foreach ($rows as $r) {
+  $nid = (int) $r->entity_id;
+  $uid = (int) $r->field_projekt_juurdepaas_target_id;
+
+  // Kontrolli, et node ja kasutaja eksisteerivad D11-s.
+  $node_exists = $dst->query('SELECT COUNT(*) FROM {node} WHERE nid = :nid', [':nid' => $nid])->fetchField();
+  $user_exists = $dst->query('SELECT COUNT(*) FROM {users_field_data} WHERE uid = :uid', [':uid' => $uid])->fetchField();
+  if (!$node_exists || !$user_exists) {
+    echo "SKIP nid=$nid uid=$uid (puudub)\n";
+    continue;
+  }
+  $by_node[$nid][] = $uid;
+}
+
+foreach ($by_node as $nid => $uids) {
+  $node = Node::load($nid);
+  if (!$node) {
+    echo "SKIP NODE $nid\n";
+    continue;
+  }
+  $node->set('field_projekt_juurdepaas', array_map(fn($u) => ['target_id' => $u], $uids));
+  $node->save();
+  $count++;
+  echo "SET nid=$nid users=" . implode(',', $uids) . "\n";
+}
+
+echo "done, nodes updated: $count\n";

+ 38 - 0
third/drupal/mustikas11/restrict_export.php

@@ -0,0 +1,38 @@
+<?php
+use Drupal\views\Views;
+
+// Liikmed vaate data_export display: piiritle rollidele administrator + emal_susteemi_administraator (D7: 3,6)
+$view = Views::getView('liikmed');
+if (!$view) {
+  echo "VIEW liikmed NOT FOUND\n";
+  exit;
+}
+
+$role_access = [
+  'type' => 'role',
+  'options' => ['role' => [
+    'administrator' => 'administrator',
+    'emal_susteemi_administraator' => 'emal_susteemi_administraator',
+  ]],
+];
+
+$storage = $view->storage;
+$displays = $storage->get('display');
+foreach (['data_export'] as $display_id) {
+  if (!isset($displays[$display_id])) {
+    echo "MISSING DISPLAY $display_id\n";
+    continue;
+  }
+  if (!isset($displays[$display_id]['display_options'])) {
+    $displays[$display_id]['display_options'] = [];
+  }
+  $displays[$display_id]['display_options']['access'] = $role_access;
+  if (!isset($displays[$display_id]['display_options']['defaults'])) {
+    $displays[$display_id]['display_options']['defaults'] = [];
+  }
+  $displays[$display_id]['display_options']['defaults']['access'] = FALSE;
+  echo "SET $display_id -> role (admin+sysadmin)\n";
+}
+$storage->set('display', $displays);
+$storage->save();
+echo "STORAGE SAVED\n";

+ 34 - 0
third/drupal/mustikas11/restrict_filedepot.php

@@ -0,0 +1,34 @@
+<?php
+use Drupal\views\Views;
+
+// dokumendid vaade: page_filedepot piiritle access filedepot õigusega.
+// page (docs) jääb access content (kõik autenditud, D7 docsview analogg).
+$view = Views::getView('dokumendid');
+if (!$view) {
+  echo "VIEW dokumendid NOT FOUND\n";
+  exit;
+}
+
+$perm_access = [
+  'type' => 'perm',
+  'options' => ['perm' => 'access filedepot'],
+];
+
+$storage = $view->storage;
+$displays = $storage->get('display');
+if (isset($displays['page_filedepot'])) {
+  if (!isset($displays['page_filedepot']['display_options'])) {
+    $displays['page_filedepot']['display_options'] = [];
+  }
+  $displays['page_filedepot']['display_options']['access'] = $perm_access;
+  if (!isset($displays['page_filedepot']['display_options']['defaults'])) {
+    $displays['page_filedepot']['display_options']['defaults'] = [];
+  }
+  $displays['page_filedepot']['display_options']['defaults']['access'] = FALSE;
+  echo "SET page_filedepot -> access filedepot\n";
+} else {
+  echo "MISSING page_filedepot\n";
+}
+$storage->set('display', $displays);
+$storage->save();
+echo "STORAGE SAVED\n";