Skip to content

Commit 882a71c

Browse files
committed
fixes for :read_forum and :read_announcements permissions
test plan: * create a course role with the ability to manage course content, but "View announcements" is disabled * a user with that role should not see the Announcements tab * having "Moderate forum" rights should not grant read rights to read discussions and announcements (if those are disabled) * having "View announcements" or "View discussions" turned off should prevent new announcements and new discussions from showing in the dashboard or from sending notifications to the restricted users closes #CNVS-28438 #CNVS-28469 #CNVS-28541 Change-Id: I9178d30edb33a6e83c492189f4a6fd1e496c42fa Reviewed-on: https://gerrit.instructure.com/76294 Reviewed-by: Jeremy Stanley <jeremy@instructure.com> Tested-by: Jenkins QA-Review: Jahnavi Yetukuri <jyetukuri@instructure.com> Product-Review: Allison Weiss <allison@instructure.com>
1 parent ab5e732 commit 882a71c

7 files changed

Lines changed: 58 additions & 12 deletions

File tree

app/models/announcement.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def self.lock_from_course(course)
6060

6161
set_broadcast_policy! do
6262
dispatch :new_announcement
63-
to { active_participants(true) - [user] }
63+
to { users_with_permissions(active_participants(true) - [user]) }
6464
whenever { |record|
6565
record.send_notification_for_context? and
6666
((record.just_created and !(record.post_delayed? || record.unpublished?)) || record.changed_state(:active, :unpublished) || record.changed_state(:active, :post_delayed))
@@ -100,7 +100,7 @@ def self.lock_from_course(course)
100100
given { |user, session| self.context.is_a?(Group) && self.context.grants_right?(user, session, :post_to_forum) }
101101
can :create
102102

103-
given { |user, session| self.context.grants_right?(user, session, :moderate_forum) } #admins.include?(user) }
103+
given { |user, session| self.context.grants_all_rights?(user, session, :read_announcements, :moderate_forum) } #admins.include?(user) }
104104
can :update and can :delete and can :reply and can :create and can :read and can :attach
105105

106106
given do |user, session|

app/models/course.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,16 +2418,16 @@ def uncached_tabs_available(user, opts)
24182418
tabs.detect { |t| t[:id] == TAB_DISCUSSIONS }[:manageable] = true if self.grants_right?(user, opts[:session], :moderate_forum)
24192419
tabs.delete_if { |t| t[:id] == TAB_SETTINGS } unless self.grants_right?(user, opts[:session], :read_as_admin)
24202420

2421+
unless announcements.temp_record.grants_right?(user, :read)
2422+
tabs.delete_if { |t| t[:id] == TAB_ANNOUNCEMENTS }
2423+
end
2424+
24212425
if !user || !self.grants_right?(user, :manage_content)
24222426
# remove some tabs for logged-out users or non-students
24232427
unless grants_any_right?(user, :read_as_admin, :participate_as_student)
24242428
tabs.delete_if {|t| [TAB_PEOPLE, TAB_OUTCOMES].include?(t[:id]) }
24252429
end
24262430

2427-
unless announcements.temp_record.grants_right?(user, :read)
2428-
tabs.delete_if { |t| t[:id] == TAB_ANNOUNCEMENTS }
2429-
end
2430-
24312431
# remove hidden tabs from students
24322432
unless self.grants_right?(user, opts[:session], :read_as_admin)
24332433
tabs.delete_if {|t| (t[:hidden] || (t[:hidden_unused] && !opts[:include_hidden_unused])) && !t[:manageable] }

app/models/discussion_topic.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def refresh_subtopics
183183
sub_topics << ensure_child_topic_for(group)
184184
end
185185
end
186-
186+
187187
self.shard.activate do
188188
# delete any lingering child topics
189189
DiscussionTopic.where(:root_topic_id => self).where.not(:id => sub_topics).update_all(:workflow_state => "deleted")
@@ -861,11 +861,11 @@ def initialize_last_reply_at
861861
given { |user, session| context.respond_to?(:allow_student_forum_attachments) && context.allow_student_forum_attachments && context.grants_right?(user, session, :post_to_forum) }
862862
can :attach
863863

864-
given { |user, session| !self.root_topic_id && self.context.grants_right?(user, session, :moderate_forum) && self.available_for?(user) }
864+
given { |user, session| !self.root_topic_id && self.context.grants_all_rights?(user, session, :read_forum, :moderate_forum) && self.available_for?(user) }
865865
can :update and can :delete and can :create and can :read and can :attach
866866

867867
# Moderators can still modify content even in unavailable topics (*especially* unlocking them), but can't create new content
868-
given { |user, session| !self.root_topic_id && self.context.grants_right?(user, session, :moderate_forum) }
868+
given { |user, session| !self.root_topic_id && self.context.grants_all_rights?(user, session, :read_forum, :moderate_forum) }
869869
can :update and can :delete and can :read and can :attach
870870

871871
given { |user, session| self.root_topic && self.root_topic.grants_right?(user, session, :update) }
@@ -961,7 +961,7 @@ def send_notification_for_context?
961961

962962
set_broadcast_policy do |p|
963963
p.dispatch :new_discussion_topic
964-
p.to { active_participants_with_visibility - [user] }
964+
p.to { users_with_permissions(active_participants_with_visibility - [user]) }
965965
p.whenever { |record|
966966
record.send_notification_for_context? and
967967
((record.just_created && record.active?) || record.changed_state(:active, !record.is_announcement ? :unpublished : :post_delayed))
@@ -986,6 +986,10 @@ def active_participants(include_observers=false)
986986
end
987987
end
988988

989+
def users_with_permissions(users)
990+
users.select{|u| self.is_announcement ? self.context.grants_right?(u, :read_announcements) : self.context.grants_right?(u, :read_forum)}
991+
end
992+
989993
def course
990994
@course ||= context.is_a?(Group) ? context.context : context
991995
end
@@ -1066,6 +1070,8 @@ def visible_for?(user = nil)
10661070
# user is the topic's author
10671071
return true if user == self.user
10681072

1073+
return false if user && !(is_announcement ? context.grants_right?(user, :read_announcements) : context.grants_right?(user, :read_forum))
1074+
10691075
# user is an admin in the context (teacher/ta/designer) OR
10701076
# user is an account admin with appropriate permission
10711077
return true if context.grants_any_right?(user, :manage, :read_course_content)

spec/models/announcement_spec.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@
9292
a = @course.announcements.create!(valid_announcement_attributes)
9393
expect(a.grants_right?(@user, :read)).to be(false)
9494
end
95+
96+
it 'does not allow announcements to be viewed without :read_announcements (even with moderate_forum)' do
97+
course_with_teacher(active_all: true)
98+
@course.account.role_overrides.create!(permission: 'read_announcements', role: teacher_role, enabled: false)
99+
a = @course.announcements.create!(valid_announcement_attributes)
100+
expect(a.grants_right?(@user, :read)).to be(false)
101+
end
95102
end
96103

97104
context "broadcast policy" do
@@ -147,5 +154,18 @@
147154
expect(to_users).to include(@observer)
148155
expect(@a.messages_sent["Announcement Created By You"].map(&:user)).to include(@teacher)
149156
end
157+
158+
it "should not broadcast if read_announcements is diabled" do
159+
Account.default.role_overrides.create!(:role => student_role, :permission => 'read_announcements', :enabled => false)
160+
course_with_student(:active_all => true)
161+
notification_name = "New Announcement"
162+
n = Notification.create(:name => notification_name, :category => "TestImmediately")
163+
NotificationPolicy.create(:notification => n, :communication_channel => @student.communication_channel, :frequency => "immediately")
164+
165+
@context = @course
166+
announcement_model(:user => @teacher)
167+
168+
expect(@a.messages_sent[notification_name]).to be_blank
169+
end
150170
end
151171
end

spec/models/course_spec.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,12 @@ def setup_DA
15051505
tab_ids = @course.tabs_available(@user).map{|t| t[:id] }
15061506
expect(tab_ids).to eql(Course.default_tabs.map{|t| t[:id] })
15071507
end
1508+
1509+
it "should not include Announcements without read_announcements rights" do
1510+
@course.account.role_overrides.create!(:role => teacher_role, :permission => 'read_announcements', :enabled => false)
1511+
tab_ids = @course.uncached_tabs_available(@teacher, {}).map{|t| t[:id] }
1512+
expect(tab_ids).to_not include(Course::TAB_ANNOUNCEMENTS)
1513+
end
15081514
end
15091515

15101516
context "students" do
@@ -1581,7 +1587,6 @@ def setup_DA
15811587
Lti::MessageHandler.stubs(:lti_apps_tabs).returns([mock_tab])
15821588
expect(@course.tabs_available(nil, :include_external => true)).to include(mock_tab)
15831589
end
1584-
15851590
end
15861591

15871592
context "observers" do

spec/models/discussion_topic_spec.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@
9292
@relevant_permissions = [:read, :reply, :update, :delete]
9393
end
9494

95+
it "should not grant moderate permissions without read permissions" do
96+
@course.account.role_overrides.create!(:role => teacher_role, :permission => 'read_forum', :enabled => false)
97+
expect((@topic.check_policy(@teacher2) & @relevant_permissions)).to be_empty
98+
end
99+
95100
it "should grant permissions if it not locked" do
96101
@topic.publish!
97102
expect((@topic.check_policy(@teacher1) & @relevant_permissions).map(&:to_s).sort).to eq ['read', 'reply', 'update', 'delete'].sort
@@ -213,7 +218,7 @@
213218

214219
account = @course.root_account
215220
nobody_role = custom_account_role('NobodyAdmin', account: account)
216-
account_with_role_changes(account: account, role: nobody_role, role_changes: { read_course_content: true })
221+
account_with_role_changes(account: account, role: nobody_role, role_changes: { read_course_content: true, read_forum: true })
217222
admin = account_admin_user(account: account, role: nobody_role, active_user: true)
218223
expect(@topic.visible_for?(admin)).to be_truthy
219224
end

spec/selenium/dashboard_spec.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ def test_hiding(url)
8181
end
8282
end
8383

84+
it "should not show announcement stream items without permissions" do
85+
@course.account.role_overrides.create!(:role => student_role, :permission => 'read_announcements', :enabled => false)
86+
87+
announcement = create_announcement
88+
item_selector = '#announcement-details tbody tr'
89+
90+
get "/"
91+
expect(f('.no_recent_messages')).to include_text('No Recent Messages')
92+
end
93+
8494
def click_recent_activity_header(type='announcement')
8595
f(".stream-#{type} .stream_header").click
8696
end

0 commit comments

Comments
 (0)