mirror of
https://github.com/discourse/discourse.git
synced 2025-05-25 00:32:52 +08:00
FEATURE: Allow users to disable new PMs.
https://meta.discourse.org/t/is-it-possible-to-disable-private-messaging-for-a-specific-user/46391
This commit is contained in:
@ -13,7 +13,8 @@ export default Ember.Controller.extend(PreferencesTabController, {
|
|||||||
'dynamic_favicon',
|
'dynamic_favicon',
|
||||||
'enable_quoting',
|
'enable_quoting',
|
||||||
'disable_jump_reply',
|
'disable_jump_reply',
|
||||||
'automatically_unpin_topics'
|
'automatically_unpin_topics',
|
||||||
|
'allow_private_messages',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (makeDefault) {
|
if (makeDefault) {
|
||||||
|
@ -247,7 +247,8 @@ const User = RestModel.extend({
|
|||||||
'notification_level_when_replying',
|
'notification_level_when_replying',
|
||||||
'like_notification_frequency',
|
'like_notification_frequency',
|
||||||
'include_tl0_in_digests',
|
'include_tl0_in_digests',
|
||||||
'theme_key'
|
'theme_key',
|
||||||
|
'allow_private_messages',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (fields) {
|
if (fields) {
|
||||||
|
@ -10,6 +10,16 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="control-group private-messages">
|
||||||
|
<label class="control-label">{{i18n 'user.private_messages'}}</label>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
{{preference-checkbox
|
||||||
|
labelKey="user.allow_private_messages"
|
||||||
|
checked=model.user_option.allow_private_messages}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{#if siteSettings.allow_user_locale}}
|
{{#if siteSettings.allow_user_locale}}
|
||||||
<div class="control-group pref-locale">
|
<div class="control-group pref-locale">
|
||||||
<label class="control-label">{{i18n 'user.locale.title'}}</label>
|
<label class="control-label">{{i18n 'user.locale.title'}}</label>
|
||||||
|
@ -59,11 +59,6 @@ class UserOption < ActiveRecord::Base
|
|||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_tracked_topics
|
|
||||||
return unless saved_change_to_auto_track_topics_after_msecs?
|
|
||||||
TrackedTopicsUpdater.new(id, auto_track_topics_after_msecs).call
|
|
||||||
end
|
|
||||||
|
|
||||||
def redirected_to_top_yet?
|
def redirected_to_top_yet?
|
||||||
last_redirected_to_top_at.present?
|
last_redirected_to_top_at.present?
|
||||||
end
|
end
|
||||||
@ -133,6 +128,13 @@ class UserOption < ActiveRecord::Base
|
|||||||
times.max
|
times.max
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def update_tracked_topics
|
||||||
|
return unless saved_change_to_auto_track_topics_after_msecs?
|
||||||
|
TrackedTopicsUpdater.new(id, auto_track_topics_after_msecs).call
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# == Schema Information
|
# == Schema Information
|
||||||
@ -162,6 +164,7 @@ end
|
|||||||
# notification_level_when_replying :integer
|
# notification_level_when_replying :integer
|
||||||
# theme_key :string
|
# theme_key :string
|
||||||
# theme_key_seq :integer default(0), not null
|
# theme_key_seq :integer default(0), not null
|
||||||
|
# allow_private_messages :boolean default(TRUE), not null
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
@ -20,7 +20,8 @@ class UserOptionSerializer < ApplicationSerializer
|
|||||||
:like_notification_frequency,
|
:like_notification_frequency,
|
||||||
:include_tl0_in_digests,
|
:include_tl0_in_digests,
|
||||||
:theme_key,
|
:theme_key,
|
||||||
:theme_key_seq
|
:theme_key_seq,
|
||||||
|
:allow_private_messages,
|
||||||
|
|
||||||
def auto_track_topics_after_msecs
|
def auto_track_topics_after_msecs
|
||||||
object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
|
object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
|
||||||
|
@ -34,7 +34,8 @@ class UserUpdater
|
|||||||
:email_in_reply_to,
|
:email_in_reply_to,
|
||||||
:like_notification_frequency,
|
:like_notification_frequency,
|
||||||
:include_tl0_in_digests,
|
:include_tl0_in_digests,
|
||||||
:theme_key
|
:theme_key,
|
||||||
|
:allow_private_messages,
|
||||||
]
|
]
|
||||||
|
|
||||||
def initialize(actor, user)
|
def initialize(actor, user)
|
||||||
|
@ -595,6 +595,7 @@ en:
|
|||||||
disable_jump_reply: "Don't jump to my post after I reply"
|
disable_jump_reply: "Don't jump to my post after I reply"
|
||||||
dynamic_favicon: "Show new / updated topic count on browser icon"
|
dynamic_favicon: "Show new / updated topic count on browser icon"
|
||||||
theme_default_on_all_devices: "Make this my default theme on all my devices"
|
theme_default_on_all_devices: "Make this my default theme on all my devices"
|
||||||
|
allow_private_messages: "Allow other users to send me private messages"
|
||||||
external_links_in_new_tab: "Open all external links in a new tab"
|
external_links_in_new_tab: "Open all external links in a new tab"
|
||||||
enable_quoting: "Enable quote reply for highlighted text"
|
enable_quoting: "Enable quote reply for highlighted text"
|
||||||
change: "change"
|
change: "change"
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
class AddAllowPrivateMessagesToUserOptions < ActiveRecord::Migration[5.1]
|
||||||
|
def change
|
||||||
|
add_column :user_options, :allow_private_messages, :boolean, default: true, null: false
|
||||||
|
end
|
||||||
|
end
|
@ -286,17 +286,22 @@ class Guardian
|
|||||||
end
|
end
|
||||||
|
|
||||||
def can_send_private_message?(target)
|
def can_send_private_message?(target)
|
||||||
(target.is_a?(Group) || target.is_a?(User)) &&
|
is_user = target.is_a?(User)
|
||||||
|
is_group = target.is_a?(Group)
|
||||||
|
|
||||||
|
(is_group || is_user) &&
|
||||||
# User is authenticated
|
# User is authenticated
|
||||||
authenticated? &&
|
authenticated? &&
|
||||||
# Have to be a basic level at least, or are contacting moderators
|
# Have to be a basic level at least, or are contacting moderators
|
||||||
(@user.has_trust_level?(SiteSetting.min_trust_to_send_messages) ||
|
(@user.has_trust_level?(SiteSetting.min_trust_to_send_messages) ||
|
||||||
(target.is_a?(User) && target.moderator?) ||
|
(target.is_a?(User) && target.moderator?) ||
|
||||||
(target.name == Group[:moderators].name)) &&
|
(target.name == Group[:moderators].name)) &&
|
||||||
|
# User disabled private message
|
||||||
|
(is_staff? || is_group || target.user_option.allow_private_messages) &&
|
||||||
# PMs are enabled
|
# PMs are enabled
|
||||||
(is_staff? || SiteSetting.enable_private_messages) &&
|
(is_staff? || SiteSetting.enable_private_messages) &&
|
||||||
# Can't send PMs to suspended users
|
# Can't send PMs to suspended users
|
||||||
(is_staff? || target.is_a?(Group) || !target.suspended?) &&
|
(is_staff? || is_group || !target.suspended?) &&
|
||||||
# Blocked users can only send PM to staff
|
# Blocked users can only send PM to staff
|
||||||
(!is_blocked? || target.staff?)
|
(!is_blocked? || target.staff?)
|
||||||
end
|
end
|
||||||
|
@ -109,10 +109,20 @@ class PostCreator
|
|||||||
# Make sure none of the users have muted the creator
|
# Make sure none of the users have muted the creator
|
||||||
users = User.where(username: names).pluck(:id, :username).to_h
|
users = User.where(username: names).pluck(:id, :username).to_h
|
||||||
|
|
||||||
MutedUser.where(user_id: users.keys, muted_user_id: @user.id).pluck(:user_id).each do |m|
|
User
|
||||||
|
.joins("LEFT JOIN user_options ON user_options.user_id = users.id")
|
||||||
|
.joins("LEFT JOIN muted_users ON muted_users.muted_user_id = #{@user.id.to_i}")
|
||||||
|
.where("user_options.user_id IS NOT NULL")
|
||||||
|
.where("
|
||||||
|
(user_options.user_id IN (:user_ids) AND NOT user_options.allow_private_messages) OR
|
||||||
|
muted_users.user_id IN (:user_ids)
|
||||||
|
", user_ids: users.keys)
|
||||||
|
.pluck(:id).each do |m|
|
||||||
|
|
||||||
errors[:base] << I18n.t(:not_accepting_pms, username: users[m])
|
errors[:base] << I18n.t(:not_accepting_pms, username: users[m])
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return false if errors[:base].present?
|
||||||
end
|
end
|
||||||
|
|
||||||
if new_topic?
|
if new_topic?
|
||||||
|
@ -190,7 +190,7 @@ class TopicCreator
|
|||||||
names = usernames.split(',').flatten
|
names = usernames.split(',').flatten
|
||||||
len = 0
|
len = 0
|
||||||
|
|
||||||
User.where(username: names).each do |user|
|
User.includes(:user_option).where(username: names).find_each do |user|
|
||||||
check_can_send_permission!(topic, user)
|
check_can_send_permission!(topic, user)
|
||||||
@added_users << user
|
@added_users << user
|
||||||
topic.topic_allowed_users.build(user_id: user.id)
|
topic.topic_allowed_users.build(user_id: user.id)
|
||||||
|
@ -233,6 +233,27 @@ describe Guardian do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'target user has private message disabled' do
|
||||||
|
before do
|
||||||
|
another_user.user_option.update!(allow_private_messages: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for a normal user' do
|
||||||
|
it 'should return false' do
|
||||||
|
expect(Guardian.new(user).can_send_private_message?(another_user)).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'for a staff user' do
|
||||||
|
it 'should return true' do
|
||||||
|
[admin, moderator].each do |staff_user|
|
||||||
|
expect(Guardian.new(staff_user).can_send_private_message?(another_user))
|
||||||
|
.to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'can_reply_as_new_topic' do
|
describe 'can_reply_as_new_topic' do
|
||||||
|
@ -954,6 +954,30 @@ describe PostCreator do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'private message to a user that has disabled private messages' do
|
||||||
|
let(:another_user) { Fabricate(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
another_user.user_option.update!(allow_private_messages: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should not be valid' do
|
||||||
|
post_creator = PostCreator.new(
|
||||||
|
user,
|
||||||
|
title: 'this message is to someone who muted me!',
|
||||||
|
raw: "you will have to see this even if you muted me!",
|
||||||
|
archetype: Archetype.private_message,
|
||||||
|
target_usernames: "#{another_user.username}"
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(post_creator).to_not be_valid
|
||||||
|
|
||||||
|
expect(post_creator.errors.full_messages).to include(I18n.t(
|
||||||
|
"not_accepting_pms", username: another_user.username
|
||||||
|
))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "private message to a muted user" do
|
context "private message to a muted user" do
|
||||||
let(:muted_me) { Fabricate(:evil_trout) }
|
let(:muted_me) { Fabricate(:evil_trout) }
|
||||||
|
|
||||||
|
@ -76,8 +76,9 @@ describe UserUpdater do
|
|||||||
notification_level_when_replying: 3,
|
notification_level_when_replying: 3,
|
||||||
email_in_reply_to: false,
|
email_in_reply_to: false,
|
||||||
date_of_birth: date_of_birth,
|
date_of_birth: date_of_birth,
|
||||||
theme_key: theme.key
|
theme_key: theme.key,
|
||||||
)
|
allow_private_messages: false)
|
||||||
|
|
||||||
expect(val).to be_truthy
|
expect(val).to be_truthy
|
||||||
|
|
||||||
user.reload
|
user.reload
|
||||||
@ -92,6 +93,7 @@ describe UserUpdater do
|
|||||||
expect(user.user_option.email_in_reply_to).to eq false
|
expect(user.user_option.email_in_reply_to).to eq false
|
||||||
expect(user.user_option.theme_key).to eq theme.key
|
expect(user.user_option.theme_key).to eq theme.key
|
||||||
expect(user.user_option.theme_key_seq).to eq(seq + 1)
|
expect(user.user_option.theme_key_seq).to eq(seq + 1)
|
||||||
|
expect(user.user_option.allow_private_messages).to eq(false)
|
||||||
expect(user.date_of_birth).to eq(date_of_birth.to_date)
|
expect(user.date_of_birth).to eq(date_of_birth.to_date)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user