在 Drupal 中,我們可以透過「角色」與「權限」的設計為網站建構出一個安全的使用環境,當核心模組提供的權限設定不符合需求時,我們還可以透過 Drupal 提供豐富的 API 來完成,本篇文章來為大家介紹如何透過客製化模組來自訂選單權限。
客製化選單權限
假設我們使用一個 Drupal 建立了包含主網域與數個子網域的網站,在這樣的情境下,通常會需要做更細緻的權限控管,這次我們以限定子網域是「sub.example.org」且角色為「Content Editor」或「Site Administrator」才有權限進行選單管理。
首先,我們先建立一個客製化模組(這裡以 Drupal 7 為例)的 .info ,由於本次我們是透過 Domain 模組來管理網域,客製化程式也會使用到相關函式,因此相依性要記得設定。
name = MY_MODULE_NAME description = Limits menu management access based on roles and domain settings. core = 7.x package = Custom dependencies[] = domain
接著來撰寫允許網域的檢查函式,我們可以先建立一個網域的白名單,將目前的網域與其比對。
/** * Checks if the current domain is in the allowed domains list. * * @return bool * TRUE if the current domain is allowed, otherwise FALSE. */ function _MY_MODULE_NAME_allowed_domain() { $allowed_domains = array('sub.example.org'); $current_domain = domain_get_domain(); return in_array($current_domain['subdomain'], $allowed_domains); }
接下來我們會建立一個檢查權限的函式,在這個函式中,我們會檢查使用者是否符合權限授予的條件,包含網域與角色的檢查。
/** * Custom access callback. */ function _MY_MODULE_NAME_access_check($menu) { $account = user_load($GLOBALS['user']->uid); // Always return TRUE for user 1 (the super admin). if ($account->uid == 1) { return TRUE; } // Check for specific roles. if (array_intersect(array('Content Editor', 'Site Administrator'), $account->roles)) { if (_MY_MODULE_NAME_allowed_domain()) { // Check user access to the domain $domain = domain_get_domain(); $user_domain_access_list = domain_get_user_domains($account, FALSE); return isset($user_domain_access_list[$domain['domain_id']]); } } // Default to no access return FALSE; }
最後,我們會需要透過 Drupal 提供的 hook_menu_alter 來進行選單權限的客製化設定。首先我們可以將選單相關路徑先逐一列出,接著透過迴圈來改寫每個路徑的「access callback」,「access callback」的對應函式就是我們上面撰寫好的「_MY_MODULE_NAME_access_check」,這樣就完成了!
/** * Implements hook_menu_alter(). */ function MY_MODULE_NAME_menu_alter(&$items) { $restricted_paths = array( 'admin/structure/menu/manage/%menu', 'admin/structure/menu/manage/%menu/add', 'admin/structure/menu/item/%menu_link/edit', 'admin/structure/menu/item/%menu_link/reset', 'admin/structure/menu/item/%menu_link/delete', ); foreach ($restricted_paths as $path) { $items[$path]['access callback'] = '_MY_MODULE_NAME_access_check'; $items[$path]['access arguments'] = array(4); } }
同場加映
如果只是要單純將每一個選單的權限拆開來設定可以使用 Menu Admin per Menu 模組。
* 本文首張圖片由 Ideogram 生成