diff --git a/README.md b/README.md index 4b0304b..dbc1e24 100755 --- a/README.md +++ b/README.md @@ -41,38 +41,37 @@ INSTALLATION CONFIGURATION ------------- Enabling Permissions: -"View a new message instance for Private Message" & -"Create a new message instance for Private Message" for users needing to create -and view private messages. -To hide private messages from this view, -you must override view provided by Message module: -admin/structure/views/view/message/edit + * "View a new message instance for Private Message" & + "Create a new message instance for Private Message" for users needing to create + and view private messages. + * To hide private messages from this view, you must override view provided by + Message module: admin/structure/views/view/message/edit When enabled, the module will provide a new message type "Private Message" and a Message Private View. Message Create Limits: -Message creation limits can be managed per role on the module settings form. A -message create limit can be set per interval per role. Users with more than one -role get the maximum limit by calculating the lowest time per message over each -role. Users with the 'bypass private message access control' permission bypass -these limitations. + * Message creation limits can be managed per role on the module settings form. + A message create limit can be set per interval per role. Users with more than + one role get the maximum limit by calculating the lowest time per message over + each role. Users with the 'bypass private message access control' permission + bypass these limitations. HOW TO USE ---------- To Create messages: -Visit /admin/content/message/create/private-message and Save the message to send -or -Visit the "Messages" tab detailed below and find the "Create a new message" + * Visit /admin/content/message/create/private-message and Save the message to + send, or + * Visit the "Messages" tab detailed below and find the "Create a new message" local action. To View inbox and sent messages: -Visit your user page at /user and find the "Messages" tab which displays + * Visit your user page at /user and find the "Messages" tab which displays received messages (Inbox local task), the "Sent" local task under that tab which displays sent messages and the "Group" local task which displays group messages. - /user/USER_ID/messages/inbox - /user/USER_ID/messages/sent + * /user/USER_ID/messages/inbox + * /user/USER_ID/messages/sent SECURITY @@ -81,8 +80,8 @@ This module does not come with any security features out-of-the-box, but you can easily configure your own, using methods and modules of your choice. E.G: -Honeypot and timestamp methods: https://www.drupal.org/project/honeypot -CAPTCHA method: https://www.drupal.org/project/recaptcha + * Honeypot and timestamp methods: https://www.drupal.org/project/honeypot + * CAPTCHA method: https://www.drupal.org/project/recaptcha DEVELOPMENT AND TEST diff --git a/message_private.module b/message_private.module index d4a8bc3..06b1556 100755 --- a/message_private.module +++ b/message_private.module @@ -1,98 +1,63 @@ moduleExists('markdown') ? \Drupal\Component\Utility\Xss::filterAdmin(\Drupal::moduleHandler()->invoke('markdown', 'filter', ['process', 0, -1, $output])) : '
' . \Drupal\Component\Utility\Html::escape($output) . ''; } } -/** - * Implements hook_views_api(). - */ -function message_private_views_api() { - list($module, $api) = func_get_args(); - if ($module == 'views' && $api == 'views_default') { - return array('version' => '3.0'); - } - return array(); -} - -/** - * Implements hook_permission(). - */ -function message_private_permission() { - - // Build the permissions. - $permissions = array(); - - $permissions['bypass private message access control'] = array( - 'title' => t('Bypass message access control'), - 'description' => t('Grant to the user the permission to apply CRUD option on any private messages.'), - 'restrict access' => TRUE, - ); - - $permissions['administer message private'] = array( - 'title' => t('Administer message private'), - 'description' => t('Access the message private administration pages.'), - ); - - return $permissions; -} - /** * Access callback for Messages tab. * @@ -119,6 +84,7 @@ function message_private_access_callback($message) { function message_private_menu_alter(&$items) { // Override access callbacks. + // @todo: add appropriate callbacks to services refering to node.services.yml. $items['message/%message']['access callback'] = 'message_private_access_control'; $items['message/%message/view']['access callback'] = 'message_private_access_control'; $items['message/%message/edit']['access callback'] = 'message_private_access_control'; diff --git a/message_private.routing.yml b/message_private.routing.yml index f21c4f0..086caa6 100644 --- a/message_private.routing.yml +++ b/message_private.routing.yml @@ -26,6 +26,7 @@ message_private.create_message: title: 'Create Private Message' description: 'Create a new message Private Message instance' options: - parameters: - message_type: 'private-message' -#'access callback' => 'message_private_access_control' \ No newline at end of file + parameters: + message_type: 'private-message' + requirements: + _message_private_add_access: 'message:private_message' \ No newline at end of file diff --git a/message_private.services.yml b/message_private.services.yml new file mode 100644 index 0000000..9b06b0c --- /dev/null +++ b/message_private.services.yml @@ -0,0 +1,6 @@ +services: + access_check.message_private.add: + class: Drupal\message_private\Access\MessagePrivateAddAccessCheck + arguments: ['@entity.manager'] + tags: + - { name: access_check, applies_to: _message_private_add_access } \ No newline at end of file diff --git a/message_private.views.inc b/message_private.views.inc deleted file mode 100644 index adfa32c..0000000 --- a/message_private.views.inc +++ /dev/null @@ -1,285 +0,0 @@ -name = 'message_private'; - $view->description = 'Show private messages for users and groups.'; - $view->tag = 'Message'; - $view->base_table = 'message'; - $view->human_name = 'Message Private'; - $view->core = 7; - $view->api_version = '3.0'; - $view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */ - - /* Display: Defaults */ - $handler = $view->new_display('default', 'Defaults', 'default'); - $handler->display->display_options['title'] = 'User Messages'; - $handler->display->display_options['use_more_always'] = FALSE; - $handler->display->display_options['access']['type'] = 'role'; - $handler->display->display_options['access']['role'] = array( - 2 => '2', - ); - $handler->display->display_options['cache']['type'] = 'none'; - $handler->display->display_options['query']['type'] = 'views_query'; - $handler->display->display_options['query']['options']['query_comment'] = FALSE; - $handler->display->display_options['exposed_form']['type'] = 'basic'; - $handler->display->display_options['pager']['type'] = 'full'; - $handler->display->display_options['pager']['options']['items_per_page'] = '30'; - $handler->display->display_options['pager']['options']['offset'] = '0'; - $handler->display->display_options['pager']['options']['id'] = '0'; - $handler->display->display_options['style_plugin'] = 'table'; - $handler->display->display_options['style_options']['columns'] = array( - 'name' => 'name', - 'field_message_subject' => 'field_message_subject', - 'view' => 'view', - 'delete' => 'view', - 'timestamp' => 'timestamp', - ); - $handler->display->display_options['style_options']['default'] = '-1'; - $handler->display->display_options['style_options']['info'] = array( - 'name' => array( - 'sortable' => 1, - 'default_sort_order' => 'asc', - 'align' => '', - 'separator' => '', - 'empty_column' => 0, - ), - 'field_message_subject' => array( - 'sortable' => 0, - 'default_sort_order' => 'asc', - 'align' => '', - 'separator' => '', - 'empty_column' => 0, - ), - 'view' => array( - 'align' => '', - 'separator' => ' ', - 'empty_column' => 0, - ), - 'delete' => array( - 'align' => '', - 'separator' => '', - 'empty_column' => 0, - ), - 'timestamp' => array( - 'sortable' => 1, - 'default_sort_order' => 'asc', - 'align' => '', - 'separator' => '', - 'empty_column' => 0, - ), - ); - $handler->display->display_options['style_options']['sticky'] = TRUE; - /* Relationship: Message: User uid */ - $handler->display->display_options['relationships']['user']['id'] = 'user'; - $handler->display->display_options['relationships']['user']['table'] = 'message'; - $handler->display->display_options['relationships']['user']['field'] = 'user'; - /* Field: User: Name */ - $handler->display->display_options['fields']['name']['id'] = 'name'; - $handler->display->display_options['fields']['name']['table'] = 'users'; - $handler->display->display_options['fields']['name']['field'] = 'name'; - $handler->display->display_options['fields']['name']['relationship'] = 'user'; - $handler->display->display_options['fields']['name']['label'] = 'From User'; - /* Field: Message: Message ID */ - $handler->display->display_options['fields']['mid']['id'] = 'mid'; - $handler->display->display_options['fields']['mid']['table'] = 'message'; - $handler->display->display_options['fields']['mid']['field'] = 'mid'; - $handler->display->display_options['fields']['mid']['exclude'] = TRUE; - /* Field: Message: Subject */ - $handler->display->display_options['fields']['field_message_subject']['id'] = 'field_message_subject'; - $handler->display->display_options['fields']['field_message_subject']['table'] = 'field_data_field_message_subject'; - $handler->display->display_options['fields']['field_message_subject']['field'] = 'field_message_subject'; - $handler->display->display_options['fields']['field_message_subject']['alter']['make_link'] = TRUE; - $handler->display->display_options['fields']['field_message_subject']['alter']['path'] = 'message/[mid]'; - /* Field: Message: View message */ - $handler->display->display_options['fields']['view']['id'] = 'view'; - $handler->display->display_options['fields']['view']['table'] = 'message'; - $handler->display->display_options['fields']['view']['field'] = 'view'; - $handler->display->display_options['fields']['view']['label'] = 'Operations'; - $handler->display->display_options['fields']['view']['element_label_colon'] = FALSE; - /* Field: Message: Delete message */ - $handler->display->display_options['fields']['delete']['id'] = 'delete'; - $handler->display->display_options['fields']['delete']['table'] = 'message'; - $handler->display->display_options['fields']['delete']['field'] = 'delete'; - $handler->display->display_options['fields']['delete']['label'] = ''; - $handler->display->display_options['fields']['delete']['element_label_colon'] = FALSE; - /* Field: Message: Timestamp */ - $handler->display->display_options['fields']['timestamp']['id'] = 'timestamp'; - $handler->display->display_options['fields']['timestamp']['table'] = 'message'; - $handler->display->display_options['fields']['timestamp']['field'] = 'timestamp'; - $handler->display->display_options['fields']['timestamp']['date_format'] = 'short'; - $handler->display->display_options['fields']['timestamp']['second_date_format'] = 'long'; - /* Sort criterion: Message: Timestamp */ - $handler->display->display_options['sorts']['timestamp']['id'] = 'timestamp'; - $handler->display->display_options['sorts']['timestamp']['table'] = 'message'; - $handler->display->display_options['sorts']['timestamp']['field'] = 'timestamp'; - $handler->display->display_options['sorts']['timestamp']['order'] = 'DESC'; - /* Contextual filter: User ID */ - $handler->display->display_options['arguments']['user']['id'] = 'user'; - $handler->display->display_options['arguments']['user']['table'] = 'message'; - $handler->display->display_options['arguments']['user']['field'] = 'user'; - $handler->display->display_options['arguments']['user']['ui_name'] = 'User ID'; - $handler->display->display_options['arguments']['user']['default_action'] = 'default'; - $handler->display->display_options['arguments']['user']['default_argument_type'] = 'current_user'; - $handler->display->display_options['arguments']['user']['summary']['number_of_records'] = '0'; - $handler->display->display_options['arguments']['user']['summary']['format'] = 'default_summary'; - $handler->display->display_options['arguments']['user']['summary_options']['items_per_page'] = '25'; - $handler->display->display_options['arguments']['user']['break_phrase'] = TRUE; - /* Filter criterion: Message: Type */ - $handler->display->display_options['filters']['type_1']['id'] = 'type_1'; - $handler->display->display_options['filters']['type_1']['table'] = 'message'; - $handler->display->display_options['filters']['type_1']['field'] = 'type'; - $handler->display->display_options['filters']['type_1']['value'] = array( - 'private_message' => 'private_message', - ); - - /* Display: Messages */ - $handler = $view->new_display('page', 'Messages', 'page_1'); - $handler->display->display_options['defaults']['title'] = FALSE; - $handler->display->display_options['title'] = 'Messages'; - $handler->display->display_options['display_description'] = 'Private messages received by the user.'; - $handler->display->display_options['defaults']['relationships'] = FALSE; - /* Relationship: Message: User uid */ - $handler->display->display_options['relationships']['user']['id'] = 'user'; - $handler->display->display_options['relationships']['user']['table'] = 'message'; - $handler->display->display_options['relationships']['user']['field'] = 'user'; - $handler->display->display_options['defaults']['arguments'] = FALSE; - /* Contextual filter: Message: To Users (field_message_user_ref) */ - $handler->display->display_options['arguments']['field_message_user_ref_target_id']['id'] = 'field_message_user_ref_target_id'; - $handler->display->display_options['arguments']['field_message_user_ref_target_id']['table'] = 'field_data_field_message_user_ref'; - $handler->display->display_options['arguments']['field_message_user_ref_target_id']['field'] = 'field_message_user_ref_target_id'; - $handler->display->display_options['arguments']['field_message_user_ref_target_id']['default_action'] = 'default'; - $handler->display->display_options['arguments']['field_message_user_ref_target_id']['default_argument_type'] = 'current_user'; - $handler->display->display_options['arguments']['field_message_user_ref_target_id']['summary']['number_of_records'] = '0'; - $handler->display->display_options['arguments']['field_message_user_ref_target_id']['summary']['format'] = 'default_summary'; - $handler->display->display_options['arguments']['field_message_user_ref_target_id']['summary_options']['items_per_page'] = '25'; - $handler->display->display_options['path'] = 'user/%/messages'; - $handler->display->display_options['menu']['type'] = 'tab'; - $handler->display->display_options['menu']['title'] = 'Messages'; - $handler->display->display_options['menu']['weight'] = '100'; - $handler->display->display_options['menu']['context'] = 1; - $handler->display->display_options['menu']['context_only_inline'] = 0; - - /* Display: Sent Messages */ - $handler = $view->new_display('page', 'Sent Messages', 'page_2'); - $handler->display->display_options['defaults']['title'] = FALSE; - $handler->display->display_options['title'] = 'Sent'; - $handler->display->display_options['display_description'] = 'Private messages sent by the user.'; - $handler->display->display_options['defaults']['style_plugin'] = FALSE; - $handler->display->display_options['style_plugin'] = 'table'; - $handler->display->display_options['style_options']['columns'] = array( - 'field_message_user_ref' => 'field_message_user_ref', - 'field_message_group_ref' => 'field_message_user_ref', - 'field_message_subject' => 'field_message_subject', - 'view' => 'view', - 'delete' => 'view', - 'timestamp' => 'timestamp', - ); - $handler->display->display_options['style_options']['default'] = '-1'; - $handler->display->display_options['style_options']['info'] = array( - 'field_message_user_ref' => array( - 'align' => '', - 'separator' => ', ', - 'empty_column' => 0, - ), - 'field_message_group_ref' => array( - 'align' => '', - 'separator' => '', - 'empty_column' => 0, - ), - 'field_message_subject' => array( - 'sortable' => 0, - 'default_sort_order' => 'asc', - 'align' => '', - 'separator' => '', - 'empty_column' => 0, - ), - 'view' => array( - 'align' => '', - 'separator' => ' ', - 'empty_column' => 0, - ), - 'delete' => array( - 'align' => '', - 'separator' => '', - 'empty_column' => 0, - ), - 'timestamp' => array( - 'sortable' => 1, - 'default_sort_order' => 'asc', - 'align' => '', - 'separator' => '', - 'empty_column' => 0, - ), - ); - $handler->display->display_options['style_options']['sticky'] = TRUE; - $handler->display->display_options['defaults']['style_options'] = FALSE; - $handler->display->display_options['defaults']['row_plugin'] = FALSE; - $handler->display->display_options['defaults']['row_options'] = FALSE; - $handler->display->display_options['defaults']['fields'] = FALSE; - /* Field: Message: To Users */ - $handler->display->display_options['fields']['field_message_user_ref']['id'] = 'field_message_user_ref'; - $handler->display->display_options['fields']['field_message_user_ref']['table'] = 'field_data_field_message_user_ref'; - $handler->display->display_options['fields']['field_message_user_ref']['field'] = 'field_message_user_ref'; - $handler->display->display_options['fields']['field_message_user_ref']['label'] = 'To Users / Groups'; - $handler->display->display_options['fields']['field_message_user_ref']['settings'] = array( - 'link' => 1, - ); - $handler->display->display_options['fields']['field_message_user_ref']['delta_offset'] = '0'; - /* Field: Message: Message ID */ - $handler->display->display_options['fields']['mid']['id'] = 'mid'; - $handler->display->display_options['fields']['mid']['table'] = 'message'; - $handler->display->display_options['fields']['mid']['field'] = 'mid'; - $handler->display->display_options['fields']['mid']['exclude'] = TRUE; - /* Field: Message: Subject */ - $handler->display->display_options['fields']['field_message_subject']['id'] = 'field_message_subject'; - $handler->display->display_options['fields']['field_message_subject']['table'] = 'field_data_field_message_subject'; - $handler->display->display_options['fields']['field_message_subject']['field'] = 'field_message_subject'; - $handler->display->display_options['fields']['field_message_subject']['alter']['make_link'] = TRUE; - $handler->display->display_options['fields']['field_message_subject']['alter']['path'] = 'message/[mid]'; - /* Field: Message: View message */ - $handler->display->display_options['fields']['view']['id'] = 'view'; - $handler->display->display_options['fields']['view']['table'] = 'message'; - $handler->display->display_options['fields']['view']['field'] = 'view'; - $handler->display->display_options['fields']['view']['label'] = 'Operations'; - $handler->display->display_options['fields']['view']['element_label_colon'] = FALSE; - /* Field: Message: Delete message */ - $handler->display->display_options['fields']['delete']['id'] = 'delete'; - $handler->display->display_options['fields']['delete']['table'] = 'message'; - $handler->display->display_options['fields']['delete']['field'] = 'delete'; - $handler->display->display_options['fields']['delete']['label'] = ''; - $handler->display->display_options['fields']['delete']['element_label_colon'] = FALSE; - /* Field: Message: Timestamp */ - $handler->display->display_options['fields']['timestamp']['id'] = 'timestamp'; - $handler->display->display_options['fields']['timestamp']['table'] = 'message'; - $handler->display->display_options['fields']['timestamp']['field'] = 'timestamp'; - $handler->display->display_options['fields']['timestamp']['date_format'] = 'short'; - $handler->display->display_options['fields']['timestamp']['second_date_format'] = 'long'; - /* Field: Message: To Groups */ - $handler->display->display_options['fields']['field_message_group_ref']['id'] = 'field_message_group_ref'; - $handler->display->display_options['fields']['field_message_group_ref']['table'] = 'field_data_field_message_group_ref'; - $handler->display->display_options['fields']['field_message_group_ref']['field'] = 'field_message_group_ref'; - $handler->display->display_options['fields']['field_message_group_ref']['settings'] = array( - 'link' => 1, - ); - $handler->display->display_options['fields']['field_message_group_ref']['delta_offset'] = '0'; - $handler->display->display_options['path'] = 'user/%/messages/sent'; - $handler->display->display_options['menu']['type'] = 'tab'; - $handler->display->display_options['menu']['title'] = 'Sent'; - $handler->display->display_options['menu']['weight'] = '11'; - $handler->display->display_options['menu']['context'] = 1; - $handler->display->display_options['menu']['context_only_inline'] = 0; - - $export['message_private'] = $view; - - return $export; -} diff --git a/src/Access/MessagePrivateAddAccessCheck.php b/src/Access/MessagePrivateAddAccessCheck.php new file mode 100644 index 0000000..788895e --- /dev/null +++ b/src/Access/MessagePrivateAddAccessCheck.php @@ -0,0 +1,73 @@ +entityManager = $entity_manager; + } + + /** + * Checks access to the message add page for the message type. + * + * @param \Drupal\Core\Session\AccountInterface $account + * The currently logged in account. + * @param \Drupal\message\MessageTypeInterface $message_type + * (optional) The node type. If not specified, access is allowed if there + * exists at least one node type for which the user may create a node. + * + * @return string + * A \Drupal\Core\Access\AccessInterface constant value. + */ + public function access(AccountInterface $account, MessageTypeInterface $message_type = NULL) { + $access_control_handler = $this->entityManager->getAccessControlHandler('message'); + // If checking whether a node of a particular type may be created. + if ($account->hasPermission('administer message private') + || $account->hasPermission('bypass private message access control')) { + return AccessResult::allowed()->cachePerPermissions(); + } + if ($message_type) { + return $access_control_handler->createAccess($message_type->id(), $account, [], TRUE); + } + // If checking whether a node of any type may be created. + foreach ($this->entityManager->getStorage('message_type')->loadMultiple() as $message_type) { + if (($access = $access_control_handler->createAccess($message_type->id(), $account, [], TRUE)) && $access->isAllowed()) { + return $access; + } + } + + // No opinion. + return AccessResult::neutral(); + } + +}