$string['blockuserconfirmbutton'] = 'Block';
$string['blocknoncontacts'] = 'Prevent non-contacts from messaging me';
$string['cancelselection'] = 'Cancel message selection';
+$string['cantblockuser'] = 'You are unable to block {$a} because they have a role with permission to message all users';
$string['contactableprivacy'] = 'Accept messages from:';
$string['contactableprivacy_onlycontacts'] = 'My contacts only';
$string['contactableprivacy_coursemember'] = 'My contacts and anyone in my courses';
isblocked: null,
iscontact: null,
isdeleted: null,
- canmessage: null,
+ canmessage: null,
+ canmessageevenifblocked: null,
requirescontact: null,
contactrequests: []
};
*/
var renderConfirmBlockUser = function(header, body, footer, user) {
if (user) {
- return Str.get_string('blockuserconfirm', 'core_message', user.fullname)
- .then(function(string) {
- return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_BLOCK], string, '', true, false);
- });
+ if (user.canmessageevenifblocked) {
+ return Str.get_string('cantblockuser', 'core_message', user.fullname)
+ .then(function(string) {
+ return showConfirmDialogue(header, body, footer, [], string, '', true, false);
+ });
+ } else {
+ return Str.get_string('blockuserconfirm', 'core_message', user.fullname)
+ .then(function(string) {
+ return showConfirmDialogue(header, body, footer, [SELECTORS.ACTION_CONFIRM_BLOCK], string, '', true, false);
+ });
+ }
} else {
return hideConfirmDialogue(header, body, footer);
}
isblocked: member.isblocked,
iscontact: member.iscontact,
isdeleted: member.isdeleted,
- canmessage: member.canmessage,
+ canmessage: member.canmessage,
+ canmessageevenifblocked: member.canmessageevenifblocked,
requirescontact: member.requirescontact,
contactrequests: member.contactrequests || []
};
*
* @param int $recipientid The recipient user id.
* @param int $senderid The sender user id.
+ * @param bool $evenifblocked This lets the user know, that even if the recipient has blocked the user
+ * the user is still able to send a message.
* @return bool true if user is permitted, false otherwise.
*/
- public static function can_send_message(int $recipientid, int $senderid) : bool {
+ public static function can_send_message(int $recipientid, int $senderid, bool $evenifblocked = false) : bool {
$systemcontext = \context_system::instance();
if (!has_capability('moodle/site:sendmessage', $systemcontext, $senderid)) {
}
// Check if the recipient can be messaged by the sender.
- return self::can_contact_user($recipientid, $senderid);
+ return self::can_contact_user($recipientid, $senderid, $evenifblocked);
}
/**
*
* @param int $recipientid
* @param int $senderid
+ * @param bool $evenifblocked This lets the user know, that even if the recipient has blocked the user
+ * the user is still able to send a message.
* @return bool true if recipient hasn't blocked sender and sender can contact to recipient, false otherwise.
*/
- protected static function can_contact_user(int $recipientid, int $senderid) : bool {
+ protected static function can_contact_user(int $recipientid, int $senderid, bool $evenifblocked = false) : bool {
if (has_capability('moodle/site:messageanyuser', \context_system::instance(), $senderid) ||
$recipientid == $senderid) {
// The sender has the ability to contact any user across the entire site or themselves.
// The initial value of $cancontact is null to indicate that a value has not been determined.
$cancontact = null;
- if (self::is_blocked($recipientid, $senderid)) {
+ if (self::is_blocked($recipientid, $senderid) || $evenifblocked) {
// The recipient has specifically blocked this sender.
$cancontact = false;
}
$data->requirescontact = null;
$data->canmessage = null;
+ $data->canmessageevenifblocked = null;
if ($includeprivacyinfo) {
$privacysetting = api::get_user_privacy_messaging_preference($member->id);
$data->requirescontact = $privacysetting == api::MESSAGE_PRIVACY_ONLYCONTACTS;
+
+ // Here we check that if the sender wanted to block the recipient, the recipient would
+ // still be able to message them regardless.
+ $data->canmessageevenifblocked = api::can_send_message($referenceuserid, $member->id, true);
$data->canmessage = !$data->isdeleted && api::can_send_message($member->id, $referenceuserid);
}
throw new required_capability_exception($context, $capability, 'nopermissions', '');
}
+ // If the blocking is going to be useless then don't do it.
+ if (\core_message\api::can_send_message($userid, $blockeduserid, true)) {
+ return [];
+ }
+
if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
\core_message\api::block_user($params['userid'], $params['blockeduserid']);
}
'isblocked' => new external_value(PARAM_BOOL, 'If the user has been blocked'),
'iscontact' => new external_value(PARAM_BOOL, 'Is the user a contact?'),
'isdeleted' => new external_value(PARAM_BOOL, 'Is the user deleted?'),
+ 'canmessageevenifblocked' => new external_value(PARAM_BOOL,
+ 'If the user can still message even if they get blocked'),
'canmessage' => new external_value(PARAM_BOOL, 'If the user can be messaged'),
'requirescontact' => new external_value(PARAM_BOOL, 'If the user requires to be contacts'),
];
$this->assertTrue(\core_message\api::can_send_message($student2->id, $teacher1->id));
}
+ /**
+ * Tests the user when blocked will not be able to send messages if they are blocked.
+ */
+ public function test_can_send_message_even_if_blocked() {
+ $this->resetAfterTest();
+
+ $user1 = self::getDataGenerator()->create_user();
+ $user2 = self::getDataGenerator()->create_user();
+
+ $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id, true));
+ }
+
+ /**
+ * Tests the user will be able to send a message even if they are blocked as the user
+ * has the capability 'moodle/site:messageanyuser'.
+ */
+ public function test_can_send_message_even_if_blocked_with_message_any_user_cap() {
+ global $DB;
+
+ $this->resetAfterTest();
+
+ $user1 = self::getDataGenerator()->create_user();
+ $user2 = self::getDataGenerator()->create_user();
+
+ $authenticateduserrole = $DB->get_record('role', array('shortname' => 'user'));
+ assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduserrole->id, context_system::instance(), true);
+
+ $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id, true));
+ }
+
+ /**
+ * Tests the user will be able to send a message even if they are blocked as the user
+ * has the capability 'moodle/site:readallmessages'.
+ */
+ public function test_can_send_message_even_if_blocked_with_read_all_message_cap() {
+ global $DB;
+
+ $this->resetAfterTest();
+
+ $user1 = self::getDataGenerator()->create_user();
+ $user2 = self::getDataGenerator()->create_user();
+
+ $authenticateduserrole = $DB->get_record('role', array('shortname' => 'user'));
+ assign_capability('moodle/site:readallmessages', CAP_ALLOW, $authenticateduserrole->id, context_system::instance(), true);
+
+ $this->assertTrue(\core_message\api::can_send_message($user2->id, $user1->id, true));
+ }
+
+ /**
+ * Tests the user can not always send a message if they are blocked just because they share a course.
+ */
+ public function test_can_send_message_even_if_blocked_shared_course() {
+ $this->resetAfterTest();
+
+ // Create some users.
+ $user1 = self::getDataGenerator()->create_user();
+ $user2 = self::getDataGenerator()->create_user();
+
+ $course = self::getDataGenerator()->create_course();
+
+ $this->getDataGenerator()->enrol_user($user1->id, $course->id);
+ $this->getDataGenerator()->enrol_user($user2->id, $course->id);
+
+ $this->assertFalse(\core_message\api::can_send_message($user2->id, $user1->id, true));
+ }
+
+ /**
+ * Tests the user can always send a message even if they are blocked because they share a course and
+ * have the capability 'moodle/site:messageanyuser' at the course context.
+ */
+ public function test_can_send_message_even_if_blocked_shared_course_with_message_any_user_cap() {
+ global $DB;
+
+ $this->resetAfterTest();
+
+ $editingteacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
+
+ $teacher = self::getDataGenerator()->create_user();
+ $student = self::getDataGenerator()->create_user();
+
+ $course = self::getDataGenerator()->create_course();
+
+ $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $editingteacherrole->id);
+ $this->getDataGenerator()->enrol_user($student->id, $course->id);
+
+ assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $editingteacherrole->id,
+ context_course::instance($course->id), true);
+
+ // Check that the second user can no longer send the first user a message.
+ $this->assertTrue(\core_message\api::can_send_message($student->id, $teacher->id, true));
+ }
+
/**
* Tests the user can post a message.
*/
--- /dev/null
+@core @core_message @javascript
+Feature: To be able to block users that we are able to or to see a message if we can not
+ In order to attempt to block a user
+ As a user
+ I need to be able to block a user or to see a message if we can not
+
+ Background:
+ Given the following "courses" exist:
+ | fullname | shortname | category |
+ | Course 1 | C1 | 0 |
+ And the following "users" exist:
+ | username | firstname | lastname | email |
+ | teacher1 | Teacher | 1 | teacher1@emample.com |
+ | student1 | Student | 1 | student1@example.com |
+ | student2 | Student | 2 | student2@example.com |
+ And the following "course enrolments" exist:
+ | user | course | role |
+ | teacher1 | C1 | teacher |
+ | student1 | C1 | student |
+ | student2 | C1 | student |
+ And the following config values are set as admin:
+ | messaging | 1 |
+
+ Scenario: Block a user
+ Given I log in as "student1"
+ And I select "Student 2" user in messaging
+ And I open contact menu
+ And I click on "Block" "link" in the "[data-region='header-container']" "css_element"
+ And I should see "Are you sure you want to block Student 2?"
+ And I click on "Block" "button" in the "[data-region='confirm-dialogue']" "css_element"
+ And I should see "You have blocked this user."
+ And I log out
+ When I log in as "student2"
+ And I open messaging
+ And I select "Student 1" user in messaging
+ Then I should see "You are unable to message this user"
+
+ Scenario: Unable to block a user
+ Given I log in as "student1"
+ And I select "Teacher 1" user in messaging
+ And I open contact menu
+ When I click on "Block" "link" in the "[data-region='header-container']" "css_element"
+ Then I should see "You are unable to block Teacher 1"
$this->assertEquals(1, $DB->count_records('message_users_blocked'));
}
+ /**
+ * Test blocking a user.
+ */
+ public function test_block_user_when_ineffective() {
+ global $DB;
+
+ $this->resetAfterTest(true);
+
+ $user1 = self::getDataGenerator()->create_user();
+ $user2 = self::getDataGenerator()->create_user();
+
+ $this->setUser($user1);
+
+ $authenticateduser = $DB->get_record('role', array('shortname' => 'user'));
+ assign_capability('moodle/site:messageanyuser', CAP_ALLOW, $authenticateduser->id, context_system::instance(), true);
+
+ // Blocking a user.
+ $return = core_message_external::block_user($user1->id, $user2->id);
+ $return = external_api::clean_returnvalue(core_message_external::block_user_returns(), $return);
+ $this->assertEquals(array(), $return);
+
+ $this->assertEquals(0, $DB->count_records('message_users_blocked'));
+ }
+
/**
* Test blocking a user with messaging disabled.
*/