canvas-lms/config/routes.rb

1905 lines
100 KiB
Ruby
Raw Normal View History

full_path_glob = '(/*full_path)'
# allow plugins to prepend routes
Dir["{gems,vendor}/plugins/*/config/pre_routes.rb"].each { |pre_routes|
load pre_routes
}
CanvasRails::Application.routes.draw do
resources :submission_comments, only: :destroy
resources :epub_exports, only: [:index]
get 'inbox' => 'context#inbox'
get 'oauth/redirect_proxy' => 'oauth_proxy#redirect_proxy'
get 'conversations/unread' => 'conversations#index', as: :conversations_unread, redirect_scope: 'unread'
get 'conversations/starred' => 'conversations#index', as: :conversations_starred, redirect_scope: 'starred'
get 'conversations/sent' => 'conversations#index', as: :conversations_sent, redirect_scope: 'sent'
get 'conversations/archived' => 'conversations#index', as: :conversations_archived, redirect_scope: 'archived'
get 'conversations/find_recipients' => 'search#recipients'
get 'search/recipients' => 'search#recipients'
post 'conversations/mark_all_as_read' => 'conversations#mark_all_as_read'
post 'conversations/watched_intro' => 'conversations#watched_intro'
get 'conversations/batches' => 'conversations#batches', as: :conversation_batches
post 'conversations/toggle_new_conversations' => 'conversations#toggle_new_conversations', as: :toggle_new_conversations
resources :conversations, only: [:index, :show, :update, :create, :destroy] do
post :add_recipients
post :add_message
post :remove_messages
end
2015-06-26 03:35:25 +08:00
post "/external_auth_observers/redirect_login" => 'login/external_auth_observers#redirect_login', as: :external_auth_validation
Register Parents and Add Observees when configured for SAML authentication Fixes PFS-1084 Parent Registration: When a Saml config is designated for Parent Registration the parent signing up will be redirected to a Saml login page where they will log in with their child's credentials. After login the child user's Saml session will be ended and the parent registration process will complete. Parent Adding Student: When a Saml config is designated for Parent Registration the parent adding another observee will be redirected to a Saml login page where they will log in with their child's credentials. After login the child user's Saml session will be ended and the observee creation process will complete. --------------------------------------- TEST PLAN: SETUP: 1) In your account settings check the box for 'Self Registration' (and either of the sub-options) 2) Add the following users to your account (these will be the students): billyjoel eltonjohn 3) In Authentication Settings add a SAML authentication service and enter the following fields (I've set up a remote SAML Idp): IdP Entity ID: http://107.170.212.143/saml2/idp/metadata.php Log On URL: http://107.170.212.143/simplesaml/saml2/idp/SSOService.php Log Out URL: http://107.170.212.143/simplesaml/saml2/idp/SingleLogoutService.php Certificate Fingerprint: 9C:11:68:93:95:CD:18:01:EC:52:2B:9E:22:7F:73:55:ED:6D:82:D4 Parent Registration: check TEST: Parent Registration: * Go to '/login/canvas' * Click on the signup banner * sign up as a parent for billyjoel or eltonjohn (on SAML login page the password for either user is: tantrum) Add Student: * Log in as a parent user w/ a Canvas Auth login * Go to '/profile/observees' * Add Student 'billyjoel' or 'eltonjohn' Authentication Settings (new parent reg checkbox): * Go to Authentication Settings * Add a second SAML config * check the parent registration checkbox - it should warn that selection will deselect the other and in fact do so upon save. - the selected config is the one used for parent reg/add student --------------------------------------- Change-Id: Ief83b604fc252c88dbb912c56de65d8620fe802f Reviewed-on: https://gerrit.instructure.com/49691 Tested-by: Jenkins QA-Review: August Thornton <august@instructure.com> Reviewed-by: Jacob Fugal <jacob@instructure.com> Product-Review: Ethan Vizitei <evizitei@instructure.com>
2015-03-03 01:41:17 +08:00
2011-02-01 09:57:29 +08:00
# So, this will look like:
refactor user creation/invitations closes #5833 fixes #5573, #5572, #5753 * communication channels are now only unique within a single user * UserList changes * Always resolve pseudonym#unique_ids * Support looking up by SMS CCs * Option to either require e-mails match an existing CC, or e-mails that don't match a Pseudonym will always be returned unattached (relying on better merging behavior to not have a gazillion accounts created) * Method to return users, creating new ones (*without* a Pseudonym) if necessary. (can't create with a pseudonym, since Pseudonym#unique_id is still unique, I can't have multiple outstanding users with the same unique_id) * EnrollmentsFromUserList is mostly gutted, now using UserList's functionality directy. * Use UserList for adding account admins, removing the now unused Account#add_admin => User#find_by_email/User#assert_by_email codepath * Update UsersController#create to not worry about duplicate communication channels * Remove AccountsController#add_user, and just use UsersController#create * Change SIS::UserImporter to send out a merge opportunity e-mail if a conflicting CC is found (but still create the CC) * In /profile, don't worry about conflicting CCs (the CC confirmation process will now allow merging) * Remove CommunicationChannelsController#try_merge and #merge * For the non-simple case of CoursesController#enrollment_invitation redirect to /register (CommunicationsChannelController#confirm) * Remove CoursesController#transfer_enrollment * Move PseudonymsController#registration_confirmation to CommunicationChannelsController#confirm (have to be able to register an account without a Pseudonym yet) * Fold the old direct confirm functionality in, if there are no available merge opportunities * Allow merging the new account with the currently logged in user * Allow changing the Pseudonym#unique_id when registering a new account (since there might be conflicts) * Display a list of merge opportunities based on conflicting communication channels * Provide link(s) to log in as the other user, redirecting back to the registration page after login is complete (to complete the merge as the current user) * Remove several assert_* methods that are no longer needed * Update PseudonymSessionsController a bit to deal with the new way of dealing with conflicting CCs (especially CCs from LDAP), and to redirect back to the registration/confirmation page when attempting to do a merge * Expose the open_registration setting; use it to control if inviting users to a course is able to create new users Change-Id: If2f38818a71af656854d3bf8431ddbf5dcb84691 Reviewed-on: https://gerrit.instructure.com/6149 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Jacob Fugal <jacob@instructure.com>
2011-10-13 04:30:48 +08:00
# http://instructure.com/register/5R32s9iqwLK75Jbbj0
match 'register/:nonce' => 'communication_channels#confirm', as: :registration_confirmation, via: [:get, :post]
refactor user creation/invitations closes #5833 fixes #5573, #5572, #5753 * communication channels are now only unique within a single user * UserList changes * Always resolve pseudonym#unique_ids * Support looking up by SMS CCs * Option to either require e-mails match an existing CC, or e-mails that don't match a Pseudonym will always be returned unattached (relying on better merging behavior to not have a gazillion accounts created) * Method to return users, creating new ones (*without* a Pseudonym) if necessary. (can't create with a pseudonym, since Pseudonym#unique_id is still unique, I can't have multiple outstanding users with the same unique_id) * EnrollmentsFromUserList is mostly gutted, now using UserList's functionality directy. * Use UserList for adding account admins, removing the now unused Account#add_admin => User#find_by_email/User#assert_by_email codepath * Update UsersController#create to not worry about duplicate communication channels * Remove AccountsController#add_user, and just use UsersController#create * Change SIS::UserImporter to send out a merge opportunity e-mail if a conflicting CC is found (but still create the CC) * In /profile, don't worry about conflicting CCs (the CC confirmation process will now allow merging) * Remove CommunicationChannelsController#try_merge and #merge * For the non-simple case of CoursesController#enrollment_invitation redirect to /register (CommunicationsChannelController#confirm) * Remove CoursesController#transfer_enrollment * Move PseudonymsController#registration_confirmation to CommunicationChannelsController#confirm (have to be able to register an account without a Pseudonym yet) * Fold the old direct confirm functionality in, if there are no available merge opportunities * Allow merging the new account with the currently logged in user * Allow changing the Pseudonym#unique_id when registering a new account (since there might be conflicts) * Display a list of merge opportunities based on conflicting communication channels * Provide link(s) to log in as the other user, redirecting back to the registration page after login is complete (to complete the merge as the current user) * Remove several assert_* methods that are no longer needed * Update PseudonymSessionsController a bit to deal with the new way of dealing with conflicting CCs (especially CCs from LDAP), and to redirect back to the registration/confirmation page when attempting to do a merge * Expose the open_registration setting; use it to control if inviting users to a course is able to create new users Change-Id: If2f38818a71af656854d3bf8431ddbf5dcb84691 Reviewed-on: https://gerrit.instructure.com/6149 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Jacob Fugal <jacob@instructure.com>
2011-10-13 04:30:48 +08:00
# deprecated
get 'pseudonyms/:id/register/:nonce' => 'communication_channels#confirm', as: :registration_confirmation_deprecated
post 'confirmations/:user_id/re_send(/:id)' => 'communication_channels#re_send_confirmation', as: :re_send_confirmation, id: nil
match 'forgot_password' => 'pseudonyms#forgot_password', as: :forgot_password, via: [:get, :post]
get 'pseudonyms/:pseudonym_id/change_password/:nonce' => 'pseudonyms#confirm_change_password', as: :confirm_change_password
post 'pseudonyms/:pseudonym_id/change_password/:nonce' => 'pseudonyms#change_password', as: :change_password
2011-02-01 09:57:29 +08:00
# callback urls for oauth authorization processes
get 'oauth' => 'users#oauth'
get 'oauth_success' => 'users#oauth_success'
get 'mr/:id' => 'info#message_redirect', as: :message_redirect
get 'help_links' => 'info#help_links'
# These are just debug routes, but they make working on error pages easier,
# and it shouldn't matter if a client stumbles across them
get 'test_error' => 'info#test_error'
concern :question_banks do
resources :question_banks do
post :bookmark
post :reorder
get :questions
post :move_questions
resources :assessment_questions
end
end
2011-02-01 09:57:29 +08:00
concern :groups do
resources :groups
resources :group_categories, only: [:create, :update, :destroy]
get 'group_unassigned_members' => 'groups#unassigned_members'
end
Allows teacher to clone a group set. Option 'Clone Group Set' added in the group set cog wheel. When modifying group membership on a group that has submitted an assignment, teacher is alerted and given option of cloning group set or changing groups. fixes CNVS-19746 test plan: - as a teacher - navigate to a course - select 'People' and go to 'Groups' - create a new group set with groups and memberships - create a group assignment for that group set - as a student who is a member of a group of that group set - submit the assignment for their group - as a teacher - modify the memberships for that group set - for groups that have submissions - drag and drop a student - out of group into another group - out of group into 'Unassigned Students' - into group from another group - into group from 'Unassigned Students' - remove student using 'Remove' option in cog wheel - move student using 'Move To...' option in cog wheel - add student from 'Unassigned Students' using '+' option - when 'Clone Group Set' modal is displayed - select 'New Group Set' - memberships in original group set should not change - within cloned group set - should contain all groups, group leader, memberships, and membership limits from original group set - group membership modification should function as normal - selecting 'Change Groups' - group membership changes - delete assignment created for group set - group membership modification should function as normal - select 'Clone Group Set' option from group set cog wheel - should follow same expectations when 'New Group Set' is selected from alert - significant UI changes were made and should be tested - accessibility has been considered and should be tested - regression test on group Change-Id: I59276eca93f86d370f8658f5bdd0e9464f3fa061 Reviewed-on: https://gerrit.instructure.com/58753 Tested-by: Jenkins Reviewed-by: Andrew Butterfield <abutterfield@instructure.com> QA-Review: Steven Shepherd <sshepherd@instructure.com> Product-Review: Andraia Allsop <aallsop@instructure.com>
2015-07-18 04:07:01 +08:00
resources :group_categories do
member do
post 'clone_with_name'
end
end
concern :files do
resources :files, :except => [:new] do
get 'inline' => 'files#text_show', as: :text_inline
get 'download' => 'files#show', download: '1'
get 'download.:type' => 'files#show', as: :typed_download, download: '1'
get 'preview' => 'files#show', preview: '1'
post 'inline_view' => 'files#show', inline: '1'
get 'contents' => 'files#attachment_content', as: :attachment_content
file preview endpoint test plan: 0. upload the following types of files into a course, and note their IDs: a) document of some type (such as Word, PDF) b) image (such as JPEG, PNG, GIF) c) media (such as MP3, MP4, MOV) 1. enable canvadocs and google docs previews in account settings. 2. test the document preview by hitting the following in a new browser tab: /courses/X/files/Y/file_preview (where X is the course ID and Y is the file ID of the document file) - You should see a Canvadocs preview of the document. - There should be no Canvas chrome in the window, just the document preview. 3. disable canvadocs but leave google doc previews enabled. 4. hit the URL from step 2. - you should see a Google preview of the document 5. disable Google docs previews. 6. hit the URL from step 2. - you should see a message indicating that no preview is available, with a link to download the file. 7. hit the URL from step 2, but substitute the file ID with the ID of an image instead of a document. - you should see the image (and nothing else). 8. hit the URL from step 2, but substitute the file ID with the ID of a media file. - You should see a functioning media player (or a message indicating the media has not been converted yet) 9. add a document to a module, and set a "must view" completion requirement 10. use this endpoint to preview the document, and confirm that the module completion requirement is fulfilled fixes CNVS-15827 Change-Id: Id0ecaa7f003248cb3d8f163e48c3b16631ee59cf Reviewed-on: https://gerrit.instructure.com/42438 Reviewed-by: Ryan Shaw <ryan@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Jahnavi Yetukuri <jyetukuri@instructure.com> Product-Review: Cosme Salazar <cosme@instructure.com>
2014-10-09 05:27:45 +08:00
get 'file_preview' => 'file_previews#show'
collection do
get "folder#{full_path_glob}" => 'files#react_files', format: false
get "search" => 'files#react_files', format: false
get :quota
post :reorder
end
get ':file_path' => 'files#show_relative', as: :relative_path, file_path: /.+/ #needs to stay below react_files route
end
end
concern :file_images do
get 'images' => 'files#images'
end
concern :relative_files do
get 'file_contents/:file_path' => 'files#show_relative', as: :relative_file_path, file_path: /.+/
end
concern :folders do
resources :folders do
get :download
end
end
concern :media do
get 'media_download' => 'users#media_download'
end
concern :users do
get 'users' => 'context#roster'
get 'user_services' => 'context#roster_user_services'
get 'users/:user_id/usage' => 'context#roster_user_usage', as: :user_usage
get 'users/:id' => 'context#roster_user', as: :user
end
concern :announcements do
resources :announcements
post 'announcements/external_feeds' => 'announcements#create_external_feed'
delete 'announcements/external_feeds/:id' => 'announcements#destroy_external_feed', as: :announcements_external_feed
end
concern :discussions do
resources :discussion_topics, only: [:index, :new, :show, :edit, :destroy]
get 'discussion_topics/:id/:extras' => 'discussion_topics#show', as: :map, extras: /.+/
resources :discussion_entries
end
concern :pages do
resources :wiki_pages, path: :pages, except: [:update, :destroy, :new], constraints: { id: %r{[^\/]+} } do
get 'revisions' => 'wiki_pages#revisions', as: :revisions
end
get 'wiki' => 'wiki_pages#front_page', as: :wiki
get 'wiki/:id' => 'wiki_pages#show_redirect', id: /[^\/]+/
get 'wiki/:id/revisions' => 'wiki_pages#revisions_redirect', id: /[^\/]+/
get 'wiki/:id/revisions/:revision_id' => 'wiki_pages#revisions_redirect', id: /[^\/]+/
end
concern :conferences do
resources :conferences do
match :join, via: [:get, :post]
match :close, via: [:get, :post]
get :settings
end
end
2011-02-01 09:57:29 +08:00
# There are a lot of resources that are all scoped to the course level
# (assignments, files, wiki pages, user lists, forums, etc.). Many of
# these resources also apply to groups and individual users. We call
# courses, users, groups, or even accounts in this setting, "contexts".
# There are some helper methods like the before_filter :get_context in application_controller
# and the application_helper method :context_url to make retrieving
# these contexts, and also generating context-specific urls, easier.
resources :courses do
# DEPRECATED
get 'self_enrollment/:self_enrollment' => 'courses#self_enrollment', as: :self_enrollment
post 'self_unenrollment/:self_unenrollment' => 'courses#self_unenrollment', as: :self_unenrollment
post :restore
post :backup
post :unconclude
get :students
post :enrollment_invitation
# this needs to come before the users concern, or users/:id will preempt it
get 'users/prior' => 'context#prior_users', as: :prior_users
concerns :users
get :statistics
delete 'unenroll/:id' => 'courses#unenroll_user', as: :unenroll
post 'move_enrollment/:id' => 'courses#move_enrollment', as: :move_enrollment
delete 'unenroll/:id.:format' => 'courses#unenroll_user', as: :formatted_unenroll
post 'limit_user_grading/:id' => 'courses#limit_user', as: :limit_user_grading
delete 'conclude_user/:id' => 'courses#conclude_user', as: :conclude_user_enrollment
post 'unconclude_user/:id' => 'courses#unconclude_user', as: :unconclude_user_enrollment
resources :sections, except: [:index, :edit, :new] do
get 'crosslist/confirm/:new_course_id' => 'sections#crosslist_check', as: :confirm_crosslist
post :crosslist
delete 'crosslist' => 'sections#uncrosslist', as: :uncrosslist
end
get 'undelete' => 'context#undelete_index', as: :undelete_items
post 'undelete/:asset_string' => 'context#undelete_item', as: :undelete_item
get "settings#{full_path_glob}", action: :settings
get :settings
get 'details' => 'courses#settings'
post :re_send_invitations
post :enroll_users
post :link_enrollment
post :update_nav
resource :gradebook do
post 'submissions_upload/:assignment_id' => 'gradebooks#submissions_zip_upload', as: :submissions_upload
collection do
get :change_gradebook_version
get :blank_submission
get :speed_grader
post :speed_grader_settings
get :history
post :update_submission
post :change_gradebook_column_size
post :save_gradebook_column_order
end
end
resource :gradebook_csv, only: [:show]
get 'gradebook2' => "gradebooks#gradebook2"
get 'attendance' => 'gradebooks#attendance'
get 'attendance/:user_id' => 'gradebooks#attendance', as: :attendance_user
2015-06-26 03:35:25 +08:00
# DEPRECATED old migration emails pointed the user to this url, leave so the controller can redirect
get 'imports/list' => 'content_imports#index', as: :import_list
# DEPRECATED
get 'imports' => 'content_imports#intro'
resource :gradebook_upload do
get 'data' => 'gradebook_uploads#data'
end
get 'grades' => 'gradebooks#grade_summary', id: nil
get 'grading_rubrics' => 'gradebooks#grading_rubrics'
get 'grades/:id' => 'gradebooks#grade_summary', as: :student_grades
sort assignments on course grades page allow sorting by assignment group, due date, module, and title on the course grades page. also, store the user's sort preferences and remember that preference on subsequent page loads. closes CNVS-21660 test plan: - as a student, go to the /courses/:course_id/grades page. - verify there is a dropdown to sort assignments by due date and title. the first time you visit this page, the dropdown option should default to ordering by due date. verify each option correctly sorts the assignments. - if the course has any Modules, there should be an option to sort by Module. if the course does not have any Modules, there should not be a Module sort option. - if the course has assignments that belong to different Assignment Groups, there should be an option to sort by Assignment Group. if the course does not have any assignments, or if all of the course's assignments belong to the same Assignment Group, there should not be an Assignment Group sort option. - select any option besides 'Due Date'. next, leave the page and return back to the page. verify the selected dropdown option matches the option you selected before leaving the page. - repeat the steps above while logged in as a teacher, TA, student view student, and admin. when logged in as a teacher, TA, or admin, the url will be /courses/:course_id/grades/ :student_id - verify the dropdown is accessible - note: if a student is enrolled in multiple courses, the dropdown for the sort order should be on the right-hand side of the /courses/:course_id/grades page (and the dropdown for the course selection should be on the left-hand side). if a student is only enrolled in one course, the dropdown for sort order should be on the left-hand side of the page. Change-Id: Idbcbea2d25051cb5d933bfb395daebeedc630855 Reviewed-on: https://gerrit.instructure.com/69419 Reviewed-by: Derek Bender <djbender@instructure.com> Tested-by: Jenkins QA-Review: KC Naegle <knaegle@instructure.com> Product-Review: Spencer Olson <solson@instructure.com>
2015-12-22 12:35:21 +08:00
post 'save_assignment_order' => 'gradebooks#save_assignment_order', as: :save_assignment_order
concerns :announcements
get 'calendar' => 'calendars#show2', as: :old_calendar
get :locks
concerns :discussions
resources :assignments do
get 'moderate' => 'assignments#show_moderate'
cleanup SubmissionsController#show fixes CNVS-25767 - Simplifies SubmissionsController#show & adds test coverage. - Adds Submissions::DownloadsController#show to handle submission download functionality. - Adds Submissions::PreviewsController#show to handle submission preview functionality. test plan: - As a teacher, add assignments for each online submission type: Text Entry, Website URL & File Uploads. - As a student, provide a submission for each of these assignments. Provide two submissions for at least one of the assignments. - As the student, view each of these submissions via the submission details page. URL path looks like: /courses/1/assignments/1/submissions/2, and can be accessed from assignment page. - Observe that the body of the submission shows up in the Submission Detail page. - Observe that for file uploads, the files can be downloaded. - As the teacher, access the speed grader for each submission. - Observe that the submission body appears in the speed grader. - Observe that, for file uploads, the files are displayed inline (this doesn't work for every media type and it will tell you as much if it's not supported). - Observe that if there are multiple files provided, the list of files appears in the left hand column, and the teacher can tolggle between them. - Observe that if the submission has multiple versions, in the left hand column there is a dropdown labeled 'Submission to view:', and toggling the selected datetime will change the submission that is displayed. - As the teacher viewing a submission in the speed grader, leave a comment in the right hand column, and attach a file. - As the student, view the submission details page. - Observe that there is a link to the fiel in the right hand column, and that the file can be downloaded. Change-Id: Ib3fff3909f47873b37c373e53ab26cb8176b94e1 Reviewed-on: https://gerrit.instructure.com/68559 Tested-by: Jenkins Reviewed-by: Mike Nomitch <mnomitch@instructure.com> QA-Review: Michael Hargiss <mhargiss@instructure.com> Product-Review: Jason Sparks <jsparks@instructure.com>
2015-12-04 00:15:27 +08:00
get 'submissions/:id', to: 'submissions/previews#show',
constraints: ->(request) do
request.query_parameters.key?(:preview) && request.format == :html
end
get 'submissions/:id', to: 'submissions/downloads#show',
constraints: ->(request) do
request.query_parameters.key?(:download)
end
resources :submissions do
post 'turnitin/resubmit' => 'submissions#resubmit_to_turnitin', as: :resubmit_to_turnitin
get 'turnitin/:asset_string' => 'submissions#turnitin_report', as: :turnitin_report
end
get :rubric
resource :rubric_association, path: :rubric do
resources :rubric_assessments, path: :assessments
2011-02-01 09:57:29 +08:00
end
get :peer_reviews
post :assign_peer_reviews
delete 'peer_reviews/:id' => 'assignments#delete_peer_review', as: :delete_peer_review
post 'peer_reviews/:id' => 'assignments#remind_peer_review', as: :remind_peer_review
post 'peer_reviews/users/:reviewer_id' => 'assignments#assign_peer_review', as: :assign_peer_review
put 'mute' => 'assignments#toggle_mute'
collection do
get :syllabus
get :submissions
2011-02-01 09:57:29 +08:00
end
member do
get :list_google_docs
2011-02-01 09:57:29 +08:00
end
end
resources :grading_standards, only: [:index, :create, :update, :destroy]
resources :assignment_groups do
post 'reorder' => 'assignment_groups#reorder_assignments', as: :reorder_assignments
collection do
post :reorder
end
end
get 'external_tools/sessionless_launch' => 'external_tools#sessionless_launch'
resources :external_tools do
get :resource_selection
get :homework_submission
get :finished
collection do
get :retrieve
get :homework_submissions
end
end
get 'lti/basic_lti_launch_request/:message_handler_id', controller: 'lti/message',
action: 'basic_lti_launch_request', as: :basic_lti_launch_request
get 'lti/tool_proxy_registration', controller: 'lti/message', action: 'registration', as: :tool_proxy_registration
get 'lti/tool_proxy_reregistration/:tool_proxy_id', controller: 'lti/message', action: 'reregistration',
as: :tool_proxy_reregistration
get 'lti/registration_return/:tool_proxy_uuid', controller: 'lti/message', action: 'registration_return',
as: :registration_return
resources :submissions
resources :calendar_events
concerns :files, :file_images, :relative_files, :folders
concerns :groups
concerns :pages
concerns :conferences
concerns :question_banks
post 'quizzes/publish' => 'quizzes/quizzes#publish'
post 'quizzes/unpublish' => 'quizzes/quizzes#unpublish'
post 'quizzes/:id/toggle_post_to_sis' => "quizzes/quizzes#toggle_post_to_sis"
resources :quizzes, controller: 'quizzes/quizzes' do
get :managed_quiz_data
get :submission_versions
get :history
get :statistics
get :read_only
get :submission_html
resources :quiz_submissions, controller: 'quizzes/quiz_submissions', path: :submissions do
collection do
put :backup
post :backup
end
member do
get :record_answer
post :record_answer
end
resources :events, controller: 'quizzes/quiz_submission_events', path: "log#{full_path_glob}"
end
post 'extensions/:user_id' => 'quizzes/quiz_submissions#extensions', as: :extensions
resources :quiz_questions, controller: 'quizzes/quiz_questions', path: :questions, only: [:create, :update, :destroy, :show]
resources :quiz_groups, controller: 'quizzes/quiz_groups', path: :groups, only: [:create, :update, :destroy] do
member do
post :reorder
end
end
match 'take' => 'quizzes/quizzes#show', take: '1', via: [:get, :post]
get 'take/questions/:question_id' => 'quizzes/quizzes#show', as: :question, take: '1'
get :moderate
get :lockdown_browser_required
end
resources :collaborations
get 'lti_collaborations' => 'collaborations#lti_index'
resources :gradebook_uploads
resources :rubrics
resources :rubric_associations do
post 'remind/:assessment_request_id' => 'rubric_assessments#remind', as: :remind_assessee
resources :rubric_assessments, path: 'assessments'
end
get 'outcomes/users/:user_id' => 'outcomes#user_outcome_results', as: :user_outcomes_results
resources :outcomes do
post 'alignments/reorder' => 'outcomes#reorder_alignments', as: :reorder_alignments
get 'alignments/:id' => 'outcomes#alignment_redirect', as: :alignment_redirect
post 'alignments' => 'outcomes#align', as: :align
delete 'alignments/:id' => 'outcomes#remove_alignment', as: :remove_alignment
get 'results' => 'outcomes#outcome_results'
get 'results/:id' => 'outcomes#outcome_result', as: :result
get :details
collection do
get :list
post :add_outcome
end
end
resources :outcome_groups, only: [:create, :update, :destroy] do
post :reorder
end
resources :context_modules, path: :modules do
post 'items' => 'context_modules#add_item', as: :add_item
post 'reorder' => 'context_modules#reorder_items', as: :reorder
post 'collapse' => 'context_modules#toggle_collapse', as: :toggle_collapse
get 'prerequisites/:code' => 'context_modules#content_tag_prerequisites_needing_finishing', as: :prerequisites_needing_finishing
get 'items/last' => 'context_modules#module_redirect', as: :last_redirect, last: 1
get 'items/first' => 'context_modules#module_redirect', as: :first_redirect, first: 1
collection do
post :reorder
get :progressions
end
end
resources :content_exports, only: [:create, :index, :destroy, :show]
get 'modules/items/assignment_info' => 'context_modules#content_tag_assignment_data', as: :context_modules_assignment_info
get 'modules/items/:id' => 'context_modules#item_redirect', as: :context_modules_item_redirect
get 'modules/items/sequence/:id' => 'context_modules#item_details', as: :context_modules_item_details
delete 'modules/items/:id' => 'context_modules#remove_item', as: :context_modules_remove_item
put 'modules/items/:id' => 'context_modules#update_item', as: :context_modules_update_item
get 'confirm_action' => 'courses#confirm_action'
get :copy, as: :start_copy
post 'copy' => 'courses#copy_course', as: :copy_course
concerns :media
get 'user_notes' => 'user_notes#user_notes'
get 'details/sis_publish' => 'courses#sis_publish_status', as: :sis_publish_status
post 'details/sis_publish' => 'courses#publish_to_sis', as: :publish_to_sis
resources :user_lists, only: :create
post 'reset' => 'courses#reset_content'
resources :alerts
post :student_view
delete 'student_view' => 'courses#leave_student_view'
delete 'test_student' => 'courses#reset_test_student'
get 'content_migrations' => 'content_migrations#index'
get 'link_validator' => 'courses#link_validator', :as => :link_validator
get 'score_range_defaults', controller: 'conditional_release/score_range_defaults', action: 'index', as: :score_range_defaults
2011-02-01 09:57:29 +08:00
end
get 'quiz_statistics/:quiz_statistics_id/files/:file_id/download' => 'files#show', as: :quiz_statistics_download, download: '1'
resources :page_views, only: :update
post 'media_objects' => 'context#create_media_object', as: :create_media_object
get 'media_objects/kaltura_notifications' => 'context#kaltura_notifications', as: :kaltura_notifications
get 'media_objects/:id' => 'context#media_object_inline', as: :media_object
get 'media_objects/:id/redirect' => 'context#media_object_redirect', as: :media_object_redirect
get 'media_objects/:id/thumbnail' => 'context#media_object_thumbnail', as: :media_object_thumbnail
get 'media_objects/:media_object_id/info' => 'media_objects#show', as: :media_object_info
get 'media_objects/:media_object_id/media_tracks/:id' => 'media_tracks#show', as: :show_media_tracks
post 'media_objects/:media_object_id/media_tracks' => 'media_tracks#create', as: :create_media_tracks
delete 'media_objects/:media_object_id/media_tracks/:media_track_id' => 'media_tracks#destroy', as: :delete_media_tracks
get 'external_content/success/:service' => 'external_content#success', as: :external_content_success
get 'external_content/success/:service/:id' => 'external_content#success', as: :external_content_update
get 'external_content/retrieve/oembed' => 'external_content#oembed_retrieve', as: :external_content_oembed_retrieve
get 'external_content/cancel/:service' => 'external_content#cancel', as: :external_content_cancel
%w(account course group user).each do |context|
match "#{context.pluralize}/:#{context}_id/external_content/success/:service" => 'external_content#success', as: "#{context}_external_content_success", via: [:get, :post]
match "#{context.pluralize}/:#{context}_id/external_content/success/:service/:id" => 'external_content#success', as: "#{context}_external_content_update", via: [:get, :post]
end
2011-02-01 09:57:29 +08:00
# We offer a bunch of atom and ical feeds for the user to get
# data out of Instructure. The :feed_code attribute is keyed
# off of either a user, and enrollment, a course, etc. based on
# that item's uuid. In config/initializers/active_record.rb you'll
# find a feed_code method to generate the code, and in
2011-02-01 09:57:29 +08:00
# application_controller there's a get_feed_context to get it back out.
scope '/feeds' do
get 'calendars/:feed_code' => 'calendar_events_api#public_feed', as: :feeds_calendar
get 'calendars/:feed_code.:format' => 'calendar_events_api#public_feed', as: :feeds_calendar_format
get 'forums/:feed_code' => 'discussion_topics#public_feed', as: :feeds_forum
get 'forums/:feed_code.:format' => 'discussion_topics#public_feed', as: :feeds_forum_format
get 'topics/:discussion_topic_id/:feed_code' => 'discussion_entries#public_feed', as: :feeds_topic
get 'topics/:discussion_topic_id/:feed_code.:format' => 'discussion_entries#public_feed', as: :feeds_topic_format
get 'announcements/:feed_code' => 'announcements#public_feed', as: :feeds_announcements
get 'announcements/:feed_code.:format' => 'announcements#public_feed', as: :feeds_announcements_format
get 'courses/:feed_code' => 'courses#public_feed', as: :feeds_course
get 'courses/:feed_code.:format' => 'courses#public_feed', as: :feeds_course_format
get 'groups/:feed_code' => 'groups#public_feed', as: :feeds_group
get 'groups/:feed_code.:format' => 'groups#public_feed', as: :feeds_group_format
get 'enrollments/:feed_code' => 'courses#public_feed', as: :feeds_enrollment
get 'enrollments/:feed_code.:format' => 'courses#public_feed', as: :feeds_enrollment_format
get 'users/:feed_code' => 'users#public_feed', as: :feeds_user
get 'users/:feed_code.:format' => 'users#public_feed', as: :feeds_user_format
get 'eportfolios/:eportfolio_id.:format' => 'eportfolios#public_feed', as: :feeds_eportfolio
get 'conversations/:feed_code' => 'conversations#public_feed', as: :feeds_conversation
get 'conversations/:feed_code.:format' => 'conversations#public_feed', as: :feeds_conversation_format
2011-02-01 09:57:29 +08:00
end
resources :assessment_questions do
get 'files/:id/download' => 'files#assessment_question_show', as: :map, download: '1'
get 'files/:id/preview' => 'files#assessment_question_show', preview: '1'
get 'files/:id/:verifier' => 'files#assessment_question_show', as: :verified_file, download: '1'
2011-02-01 09:57:29 +08:00
end
resources :eportfolios, except: :index do
post :reorder_categories
post ':eportfolio_category_id/reorder_entries' => 'eportfolios#reorder_entries', as: :reorder_entries
resources :categories, controller: :eportfolio_categories
resources :entries, controller: :eportfolio_entries do
resources :page_comments, path: :comments, only: [:create, :destroy]
get 'files/:attachment_id' => 'eportfolio_entries#attachment', as: :view_file
get 'submissions/:submission_id' => 'eportfolio_entries#submission', as: :preview_submission
end
get :export, as: :export_portfolio
get ':category_name' => 'eportfolio_categories#show', as: :named_category
get ':category_name/:entry_name' => 'eportfolio_entries#show', as: :named_category_entry
end
resources :groups do
concerns :users
delete 'remove_user/:user_id' => 'groups#remove_user', as: :remove_user
post :add_user
get 'accept_invitation/:uuid' => 'groups#accept_invitation', as: :accept_invitation
get 'members' => 'groups#context_group_members'
get 'undelete' => 'context#undelete_index', as: :undelete_items
post 'undelete/:asset_string' => 'context#undelete_item', as: :undelete_item
concerns :announcements
concerns :discussions
resources :calendar_events
concerns :files, :file_images, :relative_files, :folders
resources :external_tools, only: :show do
collection do
get :retrieve
end
end
concerns :pages
concerns :conferences
concerns :media
resources :collaborations
get 'lti_collaborations' => 'collaborations#lti_index'
get 'calendar' => 'calendars#show2', as: :old_calendar
resources :external_tools do
get :finished
get :resource_selection
collection do
get :retrieve
end
end
end
resources :accounts do
get "settings#{full_path_glob}", action: :settings
get :settings
get :admin_tools
get 'search' => 'accounts#course_user_search', :as => :course_user_search
post 'account_users' => 'accounts#add_account_user', as: :add_account_user
delete 'account_users/:id' => 'accounts#remove_account_user', as: :remove_account_user
resources :grading_standards, only: [:index, :create, :update, :destroy]
get :statistics
get 'statistics/over_time/:attribute' => 'accounts#statistics_graph', as: :statistics_graph
get 'statistics/over_time/:attribute.:format' => 'accounts#statistics_graph', as: :formatted_statistics_graph
get :turnitin_confirmation
resources :permissions, controller: :role_overrides, only: [:index, :create] do
collection do
post :add_role
delete :remove_role
end
end
subaccount branding (creation and trickle down) fixes CNVS-21426 changes theme_editor routes to nest under accounts show correct brand_config for subaccount be able to theme subaccounts parent account changes trickle down to subs theme editor default values are that of parent account add not in preview text that subaccounts dont show test plan: simple creation - create a sub-account - brand it differently from parent - if you go to courses belonging to this subaccount, it gets their css - if you go to courses belonging to the parent you get the parent css - if you go to a user dashboard you get the parent branding (maybe we can add smarts to this later in case you only are in the subaccount?) trickle down - rebrand two values on the parent - one that the subaccount explicitly sets - and one that doesnt - apply this config on the parent - wait a little and go to the child account - its theme inherits values for the parent, but... if it explicitly sets those values itself then it doesnt inherit it - go to the editor for the subaccount - the placeholder values are those of the parent account (or the canvas default if the parent hasnt set it) - test trickle down with a sub-account and a sub-sub-account still to do on different patch sets: - account settings to allow subaccount branding - show the progress of all the child compilation Change-Id: Iaddba7036f564965427807c2fd8b0a6a5d524366 Reviewed-on: https://gerrit.instructure.com/61285 Reviewed-by: Rob Orton <rob@instructure.com> QA-Review: August Thornton <august@instructure.com> Tested-by: Jenkins Product-Review: Ryan Shaw <ryan@instructure.com> Product-Review: Colleen Palmer <colleen@instructure.com>
2015-08-15 02:42:55 +08:00
scope(controller: :brand_configs) do
get 'theme_editor', action: :new, as: :theme_editor
All of the stuff from the save_a_theme dev branch this commit is the result of squashing a bunch of others together. this is everything that was already on the dev/save_a_theme branch as well as the "Add specs" commit. I left the test plans from some of the squashed commits in case they are helpful for QA Test plan: - Recompile assets, restart Canvas and clear browser cache - Go to Admin > [Your school name] - Click on Themes in the context menu - You should now see a collections page with a theme card for all the themes you have in Theme Editor: http://screencast.com/t/lb5vozF7 - Note: it might be my database, but on my end, I don't see a theme card for my Canvas default theme. There are also some brand colors missing for my theme cards. I'll be interested to see if you hit the same thing. These are issues that we can resolve with Ryan when he is back. - You should be able to click on the Apply and Delete buttons and see the confirm-overlays. We still need final copy for these. Test plan: - Go to your institution's Settings page and click Themes on the context menu. - You should now see a page listing all the default and user-created themes in your Canvas installation. - Clicking on each theme will open it inside theme editor. - The current/active theme will be correctly styled with a green outline change redirect targets and messages in theme editor test plan: exiting theme editor should redirect you back to the /accounts/x/themes page instead of /acounts/x make room for footer in theme editor test plan: in theme editor, scroll the preview to the bottom you should be able to scroll all the way, without having the bottom cut off by the footer remove "theme editor" button from account user/course search this is not needed since "Themes" now shows up in the left nav. test plan: turn on the 'Course and User Search' feature flag go to accounts/x you should not see a "theme editor" button on the right aka, not like this: http://cl.ly/2G2C3p3s3n0C fix "Exit" button in theme editor we were warning "you will lose unsaved changes" even when you hand not made any changes add specs to "Save A theme" stuff closes: CNVS-27961 test plan: do a whole regression test on the theme editor don't show both "k12 theme" and "canvas default" as options fixes: CNVS-25495 description (and test plan): if you are a k12 school, rather than seeing both "Canvas Default" and "K12 Theme" as options on the tiles of system themes to start from, you should now just see "Canvas Default". if you pick that, it should show the k12 theme. Change-Id: I5c2512e576dcb2aedaa899e17080d9c106e159ca Reviewed-on: https://gerrit.instructure.com/78163 Tested-by: Jenkins Reviewed-by: Rob Orton <rob@instructure.com> Product-Review: Ryan Shaw <ryan@instructure.com> QA-Review: Ryan Shaw <ryan@instructure.com>
2016-01-19 03:29:32 +08:00
get 'brand_configs', action: :index
subaccount branding (creation and trickle down) fixes CNVS-21426 changes theme_editor routes to nest under accounts show correct brand_config for subaccount be able to theme subaccounts parent account changes trickle down to subs theme editor default values are that of parent account add not in preview text that subaccounts dont show test plan: simple creation - create a sub-account - brand it differently from parent - if you go to courses belonging to this subaccount, it gets their css - if you go to courses belonging to the parent you get the parent css - if you go to a user dashboard you get the parent branding (maybe we can add smarts to this later in case you only are in the subaccount?) trickle down - rebrand two values on the parent - one that the subaccount explicitly sets - and one that doesnt - apply this config on the parent - wait a little and go to the child account - its theme inherits values for the parent, but... if it explicitly sets those values itself then it doesnt inherit it - go to the editor for the subaccount - the placeholder values are those of the parent account (or the canvas default if the parent hasnt set it) - test trickle down with a sub-account and a sub-sub-account still to do on different patch sets: - account settings to allow subaccount branding - show the progress of all the child compilation Change-Id: Iaddba7036f564965427807c2fd8b0a6a5d524366 Reviewed-on: https://gerrit.instructure.com/61285 Reviewed-by: Rob Orton <rob@instructure.com> QA-Review: August Thornton <august@instructure.com> Tested-by: Jenkins Product-Review: Ryan Shaw <ryan@instructure.com> Product-Review: Colleen Palmer <colleen@instructure.com>
2015-08-15 02:42:55 +08:00
post 'brand_configs', action: :create
delete 'brand_configs', action: :destroy
post 'brand_configs/save_to_account', action: :save_to_account
post 'brand_configs/save_to_user_session', action: :save_to_user_session
end
resources :role_overrides, only: [:index, :create] do
collection do
post :add_role
delete :remove_role
end
end
resources :terms, except: [:show, :new, :edit]
resources :sub_accounts
get :avatars
get :sis_import
resources :sis_imports, only: [:create, :show, :index], controller: :sis_imports_api
post 'users' => 'users#create', as: :add_user
get 'users/:user_id/delete' => 'accounts#confirm_delete_user', as: :confirm_delete_user
delete 'users/:user_id' => 'accounts#remove_user', as: :delete_user
clean up user "deletion" fixes CNVS-1552 any time the UI/API tries to "delete" a user, it should only be trying to remove it from some root account (the @domain_root_account if not otherwise specified). if that root account was the last root account the user was associated with, then the remnants of the user are fully deleted, but only then. leave User#destroy as a short-cut to delete the user from all their accounts at once, but should not be invoked directly from any UI/API actions. test-plan: PERMISSIONS being able to remove a user from an account entails being able to: - DELETE http://accounts-domain/users/:user - DELETE /accounts/:account/users/:user both should fail or succeed together * given - Sally who's an admin with the :manage_user_logins permission on one account (Account1) and a student on another account (Account2) - Bob who's a student on both accounts - Alice who's an admin on Account1 with greater permissions than Sally * Sally should: - see "Delete My Account" on her Account1 profile - not see "Delete My Account" on her Account2 profile - not see "Delete My Account" on Bob's Account1 profile - not see "Delete My Account" on Alice's Account1 profile - see "Delete from Account1" at /users/:sally - see "Delete from Account1" at /users/:bob - not see "Delete from Account2" at /users/:sally - not see "Delete from Account2" at /users/:bob - not see "Delete from Account1" at /users/:alice - be able to remove herself from Account1 - be able to remove Bob from Account1 - not be able to remove herself from Account2 - not be able to remove Bob from Account2 - not be able to remove Alice from Account1 * given Sally's Account1 pseudonym has a SIS ID but her Account2 pseudonym doesn't, Sally should: - no longer see "Delete My Account" on her Account1 profile - no longer see "Delete from Account1" at /users/:sally - still see "Delete from Account1" at /users/:bob - no longer be able to remove herself from Account1 - still be able to remove Bob from Account1 EFFECTS * as Sally, remove Bob from Account1 via DELETE http://account1-domain/users/:bob - Bob's pseudonyms, enrollments, etc. in Account1 should be removed - Bob's pseudonyms, enrollments, etc. in Account2 should be untouched * repeat using DELETE /accounts/:account1/users/:bob, with the same expectations Change-Id: Ib7612f95d1c7e4cca36d8486950565ec096b4ab1 Reviewed-on: https://gerrit.instructure.com/41591 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: August Thornton <august@instructure.com> Reviewed-by: Cody Cutrer <cody@instructure.com> Product-Review: Jacob Fugal <jacob@instructure.com>
2014-09-23 07:04:03 +08:00
# create/delete are handled by specific routes just above
resources :users, only: [:index, :new, :edit, :show, :update]
resources :account_notifications, only: [:create, :update, :destroy]
concerns :announcements
resources :submissions
delete 'authentication_providers' => 'account_authorization_configs#destroy_all', as: :remove_all_authentication_providers
refactor views for unified AAC administration closes CNVS-20076 First, pull a presenter out of the AAC index This thing needs more flexibility before introducing multiple OAuth connectors. This commit adds a couple characterization specs for the AAC controller, then drives out a presenter to pull as much logic and config out of the nested views as possible. Then, this commit refactors the previously-somewhat-bespoke-and-presumptive sac configuration into a workflow that shows each aac in turn according to it's type, creating forms for each type at the bottom, and showing the relevant form for a new one based on selection on the right. Have regression tested in the browser to the level of CRUD functionality, but also deserves solid QA for SSO functionality post-configuration. DONE: -successful CAS creation/editing/deletion -successful LDAP creation/editing/deletion -proper differentiation between LDAP primary and secondary -proper SAML creation/editing -move away from "update_all" deprecated endpoint -Selenium Spec fixes -ensure discovery URL and debugging workflows for saml -remove duplication from views -tear down old JS workflow -apply appropriate tests for new behavior -remove presenter methods that are no longer valuable -Moved change_password_url and login_handle_name -up to account settings, removed them from AACs, and built -migrations to manage the transition. -Found and fixed all references to change_password_url on AACs -Found and fixes all references to login_handle_name on AACs -add datafixup for migrating AAC data to account settings -unify repetative individual files into single form delcarations \o/ -remove old SAML editing js -Make sure SAML still works -Make LDAP partial flow just like SAML/CAS -Unify position information across all types -update "acts_as_list" to support STI classes -move discovery URL into account auth form -remove discover URL js management -Unify form generation between new/existing aacs -deprecate discovery url API endpoints -update docs for authorization settings to deprecate their usage in AAC api and redirect their values to current settings for now -make delete links non-js-y to stop this silly page refresh on api completion -make form submissions actually submit the form rather than do this silly page refresh on api completion -See if anything needs “Edit Details” button, remove if not -Wire up removing account settings by blanking out form -Removed "cancel" button from form because fields are always open -placate gergich -Test removing config info -Test population fixup on real data -write docs for authorization settings -fix existing specs -fix routing and docs to not break doc generation -fix stupid jenkins task that thinks it can’t see controls -re-fix selenium -fix saml debugging workflow -write tests for acts_as_list behavior -write tests for authorization settings -remove auth_info types of things -clean up and unify styles where possible TEST PLAN: Regression test creating/deleting/editing and logging in with SSO solutions for CAS, LDAP, and SAML. Should be no functional behavior modification, though workflow will be a little more unified between the 3 currently supported types (each one will require using the menu in the right sidebar to add a new AAC). Also test setting and deleting account settings through the form underneath the configs when there are AACs in existence. Finally, make sure that the SAML Debugging workflow still works. Change-Id: I448db10185512d1b9469c2a425be0a3bcf9e6ebf Reviewed-on: https://gerrit.instructure.com/53448 Tested-by: Jenkins Reviewed-by: Cody Cutrer <cody@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Ethan Vizitei <evizitei@instructure.com>
2015-04-28 05:23:04 +08:00
put 'sso_settings' => 'account_authorization_configs#update_sso_settings',
as: :update_sso_settings
resources :authentication_providers, controller: :account_authorization_configs, only: [:index, :create, :update, :destroy]
get 'test_ldap_connections' => 'account_authorization_configs#test_ldap_connection'
get 'test_ldap_binds' => 'account_authorization_configs#test_ldap_bind'
get 'test_ldap_searches' => 'account_authorization_configs#test_ldap_search'
match 'test_ldap_logins' => 'account_authorization_configs#test_ldap_login', via: [:get, :post]
get 'saml_testing' => 'account_authorization_configs#saml_testing'
get 'saml_testing_stop' => 'account_authorization_configs#saml_testing_stop'
get 'external_tools/sessionless_launch' => 'external_tools#sessionless_launch'
resources :external_tools do
get :finished
get :resource_selection
collection do
get :retrieve
end
end
get 'lti/basic_lti_launch_request/:message_handler_id', controller: 'lti/message',
action: 'basic_lti_launch_request', as: :basic_lti_launch_request
get 'lti/tool_proxy_registration', controller: 'lti/message', action: 'registration', as: :tool_proxy_registration
get 'lti/tool_proxy_reregistration/:tool_proxy_id', controller: 'lti/message', action: 'reregistration',
as: :tool_proxy_reregistration
get 'lti/registration_return/:tool_proxy_uuid', controller: 'lti/message', action: 'registration_return',
as: :registration_return
get 'outcomes/users/:user_id' => 'outcomes#user_outcome_results', as: :user_outcomes_results
resources :outcomes do
get 'results' => 'outcomes#outcome_results'
get 'results/:id' => 'outcomes#outcome_result', as: :result
get 'alignments/:id' => 'outcomes#alignment_redirect', as: :alignment_redirect
get :details
collection do
get :list
post :add_outcome
end
end
resources :outcome_groups, only: [:create, :update, :destroy] do
post :reorder
end
resources :rubrics
resources :rubric_associations do
resources :rubric_assessments, path: 'assessments'
end
concerns :files, :file_images, :relative_files, :folders
concerns :media
concerns :groups
resources :outcomes
get :courses
get 'courses/:id' => 'accounts#courses_redirect', as: :courses_redirect
get 'user_notes' => 'user_notes#user_notes'
resources :alerts
resources :question_banks do
post :bookmark
post :reorder
get :questions
post :move_questions
resources :assessment_questions
end
resources :user_lists, only: :create
member do
get :statistics
end
resources :developer_keys, only: :index
2011-02-01 09:57:29 +08:00
end
get 'images/users/:user_id' => 'users#avatar_image', as: :avatar_image
get 'images/thumbnails/:id/:uuid' => 'files#image_thumbnail', as: :thumbnail_image
get 'images/thumbnails/show/:id/:uuid' => 'files#show_thumbnail', as: :show_thumbnail_image
post 'images/users/:user_id/report' => 'users#report_avatar_image', as: :report_avatar_image
put 'images/users/:user_id' => 'users#update_avatar_image', as: :update_avatar_image
get 'all_menu_courses' => 'users#all_menu_courses'
get 'grades' => 'users#grades'
feature flag for 'All Grading Periods' totals Add grading period dropdowns on the 'grades' page, and add a "Display Totals for 'All Grading Periods'" feature flag. By default, the feature will be turned 'off'. When the feature is 'off': - Totals will not display in the gradebook or the 'student grades' page when the 'All Grading Periods' option is selected. - The grading period dropdowns on the 'grades' page will not have an 'All Grading Periods' option. When the feature is 'on': - Totals will display in the gradebook and the 'student grades' page when the 'All Grading Periods' option is selected. - The grading period dropdowns on the 'grades' page will have an 'All Grading Periods' option. closes CNVS-23995 test plan: 1) as a teacher, enable the 'multiple grading periods' feature (do not enable the 'display totals for all grading periods' feature yet). a) verify the gradebook does not show totals when the 'All Grading Periods' option is selected. b) verify the 'student grades page' (courses/4/grades/9#tab-assignments) does not show totals, and the calculation of 'what-if' grades is disabled when the 'All Grading Periods' option is selected. c) turn on the 'display totals for all grading periods' feature. repeat steps a & b and verify that the totals now show up (and you can calculate what-if grades on the student grades page when 'All Grading Periods is selected') 2) sign in as a student that is enrolled in 3 courses: 1 course with MGP disabled, 1 course with MGP enabled and 'display all grading periods totals' (DAGPT) disabled, and 1 course with MGP enabled and DAGPT enabled. go the the 'grades' page (/grades). a) verify there is a grading period dropdown next to the totals for courses that have MGP enabled. verify there is not a grading period dropdown next to the total for the course with MGP disabled. b) verify that the current grading period is selected by default, if one exists. if a current grading period does not exist, then: - the dropdown next to the total for the course with DAGPT disabled should show 'Select a grading period' and the total grade should show as '--'. - the dropdown next to the total for the course with DAGPT enabled should show 'All Grading Periods' and the total grade should be displayed. c) verify clicking a grading period in the dropdown changes the total, and shows the correct total for that grading period. 3) repeat steps 2a-c, but sign in as an observer that is observing at least 3 students in 3 different courses(1 course with MGP disabled, 1 with MGP enabled and DAGPT disabled, and 1 course with MGP enabled + DAGPT enabled). 4) verify that the grading period dropdowns that were added are accessible. Note: The 'grades' page (/grades) will _always_ display the total for 'All Grading Periods' when signed in as a teacher. We are aware of this existing bug and we're working on a solution. Change-Id: If501b47aa57121d17d4e6629d1dcdbc8676971a2 Reviewed-on: https://gerrit.instructure.com/65847 Tested-by: Jenkins Reviewed-by: Strand McCutchen <smccutchen@instructure.com> Reviewed-by: Dylan Ross <dross@instructure.com> Reviewed-by: Derek Bender <djbender@instructure.com> QA-Review: Jason Carter <jcarter@instructure.com> Product-Review: Spencer Olson <solson@instructure.com>
2015-10-14 03:20:03 +08:00
get 'grades_for_student' => 'users#grades_for_student'
refactor PseudonymSessionsController fixes CNVS-20394 split it into appropriate concerns. main points are: * /login never renders a login form - it redirects forward to the default auth controller based on the first account authorization config (or discovery url on the account) * /login/canvas is the new home of the old login form. this form is never rendered in-situ anymore - other places that used to render it now redirect to /login (and then forward to here), reducing their knowledge of SSO * /login/ldap ends up at the same place (cause LDAP auth is handled transparently) * /login/cas and /login/saml redirect forward to the first SSO configuration of the appropriate type. /login/:auth_type/:id can be used to select a specific one * if an SSO fails, it redirects back to /login with flash[:error] set. this can forward to the discovery url appropriately, or render an error page appropriately (the old no_auto=1, but now it's not layered on top of the login partial that didn't show a login form) * ?canvas_login=1 is deprecated. just go directly to /login/canvas * /saml_consume, /saml_logout are deprecated. they are processed directly by /login/saml and /login/saml/logout * /login/:id is deprecated - it forwards to /login/:auth_type/:id as appropriate (presumably only saml, since that was the only one that previously should have been using these links) * OTP has been split into its own controller, and separated into multiple actions instead of one all-in-one action * /logout has been vastly simplified. the login controller should set session[:login_aac], and on logout it will check with that AAC for a url to redirect to after logout, instead of /login. SSO logout is handled by each controller if they support it test plan: * regression test the following functionality - * login with canvas auth * login with LDAP auth * login with SAML auth - and multiple SAMLs * login with CAS auth * MFA (configure, using, auto-setup) * Canvas as OAuth Provider flow * redirects to the login page when you're not logged in * failure of SAML/CAS (i.e. can't find user) show a decent error page and allows retry * "sticky" site admin auth (site admin is CAS/SAML, going directly to another domain logs you in with site admin) Change-Id: I1bb9d81a101939f812cbd5020e20749e883fdc0f Reviewed-on: https://gerrit.instructure.com/53220 QA-Review: August Thornton <august@instructure.com> Tested-by: Jenkins Reviewed-by: Ethan Vizitei <evizitei@instructure.com> Product-Review: Cody Cutrer <cody@instructure.com>
2015-05-01 03:58:57 +08:00
get 'login' => 'login#new'
delete 'logout' => 'login#destroy'
get 'logout' => 'login#logout_confirm'
get 'login/canvas' => 'login/canvas#new', as: :canvas_login
post 'login/canvas' => 'login/canvas#create'
# deprecated alias
post 'login' => 'login/canvas#create'
get 'login/ldap' => 'login/ldap#new'
post 'login/ldap' => 'login/ldap#create'
get 'login/cas' => 'login/cas#new'
get 'login/cas/:id' => 'login/cas#new', as: :cas_login
post 'login/cas' => 'login/cas#destroy', as: :cas_logout
post 'login/cas/:id' => 'login/cas#destroy'
get 'login/saml' => 'login/saml#new'
get 'login/saml/logout' => 'login/saml#destroy'
# deprecated alias
get 'saml_logout' => 'login/saml#destroy'
get 'login/saml/:id' => 'login/saml#new', as: :saml_login
Register Parents and Add Observees when configured for SAML authentication Fixes PFS-1084 Parent Registration: When a Saml config is designated for Parent Registration the parent signing up will be redirected to a Saml login page where they will log in with their child's credentials. After login the child user's Saml session will be ended and the parent registration process will complete. Parent Adding Student: When a Saml config is designated for Parent Registration the parent adding another observee will be redirected to a Saml login page where they will log in with their child's credentials. After login the child user's Saml session will be ended and the observee creation process will complete. --------------------------------------- TEST PLAN: SETUP: 1) In your account settings check the box for 'Self Registration' (and either of the sub-options) 2) Add the following users to your account (these will be the students): billyjoel eltonjohn 3) In Authentication Settings add a SAML authentication service and enter the following fields (I've set up a remote SAML Idp): IdP Entity ID: http://107.170.212.143/saml2/idp/metadata.php Log On URL: http://107.170.212.143/simplesaml/saml2/idp/SSOService.php Log Out URL: http://107.170.212.143/simplesaml/saml2/idp/SingleLogoutService.php Certificate Fingerprint: 9C:11:68:93:95:CD:18:01:EC:52:2B:9E:22:7F:73:55:ED:6D:82:D4 Parent Registration: check TEST: Parent Registration: * Go to '/login/canvas' * Click on the signup banner * sign up as a parent for billyjoel or eltonjohn (on SAML login page the password for either user is: tantrum) Add Student: * Log in as a parent user w/ a Canvas Auth login * Go to '/profile/observees' * Add Student 'billyjoel' or 'eltonjohn' Authentication Settings (new parent reg checkbox): * Go to Authentication Settings * Add a second SAML config * check the parent registration checkbox - it should warn that selection will deselect the other and in fact do so upon save. - the selected config is the one used for parent reg/add student --------------------------------------- Change-Id: Ief83b604fc252c88dbb912c56de65d8620fe802f Reviewed-on: https://gerrit.instructure.com/49691 Tested-by: Jenkins QA-Review: August Thornton <august@instructure.com> Reviewed-by: Jacob Fugal <jacob@instructure.com> Product-Review: Ethan Vizitei <evizitei@instructure.com>
2015-03-03 01:41:17 +08:00
get 'saml_observee' => 'login/saml#observee_validation', as: :saml_observee
refactor PseudonymSessionsController fixes CNVS-20394 split it into appropriate concerns. main points are: * /login never renders a login form - it redirects forward to the default auth controller based on the first account authorization config (or discovery url on the account) * /login/canvas is the new home of the old login form. this form is never rendered in-situ anymore - other places that used to render it now redirect to /login (and then forward to here), reducing their knowledge of SSO * /login/ldap ends up at the same place (cause LDAP auth is handled transparently) * /login/cas and /login/saml redirect forward to the first SSO configuration of the appropriate type. /login/:auth_type/:id can be used to select a specific one * if an SSO fails, it redirects back to /login with flash[:error] set. this can forward to the discovery url appropriately, or render an error page appropriately (the old no_auto=1, but now it's not layered on top of the login partial that didn't show a login form) * ?canvas_login=1 is deprecated. just go directly to /login/canvas * /saml_consume, /saml_logout are deprecated. they are processed directly by /login/saml and /login/saml/logout * /login/:id is deprecated - it forwards to /login/:auth_type/:id as appropriate (presumably only saml, since that was the only one that previously should have been using these links) * OTP has been split into its own controller, and separated into multiple actions instead of one all-in-one action * /logout has been vastly simplified. the login controller should set session[:login_aac], and on logout it will check with that AAC for a url to redirect to after logout, instead of /login. SSO logout is handled by each controller if they support it test plan: * regression test the following functionality - * login with canvas auth * login with LDAP auth * login with SAML auth - and multiple SAMLs * login with CAS auth * MFA (configure, using, auto-setup) * Canvas as OAuth Provider flow * redirects to the login page when you're not logged in * failure of SAML/CAS (i.e. can't find user) show a decent error page and allows retry * "sticky" site admin auth (site admin is CAS/SAML, going directly to another domain logs you in with site admin) Change-Id: I1bb9d81a101939f812cbd5020e20749e883fdc0f Reviewed-on: https://gerrit.instructure.com/53220 QA-Review: August Thornton <august@instructure.com> Tested-by: Jenkins Reviewed-by: Ethan Vizitei <evizitei@instructure.com> Product-Review: Cody Cutrer <cody@instructure.com>
2015-05-01 03:58:57 +08:00
post 'login/saml' => 'login/saml#create'
# deprecated alias; no longer advertised
post 'saml_consume' => 'login/saml#create'
refactor PseudonymSessionsController fixes CNVS-20394 split it into appropriate concerns. main points are: * /login never renders a login form - it redirects forward to the default auth controller based on the first account authorization config (or discovery url on the account) * /login/canvas is the new home of the old login form. this form is never rendered in-situ anymore - other places that used to render it now redirect to /login (and then forward to here), reducing their knowledge of SSO * /login/ldap ends up at the same place (cause LDAP auth is handled transparently) * /login/cas and /login/saml redirect forward to the first SSO configuration of the appropriate type. /login/:auth_type/:id can be used to select a specific one * if an SSO fails, it redirects back to /login with flash[:error] set. this can forward to the discovery url appropriately, or render an error page appropriately (the old no_auto=1, but now it's not layered on top of the login partial that didn't show a login form) * ?canvas_login=1 is deprecated. just go directly to /login/canvas * /saml_consume, /saml_logout are deprecated. they are processed directly by /login/saml and /login/saml/logout * /login/:id is deprecated - it forwards to /login/:auth_type/:id as appropriate (presumably only saml, since that was the only one that previously should have been using these links) * OTP has been split into its own controller, and separated into multiple actions instead of one all-in-one action * /logout has been vastly simplified. the login controller should set session[:login_aac], and on logout it will check with that AAC for a url to redirect to after logout, instead of /login. SSO logout is handled by each controller if they support it test plan: * regression test the following functionality - * login with canvas auth * login with LDAP auth * login with SAML auth - and multiple SAMLs * login with CAS auth * MFA (configure, using, auto-setup) * Canvas as OAuth Provider flow * redirects to the login page when you're not logged in * failure of SAML/CAS (i.e. can't find user) show a decent error page and allows retry * "sticky" site admin auth (site admin is CAS/SAML, going directly to another domain logs you in with site admin) Change-Id: I1bb9d81a101939f812cbd5020e20749e883fdc0f Reviewed-on: https://gerrit.instructure.com/53220 QA-Review: August Thornton <august@instructure.com> Tested-by: Jenkins Reviewed-by: Ethan Vizitei <evizitei@instructure.com> Product-Review: Cody Cutrer <cody@instructure.com>
2015-05-01 03:58:57 +08:00
# the callback URL for all OAuth1.0a based SSO
get 'login/oauth/callback' => 'login/oauth#create', as: :oauth_login_callback
# the callback URL for all OAuth2 based SSO
get 'login/oauth2/callback' => 'login/oauth2#create', as: :oauth2_login_callback
# ActionController::TestCase can't deal with aliased controllers when finding
# routes, so we let this route exist only for tests
get 'login/oauth2' => 'login/oauth2#new' if Rails.env.test?
get 'login/clever' => 'login/clever#new', as: :clever_login
# Clever gets their own callback, cause we have to add additional processing
# for their Instant Login feature
get 'login/clever/callback' => 'login/clever#create', as: :clever_callback
get 'login/clever/:id' => 'login/clever#new'
get 'login/facebook' => 'login/facebook#new', as: :facebook_login
get 'login/github' => 'login/github#new', as: :github_login
get 'login/google' => 'login/google#new', as: :google_login
get 'login/google/:id' => 'login/google#new'
get 'login/linkedin' => 'login/linkedin#new', as: :linkedin_login
Add Microsoft Login Commit from Siimpl Fixes OI-3, OI-4 test plan: * register an application with Microsoft * configure microsoft as an authentication source * login with microsoft * it should complain about a missing user for an ID * add that ID to your user * login again, it should work * delete microsoft authentication * reconfigure at /plugins/microsoft * add authentication again; this time it shouldn't let you configure the integration * login with microsoft again * change to email attribute * login and it should show your e-mail, instead of an opaque ID * change tenant to "organizations" * login with a regular Microsoft account * it should give an error about not being able to log in * login with an organization account (@instructure.com works) * it should show your email * change tenant to "consumers" * login with your regular Microsoft account; it should work * login with an organization account; it should give an error NOTE: Microsoft requires https. so if you're testing locally, and don't have https, you'll need to change oauth2_controller.rb and add (protocol: 'https') to both oauth2_login_callback_url calls; during the login flow it will redirect you back to the app over https; edit the url and connect to http and it will work Change-Id: I578df7c2865b8775752ead28a1153918cd24aaa6 Reviewed-on: https://gerrit.instructure.com/72971 Tested-by: Jenkins Reviewed-by: Andrew Butterfield <abutterfield@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Andrew Butterfield <abutterfield@instructure.com>
2016-02-19 02:53:10 +08:00
get 'login/microsoft' => 'login/microsoft#new'
get 'login/microsoft/:id' => 'login/microsoft#new', as: :microsoft_login
get 'login/openid_connect' => 'login/openid_connect#new'
get 'login/openid_connect/:id' => 'login/openid_connect#new', as: :openid_connect_login
get 'login/twitter' => 'login/twitter#new', as: :twitter_login
refactor PseudonymSessionsController fixes CNVS-20394 split it into appropriate concerns. main points are: * /login never renders a login form - it redirects forward to the default auth controller based on the first account authorization config (or discovery url on the account) * /login/canvas is the new home of the old login form. this form is never rendered in-situ anymore - other places that used to render it now redirect to /login (and then forward to here), reducing their knowledge of SSO * /login/ldap ends up at the same place (cause LDAP auth is handled transparently) * /login/cas and /login/saml redirect forward to the first SSO configuration of the appropriate type. /login/:auth_type/:id can be used to select a specific one * if an SSO fails, it redirects back to /login with flash[:error] set. this can forward to the discovery url appropriately, or render an error page appropriately (the old no_auto=1, but now it's not layered on top of the login partial that didn't show a login form) * ?canvas_login=1 is deprecated. just go directly to /login/canvas * /saml_consume, /saml_logout are deprecated. they are processed directly by /login/saml and /login/saml/logout * /login/:id is deprecated - it forwards to /login/:auth_type/:id as appropriate (presumably only saml, since that was the only one that previously should have been using these links) * OTP has been split into its own controller, and separated into multiple actions instead of one all-in-one action * /logout has been vastly simplified. the login controller should set session[:login_aac], and on logout it will check with that AAC for a url to redirect to after logout, instead of /login. SSO logout is handled by each controller if they support it test plan: * regression test the following functionality - * login with canvas auth * login with LDAP auth * login with SAML auth - and multiple SAMLs * login with CAS auth * MFA (configure, using, auto-setup) * Canvas as OAuth Provider flow * redirects to the login page when you're not logged in * failure of SAML/CAS (i.e. can't find user) show a decent error page and allows retry * "sticky" site admin auth (site admin is CAS/SAML, going directly to another domain logs you in with site admin) Change-Id: I1bb9d81a101939f812cbd5020e20749e883fdc0f Reviewed-on: https://gerrit.instructure.com/53220 QA-Review: August Thornton <august@instructure.com> Tested-by: Jenkins Reviewed-by: Ethan Vizitei <evizitei@instructure.com> Product-Review: Cody Cutrer <cody@instructure.com>
2015-05-01 03:58:57 +08:00
get 'login/otp' => 'login/otp#new', as: :otp_login
post 'login/otp/sms' => 'login/otp#send_via_sms', as: :send_otp_via_sms
post 'login/otp' => 'login/otp#create'
# deprecated redirect
get 'login/:id' => 'login#new'
delete 'users/:user_id/mfa' => 'login/otp#destroy', as: :disable_mfa
get 'file_session/clear' => 'login#clear_file_session', as: :clear_file_session
get 'register' => 'users#new'
get 'register_from_website' => 'users#new'
get 'enroll/:self_enrollment_code' => 'self_enrollments#new', as: :enroll
get 'services' => 'users#services'
get 'search/bookmarks' => 'users#bookmark_search', as: :bookmark_search
get 'search/rubrics' => 'search#rubrics'
get 'search/all_courses' => 'search#all_courses'
resources :users do
match 'masquerade', via: [:get, :post]
delete :delete
concerns :files, :file_images
resources :page_views, only: :index
resources :folders do
get :download
end
resources :calendar_events
get 'external_tools/:id' => 'users#external_tool', as: :external_tool
resources :rubrics
resources :rubric_associations do
resources :rubric_assessments, path: :assessments
end
resources :pseudonyms, except: :index
resources :question_banks, only: :index
get :assignments_needing_grading
get :assignments_needing_submitting
get :admin_merge
post :merge
get :grades
resources :user_notes
get :manageable_courses
get 'outcomes' => 'outcomes#user_outcome_results'
get 'teacher_activity/course/:course_id' => 'users#teacher_activity', as: :course_teacher_activity
get 'teacher_activity/student/:student_id' => 'users#teacher_activity', as: :student_teacher_activity
get :media_download
resources :messages, only: [:index, :create] do
get :html_message
end
2011-02-01 09:57:29 +08:00
end
get 'show_message_template' => 'messages#show_message_template'
get 'message_templates' => 'messages#templates'
resource :profile, controller: :profile, only: [:show, :update] do
resources :pseudonyms, except: :index
resources :tokens, except: :index
member do
put :update_profile
get :communication
put :communication_update
get :settings
get :observees
end
2011-02-01 09:57:29 +08:00
end
scope '/profile' do
post 'toggle_disable_inbox' => 'profile#toggle_disable_inbox'
get 'profile_pictures' => 'profile#profile_pics', as: :profile_pics
delete 'user_services/:id' => 'users#delete_user_service', as: :profile_user_service
post 'user_services' => 'users#create_user_service', as: :profile_create_user_service
2011-02-01 09:57:29 +08:00
end
get 'about/:id' => 'profile#show', as: :user_profile
resources :communication_channels
2011-02-01 09:57:29 +08:00
get '' => 'users#user_dashboard', as: 'dashboard'
get 'dashboard-sidebar' => 'users#dashboard_sidebar', as: :dashboard_sidebar
post 'users/toggle_recent_activity_dashboard' => 'users#toggle_recent_activity_dashboard'
get 'styleguide' => 'info#styleguide'
get sub account branding and custom css/includes working fixes: CNVS-24787 fixes: CNVS-23964 fixes: CNVS-23957 - Handle parent account custom css/js for new_styles test plan: * set up a root account, child account, and grandchild account * use theme editor to set a custom css/js file for each (eg: for css `* {color:red}` and for js 'console.log("from grandchild")` * make a course & a group in the grandchild account * load a page in that course and group and make sure you see grandchild account's branding, and root's, child's, and then grandchild's css loaded on the page (grandchild should be loaded last so you see it's css effects override root or child's and you should see the console.log from root then child then grandchild) * view a page in "child". it should have root and child's css/js but not grandchild * as a user that only has enrollments (account associations) in "child", go to the dashboard. you should see css/js for both root and child but not grandchild fixes: CNVS-25051 Opening Theme Editor for sub-accounts shows incorrect theme preview test plan: * Go to a sub-account in theme editor and change settings so the Branding is different and save. * the preview on the right should reflect your changes both after you "apply" and "save" (and not just show the preview of the root account's branding) fixes: CNVS-23406 - global JS and CSS files are being included when Global CSS/JavaScript includes is false test plan: * go to /accounts/self/, and go to theme editor and upload a css_override * see that that css is loaded on pages * back in root account settings disable Global CSS/JavaScript includes * check that the css is no longer loaded. * do the same thing checking a subaccount's custom css fixes: CNVS-25558 - load whole chain of custom css/js in native app api requests test plan: * make api request for a wiki page in course in a subaccount that has custom css/js within a root account that also has custom css/js * you should see both the root account's css/js and the child account's returned in the response to test grandchild js issue jeremyp found: * go to theme editor for a grandchild account * choose a js override file (like: `console.log('first')`) * preview & apply * you should see "first" in console * go back to theme editor, pick a new file (like: `console.log('second')`) * preview & apply * you should only see "second" in console. not "first" Change-Id: I8d9047948f5da94be41e0205844629a170f980af Reviewed-on: https://gerrit.instructure.com/68249 Reviewed-by: Simon Williams <simon@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> Tested-by: Jenkins Product-Review: Ryan Shaw <ryan@instructure.com>
2015-12-05 00:57:07 +08:00
get 'accounts/:account_id/theme-preview' => 'brand_configs#show'
get 'old_styleguide' => 'info#old_styleguide'
root to: 'users#user_dashboard', as: 'root', via: :get
# backwards compatibility with the old /dashboard url
get 'dashboard' => 'users#user_dashboard', as: :dashboard_redirect
2011-02-01 09:57:29 +08:00
# Thought this idea of having dashboard-scoped urls was a good idea at the
# time... now I'm not as big a fan.
resource :dashboard, only: [] do
resources :content_exports, path: :data_exports
end
2011-02-01 09:57:29 +08:00
scope '/dashboard' do
delete 'account_notifications/:id' => 'users#close_notification', as: :dashboard_close_notification
get 'eportfolios' => 'eportfolios#user_index', as: :dashboard_eportfolios
post 'comment_session' => 'services_api#start_kaltura_session', as: :dashboard_comment_session
delete 'ignore_stream_item/:id' => 'users#ignore_stream_item', as: :dashboard_ignore_stream_item
end
2011-02-01 09:57:29 +08:00
resources :plugins, only: [:index, :show, :update]
get 'calendar' => 'calendars#show2'
get 'calendar2' => 'calendars#show2'
get 'course_sections/:course_section_id/calendar_events/:id' => 'calendar_events#show', as: :course_section_calendar_event
get 'files' => 'files#index'
get "files/folder#{full_path_glob}", controller: 'files', action: 'react_files', format: false
get "files/search", controller: 'files', action: 'react_files', format: false
get 'files/s3_success/:id' => 'files#s3_success', as: :s3_success
get 'files/:id/public_url' => 'files#public_url', as: :public_url
get 'files/preflight' => 'files#preflight', as: :file_preflight
post 'files/pending' => 'files#create_pending', as: :file_create_pending
resources :assignments, only: :index do
resources :files, only: [] do
post 'inline_view' => 'files#show', inline: '1'
request scribd re-render when no preview available test plan: 1. work in an account with scribd enabled and google doc previews disabled (in console, add "-google_docs_previews" to the Accounts's allowed_services) 2. upload a scribd-previewable file type in the files tab (it needs to be a new file that is not already in the canvas instance) 3. make sure it previews properly (it may take a minute after uploading for the scribd rendering to complete) 4. delete the file 5. undelete the file (/courses/X/undelete) 6. reload the files tab, and click on the filename on the left side. - on the right, you should see a message like "the preview for this document is unavailable; please try again later". 7. reload the files tab again, then click on the filename. - if the scribd rendering has completed, you should see a scribd preview. if you don't, wait a few minutes and reload the files page again, to give scribd some time. 8. test other areas documents can be previewed. (it's permissible to simply delete the scribd_doc in the console via attachment.delete_scribd_doc, then try to preview, see that a "try again later" message appears, and the scribd preview appears in later page views.) a. documents embedded in rich text via the wiki sidebar b. student submissions, as viewed by the student ("submission details" button, "preview" icon) c. student submissions, as viewed by the teacher in SpeedGrader(TM) fixes CNVS-7019 Change-Id: I37be820a776637252e14b6a28a1be389b718ff9f Reviewed-on: https://gerrit.instructure.com/22438 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Bracken Mosbacker <bracken@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Matt Goodwin <mattg@instructure.com>
2013-07-17 06:02:44 +08:00
end
end
2011-02-01 09:57:29 +08:00
resources :appointment_groups, only: [:index, :show]
2011-02-01 09:57:29 +08:00
resources :errors, only: [:show, :index, :create], path: :error_reports
2011-02-01 09:57:29 +08:00
get 'health_check' => 'info#health_check'
2011-02-01 09:57:29 +08:00
get 'browserconfig.xml', to: 'info#browserconfig', defaults: { format: 'xml' }
post 'object_snippet' => 'context#object_snippet'
get 'saml2' => 'accounts#saml_meta_data'
get 'saml_meta_data' => 'accounts#saml_meta_data'
2011-02-01 09:57:29 +08:00
# Routes for course exports
get 'xsd/:version.xsd' => 'content_exports#xml_schema'
resources :jobs, only: [:index, :show] do
collection do
post 'batch_update'
end
end
2011-02-01 09:57:29 +08:00
get 'equation_images/:id' => 'equation_images#show', as: :equation_images, id: /.+/
# assignments at the top level (without a context) -- we have some specs that
# assert these routes exist, but just 404. I'm not sure we ever actually want
# top-level assignments available, maybe we should change the specs instead.
resources :assignments, only: [:index, :show]
resources :files, :except => [:new] do
get 'download' => 'files#show', download: '1'
end
resources :developer_keys, only: :index
resources :rubrics do
resources :rubric_assessments, path: :assessments
end
post 'selection_test' => 'external_content#selection_test'
scope '/quizzes/quiz_submissions/:quiz_submission_id', as: 'quiz_submission' do
concerns :files
end
get 'courses/:course_id/outcome_rollups' => 'outcome_results#rollups', as: 'course_outcome_rollups'
get 'terms_of_use' => 'legal_information#terms_of_use', as: 'terms_of_use_redirect'
get 'privacy_policy' => 'legal_information#privacy_policy', as: 'privacy_policy_redirect'
### API routes ###
# TODO: api routes can't yet take advantage of concerns for DRYness, because of
# the way ApiRouteSet works. For now we get around it by defining methods
# inline in the routes file, but getting concerns working would rawk.
ApiRouteSet::V1.draw(self) do
scope(controller: :courses) do
get 'courses', action: :index, as: 'courses'
put 'courses/:id', action: :update
get 'courses/:id', action: :show, as: 'course'
delete 'courses/:id', action: :destroy
post 'accounts/:account_id/courses', action: :create
get 'courses/:course_id/students', action: :students
get 'courses/:course_id/settings', action: :settings, as: 'course_settings'
put 'courses/:course_id/settings', action: :update_settings
get 'courses/:course_id/recent_students', action: :recent_students, as: 'course_recent_students'
get 'courses/:course_id/users', action: :users, as: 'course_users'
get 'courses/:course_id/collaborations', controller: :collaborations, action: :api_index, as: 'course_collaborations_index'
delete 'courses/:course_id/collaborations/:id', controller: :collaborations, action: :destroy
# this api endpoint has been removed, it was redundant with just courses#users
# we keep it around for backward compatibility though
get 'courses/:course_id/search_users', action: :users
get 'courses/:course_id/users/:id', action: :user, as: 'course_user'
get 'courses/:course_id/activity_stream', action: :activity_stream, as: 'course_activity_stream'
get 'courses/:course_id/activity_stream/summary', action: :activity_stream_summary, as: 'course_activity_stream_summary'
get 'courses/:course_id/todo', action: :todo_items
post 'courses/:course_id/preview_html', action: :preview_html
post 'courses/:course_id/course_copy', controller: :content_imports, action: :copy_course_content
get 'courses/:course_id/course_copy/:id', controller: :content_imports, action: :copy_course_status, as: :course_copy_status
get 'courses/:course_id/files', controller: :files, action: :api_index, as: 'course_files'
post 'courses/:course_id/files', action: :create_file, as: 'course_create_file'
get 'courses/:course_id/folders', controller: :folders, action: :list_all_folders, as: 'course_folders'
post 'courses/:course_id/folders', controller: :folders, action: :create
get 'courses/:course_id/folders/by_path/*full_path', controller: :folders, action: :resolve_path
get 'courses/:course_id/folders/by_path', controller: :folders, action: :resolve_path
get 'courses/:course_id/folders/:id', controller: :folders, action: :show, as: 'course_folder'
put 'accounts/:account_id/courses', action: :batch_update
post 'courses/:course_id/ping', action: :ping, as: 'course_ping'
get 'courses/:course_id/link_validation', action: :link_validation, as: 'course_link_validation'
post 'courses/:course_id/link_validation', action: :start_link_validation
post 'courses/:course_id/reset_content', :action => :reset_content
get 'users/:user_id/courses', action: :user_index
end
scope(controller: :account_notifications) do
post 'accounts/:account_id/account_notifications', action: :create, as: 'account_notification'
put 'accounts/:account_id/account_notifications/:id', action: :update, as: 'account_notification_update'
get 'accounts/:account_id/users/:user_id/account_notifications', action: :user_index, as: 'user_account_notifications'
get 'accounts/:account_id/users/:user_id/account_notifications/:id', action: :show, as: 'user_account_notification_show'
delete 'accounts/:account_id/users/:user_id/account_notifications/:id', action: :user_close_notification, as: 'user_account_notification'
end
scope(controller: :tabs) do
get "courses/:course_id/tabs", action: :index, as: 'course_tabs'
get "groups/:group_id/tabs", action: :index, as: 'group_tabs'
put "courses/:course_id/tabs/:tab_id", action: :update
end
scope(controller: :sections) do
get 'courses/:course_id/sections', action: :index, as: 'course_sections'
get 'courses/:course_id/sections/:id', action: :show, as: 'course_section'
get 'sections/:id', action: :show
post 'courses/:course_id/sections', action: :create
put 'sections/:id', action: :update
delete 'sections/:id', action: :destroy
post 'sections/:id/crosslist/:new_course_id', action: :crosslist
delete 'sections/:id/crosslist', action: :uncrosslist
end
scope(controller: :enrollments_api) do
get 'courses/:course_id/enrollments', action: :index, as: 'course_enrollments'
get 'sections/:section_id/enrollments', action: :index, as: 'section_enrollments'
get 'users/:user_id/enrollments', action: :index, as: 'user_enrollments'
get 'accounts/:account_id/enrollments/:id', action: :show, as: 'enrollment'
post 'courses/:course_id/enrollments', action: :create
post 'sections/:section_id/enrollments', action: :create
put 'courses/:course_id/enrollments/:id/reactivate', :action => :reactivate, :as => 'reactivate_enrollment'
delete 'courses/:course_id/enrollments/:id', action: :destroy
end
scope(controller: :terms_api) do
get 'accounts/:account_id/terms', action: :index, as: 'enrollment_terms'
end
scope(controller: :terms) do
post 'accounts/:account_id/terms', action: :create
put 'accounts/:account_id/terms/:id', action: :update
delete 'accounts/:account_id/terms/:id', action: :destroy
end
scope(controller: :authentication_audit_api) do
get 'audit/authentication/logins/:login_id', action: :for_login, as: 'audit_authentication_login'
get 'audit/authentication/accounts/:account_id', action: :for_account, as: 'audit_authentication_account'
get 'audit/authentication/users/:user_id', action: :for_user, as: 'audit_authentication_user'
Auditors::Authentication fixes CNVS-390 stores and allows querying by user/account/pseudonym of login/logout events. test-plan: [setup] - set up an 'auditors' keyspace in cassandra and run migrations - have shardX and shardY on one database server, and shardZ on a different database server - have accountW and accountX on shardX - have accountY and accountZ on shardY and shardZ, respectively - have userA on shardX with pseudonymAW in accountW and pseudonymAX in accountX (cross-account, single-shard user) - have userB on shardY with pseudonymBY in accountY and pseudonymBX in accountX (cross-shard user) - have userC on shardZ with pseudonymCZ in accountZ and pseudonymCX in accountX (cross-db-server user) - log in and out of each pseudonym above multiple times [index isolation] - /api/v1/audit/authentication/pseudonyms/<pseudonymAX> should include logins and logouts from pseudonymAX only - /api/v1/audit/authentication/accounts/<accountX> should include logins and logouts from pseudonymAX, pseudonymBX, and pseudonymCX but not pseudonymAW - /api/v1/audit/authentication/users/<userA> should include logins and logouts from both pseudonymAW and pseudonymAX but not pseudonymBX or pseudonymCX [permission isolation] (in each of these, either :view_statistics or :manage_user_logins on an account qualifies as "having permission") - /api/v1/audit/authentication/pseudonyms/<pseudonymAX> should be unauthorized if the current user doesn't have permission on accountX - /api/v1/audit/authentication/accounts/<accountX> should be unauthorized if the current user doesn't have permission on accountX - /api/v1/audit/authentication/users/<userA> should be unauthorized if the current user doesn't have permission on either of accountW or accountX - /api/v1/audit/authentication/users/<userA> should include logins and logouts from accountW but not from accountX if the current user has permission on accountW but not on accountX [sharding] - /api/v1/audit/authentication/users/<userB> should include logins and logouts from both pseudonymBY and pseudonymBX - /api/v1/audit/authentication/users/<userB> should not include duplicate logins and logouts from either pseudonymBY and pseudonymBX (potential for bug due to both pseudonyms' shards being on the same database server) - /api/v1/audit/authentication/users/<userC> should include logins and logouts from both pseudonymCZ and pseudonymCX Change-Id: I74b1573b346935f733fe5b07919d2d450cf07592 Reviewed-on: https://gerrit.instructure.com/21829 Reviewed-by: Brian Palmer <brianp@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Jeremy Putnam <jeremyp@instructure.com> Product-Review: Jacob Fugal <jacob@instructure.com>
2013-06-28 06:43:15 +08:00
end
scope(controller: :grade_change_audit_api) do
get 'audit/grade_change/assignments/:assignment_id', action: :for_assignment, as: 'audit_grade_change_assignment'
get 'audit/grade_change/courses/:course_id', action: :for_course, as: 'audit_grade_change_course'
get 'audit/grade_change/students/:student_id', action: :for_student, as: 'audit_grade_change_student'
get 'audit/grade_change/graders/:grader_id', action: :for_grader, as: 'audit_grade_change_grader'
end
scope(controller: :course_audit_api) do
get 'audit/course/courses/:course_id', action: :for_course, as: 'audit_course_for_course'
end
scope(controller: :assignments_api) do
get 'courses/:course_id/assignments', action: :index, as: 'course_assignments'
get 'users/:user_id/courses/:course_id/assignments', action: :user_index, as: 'user_course_assignments'
get 'courses/:course_id/assignments/:id', action: :show, as: 'course_assignment'
post 'courses/:course_id/assignments', action: :create
put 'courses/:course_id/assignments/:id', action: :update
delete 'courses/:course_id/assignments/:id', action: :destroy, controller: :assignments
end
peer reviews api refs: PFS-2071, PFS-2072, PFS-2073, PFS-2074 **Test Plan PFS-2071 1. Create course with assignment, teacher and two students 2. setup peer reviews on assignment 3. As student 1 create a submission 4. As student 2 peer review submission, leave comments 5. execute the following api courses/:course_id/assignments/:assignment_id/peer_reviews 6. As account admin all information should be shown 7. As teacher all information should be shown 8. As student should see all information 9. Repeat above but set anonymous peer reviews on assignment 10. As account admin all information should be shown 11. As teacher all information should be shown 12. As student should see comments but all reviewer information should not be shown 13. include the following include parameters, include[]=submission_comments, include[]=user make sure additional information is shown according to parameter. PFS-2072 1. Follow setup from PFS-2071 2. execute a get on the following api /api/v1/courses/:course_id/assignments/:assignment_id/submissions/:submission_id/peer_reviews 3. validate that only peer reviews for the given submission are shown PFS-2073 1. Follow setup from PFS-2071 2. execute a post on the following api, including a user_id parameter /api/v1/courses/:course_id/assignments/:assignment1_id/submissions/:submission_id/peer_reviews 3. validate that user from user_id parameter is added as a reviwer on the submission PFS-2074 1. follow setup from PFS-2071 2. execute a delete on the following api, including a user_id parameter /api/v1/courses/:course_id/assignments/:assignment1_id/submissions/:submission_id/peer_reviews 3. validate that user from user_id parameter is removed as a reviewer on the submission (cherry picked from commit 91744bbcd5a81be968139b1f68b65c3e9eaa7b4a) Change-Id: Ic09a16956cddb2f113625ff61bc733503d713abb Reviewed-on: https://gerrit.instructure.com/56936 Tested-by: Jenkins QA-Review: Adam Stone <astone@instructure.com> Reviewed-by: John Corrigan <jcorrigan@instructure.com> Product-Review: Brandon Broschinsky <brandonbr@instructure.com>
2015-06-18 00:34:45 +08:00
scope(controller: :peer_reviews_api) do
get 'courses/:course_id/assignments/:assignment_id/peer_reviews', action: :index
get 'sections/:section_id/assignments/:assignment_id/peer_reviews', action: :index
get 'courses/:course_id/assignments/:assignment_id/submissions/:submission_id/peer_reviews', action: :index
get 'sections/:section_id/assignments/:assignment_id/submissions/:submission_id/peer_reviews', action: :index
post 'courses/:course_id/assignments/:assignment_id/submissions/:submission_id/peer_reviews', action: :create
post 'sections/:section_id/assignments/:assignment_id/submissions/:submission_id/peer_reviews', action: :create
delete 'courses/:course_id/assignments/:assignment_id/submissions/:submission_id/peer_reviews', action: :destroy
delete 'sections/:section_id/assignments/:assignment_id/submissions/:submission_id/peer_reviews', action: :destroy
end
scope(controller: :assignment_overrides) do
get 'courses/:course_id/assignments/:assignment_id/overrides', action: :index
post 'courses/:course_id/assignments/:assignment_id/overrides', action: :create
get 'courses/:course_id/assignments/:assignment_id/overrides/:id', action: :show, as: 'assignment_override'
put 'courses/:course_id/assignments/:assignment_id/overrides/:id', action: :update
delete 'courses/:course_id/assignments/:assignment_id/overrides/:id', action: :destroy
get 'sections/:course_section_id/assignments/:assignment_id/override', action: :section_alias
get 'groups/:group_id/assignments/:assignment_id/override', action: :group_alias
end
scope(controller: :moderation_set) do
get 'courses/:course_id/assignments/:assignment_id/moderated_students', action: :index, as: :moderated_students
post 'courses/:course_id/assignments/:assignment_id/moderated_students', action: :create, as: :add_moderated_students
end
scope(controller: :submissions_api) do
2015-06-26 03:35:25 +08:00
[%w(course course), %w(section course_section)].each do |(context, path_prefix)|
post "#{context.pluralize}/:#{context}_id/submissions/update_grades", action: :bulk_update
put "#{context.pluralize}/:#{context}_id/assignments/:assignment_id/submissions/:user_id/read", action: :mark_submission_read, as: "#{context}_submission_mark_read"
delete "#{context.pluralize}/:#{context}_id/assignments/:assignment_id/submissions/:user_id/read", action: :mark_submission_unread, as: "#{context}_submission_mark_unread"
get "#{context.pluralize}/:#{context}_id/assignments/:assignment_id/submissions", action: :index, as: "#{path_prefix}_assignment_submissions"
get "#{context.pluralize}/:#{context}_id/students/submissions", controller: :submissions_api, action: :for_students, as: "#{path_prefix}_student_submissions"
get "#{context.pluralize}/:#{context}_id/assignments/:assignment_id/submissions/:user_id", action: :show, as: "#{path_prefix}_assignment_submission"
post "#{context.pluralize}/:#{context}_id/assignments/:assignment_id/submissions", action: :create, controller: :submissions
post "#{context.pluralize}/:#{context}_id/assignments/:assignment_id/submissions/:user_id/files", action: :create_file
put "#{context.pluralize}/:#{context}_id/assignments/:assignment_id/submissions/:user_id", action: :update
post "#{context.pluralize}/:#{context}_id/assignments/:assignment_id/submissions/update_grades", action: :bulk_update
end
get "courses/:course_id/assignments/:assignment_id/gradeable_students", action: :gradeable_students, as: "course_assignment_gradeable_students"
end
copy to final provisional grade test plan: 1. create a moderated assignment 2. associate a rubric with the assignment 3. add a student to the moderation set, using g/63360, or if that's not available yet, the Rails console: assignment.moderated_grading_selections.create! student: student 4. submit to the assignment as a student 5. grade the assignment as a TA in speedgrader, commenting and marking the rubric in the process 6. as a teacher, view the submission using the "Get a single submission" API endpoint, including provisional_grades, submission_comments, and rubric_assessment GET /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}?include[]=provisional_grades&include[]=submission_comments&include[]=rubric_assessment 7. retrieve the provisional_grade_id from the above, to use in the next step 8. as a teacher, call the copy_to_final_grade endpoint to copy the TA's provisional grade to the "final" provisional grade editable by moderators POST /api/v1/courses/{course_id}/assignments/{assignment_id}/provisional_grades/{provisional_grade_id}/copy_to_final_mark 9. as a teacher, repeat the GET from step 6 and ensure that the provisional grade appears twice, once with the TA as the scorer_id and once with the teacher - the teacher's entry should have final=true while the TA's is false - the comments and rubric assessment written by the TA should be included in the teacher's provisional grade, but still attributed to the TA's user id closes CNVS-23300 Change-Id: Id09f828ddb4c262ef5452a62702a3a1828091486 Reviewed-on: https://gerrit.instructure.com/63563 Reviewed-by: James Williams <jamesw@instructure.com> Tested-by: Jenkins QA-Review: Jahnavi Yetukuri <jyetukuri@instructure.com> Product-Review: Jeremy Stanley <jeremy@instructure.com>
2015-09-18 08:18:45 +08:00
scope(controller: :provisional_grades) do
get "courses/:course_id/assignments/:assignment_id/provisional_grades/status", action: :status, as: "course_assignment_provisional_status"
post "courses/:course_id/assignments/:assignment_id/provisional_grades/publish", action: :publish, as: 'publish_provisional_grades'
put "courses/:course_id/assignments/:assignment_id/provisional_grades/:provisional_grade_id/select", action: :select, as: 'select_provisional_grade'
copy to final provisional grade test plan: 1. create a moderated assignment 2. associate a rubric with the assignment 3. add a student to the moderation set, using g/63360, or if that's not available yet, the Rails console: assignment.moderated_grading_selections.create! student: student 4. submit to the assignment as a student 5. grade the assignment as a TA in speedgrader, commenting and marking the rubric in the process 6. as a teacher, view the submission using the "Get a single submission" API endpoint, including provisional_grades, submission_comments, and rubric_assessment GET /api/v1/courses/{course_id}/assignments/{assignment_id}/submissions/{user_id}?include[]=provisional_grades&include[]=submission_comments&include[]=rubric_assessment 7. retrieve the provisional_grade_id from the above, to use in the next step 8. as a teacher, call the copy_to_final_grade endpoint to copy the TA's provisional grade to the "final" provisional grade editable by moderators POST /api/v1/courses/{course_id}/assignments/{assignment_id}/provisional_grades/{provisional_grade_id}/copy_to_final_mark 9. as a teacher, repeat the GET from step 6 and ensure that the provisional grade appears twice, once with the TA as the scorer_id and once with the teacher - the teacher's entry should have final=true while the TA's is false - the comments and rubric assessment written by the TA should be included in the teacher's provisional grade, but still attributed to the TA's user id closes CNVS-23300 Change-Id: Id09f828ddb4c262ef5452a62702a3a1828091486 Reviewed-on: https://gerrit.instructure.com/63563 Reviewed-by: James Williams <jamesw@instructure.com> Tested-by: Jenkins QA-Review: Jahnavi Yetukuri <jyetukuri@instructure.com> Product-Review: Jeremy Stanley <jeremy@instructure.com>
2015-09-18 08:18:45 +08:00
post "courses/:course_id/assignments/:assignment_id/provisional_grades/:provisional_grade_id/copy_to_final_mark", action: :copy_to_final_mark, as: 'copy_to_final_mark'
end
2015-06-26 03:35:25 +08:00
post '/courses/:course_id/assignments/:assignment_id/submissions/:user_id/comments/files', action: :create_file, controller: :submission_comments_api
scope(controller: :gradebook_history_api) do
get "courses/:course_id/gradebook_history/days", action: :days, as: 'gradebook_history'
get "courses/:course_id/gradebook_history/feed", action: :feed, as: 'gradebook_history_feed'
get "courses/:course_id/gradebook_history/:date", action: :day_details, as: 'gradebook_history_for_day'
get "courses/:course_id/gradebook_history/:date/graders/:grader_id/assignments/:assignment_id/submissions", action: :submissions, as: 'gradebook_history_submissions'
gradebook history api fixes #CNVS-2802 This provides a reimplementation of the functionality in 'lib/submission_list.rb'. That lib file has been used to produce a grade book history page, but it loads the entire history of the course at once, which is untenable. This take all the same data, and provides it through a paginated API endpoint. Using this API, a rich front end will be possible to create in order to replace the current large grade book history page, one that makes API calls to reveal data further d own the tree as it is requested. This is an unusual API endpoint in that it does not present data as it is in the database, there is a series of transformations that the submission data is put through to arrive at a versioned history where each node contains within itself some contextual knowledge of the flow of the submission progress (each version knows what the grade of the version before it was, and what the grade is today, for example). TEST PLAN: This is a new API endpoint and does not yet get used by any front end code yet. It can be played with by performing some valid API queries against the following paths: /courses/:course_id/gradebook_history/days /courses/:course_id/gradebook_history/:date ^ date is like "2013-01-31" ^ /courses/:course_id/gradebook_history/:date/graders/:grader_id/assignments/:assignment_id/submissions (yes, that last one is huge, but it does follow the nested structure described by the original grade book history page). The user that is selected for testing needs to have the "manage_grades" permission on the referenced course. API documentation is available on the controller class app/controllers/gradebook_history_api_controller.rb Change-Id: I18e0b4b967d6c20ad47b86e98adbc15b87276098 Reviewed-on: https://gerrit.instructure.com/17366 QA-Review: Clare Hetherington <clare@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Brian Palmer <brianp@instructure.com>
2013-02-01 08:35:16 +08:00
end
get 'courses/:course_id/assignment_groups', controller: :assignment_groups, action: :index
scope(controller: :assignment_groups_api) do
resources :assignment_groups, path: "courses/:course_id/assignment_groups", name_prefix: "course_", except: :index
end
scope(controller: :discussion_topics) do
get 'courses/:course_id/discussion_topics', action: :index, as: 'course_discussion_topics'
get 'groups/:group_id/discussion_topics', action: :index, as: 'group_discussion_topics'
end
scope(controller: :content_migrations) do
%w(account course group user).each do |context|
get "#{context.pluralize}/:#{context}_id/content_migrations/migrators", action: :available_migrators, as: "#{context}_content_migration_migrators_list"
get "#{context.pluralize}/:#{context}_id/content_migrations/:id", action: :show, as: "#{context}_content_migration"
get "#{context.pluralize}/:#{context}_id/content_migrations", action: :index, as: "#{context}_content_migration_list"
post "#{context.pluralize}/:#{context}_id/content_migrations", action: :create, as: "#{context}_content_migration_create"
put "#{context.pluralize}/:#{context}_id/content_migrations/:id", action: :update, as: "#{context}_content_migration_update"
get "#{context.pluralize}/:#{context}_id/content_migrations/:id/selective_data", action: :content_list, as: "#{context}_content_migration_selective_data"
end
end
scope(controller: :migration_issues) do
%w(account course group user).each do |context|
get "#{context.pluralize}/:#{context}_id/content_migrations/:content_migration_id/migration_issues/:id", action: :show, as: "#{context}_content_migration_migration_issue"
get "#{context.pluralize}/:#{context}_id/content_migrations/:content_migration_id/migration_issues", action: :index, as: "#{context}_content_migration_migration_issue_list"
post "#{context.pluralize}/:#{context}_id/content_migrations/:content_migration_id/migration_issues", action: :create, as: "#{context}_content_migration_migration_issue_create"
put "#{context.pluralize}/:#{context}_id/content_migrations/:content_migration_id/migration_issues/:id", action: :update, as: "#{context}_content_migration_migration_issue_update"
end
end
scope(controller: :discussion_topics_api) do
2015-06-26 03:35:25 +08:00
%w(course group).each do |context|
get "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id", action: :show, as: "#{context}_discussion_topic"
post "#{context.pluralize}/:#{context}_id/discussion_topics", controller: :discussion_topics, action: :create
put "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id", controller: :discussion_topics, action: :update
post "#{context.pluralize}/:#{context}_id/discussion_topics/reorder", controller: :discussion_topics, action: :reorder
delete "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id", controller: :discussion_topics, action: :destroy
get "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/view", action: :view, as: "#{context}_discussion_topic_view"
get "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/entry_list", action: :entry_list, as: "#{context}_discussion_topic_entry_list"
post "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/entries", action: :add_entry, as: "#{context}_discussion_add_entry"
get "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/entries", action: :entries, as: "#{context}_discussion_entries"
post "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/entries/:entry_id/replies", action: :add_reply, as: "#{context}_discussion_add_reply"
get "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/entries/:entry_id/replies", action: :replies, as: "#{context}_discussion_replies"
put "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/entries/:id", controller: :discussion_entries, action: :update, as: "#{context}_discussion_update_reply"
delete "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/entries/:id", controller: :discussion_entries, action: :destroy, as: "#{context}_discussion_delete_reply"
put "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/read", action: :mark_topic_read, as: "#{context}_discussion_topic_mark_read"
delete "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/read", action: :mark_topic_unread, as: "#{context}_discussion_topic_mark_unread"
put "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/read_all", action: :mark_all_read, as: "#{context}_discussion_topic_mark_all_read"
delete "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/read_all", action: :mark_all_unread, as: "#{context}_discussion_topic_mark_all_unread"
put "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/entries/:entry_id/read", action: :mark_entry_read, as: "#{context}_discussion_topic_discussion_entry_mark_read"
delete "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/entries/:entry_id/read", action: :mark_entry_unread, as: "#{context}_discussion_topic_discussion_entry_mark_unread"
post "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/entries/:entry_id/rating",
action: :rate_entry, as: "#{context}_discussion_topic_discussion_entry_rate"
put "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/subscribed", action: :subscribe_topic, as: "#{context}_discussion_topic_subscribe"
delete "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/subscribed", action: :unsubscribe_topic, as: "#{context}_discussion_topic_unsubscribe"
end
finish discussion topics API supports creating and listing top-level entries in a discussion topic, and creating and listing replies to a discussion entry. listing discussion topics was already supported. includes support for attachments on top-level entries. test-plan: creating an entry under a topic should allow creating an entry under a topic and create it correctly should return json representation of the new entry should allow creating a reply to an existing top-level entry should not allow reply-to-reply should allow including attachments on top-level entries should silently ignore attachments on replies to top-level entries should include attachment info in the json response listing top-level discussion entries should return top level entries for a topic should return attachments on top level entries should include replies on top level entries should sort top-level entries by descending created_at should sort replies included on top-level entries by descending created_at should paginate top-level entries should only include the first 10 replies for each top-level entry listing replies should return replies for an entry should sort replies by descending created_at should paginate replies require initial post should allow admins to see posts without posting shouldn't allow student who hasn't posted to see shouldn't allow student's observer who hasn't posted to see should allow student who has posted to see should allow student's observer who has posted to see fixes #4752 Change-Id: I0da83e6c301be74f1ac5d2d957ebb6338a98179c Reviewed-on: https://gerrit.instructure.com/6690 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Cody Cutrer <cody@instructure.com>
2011-11-04 05:51:29 +08:00
end
scope(controller: :collaborations) do
get 'collaborations/:id/members', action: :members, as: 'collaboration_members'
end
scope(controller: :external_tools) do
2015-06-26 03:35:25 +08:00
%w(course account).each do |context|
get "#{context}s/:#{context}_id/external_tools/sessionless_launch", action: :generate_sessionless_launch, as: "#{context}_external_tool_sessionless_launch"
get "#{context}s/:#{context}_id/external_tools/:external_tool_id", action: :show, as: "#{context}_external_tool_show"
get "#{context}s/:#{context}_id/external_tools", action: :index, as: "#{context}_external_tools"
post "#{context}s/:#{context}_id/external_tools", action: :create, as: "#{context}_external_tools_create"
put "#{context}s/:#{context}_id/external_tools/:external_tool_id", action: :update, as: "#{context}_external_tools_update"
delete "#{context}s/:#{context}_id/external_tools/:external_tool_id", action: :destroy, as: "#{context}_external_tools_delete"
end
get "groups/:group_id/external_tools", action: :index, as: "group_external_tools"
end
scope(controller: 'lti/lti_apps') do
2015-06-26 03:35:25 +08:00
%w(course account).each do |context|
get "#{context}s/:#{context}_id/lti_apps/launch_definitions", action: :launch_definitions, as: "#{context}_launch_definitions"
get "#{context}s/:#{context}_id/lti_apps", action: :index, as: "#{context}_app_definitions"
end
end
scope(controller: 'lti/tool_proxy') do
2015-06-26 03:35:25 +08:00
%w(course account).each do |context|
delete "#{context}s/:#{context}_id/tool_proxies/:tool_proxy_id", action: :destroy,
as: "#{context}_delete_tool_proxy"
put "#{context}s/:#{context}_id/tool_proxies/:tool_proxy_id", action: :update,
as: "#{context}_update_tool_proxy"
delete "#{context}s/:#{context}_id/tool_proxies/:tool_proxy_id/update", action: :dismiss_update,
as: "#{context}_dismiss_update_tool_proxy"
put "#{context}s/:#{context}_id/tool_proxies/:tool_proxy_id/update", action: :accept_update,
as: "#{context}_accept_update_tool_proxy"
end
end
scope(controller: :external_feeds) do
2015-06-26 03:35:25 +08:00
%w(course group).each do |context|
get "#{context}s/:#{context}_id/external_feeds", action: :index, as: "#{context}_external_feeds"
post "#{context}s/:#{context}_id/external_feeds", action: :create, as: "#{context}_external_feeds_create"
delete "#{context}s/:#{context}_id/external_feeds/:external_feed_id", action: :destroy, as: "#{context}_external_feeds_delete"
new discussion topics/announcement index, edit and create closes: #7172 test plan: * open discussion topic index page: - see how it looks in blank course - full course - try graded & unread filters (make sure you see things you expect to and not those you don't) - do bulk actions by clicking checkbox for a few and hitting delete and lock buttons - verify infinite scroll works - verify that as a student you don't see posts that had delayed posting - click "create new" button to make a new one, make sure it works - do all the above in the announcement index page * while viewing announcements index: - verify teacher can create external feed on right - no right side unless external feeds exist or they are teacher - external feeds are listed - only teacher can delete external feed * while editing/creating new discussion/announcement - verify that announcement cant be made into assignment - for discussion topic, set as assignment and make sure the assignment settings set. - cant change discussion -> announcement (& vise versa) - type crazy & blank input, verify that it validates it for you - title cant be longer than 254 - make sure these features work: - podcast feed - student posts in podcast feed - delayed posting - toggling threaded/unthreaded - must post before seeing replies - attach file, remove file attachment, upload new attachment should work * make sure announcements/discussions look & behave right in other places they show up (like course, user dashboard) * if you can think of any other places where you can edit/create discussions/announcements, make sure that still works Change-Id: Ib0acaff8542bf09f99cd7aa99fb3ed16c999d224 Reviewed-on: https://gerrit.instructure.com/12655 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com>
2012-08-01 07:22:48 +08:00
end
end
scope(controller: :sis_imports_api) do
post 'accounts/:account_id/sis_imports', action: :create
get 'accounts/:account_id/sis_imports/:id', action: :show
get 'accounts/:account_id/sis_imports', action: :index, as: "account_sis_imports"
end
scope(controller: :users) do
get 'users/self/activity_stream', action: :activity_stream, as: 'user_activity_stream'
get 'users/activity_stream', action: :activity_stream # deprecated
get 'users/self/activity_stream/summary', action: :activity_stream_summary, as: 'user_activity_stream_summary'
delete 'users/self/activity_stream/:id', action: 'ignore_stream_item'
delete 'users/self/activity_stream', action: 'ignore_all_stream_items'
put "users/:user_id/followers/self", action: :follow
delete "users/:user_id/followers/self", action: :unfollow
get 'users/self/todo', action: :todo_items
get 'users/self/upcoming_events', action: :upcoming_events
get 'users/:user_id/missing_submissions', action: :missing_submissions
delete 'users/self/todo/:asset_string/:purpose', action: :ignore_item, as: 'users_todo_ignore'
post 'accounts/:account_id/users', action: :create
post 'accounts/:account_id/self_registration', action: :create_self_registered_user
get 'accounts/:account_id/users', action: :index, as: 'account_users'
get 'users/:id', action: :api_show
put 'users/:id', action: :update
post 'users/:user_id/files', action: :create_file
get 'users/:user_id/files', controller: :files, action: :api_index, as: 'user_files'
get 'users/:user_id/folders', controller: :folders, action: :list_all_folders, as: 'user_folders'
post 'users/:user_id/folders', controller: :folders, action: :create
get 'users/:user_id/folders/by_path/*full_path', controller: :folders, action: :resolve_path
get 'users/:user_id/folders/by_path', controller: :folders, action: :resolve_path
get 'users/:user_id/folders/:id', controller: :folders, action: :show, as: 'user_folder'
get 'users/:id/settings', controller: 'users', action: 'settings'
put 'users/:id/settings', controller: 'users', action: 'settings', as: 'user_settings'
get 'users/:id/colors', controller: 'users', action: 'get_custom_colors'
get 'users/:id/colors/:asset_string', controller: 'users', action: 'get_custom_color'
put 'users/:id/colors/:asset_string', controller: 'users', action: 'set_custom_color'
put 'users/:id/merge_into/:destination_user_id', controller: 'users', action: 'merge_into'
put 'users/:id/merge_into/accounts/:destination_account_id/users/:destination_user_id', controller: 'users', action: 'merge_into'
post 'users/:id/split', controller: 'users', action: 'split'
scope(controller: :user_observees) do
get 'users/:user_id/observees', action: :index, as: 'user_observees'
post 'users/:user_id/observees', action: :create
get 'users/:user_id/observees/:observee_id', action: :show, as: 'user_observee'
put 'users/:user_id/observees/:observee_id', action: :update
delete 'users/:user_id/observees/:observee_id', action: :destroy
end
end
scope(controller: :custom_data) do
glob = '(/*scope)'
add serializable hash of CustomData for User models fixes CNVS-11424 test plan: - rake db:migrate - if you don't already have one, set yourself up with a developer token. (you can do so from <canvas>/developer_keys) - $ curl -H "Authorization: Bearer <ACCESS-TOKEN>" \ -X GET -F 'ns=test' \ <canvas>/api/v1/users/self/custom_data #=> {"message":"no data for scope"} - $ curl -H "Authorization: Bearer <ACCESS-TOKEN>" \ -X PUT -F 'ns=test' \ -F 'data[apple]=so tasty' \ -F 'data[kiwi]=a bit sour' \ <canvas>/api/v1/users/self/custom_data/fruit #=> {"data":{"apple":"so tasty","kiwi":"a bit sour"}} - $ curl -H "Authorization: Bearer <ACCESS-TOKEN>" \ -X GET -F 'ns=test' \ <canvas>/api/v1/users/self/custom_data #=> {"data":{"fruit":{"apple":"so tasty","kiwi":"a bit sour"}}} - $ curl -H "Authorization: Bearer <ACCESS-TOKEN>" \ -X DELETE -F 'ns=test' \ <canvas>/api/v1/users/self/custom_data/fruit/kiwi #=> {"data":"a bit sour"} - $ curl -H "Authorization: Bearer <ACCESS-TOKEN>" \ -X GET -F 'ns=test' \ <canvas>/api/v1/users/self/custom_data #=> {"data":{"fruit":{"apple":"so tasty"}}} - see new API doc for more info about how it should work, but basically, you should be able to GET, PUT, and DELETE at will for any given scope, and PUTting JSON hashes creates referenceable scopes. (e.g. the DELETE above has 'kiwi' in its scope) Change-Id: If027ae4aeec14edf44275ba0372a68aef7e5600e Reviewed-on: https://gerrit.instructure.com/31173 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Matt Fairbourn <mfairbourn@instructure.com> Reviewed-by: Jon Jensen <jon@instructure.com> Product-Review: Jon Jensen <jon@instructure.com>
2014-03-04 03:55:14 +08:00
get "users/:user_id/custom_data#{glob}", action: 'get_data'
put "users/:user_id/custom_data#{glob}", action: 'set_data'
delete "users/:user_id/custom_data#{glob}", action: 'delete_data'
end
scope(controller: :pseudonyms) do
get 'accounts/:account_id/logins', action: :index, as: 'account_pseudonyms'
get 'users/:user_id/logins', action: :index, as: 'user_pseudonyms'
post 'accounts/:account_id/logins', action: :create
put 'accounts/:account_id/logins/:id', action: :update
delete 'users/:user_id/logins/:id', action: :destroy
end
scope(controller: :accounts) do
get 'accounts', action: :index, as: :accounts
get 'course_accounts', :action => :course_accounts, :as => :course_accounts
get 'accounts/:id', action: :show, as: :account
put 'accounts/:id', action: :update
get 'accounts/:account_id/courses', action: :courses_api, as: 'account_courses'
get 'accounts/:account_id/sub_accounts', action: :sub_accounts, as: 'sub_accounts'
get 'accounts/:account_id/courses/:id', controller: :courses, action: :show, as: 'account_course_show'
clean up user "deletion" fixes CNVS-1552 any time the UI/API tries to "delete" a user, it should only be trying to remove it from some root account (the @domain_root_account if not otherwise specified). if that root account was the last root account the user was associated with, then the remnants of the user are fully deleted, but only then. leave User#destroy as a short-cut to delete the user from all their accounts at once, but should not be invoked directly from any UI/API actions. test-plan: PERMISSIONS being able to remove a user from an account entails being able to: - DELETE http://accounts-domain/users/:user - DELETE /accounts/:account/users/:user both should fail or succeed together * given - Sally who's an admin with the :manage_user_logins permission on one account (Account1) and a student on another account (Account2) - Bob who's a student on both accounts - Alice who's an admin on Account1 with greater permissions than Sally * Sally should: - see "Delete My Account" on her Account1 profile - not see "Delete My Account" on her Account2 profile - not see "Delete My Account" on Bob's Account1 profile - not see "Delete My Account" on Alice's Account1 profile - see "Delete from Account1" at /users/:sally - see "Delete from Account1" at /users/:bob - not see "Delete from Account2" at /users/:sally - not see "Delete from Account2" at /users/:bob - not see "Delete from Account1" at /users/:alice - be able to remove herself from Account1 - be able to remove Bob from Account1 - not be able to remove herself from Account2 - not be able to remove Bob from Account2 - not be able to remove Alice from Account1 * given Sally's Account1 pseudonym has a SIS ID but her Account2 pseudonym doesn't, Sally should: - no longer see "Delete My Account" on her Account1 profile - no longer see "Delete from Account1" at /users/:sally - still see "Delete from Account1" at /users/:bob - no longer be able to remove herself from Account1 - still be able to remove Bob from Account1 EFFECTS * as Sally, remove Bob from Account1 via DELETE http://account1-domain/users/:bob - Bob's pseudonyms, enrollments, etc. in Account1 should be removed - Bob's pseudonyms, enrollments, etc. in Account2 should be untouched * repeat using DELETE /accounts/:account1/users/:bob, with the same expectations Change-Id: Ib7612f95d1c7e4cca36d8486950565ec096b4ab1 Reviewed-on: https://gerrit.instructure.com/41591 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: August Thornton <august@instructure.com> Reviewed-by: Cody Cutrer <cody@instructure.com> Product-Review: Jacob Fugal <jacob@instructure.com>
2014-09-23 07:04:03 +08:00
delete 'accounts/:account_id/users/:user_id', action: :remove_user
end
scope(controller: :sub_accounts) do
post 'accounts/:account_id/sub_accounts', action: :create
end
scope(controller: :role_overrides) do
get 'accounts/:account_id/roles', action: :api_index, as: 'account_roles'
get 'accounts/:account_id/roles/:id', action: :show
post 'accounts/:account_id/roles', action: :add_role
post 'accounts/:account_id/roles/:id/activate', action: :activate_role
put 'accounts/:account_id/roles/:id', action: :update
delete 'accounts/:account_id/roles/:id', action: :remove_role
add new permission and API endpoint for manage_catalog refs CAT-819, CAT-822 Test plan: 1. rake db:migrate and sign into Canvas as an admin 2. Visit the permissions page for your account hooked up to Catalog and switch to the Account Roles tab. 3. Note the "Manage catalog" permission does not show up. 4. Now, console in and update that account to have a setting of :catalog_enabled => true, e.g. a = Account.find(1) a.settings[:catalog_enabled] = true a.save! 5. Reload Canvas and note that "Manage catalog" now displays in the Account Roles tab. refs CAT-823 Test plan: 1. As a few different user types, make API requests to /api/v1/accounts/:id/permissions/manage_catalog For instance: curl 'http://canvas.dev:3000/api/v1/accounts/1/permissions/manage_catalog' -H 'Authorization: Bearer your-token' * Account admins should receive {granted: true} * Non-admin users should receive {granted: false} * Users with custom roles that have the Manage Catalog permission should receive {granted: true} * If :catalog_enabled is not set on the account in question, it should never return {granted: true} * Try changing up the permission name in the URL (to something other than manage_catalog). The response should be an error (status code: 400), since we only support checking manage_catalog for now. Change-Id: I4fa53665ff866f5c016f32ce72036e8b5a75bda5 Reviewed-on: https://gerrit.instructure.com/48119 Tested-by: Jenkins Reviewed-by: Ethan Gunderson <egunderson@instructure.com> Product-Review: Ethan Gunderson <egunderson@instructure.com> QA-Review: Ethan Gunderson <egunderson@instructure.com>
2015-02-03 13:43:14 +08:00
get 'accounts/:account_id/permissions/:permission', action: :check_account_permission
end
scope(controller: :account_reports) do
get 'accounts/:account_id/reports/:report', action: :index
get 'accounts/:account_id/reports', action: :available_reports
get 'accounts/:account_id/reports/:report/:id', action: :show
post 'accounts/:account_id/reports/:report', action: :create, as: 'account_create_report'
delete 'accounts/:account_id/reports/:report/:id', action: :destroy
end
scope(controller: :admins) do
post 'accounts/:account_id/admins', action: :create
delete 'accounts/:account_id/admins/:user_id', action: :destroy
get 'accounts/:account_id/admins', action: :index, as: 'account_admins'
end
scope(controller: :account_authorization_configs) do
get 'accounts/:account_id/sso_settings', action: :show_sso_settings, as: 'account_show_sso_settings_url'
put 'accounts/:account_id/sso_settings', action: :update_sso_settings, as: 'account_update_sso_settings_url'
get 'accounts/:account_id/authentication_providers', action: :index
get 'accounts/:account_id/authentication_providers/:id', action: :show
post 'accounts/:account_id/authentication_providers', action: :create, as: 'account_create_ap'
put 'accounts/:account_id/authentication_providers/:id', action: :update, as: 'account_update_ap'
delete 'accounts/:account_id/authentication_providers/:id', action: :destroy, as: 'account_delete_ap'
# deprecated
get 'accounts/:account_id/account_authorization_configs/discovery_url', action: :show_discovery_url
put 'accounts/:account_id/account_authorization_configs/discovery_url', action: :update_discovery_url, as: 'account_update_discovery_url'
delete 'accounts/:account_id/account_authorization_configs/discovery_url', action: :destroy_discovery_url, as: 'account_destroy_discovery_url'
get 'accounts/:account_id/account_authorization_configs', action: :index
get 'accounts/:account_id/account_authorization_configs/:id', action: :show
post 'accounts/:account_id/account_authorization_configs', action: :create, as: 'account_create_aac'
put 'accounts/:account_id/account_authorization_configs/:id', action: :update, as: 'account_update_aac'
delete 'accounts/:account_id/account_authorization_configs/:id', action: :destroy, as: 'account_delete_aac'
end
get 'users/:user_id/page_views', controller: :page_views, action: :index, as: 'user_page_views'
get 'users/:user_id/profile', controller: :profile, action: :settings
get 'users/:user_id/avatars', controller: :profile, action: :profile_pics
# deprecated routes, second one is solely for YARD. preferred API is api/v1/search/recipients
get 'conversations/find_recipients', controller: :search, action: :recipients
get 'conversations/find_recipients', controller: :conversations, action: :find_recipients
scope(controller: :conversations) do
get 'conversations', action: :index, as: 'conversations'
post 'conversations', action: :create
post 'conversations/mark_all_as_read', action: :mark_all_as_read
get 'conversations/batches', action: :batches, as: 'conversations_batches'
get 'conversations/unread_count', action: :unread_count
get 'conversations/:id', action: :show
put 'conversations/:id', action: :update # stars, subscribed-ness, workflow_state
delete 'conversations/:id', action: :destroy
post 'conversations/:id/add_message', action: :add_message
post 'conversations/:id/add_recipients', action: :add_recipients
post 'conversations/:id/remove_messages', action: :remove_messages
put 'conversations', action: :batch_update
delete 'conversations/:id/delete_for_all', action: :delete_for_all
end
scope(controller: :communication_channels) do
get 'users/:user_id/communication_channels', action: :index, as: 'communication_channels'
post 'users/:user_id/communication_channels', action: :create
Link to reset bounce counts for communication channels Fixes CNVS-20747 Test plan: - Create a user - Add an email address to the user - The address doesn't need to be able to actually receive messages, so put anything you want in here - Make note of the user's id - Assuming the user's id is 42, open a rails console and type: c = User.find(42).email_channel c.bounce_count = 3 c.save! - Log in as the user (actually log in, don't just masquerade) - Visit the user's settings page - Verify you see the usual warning triangle next to the user's email address - Verify you don't see the reset icon (just a refresh-like icon, two arrows pointing in a circle) - Log in as a siteadmin - Masquerade as the user - Visit the user's settings page - Verify you see both the warning triangle and the reset icon - Click the reset icon - Verify that the reset icon and the warning triangle go away - Refresh the page and verify that they're still gone - Assuming the user's id is 42, open a rails console and type: c = User.find(42).email_channel c.bounce_count = 1 c.save! - Log in as a siteadmin - Masquerade as the user - Visit the user's settings page - Verify you see only the reset icon and not the warning triangle - Click the reset icon - Verify that it goes away - Refresh the page and verify that it's still gone Change-Id: Ibd9d2e04555be2ec3eae811fd93f2cba0645d870 Reviewed-on: https://gerrit.instructure.com/55139 Reviewed-by: Joel Hough <joel@instructure.com> Tested-by: Jenkins QA-Review: Adrian Russell <arussell@instructure.com> Product-Review: Allison Weiss <allison@instructure.com>
2015-10-07 12:27:50 +08:00
post 'users/:user_id/communication_channels/:id', action: :reset_bounce_count, as: 'reset_bounce_count'
Add API to bulk fetch and reset communication channels Fixes CNVS-24295 Test plan: - Create at least three users and give each of them a few email addresses - Add 'foo@example.com', 'bar@example.com', and 'foobar@example.com' as addresses to the first of those three users - Run the following, with U1 and U2 replaced with the ids of the first and second users you created, respectively (do not include the id of the third user in this list): CommunicationChannel .where(user_id: U1) .update_all(bounce_count: 1, last_bounce_at: Time.now) CommunicationChannel .where(user_id: U2) .update_all(bounce_count: 1, last_bounce_at: Time.now - 1.day) - As a site admin and on the account's domain, navigate to /api/v1/accounts/self/bouncing_communication_channels.csv - Ensure that you're given a CSV file that mentions all of the first and second user's channels but none of the third user's channels - Ensure that the second user's channels come before the first user's channels, and that the first user's channels mention today's date as the last date at which they bounced while the second user's channels mention yesterday instead - Navigate to /api/v1/accounts/.../bouncing_communication_channels.csv, where ... is the id of the account, and verify that you get the same result - Navigate to /api/v1/accounts/self/bouncing_communication_channels.csv?pattern=foo* - Ensure that the resulting CSV mentions foo@example.com and foobar@example.com but not bar@example.com - Navigate to /api/v1/accounts/self/bouncing_communication_channels.csv?before=TODAY where TODAY is today's date in ISO 8601 format - Ensure that the resulting CSV mentions only the second user's channels and not the first user's - Navigate to /api/v1/accounts/self/bouncing_communication_channels.csv?after=TODAY - Ensure that the resulting CSV mentions only the first user's channels and not the second user's - Make a POST request to /api/v1/accounts/self/boucing_communication_channels/reset with parameters pattern=foo* - View the first user's profile - Ensure that foo@example.com and foobar@example.com are no longer marked as bouncing, but all the other addresses are - Make a POST request to /api/v1/accounts/self/bouncing_communication_channels/reset with parameters before=TODAY where TODAY is today's date in ISO 8601 format - View the second user's profile - Ensure that all of the second user's communication channels are no longer marked as bouncing - View the first user's profile - Ensure that the user's channels are still marked as bouncing - Make a POST request to /api/v1/accounts/self/bouncing_communication_channels/reset - View the first user's profile - Ensure that their channels are now no longer marked as bouncing Change-Id: Ic937777a03481dc0b442ff6cf766175cc987fd80 Reviewed-on: https://gerrit.instructure.com/68328 Reviewed-by: Alex Boyd <aboyd@instructure.com> Reviewed-by: Steven Burnett <sburnett@instructure.com> QA-Review: Heath Hales <hhales@instructure.com> Product-Review: Allison Weiss <allison@instructure.com> Tested-by: Jenkins
2015-12-04 15:56:13 +08:00
get 'accounts/:account_id/bouncing_communication_channels.csv', action: :bouncing_channel_report
post 'accounts/:account_id/bouncing_communication_channels/reset', action: :bulk_reset_bounce_counts
get 'accounts/:account_id/unconfirmed_communication_channels.csv', action: :unconfirmed_channel_report
post 'accounts/:account_id/unconfirmed_communication_channels/confirm', action: :bulk_confirm
delete 'users/:user_id/communication_channels/:id', action: :destroy
delete 'users/:user_id/communication_channels/:type/:address', action: :destroy, constraints: { address: %r{[^/?]+} }
end
scope(controller: :notification_preferences) do
get 'users/:user_id/communication_channels/:communication_channel_id/notification_preferences', action: :index
get 'users/:user_id/communication_channels/:communication_channel_id/notification_preference_categories', action: :category_index
get 'users/:user_id/communication_channels/:type/:address/notification_preferences', action: :index, constraints: { address: %r{[^/?]+} }
get 'users/:user_id/communication_channels/:communication_channel_id/notification_preferences/:notification', action: :show
get 'users/:user_id/communication_channels/:type/:address/notification_preferences/:notification', action: :show, constraints: { address: %r{[^/?]+} }
put 'users/self/communication_channels/:communication_channel_id/notification_preferences/:notification', action: :update
put 'users/self/communication_channels/:type/:address/notification_preferences/:notification', action: :update, constraints: { address: %r{[^/?]+} }
put 'users/self/communication_channels/:communication_channel_id/notification_preferences', action: :update_all
put 'users/self/communication_channels/:type/:address/notification_preferences', action: :update_all, constraints: { address: %r{[^/?]+} }
put 'users/self/communication_channels/:communication_channel_id/notification_preference_categories/:category', action: :update_preferences_by_category
end
scope(controller: :comm_messages_api) do
get 'comm_messages', action: :index, as: 'comm_messages'
end
scope(controller: :services_api) do
get 'services/kaltura', action: :show_kaltura_config
post 'services/kaltura_session', action: :start_kaltura_session
end
scope(controller: :calendar_events_api) do
get 'calendar_events', action: :index, as: 'calendar_events'
get 'users/:user_id/calendar_events', action: :user_index, as: 'user_calendar_events'
post 'calendar_events', action: :create
get 'calendar_events/visible_contexts', action: :visible_contexts
get 'calendar_events/:id', action: :show, as: 'calendar_event'
put 'calendar_events/:id', action: :update
delete 'calendar_events/:id', action: :destroy
post 'calendar_events/:id/reservations', action: :reserve
post 'calendar_events/:id/reservations/:participant_id', action: :reserve, as: 'calendar_event_reserve'
post 'calendar_events/save_selected_contexts', action: :save_selected_contexts
end
scope(controller: :appointment_groups) do
get 'appointment_groups', action: :index, as: 'appointment_groups'
post 'appointment_groups', action: :create
get 'appointment_groups/:id', action: :show, as: 'appointment_group'
put 'appointment_groups/:id', action: :update
delete 'appointment_groups/:id', action: :destroy
get 'appointment_groups/:id/users', action: :users, as: 'appointment_group_users'
get 'appointment_groups/:id/groups', action: :groups, as: 'appointment_group_groups'
end
scope(controller: :groups) do
resources :groups, except: :index
get 'users/self/groups', action: :index, as: "current_user_groups"
get 'accounts/:account_id/groups', action: :context_index, as: 'account_user_groups'
get 'courses/:course_id/groups', action: :context_index, as: 'course_user_groups'
get 'groups/:group_id/users', action: :users, as: 'group_users'
post 'groups/:group_id/invite', action: :invite
post 'groups/:group_id/files', action: :create_file
post 'groups/:group_id/preview_html', action: :preview_html
post 'group_categories/:group_category_id/groups', action: :create
get 'groups/:group_id/activity_stream', action: :activity_stream, as: 'group_activity_stream'
get 'groups/:group_id/activity_stream/summary', action: :activity_stream_summary, as: 'group_activity_stream_summary'
put "groups/:group_id/followers/self", action: :follow
delete "groups/:group_id/followers/self", action: :unfollow
get 'groups/:group_id/collaborations', controller: :collaborations, action: :api_index, as: 'group_collaborations_index'
delete 'groups/:group_id/collaborations/:id', controller: :collaborations, action: :destroy
scope(controller: :group_memberships) do
resources :memberships, path: "groups/:group_id/memberships", name_prefix: "group_", controller: :group_memberships
resources :users, path: "groups/:group_id/users", name_prefix: "group_", controller: :group_memberships, except: [:index, :create]
end
get 'groups/:group_id/files', controller: :files, action: :api_index, as: 'group_files'
get 'groups/:group_id/folders', controller: :folders, action: :list_all_folders, as: 'group_folders'
post 'groups/:group_id/folders', controller: :folders, action: :create
get 'groups/:group_id/folders/by_path/*full_path', controller: :folders, action: :resolve_path
get 'groups/:group_id/folders/by_path', controller: :folders, action: :resolve_path
get 'groups/:group_id/folders/:id', controller: :folders, action: :show, as: 'group_folder'
end
scope(controller: :developer_keys) do
get 'developer_keys', action: :index
get 'developer_keys/:id', action: :show
delete 'developer_keys/:id', action: :destroy
put 'developer_keys/:id', action: :update
post 'developer_keys', action: :create
get 'accounts/:account_id/developer_keys', action: :index
post 'accounts/:account_id/developer_keys', action: :create
end
scope(controller: :search) do
get 'search/rubrics', action: 'rubrics', as: 'search_rubrics'
get 'search/recipients', action: 'recipients', as: 'search_recipients'
get 'search/all_courses', action: 'all_courses', as: 'search_all_courses'
end
post 'files/:id/create_success', controller: :files, action: :api_create_success, as: 'files_create_success'
get 'files/:id/create_success', controller: :files, action: :api_create_success
scope(controller: :files) do
post 'files/:id/create_success', action: :api_create_success
get 'files/:id/create_success', action: :api_create_success
match '/api/v1/files/:id/create_success', via: [:options], action: :api_create_success_cors
modules api, closes #10404 also modifies the discussion topic and assignment API controllers to make sure "must_view" requirements are fulfilled test plan: * check the API documentation; ensure it looks okay * create a course with module items of each supported type * set completion criteria of each supported type * create another module, so you can set prerequisites * use the list modules API and verify its output matches the course and the documentation * as a teacher, "state" should be missing * as a student, "state" should be "locked", "unlocked", "started", or "completed" * use the show module API and verify the correct information is returned for a single module * use the list module items API and verify the output * as a teacher, the "completion_requirement" omits the "completed" flag * as a student, "completed" should be true or false, depending on whether the requirement was met * use the show module API and verify the correct information is returned for a single module item * last but not least, verify "must view" requirements can be fulfilled through the api_data_endpoints supplied for files, pages, discussions, and assignments * files are viewed when downloading their content * pages are viewed by the show action (where content is returned) * discussions are viewed when marked read via the mark_topic_read or mark_all_read actions * assignments are viewed by the show action (where description is returned). they are not viewed if the assignment is locked and the user does not have access to the content yet. Change-Id: I0cbbbc542f69215e7b396a501d4d86ff2f76c149 Reviewed-on: https://gerrit.instructure.com/13626 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Simon Williams <simon@instructure.com>
2012-09-12 01:16:48 +08:00
# 'attachment' (rather than 'file') is used below so modules API can use polymorphic_url to generate an item API link
get 'files/:id', action: :api_show, as: 'attachment'
delete 'files/:id', action: :destroy
put 'files/:id', action: :api_update
get 'files/:id/:uuid/status', action: :api_file_status, as: 'file_status'
get 'files/:id/public_url', action: :public_url
%w(course group user).each do |context|
get "#{context}s/:#{context}_id/files/quota", action: :api_quota
get "#{context}s/:#{context}_id/files/:id", action: :api_show, as: "#{context}_attachment"
end
end
scope(controller: :folders) do
get 'folders/:id', action: :show
get 'folders/:id/folders', action: :api_index, as: 'list_folders'
get 'folders/:id/files', controller: :files, action: :api_index, as: 'list_files'
delete 'folders/:id', action: :api_destroy
put 'folders/:id', action: :update
post 'folders/:folder_id/folders', action: :create, as: 'create_folder'
post 'folders/:folder_id/files', action: :create_file
post 'folders/:dest_folder_id/copy_file', action: :copy_file
post 'folders/:dest_folder_id/copy_folder', action: :copy_folder
end
scope(controller: :favorites) do
get "users/self/favorites/courses", action: :list_favorite_courses, as: :list_favorite_courses
post "users/self/favorites/courses/:id", action: :add_favorite_course, as: :add_favorite_course
delete "users/self/favorites/courses/:id", action: :remove_favorite_course, as: :remove_favorite_course
delete "users/self/favorites/courses", action: :reset_course_favorites
get "users/self/favorites/groups", action: :list_favorite_groups, as: :list_favorite_groups
post "users/self/favorites/groups/:id", action: :add_favorite_groups, as: :add_favorite_groups
delete "users/self/favorites/groups/:id", action: :remove_favorite_groups, as: :remove_favorite_groups
delete "users/self/favorites/groups", action: :reset_groups_favorites
end
scope(controller: :wiki_pages_api) do
get "courses/:course_id/front_page", action: :show_front_page
get "groups/:group_id/front_page", action: :show_front_page
put "courses/:course_id/front_page", action: :update_front_page
put "groups/:group_id/front_page", action: :update_front_page
allow PUT requests to create wiki pages implicitly testing note: this change affects all wiki page endpoints: api, draft state, and non-draft state. basic functionality for all of these pages should be verified, specifically when dealing with non-existent or deleted pages. test plan: * PUT to /api/v1/courses/:course_id/front_page - variations: * wiki_page[title] - provided/not provided * wiki_page[published] - true/false/not provided * wiki_page[hide_from_students] - true/false/not provided (hiding/unpublishing the front page is not allowed) * PUT to /api/v1/courses/:course_id/pages/non-existent-page - same variations as front_page (above) * navigating to a non-existent/deleted page (draft state/non-draft state) - should redirect teachers to the edit page - should redirect students to the index page (with an alert message indicating why) * navigating to the 'Pages' tab (non-draft state) - if the 'Front Page' exists - shows the page - if the 'Front Page' has been deleted (with draft state enabled) - shows the edit page - if the 'Front Page' has never existed - shows the edit page * all other pages functionality should remain unchanged - non-draft state UI - show page - edit page - draft state UI - index page - show page - edit page - api - .../pages - GET (index) - POST (create page) - .../front_page - GET (show front page) - PUT (create/update front page) - .../pages/page-url - GET (show page) - PUT (create/update page) - DELETE (destroy page) fixes CNVS-8488 Change-Id: I563e6944e1602e0b21ab69c6fe2dcd643c06611d Reviewed-on: https://gerrit.instructure.com/23590 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Matt Fairbourn <mfairbourn@instructure.com> Reviewed-by: Jeremy Stanley <jeremy@instructure.com> Product-Review: Bracken Mosbacker <bracken@instructure.com>
2013-08-22 23:43:03 +08:00
get "courses/:course_id/pages", action: :index, as: 'course_wiki_pages'
get "groups/:group_id/pages", action: :index, as: 'group_wiki_pages'
get "courses/:course_id/pages/:url", action: :show, as: 'course_wiki_page'
get "groups/:group_id/pages/:url", action: :show, as: 'group_wiki_page'
get "courses/:course_id/pages/:url/revisions", action: :revisions, as: 'course_wiki_page_revisions'
get "groups/:group_id/pages/:url/revisions", action: :revisions, as: 'group_wiki_page_revisions'
get "courses/:course_id/pages/:url/revisions/latest", action: :show_revision
get "groups/:group_id/pages/:url/revisions/latest", action: :show_revision
get "courses/:course_id/pages/:url/revisions/:revision_id", action: :show_revision
get "groups/:group_id/pages/:url/revisions/:revision_id", action: :show_revision
post "courses/:course_id/pages/:url/revisions/:revision_id", action: :revert
post "groups/:group_id/pages/:url/revisions/:revision_id", action: :revert
post "courses/:course_id/pages", action: :create
post "groups/:group_id/pages", action: :create
put "courses/:course_id/pages/:url", action: :update
put "groups/:group_id/pages/:url", action: :update
delete "courses/:course_id/pages/:url", action: :destroy
delete "groups/:group_id/pages/:url", action: :destroy
end
scope(controller: :context_modules_api) do
get "courses/:course_id/modules", action: :index, as: 'course_context_modules'
get "courses/:course_id/modules/:id", action: :show, as: 'course_context_module'
put "courses/:course_id/modules", action: :batch_update
post "courses/:course_id/modules", action: :create, as: 'course_context_module_create'
put "courses/:course_id/modules/:id", action: :update, as: 'course_context_module_update'
delete "courses/:course_id/modules/:id", action: :destroy
put "courses/:course_id/modules/:id/relock", action: :relock
end
scope(controller: :context_module_items_api) do
get "courses/:course_id/modules/:module_id/items", action: :index, as: 'course_context_module_items'
get "courses/:course_id/modules/:module_id/items/:id", action: :show, as: 'course_context_module_item'
put "courses/:course_id/modules/:module_id/items/:id/done", action: :mark_as_done, as: 'course_context_module_item_done'
delete "courses/:course_id/modules/:module_id/items/:id/done", action: :mark_as_not_done, as: 'course_context_module_item_not_done'
get "courses/:course_id/module_item_redirect/:id", action: :redirect, as: 'course_context_module_item_redirect'
get "courses/:course_id/module_item_sequence", action: :item_sequence
post "courses/:course_id/modules/:module_id/items", action: :create, as: 'course_context_module_items_create'
put "courses/:course_id/modules/:module_id/items/:id", action: :update, as: 'course_context_module_item_update'
delete "courses/:course_id/modules/:module_id/items/:id", action: :destroy
post "courses/:course_id/modules/:module_id/items/:id/mark_read", action: :mark_item_read
end
scope(controller: 'quizzes/quiz_assignment_overrides') do
get "courses/:course_id/quizzes/assignment_overrides", action: :index, as: 'course_quiz_assignment_overrides'
quiz index optimizations Closes CNVS-15109, CNVS-15173 CHANGES ------- - "auto-grading" of due submissions that was previously done synchronously in the index action is now done in a DJ - when viewing the index page, you don't get to see due/available dates on load, instead the dates are fetched on the client-side and load progressively - new API endpoint for retrieving assignment overrides for a bunch of quizzes at [GET] /courses/:course_id/quizzes/assignment_overrides - we now cache the user's quiz permissions - Canvas AMS API serializer now accepts a new option, see docs - QuizSerializer behavior changed radically: - "takeable", "submitted_students", "unsubmitted_students" disabled - all associations disabled including the submission, assignment group, and any student participants - it can now utilize preloaded permissions Rationale behind disabling things in the serializer is that these were exclusive for the "show" action, so the next step forwards is to allow the serializer to recognize different "modes" for output (e.g, for index and one for show) and tailor the associations/fields accordingly. Using "#filter" right now isn't cutting it, because assocs get loaded anyway. REFACTORING ----------- - broke down index into three actions for visibility: 1. default, Draft-State version 2. legacy non-DS version that's not reachable in the UI, kept around until we upgrade the tests 3. ember version - legacy non-DS ERB code goes into its own file - moved code that used to grade due submissions inside index to SubmissionGrader in preparation to remove it from there entirely - cleaned up internal docs for the Canvas AMS api serializer TEST PLAN ---- ---- - create ~30 quizzes + make one of them have many questions + make a good number of submissions (i tested with 420 and 20 students) - create multiple sections + specify date overrides for certain sections, and have at least one student enrolled in that section - as a teacher and/or an observer, go to quizzes index + verify the page renders fine + verify that you see "loading indicators" in the due/available field which get replaced with actual dates when they're loaded + verify it's faster than the version in master (should be at least 60% faster) - as a student in the general section, go to quizzes index + verify the page renders + verify you see the same loading behavior for dates as in teacher view - as a student in one of the section with overrides, go to index: + verify you see the overridden date Change-Id: I741d89625da1b858148baa95e881fcc75c1802e5 Reviewed-on: https://gerrit.instructure.com/40350 Reviewed-by: Derek DeVries <ddevries@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Trevor deHaan <tdehaan@instructure.com> Product-Review: Ahmad Amireh <ahmad@instructure.com>
2014-08-31 15:20:52 +08:00
end
scope(controller: 'quizzes/quizzes_api') do
get "courses/:course_id/quizzes", action: :index, as: 'course_quizzes'
post "courses/:course_id/quizzes", action: :create, as: 'course_quiz_create'
get "courses/:course_id/quizzes/:id", action: :show, as: 'course_quiz'
put "courses/:course_id/quizzes/:id", action: :update, as: 'course_quiz_update'
delete "courses/:course_id/quizzes/:id", action: :destroy, as: 'course_quiz_destroy'
post "courses/:course_id/quizzes/:id/reorder", action: :reorder, as: 'course_quiz_reorder'
post "courses/:course_id/quizzes/:id/validate_access_code", action: :validate_access_code, as: 'course_quiz_validate_access_code'
end
scope(controller: 'quizzes/quiz_submission_users') do
get "courses/:course_id/quizzes/:id/submission_users", action: :index, as: 'course_quiz_submission_users'
post "courses/:course_id/quizzes/:id/submission_users/message", action: :message, as: 'course_quiz_submission_users_message'
end
scope(controller: 'quizzes/quiz_groups') do
get "courses/:course_id/quizzes/:quiz_id/groups/:id", action: :show, as: 'course_quiz_group'
post "courses/:course_id/quizzes/:quiz_id/groups", action: :create, as: 'course_quiz_group_create'
put "courses/:course_id/quizzes/:quiz_id/groups/:id", action: :update, as: 'course_quiz_group_update'
delete "courses/:course_id/quizzes/:quiz_id/groups/:id", action: :destroy, as: 'course_quiz_group_destroy'
post "courses/:course_id/quizzes/:quiz_id/groups/:id/reorder", action: :reorder, as: 'course_quiz_group_reorder'
end
scope(controller: 'quizzes/quiz_questions') do
get "courses/:course_id/quizzes/:quiz_id/questions", action: :index, as: 'course_quiz_questions'
get "courses/:course_id/quizzes/:quiz_id/questions/:id", action: :show, as: 'course_quiz_question'
post "courses/:course_id/quizzes/:quiz_id/questions", action: :create, as: 'course_quiz_question_create'
put "courses/:course_id/quizzes/:quiz_id/questions/:id", action: :update, as: 'course_quiz_question_update'
delete "courses/:course_id/quizzes/:quiz_id/questions/:id", action: :destroy, as: 'course_quiz_question_destroy'
end
scope(controller: 'quizzes/quiz_reports') do
post "courses/:course_id/quizzes/:quiz_id/reports", action: :create, as: 'course_quiz_reports_create'
Quiz Reports API - force regeneration Extends the quiz reports API with the ability to re-trigger failed CSV generation jobs, and to abort them completely. The UI is extended to utilize those new APIs. Closes CNVS-16525 TEST PLAN ---- ---- - create a quiz with a file upload question - take the quiz by a student and upload a file, then submit - turn on new stats and go to new stats page - click the "Student Analysis" report generator button and verify that the CSV file is generated and you get prompted to save it Now... we break the student's submission by removing the attachment and then the student analysis will start failing to generate. Launch a rails console and perform the following command: [ 'Quizzes::QuizSubmission', 'Quizzes::QuizStatistics' ].each do |type| Attachment.where({ context_type: type }).last.destroy! end - reload the stats page + the "Student Analysis" button should now read that it had never been generated, that's right because we just removed the CSV file attachment using the console + try generating the report again - verify that it blows up + you should now see a notification as in the screencast - clicking the "retry" link should retry generating the report (which will fail again) - clicking the "cancel" link should remove the notification - clicking "Dismiss" should dismiss the notification, but if you reload the page, it's still there Change-Id: I467a9030c3ef94d685ec20b31dd533e530e24758 Reviewed-on: https://gerrit.instructure.com/43862 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Trevor deHaan <tdehaan@instructure.com> Reviewed-by: Derek DeVries <ddevries@instructure.com> Product-Review: Derek DeVries <ddevries@instructure.com>
2014-10-29 00:11:34 +08:00
delete "courses/:course_id/quizzes/:quiz_id/reports/:id", action: :abort, as: 'course_quiz_reports_abort'
get "courses/:course_id/quizzes/:quiz_id/reports", action: :index, as: 'course_quiz_reports'
get "courses/:course_id/quizzes/:quiz_id/reports/:id", action: :show, as: 'course_quiz_report'
end
scope(controller: 'quizzes/quiz_submission_files') do
post 'courses/:course_id/quizzes/:quiz_id/submissions/self/files', action: :create, as: 'quiz_submission_files'
end
scope(controller: 'quizzes/quiz_submissions_api') do
get 'courses/:course_id/quizzes/:quiz_id/submissions', action: :index, as: 'course_quiz_submissions'
get 'courses/:course_id/quizzes/:quiz_id/submissions/:id', action: :show, as: 'course_quiz_submission'
get 'courses/:course_id/quizzes/:quiz_id/submissions/:id/time', action: :time, as: 'course_quiz_submission_time'
post 'courses/:course_id/quizzes/:quiz_id/submissions', action: :create, as: 'course_quiz_submission_create'
put 'courses/:course_id/quizzes/:quiz_id/submissions/:id', action: :update, as: 'course_quiz_submission_update'
post 'courses/:course_id/quizzes/:quiz_id/submissions/:id/complete', action: :complete, as: 'course_quiz_submission_complete'
end
scope(:controller => 'quizzes/outstanding_quiz_submissions') do
get 'courses/:course_id/quizzes/:quiz_id/outstanding_quiz_submissions', :action => :index, :path_name => 'outstanding_quiz_submission_index'
post 'courses/:course_id/quizzes/:quiz_id/outstanding_quiz_submissions', :action => :grade, :path_name => 'outstanding_quiz_submission_grade'
end
scope(controller: 'quizzes/quiz_extensions') do
post 'courses/:course_id/quizzes/:quiz_id/extensions', action: :create, as: 'course_quiz_extensions_create'
add api for quiz submission extensions quiz submissions can have their time limit or number of attempts extended. we can extend both existing quiz submissions, and also those that don't exist yet. adding this functionality to the existing quiz submissions api would muddle up responsibilities. So instead we post all extensions to a the quiz extensions api which is specifically meant for adding extensions to a submission whether it has been started yet or not. Also add 'manually_unlocked' to the quiz submissions api. this field lets us know if a student can take a quiz after it has been locked for everyone else. fixes CNVS-13165 test plan - There is a new attribute added to quiz_submissions objects in the api called 'manually_unlocked'. This attribute will now show up when returning results back from - GET /api/v1/courses/:course_id/quizzes/:quiz_id/submissions (index) - GET /api/v1/courses/:course_id/quizzes/:quiz_id/submissions/:id (show) - There is a new endpoint to create quiz extensions. This should work to create quiz extensions for users that both have existing quiz submissions started, and users who have not yet started a quiz: - POST /api/v1/courses/:course_id/quizzes/:quiz_id/extensions (create) - Check Permissions on the new quiz extension endpoint. Only teachers should be able to extend the quizzes. - Check that all the documentation looks okay for quiz extensions. Change-Id: Ie23113c1f30e139a1e376475fb35a2cf3ce0212c Reviewed-on: https://gerrit.instructure.com/35111 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Ahmad Amireh <ahmad@instructure.com> QA-Review: Caleb Guanzon <cguanzon@instructure.com> Product-Review: Derek DeVries <ddevries@instructure.com>
2014-05-20 04:04:00 +08:00
end
scope(controller: 'quizzes/course_quiz_extensions') do
post 'courses/:course_id/quiz_extensions', action: :create
end
scope(controller: "quizzes/quiz_submission_events_api") do
get "courses/:course_id/quizzes/:quiz_id/submissions/:id/events", action: :index, as: 'course_quiz_submission_events'
post "courses/:course_id/quizzes/:quiz_id/submissions/:id/events", action: :create, as: 'create_quiz_submission_events'
end
scope(controller: 'quizzes/quiz_submission_questions') do
get '/quiz_submissions/:quiz_submission_id/questions', action: :index, as: 'quiz_submission_questions'
post '/quiz_submissions/:quiz_submission_id/questions', action: :answer, as: 'quiz_submission_question_answer'
get '/quiz_submissions/:quiz_submission_id/questions/:id', action: :show, as: 'quiz_submission_question'
put '/quiz_submissions/:quiz_submission_id/questions/:id/flag', action: :flag, as: 'quiz_submission_question_flag'
put '/quiz_submissions/:quiz_submission_id/questions/:id/unflag', action: :unflag, as: 'quiz_submission_question_unflag'
Quiz Submission Questions API - Update This patch provides support for answering Quiz Questions via the API. closes CNVS-9844, CNVS-10225 TEST PLAN ---- ---- Testing this will be a bit rough because there are many variations and validations to cover. I'll spare the validations that are covered by specs from the test plan. Create a quiz with a question of *each* type except "Text" and "File Upload". There's a script that creates a quiz with its questions automatically for you if you don't want to keep doing this manually. See references. > Answering Questions Now you need to answer each question via the API. Most of them vary in formats, but they are fully specified in the API documentation page (along with examples). See DOCUMENTATION for more info. > Flagging Questions Flagging, and unflagging, a question is the same regardless of its type, see the "EXAMPLE REQUESTS" section. > Access Validations Here are some generic, non-question based validations to verify. You should NOT be able to answer a question if: - the quiz submission has been turned in - the quiz submission is overdue - the Access Code for the quiz is invalid - the IP filter of the Quiz prohibits you from taking the quiz - the quiz submission :validation_token is incorrectly specified (ie, other students shouldn't be able to answer your questions) - you don't specify the latest :attempt, so if the Quiz has multiple attempts, and this is your 2nd take, you specify an :attempt of 1, 3, or anything but 2 should fail - NEW: turn quiz into an OQAAT quiz with the "Can't go back" flag on; the API should not reject all requests to modify any of the questions with a 501 error saying that type of quizzes is not supported yet (support will come in CNVS-10224) > Grading Also, when you're done answering the questions, take a look at the grades and make sure everything gets graded just like it does when using the UI directly. > Verifying results in the browser While taking a quiz in the canvas UI, the scripts perform backups in the background that would overwrite any changes you do via the API. If you want to verify the changes you make via the API from the UI, you must append "?backup=false" to the take quiz page URL, something like this: http://localhost:3000/courses/1/quizzes/1/take?backup=false Setting that flag will (for now) disable the backup behaviour and should make things tick. EXAMPLE REQUESTS ------- -------- Don't forget to set the 'Content-Type' header to 'application/json'! > Answering a Multiple-Choice question [PUT] /api/v1/quiz_submissions/:quiz_submission_id/questions/:id { "attempt": 1, "validation_token": "1babd0...", "answer": 10 } > Flagging a question [PUT] /api/v1/quiz_submissions/:quiz_submission_id/questions/:id/flag { "attempt": 1, "validation_token": "1babd0..." } > Unflagging a question [PUT] /api/v1/quiz_submissions/:quiz_submission_id/questions/:id/unflag { "attempt": 1, "validation_token": "1babd0..." } DOCUMENTATION ------------- Run `bundle exec rake doc:api` and check out the Quiz Submission Questions page. There's an Appendix that contains example requests for each question type, as well as the errors produced by each handler. LINKS ----- - bootstrap script: https://gist.github.com/amireh/e7e8f835ffbf1d053e4c - direct link to the API documentation page: http://canvas.docs.kodoware.com/quiz_submission_questions.html Change-Id: I9a958323ece8854bc21a24c2affd8dc3972e46d5 Reviewed-on: https://gerrit.instructure.com/27206 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Derek DeVries <ddevries@instructure.com> QA-Review: Myller de Araujo <myller@instructure.com> Product-Review: Ahmad Amireh <ahmad@instructure.com>
2013-12-10 17:15:01 +08:00
end
scope(controller: 'quizzes/quiz_ip_filters') do
get 'courses/:course_id/quizzes/:quiz_id/ip_filters', action: :index, as: 'course_quiz_ip_filters'
Quiz IP Filters API controller - #index This patch moves rendering of IP filters from the QuizzesController into a separate, specialized API controller - QuizzesIpFilters. The rendered IP filter object is backwards-compatible, as in it provides the same three attributes: name, account, and filter. However, the endpoint output has been modified to scope the array of filters under "quiz_ip_filters". The front-end/JS part has been adjusted to accommodate this change. REFACTORING ----------- In an effort to reduce complexity, I've also taken to refactor all the :before_filters that were looking up Quiz in the current context across all Quiz controllers (where it was applicable), and that was done by introducing a new component set: API Helpers. API Helpers are modules that can be mixed-in, just like the API Modules, that are really just a place to hold routines common between the API and the regular controllers. I've put the first one in lib/api/v1/helpers, namespaced under Api::V1::Helpers... TEST PLAN ---- ---- - Create a Quiz. No questions. - Set an IP filter of 192.168.1.1 on the Quiz - the restriction should still hold like it usually does - Perform a GET request to this endpoint: /courses/:course_id/quizzes/:quiz_id/ip_filters - A list of filters should be returned in JSON-API format containing the filter you set for the Quiz - Add one or more IP Filters on the account-level, and: - Re-perform the GET query: - The list should contain both the Quiz and the Account filters - Using the IP Filter search box from the Quiz settings page: - It should still properly list the available filters refs CNVS-8988, CNVS-9586 Change-Id: I75c1b85024a58e6accd1627b7bee3da1185d2658 Reviewed-on: https://gerrit.instructure.com/26440 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Derek DeVries <ddevries@instructure.com> QA-Review: Myller de Araujo <myller@instructure.com> Product-Review: Ahmad Amireh <ahmad@instructure.com>
2013-11-19 17:06:49 +08:00
end
scope(controller: 'quizzes/quiz_statistics') do
get 'courses/:course_id/quizzes/:quiz_id/statistics', action: :index, as: 'course_quiz_statistics'
end
Quiz IP Filters API controller - #index This patch moves rendering of IP filters from the QuizzesController into a separate, specialized API controller - QuizzesIpFilters. The rendered IP filter object is backwards-compatible, as in it provides the same three attributes: name, account, and filter. However, the endpoint output has been modified to scope the array of filters under "quiz_ip_filters". The front-end/JS part has been adjusted to accommodate this change. REFACTORING ----------- In an effort to reduce complexity, I've also taken to refactor all the :before_filters that were looking up Quiz in the current context across all Quiz controllers (where it was applicable), and that was done by introducing a new component set: API Helpers. API Helpers are modules that can be mixed-in, just like the API Modules, that are really just a place to hold routines common between the API and the regular controllers. I've put the first one in lib/api/v1/helpers, namespaced under Api::V1::Helpers... TEST PLAN ---- ---- - Create a Quiz. No questions. - Set an IP filter of 192.168.1.1 on the Quiz - the restriction should still hold like it usually does - Perform a GET request to this endpoint: /courses/:course_id/quizzes/:quiz_id/ip_filters - A list of filters should be returned in JSON-API format containing the filter you set for the Quiz - Add one or more IP Filters on the account-level, and: - Re-perform the GET query: - The list should contain both the Quiz and the Account filters - Using the IP Filter search box from the Quiz settings page: - It should still properly list the available filters refs CNVS-8988, CNVS-9586 Change-Id: I75c1b85024a58e6accd1627b7bee3da1185d2658 Reviewed-on: https://gerrit.instructure.com/26440 Tested-by: Jenkins <jenkins@instructure.com> Reviewed-by: Derek DeVries <ddevries@instructure.com> QA-Review: Myller de Araujo <myller@instructure.com> Product-Review: Ahmad Amireh <ahmad@instructure.com>
2013-11-19 17:06:49 +08:00
scope(controller: 'polling/polls') do
get "polls", action: :index, as: 'polls'
post "polls", action: :create, as: 'poll_create'
get "polls/:id", action: :show, as: 'poll'
put "polls/:id", action: :update, as: 'poll_update'
delete "polls/:id", action: :destroy, as: 'poll_destroy'
end
scope(controller: 'polling/poll_choices') do
get "polls/:poll_id/poll_choices", action: :index, as: 'poll_choices'
post "polls/:poll_id/poll_choices", action: :create, as: 'poll_choices_create'
get "polls/:poll_id/poll_choices/:id", action: :show, as: 'poll_choice'
put "polls/:poll_id/poll_choices/:id", action: :update, as: 'poll_choice_update'
delete "polls/:poll_id/poll_choices/:id", action: :destroy, as: 'poll_choice_destroy'
add polling session and submission apis fixes CNVS-12474, CNVS-12477, CNVS-12478 this commit fleshes out the API endpoints for polling sessions and submissions, and solidifies the other polling endpoints. Test plan - Full tests on the following endpoints: - Polls are the basic data model of the polling app. They can take a question attribute and a description attribute. They are only creatable and modifiable by teachers. - GET /api/v1/polls (index action) - POST /api/v1/polls (create action) - GET /api/v1/polls/:id (show action) - PUT /api/v1/polls/:id (update action) - DELETE /api/v1/polls/:id (destroy action) - Poll choices belong to polls. They consist of the particular answers a submitter can choose when participating in a poll session. They have attributes of text (the answer text), their associated poll, and an 'is_correct' boolean attribute. The 'is_correct' attribute show not be accessible by students. Poll choices are only creatable and modifiable by the creator of the poll. - GET /api/v1/polls/:poll_id/poll_choices (index action) - POST /api/v1/polls/:poll_id/poll_choices (create action) - GET /api/v1/polls/:poll_id/poll_choices/:id (show action) - PUT /api/v1/polls/:poll_id/poll_choices/:id (update action) - DELETE /api/v1/polls/:poll_id/poll_choices/:id (destroy action) - Poll sessions are for publishing a poll so that it can accept submissions. They should only be createable / modifiable by teachers. Only students that are enrolled in the associated course of the poll session should be allowed to view them. The show action of a poll session acts differently for a teacher. They are able to see the results of the voting that has taken place by students since the session was published. - GET /api/v1/polls/:poll_id/poll_sessions (index action) - POST /api/v1/polls/:poll_id/poll_sessions (create action) - GET /api/v1/polls/:poll_id/poll_sessions/:id (show action) - PUT /api/v1/polls/:poll_id/poll_sessions/:id (update action) - DELETE /api/v1/polls/:poll_id/poll_sessions/:id (destroy action) - GET /api/v1/polls/:poll_id/poll_sessions/:id/publish (publish action) - GET /api/v1/polls/:poll_id/poll_sessions/:id/close (close action) - Poll submissions are for submitting an answer for a particular poll session. A student should only be allowed to submit a poll choice for a session they're able to view, and they can only submit one poll choice per poll session. - GET /api/v1/polls/:poll_id/poll_sessions/:poll_session_id/poll_submissions/:id (show action) - POST /api/v1/polls/:poll_id/poll_sessions/:poll_session_id/poll_submissions (create action) Change-Id: Ifcfd72ec30597e37fc54c687fb7d61a644d7348c Reviewed-on: https://gerrit.instructure.com/34605 Reviewed-by: Derek DeVries <ddevries@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Caleb Guanzon <cguanzon@instructure.com> Product-Review: Josh Simpson <jsimpson@instructure.com>
2014-05-06 05:58:49 +08:00
end
scope(controller: 'polling/poll_sessions') do
get "polls/:poll_id/poll_sessions", action: :index, as: 'poll_sessions'
post "polls/:poll_id/poll_sessions", action: :create, as: 'poll_sessions_create'
get "polls/:poll_id/poll_sessions/:id", action: :show, as: 'poll_session'
put "polls/:poll_id/poll_sessions/:id", action: :update, as: 'poll_session_update'
delete "polls/:poll_id/poll_sessions/:id", action: :destroy, as: 'poll_session_destroy'
get "polls/:poll_id/poll_sessions/:id/open", action: :open, as: 'poll_session_publish'
get "polls/:poll_id/poll_sessions/:id/close", action: :close, as: 'poll_session_close'
get "poll_sessions/opened", action: :opened, as: 'poll_sessions_opened'
get "poll_sessions/closed", action: :closed, as: 'poll_sessions_closed'
add polling session and submission apis fixes CNVS-12474, CNVS-12477, CNVS-12478 this commit fleshes out the API endpoints for polling sessions and submissions, and solidifies the other polling endpoints. Test plan - Full tests on the following endpoints: - Polls are the basic data model of the polling app. They can take a question attribute and a description attribute. They are only creatable and modifiable by teachers. - GET /api/v1/polls (index action) - POST /api/v1/polls (create action) - GET /api/v1/polls/:id (show action) - PUT /api/v1/polls/:id (update action) - DELETE /api/v1/polls/:id (destroy action) - Poll choices belong to polls. They consist of the particular answers a submitter can choose when participating in a poll session. They have attributes of text (the answer text), their associated poll, and an 'is_correct' boolean attribute. The 'is_correct' attribute show not be accessible by students. Poll choices are only creatable and modifiable by the creator of the poll. - GET /api/v1/polls/:poll_id/poll_choices (index action) - POST /api/v1/polls/:poll_id/poll_choices (create action) - GET /api/v1/polls/:poll_id/poll_choices/:id (show action) - PUT /api/v1/polls/:poll_id/poll_choices/:id (update action) - DELETE /api/v1/polls/:poll_id/poll_choices/:id (destroy action) - Poll sessions are for publishing a poll so that it can accept submissions. They should only be createable / modifiable by teachers. Only students that are enrolled in the associated course of the poll session should be allowed to view them. The show action of a poll session acts differently for a teacher. They are able to see the results of the voting that has taken place by students since the session was published. - GET /api/v1/polls/:poll_id/poll_sessions (index action) - POST /api/v1/polls/:poll_id/poll_sessions (create action) - GET /api/v1/polls/:poll_id/poll_sessions/:id (show action) - PUT /api/v1/polls/:poll_id/poll_sessions/:id (update action) - DELETE /api/v1/polls/:poll_id/poll_sessions/:id (destroy action) - GET /api/v1/polls/:poll_id/poll_sessions/:id/publish (publish action) - GET /api/v1/polls/:poll_id/poll_sessions/:id/close (close action) - Poll submissions are for submitting an answer for a particular poll session. A student should only be allowed to submit a poll choice for a session they're able to view, and they can only submit one poll choice per poll session. - GET /api/v1/polls/:poll_id/poll_sessions/:poll_session_id/poll_submissions/:id (show action) - POST /api/v1/polls/:poll_id/poll_sessions/:poll_session_id/poll_submissions (create action) Change-Id: Ifcfd72ec30597e37fc54c687fb7d61a644d7348c Reviewed-on: https://gerrit.instructure.com/34605 Reviewed-by: Derek DeVries <ddevries@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Caleb Guanzon <cguanzon@instructure.com> Product-Review: Josh Simpson <jsimpson@instructure.com>
2014-05-06 05:58:49 +08:00
end
scope(controller: 'polling/poll_submissions') do
post "polls/:poll_id/poll_sessions/:poll_session_id/poll_submissions", action: :create, as: 'poll_submissions_create'
get "polls/:poll_id/poll_sessions/:poll_session_id/poll_submissions/:id", action: :show, as: 'poll_submission'
end
scope(controller: 'live_assessments/assessments') do
2015-06-26 03:35:25 +08:00
get "courses/:course_id/live_assessments", action: :index, as: "course_live_assessments"
post "courses/:course_id/live_assessments", action: :create, as: "course_live_assessment_create"
end
scope(controller: 'live_assessments/results') do
2015-06-26 03:35:25 +08:00
get "courses/:course_id/live_assessments/:assessment_id/results", action: :index, as: "course_live_assessment_results"
post "courses/:course_id/live_assessments/:assessment_id/results", action: :create, as: "course_live_assessment_result_create"
end
scope(controller: :outcome_groups_api) do
2015-06-26 03:35:25 +08:00
%w(global account course).each do |context|
prefix = (context == "global" ? context : "#{context}s/:#{context}_id")
unless context == "global"
get "#{prefix}/outcome_groups", action: :index, as: "#{context}_outcome_groups"
get "#{prefix}/outcome_group_links", action: :link_index, as: "#{context}_outcome_group_links"
end
get "#{prefix}/root_outcome_group", action: :redirect, as: "#{context}_redirect"
get "#{prefix}/outcome_groups/account_chain", action: :account_chain, as: "#{context}_account_chain"
get "#{prefix}/outcome_groups/:id", action: :show, as: "#{context}_outcome_group"
put "#{prefix}/outcome_groups/:id", action: :update
delete "#{prefix}/outcome_groups/:id", action: :destroy
get "#{prefix}/outcome_groups/:id/outcomes", action: :outcomes, as: "#{context}_outcome_group_outcomes"
get "#{prefix}/outcome_groups/:id/available_outcomes", action: :available_outcomes, as: "#{context}_outcome_group_available_outcomes"
post "#{prefix}/outcome_groups/:id/outcomes", action: :link
put "#{prefix}/outcome_groups/:id/outcomes/:outcome_id", action: :link, as: "#{context}_outcome_link"
delete "#{prefix}/outcome_groups/:id/outcomes/:outcome_id", action: :unlink
get "#{prefix}/outcome_groups/:id/subgroups", action: :subgroups, as: "#{context}_outcome_group_subgroups"
post "#{prefix}/outcome_groups/:id/subgroups", action: :create
post "#{prefix}/outcome_groups/:id/import", action: :import, as: "#{context}_outcome_group_import"
post "#{prefix}/outcome_groups/:id/batch", action: :batch, as: "#{context}_outcome_group_batch"
end
end
scope(controller: :outcomes_api) do
get "outcomes/:id", action: :show, as: "outcome"
put "outcomes/:id", action: :update
delete "outcomes/:id", action: :destroy
end
scope(controller: :outcome_results) do
get 'courses/:course_id/outcome_rollups', action: :rollups, as: 'course_outcome_rollups'
get 'courses/:course_id/outcome_results', action: :index, as: 'course_outcome_results'
end
scope(controller: :outcomes_import_api) do
# These can be uncommented when implemented
# get "global/outcomes_import", action: :index
# get "global/outcomes_import/:id", action: :show
# put "global/outcomes_import/:id", action: :cancel
# get "global/outcomes_import/list/:guid", action: :list
get "global/outcomes_import/available", action: :available
post "global/outcomes_import", action: :create
get "global/outcomes_import/migration_status/:migration_id", action: :migration_status
end
scope(controller: :group_categories) do
resources :group_categories, except: [:index, :create]
get 'accounts/:account_id/group_categories', action: :index, as: 'account_group_categories'
get 'courses/:course_id/group_categories', action: :index, as: 'course_group_categories'
post 'accounts/:account_id/group_categories', action: :create
post 'courses/:course_id/group_categories', action: :create
get 'group_categories/:group_category_id/groups', action: :groups, as: 'group_category_groups'
get 'group_categories/:group_category_id/users', action: :users, as: 'group_category_users'
post 'group_categories/:group_category_id/assign_unassigned_members', action: 'assign_unassigned_members', as: 'group_category_assign_unassigned_members'
end
scope(controller: :progress) do
get "progress/:id", action: :show, as: "progress"
end
scope(controller: :app_center) do
2015-06-26 03:35:25 +08:00
%w(course account).each do |context|
prefix = "#{context}s/:#{context}_id/app_center"
get "#{prefix}/apps", action: :index, as: "#{context}_app_center_apps"
get "#{prefix}/apps/:app_id/reviews", action: :reviews, as: "#{context}_app_center_app_reviews"
get "#{prefix}/apps/:app_id/reviews/self", action: :review, as: "#{context}_app_center_app_review"
post "#{prefix}/apps/:app_id/reviews/self", action: :add_review
end
end
feature flags infrastructure and API test plan: - install the test_features plugin (since no real features exist yet) - render and consult the feature flags documentation - have a test environment with a root account, sub-account, course in sub-account, and user - Use the "list features" endpoint as a root account admin (with no site admin privileges), on the root account context, and confirm that hidden features do not show up - Use the "list features" endpoint as a site admin user, on the root account context, and confirm that hidden features show up - Use the "list features" endpoint on the site admin account and confirm the hidden features show up - Use the "set feature flag" endpoint on a hidden feature on site admin and ensure the feature becomes visible in all root accounts - Use the "set feature flag endpoint" on a hidden feature on a single root account, and ensure the feature becomes visible to that root account and not others - Confirm that root_opt_in features appear "Off" by default in root accounts, after being "Allowed" in code or site admin - Confirm a feature flag that is set to "on" or "off" (vs. "allowed") cannot be overridden in a lower context (and the API returns locked=true for them) - Confirm that setting locking_account_id requires admin rights in the locking account - Confirm that a feature flag with locking_account_id cannot be changed without admin rights in the locking account (e.g., set a feature flag on a course, locked with the root account's id, and make sure a teacher who is not an account admin can't change it) - Confirm feature flags can be deleted with the "remove feature flag" endpoint (and they are only deleted where they are defined, not when called on an object that inherits a flag) Change-Id: I3e12e23b4454889b6e8b263f1315e82d8f2ada52 Reviewed-on: https://gerrit.instructure.com/25502 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Matt Fairbourn <mfairbourn@instructure.com> Product-Review: Matt Goodwin <mattg@instructure.com> Reviewed-by: Zach Pendleton <zachp@instructure.com>
2013-10-22 23:28:26 +08:00
scope(controller: :feature_flags) do
2015-06-26 03:35:25 +08:00
%w(course account user).each do |context|
feature flags infrastructure and API test plan: - install the test_features plugin (since no real features exist yet) - render and consult the feature flags documentation - have a test environment with a root account, sub-account, course in sub-account, and user - Use the "list features" endpoint as a root account admin (with no site admin privileges), on the root account context, and confirm that hidden features do not show up - Use the "list features" endpoint as a site admin user, on the root account context, and confirm that hidden features show up - Use the "list features" endpoint on the site admin account and confirm the hidden features show up - Use the "set feature flag" endpoint on a hidden feature on site admin and ensure the feature becomes visible in all root accounts - Use the "set feature flag endpoint" on a hidden feature on a single root account, and ensure the feature becomes visible to that root account and not others - Confirm that root_opt_in features appear "Off" by default in root accounts, after being "Allowed" in code or site admin - Confirm a feature flag that is set to "on" or "off" (vs. "allowed") cannot be overridden in a lower context (and the API returns locked=true for them) - Confirm that setting locking_account_id requires admin rights in the locking account - Confirm that a feature flag with locking_account_id cannot be changed without admin rights in the locking account (e.g., set a feature flag on a course, locked with the root account's id, and make sure a teacher who is not an account admin can't change it) - Confirm feature flags can be deleted with the "remove feature flag" endpoint (and they are only deleted where they are defined, not when called on an object that inherits a flag) Change-Id: I3e12e23b4454889b6e8b263f1315e82d8f2ada52 Reviewed-on: https://gerrit.instructure.com/25502 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Matt Fairbourn <mfairbourn@instructure.com> Product-Review: Matt Goodwin <mattg@instructure.com> Reviewed-by: Zach Pendleton <zachp@instructure.com>
2013-10-22 23:28:26 +08:00
prefix = "#{context}s/:#{context}_id/features"
get "#{prefix}", action: :index, as: "#{context}_features"
get "#{prefix}/enabled", action: :enabled_features, as: "#{context}_enabled_features"
get "#{prefix}/flags/:feature", action: :show
put "#{prefix}/flags/:feature", action: :update
delete "#{prefix}/flags/:feature", action: :delete
feature flags infrastructure and API test plan: - install the test_features plugin (since no real features exist yet) - render and consult the feature flags documentation - have a test environment with a root account, sub-account, course in sub-account, and user - Use the "list features" endpoint as a root account admin (with no site admin privileges), on the root account context, and confirm that hidden features do not show up - Use the "list features" endpoint as a site admin user, on the root account context, and confirm that hidden features show up - Use the "list features" endpoint on the site admin account and confirm the hidden features show up - Use the "set feature flag" endpoint on a hidden feature on site admin and ensure the feature becomes visible in all root accounts - Use the "set feature flag endpoint" on a hidden feature on a single root account, and ensure the feature becomes visible to that root account and not others - Confirm that root_opt_in features appear "Off" by default in root accounts, after being "Allowed" in code or site admin - Confirm a feature flag that is set to "on" or "off" (vs. "allowed") cannot be overridden in a lower context (and the API returns locked=true for them) - Confirm that setting locking_account_id requires admin rights in the locking account - Confirm that a feature flag with locking_account_id cannot be changed without admin rights in the locking account (e.g., set a feature flag on a course, locked with the root account's id, and make sure a teacher who is not an account admin can't change it) - Confirm feature flags can be deleted with the "remove feature flag" endpoint (and they are only deleted where they are defined, not when called on an object that inherits a flag) Change-Id: I3e12e23b4454889b6e8b263f1315e82d8f2ada52 Reviewed-on: https://gerrit.instructure.com/25502 Tested-by: Jenkins <jenkins@instructure.com> QA-Review: Matt Fairbourn <mfairbourn@instructure.com> Product-Review: Matt Goodwin <mattg@instructure.com> Reviewed-by: Zach Pendleton <zachp@instructure.com>
2013-10-22 23:28:26 +08:00
end
end
scope(controller: :conferences) do
%w(course group).each do |context|
prefix = "#{context}s/:#{context}_id/conferences"
get prefix, action: :index, as: "#{context}_conferences"
post "#{prefix}/:conference_id/recording_ready", action: :recording_ready, as: "#{context}_conferences_recording_ready"
end
end
scope(controller: :custom_gradebook_columns_api) do
prefix = "courses/:course_id/custom_gradebook_columns"
get prefix, action: :index, as: "course_custom_gradebook_columns"
post prefix, action: :create
2015-06-26 03:35:25 +08:00
post "#{prefix}/reorder", action: :reorder, as: "custom_gradebook_columns_reorder"
put "#{prefix}/:id", action: :update, as: "course_custom_gradebook_column"
delete "#{prefix}/:id", action: :destroy
end
scope(controller: :custom_gradebook_column_data_api) do
prefix = "courses/:course_id/custom_gradebook_columns/:id/data"
get prefix, action: :index, as: "course_custom_gradebook_column_data"
put "#{prefix}/:user_id", action: :update, as: "course_custom_gradebook_column_datum"
end
scope(controller: :content_exports_api) do
zip content exports for course, group, user test plan: 1. use the content exports api with export_type=zip to export files from courses, groups, and users a. confirm only users who have permission to download files from these contexts can perform the export b. confirm that deleted files and folders do not show up in the downloaded archive c. confirm that students cannot download locked files or folders from courses this way d. check the progress endpoint and make sure it increments sanely 2. perform selective content exports by passing an array of ids in select[folders] and/or select[attachments]. for example, ?select[folders][]=123&select[folders][]=456 ?select[attachments][]=345 etc. a. any selected files, plus the full contents of any selected folders (that the caller has permission to see) should be included - that means locked files and subfolders should be excluded from the archive b. if all selected files and folders are descendants of the same subfolder X, the export should be named "X_export.zip" and all paths inside the zip should be relative to it. for example, if you are exporting A/B/1 and A/C/2, you should get "A_export.zip" containing files "B/1" and "C/2". 3. use the index and show endpoints to list and view content exports in courses, groups, and users a. confirm students cannot view non-zip course exports (such as common cartridge exports) b. confirm students cannot view other users' file (zip) exports, in course, group, and user context c. confirm teachers cannot view other users' file (zip) exports, in course, group, and user context (but can still view course [cc] exports initiated by other teachers) 4. look at /courses/X/content_exports (web, not API) a. confirm teachers see file exports they performed b. confirm teachers do not see file exports performed by other teachers c. confirm teachers see all non-zip course exports (cc/qti) including those initiated by other teachers 5. as a site admin user, perform a zip export of another user's files. then, as that other user, go to /dashboard/data_exports and confirm that the export performed by the site admin user is not shown. fixes CNVS-12706 Change-Id: Ie9b58e44ac8006a9c9171b3ed23454bf135385b0 Reviewed-on: https://gerrit.instructure.com/34341 Reviewed-by: James Williams <jamesw@instructure.com> QA-Review: Trevor deHaan <tdehaan@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> Product-Review: Jon Willesen <jonw@instructure.com>
2014-07-18 04:00:32 +08:00
%w(course group user).each do |context|
context_prefix = "#{context.pluralize}/:#{context}_id"
prefix = "#{context_prefix}/content_exports"
get prefix, action: :index, as: "#{context}_content_exports"
post prefix, action: :create
get "#{prefix}/:id", action: :show
zip content exports for course, group, user test plan: 1. use the content exports api with export_type=zip to export files from courses, groups, and users a. confirm only users who have permission to download files from these contexts can perform the export b. confirm that deleted files and folders do not show up in the downloaded archive c. confirm that students cannot download locked files or folders from courses this way d. check the progress endpoint and make sure it increments sanely 2. perform selective content exports by passing an array of ids in select[folders] and/or select[attachments]. for example, ?select[folders][]=123&select[folders][]=456 ?select[attachments][]=345 etc. a. any selected files, plus the full contents of any selected folders (that the caller has permission to see) should be included - that means locked files and subfolders should be excluded from the archive b. if all selected files and folders are descendants of the same subfolder X, the export should be named "X_export.zip" and all paths inside the zip should be relative to it. for example, if you are exporting A/B/1 and A/C/2, you should get "A_export.zip" containing files "B/1" and "C/2". 3. use the index and show endpoints to list and view content exports in courses, groups, and users a. confirm students cannot view non-zip course exports (such as common cartridge exports) b. confirm students cannot view other users' file (zip) exports, in course, group, and user context c. confirm teachers cannot view other users' file (zip) exports, in course, group, and user context (but can still view course [cc] exports initiated by other teachers) 4. look at /courses/X/content_exports (web, not API) a. confirm teachers see file exports they performed b. confirm teachers do not see file exports performed by other teachers c. confirm teachers see all non-zip course exports (cc/qti) including those initiated by other teachers 5. as a site admin user, perform a zip export of another user's files. then, as that other user, go to /dashboard/data_exports and confirm that the export performed by the site admin user is not shown. fixes CNVS-12706 Change-Id: Ie9b58e44ac8006a9c9171b3ed23454bf135385b0 Reviewed-on: https://gerrit.instructure.com/34341 Reviewed-by: James Williams <jamesw@instructure.com> QA-Review: Trevor deHaan <tdehaan@instructure.com> Tested-by: Jenkins <jenkins@instructure.com> Product-Review: Jon Willesen <jonw@instructure.com>
2014-07-18 04:00:32 +08:00
end
get "courses/:course_id/content_list", action: :content_list, as: "course_content_list"
end
scope(controller: :epub_exports) do
get 'courses/:course_id/epub_exports/:id', {
action: :show
}
get 'epub_exports', {
action: :index
}
post 'courses/:course_id/epub_exports', {
action: :create
}
end
scope(controller: :grading_standards_api) do
get 'courses/:course_id/grading_standards', action: :context_index
get 'accounts/:account_id/grading_standards', action: :context_index
post 'accounts/:account_id/grading_standards', action: :create
post 'courses/:course_id/grading_standards', action: :create
end
get '/crocodoc_session', controller: 'crocodoc_sessions', action: 'show', as: :crocodoc_session
get '/canvadoc_session', controller: 'canvadoc_sessions', action: 'show', as: :canvadoc_session
scope(controller: :grading_period_sets) do
get 'accounts/:account_id/grading_period_sets', action: :index, as: :account_grading_period_sets
post 'accounts/:account_id/grading_period_sets', action: :create
patch 'accounts/:account_id/grading_period_sets/:id', action: :update, as: :account_grading_period_set
delete 'accounts/:account_id/grading_period_sets/:id', action: :destroy
end
scope(controller: :grading_periods) do
remove account association from grading periods and their groups Accounts will no longer be directly associated with grading periods or grading period groups. A grading period group can: * have only one or more enrollment terms * belong only to a course (for legacy data) Testing Notes: * To create a GradingPeriodGroup for an EnrollmentTerm: * Create an EnrollmentTerm `enrollment_term` * `group = GradingPeriodGroup.new(title: "Example")` * `group.enrollment_terms << enrollment_term` * `group.save!` test plan: A. repeat tests with commit at SHA: 861015a B. grading standards for an account 1. find or create an Account 2. visit `/accounts/[account id]/grading_standards` 3. verify there is no grading periods UI 4. verify that grading schemes are still manageable C. grading standards for a course with grading periods 1. find or create: a. an Account b. an EnrollmentTerm for the Account c. a Course for that Account 2. associate the Course with the EnrollmentTerm 3. in the Rails console `bundle exec rails console` a. create a GradingPeriodGroup for the Course b. create at least one GradingPeriod in the course group c. create a GradingPeriodGroup for the EnrollmentTerm d. create at least one GradingPeriod in the term group 4. visit `/courses/[course id]/grading_standards` 5. verify the grading period(s) on the course are present 5. verify the grading period(s) on the term are not present 6. verify that grading schemes are still manageable D. grading standards for a course with no grading periods 1. find or create: a. an Account b. an EnrollmentTerm for the Account c. a Course for that Account 2. associate the Course with the EnrollmentTerm 3. in the Rails console `bundle exec rails console` a. create a GradingPeriodGroup for the EnrollmentTerm b. create at least one GradingPeriod in the group 4. visit `/courses/[course id]/grading_standards` 5. verify the grading periods on the term are present 6. verify that grading schemes are still manageable closes CNVS-26725 Change-Id: I7883cb421c87ebb91c818223c0483557fdd5e40a Reviewed-on: https://gerrit.instructure.com/78167 Reviewed-by: Derek Bender <djbender@instructure.com> Reviewed-by: Spencer Olson <solson@instructure.com> QA-Review: KC Naegle <knaegle@instructure.com> Tested-by: Jenkins Product-Review: Keith T. Garner <kgarner@instructure.com>
2016-04-22 06:09:15 +08:00
# FIXME: This route will be removed/replaced with CNVS-27101
get 'accounts/:account_id/grading_periods', action: :index, as: :account_grading_periods
get 'courses/:course_id/grading_periods', action: :index, as: :course_grading_periods
get 'courses/:course_id/grading_periods/:id', action: :show, as: :course_grading_period
patch 'courses/:course_id/grading_periods/batch_update',
action: :batch_update, as: :course_grading_period_batch_update
put 'courses/:course_id/grading_periods/:id', action: :update, as: :course_grading_period_update
delete 'courses/:course_id/grading_periods/:id', action: :destroy, as: :course_grading_period_destroy
delete grading periods and grading period sets allows the user to delete grading periods and grading period sets after confirmation. closes CNVS-27105 test plan 1 - grading period deletion: - go to the account grading periods page for an account with at least 2 grading period sets with some grading periods in them - click the trash can icon next to a grading period - verify an alert pops up asking the user to confirm that they want to delete the period - verify the period is not deleted if you click cancel - verify the period is deleted if you click OK - kill your server locally, and attempt to delete a grading period by clicking the trash icon. verify a message is displayed that says an error occured while deleting the grading period test plan 2 - grading period set deletion: - go to the account grading periods page for an account with at least 2 grading period sets - click the trash can icon next to a grading period set name - verify an alert pops up asking the user to confirm that they want to delete the set - verify the set is not deleted if you click cancel - verify the set is deleted if you click OK - kill your server locally, and attempt to delete a grading period set by clicking the trash icon. verify a message is displayed that says an error occured while deleting the grading period set test plan 3 - permissions: - go to a sub account grading periods page - verify there are no trash can icons Change-Id: Ic7a48e6a1fd2d2fb515c2e159bc547b104cbf3ac Reviewed-on: https://gerrit.instructure.com/81686 Reviewed-by: Jeremy Neander <jneander@instructure.com> Tested-by: Jenkins Reviewed-by: Keith T. Garner <kgarner@instructure.com> QA-Review: Amber Taniuchi <amber@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
2016-06-07 00:28:17 +08:00
delete 'accounts/:account_id/grading_periods/:id', action: :destroy, as: :account_grading_period_destroy
create new grading periods on account grading standards page When visiting the grading standards page, account admins need to be able to create new grading periods within grading period sets for their accounts. This implements that. closes CNVS-27102 To create a grading period, perform the following steps: 1. Select or create: a. a root account b. a root account admin c. an active enrollment term (required for grading period set) d. an active grading period set 2. Visit the account grading standards page 3. Expand a/the grading period set 4. Verify that the '+ Grading Period' button is visible 5. Click the '+ Grading Period' button 6. Fill in the form with: a. any title b. the given (or any) start date c. the given (or any) end date after the given start date 7. Click 'Create' 8. Verify: a. An flash message indicates a successful save b. The grading period is visible c. The grading period was created in the database d. The grading period has the expected attributes e. All grading periods are sorted by start date f. The grading period form was dismissed 9. OR verify: a. An flash message indicates a failure b. The grading period was not created c. The grading period form was not dismissed 10. Refresh the page 11. Verify the page reflects the expected presence/absence of the existing/created grading periods test plan: A. Can create a grading period with valid dates B. Can create multiple grading periods with valid dates C. Cannot create a grading period with an end date before its start date D. Cannot create a grading period without: 1. title 2. start date 3. end date E. Cannot create a grading period with a date range that includes the start date and/or end date of other grading periods F. Clicking 'Cancel' dismisses the form G. Creating a grading period between two other grading periods will display it between those grading periods H. Creating a grading period before any other grading periods will display it above those grading periods I. Can only view with sub accounts 1. Select or create: a. a root account b. an active enrollment term (required for grading period set) c. an active grading period set 2. Visit the account grading standards page 3. Expand a/the grading period set 4. Verify that the '+ Grading Period' button is NOT visible Change-Id: Ia6d2d5248a6e96815b2f881f5088dd46cc040e57 Reviewed-on: https://gerrit.instructure.com/81010 Tested-by: Jenkins QA-Review: KC Naegle <knaegle@instructure.com> Reviewed-by: Spencer Olson <solson@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
2016-06-02 09:29:09 +08:00
patch 'grading_period_sets/:set_id/grading_periods/batch_update',
action: :batch_update, as: :grading_period_set_periods_update
end
scope(controller: :usage_rights) do
%w(course group user).each do |context|
content_prefix = "#{context.pluralize}/:#{context}_id"
put "#{content_prefix}/usage_rights", action: :set_usage_rights
delete "#{content_prefix}/usage_rights", action: :remove_usage_rights
get "#{content_prefix}/content_licenses", action: :licenses
end
end
scope(controller: 'bookmarks/bookmarks') do
get 'users/self/bookmarks/', action: :index, as: :bookmarks
get 'users/self/bookmarks/:id', action: :show
post 'users/self/bookmarks', action: :create
delete 'users/self/bookmarks/:id', action: :destroy
put 'users/self/bookmarks/:id', action: :update
end
scope(controller: :course_nicknames) do
get 'users/self/course_nicknames', action: :index, as: :course_nicknames
get 'users/self/course_nicknames/:course_id', action: :show
put 'users/self/course_nicknames/:course_id', action: :update
delete 'users/self/course_nicknames/:course_id', action: :delete
delete 'users/self/course_nicknames', action: :clear
end
All of the stuff from the save_a_theme dev branch this commit is the result of squashing a bunch of others together. this is everything that was already on the dev/save_a_theme branch as well as the "Add specs" commit. I left the test plans from some of the squashed commits in case they are helpful for QA Test plan: - Recompile assets, restart Canvas and clear browser cache - Go to Admin > [Your school name] - Click on Themes in the context menu - You should now see a collections page with a theme card for all the themes you have in Theme Editor: http://screencast.com/t/lb5vozF7 - Note: it might be my database, but on my end, I don't see a theme card for my Canvas default theme. There are also some brand colors missing for my theme cards. I'll be interested to see if you hit the same thing. These are issues that we can resolve with Ryan when he is back. - You should be able to click on the Apply and Delete buttons and see the confirm-overlays. We still need final copy for these. Test plan: - Go to your institution's Settings page and click Themes on the context menu. - You should now see a page listing all the default and user-created themes in your Canvas installation. - Clicking on each theme will open it inside theme editor. - The current/active theme will be correctly styled with a green outline change redirect targets and messages in theme editor test plan: exiting theme editor should redirect you back to the /accounts/x/themes page instead of /acounts/x make room for footer in theme editor test plan: in theme editor, scroll the preview to the bottom you should be able to scroll all the way, without having the bottom cut off by the footer remove "theme editor" button from account user/course search this is not needed since "Themes" now shows up in the left nav. test plan: turn on the 'Course and User Search' feature flag go to accounts/x you should not see a "theme editor" button on the right aka, not like this: http://cl.ly/2G2C3p3s3n0C fix "Exit" button in theme editor we were warning "you will lose unsaved changes" even when you hand not made any changes add specs to "Save A theme" stuff closes: CNVS-27961 test plan: do a whole regression test on the theme editor don't show both "k12 theme" and "canvas default" as options fixes: CNVS-25495 description (and test plan): if you are a k12 school, rather than seeing both "Canvas Default" and "K12 Theme" as options on the tiles of system themes to start from, you should now just see "Canvas Default". if you pick that, it should show the k12 theme. Change-Id: I5c2512e576dcb2aedaa899e17080d9c106e159ca Reviewed-on: https://gerrit.instructure.com/78163 Tested-by: Jenkins Reviewed-by: Rob Orton <rob@instructure.com> Product-Review: Ryan Shaw <ryan@instructure.com> QA-Review: Ryan Shaw <ryan@instructure.com>
2016-01-19 03:29:32 +08:00
scope(controller: :shared_brand_configs) do
post 'accounts/:account_id/shared_brand_configs', action: :create
put 'accounts/:account_id/shared_brand_configs/:id', action: :update
delete 'shared_brand_configs/:id', action: :destroy
end
scope(controller: :errors) do
post "error_reports", action: :create
end
scope(controller: :jwts) do
post 'jwts', action: :create
end
scope(controller: :gradebook_settings) do
put 'courses/:course_id/gradebook_settings', action: :update, as: :course_gradebook_settings_update
end
2011-02-01 09:57:29 +08:00
end
Expose delayed jobs as an API route This patch exposes delayed jobs data as an API route, which makes it accessible using a bearer token. Currently, a token is not accepted as valid authentication, and an Unauthorized error is returned to the client. Test plan: - create a user in the Site Admin account and grant it admin rights to Site Admin - create a user in the Site Admin account (or any other account) but do not grant it admin rights to Site Admin - create some delayed jobs, failed and otherwise - test the following routes: -`GET /api/v1/jobs?only=jobs&flavor=[failed|future|current|waiting]`: should return list of jobs for specified flavor in JSON -`GET /api/v1/jobs/:id`: should return a specific non-failed job -`GET /api/v1/jobs/:id`: should return a specific failed job - `POST /api/v1/jobs/batch_update` with body `update_action=destroy&job_ids[]=$id1&job_ids[]=$id2`: (replacing $id1 and $id2 with the IDs of real non-failed jobs) should return a success message with count of destroyed jobs. - `POST /api/v1/jobs/batch_update` with body `update_action=destroy&job_ids[]=$id1&job_ids[]=$id2&flavor=failed`: (replacing $id1 and $id2 with the IDs of real failed jobs) will fail pending instructure/canvas-jobs#2 (with that pull, it will return a success message with count of destroyed jobs). - `POST /api/v1/jobs/batch_update` with body `update_action=destroy&flavor=future`: should return a success message with count of destroyed jobs - `POST /api/v1/jobs/batch_update` with body `update_action=hold&flavor=future`: should return an error report (can't hold failed jobs). When testing the routes, using the second user created (without Site Admin rights) should throw an Unauthorized error. Using a developer key should throw an Invalid Token error.
2015-10-10 06:43:00 +08:00
# this is not a "normal" api endpoint in the sense that it is not documented or
# generally available to hosted customers. it also does not respect the normal
# pagination options; however, jobs_controller already accepts `limit` and `offset`
# paramaters and defines a sane default limit
ApiRouteSet::V1.draw(self) do
scope(controller: :jobs) do
get 'jobs', action: :index
get 'jobs/:id', action: :show
post 'jobs/batch_update', action: :batch_update
end
end
# this is not a "normal" api endpoint in the sense that it is not documented
# or called directly, it's used as the redirect in the file upload process
# for local files. it also doesn't use the normal oauth authentication
# system, so we can't put it in the api uri namespace.
post 'files_api' => 'files#api_create', as: :api_v1_files_create
get 'login/oauth2/auth' => 'oauth2_provider#auth', as: :oauth2_auth
post 'login/oauth2/token' => 'oauth2_provider#token', as: :oauth2_token
get 'login/oauth2/confirm' => 'oauth2_provider#confirm', as: :oauth2_auth_confirm
post 'login/oauth2/accept' => 'oauth2_provider#accept', as: :oauth2_auth_accept
get 'login/oauth2/deny' => 'oauth2_provider#deny', as: :oauth2_auth_deny
delete 'login/oauth2/token' => 'oauth2_provider#destroy', as: :oauth2_logout
ApiRouteSet.draw(self, "/api/lti/v1") do
post "tools/:tool_id/grade_passback", controller: :lti_api, action: :grade_passback, as: "lti_grade_passback_api"
post "tools/:tool_id/ext_grade_passback", controller: :lti_api, action: :legacy_grade_passback, as: "blti_legacy_grade_passback_api"
post "xapi/:token", controller: :lti_api, action: :xapi_service, as: "lti_xapi"
post "caliper/:token", controller: :lti_api, action: :caliper_service, as: "lti_caliper"
post "logout_service/:token", controller: :lti_api, action: :logout_service, as: "lti_logout_service"
post "turnitin/outcomes_placement/:tool_id", controller: :lti_api, action: :turnitin_outcomes_placement, as: "lti_turnitin_outcomes_placement"
end
ApiRouteSet.draw(self, "/api/lti") do
2015-06-26 03:35:25 +08:00
%w(course account).each do |context|
prefix = "#{context}s/:#{context}_id"
get "#{prefix}/tool_consumer_profile/:tool_consumer_profile_id", controller: 'lti/ims/tool_consumer_profile',
action: 'show', as: "#{context}_tool_consumer_profile"
post "#{prefix}/tool_proxy", controller: 'lti/ims/tool_proxy', action: :re_reg,
as: "re_reg_#{context}_lti_tool_proxy", constraints: Lti::ReRegConstraint.new
post "#{prefix}/tool_proxy", controller: 'lti/ims/tool_proxy', action: :create,
as: "create_#{context}_lti_tool_proxy"
get "#{prefix}/jwt_token", controller: 'external_tools', action: :jwt_token
end
#Tool Setting Services
get "tool_settings/:tool_setting_id", controller: 'lti/ims/tool_setting', action: :show, as: 'show_lti_tool_settings'
put "tool_settings/:tool_setting_id", controller: 'lti/ims/tool_setting', action: :update, as: 'update_lti_tool_settings'
#Tool Proxy Services
get "tool_proxy/:tool_proxy_guid", controller: 'lti/ims/tool_proxy', action: :show, as: "show_lti_tool_proxy"
# Membership Service
get "courses/:course_id/membership_service", controller: "lti/membership_service", action: :course_index, as: :course_membership_service
get "groups/:group_id/membership_service", controller: "lti/membership_service", action: :group_index, as: :group_membership_service
end
ApiRouteSet.draw(self, '/api/sis') do
scope(controller: :sis_api) do
get 'accounts/:account_id/assignments', action: 'sis_assignments', as: :sis_account_assignments
get 'courses/:course_id/assignments', action: 'sis_assignments', as: :sis_course_assignments
end
end
2011-02-01 09:57:29 +08:00
end