Merge pull request #3247 from jmay/group-manager-invites

group manager can issue invitations from restricted topics
This commit is contained in:
Régis Hanol 2015-03-16 09:53:04 +01:00
commit 3a40875e0b
8 changed files with 132 additions and 7 deletions

View File

@ -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'),

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) }

View File

@ -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