Merge pull request #3247 from jmay/group-manager-invites
group manager can issue invitations from restricted topics
This commit is contained in:
commit
3a40875e0b
|
@ -21,6 +21,7 @@ export default ObjectController.extend(ModalFunctionality, {
|
|||
if (this.get('saving')) return true;
|
||||
if (this.blank('email')) return true;
|
||||
if (!Discourse.Utilities.emailValid(this.get('email'))) return true;
|
||||
if (this.get('model.details.can_invite_to')) return false;
|
||||
if (this.get('isPrivateTopic') && this.blank('groupNames')) return true;
|
||||
return false;
|
||||
}.property('email', 'isPrivateTopic', 'groupNames', 'saving'),
|
||||
|
|
|
@ -56,6 +56,21 @@ class Invite < ActiveRecord::Base
|
|||
end
|
||||
|
||||
|
||||
def add_groups_for_topic(topic)
|
||||
if topic.category
|
||||
(topic.category.groups - groups).each { |group| group.add(user) }
|
||||
end
|
||||
end
|
||||
|
||||
def self.extend_permissions(topic, user, invited_by)
|
||||
if topic.private_message?
|
||||
topic.grant_permission_to_user(user.email)
|
||||
elsif topic.category && topic.category.groups.any?
|
||||
if Guardian.new(invited_by).can_invite_to?(topic)
|
||||
(topic.category.groups - user.groups).each { |group| group.add(user) }
|
||||
end
|
||||
end
|
||||
end
|
||||
# Create an invite for a user, supplying an optional topic
|
||||
#
|
||||
# Return the previously existing invite if already exists. Returns nil if the invite can't be created.
|
||||
|
@ -64,7 +79,7 @@ class Invite < ActiveRecord::Base
|
|||
user = User.find_by(email: lower_email)
|
||||
|
||||
if user
|
||||
topic.grant_permission_to_user(lower_email) if topic && topic.private_message?
|
||||
extend_permissions(topic, user, invited_by) if topic
|
||||
return nil
|
||||
end
|
||||
|
||||
|
@ -93,6 +108,11 @@ class Invite < ActiveRecord::Base
|
|||
group_ids.each do |group_id|
|
||||
invite.invited_groups.create!(group_id: group_id)
|
||||
end
|
||||
else
|
||||
if topic && topic.category # && Guardian.new(invited_by).can_invite_to?(topic)
|
||||
group_ids = topic.category.groups.pluck(:id) - invite.invited_groups.pluck(:group_id)
|
||||
group_ids.each { |group_id| invite.invited_groups.create!(group_id: group_id) }
|
||||
end
|
||||
end
|
||||
|
||||
Jobs.enqueue(:invite_email, invite_id: invite.id)
|
||||
|
|
|
@ -197,6 +197,12 @@ class Guardian
|
|||
is_me?(user)
|
||||
end
|
||||
|
||||
def invitations_allowed?
|
||||
!SiteSetting.enable_sso &&
|
||||
SiteSetting.enable_local_logins &&
|
||||
(!SiteSetting.must_approve_users? || is_staff?)
|
||||
end
|
||||
|
||||
def can_invite_to_forum?(groups=nil)
|
||||
authenticated? &&
|
||||
!SiteSetting.enable_sso &&
|
||||
|
@ -209,10 +215,21 @@ class Guardian
|
|||
end
|
||||
|
||||
def can_invite_to?(object, group_ids=nil)
|
||||
can_invite = can_see?(object) && can_invite_to_forum? && ( group_ids.blank? || is_admin? )
|
||||
#TODO how should invite to PM work?
|
||||
can_invite = can_invite && ( !object.category.read_restricted || is_admin? ) if object.is_a?(Topic) && object.category
|
||||
can_invite
|
||||
return false if ! authenticated?
|
||||
return false if ! invitations_allowed?
|
||||
return true if is_admin?
|
||||
return false if ! can_see?(object)
|
||||
|
||||
return false if group_ids.present?
|
||||
|
||||
if object.is_a?(Topic) && object.category
|
||||
if object.category.groups.any?
|
||||
return true if object.category.groups.all? { |g| can_edit_group?(g) }
|
||||
end
|
||||
return false if object.category.read_restricted
|
||||
end
|
||||
|
||||
user.has_trust_level?(TrustLevel[2])
|
||||
end
|
||||
|
||||
def can_bulk_invite_to_forum?(user)
|
||||
|
|
|
@ -266,6 +266,9 @@ describe Guardian do
|
|||
let(:user) { topic.user }
|
||||
let(:moderator) { Fabricate(:moderator) }
|
||||
let(:admin) { Fabricate(:admin) }
|
||||
let(:private_category) { Fabricate(:private_category, group: group) }
|
||||
let(:group_private_topic) { Fabricate(:topic, category: private_category) }
|
||||
let(:group_manager) { group_private_topic.user.tap { |u| group.add(u); group.appoint_manager(u) } }
|
||||
|
||||
it 'handles invitation correctly' do
|
||||
expect(Guardian.new(nil).can_invite_to?(topic)).to be_falsey
|
||||
|
@ -298,6 +301,9 @@ describe Guardian do
|
|||
expect(Guardian.new(admin).can_invite_to?(private_topic)).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns true for a group manager' do
|
||||
expect(Guardian.new(group_manager).can_invite_to?(group_private_topic)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
describe 'can_see?' do
|
||||
|
|
|
@ -790,6 +790,20 @@ describe TopicsController do
|
|||
expect { xhr :post, :invite, topic_id: 1, email: 'jake@adventuretime.ooo' }.to raise_error(Discourse::NotLoggedIn)
|
||||
end
|
||||
|
||||
describe 'when logged in as group manager' do
|
||||
let(:group_manager) { log_in }
|
||||
let(:group) { Fabricate(:group).tap { |g| g.add(group_manager); g.appoint_manager(group_manager) } }
|
||||
let(:private_category) { Fabricate(:private_category, group: group) }
|
||||
let(:group_private_topic) { Fabricate(:topic, category: private_category, user: group_manager) }
|
||||
let(:recipient) { 'jake@adventuretime.ooo' }
|
||||
|
||||
it "should attach group to the invite" do
|
||||
xhr :post, :invite, topic_id: group_private_topic.id, user: recipient
|
||||
expect(response).to be_success
|
||||
expect(Invite.find_by(email: recipient).groups).to eq([group])
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when logged in' do
|
||||
before do
|
||||
@topic = Fabricate(:topic, user: log_in)
|
||||
|
@ -806,7 +820,7 @@ describe TopicsController do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'with permission' do
|
||||
describe 'with admin permission' do
|
||||
|
||||
let!(:admin) do
|
||||
log_in :admin
|
||||
|
|
|
@ -13,3 +13,15 @@ Fabricator(:happy_category, from: :category) do
|
|||
slug 'happy'
|
||||
user
|
||||
end
|
||||
|
||||
Fabricator(:private_category, from: :category) do
|
||||
transient :group
|
||||
|
||||
name 'Private Category'
|
||||
slug 'private'
|
||||
user
|
||||
after_build do |cat, transients|
|
||||
cat.update!(read_restricted: true)
|
||||
cat.category_groups.build(group_id: transients[:group].id, permission_type: :full)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -127,6 +127,28 @@ describe Invite do
|
|||
end
|
||||
end
|
||||
|
||||
context 'to a group-private topic' do
|
||||
let(:group) { Fabricate(:group) }
|
||||
let(:private_category) { Fabricate(:private_category, group: group) }
|
||||
let(:group_private_topic) { Fabricate(:topic, category: private_category) }
|
||||
let(:inviter) { group_private_topic.user }
|
||||
|
||||
before do
|
||||
@invite = group_private_topic.invite_by_email(inviter, iceking)
|
||||
end
|
||||
|
||||
it 'should add the groups to the invite' do
|
||||
expect(@invite.groups).to eq([group])
|
||||
end
|
||||
|
||||
context 'when duplicated' do
|
||||
it 'should not duplicate the groups' do
|
||||
expect(group_private_topic.invite_by_email(inviter, iceking)).to eq(@invite)
|
||||
expect(@invite.groups).to eq([group])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'an existing user' do
|
||||
let(:topic) { Fabricate(:topic, category_id: nil, archetype: 'private_message') }
|
||||
let(:coding_horror) { Fabricate(:coding_horror) }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# encoding: UTF-8
|
||||
# encoding: utf-8
|
||||
|
||||
require 'spec_helper'
|
||||
require_dependency 'post_destroyer'
|
||||
|
@ -1352,4 +1352,37 @@ describe Topic do
|
|||
topic.last_posted_at = 1.minute.ago
|
||||
expect(topic.save).to eq(true)
|
||||
end
|
||||
|
||||
context 'invite by group manager' do
|
||||
let(:group_manager) { Fabricate(:user) }
|
||||
let(:group) { Fabricate(:group).tap { |g| g.add(group_manager); g.appoint_manager(group_manager) } }
|
||||
let(:private_category) { Fabricate(:private_category, group: group) }
|
||||
let(:group_private_topic) { Fabricate(:topic, category: private_category, user: group_manager) }
|
||||
|
||||
context 'to an email' do
|
||||
let(:randolph) { 'randolph@duke.ooo' }
|
||||
|
||||
it "should attach group to the invite" do
|
||||
invite = group_private_topic.invite(group_manager, randolph)
|
||||
expect(invite.groups).to eq([group])
|
||||
end
|
||||
end
|
||||
|
||||
# should work for an existing user - give access, send notification
|
||||
context 'to an existing user' do
|
||||
let(:walter) { Fabricate(:walter_white) }
|
||||
|
||||
it "should add user to the group" do
|
||||
expect(Guardian.new(walter).can_see?(group_private_topic)).to be_falsey
|
||||
invite = group_private_topic.invite(group_manager, walter.email)
|
||||
expect(invite).to be_nil
|
||||
expect(walter.groups).to include(group)
|
||||
expect(Guardian.new(walter).can_see?(group_private_topic)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
||||
context 'to a previously-invited user' do
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue