Skip to content

Commit 54203f5

Browse files
committed
Allow space administrators to manage sources in their spaces
1 parent eb2e714 commit 54203f5

8 files changed

Lines changed: 108 additions & 14 deletions

File tree

app/controllers/sources_controller.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def show
2424

2525
# GET /sources/new
2626
def new
27-
authorize Source
27+
authorize @content_provider, :create_source?
2828
@source = @content_provider.sources.build
2929
end
3030

@@ -36,7 +36,7 @@ def edit
3636
# POST /sources
3737
# POST /sources.json
3838
def create
39-
authorize Source
39+
authorize @content_provider, :create_source?
4040
@source = @content_provider.sources.build(source_params)
4141
@source.user = current_user
4242
@source.space = current_space
@@ -146,13 +146,12 @@ def set_source
146146
def set_content_provider
147147
@content_provider = @source.content_provider if @source
148148
@content_provider ||= ContentProvider.friendly.find(params[:content_provider_id])
149-
authorize @content_provider, :manage?
150149
end
151150

152151
# Never trust parameters from the scary internet, only allow the white list through.
153152
def source_params
154153
permitted = [:url, :method, :token, :default_language, :enabled]
155-
permitted << :approval_status if policy(Source).approve?
154+
permitted << :approval_status if policy(@source || Source).approve?
156155
permitted << :content_provider_id if policy(Source).index?
157156

158157
params.require(:source).permit(permitted)

app/mailers/curation_mailer.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ def source_requires_approval(source, user)
1717
@user = user
1818
@source = source
1919
subject = "#{TeSS::Config.site['title_short']} source \"#{@source.title}\" requires approval"
20-
mail(subject:, to: User.with_role('admin').map(&:email)) do |format|
20+
space = @source.space || Space.default
21+
mail(subject:, to: space.administrators.map(&:email)) do |format|
2122
format.html
2223
format.text
2324
end

app/models/default_space.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,8 @@ def learning_path_topics
5656
def default?
5757
true
5858
end
59+
60+
def administrators
61+
User.with_role('admin')
62+
end
5963
end

app/policies/application_policy.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ def initialize(context, record)
1616
@user = context.user
1717
@request = context.request
1818
@record = record
19+
@space = nil
20+
@space = record.space if record.respond_to?(:space)
1921
end
2022

2123
def index?
@@ -83,9 +85,11 @@ def scraper?
8385
end
8486

8587
# Check if the user has any of the given roles.
88+
# If we're in a space, also check they have any of those roles in the context of the space.
8689
def user_has_role?(*roles)
8790
return false if @user.nil?
88-
roles.any? { |r| @user.has_role?(r) }
91+
roles.any? { |r| @user.has_role?(r) } ||
92+
(@space && roles.any? { |r| @user.has_space_role?(@space, r) })
8993
end
9094

9195
end
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
class ContentProviderPolicy < ScrapedResourcePolicy
2-
2+
def create_source?
3+
TeSS::Config.feature['user_source_creation'] && manage? ||
4+
user_has_role?(:admin, :curator)
5+
end
36
end

app/policies/source_policy.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ def index?
1313
end
1414

1515
def create?
16-
if TeSS::Config.feature['user_source_creation']
17-
super
18-
else
19-
administration?
20-
end
16+
administration?
2117
end
2218

2319
def approve?
@@ -31,7 +27,7 @@ def request_approval?
3127
private
3228

3329
def administration? # Can edit sources for any content provider
34-
curators_and_admin
30+
curators_and_admin || user_has_role?(:admin)
3531
end
3632

3733
def user_management?

test/controllers/sources_controller_test.rb

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,28 @@ class SourcesControllerTest < ActionController::TestCase
203203
assert_response :success
204204
end
205205

206+
test 'space admin should get edit for source in their space' do
207+
sign_in users(:space_admin)
208+
source = sources(:unapproved_source)
209+
space = spaces(:plants)
210+
source.space = space
211+
source.save!
212+
213+
get :edit, params: { id: source }
214+
assert_response :success
215+
end
216+
217+
test 'space admin should not get edit for source in another space' do
218+
sign_in users(:space_admin)
219+
source = sources(:unapproved_source)
220+
space = spaces(:astro)
221+
source.space = space
222+
source.save!
223+
224+
get :edit, params: { id: source }
225+
assert_response :forbidden
226+
end
227+
206228
# CREATE Tests
207229
test 'public should not create source' do
208230
assert_no_difference 'Source.count' do
@@ -436,9 +458,48 @@ class SourcesControllerTest < ActionController::TestCase
436458
assert source.reload.approved?
437459
end
438460

461+
test 'space admin can approve source in their space' do
462+
sign_in users(:space_admin)
463+
source = sources(:unapproved_source)
464+
space = spaces(:plants)
465+
source.space = space
466+
source.save!
467+
refute source.approved?
468+
469+
patch :update, params: { id: source, source: { approval_status: 'approved' } }
470+
471+
assert_redirected_to source_path(assigns(:source))
472+
assert source.reload.approved?
473+
end
474+
475+
test 'space admin cannot approve source in other space' do
476+
sign_in users(:space_admin)
477+
source = sources(:unapproved_source)
478+
space = spaces(:astro)
479+
source.space = space
480+
source.save!
481+
refute source.approved?
482+
483+
patch :update, params: { id: source, source: { approval_status: 'approved' } }
484+
485+
assert_response :forbidden
486+
refute source.reload.approved?
487+
end
488+
439489
test 'regular user cannot approve source' do
440-
sign_in @user
490+
sign_in users(:another_regular_user)
491+
source = sources(:unapproved_source)
492+
refute source.approved?
493+
494+
patch :update, params: { id: source, source: { approval_status: 'approved' } }
495+
496+
assert_response :forbidden
497+
refute source.reload.approved?
498+
end
499+
500+
test 'source owner cannot approve source' do
441501
source = sources(:unapproved_source)
502+
sign_in source.user
442503
refute source.approved?
443504

444505
patch :update, params: { id: source, source: { approval_status: 'approved' } }

test/mailers/curation_mailer_test.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,4 +249,30 @@ class CurationMailerTest < ActionMailer::TestCase
249249
end
250250
end
251251
end
252+
253+
test 'source approval requests go to administrators' do
254+
source = sources(:unapproved_source)
255+
user = source.user
256+
assert_nil source.space
257+
email = CurationMailer.source_requires_approval(source, user)
258+
259+
admins = User.with_role('admin')
260+
assert admins.any?
261+
assert_equal admins.map(&:email).sort, email.to.sort
262+
end
263+
264+
test 'source in space approval requests go to space administrators' do
265+
source = sources(:unapproved_source)
266+
space = spaces(:plants)
267+
source.space = space
268+
source.save!
269+
user = source.user
270+
assert source.space
271+
email = CurationMailer.source_requires_approval(source, user)
272+
273+
space_admins = space.administrators
274+
assert_equal 1, space_admins.length
275+
assert_equal 1, email.to.length
276+
assert_equal 'plantboss@example.com', email.to.first
277+
end
252278
end

0 commit comments

Comments
 (0)