override bookmark pagination for some dev keys

* only in the enrollments API
* only for two developer keys
* temporary change while they sort out their client apps
* this list may be changed by changing the Setting

closes INTEROP-5326
flag=none

test plan
* get an API access token from Account -> Settings
* make a GET request to `http://<canvas>/api/v1/courses/1/enrollments`
* include the header `Authorization: Bearer <token>`
* it should paginate the results using a bookmark (if this is hard to
see locally, slap a debugger in enrollments_api_controller:430
and check if `use_bookmarking` is true
* in a console, run:
`global_id = Shard.global_id_for(DeveloperKey.default.id)`
`Setting.set("pagination_override_key_list", global_id.to_s)`
* make that GET request again and it should be paginated with page
numbers (or `use_bookmarking` should be false)

Change-Id: Iee1946648f4cc59abffeec8d69c92a4ea71bc4bf
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/243794
Reviewed-by: Weston Dransfield <wdransfield@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Tucker Mcknight <tmcknight@instructure.com>
Product-Review: Xander Moffatt <xmoffatt@instructure.com>
This commit is contained in:
Xander Moffatt 2020-07-29 13:55:13 -06:00
parent c78da34e90
commit cde3ab1a05
2 changed files with 146 additions and 112 deletions

View File

@ -423,7 +423,10 @@ class EnrollmentsApiController < ApplicationController
course_index_enrollments :
user_index_enrollments
use_bookmarking = @domain_root_account&.feature_enabled?(:bookmarking_for_enrollments_index)
# a few specific developer keys temporarily need bookmarking disabled, see INTEROP-5326
pagination_override_key_list = Setting.get("pagination_override_key_list", "").split(',').map(&:to_i)
use_numeric_pagination_override = pagination_override_key_list.include?(@access_token&.global_developer_key_id)
use_bookmarking = @domain_root_account&.feature_enabled?(:bookmarking_for_enrollments_index) && !use_numeric_pagination_override
enrollments = use_bookmarking ?
enrollments.joins(:user).select("enrollments.*, users.sortable_name AS sortable_name") :
enrollments.joins(:user).select("enrollments.*").

View File

@ -2185,121 +2185,152 @@ describe EnrollmentsApiController, type: :request do
end
describe "pagination" do
it "should properly paginate" do
Account.default.enable_feature!(:bookmarking_for_enrollments_index)
json = api_call(:get, "#{@path}?page=1&per_page=1", @params.merge(:page => 1.to_param, :per_page => 1.to_param))
enrollments = %w{observer student ta teacher}.inject([]) { |res, type|
res = res + @course.send("#{type}_enrollments").preload(:user)
}.map do |e|
h = {
'root_account_id' => e.root_account_id,
'limit_privileges_to_course_section' => e.limit_privileges_to_course_section,
'enrollment_state' => e.workflow_state,
'id' => e.id,
'user_id' => e.user_id,
'type' => e.type,
'role' => e.role.name,
'role_id' => e.role.id,
'course_section_id' => e.course_section_id,
'course_id' => e.course_id,
'user' => {
'name' => e.user.name,
'sortable_name' => e.user.sortable_name,
'short_name' => e.user.short_name,
'id' => e.user.id,
'created_at' => e.user.created_at.iso8601
},
'html_url' => course_user_url(@course, e.user),
'associated_user_id' => nil,
'updated_at' => e.updated_at.xmlschema,
'created_at' => e.created_at.xmlschema,
'start_at' => nil,
'end_at' => nil,
'last_activity_at' => nil,
'last_attended_at' => nil,
'total_activity_time' => 0
}
h['grades'] = {
'html_url' => course_student_grades_url(@course, e.user),
'final_score' => nil,
'current_score' => nil,
'final_grade' => nil,
'current_grade' => nil,
} if e.student?
h
end
link_header = response.headers['Link'].split(',')
expect(link_header[0]).to match /page=first&per_page=1/ # current page
md = link_header[1].match(/page=(bookmark.*)&per_page=1/) # next page
bookmark = md[1]
expect(bookmark).to be_present
expect(link_header[2]).to match /page=first&per_page=1/ # first page
expect(json).to eql [enrollments[0]]
shared_examples_for 'numeric pagination' do
it "should properly paginate" do
json = api_call(:get, "#{@path}?page=1&per_page=1", @params.merge(:page => 1.to_param, :per_page => 1.to_param))
enrollments = %w{observer student ta teacher}.inject([]) { |res, type|
res = res + @course.send("#{type}_enrollments").preload(:user)
}.map do |e|
h = {
'root_account_id' => e.root_account_id,
'limit_privileges_to_course_section' => e.limit_privileges_to_course_section,
'enrollment_state' => e.workflow_state,
'id' => e.id,
'user_id' => e.user_id,
'type' => e.type,
'role' => e.role.name,
'role_id' => e.role.id,
'course_section_id' => e.course_section_id,
'course_id' => e.course_id,
'user' => {
'name' => e.user.name,
'sortable_name' => e.user.sortable_name,
'short_name' => e.user.short_name,
'id' => e.user.id,
'created_at' => e.user.created_at.iso8601
},
'html_url' => course_user_url(@course, e.user),
'associated_user_id' => nil,
'updated_at' => e.updated_at.xmlschema,
'created_at' => e.created_at.xmlschema,
'start_at' => nil,
'end_at' => nil,
'last_activity_at' => nil,
'last_attended_at' => nil,
'total_activity_time' => 0
}
h['grades'] = {
'html_url' => course_student_grades_url(@course, e.user),
'final_score' => nil,
'current_score' => nil,
'final_grade' => nil,
'current_grade' => nil,
} if e.student?
h
end
link_header = response.headers['Link'].split(',')
expect(link_header[0]).to match /page=1&per_page=1/ # current page
expect(link_header[1]).to match /page=2&per_page=1/ # next page
expect(link_header[2]).to match /page=1&per_page=1/ # first page
expect(link_header[3]).to match /page=2&per_page=1/ # last page
expect(json).to eql [enrollments[0]]
json = api_call(:get, "#{@path}?page=#{bookmark}&per_page=1", @params.merge(:page => bookmark, :per_page => 1.to_param))
link_header = response.headers['Link'].split(',')
expect(link_header[0]).to match /page=#{bookmark}&per_page=1/ # current page
expect(link_header[1]).to match /page=first&per_page=1/ # first page
expect(link_header[2]).to match /page=#{bookmark}&per_page=1/ # last page
expect(json).to eql [enrollments[1]]
json = api_call(:get, "#{@path}?page=2&per_page=1", @params.merge(:page => 2.to_param, :per_page => 1.to_param))
link_header = response.headers['Link'].split(',')
expect(link_header[0]).to match /page=2&per_page=1/ # current page
expect(link_header[1]).to match /page=1&per_page=1/ # prev page
expect(link_header[2]).to match /page=1&per_page=1/ # first page
expect(link_header[3]).to match /page=2&per_page=1/ # last page
expect(json).to eql [enrollments[1]]
end
end
it "should properly paginate with bookmarking not enabled" do
json = api_call(:get, "#{@path}?page=1&per_page=1", @params.merge(:page => 1.to_param, :per_page => 1.to_param))
enrollments = %w{observer student ta teacher}.inject([]) { |res, type|
res = res + @course.send("#{type}_enrollments").preload(:user)
}.map do |e|
h = {
'root_account_id' => e.root_account_id,
'limit_privileges_to_course_section' => e.limit_privileges_to_course_section,
'enrollment_state' => e.workflow_state,
'id' => e.id,
'user_id' => e.user_id,
'type' => e.type,
'role' => e.role.name,
'role_id' => e.role.id,
'course_section_id' => e.course_section_id,
'course_id' => e.course_id,
'user' => {
'name' => e.user.name,
'sortable_name' => e.user.sortable_name,
'short_name' => e.user.short_name,
'id' => e.user.id,
'created_at' => e.user.created_at.iso8601
},
'html_url' => course_user_url(@course, e.user),
'associated_user_id' => nil,
'updated_at' => e.updated_at.xmlschema,
'created_at' => e.created_at.xmlschema,
'start_at' => nil,
'end_at' => nil,
'last_activity_at' => nil,
'last_attended_at' => nil,
'total_activity_time' => 0
}
h['grades'] = {
'html_url' => course_student_grades_url(@course, e.user),
'final_score' => nil,
'current_score' => nil,
'final_grade' => nil,
'current_grade' => nil,
} if e.student?
h
end
link_header = response.headers['Link'].split(',')
expect(link_header[0]).to match /page=1&per_page=1/ # current page
expect(link_header[1]).to match /page=2&per_page=1/ # next page
expect(link_header[2]).to match /page=1&per_page=1/ # first page
expect(link_header[3]).to match /page=2&per_page=1/ # last page
expect(json).to eql [enrollments[0]]
shared_examples_for 'bookmarked pagination' do
it "should properly paginate" do
json = api_call(:get, "#{@path}?page=1&per_page=1", @params.merge(:page => 1.to_param, :per_page => 1.to_param))
enrollments = %w{observer student ta teacher}.inject([]) { |res, type|
res = res + @course.send("#{type}_enrollments").preload(:user)
}.map do |e|
h = {
'root_account_id' => e.root_account_id,
'limit_privileges_to_course_section' => e.limit_privileges_to_course_section,
'enrollment_state' => e.workflow_state,
'id' => e.id,
'user_id' => e.user_id,
'type' => e.type,
'role' => e.role.name,
'role_id' => e.role.id,
'course_section_id' => e.course_section_id,
'course_id' => e.course_id,
'user' => {
'name' => e.user.name,
'sortable_name' => e.user.sortable_name,
'short_name' => e.user.short_name,
'id' => e.user.id,
'created_at' => e.user.created_at.iso8601
},
'html_url' => course_user_url(@course, e.user),
'associated_user_id' => nil,
'updated_at' => e.updated_at.xmlschema,
'created_at' => e.created_at.xmlschema,
'start_at' => nil,
'end_at' => nil,
'last_activity_at' => nil,
'last_attended_at' => nil,
'total_activity_time' => 0
}
h['grades'] = {
'html_url' => course_student_grades_url(@course, e.user),
'final_score' => nil,
'current_score' => nil,
'final_grade' => nil,
'current_grade' => nil,
} if e.student?
h
end
link_header = response.headers['Link'].split(',')
expect(link_header[0]).to match /page=first&per_page=1/ # current page
md = link_header[1].match(/page=(bookmark.*)&per_page=1/) # next page
bookmark = md[1]
expect(bookmark).to be_present
expect(link_header[2]).to match /page=first&per_page=1/ # first page
expect(json).to eql [enrollments[0]]
json = api_call(:get, "#{@path}?page=2&per_page=1", @params.merge(:page => 2.to_param, :per_page => 1.to_param))
link_header = response.headers['Link'].split(',')
expect(link_header[0]).to match /page=2&per_page=1/ # current page
expect(link_header[1]).to match /page=1&per_page=1/ # prev page
expect(link_header[2]).to match /page=1&per_page=1/ # first page
expect(link_header[3]).to match /page=2&per_page=1/ # last page
expect(json).to eql [enrollments[1]]
json = api_call(:get, "#{@path}?page=#{bookmark}&per_page=1", @params.merge(:page => bookmark, :per_page => 1.to_param))
link_header = response.headers['Link'].split(',')
expect(link_header[0]).to match /page=#{bookmark}&per_page=1/ # current page
expect(link_header[1]).to match /page=first&per_page=1/ # first page
expect(link_header[2]).to match /page=#{bookmark}&per_page=1/ # last page
expect(json).to eql [enrollments[1]]
end
end
context 'with normal settings' do
it_behaves_like 'numeric pagination'
context 'with developer key pagination override' do
before do
global_id = Shard.global_id_for(DeveloperKey.default.id)
Setting.set("pagination_override_key_list", global_id.to_s)
end
it_behaves_like 'numeric pagination'
end
end
context 'with bookmark flag enabled' do
before { Account.default.enable_feature!(:bookmarking_for_enrollments_index) }
it_behaves_like 'bookmarked pagination'
context 'with developer key pagination override' do
before do
global_id = Shard.global_id_for(DeveloperKey.default.id)
Setting.set("pagination_override_key_list", global_id.to_s)
end
it_behaves_like 'numeric pagination'
end
end
end