diff --git a/app/assets/javascripts/discourse/app/controllers/create-invite.js b/app/assets/javascripts/discourse/app/controllers/create-invite.js index e4dc979f0ed..ad8a302ec14 100644 --- a/app/assets/javascripts/discourse/app/controllers/create-invite.js +++ b/app/assets/javascripts/discourse/app/controllers/create-invite.js @@ -121,7 +121,7 @@ export default Controller.extend( return this.invite .save(data) - .then((result) => { + .then(() => { this.rollbackBuffer(); if ( @@ -131,22 +131,14 @@ export default Controller.extend( this.invites.unshiftObject(this.invite); } - if (result.warnings) { + if (this.isEmail && opts.sendEmail) { + this.send("closeModal"); + } else { this.setProperties({ - flashText: sanitize(result.warnings.join(",")), - flashClass: "warning", + flashText: sanitize(I18n.t("user.invited.invite.invite_saved")), + flashClass: "success", flashLink: !this.editing, }); - } else { - if (this.isEmail && opts.sendEmail) { - this.send("closeModal"); - } else { - this.setProperties({ - flashText: sanitize(I18n.t("user.invited.invite.invite_saved")), - flashClass: "success", - flashLink: !this.editing, - }); - } } }) .catch((e) => diff --git a/app/assets/javascripts/discourse/app/controllers/share-topic.js b/app/assets/javascripts/discourse/app/controllers/share-topic.js index 3c54976d9b5..b9a06513730 100644 --- a/app/assets/javascripts/discourse/app/controllers/share-topic.js +++ b/app/assets/javascripts/discourse/app/controllers/share-topic.js @@ -105,7 +105,10 @@ export default Controller.extend( inviteUsers() { this.set("showNotifyUsers", false); const controller = showModal("create-invite"); - controller.set("inviteToTopic", true); + controller.setProperties({ + inviteToTopic: true, + topics: [this.topic], + }); controller.buffered.setProperties({ topicId: this.topic.id, topicTitle: this.topic.title, diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index ed737cb3695..35aee33d470 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -138,6 +138,11 @@ class InvitesController < ApplicationController guardian.ensure_can_invite_to_forum!(groups) + if !groups_can_see_topic?(groups, topic) + editable_topic_groups = topic.category.groups.filter { |g| guardian.can_edit_group?(g) } + return render_json_error(I18n.t("invite.requires_groups", groups: editable_topic_groups.pluck(:name).join(", "))) + end + begin invite = Invite.generate(current_user, email: params[:email], @@ -201,6 +206,11 @@ class InvitesController < ApplicationController groups.each { |group| invite.invited_groups.find_or_create_by!(group_id: group.id) } if groups.present? end + if !groups_can_see_topic?(invite.groups, invite.topics.first) + editable_topic_groups = invite.topics.first.category.groups.filter { |g| guardian.can_edit_group?(g) } + return render_json_error(I18n.t("invite.requires_groups", groups: editable_topic_groups.pluck(:name).join(", "))) + end + if params.has_key?(:email) old_email = invite.email.presence new_email = params[:email].presence @@ -448,6 +458,15 @@ class InvitesController < ApplicationController end end + def groups_can_see_topic?(groups, topic) + if topic&.read_restricted_category? + topic_groups = topic.category.groups + return false if (groups & topic_groups).blank? + end + + true + end + def post_process_invite(user) user.enqueue_welcome_message('welcome_invite') if user.send_welcome_message diff --git a/app/models/invite.rb b/app/models/invite.rb index 1594a109ab4..9b715a5d5a4 100644 --- a/app/models/invite.rb +++ b/app/models/invite.rb @@ -239,23 +239,6 @@ class Invite < ActiveRecord::Base Jobs.enqueue(:invite_email, invite_id: self.id) end - def warnings(guardian) - @warnings ||= begin - warnings = [] - - topic = self.topics.first - if topic&.read_restricted_category? - topic_groups = topic.category.groups - if (self.groups & topic_groups).blank? - editable_topic_groups = topic_groups.filter { |g| guardian.can_edit_group?(g) } - warnings << I18n.t("invite.requires_groups", groups: editable_topic_groups.pluck(:name).join(", ")) - end - end - - warnings - end - end - def limit_invites_per_day RateLimiter.new(invited_by, "invites-per-day", SiteSetting.max_invites_per_day, 1.day.to_i) end diff --git a/app/serializers/invite_serializer.rb b/app/serializers/invite_serializer.rb index f9f61aa70ea..5ca6021c9a1 100644 --- a/app/serializers/invite_serializer.rb +++ b/app/serializers/invite_serializer.rb @@ -13,8 +13,7 @@ class InviteSerializer < ApplicationSerializer :created_at, :updated_at, :expires_at, - :expired, - :warnings + :expired has_many :topics, embed: :object, serializer: BasicTopicSerializer has_many :groups, embed: :object, serializer: BasicGroupSerializer @@ -46,12 +45,4 @@ class InviteSerializer < ApplicationSerializer def expired object.expired? end - - def warnings - object.warnings(scope) - end - - def include_warnings? - object.warnings(scope).present? - end end diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 9024bbbba31..24fe3a11b7f 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -258,7 +258,7 @@ en: disabled_errors: discourse_connect_enabled: "Invites are disabled because DiscourseConnect is enabled." invalid_access: "You are not permitted to view the requested resource." - requires_groups: "Invite saved. To give access to the specified topic, add one of the following groups: %{groups}." + requires_groups: "Invite was not saved because the specified topic is inaccessible. Add one of the following groups: %{groups}." domain_not_allowed: "Your email cannot be used to redeem this invite." bulk_invite: diff --git a/spec/models/invite_spec.rb b/spec/models/invite_spec.rb index 994aeeabe51..9664cba4092 100644 --- a/spec/models/invite_spec.rb +++ b/spec/models/invite_spec.rb @@ -429,27 +429,4 @@ describe Invite do expect(invite.invalidated_at).to be_nil end end - - describe '#warnings' do - fab!(:admin) { Fabricate(:admin) } - fab!(:invite) { Fabricate(:invite) } - fab!(:group) { Fabricate(:group) } - fab!(:secured_category) do - secured_category = Fabricate(:category) - secured_category.permissions = { group.name => :full } - secured_category.save! - secured_category - end - - it 'does not return any warnings for simple invites' do - expect(invite.warnings(admin.guardian)).to be_blank - end - - it 'returns a warning if topic is private' do - topic = Fabricate(:topic, category: secured_category) - TopicInvite.create!(topic: topic, invite: invite) - - expect(invite.warnings(admin.guardian)).to contain_exactly(I18n.t("invite.requires_groups", groups: group.name)) - end - end end diff --git a/spec/requests/invites_controller_spec.rb b/spec/requests/invites_controller_spec.rb index dd3d9e70b26..d0262eb5b22 100644 --- a/spec/requests/invites_controller_spec.rb +++ b/spec/requests/invites_controller_spec.rb @@ -203,6 +203,35 @@ describe InvitesController do post '/invites.json', params: { email: 'test@example.com', topic_id: -9999 } expect(response.status).to eq(400) end + + context 'topic is private' do + fab!(:group) { Fabricate(:group) } + + fab!(:secured_category) do |category| + category = Fabricate(:category) + category.permissions = { group.name => :full } + category.save! + category + end + + fab!(:topic) { Fabricate(:topic, category: secured_category) } + + it 'does not work and returns a list of required groups' do + sign_in(admin) + + post '/invites.json', params: { email: 'test@example.com', topic_id: topic.id } + expect(response.status).to eq(422) + expect(response.parsed_body["errors"]).to contain_exactly(I18n.t("invite.requires_groups", groups: group.name)) + end + + it 'does not work if user cannot edit groups' do + group.add(user) + sign_in(user) + + post '/invites.json', params: { email: 'test@example.com', topic_id: topic.id } + expect(response.status).to eq(403) + end + end end context 'invite to group' do