add new option for dev keys to allow includes

closes PLAT-5154
flag = developer_key_support_includes

Test Plan:
- Create or Edit an API Developer Key
- set the flag on the Developer Key to allow includes 'allow_includes'
- Use an API tool to authenticate and hit an API endpoint and include
  'include' parameters (see Clint or Weston on how to authenticate)
  ex: /api/v1/courses/:id?include[]=permissions&include[]=concluded
- verify that in the response json, the included data exists

Change-Id: I268f59287505151b9e3cb0c0024a4f837e33412e
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/222143
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Product-Review: Clint Furse <cfurse@instructure.com>
Reviewed-by: Weston Dransfield <wdransfield@instructure.com>
QA-Review: Weston Dransfield <wdransfield@instructure.com>
This commit is contained in:
Clint Furse 2020-01-06 15:41:41 -07:00
parent b33e5461d2
commit 1d2ad17214
3 changed files with 55 additions and 8 deletions

View File

@ -0,0 +1,27 @@
#
# Copyright (C) 2019 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
class AddAllowIncludeParamsToDeveloperKey < ActiveRecord::Migration[5.2]
tag :predeploy
def change
add_column :developer_keys, :allow_includes, :boolean
change_column_default(:developer_keys, :allow_includes, false)
DataFixup::BackfillNulls.run(DeveloperKey, :allow_includes, default_value: false)
change_column_null(:developer_keys, :allow_includes, false)
end
end

View File

@ -94,18 +94,20 @@ module AuthenticationMethods
end
def validate_scopes
if @access_token
developer_key = @access_token.developer_key
request_method = request.method.casecmp('HEAD') == 0 ? 'GET' : request.method.upcase
return unless @access_token
if developer_key.try(:require_scopes)
scope_patterns = @access_token.url_scopes_for_method(request_method).concat(AccessToken.always_allowed_scopes)
if scope_patterns.any? { |scope| scope =~ request.path }
developer_key = @access_token.developer_key
request_method = request.method.casecmp('HEAD') == 0 ? 'GET' : request.method.upcase
if developer_key.try(:require_scopes)
scope_patterns = @access_token.url_scopes_for_method(request_method).concat(AccessToken.always_allowed_scopes)
if scope_patterns.any? { |scope| scope =~ request.path }
unless developer_key.try(:allow_includes)
filter_includes(:include)
filter_includes(:includes)
else
raise AccessTokenScopeError
end
else
raise AccessTokenScopeError
end
end
end

View File

@ -1614,6 +1614,24 @@ describe CoursesController do
expect(params).to eq(include: [], includes: ['uuid'])
end
end
context 'with valid scopes and allow includes on dev key' do
let(:developer_key) { DeveloperKey.create!(require_scopes: true, allow_includes: true, scopes: ['url:GET|/api/v1/accounts']) }
it 'keeps includes for adequately scoped requests' do
user = user_model
token = AccessToken.create!(user: user, developer_key: developer_key, scopes: ['url:GET|/api/v1/accounts'])
controller.instance_variable_set(:@access_token, token)
allow(controller).to receive(:request).and_return(double({
method: 'GET',
path: '/api/v1/accounts'
}))
params = { include: ['a'], includes: ['uuid', 'b']}
allow(controller).to receive(:params).and_return(params)
controller.send(:validate_scopes)
expect(params).to eq(include: ['a'], includes: ['uuid', 'b'])
end
end
end
end