mirror of
https://github.com/discourse/discourse.git
synced 2025-04-09 20:00:49 +08:00
FEATURE: Allow user to leave a PM.
This commit is contained in:
parent
79de10b212
commit
25c25ae423
@ -231,7 +231,11 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
removeAllowedUser(user) {
|
removeAllowedUser(user) {
|
||||||
return this.get('model.details').removeAllowedUser(user);
|
return this.get('model.details').removeAllowedUser(user).then(() => {
|
||||||
|
if (this.currentUser.id === user.id) {
|
||||||
|
this.transitionToRoute("userPrivateMessages", user);
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
removeAllowedGroup(group) {
|
removeAllowedGroup(group) {
|
||||||
|
@ -127,6 +127,7 @@ export default function transformPost(currentUser, site, post, prevPost, nextPos
|
|||||||
postAtts.allowedGroups = details.allowed_groups;
|
postAtts.allowedGroups = details.allowed_groups;
|
||||||
postAtts.allowedUsers = details.allowed_users;
|
postAtts.allowedUsers = details.allowed_users;
|
||||||
postAtts.canRemoveAllowedUsers = details.can_remove_allowed_users;
|
postAtts.canRemoveAllowedUsers = details.can_remove_allowed_users;
|
||||||
|
postAtts.canRemoveSelfId = details.can_remove_self_id;
|
||||||
postAtts.canInvite = details.can_invite_to;
|
postAtts.canInvite = details.can_invite_to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ const icons = {
|
|||||||
'split_topic': 'sign-out',
|
'split_topic': 'sign-out',
|
||||||
'invited_user': 'plus-circle',
|
'invited_user': 'plus-circle',
|
||||||
'invited_group': 'plus-circle',
|
'invited_group': 'plus-circle',
|
||||||
|
'user_left': 'minus-circle',
|
||||||
'removed_user': 'minus-circle',
|
'removed_user': 'minus-circle',
|
||||||
'removed_group': 'minus-circle',
|
'removed_group': 'minus-circle',
|
||||||
'public_topic': 'comment',
|
'public_topic': 'comment',
|
||||||
|
@ -36,8 +36,12 @@ createWidget('pm-remove-link', {
|
|||||||
template: hbs`{{d-icon "times"}}`,
|
template: hbs`{{d-icon "times"}}`,
|
||||||
|
|
||||||
click() {
|
click() {
|
||||||
bootbox.confirm(I18n.t("private_message_info.remove_allowed_user", {name: this.attrs.username}), (confirmed) => {
|
const messageKey = this.attrs.isCurrentUser ? 'leave_message' : 'remove_allowed_user';
|
||||||
if (confirmed) { this.sendWidgetAction('removeAllowedUser', this.attrs); }
|
|
||||||
|
bootbox.confirm(I18n.t(`private_message_info.${messageKey}`, { name: this.attrs.user.username }), confirmed => {
|
||||||
|
if (confirmed) {
|
||||||
|
this.sendWidgetAction('removeAllowedUser', this.attrs.user);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -49,11 +53,12 @@ createWidget('pm-map-user', {
|
|||||||
const user = attrs.user;
|
const user = attrs.user;
|
||||||
const avatar = avatarFor('small', { template: user.avatar_template, username: user.username });
|
const avatar = avatarFor('small', { template: user.avatar_template, username: user.username });
|
||||||
const link = h('a', { attributes: { href: user.get('path') } }, [ avatar, ' ', user.username ]);
|
const link = h('a', { attributes: { href: user.get('path') } }, [ avatar, ' ', user.username ]);
|
||||||
|
|
||||||
const result = [link];
|
const result = [link];
|
||||||
if (attrs.canRemoveAllowedUsers) {
|
const isCurrentUser = attrs.canRemoveSelfId === user.get('id');
|
||||||
|
|
||||||
|
if (attrs.canRemoveAllowedUsers || isCurrentUser) {
|
||||||
result.push(' ');
|
result.push(' ');
|
||||||
result.push(this.attach('pm-remove-link', user));
|
result.push(this.attach('pm-remove-link', { user, isCurrentUser } ));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -67,12 +72,23 @@ export default createWidget('private-message-map', {
|
|||||||
const participants = [];
|
const participants = [];
|
||||||
|
|
||||||
if (attrs.allowedGroups.length) {
|
if (attrs.allowedGroups.length) {
|
||||||
participants.push(attrs.allowedGroups.map(ag => this.attach('pm-map-user-group', {group: ag, canRemoveAllowedUsers: attrs.canRemoveAllowedUsers})));
|
participants.push(attrs.allowedGroups.map(ag => {
|
||||||
|
this.attach('pm-map-user-group', {
|
||||||
|
group: ag,
|
||||||
|
canRemoveAllowedUsers: attrs.canRemoveAllowedUsers
|
||||||
|
});
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attrs.allowedUsers.length) {
|
const allowedUsersLength = attrs.allowedUsers.length;
|
||||||
|
|
||||||
|
if (allowedUsersLength) {
|
||||||
participants.push(attrs.allowedUsers.map(au => {
|
participants.push(attrs.allowedUsers.map(au => {
|
||||||
return this.attach('pm-map-user', { user: au, canRemoveAllowedUsers: attrs.canRemoveAllowedUsers });
|
return this.attach('pm-map-user', {
|
||||||
|
user: au,
|
||||||
|
canRemoveAllowedUsers: attrs.canRemoveAllowedUsers,
|
||||||
|
canRemoveSelfId: attrs.canRemoveSelfId
|
||||||
|
});
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,9 +439,10 @@ class TopicsController < ApplicationController
|
|||||||
def remove_allowed_user
|
def remove_allowed_user
|
||||||
params.require(:username)
|
params.require(:username)
|
||||||
topic = Topic.find_by(id: params[:topic_id])
|
topic = Topic.find_by(id: params[:topic_id])
|
||||||
guardian.ensure_can_remove_allowed_users!(topic)
|
user = User.find_by(username: params[:username])
|
||||||
|
guardian.ensure_can_remove_allowed_users!(topic, user)
|
||||||
|
|
||||||
if topic.remove_allowed_user(current_user, params[:username])
|
if topic.remove_allowed_user(current_user, user)
|
||||||
render json: success_json
|
render json: success_json
|
||||||
else
|
else
|
||||||
render json: failed_json, status: 422
|
render json: failed_json, status: 422
|
||||||
|
@ -709,14 +709,21 @@ SQL
|
|||||||
end
|
end
|
||||||
|
|
||||||
def remove_allowed_user(removed_by, username)
|
def remove_allowed_user(removed_by, username)
|
||||||
if user = User.find_by(username: username)
|
user = username.is_a?(User) ? username : User.find_by(username: username)
|
||||||
|
|
||||||
|
if user
|
||||||
topic_user = topic_allowed_users.find_by(user_id: user.id)
|
topic_user = topic_allowed_users.find_by(user_id: user.id)
|
||||||
|
|
||||||
if topic_user
|
if topic_user
|
||||||
topic_user.destroy
|
topic_user.destroy
|
||||||
# we can not remove ourselves cause then we will end up adding
|
|
||||||
# ourselves in add_small_action
|
if user.id == removed_by&.id
|
||||||
removed_by = Discourse.system_user if user.id == removed_by&.id
|
removed_by = Discourse.system_user
|
||||||
|
add_small_action(removed_by, "user_left", user.username)
|
||||||
|
else
|
||||||
add_small_action(removed_by, "removed_user", user.username)
|
add_small_action(removed_by, "removed_user", user.username)
|
||||||
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -114,6 +114,7 @@ class TopicViewSerializer < ApplicationSerializer
|
|||||||
result[:can_delete] = true if scope.can_delete?(object.topic)
|
result[:can_delete] = true if scope.can_delete?(object.topic)
|
||||||
result[:can_recover] = true if scope.can_recover_topic?(object.topic)
|
result[:can_recover] = true if scope.can_recover_topic?(object.topic)
|
||||||
result[:can_remove_allowed_users] = true if scope.can_remove_allowed_users?(object.topic)
|
result[:can_remove_allowed_users] = true if scope.can_remove_allowed_users?(object.topic)
|
||||||
|
result[:can_remove_self_id] = scope.user.id if scope.can_remove_allowed_users?(object.topic, scope.user)
|
||||||
result[:can_invite_to] = true if scope.can_invite_to?(object.topic)
|
result[:can_invite_to] = true if scope.can_invite_to?(object.topic)
|
||||||
result[:can_invite_via_email] = true if scope.can_invite_via_email?(object.topic)
|
result[:can_invite_via_email] = true if scope.can_invite_via_email?(object.topic)
|
||||||
result[:can_create_post] = true if scope.can_create?(Post, object.topic)
|
result[:can_create_post] = true if scope.can_create?(Post, object.topic)
|
||||||
|
@ -143,6 +143,7 @@ en:
|
|||||||
split_topic: "split this topic %{when}"
|
split_topic: "split this topic %{when}"
|
||||||
invited_user: "invited %{who} %{when}"
|
invited_user: "invited %{who} %{when}"
|
||||||
invited_group: "invited %{who} %{when}"
|
invited_group: "invited %{who} %{when}"
|
||||||
|
user_left: "%{who} left this message %{when}"
|
||||||
removed_user: "removed %{who} %{when}"
|
removed_user: "removed %{who} %{when}"
|
||||||
removed_group: "removed %{who} %{when}"
|
removed_group: "removed %{who} %{when}"
|
||||||
autoclosed:
|
autoclosed:
|
||||||
@ -1030,6 +1031,7 @@ en:
|
|||||||
private_message_info:
|
private_message_info:
|
||||||
title: "Message"
|
title: "Message"
|
||||||
invite: "Invite Others..."
|
invite: "Invite Others..."
|
||||||
|
leave_message: "Do you really want to leave this message?"
|
||||||
remove_allowed_user: "Do you really want to remove {{name}} from this message?"
|
remove_allowed_user: "Do you really want to remove {{name}} from this message?"
|
||||||
remove_allowed_group: "Do you really want to remove {{name}} from this message?"
|
remove_allowed_group: "Do you really want to remove {{name}} from this message?"
|
||||||
|
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
#mixin for all guardian methods dealing with topic permisions
|
#mixin for all guardian methods dealing with topic permisions
|
||||||
module TopicGuardian
|
module TopicGuardian
|
||||||
|
|
||||||
def can_remove_allowed_users?(topic)
|
def can_remove_allowed_users?(topic, target_user = nil)
|
||||||
is_staff?
|
is_staff? ||
|
||||||
|
(
|
||||||
|
topic.allowed_users.count > 1 &&
|
||||||
|
topic.user != target_user &&
|
||||||
|
!!(target_user && user == target_user)
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Creating Methods
|
# Creating Methods
|
||||||
|
@ -2613,4 +2613,60 @@ describe Guardian do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#can_remove_allowed_users?' do
|
||||||
|
context 'staff users' do
|
||||||
|
it 'should be true' do
|
||||||
|
expect(Guardian.new(moderator).can_remove_allowed_users?(topic))
|
||||||
|
.to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'normal user' do
|
||||||
|
let(:topic) { Fabricate(:topic, user: Fabricate(:user)) }
|
||||||
|
let(:another_user) { Fabricate(:user) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
topic.allowed_users << user
|
||||||
|
topic.allowed_users << another_user
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should be false' do
|
||||||
|
expect(Guardian.new(user).can_remove_allowed_users?(topic))
|
||||||
|
.to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'target_user is the user' do
|
||||||
|
describe 'when user is in a pm with another user' do
|
||||||
|
it 'should return true' do
|
||||||
|
expect(Guardian.new(user).can_remove_allowed_users?(topic, user))
|
||||||
|
.to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when user is the creator of the topic' do
|
||||||
|
it 'should return false' do
|
||||||
|
expect(Guardian.new(topic.user).can_remove_allowed_users?(topic, topic.user))
|
||||||
|
.to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when user is the only user in the topic' do
|
||||||
|
it 'should return false' do
|
||||||
|
topic.remove_allowed_user(Discourse.system_user, another_user.username)
|
||||||
|
|
||||||
|
expect(Guardian.new(user).can_remove_allowed_users?(topic, user))
|
||||||
|
.to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'target_user is not the user' do
|
||||||
|
it 'should return false' do
|
||||||
|
expect(Guardian.new(user).can_remove_allowed_users?(topic, moderator))
|
||||||
|
.to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -6,6 +6,7 @@ require_dependency 'post_destroyer'
|
|||||||
describe Topic do
|
describe Topic do
|
||||||
let(:now) { Time.zone.local(2013, 11, 20, 8, 0) }
|
let(:now) { Time.zone.local(2013, 11, 20, 8, 0) }
|
||||||
let(:user) { Fabricate(:user) }
|
let(:user) { Fabricate(:user) }
|
||||||
|
let(:topic) { Fabricate(:topic) }
|
||||||
|
|
||||||
context 'validations' do
|
context 'validations' do
|
||||||
let(:topic) { Fabricate.build(:topic) }
|
let(:topic) { Fabricate.build(:topic) }
|
||||||
@ -2040,4 +2041,23 @@ describe Topic do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#remove_allowed_user' do
|
||||||
|
let(:another_user) { Fabricate(:user) }
|
||||||
|
|
||||||
|
describe 'removing oneself' do
|
||||||
|
it 'should remove onself' do
|
||||||
|
topic.allowed_users << another_user
|
||||||
|
|
||||||
|
expect(topic.remove_allowed_user(another_user, another_user)).to eq(true)
|
||||||
|
expect(topic.allowed_users.include?(another_user)).to eq(false)
|
||||||
|
|
||||||
|
post = Post.last
|
||||||
|
|
||||||
|
expect(post.user).to eq(Discourse.system_user)
|
||||||
|
expect(post.post_type).to eq(Post.types[:small_action])
|
||||||
|
expect(post.action_code).to eq('user_left')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user