|
| 1 | +require_relative '../test_case' |
| 2 | + |
| 3 | +# Verifies the `admin_only!` authorization gate (helpers/application_helper.rb): |
| 4 | +# every endpoint guarded by it must return 403 for an authenticated non-admin. |
| 5 | +# `admin_only!` is the first line of each guarded handler, so it halts before |
| 6 | +# any endpoint work runs -- no valid payload or target resource is required. |
| 7 | +# |
| 8 | +# The "admin is allowed through" path is left to the existing endpoint tests |
| 9 | +# (e.g. test_slices_controller, test_users_controller); it is not re-exercised |
| 10 | +# here to avoid their side effects (slice/user mutation, annotator dictionary |
| 11 | +# and cache rebuilds). |
| 12 | +class TestAdminOnlyEndpoints < TestCase |
| 13 | + |
| 14 | + # [http verb, path] for every reachable handler that calls `admin_only!`. |
| 15 | + # |
| 16 | + # GET /slices/synchronize_groups also calls admin_only! but is unreachable -- |
| 17 | + # the earlier `get '/:slice_id'` route shadows it -- so it is omitted here. |
| 18 | + ADMIN_ONLY_ENDPOINTS = [ |
| 19 | + [:post, "/slices"], |
| 20 | + [:patch, "/slices/any"], |
| 21 | + [:delete, "/slices/any"], |
| 22 | + [:delete, "/users/any"], |
| 23 | + [:post, "/annotator/dictionary"], |
| 24 | + [:post, "/annotator/cache"] |
| 25 | + ].freeze |
| 26 | + |
| 27 | + def before_suite |
| 28 | + self.class.delete_user("test-admin-gate") |
| 29 | + @@user = self.class.create_user("test-admin-gate") |
| 30 | + end |
| 31 | + |
| 32 | + def after_suite |
| 33 | + self.class.delete_user("test-admin-gate") |
| 34 | + end |
| 35 | + |
| 36 | + def setup |
| 37 | + # Reset the role with security off: user.save runs a write permission check |
| 38 | + # when security is on, which denies outside an authenticated request. The |
| 39 | + # request under test enables security itself. |
| 40 | + with_settings(enable_security: false) do |
| 41 | + self.class.reset_to_not_admin(@@user) |
| 42 | + end |
| 43 | + end |
| 44 | + |
| 45 | + def test_admin_only_endpoints_forbidden_for_non_admin |
| 46 | + with_settings(enable_security: true) do |
| 47 | + ADMIN_ONLY_ENDPOINTS.each do |verb, path| |
| 48 | + send(verb, "#{path}?apikey=#{@@user.apikey}") |
| 49 | + |
| 50 | + assert_equal 403, last_response.status, |
| 51 | + "expected 403 for #{verb.upcase} #{path} as a non-admin user, " \ |
| 52 | + "got #{last_response.status}: #{last_response.body}" |
| 53 | + assert_match(/access denied/i, last_response.body, |
| 54 | + "expected an 'Access denied' body for #{verb.upcase} #{path}") |
| 55 | + end |
| 56 | + end |
| 57 | + end |
| 58 | +end |
0 commit comments