canvas-lms/config/routes.rb

2338 lines
124 KiB
Ruby
Raw Normal View History

#
# Copyright (C) 2011 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
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
post "/api/graphql", to: "graphql#execute"
get 'graphiql', to: 'graphql#graphiql'
resources :submissions, only: [] do
resources :submission_comments, path: :comments, only: :index, defaults: { format: :pdf }
add new endpoint for docviewer audit events refs GRADE-1331 Test Plan - Create/edit dynamic_settings.yml and add in an entry under "config" that is: canvadoc: app-host: "http://api.canvadoc.docker" secret: "c2Vrcml0" * app-host url doesn't matter, and the secret is "sekrit" base64 encoded if you're curious. - Open a rails console and enter: `Canvas::Security.create_jwt({}, nil, 'sekrit', :HS512)` The resulting token is your auth token for the duration of testing. - Create an assignment that accepts file uploads. - As a student, submit to that with a document. - As a teacher, launch speedgrader once for that assignment and view the document. - Open a rails console and find the submission, the attachment for that submission, and the canvadoc id related to that attachment. - use Postman or similar to do a post request to the new endpoint (submissions/:submission_id/docviewer_audit_events) with params as: canvas_user_id: (some teacher's id) document_id: (the canvadoc id) event_type: (anything you want, but 'highlight_created' is good) related_annotation_id: (pick a number) submission_id: (the id of the submission) token: (your auth_token from the first few steps) annotation_body: { color: (pick a color) content: (some text) created_at: (pick a date) modified_at: (pick a date) page: (pick a number) type: (pick some text) } - Open a rails console and verify that an AnonymousOrModerationEvent with the attributes you set above was created. Change-Id: Ia41dba4814799a0c7b297b7b8f87d37e26fc6a2a Reviewed-on: https://gerrit.instructure.com/161049 Reviewed-by: Spencer Olson <solson@instructure.com> Tested-by: Jenkins Reviewed-by: Keith T. Garner <kgarner@instructure.com> QA-Review: Adrian Packel <apackel@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-08-15 02:33:56 +08:00
resources :docviewer_audit_events, only: [:create], constraints: { format: :json }
end
autosave comments on navigating to different user in speedgrader closes CNVS-28529 While in SpeedGrader, if you have something entered in the comments field and, without submitting those comments, you navigate to a different user or otherwise navigate away from SpeedGrader, your comments will now automatically be saved as "draft" comments for that user's submission. Draft comments * don't show up anywhere other than while grading * are invisible to users whether or not the assignment is muted * are only "submittable" by the author of the draft comment test plan: 1. Create a course, with at least two students 2. Add a quiz with at least one essay type question 3. As each student, take the quiz 4. As the teacher, grade the quiz and start up SpeedGrader 5. Enter comments for the first student's submission but do *not* submit them 6. Navigate to the next student 7. You should see a message telling you your comment was auto-saved 8. Go back to the previous student 9. You should see your comment styled differently with a red asterisk before it, indicating a draft comment (also using aria-label for a11y goodness) 10.Enter another comment and this time submit it 11.You should see your comment styled normally without a red asterisk before it, indicating a normal (non-draft) comment 12.Try steps 5 through 11 with different ways of leaving that student in step #6 e.g. using the drop down, or quitting SpeedGrader altogether and you should see the same results for draft comments 13.Go back to a submission with a draft comment. 14.Click on the button labelled "Publish" next to your draft comment. 15.Watch your comment change in appearance from a draft comment to a regular comment 16.Delete any comment and watch it disappear from the comment list. 17.Go to the next student 18.Go back to the previous student for whose submission you deleted the comment 19.Notice the deleted comment remains missing from the comment list. 20.Verify that, if logged in as a student, you never see draft comments Change-Id: If32294a7bed6f847709b54d4c8e4fc21fb2a6eca Reviewed-on: https://gerrit.instructure.com/77133 Reviewed-by: Spencer Olson <solson@instructure.com> Reviewed-by: Neil Gupta <ngupta@instructure.com> Tested-by: Jenkins QA-Review: Amber Taniuchi <amber@instructure.com> Product-Review: Christi Wruck
2016-04-14 05:02:28 +08:00
resources :submission_comments, only: [:update, :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
get 'confirmations/:user_id/limit_reached(/:id)' => 'communication_channels#confirmation_limit_reached', as: :confirmation_limit_reached, 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'
redesign and simplify error pages fixes ADMIN-2336 test plan: - create a page in a course that links to the following: * a file that has been deleted * a file with an invalid id * a resource (file, assignment, etc.) that is unpublished * a resource that is in a different course (most easily done by changing the course id in the link in the html) - as a student, click these links and ensure the pages you see look like the mockups in ADMIN-2331. - in all of these cases, * there is a centered image - this image is not read by screen readers, since it is purely decorative * there is not a red box * there is not a link to contact support - for the deleted file, you should see "Page Not Found" and a note that the file has been deleted - for other links to nonexistent items, you should just see "Page Not Found" - for unpublished items, you should see "Not Yet Available" and a locked document picture - for items in a different course (that the student is not enrolled in), you should see "Access Denied" and a lock picture - also test the new 400 and 500 error pages. the easiest way to do this is with the /test_error endpoint: - /test_error?status=400 - /test_error?status=500 - these show the broken rocket picture and still include a support link Change-Id: I9f20e742e690482887cf375c79e4060aff6d7146 Reviewed-on: https://gerrit.instructure.com/178581 Tested-by: Jenkins Reviewed-by: Ed Schiebel <eschiebel@instructure.com> Reviewed-by: Carl Kibler <ckibler@instructure.com> QA-Review: Carl Kibler <ckibler@instructure.com> Product-Review: Kyle Follett <kfollett@instructure.com>
2019-01-19 05:37:35 +08:00
# This is a debug route that makes working on error pages easier
get 'test_error' => 'info#test_error' unless Rails.env.production?
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, except: :edit
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
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
# rubocop:disable SymbolArray
match :join, via: [:get, :post]
match :close, via: [:get, :post]
match :recording, via: [:get]
match :recording, via: [:delete], to: 'conferences#delete_recording', as: :delete_recording
# rubocop:enable SymbolArray
get :settings
end
end
get '/courses/:course_id/gradebook2', to: redirect('/courses/%{course_id}/gradebook')
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 :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
create endpoint for final grade overrides closes GRADE-1876 test plan: Notes: * To test the endpoint, send use the path: GET /courses/:course_id/gradebook/final_grade_overrides * To set overrides, perform the following in the Rails console: enrollment = course.enrollments.find_by(user_id: <student.id>) # to update a course score score = enrollment.scores.find_by!(course_score: true) score.update!(override_score: 89.2) # some score value # to update a grading period score period = <some grading period> score = enrollment.scores.find_by!(grading_period: period) score.update!(override_score: 89.2) # some score value A. Setup 1. Select or create a course 2. Ensure the course has at least one assignment 3. Enable the "Final Grade Override" feature flag 4. Use an enrollment term with some grading periods 5. Override a student's course score 6. Override a student's grading period score B. Verify 1. As a teacher in the course, send a request to the endpoint 2. Verify the response is structured as follows: { final_grade_overrides: { <student_id>: { course_grade: { percentage: 12.34 }, grading_period_grades: { <grading_period_id>: { percentage: 56.78 }, <grading_period_id>: { percentage: 90.12 } } }, <student_id>: {…} } } 3. Verify the response includes ids of only students with overrides 4. Verify each student represented includes scores for only the specific overrides assigned * not all grading period ids will be included if they do not all have overrides * the course grade override will not be included if not assigned 5. Verify the override percentage values are accurate Change-Id: I0e7df11139518b94460883d3dbd4700cba9aaeda Reviewed-on: https://gerrit.instructure.com/174017 Tested-by: Jenkins Reviewed-by: Gary Mei <gmei@instructure.com> Reviewed-by: Adrian Packel <apackel@instructure.com> QA-Review: Adrian Packel <apackel@instructure.com> Product-Review: Keith Garner <kgarner@instructure.com>
2018-12-04 01:15:02 +08:00
get :final_grade_overrides
get :speed_grader
post :speed_grader_settings
get :history
post :update_submission
post :change_gradebook_column_size
post :save_gradebook_column_order
add user_ids endpoint to gradebooks_controller Add endpoint to gradebooks controller which returns user ids sorted according to the user's gradebook sort preferences. closes CNVS-37608 Test Plan: 1. Create a course that has some active students, inactive students, and concluded students. Enable New Gradebook and go to the gradebook. 2. Click on the student header and select 'Inactive enrollments' and 'Concluded enrollments'. Then select 'Sort by -> A-Z'. 2. As a student in the course, hit the new endpoint to get user IDs (GET /courses/:course_id/gradebook/user_ids). Verify you get a 401 unauthorized response. 3. As a teacher in the course, hit the user_ids endpoint and verify you get a list of user IDs back. The user IDs should be ordered such that their corresponding users' names are in alpha ascending order. The list of user IDs should also include inactive and concluded students' IDs. 4. Go to the gradebook and click on the student header. Select 'Sort by -> Z-A'. 5. Hit the user_ids endpoint and verify the returned user IDs are now ordered such that their corresponding users' names are in alpha descending order. The list of user IDs should also include inactive and concluded students' IDs. 6. Go to the gradebook and click on the student column header. Deselect the 'Inactive enrollments' and 'Concluded enrollments' options. 7. Hit the user_ids endpoint and verify the returned user IDs no longer include IDs for inactive or concluded students. The IDs should still be ordered such that their corresponding users' names are in alpha descending order. 8. Go to the gradebook and click on the total grade header. Select 'Sort by Grade -> Low to High' 9. Hit the user_ids endpoint and verify the returned user IDs are ordered such that their corresponding users' current total grades are in ascending order. 10. Go to the gradebook and click on the total grade header. Select 'Sort by Grade -> High to Low' 11. Hit the user_ids endpoint and verify the returned user IDs are ordered such that their corresponding users' current total grades are in descending order. 12. In the same manner as the steps above, make sure changing the following settings in the gradebook causes the user_ids endpoint to return an array of IDs ordered according to the gradebook sort preferences: a) Assignment column header -> Sort by Grade -> Low to High b) Assignment column header -> Sort by Grade -> High to Low c) Assignment column header -> Sort by -> Missing (the user_ids endpoint should return all users with a missing submission for that assignment first) d) Assignment column header -> Sort by -> Late (the user_ids endpoint shoudl return all users with a late submission for that assignment first) e) Select a grading period and sort by total grade. The user_ids endpoint should return user IDs that are ordered such that their corresponding users' grades are in ascending or descending order for the selected grading period. * Note: Sorting by assignment group totals is not currently supported. Change-Id: I4a36aa5b82d87f49d2396bbc16e1cc56e89eba0f Reviewed-on: https://gerrit.instructure.com/116491 Reviewed-by: Shahbaz Javeed <sjaveed@instructure.com> Tested-by: Jenkins Reviewed-by: Keith T. Garner <kgarner@instructure.com> QA-Review: Anju Reddy <areddy@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
2017-06-17 06:37:46 +08:00
get :user_ids
get :grading_period_assignments
end
end
resource :gradebook_csv, only: [:show]
# 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#show'
get :locks
concerns :discussions
resources :assignments do
get 'moderate' => 'assignments#show_moderate'
get 'anonymous_submissions/:anonymous_id', to: 'submissions/anonymous_previews#show',
constraints: ->(request) do
request.query_parameters.key?(:preview) && request.format == :html
end
get 'anonymous_submissions/:anonymous_id', to: 'submissions/anonymous_downloads#show',
constraints: ->(request) do
request.query_parameters.key?(:download)
end
get 'anonymous_submissions/:anonymous_id', to: 'anonymous_submissions#show', as: :anonymous_submission
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
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/downloads#show',
constraints: ->(request) do
request.query_parameters.key?(:download)
end
put 'anonymous_submissions/:anonymous_id', to: 'anonymous_submissions#update'
resources :submissions do
get 'originality_report/:asset_string' => 'submissions#originality_report', as: :originality_report
post 'turnitin/resubmit' => 'submissions#resubmit_to_turnitin', as: :resubmit_to_turnitin
get 'turnitin/:asset_string' => 'submissions#turnitin_report', as: :turnitin_report
post 'vericite/resubmit' => 'submissions#resubmit_to_vericite', as: :resubmit_to_vericite
get 'vericite/:asset_string' => 'submissions#vericite_report', as: :vericite_report
get 'audit_events' => 'submissions#audit_events', as: :audit_events
end
Reenable anon plagiarism in SG for Turnitin For assignments using Turnitin (but not Vericite), re-enable the SpeedGrader link to the similarity report and the resubmit button even for assignments that are currently anonymizing. closes GRADE-1883 Test plan: - Create an anonymous assignment (with or without file submissions; see creation steps below) - In a Rails console, create some OriginalityReport objects for multiple submissions (see below) - Give at least one a valid score and workflow_state of 'scored' - Maybe enter a value for originality_report_url for one of them - Give at least one a workflow_state of 'error' - (or use "pending", in which case leave the score blank) - If your assignment involves file submissions, ensure each report's attachment_id matches an existent attachment - Open these submissions in SpeedGrader and check the following: - For 'scored' reports, you should see a clickable similarity score that links to a URL of the form: - .../anonymous_submissions/3oPSs/originality_report/asset_id (asset_id will be, e.g., submission_34 or attachment_999) - Visiting that URL should take you to the report's custom URL if defined, or else return you to SpeedGrader saying that a report couldn't be found (which is expected since our data is made up) - For 'pending'/'error' reports, you should see an error icon that reveals a 'Resubmit' button when clicked - Clicking 'Resubmit' should make a request to a URL of the form (you can check this in your logs): .../anonymous_submissions/3oPSs/turnitin/resubmit - This should then redirect you to the submission in SpeedGrader - Unmute the assignment - The above URLs should now be in the familiar 'submissions/<submission ID>' form, but work identically - The one change should be that the above links redirect you to the submission details page instead of SpeedGrader APPENDIX: Creating Turnitin originality data: For a given submission: > submission.originality_reports.create!( workflow_state; 'scored', # or 'error' or 'pending' originality_score: 88.0, # 0 = bad, 100 = great originality_report_url: <a custom URL if desired> attachment_id: <specific attachment ID or nil> ) If your assignment involves submitting files, you will need to specify a valid attachment ID for attachment_id; otherwise, leave it blank. APPENDIX 2: A note on Turnitin It is also possible to set up an LTI-based assignment that uses Turnitin but this is not strictly required to view originality scores, and furthermore this author was not sure how to configure it (beyond the directions given in Confluence) to result in anything other than an error when opening it, apparently because we were trying to pass a context_id that was already in use. Change-Id: Ibf14e6c83e77516ae34d2dde409b623e693d5677 Reviewed-on: https://gerrit.instructure.com/175816 Reviewed-by: Gary Mei <gmei@instructure.com> Reviewed-by: Keith Garner <kgarner@instructure.com> Tested-by: Jenkins QA-Review: Gary Mei <gmei@instructure.com> Product-Review: Sidharth Oberoi <soberoi@instructure.com>
2018-12-15 00:46:42 +08:00
get 'anonymous_submissions/:anonymous_id/originality_report/:asset_string',
to: 'anonymous_submissions#originality_report',
as: :anonymous_submission_originality_report
post 'anonymous_submissions/:anonymous_id/turnitin/resubmit',
to: 'anonymous_submissions#resubmit_to_turnitin',
as: :anonymous_submission_resubmit_to_turnitin
get 'anonymous_submissions/:anonymous_id/turnitin/:asset_string',
to: 'anonymous_submissions#turnitin_report',
as: :anonymous_submission_turnitin_report
post 'anonymous_submissions/:anonymous_id/vericite/resubmit',
to: 'anonymous_submissions#resubmit_to_vericite',
as: :anonymous_submission_resubmit_to_vericite
get 'anonymous_submissions/:anonymous_id/vericite/:asset_string',
to: 'anonymous_submissions#vericite_report',
as: :anonymous_submission_vericite_report
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
get 'lti/resource/:resource_link_id', controller: 'lti/message',
action: 'resource', as: :resource_link_id
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
match :resource_selection, via: [:get, :post]
get :homework_submission
get :finished
collection do
get :retrieve
get :homework_submissions
end
end
get 'lti/resource/:resource_link_id', controller: 'lti/message',
action: 'resource', as: :resource_link_id
get 'lti/basic_lti_launch_request/:message_handler_id', controller: 'lti/message',
action: 'basic_lti_launch_request', as: :basic_lti_launch_request
post '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', 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"
post 'quizzes/new' => 'quizzes/quizzes#new' # use POST instead of GET (not idempotent)
resources :quizzes, controller: 'quizzes/quizzes', except: :new 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'
get 'lti_collaborations/*all' => '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 'offline_web_exports' => 'courses#offline_web_exports'
post 'start_offline_web_export' => 'courses#start_offline_web_export'
get 'modules/items/assignment_info' => 'context_modules#content_tag_assignment_data', as: :context_modules_assignment_info
get 'modules/items/master_course_info' => 'context_modules#content_tag_master_course_data', as: :context_modules_master_course_info
get 'modules/items/:id' => 'context_modules#item_redirect', as: :context_modules_item_redirect
implement cyoe gear option for score-able objects refs CYOE-304 test plan: - there should be no changes in the student view - part 1: - create a new course with cyoe disabled - create two new assignments (one graded, one ungraded), four new quizzes (one graded, one practice, one survey, one graded survey), and two discussions (one graded, one ungraded), one page - create a new module and add the items from above as module items - check the cog menu on the created items and ensure that there is no "Mastery Paths" option in any of the following views: - assignments index page - quizzes index page - discussions index page - all items on the modules page - part 2: - enable cyoe in the course from part 1 - create a new page with "allow in mastery paths" checkbox checked - create a module item for the new page - check the same four index pages as before (assignments, quizzes, discussions, and modules) and make sure that: - the following items have a "Mastery Paths" cog menu option: - the graded assignment - the graded discussion - the graded quiz - clicking on the "Mastery Paths" menu option on any of the above menus navigates to the correct edit page with the mastery paths tab opened on page load - the following items do not have the "Mastery Paths" option: - the ungraded assignment - the ungraded discussion - the practice quiz - the survey - the graded survey - both pages Change-Id: I20c905d764fd3533ae8e68dbd99b7b73fcff81ed Reviewed-on: https://gerrit.instructure.com/91129 Tested-by: Jenkins Reviewed-by: Christian Prescott <cprescott@instructure.com> Reviewed-by: Michael Brewer-Davis <mbd@instructure.com> QA-Review: Jahnavi Yetukuri <jyetukuri@instructure.com> Product-Review: Felix Milea-Ciobanu <fmileaciobanu@instructure.com>
2016-09-22 23:23:50 +08:00
get 'modules/items/:id/edit_mastery_paths' => 'context_modules#item_redirect_mastery_paths'
get 'modules/items/:id/choose' => 'context_modules#choose_mastery_path'
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 'invite_users' => 'users#invite_users', :as => :invite_users
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
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/: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).each do |context|
prefix = "#{context}s/:#{context}_id"
post "#{prefix}/deep_linking_response", controller: 'lti/ims/deep_linking', action: :deep_linking_response, as: "#{context}_deep_linking_response"
end
%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 'lti_collaborations/*all' => 'collaborations#lti_index'
get 'calendar' => 'calendars#show'
resources :external_tools do
get :finished
match :resource_selection, via: [:get, :post]
collection do
get :retrieve
end
end
end
resources :accounts do
get 'search(/:tab)', action: :course_user_search
get "settings#{full_path_glob}", action: :settings
get :reports_tab
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
get :vericite_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' => 'authentication_providers#destroy_all', as: :remove_all_authentication_providers
put 'sso_settings' => 'authentication_providers#update_sso_settings',
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
as: :update_sso_settings
resources :authentication_providers, only: [:index, :create, :update, :destroy] do
get :debugging, action: :debug_data
put :debugging, action: :start_debugging
delete :debugging, action: :stop_debugging
end
get 'test_ldap_connections' => 'authentication_providers#test_ldap_connection'
get 'test_ldap_binds' => 'authentication_providers#test_ldap_bind'
get 'test_ldap_searches' => 'authentication_providers#test_ldap_search'
match 'test_ldap_logins' => 'authentication_providers#test_ldap_login', via: [:get, :post]
get 'external_tools/sessionless_launch' => 'external_tools#sessionless_launch'
resources :external_tools do
get :finished
match :resource_selection, via: [:get, :post]
collection do
get :retrieve
end
end
get 'lti/resource/:resource_link_id', controller: 'lti/message',
action: 'resource', as: :resource_link_id
get 'lti/basic_lti_launch_request/:message_handler_id', controller: 'lti/message',
action: 'basic_lti_launch_request', as: :basic_lti_launch_request
post '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', 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 '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'
get 'login/session_token' => 'login#session_token'
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
delete 'logout' => 'login#destroy'
get 'logout' => 'login#logout_landing'
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/canvas' => 'login/canvas#new', as: :canvas_login
post 'login/canvas' => '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', as: :saml_login_base
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/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
get 'login/saml_idp_discovery' => 'login/saml_idp_discovery#new'
get 'login/saml_idp_discovery/:id' => 'login/saml_idp_discovery#new', as: :saml_idp_discovery_login
# 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'
get 'users/self/otps' => 'one_time_passwords#index', as: :one_time_passwords
delete 'users/self/otps' => 'one_time_passwords#destroy_all', as: :destroy_all_one_time_passwords
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
# 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, except: [:destroy, :index] do
match 'masquerade', via: [:get, :post]
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 :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_hide_dashcard_color_overlays' => 'users#toggle_hide_dashcard_color_overlays'
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'
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
get 'stream_items' => 'users#dashboard_stream_items', as: :dashboard_stream_items
2018-08-21 23:41:56 +08:00
get 'dashboard_cards' => 'users#dashboard_cards', as: :dashboard_dashboard_cards
put 'view' => 'users#dashboard_view'
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#show'
get 'calendar2' => 'calendars#show'
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/:id/public_url' => 'files#public_url', as: :public_url
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, :edit]
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'
get 'health_prognosis' => 'info#health_prognosis'
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' => 'login/saml#metadata'
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 unless it is a download from local
# storage. I'm not sure we ever actually want top-level assignments available,
# maybe we should change the specs instead.
# Note, if local storage is used, a file is fetched from this top level
# (i.e. SpeedGrader document preview with Google Docs viewer)
resources :assignments, only: [:index, :show] do
get "files/:id/download" => 'files#show', download: '1'
end
resources :files, :except => [:new] do
get 'download' => 'files#show', download: '1'
end
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: :api_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, as: 'course_todo_list_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/media', controller: :folders, action: :media_folder
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, as: 'user_courses'
get 'courses/:course_id/effective_due_dates', action: :effective_due_dates, as: 'course_effective_due_dates'
get 'courses/:course_id/permissions', action: :permissions
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/account_notifications', action: :user_index, as: 'user_account_notifications' # to change the api docs
get 'accounts/:account_id/users/:user_id/account_notifications', action: :user_index_deprecated # for back compat
get 'accounts/:account_id/account_notifications/:id', action: :show, as: 'user_account_notification_show'
get 'accounts/:account_id/users/:user_id/account_notifications/:id', action: :show_deprecated
delete 'accounts/:account_id/account_notifications/:id', action: :user_close_notification, as: 'user_account_notification'
delete 'accounts/:account_id/users/:user_id/account_notifications/:id', action: :user_close_notification_deprecated
end
scope(controller: :brand_configs_api) do
get "brand_variables", action: :show
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: :scopes_api) do
get "accounts/:account_id/scopes", action: :index
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
post 'courses/:course_id/enrollments/:id/accept', action: :accept
post 'courses/:course_id/enrollments/:id/reject', action: :reject
put 'courses/:course_id/users/:user_id/last_attended', :action => :last_attended
put 'courses/:course_id/enrollments/:id/reactivate', :action => :reactivate, :as => 'reactivate_enrollment'
delete 'courses/:course_id/enrollments/:id', action: :destroy, :as => "destroy_enrollment"
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'
add more search capabilities to audit endpoint This adds more search capabilities to the audit endpoint to give maximum flexibility to support the new gradebook history page. This adds the ability to search for course AND any combination of the following: assignment, grader, student. Permissions were not touched in this patchset, so only admins can access currently. closes CNVS-37299 test plan: - Create a course with two teachers, two assignments, and two student. - Grade the students for the assignments and change the grades a few times as each teacher - Visit the following API endpoints with appropriate ids confirming that appropriate data is returned: o /api/v1/audit/grade_change/courses/:course_id/assignments/:assignment_id o /api/v1/audit/grade_change/courses/:course_id/assignments/:assignment_id/graders/:grader_id o /api/v1/audit/grade_change/courses/:course_id/assignments/:assignment_id/graders/:grader_id/students/:student_id o /api/v1/audit/grade_change/courses/:course_id/assignments/:assignment_id/students/:student_id o /api/v1/audit/grade_change/courses/:course_id/graders/:grader_id o /api/v1/audit/grade_change/courses/:course_id/graders/:grader_id/students/:student_id o /api/v1/audit/grade_change/courses/:course_id/students/:student_id Change-Id: I86648896d49d7228ddce04864e80221da9b5f96d Reviewed-on: https://gerrit.instructure.com/114146 Reviewed-by: Shahbaz Javeed <sjaveed@instructure.com> Tested-by: Jenkins Reviewed-by: Derek Bender <djbender@instructure.com> QA-Review: Anju Reddy <areddy@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
2017-06-03 07:24:41 +08:00
get 'audit/grade_change/courses/:course_id/assignments/:assignment_id',
action: :for_course_and_other_parameters, as: 'audit_grade_change_course_assignment'
get 'audit/grade_change/courses/:course_id/assignments/:assignment_id/graders/:grader_id',
action: :for_course_and_other_parameters, as: 'audit_grade_change_course_assignment_grader'
get 'audit/grade_change/courses/:course_id/assignments/:assignment_id/graders/:grader_id/students/:student_id',
action: :for_course_and_other_parameters, as: 'audit_grade_change_course_assignment_grader_student'
get 'audit/grade_change/courses/:course_id/assignments/:assignment_id/students/:student_id',
action: :for_course_and_other_parameters, as: 'audit_grade_change_course_assignment_student'
get 'audit/grade_change/courses/:course_id/graders/:grader_id',
action: :for_course_and_other_parameters, as: 'audit_grade_change_course_grader'
get 'audit/grade_change/courses/:course_id/graders/:grader_id/students/:student_id',
action: :for_course_and_other_parameters, as: 'audit_grade_change_course_grader_student'
get 'audit/grade_change/courses/:course_id/students/:student_id',
action: :for_course_and_other_parameters, as: 'audit_grade_change_course_student'
end
scope(controller: :course_audit_api) do
get 'audit/course/courses/:course_id', action: :for_course, as: 'audit_course_for_course'
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
get 'courses/:course_id/assignments/overrides', action: :batch_retrieve
put 'courses/:course_id/assignments/overrides', action: :batch_update
post 'courses/:course_id/assignments/overrides', action: :batch_create
end
scope(controller: :assignments_api) do
get "courses/:course_id/assignments/gradeable_students", controller: :submissions_api, action: :multiple_gradeable_students, as: "multiple_assignments_gradeable_students"
get 'courses/:course_id/assignments', action: :index, as: 'course_assignments'
get 'courses/:course_id/assignment_groups/:assignment_group_id/assignments', action: :index, as: 'course_assignment_group_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
post 'courses/:course_id/assignments/:assignment_id/duplicate', action: :duplicate
delete 'courses/:course_id/assignments/:id', action: :destroy, controller: :assignments
end
scope(controller: 'assignment_extensions') do
post "courses/:course_id/assignments/:assignment_id/extensions", action: :create, as: "course_assignment_extensions_create"
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: :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
get "#{context.pluralize}/:#{context}_id/assignments/:assignment_id/submission_summary", action: :submission_summary, as: "#{path_prefix}_assignment_submission_summary"
end
get "courses/:course_id/assignments/:assignment_id/gradeable_students", action: :gradeable_students, as: "course_assignment_gradeable_students"
end
scope(controller: :anonymous_provisional_grades) do
get "courses/:course_id/assignments/:assignment_id/anonymous_provisional_grades/status",
action: :status, as: "course_assignment_anonymous_provisional_status"
end
Create OriginalityReport Api Create endpoint Fixes: PLAT-1906 Test Plan: - Create a new assignment with submission type online with file upload. - As a student submit a document as a submission for the assignment and get the Attachment id from the submission. - Make a post request to "/api/v1/assignments /:assignment_id/submissions/:submission_id/originality_report" with the following param in the body: "originality_report": { "external_tool_id":<id of the tool you installed>, "originality_score": <any value between 0 and 1> } - Verify a new OriginalityReport is created. - Verify create action fails if not all required params are given - Verify create action sets optional params correctly. - Verify the action requires all specified resources exists (file_id, and originality_score). - Verify the action does not allow creating a tool with an originality_score not in the 0..1 range. - Verify the action requires the attachment to be part of the submission. - verify the action requires the submission to be part of the assignment. Change-Id: Id5b0b61d399e4330c8c815bd4715735907f7cc6b Create OriginalityReport Api Create endpoint Fixes: PLAT-1906 Test Plan: - Create a new assignment with submission type online with file upload. - As a student submit a document as a submission for the assignment and get the Attachment id from the submission. - Make a post request to "/api/v1/assignments /:assignment_id/submissions/:submission_id/originality_report" with the following param in the body: "originality_report": { "external_tool_id":<id of the tool you installed>, "originality_score": <any value between 0 and 1> } - Verify a new OriginalityReport is created. - Verify create action fails if not all required params are given - Verify create action sets optional params correctly - Verify the action requires all specified resources exists (file_id, and originality_score). - Verify the action does not allow creating a tool with an originality_score not in the 0..1 range. - Verify the action requires the attachment to be part of the submission. - verify the action requires the submission to be part of the assignment. Change-Id: Id5b0b61d399e4330c8c815bd4715735907f7cc6b Reviewed-on: https://gerrit.instructure.com/94476 Tested-by: Jenkins Reviewed-by: Nathan Mills <nathanm@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Weston Dransfield <wdransfield@instructure.com>
2016-11-03 01:54:06 +08:00
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
add bulk selection for provisional grades closes GRADE-1480 test plan: A. Setup 1. Create a published course 2. Enroll one teacher 3. Enroll two TAs 4. Enroll three students 5. Create a moderated assignment * with Teacher as final grader 6. As the first TA: a. Visit SpeedGrader for the assignment b. Grade Student 1 c. Grade Student 2 7. As the second TA: a. Visit SpeedGrader for the assignment b. Grade Student 2 c. Grade Student 3 8. Open the Rails console 9. Note these attributes of the provisional grades: * `id` (provisional grade id) * `user_id` (student id) * `scorer_id` (grader id) assignment = Assignment.find(:id) assignment.pluck(:id, :user_id, :scorer_id) B. Verification without Anonymity * To test bulk selection, send a PUT request to: /api/v1/courses/:course_id/assignments/:assignment_id/ ↪ provisional_grades/bulk_select * Use a session for the final grader * Include in the request body an object as follows: {provisional_grade_ids: […]} * The array will contain some of the provisional grade ids noted from the Rails console * The response will include an array of objects as follows: { "assignment_id": "1", "selected_provisional_grade_id": "2", "student_id": "3" } * To verify grade selection: a. Log in or act as the Teacher b. Visit the moderation page for the assignment c. Verify the intended grades have been selected * Each of the following steps will be done in sequence without resetting anything to a prior state 1. Bulk select the following grades: * TA-1's grade for Student 1 * TA-2's grade for Student 2 2. Verify the JSON includes the following grades: * TA-1's grade for Student 1 * TA-2's grade for Student 2 3. Verify the following grades are selected: * TA-1's grade for Student 1 * TA-2's grade for Student 2 4. Bulk select the following grades: * TA-1's grade for Student 2 * TA-2's grade for Student 3 5. Verify the JSON includes the following grades: * TA-1's grade for Student 2 * TA-2's grade for Student 3 6. Verify the following grades are selected: * TA-1's grade for Student 1 * TA-1's grade for Student 2 * TA-2's grade for Student 3 7. Bulk select the following grades (listed in this order): * TA-1's grade for Student 1 * TA-2's grade for Student 3 * TA-1's grade for Student 3 8. Verify the JSON includes the following grades: * TA-1's grade for Student 3 9. Verify the following grades are selected: * TA-1's grade for Student 1 * TA-1's grade for Student 2 * TA-1's grade for Student 3 B. Verification with Anonymity 1. Enable anonymous grading for the assignment 2. Bulk select the following grades: * TA-2's grade for Student 2 * TA-2's grade for Student 3 3. Verify the JSON includes "anonymous_id" 4. Verify the JSON excludes "student_id" e1d4b3ee4d0d1a4bb647d7a149b57894d91bb503 Change-Id: I51190808a9dfd321c6110f50d6d0e4661fa86c1c Reviewed-on: https://gerrit.instructure.com/161215 Reviewed-by: Adrian Packel <apackel@instructure.com> Tested-by: Jenkins Reviewed-by: Gary Mei <gmei@instructure.com> QA-Review: James Butters <jbutters@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
2018-08-18 03:09:54 +08:00
put "courses/:course_id/assignments/:assignment_id/provisional_grades/bulk_select",
action: :bulk_select, as: 'bulk_select_provisional_grades'
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
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"
post "#{context.pluralize}/:#{context}_id/discussion_topics/:topic_id/duplicate", action: :duplicate
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'
get 'courses/:course_id/potential_collaborators', action: :potential_collaborators, as: 'course_potential_collaborators'
get 'groups/:group_id/potential_collaborators', action: :potential_collaborators, as: 'group_potential_collaborators'
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"
post "#{context}s/:#{context}_id/create_tool_with_verification", action: :create_tool_with_verification, as: "#{context}_create_tool_with_verification"
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
put 'accounts/:account_id/sis_imports/abort_all_pending', action: :abort_all_pending
get 'accounts/:account_id/sis_imports/importing', action: :importing
get 'accounts/:account_id/sis_imports/:id', action: :show
get 'accounts/:account_id/sis_imports', action: :index, as: "account_sis_imports"
put 'accounts/:account_id/sis_imports/:id/abort', action: :abort
put 'accounts/:account_id/sis_imports/:id/restore_states', action: :restore_states
end
scope(controller: :sis_import_errors_api) do
get 'accounts/:account_id/sis_imports/:id/errors', action: :index, as: :sis_batch_import_errors
get 'accounts/:account_id/sis_import_errors', action: :index, as: :account_sis_import_errors
end
Outcome import creation/status endpoints closes OUT-1534 Scheduling of outcome import jobs will occur in a separate PS, after this merges and OUT-1997 is merged too. test plan: - start up canvas - generate api docs: > docker-compose run --rm web bundle exec rake doc:api - load api docs in http://canvas.docker/doc/api/index.html - read over the "Outcomes CSV Format" and make sure it reads well - read over the "Outcomes Import" and make sure it reads well - obtain an access token: https://community.canvaslms.com/docs/DOC-10806-4214724194 - request an outcome import, replace "canvas-path" and "token" values: curl -F attachment=@<canvas-path>/spec/lib/outcomes/fixtures/demo.csv \ -F 'import_type=instructure_csv' \ -H "Authorization: Bearer <token>" \ http://canvas.docker/api/v1/accounts/1/outcome_imports - in a rails console, confirm that the import was accepted: > docker-compose run --rm web bin/rails console % pp OutcomeImport.last # confirm that the import is in the 'created' state, associated with your user and associated with an account context # note the "id" value for later use % pp OutcomeImport.last.attachment # confirm that the attachment is in the 'processed' state and has the filename "test_outcomes_1.csv" passed in above - request the status of the outcome import (should return a message saying "The specified resource does not exist"): curl -H "Authorization: Bearer <token>" \ http://canvas.docker/api/v1/accounts/1/outcome_imports/latest - back in the rails console created above, manually transition the import to "importing": % OutcomeImport.last.job_started - run the above curl command again, and this time the latest outcome import should be returned, in the 'importing' state - run the above curl command again, replacing "latest" with the "id" value obtained above. it should return the same response as the previous step. Change-Id: Ice7d67b625b443cec70f531f2e673face6d6fbeb Reviewed-on: https://gerrit.instructure.com/142024 Reviewed-by: Neil Gupta <ngupta@instructure.com> Reviewed-by: Frank Murphy <fmurphy@instructure.com> Tested-by: Jenkins QA-Review: Frank Murphy <fmurphy@instructure.com> Product-Review: Neil Gupta <ngupta@instructure.com>
2018-02-24 06:18:42 +08:00
scope(controller: :outcome_imports_api) do
%w(account course).each do |context|
post "#{context}s/:#{context}_id/outcome_imports", action: :create
get "#{context}s/:#{context}_id/outcome_imports/:id", action: :show
end
end
Outcome proficiency endpoints closes OUT-1855, OUT-2214 test plan: - create an access token, which will be used below to perform HTTP requests, see: https://canvas.instructure.com/doc/api/file.oauth.html#using-access-tokens - using a tool like Postman, set an outcome proficiency for an account. perform a POST request at the endpoint `http://canvas.docker/api/v1/accounts/1/outcome_proficiency` with a `Content-Type` header value `application/json` and body with content like: { "ratings": [ { "description": "great work", "points": 10, "mastery": true, "color": "00ff00" } ] } - retrieve the saved proficiency by performing GET request at the endpoint `http://canvas.docker/api/v1/accounts/1/outcome_proficiency`. it should match the proficiency created above. - update the proficiency by doing another POST request, but with multiple ratings, like: { "ratings": [ { "description": "great work", "points": 10, "mastery": true, "color": "00ff00" }, { "description": "bad work", "points": 0, "mastery": false, "color": "ff0000" } ] } - do a GET request to confirm the above changes were saved - do several other POST requests with multiple ratings that contain either multiple mastery ratings or none. these requests should fail with a 422 status code and an error message that contains `Only one rating can have mastery`. Change-Id: Ib301c0394a99dbf55d7d85ceef28a95075faaec2 Reviewed-on: https://gerrit.instructure.com/150095 Reviewed-by: Frank Murphy <fmurphy@instructure.com> Tested-by: Jenkins Reviewed-by: Rob Orton <rob@instructure.com> Reviewed-by: Matt Berns <mberns@instructure.com> QA-Review: Andrew Porter <hporter-c@instructure.com> Product-Review: Michael Brewer-Davis <mbd@instructure.com>
2018-04-14 06:16:16 +08:00
scope(controller: :outcome_proficiency_api) do
post "accounts/:account_id/outcome_proficiency", action: :create
get "accounts/:account_id/outcome_proficiency", action: :show
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, as: 'user_todo_list_items'
get 'users/self/todo_item_count', action: :todo_item_count
get 'users/self/upcoming_events', action: :upcoming_events
get 'users/:user_id/missing_submissions', action: :missing_submissions, as: 'user_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'
get 'users/:id/new_user_tutorial_statuses', action: 'get_new_user_tutorial_statuses'
put 'users/:id/new_user_tutorial_statuses/:page_name', action: 'set_new_user_tutorial_status'
get 'users/:id/dashboard_positions', controller: 'users', action: 'get_dashboard_positions'
put 'users/:id/dashboard_positions', controller: 'users', action: 'set_dashboard_positions'
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'
post 'users/self/pandata_events_token', controller: 'users', action: 'pandata_events_token'
get 'dashboard/dashboard_cards', controller: 'users', action: 'dashboard_cards', as: :dashboard_dashboard_cards
get 'users/:id/graded_submissions', controller: 'users', action: 'user_graded_submissions', as: :user_submissions
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
scope(controller: :observer_alerts_api) do
get 'users/:user_id/observer_alerts/unread_count', action: :alerts_count
get 'users/:user_id/observer_alerts/:student_id', action: :alerts_by_student, as: 'observer_alerts_by_student'
put 'users/:user_id/observer_alerts/:observer_alert_id/:workflow_state', action: :update
end
scope(controller: :observer_alert_thresholds_api) do
get 'users/:user_id/observer_alert_thresholds', action: :index
post 'users/:user_id/observer_alert_thresholds', action: :create
get 'users/:user_id/observer_alert_thresholds/:observer_alert_threshold_id', action: :show
put 'users/:user_id/observer_alert_thresholds/:observer_alert_threshold_id', action: :update
delete 'users/:user_id/observer_alert_thresholds/:observer_alert_threshold_id', action: :destroy
end
scope(controller: :observer_pairing_codes_api) do
post 'users/:user_id/observer_pairing_codes', action: :create
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/terms_of_service', action: :terms_of_service
get 'accounts/:account_id/help_links', action: :help_links
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'
get 'accounts/:account_id/permissions', action: :permissions
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
delete 'accounts/:account_id/sub_accounts/:id', action: :destroy
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: :authentication_providers) 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'
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
get 'conversations/deleted', action: :deleted_index, as: 'deleted_conversations'
put 'conversations/restore', action: :restore_message
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'
get 'accounts/:account_id/bounced_communication_channels.csv', action: :bouncing_channel_report
post 'accounts/:account_id/bounced_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/self/communication_channels/push', action: :delete_push_token
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'
get 'calendar_events/:id/participants', action: :participants, as: 'calendar_event_participants'
post 'calendar_events/save_selected_contexts', action: :save_selected_contexts
get 'courses/:course_id/calendar_events/timetable', action: :get_course_timetable
post 'courses/:course_id/calendar_events/timetable', action: :set_course_timetable
post 'courses/:course_id/calendar_events/timetable_events', action: :set_course_timetable_events
end
scope(controller: :appointment_groups) do
get 'appointment_groups', action: :index, as: 'appointment_groups'
post 'appointment_groups', action: :create
get 'appointment_groups/next_appointment', action: :next_appointment
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'
get 'groups/:group_id/permissions', action: :permissions
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/media', controller: :folders, action: :media_folder
get 'groups/:group_id/folders/:id', controller: :folders, action: :show, as: 'group_folder'
end
Create DeveloperKeyAccountBinding API Closes PLAT-3208 Test Plan: - For all new endpoints verify the the user must have the manage developer key permission for the requestd account. CREATE - In a root account create a developer key. - Using the new binding create endpoint create a developer key account binding: POST { "developer_key_account_binding": { "workflow_state": "on" } } - Verify a DeveloperKeyAccountBinding was created with a workflow state of 'on', an account id pointing to the root account, and a develoepr key pointing to the root account developer key. - Create a developer key in a sub account. - Repeate the above process but create a binding for the sub account and sub account developer key. - Verify you cannont create a binding using the root account id and the sub account develope key id. UPDATE PUT { "developer_key_account_binding": { "workflow_state": "off" } } - Verify you can use the update endpoint to modify the workflow_state of the DeveloperKeyAccountBinding create previously in the root account. - Do the same for sub accounts. INDEX - Verify the endpoint lists all DeveloperKeyAccountBindings from the account specified by the account_id param. - Verify the endpoint lists all DeveloperKeyAccountBindings from any parent accounts. - Verify the endpoint lists all DeveloperKeyAccountBindings from the site admin account. Change-Id: Id81b1d5ef0eb1d6a62ca180b66be6f92a285c3de Reviewed-on: https://gerrit.instructure.com/143908 Tested-by: Jenkins Reviewed-by: Stewie aka Nicholas Stewart <nstewart@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Weston Dransfield <wdransfield@instructure.com>
2018-03-17 04:59:43 +08:00
scope(controller: :developer_key_account_bindings) do
2018-03-20 01:09:59 +08:00
post 'accounts/:account_id/developer_keys/:developer_key_id/developer_key_account_bindings', action: :create_or_update
Create DeveloperKeyAccountBinding API Closes PLAT-3208 Test Plan: - For all new endpoints verify the the user must have the manage developer key permission for the requestd account. CREATE - In a root account create a developer key. - Using the new binding create endpoint create a developer key account binding: POST { "developer_key_account_binding": { "workflow_state": "on" } } - Verify a DeveloperKeyAccountBinding was created with a workflow state of 'on', an account id pointing to the root account, and a develoepr key pointing to the root account developer key. - Create a developer key in a sub account. - Repeate the above process but create a binding for the sub account and sub account developer key. - Verify you cannont create a binding using the root account id and the sub account develope key id. UPDATE PUT { "developer_key_account_binding": { "workflow_state": "off" } } - Verify you can use the update endpoint to modify the workflow_state of the DeveloperKeyAccountBinding create previously in the root account. - Do the same for sub accounts. INDEX - Verify the endpoint lists all DeveloperKeyAccountBindings from the account specified by the account_id param. - Verify the endpoint lists all DeveloperKeyAccountBindings from any parent accounts. - Verify the endpoint lists all DeveloperKeyAccountBindings from the site admin account. Change-Id: Id81b1d5ef0eb1d6a62ca180b66be6f92a285c3de Reviewed-on: https://gerrit.instructure.com/143908 Tested-by: Jenkins Reviewed-by: Stewie aka Nicholas Stewart <nstewart@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Weston Dransfield <wdransfield@instructure.com>
2018-03-17 04:59:43 +08:00
get 'accounts/:account_id/developer_key_account_bindings', action: :index
end
scope(controller: :developer_keys) do
get 'developer_keys/:id', action: :show
delete 'developer_keys/:id', action: :destroy
put 'developer_keys/:id', action: :update
get 'accounts/:account_id/developer_keys', action: :index, as: 'account_developer_keys'
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
inst-fs upload preflight (and capture fixes) fixes CNVS-38591 when the inst-fs service is enabled, generate a preflight response tailored for inst-fs instead of for S3. the service will then receive the POSTed file data, generate it, and ping Canvas at the embedded capture URL. compatible with existing Canvas UI. along the way, some cleanup refactoring in api_attachment_preflight: * instead of taking submission_context and inferring a folder from that, have the submission API be responsible for determining the folder and then just specify it. note that the folder inference was the only use of submission_context, the submission API was the only caller of api_preflight_json to specify submission_context, and the folder option we took over was previously both broken and unused. * simplify the remaining folder inference code. if a folder is specified by the code (vs. the user in params), assume they have necessary access (the :manage_contents permission would fail for a student making a submission) * correctly abort if params[:on_duplicate] is invalid. before, if the UI provided an explicit but invalid value, it would cause a double render error. * inline process_attachment_params for update, and skip it on preflight. the UI never provides any of the possible params but display_name for preflight, which is then ignored from the process_attachment_params result because it's treated separately TODO: tests * InstFS.upload_preflight_json * api_attachment_preflight: - uploading a file to a submission (submissions_api#create_file) when the submissions_folder feature is enabled stores the file in the user's submissions folder - student uploading a file to a submission is not blocked by permissions - user with :manage_contents permission on a folder is not blocked when uploading to that folder - user without :manage_contents permission on a folder is blocked when attempting to upload to that folder - no double render error on on_duplicate=invalid - updates to lock_at, etc., on a file (via files#api_update) stick * files#api_capture: - reject if over quota and not flagged quota_exempt - attachment.locked based on usage rights settings - attachment.handle_duplicates - content migration success callback triggered * InstFS.authenticated_url: - includes iat claim - expiration is a timestamp test-plan: inst-fs upload happy path: - have inst-fs service running, have canvas configured to be able to find and share a secret with it, and enable the inst-fs plugin setting - go to the files area, or a discussion, or a conversation, etc., and upload a file. - the file should be successfully uploaded - NOTE: known issue, there seems to be a race condition in the service responding 201 Created with a Location before Canvas is ready to respond to that Location. This will make the upload appear to fail. But if you refresh the page, the file should be present. This race condition will be fixed in a later commit; it has already been filed as a separate bug. - attempt to download/preview the file - download/preview should work, and should be served from inst-fs quota enforcement: - configure a course to have a quota - select a file that should exceed that quota when uploaded - bypassing the canvas UI, access the preflight endpoint directly while providing the true size; preflight should fail - access the preflight endpoint directly while providing a false size that would fit inside the quota; preflight should succeed - attempt to POST the file to the returned upload_url with the returned upload_params; the upload should fail locking pending usage rights: - configure the account to lock files without usage rights - upload a file - the newly created file should be locked - assign usage rights to the new file - it should unlock path collisions: - upload a file to a folder - upload a distinct file but with the same filename to the same folder - should be prompted to rename or overwrite - select rename; the newly uploaded file should have the filename modified to avoid the collision - repeat, but selecting overwrite; the filename should now refer to the new file, and the old file should not be accessible in the UI non-inst-fs unharmed: - disable the inst-fs plugin setting - do general regression tests on file uploads (whether S3 or local storage) Change-Id: I2bff1e3c31a3ed0955c29e677a422b7149253318 Reviewed-on: https://gerrit.instructure.com/124929 Tested-by: Jenkins Reviewed-by: Andrew Huff <ahuff@instructure.com> QA-Review: Collin Parrish <cparrish@instructure.com> Product-Review: Jacob Fugal <jacob@instructure.com>
2017-09-06 02:53:02 +08:00
post 'files/capture', action: :api_capture, as: 'files_capture'
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
# exists as an alias of GET for backwards compatibility
#
# older API clients were told to POST to the value of the Location header
# returned after upload to S3, when that was the create_success URL.
# that's no longer necessary, but they are still given a Location header
# pointed at this endpoint which they can GET for the file details (which
# create_success would have provided). for those that are still POSTing,
# we'll allow this but it's a noop (as far as side effects)
#
# to actually change the file metadata (e.g. rename), the PUT route above
# must be used.
post 'files/:id', action: :api_show
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
Add the ability to duplicate pages. * Closes FALCOR-139 * Closes FALCOR-140 * Closes FALCOR-141 Test Plan: * Create a course, and make a wiki page. * If "Duplicate Enabled" feature option is set, then a duplicate option should occur on the cog next to the page you created. * When this is clicked, a new page should pop up below unpublished, with focus on the cog of the new page. * (If you make a page that is an assignment, the new page will also show up on the assignments list) * A student should not be able to see this option, and if the feature flag is off, this option also should not appear. * A wiki page assignment can now also be duplicated from the "Assignments" list as well. * Discussion and Quizzes still cannot be duplicated from the "Assignments" list * Title convention: If title does not end in "Copy" or "Copy #" will append "Copy" to the end of the title. * After doing the above, finds the lowest number that doesn't duplicate an existing assignment or wiki page name (if a number is needed to effect this) * In the above search, if a "#" is present on the title, *always* starts from the # given. So "Copy 7" will go to "Copy 8" even if 1-6 are not used. Change-Id: Ib595a859b9186f934626b56e94a00eea231baa5a Reviewed-on: https://gerrit.instructure.com/115934 Tested-by: Jenkins Reviewed-by: Steven Burnett <sburnett@instructure.com> Reviewed-by: Dan Minkevitch <dan@instructure.com> QA-Review: Deepeeca Soundarrajan <dsoundarrajan@instructure.com> Product-Review: Mary Jane Anderson <manderson@instructure.com>
2017-06-14 01:25:49 +08:00
post "courses/:course_id/pages/:url/duplicate", action: :duplicate
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/:module_id/duplicate", action: :duplicate
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
post "courses/:course_id/modules/:module_id/items/:id/select_mastery_path", action: :select_mastery_path
post "courses/:course_id/modules/items/:id/duplicate", action: :duplicate, as: :course_context_module_item_duplicate
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
Deterministically get a submission for a user fixes CNVS-30098 The course/:course_id/quizzes/:quiz_id/submissions api returns different things in different cases and the mobile teams want a way to be able to easily get the submission for the current user so they don't have to do client-side filtering on all of the apps. Let's add that as course/:course_id/quizzes/:quiz_id/submission that'll only ever give any one submission for you. Also update the docs for the existing API so it is more clear what it does. test plan: - request the new API as a student without a quiz submission and verify you are returned an empty set of quiz submissions - request the new API as a student with a quiz submission that is not yet submitted and verify that you are returned a single quiz submission with workflow_state = untaken - reuqest the new API as a student with a quiz submission that is submitted and verify that you are returned a single quiz submission with workfow_state = complete - request the new API as a student with a quiz submission that has many submitted attempts and verify that you are returned a single quiz submission with workflow_state = complete and attempt number is the latest attempt - request the new API as a teacher or admin and verify that you are returned an empty set of quiz submissions - request the new API as a teacher or admin who is also a student with a quiz submission and verify that you are returned only your one quiz submission Change-Id: Ib364e9c4be0f196c10892dafe5bad75c86acbdbc Reviewed-on: https://gerrit.instructure.com/83846 Reviewed-by: Davis Lynn McClellan <dmcclellan@instructure.com> Tested-by: Jenkins QA-Review: Robin Kuss <rkuss@instructure.com> Product-Review: Brandon Pluim <bpluim@instructure.com>
2016-06-29 05:51:09 +08:00
get 'courses/:course_id/quizzes/:quiz_id/submission', action: :submission, as: 'course_quiz_user_submission'
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: 'support_helpers/turnitin') do
get "support_helpers/turnitin/md5", action: :md5
get "support_helpers/turnitin/error2305", action: :error2305
get "support_helpers/turnitin/shard", action: :shard
get "support_helpers/turnitin/assignment", action: :assignment
get "support_helpers/turnitin/pending", action: :pending
get "support_helpers/turnitin/expired", action: :expired
get "support_helpers/turnitin/refresh_lti_attachment", action: :lti_attachment
end
scope(controller: 'support_helpers/plagiarism_platform') do
get "support_helpers/plagiarism_platform/add_service", action: :add_service
get "support_helpers/plagiarism_platform/resubmit_for_assignment/:assignment_id", action: :resubmit_for_assignment
end
scope(controller: 'support_helpers/crocodoc') do
get "support_helpers/crocodoc/shard", action: :shard
get "support_helpers/crocodoc/submission", action: :submission
end
scope(controller: 'support_helpers/due_date_cache') do
get "support_helpers/due_date_cache/course", action: :course
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
get "courses/:course_id/outcome_alignments", action: :outcome_alignments
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"
put "courses/:course_id/custom_gradebook_column_data", action: :bulk_update, as: "course_custom_gradebook_column_bulk_data"
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: :web_zip_exports) do
get 'courses/:course_id/web_zip_exports', action: :index, as: "web_zip_exports"
get 'courses/:course_id/web_zip_exports/:id', action: :show
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
get 'courses/:course_id/grading_standards/:grading_standard_id', action: :context_show
get 'accounts/:account_id/grading_standards/:grading_standard_id', action: :context_show
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
add endpoint to refresh jwt with with workflows now that services jwts have a concept of workflows and extra data encoded in the token based on workflow requirements, the existing jwts endpoint is insufficient for refreshing expired jwts. to some extent it was already broken since it lost the context when refreshed with that endpoint a new refresh endpoint has been addded that takes an exisintg jwt as a param. this makes it possible to get a new token with the same workflows, state, and context as an existing expired token as long as the token matches your user and is requested with a valid session or oauth token. tokens may only be used for refresh up to six hours past expiration. refs CNVS-35199 test plan: - go to "Pages" in a couse with RCS enabled - open the console, and get the jwt from ENV.JWT - wait at least an hour - make a POST to [same-domain]/api/v1/jwts/refresh with the token as the `jwt` param - it should return a json response with a token property - copy the token - open up your rails console - run Canvas::Security.ServicesJwt.new("[copied token]").original_token - should return hash with the following proerties - should have :sub with your users global id - should have :domain that matches your canvas domain - should have :context_type of Course - should have :context_id of the course you generated the original token from - should have :workflows with rich_content and ui - repeat process masquerading as another user - when making a the post to the refresh endpoint use your user and set a param `as_user_id` to the id of the user you are masquerading as - the hash in the console should have - :sub with the global id of the user you are masquerading as - :masq_sub with your user id Change-Id: I399569ed8f2d3d0646728f72910456b77b3ed46a Reviewed-on: https://gerrit.instructure.com/102909 Reviewed-by: Tucker McKnight <tmcknight@instructure.com> QA-Review: Tucker McKnight <tmcknight@instructure.com> Tested-by: Jenkins Product-Review: Brent Burgoyne <bburgoyne@instructure.com>
2017-02-23 00:16:49 +08:00
post 'jwts/refresh', action: :refresh
end
scope(controller: :gradebook_settings) do
put 'courses/:course_id/gradebook_settings', action: :update, as: :course_gradebook_settings_update
end
scope(controller: :announcements_api) do
get 'announcements', action: :index, as: :announcements
end
add new Rubric API endpoint closes OUT-358 refs PFS-4925 test plan: - review new API documentation - create some rubrics in the context of an account - create some rubrics in the context of a course - attach the rubrics to some assignments - for at least one assignment, enable peer reviews and assign some students - as a teacher, assess the assignment - as a student, complete some peer reviews - go to the following endpoints api/v1/accounts/{account_id}/rubrics - should list all rubrics in the given account api/v1/courses/{course_id}/rubrics - should list all rubrics in the given course api/v1/accounts/{account_id}/rubrics/{rubric_id} - should list the specific account rubric api/v1/courses/{course_id}/rubrics/{rubric_id} - should list the specific course rubric api/v1/courses/{course_id}/rubrics/{rubric_id}?include=assessments - should include all assessments for the rubric api/v1/courses/{course_id}/rubrics/{rubric_id}?include=graded_assessments - should include only the assessment(s) used for grading the rubric api/v1/courses/{course_id}/rubrics/{rubric_id}?include=peer_assessments - should include only the peer_assessment(s) for the rubric - when getting assessments, add the following parameters &style=full should return the full data hash associated with returned assessments &style=comments_only should only return the comments from an assessment's data hash - when entering in invalid values for include or style, an error should be returned that provides you with the valid values for the respective parameters Change-Id: Ib46900d4c58e06d6fa2771614ba2efa11d3b5b6c Reviewed-on: https://gerrit.instructure.com/87702 Tested-by: Jenkins Reviewed-by: Michael Brewer-Davis <mbd@instructure.com> QA-Review: Alex Ortiz-Rosado <aortiz@instructure.com> Product-Review: Josh Simpson <jsimpson@instructure.com>
2016-08-13 04:40:02 +08:00
scope(controller: :rubrics_api) do
get 'accounts/:account_id/rubrics', action: :index, as: :account_rubrics
get 'accounts/:account_id/rubrics/:id', action: :show
get 'courses/:course_id/rubrics', action: :index, as: :course_rubrics
get 'courses/:course_id/rubrics/:id', action: :show
post 'courses/:course_id/rubrics', controller: :rubrics, action: :create
put 'courses/:course_id/rubrics/:id', controller: :rubrics, action: :update
delete 'courses/:course_id/rubrics/:id', controller: :rubrics, action: :destroy
add new Rubric API endpoint closes OUT-358 refs PFS-4925 test plan: - review new API documentation - create some rubrics in the context of an account - create some rubrics in the context of a course - attach the rubrics to some assignments - for at least one assignment, enable peer reviews and assign some students - as a teacher, assess the assignment - as a student, complete some peer reviews - go to the following endpoints api/v1/accounts/{account_id}/rubrics - should list all rubrics in the given account api/v1/courses/{course_id}/rubrics - should list all rubrics in the given course api/v1/accounts/{account_id}/rubrics/{rubric_id} - should list the specific account rubric api/v1/courses/{course_id}/rubrics/{rubric_id} - should list the specific course rubric api/v1/courses/{course_id}/rubrics/{rubric_id}?include=assessments - should include all assessments for the rubric api/v1/courses/{course_id}/rubrics/{rubric_id}?include=graded_assessments - should include only the assessment(s) used for grading the rubric api/v1/courses/{course_id}/rubrics/{rubric_id}?include=peer_assessments - should include only the peer_assessment(s) for the rubric - when getting assessments, add the following parameters &style=full should return the full data hash associated with returned assessments &style=comments_only should only return the comments from an assessment's data hash - when entering in invalid values for include or style, an error should be returned that provides you with the valid values for the respective parameters Change-Id: Ib46900d4c58e06d6fa2771614ba2efa11d3b5b6c Reviewed-on: https://gerrit.instructure.com/87702 Tested-by: Jenkins Reviewed-by: Michael Brewer-Davis <mbd@instructure.com> QA-Review: Alex Ortiz-Rosado <aortiz@instructure.com> Product-Review: Josh Simpson <jsimpson@instructure.com>
2016-08-13 04:40:02 +08:00
end
scope(controller: :rubric_associations) do
post 'courses/:course_id/rubric_associations', action: :create
put 'courses/:course_id/rubric_associations/:id', action: :update
delete 'courses/:course_id/rubric_associations/:id', action: :destroy
end
Expose Rubric Assessment API endpoints CUD Test Plan. Use postman or curl to test the following endpoints Remember to change the: :course_id with the appropiate course_id :rubric_association_id with the appropiate rubric_association_id :id with the rubric_assessment_id POST 'courses/:course_id/rubric_associations/ :rubric_association_id/rubric_assessments' params example: { "rubric_assessment": { "user_id": "22", "assessment_type": "grading", "criterion__7226": { "points": "3", "comments": "", "save_comment": "0" } }, "graded_anonymously": "false" } PUT 'courses/:course_id/rubric_associations/ :rubric_association_id/rubric_assessments/:id' params example: { "rubric_assessment": { "user_id": "22", "assessment_type": "grading", "criterion__7226": { "points": "3", "comments": "", "save_comment": "0" } }, "graded_anonymously": "false" } DELETE 'courses/:course_id/rubric_associations/ :rubric_association_id/rubric_assessments/:id' refs: PFS-11756 Change-Id: Ib67898f2dec37c3438e1d8f5745c20f1c41113e0 Reviewed-on: https://gerrit.instructure.com/180683 Tested-by: Jenkins QA-Review: Aiona Rae Hernandez <ahernandez@instructure.com> QA-Review: Brian Watson <bwatson@instructure.com> Reviewed-by: Neil Gupta <ngupta@instructure.com> Reviewed-by: Colin Cromar <ccromar@instructure.com> Reviewed-by: Augusto Callejas <acallejas@instructure.com> Product-Review: Augusto Callejas <acallejas@instructure.com> (cherry picked from commit d17de50121f60104c136b0a1831db786b816231c) Reviewed-on: https://gerrit.instructure.com/183188 Product-Review: Neil Gupta <ngupta@instructure.com>
2019-02-06 06:34:04 +08:00
scope(controller: :rubric_assessment_api) do
post 'courses/:course_id/rubric_associations/:rubric_association_id/rubric_assessments', controller: :rubric_assessments, action: :create
put 'courses/:course_id/rubric_associations/:rubric_association_id/rubric_assessments/:id', controller: :rubric_assessments, action: :update
delete 'courses/:course_id/rubric_associations/:rubric_association_id/rubric_assessments/:id', controller: :rubric_assessments, action: :destroy
end
scope(controller: 'master_courses/master_templates') do
get 'courses/:course_id/blueprint_templates/:template_id', action: :show
get 'courses/:course_id/blueprint_templates/:template_id/associated_courses', action: :associated_courses, as: :course_blueprint_associated_courses
put 'courses/:course_id/blueprint_templates/:template_id/update_associations', action: :update_associations
get 'courses/:course_id/blueprint_templates/:template_id/unsynced_changes', action: :unsynced_changes, as: :course_blueprint_unsynced_changes
post 'courses/:course_id/blueprint_templates/:template_id/migrations', action: :queue_migration
get 'courses/:course_id/blueprint_templates/:template_id/migrations', action: :migrations_index, as: :course_blueprint_migrations
get 'courses/:course_id/blueprint_templates/:template_id/migrations/:id', action: :migrations_show
get 'courses/:course_id/blueprint_templates/:template_id/migrations/:id/details', action: :migration_details
put 'courses/:course_id/blueprint_templates/:template_id/restrict_item', action: :restrict_item
get 'courses/:course_id/blueprint_subscriptions', action: :subscriptions_index, as: :course_blueprint_subscriptions
get 'courses/:course_id/blueprint_subscriptions/:subscription_id/migrations', action: :imports_index, as: :course_blueprint_imports
get 'courses/:course_id/blueprint_subscriptions/:subscription_id/migrations/:id', action: :imports_show
get 'courses/:course_id/blueprint_subscriptions/:subscription_id/migrations/:id/details', action: :import_details
end
scope(controller: :late_policy) do
get 'courses/:id/late_policy', action: :show
post 'courses/:id/late_policy', action: :create
patch 'courses/:id/late_policy', action: :update
end
Planner API Closes FALCOR-183 Closes FALCOR-184 Closes FALCOR-255 Closes FALCOR-186 Closes FALCOR-187 Closes FALCOR-188 Closes FALCOR-189 Closes FALCOR-147 Closes FALCOR-148 Test Plan: * As a student in an account with the Student Planner feature flag enabled * In a course with multiple upcoming due assignments in the current and following weeks * Test that the following API endpoints provide you with the data described: get '/api/v1/planner/items' * Should return a list matching that of the todo list endpoint, while adding an additional key named `visible_in_planner` get '/api/v1/planner/overrides' * Should return a list of previously created PlannerOverrides get '/api/v1/planner/overrides/:override_id' * Should return the specific override for the passed in id put '/api/v1/planner/overrides/:override_id' * Should update an existing override's `visible` value to match what was passed in the request. No other values should be updated post '/api/v1/planner/overrides' * Should create a new PlannerOverride with the specified `plannable_type`, `plannable_id`, and `visible` values. `user_id` should match that of the user making the request delete '/api/v1/planner/overrides/:override_id' * Should set the PlannerOverride's `deleted_at` to when the request was made, as well as updating the `workflow_state` to `deleted` Change-Id: I03890a525f8201a8df1d2f1290cdcd549ba548d7 Reviewed-on: https://gerrit.instructure.com/107495 Tested-by: Jenkins Reviewed-by: Steven Burnett <sburnett@instructure.com> QA-Review: Deepeeca Soundarrajan <dsoundarrajan@instructure.com> Product-Review: Dan Minkevitch <dan@instructure.com>
2017-05-11 12:40:45 +08:00
scope(controller: :planner) do
get 'planner/items', action: :index, as: :planner_items
end
Planner API Closes FALCOR-183 Closes FALCOR-184 Closes FALCOR-255 Closes FALCOR-186 Closes FALCOR-187 Closes FALCOR-188 Closes FALCOR-189 Closes FALCOR-147 Closes FALCOR-148 Test Plan: * As a student in an account with the Student Planner feature flag enabled * In a course with multiple upcoming due assignments in the current and following weeks * Test that the following API endpoints provide you with the data described: get '/api/v1/planner/items' * Should return a list matching that of the todo list endpoint, while adding an additional key named `visible_in_planner` get '/api/v1/planner/overrides' * Should return a list of previously created PlannerOverrides get '/api/v1/planner/overrides/:override_id' * Should return the specific override for the passed in id put '/api/v1/planner/overrides/:override_id' * Should update an existing override's `visible` value to match what was passed in the request. No other values should be updated post '/api/v1/planner/overrides' * Should create a new PlannerOverride with the specified `plannable_type`, `plannable_id`, and `visible` values. `user_id` should match that of the user making the request delete '/api/v1/planner/overrides/:override_id' * Should set the PlannerOverride's `deleted_at` to when the request was made, as well as updating the `workflow_state` to `deleted` Change-Id: I03890a525f8201a8df1d2f1290cdcd549ba548d7 Reviewed-on: https://gerrit.instructure.com/107495 Tested-by: Jenkins Reviewed-by: Steven Burnett <sburnett@instructure.com> QA-Review: Deepeeca Soundarrajan <dsoundarrajan@instructure.com> Product-Review: Dan Minkevitch <dan@instructure.com>
2017-05-11 12:40:45 +08:00
scope(controller: :planner_overrides) do
get 'planner/overrides', action: :index, as: :planner_overrides
get 'planner/overrides/:id', action: :show
put 'planner/overrides/:id', action: :update
Planner API Closes FALCOR-183 Closes FALCOR-184 Closes FALCOR-255 Closes FALCOR-186 Closes FALCOR-187 Closes FALCOR-188 Closes FALCOR-189 Closes FALCOR-147 Closes FALCOR-148 Test Plan: * As a student in an account with the Student Planner feature flag enabled * In a course with multiple upcoming due assignments in the current and following weeks * Test that the following API endpoints provide you with the data described: get '/api/v1/planner/items' * Should return a list matching that of the todo list endpoint, while adding an additional key named `visible_in_planner` get '/api/v1/planner/overrides' * Should return a list of previously created PlannerOverrides get '/api/v1/planner/overrides/:override_id' * Should return the specific override for the passed in id put '/api/v1/planner/overrides/:override_id' * Should update an existing override's `visible` value to match what was passed in the request. No other values should be updated post '/api/v1/planner/overrides' * Should create a new PlannerOverride with the specified `plannable_type`, `plannable_id`, and `visible` values. `user_id` should match that of the user making the request delete '/api/v1/planner/overrides/:override_id' * Should set the PlannerOverride's `deleted_at` to when the request was made, as well as updating the `workflow_state` to `deleted` Change-Id: I03890a525f8201a8df1d2f1290cdcd549ba548d7 Reviewed-on: https://gerrit.instructure.com/107495 Tested-by: Jenkins Reviewed-by: Steven Burnett <sburnett@instructure.com> QA-Review: Deepeeca Soundarrajan <dsoundarrajan@instructure.com> Product-Review: Dan Minkevitch <dan@instructure.com>
2017-05-11 12:40:45 +08:00
post 'planner/overrides', action: :create
delete 'planner/overrides/:id', action: :destroy
Planner API Closes FALCOR-183 Closes FALCOR-184 Closes FALCOR-255 Closes FALCOR-186 Closes FALCOR-187 Closes FALCOR-188 Closes FALCOR-189 Closes FALCOR-147 Closes FALCOR-148 Test Plan: * As a student in an account with the Student Planner feature flag enabled * In a course with multiple upcoming due assignments in the current and following weeks * Test that the following API endpoints provide you with the data described: get '/api/v1/planner/items' * Should return a list matching that of the todo list endpoint, while adding an additional key named `visible_in_planner` get '/api/v1/planner/overrides' * Should return a list of previously created PlannerOverrides get '/api/v1/planner/overrides/:override_id' * Should return the specific override for the passed in id put '/api/v1/planner/overrides/:override_id' * Should update an existing override's `visible` value to match what was passed in the request. No other values should be updated post '/api/v1/planner/overrides' * Should create a new PlannerOverride with the specified `plannable_type`, `plannable_id`, and `visible` values. `user_id` should match that of the user making the request delete '/api/v1/planner/overrides/:override_id' * Should set the PlannerOverride's `deleted_at` to when the request was made, as well as updating the `workflow_state` to `deleted` Change-Id: I03890a525f8201a8df1d2f1290cdcd549ba548d7 Reviewed-on: https://gerrit.instructure.com/107495 Tested-by: Jenkins Reviewed-by: Steven Burnett <sburnett@instructure.com> QA-Review: Deepeeca Soundarrajan <dsoundarrajan@instructure.com> Product-Review: Dan Minkevitch <dan@instructure.com>
2017-05-11 12:40:45 +08:00
end
scope(controller: :planner_notes) do
get 'planner_notes', action: :index, as: :planner_notes
BookmarkedCollection for Planner API Closes FALCOR-325 Fixes FALCOR-361 Test Plan Date Range Testing: * With "Student Planner" enabled * As a student * Make a GET request to /api/v1/planner/items with ?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD&filter=new_activity * The response should only contain results with new activity between those time ranges (test with dates and dates with times) Pagination Testing: * With "Student Planner" enabled * As a student * Make a GET request to /api/v1/planner/items with some combination of start_date, end_date, and filter * Include a a `per_page` param * The response should only contain only `per_page` number of results * The response should contain a `Link` header with links to the current, next, and previous pages (you should see a URL with a `page=bookmark:[bunch of characters]`) * Copy the `page` param from the `Link` header for the next page of results * Make a request with the newly copied `page=bookmark:[stuff]` parameter added to the request * You should get the next page of results in the response * The previous and next URLs in the `Link` response header should return the previous and next page of results Regression Testing: * Full regression test of "New Student Planner" Change-Id: Ie6352aec71f5de3c60981aaeee65119cc43ed6f7 Reviewed-on: https://gerrit.instructure.com/114848 Reviewed-by: Steven Burnett <sburnett@instructure.com> Tested-by: Jenkins QA-Review: Deepeeca Soundarrajan <dsoundarrajan@instructure.com> Product-Review: Dan Minkevitch <dan@instructure.com>
2017-06-09 10:52:02 +08:00
get 'planner_notes/:id', action: :show, as: :planner_notes_show
put 'planner_notes/:id', action: :update
post 'planner_notes', action: :create
delete 'planner_notes/:id', action: :destroy
end
scope(:controller => :csp_settings) do
%w(course account).each do |context|
get "#{context.pluralize}/:#{context}_id/csp_settings", :action => :get_csp_settings
put "#{context.pluralize}/:#{context}_id/csp_settings", :action => :set_csp_setting
end
put "accounts/:account_id/csp_settings/lock", :action => :set_csp_lock
post "accounts/:account_id/csp_settings/domains", :action => :add_domain
post "accounts/:account_id/csp_settings/domains/batch_create", :action => :add_multiple_domains
delete "accounts/:account_id/csp_settings/domains", :action => :remove_domain
get "accounts/:account_id/csp_log", action: :csp_log
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
LTI2 API webhook subscription service Fixes: PLAT-2129 PLAT-2126 Test Plan: - Verify you can create and retrieve a TCP with the new subscription service and capabilities. - Install an LTI2 tool using the split secret capability. The tool's security contract should use the new webhook service. Example security contract: "tp_half_shared_secret"=> "873f5...", "tool_service"=> [{"@type"=>"RestServiceProfile", "service"=>"vnd.Canvas.webhooksSubscription", "action"=>["GET", "POST"]}]} - Do a POST request to /api/lti/subscriptions with the following body: { "subscription":{ "EventTypes":[ "submission_created" ], "ContextType":"course", "ContextId":<valid course id here>, "Format":"live-event", "TransportType":"sqs", "TransportMetadata":{ "Url":"http://sqs.docker" } } } - Verify a 401 is returned - Using https://docs.google.com/document/d /12x6Peif-I-0zvl2uMv2JVbQdZumGGqMtspWKYTqlL9o/edit attempt to create each subscription type (in bold) and verify 401s are returned in each case. - Using the same document, verify that adding one of the capabilities listed under a subscription types allows you to create the subscription - Verify that using the vnd.instructure.webhooks.root_account.all capability allows you to create any subscription. - Install an LTI2 tool in a course - Attempt to create a subscription in another course and verify a 401 is given. Change-Id: I322e4bb2c49209afdc6f0a3c3a8b5c73e339996e Reviewed-on: https://gerrit.instructure.com/102272 Tested-by: Jenkins QA-Review: August Thornton <august@instructure.com> Reviewed-by: Andrew Butterfield <abutterfield@instructure.com> Product-Review: Weston Dransfield <wdransfield@instructure.com>
2017-02-14 23:55:06 +08:00
scope(controller: 'lti/tool_configurations_api') do
put 'developer_keys/:developer_key_id/tool_configuration', action: :update
post 'accounts/:account_id/developer_keys/tool_configuration', action: :create
delete 'developer_keys/:developer_key_id/tool_configuration', action: :destroy
%w(account course).each do |context|
get "#{context}s/:#{context}_id/developer_keys/:developer_key_id/tool_configuration", action: :show
end
end
LTI2 API webhook subscription service Fixes: PLAT-2129 PLAT-2126 Test Plan: - Verify you can create and retrieve a TCP with the new subscription service and capabilities. - Install an LTI2 tool using the split secret capability. The tool's security contract should use the new webhook service. Example security contract: "tp_half_shared_secret"=> "873f5...", "tool_service"=> [{"@type"=>"RestServiceProfile", "service"=>"vnd.Canvas.webhooksSubscription", "action"=>["GET", "POST"]}]} - Do a POST request to /api/lti/subscriptions with the following body: { "subscription":{ "EventTypes":[ "submission_created" ], "ContextType":"course", "ContextId":<valid course id here>, "Format":"live-event", "TransportType":"sqs", "TransportMetadata":{ "Url":"http://sqs.docker" } } } - Verify a 401 is returned - Using https://docs.google.com/document/d /12x6Peif-I-0zvl2uMv2JVbQdZumGGqMtspWKYTqlL9o/edit attempt to create each subscription type (in bold) and verify 401s are returned in each case. - Using the same document, verify that adding one of the capabilities listed under a subscription types allows you to create the subscription - Verify that using the vnd.instructure.webhooks.root_account.all capability allows you to create any subscription. - Install an LTI2 tool in a course - Attempt to create a subscription in another course and verify a 401 is given. Change-Id: I322e4bb2c49209afdc6f0a3c3a8b5c73e339996e Reviewed-on: https://gerrit.instructure.com/102272 Tested-by: Jenkins QA-Review: August Thornton <august@instructure.com> Reviewed-by: Andrew Butterfield <abutterfield@instructure.com> Product-Review: Weston Dransfield <wdransfield@instructure.com>
2017-02-14 23:55:06 +08:00
scope(controller: 'lti/subscriptions_api') do
post "subscriptions", action: :create
delete "subscriptions/:id", action: :destroy
get "subscriptions/:id", action: :show
put "subscriptions/:id", action: :update
get "subscriptions", action: :index
LTI2 API webhook subscription service Fixes: PLAT-2129 PLAT-2126 Test Plan: - Verify you can create and retrieve a TCP with the new subscription service and capabilities. - Install an LTI2 tool using the split secret capability. The tool's security contract should use the new webhook service. Example security contract: "tp_half_shared_secret"=> "873f5...", "tool_service"=> [{"@type"=>"RestServiceProfile", "service"=>"vnd.Canvas.webhooksSubscription", "action"=>["GET", "POST"]}]} - Do a POST request to /api/lti/subscriptions with the following body: { "subscription":{ "EventTypes":[ "submission_created" ], "ContextType":"course", "ContextId":<valid course id here>, "Format":"live-event", "TransportType":"sqs", "TransportMetadata":{ "Url":"http://sqs.docker" } } } - Verify a 401 is returned - Using https://docs.google.com/document/d /12x6Peif-I-0zvl2uMv2JVbQdZumGGqMtspWKYTqlL9o/edit attempt to create each subscription type (in bold) and verify 401s are returned in each case. - Using the same document, verify that adding one of the capabilities listed under a subscription types allows you to create the subscription - Verify that using the vnd.instructure.webhooks.root_account.all capability allows you to create any subscription. - Install an LTI2 tool in a course - Attempt to create a subscription in another course and verify a 401 is given. Change-Id: I322e4bb2c49209afdc6f0a3c3a8b5c73e339996e Reviewed-on: https://gerrit.instructure.com/102272 Tested-by: Jenkins QA-Review: August Thornton <august@instructure.com> Reviewed-by: Andrew Butterfield <abutterfield@instructure.com> Product-Review: Weston Dransfield <wdransfield@instructure.com>
2017-02-14 23:55:06 +08:00
end
scope(controller: 'lti/users_api') do
get 'users/:id', action: :show
get 'groups/:group_id/users', action: :group_index, as: 'lti_user_group_index'
end
scope(controller: 'lti/assignments_api') do
get 'assignments/:assignment_id', action: :show
end
scope(controller: 'lti/ims/authentication') do
post 'authorize_redirect', action: :authorize_redirect
get 'authorize_redirect', action: :authorize_redirect
get 'authorize', action: :authorize, as: :lti_1_3_authorization
end
2015-06-26 03:35:25 +08:00
%w(course account).each do |context|
prefix = "#{context}s/:#{context}_id"
post "#{prefix}/authorize", controller: 'lti/ims/authorization', action: :authorize, as: "#{context}_lti_oauth2_authorize"
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
get "tool_proxy/:tool_proxy_guid/#{prefix}/tool_setting", controller: 'lti/ims/tool_setting', action: :show, as: "show_#{context}_tool_setting"
get "tool_proxy/:tool_proxy_guid/#{prefix}/resource_link_id/:resource_link_id/tool_setting", controller: 'lti/ims/tool_setting', action: :show, as: "show_#{context}_resource_link_id_tool_setting"
put "tool_proxy/:tool_proxy_guid/#{prefix}/tool_setting", controller: 'lti/ims/tool_setting', action: :update, as: "update_#{context}_tool_setting"
put "tool_proxy/:tool_proxy_guid/#{prefix}/resource_link_id/:resource_link_id/tool_setting", controller: 'lti/ims/tool_setting', action: :update, as: "update_#{context}_update_resource_link_id_tool_setting"
end
#Tool Setting Services
get "tool_settings/:tool_setting_id", controller: 'lti/ims/tool_setting', action: :show, as: :show_lti_tool_settings
get "tool_proxy/:tool_proxy_guid/tool_setting", controller: 'lti/ims/tool_setting', action: :show, as: :show_tool_proxy_lti_tool_settings
put "tool_settings/:tool_setting_id", controller: 'lti/ims/tool_setting', action: :update, as: :update_lti_tool_settings
put "tool_proxy/:tool_proxy_guid/tool_setting", controller: 'lti/ims/tool_setting', action: :update, as: :update_tool_proxy_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
# Submissions Service
scope(controller: 'lti/submissions_api') do
get "assignments/:assignment_id/submissions/:submission_id", action: :show
get "assignments/:assignment_id/submissions/:submission_id/history", action: :history
get "assignments/:assignment_id/submissions/:submission_id/attachment/:attachment_id", action: :attachment, as: :lti_submission_attachment_download
end
# Originality Report Service
scope(controller: 'lti/originality_reports_api') do
post "assignments/:assignment_id/submissions/:submission_id/originality_report", action: :create
put "assignments/:assignment_id/submissions/:submission_id/originality_report/:id", action: :update
put "assignments/:assignment_id/files/:file_id/originality_report", action: :update
get "assignments/:assignment_id/submissions/:submission_id/originality_report/:id", action: :show
get "assignments/:assignment_id/files/:file_id/originality_report", action: :show
end
Line Item Controller (sans index) Closes PLAT-3004 Test Plan: CREATE - Attempt to create a new Line Item using the create endpont. Verify the following params are required: - scoreMaximum - label - Verify a new line item is returned and properly serialized. example: { "id" : <line item show/update endpoint> "scoreMaximum" : 60, "label" : "Chapter 5 Test", "resourceId" : "quiz-231", "tag" : "grade" } - Verify the create endpoint allows setting the following optional params: - resourceId - tag - ltiLinkId (Must be the `resource_link_id` of an Lti::ResourceLink. This resource link must already have one line item associated with it.) - Verify a Line Item cannot be created for an Lti::ResourceLink that does not already have at least one Line Item associated with it already. - Verify a Line Item may be created for an Lti::ResourceLink if it already has at least one Line Item associated with it. - Verify that creating a Line Item _without_ specifying an `ltiLinkId` creates a line item and a new assignment specified with the line item. The new assignment should have the following: - context: context of the new line item - name: label of the new line item - point_possible: the score maximum of the new line item - submission_types: none UPDATE - Verify the following attributes may be updated: - scoreMaximum - label - resourceId - tag - Verify that the ltiLinkId may not be updated - Verify that updating the Line Item label also updates the assignment title in the following cases: - when the line item has no associate Lti::ResourceLink - when the Lti::ResourceLink associated with the Line Item only has one line item (the one being updated) - Verify the update response is properly serialized (see example in CREATE). SHOW - Verify the show endpoint allows retrieving the Line Item. - Verify the endpoint responds with 404 if the Line Item does not exist. - Verify the endpoint responds with a 404 if the Line Item exists but is in a different course than the one specified as a parameter. DESTROY - Verify the endpoint responds with 404s in the same instances as the show endpoint. - Verify the endpoint does not allow destroying a Line Item when it is the first line item created chronologically for its associate Lti::ResourceLink - Verify the endpoint allows destroying line items. Change-Id: Iaf26e6addd1e3fe38c5fb76db33fed41a069e7c9 Reviewed-on: https://gerrit.instructure.com/138831 Tested-by: Jenkins Reviewed-by: Marc Alan Phillips <mphillips@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Weston Dransfield <wdransfield@instructure.com>
2018-01-24 01:03:35 +08:00
# Line Item Service
scope(controller: 'lti/ims/line_items') do
post "courses/:course_id/line_items", action: :create, as: :lti_line_item_create
get "courses/:course_id/line_items/:id", action: :show, as: :lti_line_item_show
get "courses/:course_id/line_items", action: :index, as: :lti_line_item_index
Line Item Controller (sans index) Closes PLAT-3004 Test Plan: CREATE - Attempt to create a new Line Item using the create endpont. Verify the following params are required: - scoreMaximum - label - Verify a new line item is returned and properly serialized. example: { "id" : <line item show/update endpoint> "scoreMaximum" : 60, "label" : "Chapter 5 Test", "resourceId" : "quiz-231", "tag" : "grade" } - Verify the create endpoint allows setting the following optional params: - resourceId - tag - ltiLinkId (Must be the `resource_link_id` of an Lti::ResourceLink. This resource link must already have one line item associated with it.) - Verify a Line Item cannot be created for an Lti::ResourceLink that does not already have at least one Line Item associated with it already. - Verify a Line Item may be created for an Lti::ResourceLink if it already has at least one Line Item associated with it. - Verify that creating a Line Item _without_ specifying an `ltiLinkId` creates a line item and a new assignment specified with the line item. The new assignment should have the following: - context: context of the new line item - name: label of the new line item - point_possible: the score maximum of the new line item - submission_types: none UPDATE - Verify the following attributes may be updated: - scoreMaximum - label - resourceId - tag - Verify that the ltiLinkId may not be updated - Verify that updating the Line Item label also updates the assignment title in the following cases: - when the line item has no associate Lti::ResourceLink - when the Lti::ResourceLink associated with the Line Item only has one line item (the one being updated) - Verify the update response is properly serialized (see example in CREATE). SHOW - Verify the show endpoint allows retrieving the Line Item. - Verify the endpoint responds with 404 if the Line Item does not exist. - Verify the endpoint responds with a 404 if the Line Item exists but is in a different course than the one specified as a parameter. DESTROY - Verify the endpoint responds with 404s in the same instances as the show endpoint. - Verify the endpoint does not allow destroying a Line Item when it is the first line item created chronologically for its associate Lti::ResourceLink - Verify the endpoint allows destroying line items. Change-Id: Iaf26e6addd1e3fe38c5fb76db33fed41a069e7c9 Reviewed-on: https://gerrit.instructure.com/138831 Tested-by: Jenkins Reviewed-by: Marc Alan Phillips <mphillips@instructure.com> QA-Review: August Thornton <august@instructure.com> Product-Review: Weston Dransfield <wdransfield@instructure.com>
2018-01-24 01:03:35 +08:00
put "courses/:course_id/line_items/:id", action: :update, as: :lti_line_item_edit
delete "courses/:course_id/line_items/:id", action: :destroy, as: :lti_line_item_delete
end
# Scores Service
scope(controller: 'lti/ims/scores') do
post "courses/:course_id/line_items/:line_item_id/scores", action: :create, as: :lti_result_create
end
# Result Service
scope(controller: 'lti/ims/results') do
get "courses/:course_id/line_items/:line_item_id/results/:id", action: :show, as: :lti_result_show
get "courses/:course_id/line_items/:line_item_id/results", action: :index
end
Add LTI NRPS v2 Course and Group membership list API - No-frills support for LTI Advantage Names and Roles Provisioning Service version 2. I.e. no query param support, no pagination. - Similar to other LTI Adv services, this API is disabled in prod env due to incompleteness, esp lack of authN/authZ. - URL scheme: `/api/lti/[courses|groups]/:context_id/names_and_roles` Closes LTIA-11 Test Plan * Create course with several participating (i.e. invite-accepted) and pending enrollments. Add several of those enrolled users to one or more groups in that course. * Ensure participating enrollments are spread across all base roles and several custom roles. * GET `/api/lti/[courses|groups]/:context_id/names_and_roles` for the course and group, respectively. * Verify all participating users returned with correct attribute mappings, all non-participating users not returned. * See LTIA-11 for additional attribute mapping details, esp role mappings. * Create another course with no enrollments and an empty group. * Verify GET `/api/lti/[courses|groups]/:context_id/names_and_roles` returns 200 with an empty `members` array for the course and group, respectively. * Verify GET `/api/lti/[courses|groups]/:context_id/names_and_roles` for non-existent contexts returns 404. Change-Id: Ib8d174a3d583435423ce41f2488c80ae6d66cb72 Reviewed-on: https://gerrit.instructure.com/165275 Reviewed-by: Marc Alan Phillips <mphillips@instructure.com> Product-Review: Karl Lloyd <karl@instructure.com> Tested-by: Jenkins QA-Review: Pedro Fajardo <pfajardo@instructure.com>
2018-09-18 08:08:52 +08:00
# Names and Roles Provisioning (NRPS) v2 Service
scope(controller: 'lti/ims/names_and_roles') do
get "courses/:course_id/names_and_roles", controller: "lti/ims/names_and_roles", action: :course_index, as: :course_names_and_roles
get "groups/:group_id/names_and_roles", controller: "lti/ims/names_and_roles", action: :group_index, as: :group_names_and_roles
end
# Security
scope(controller: 'lti/ims/security') do
get "security/jwks", action: :jwks, as: :jwks_show
end
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
scope(controller: :disable_post_to_sis_api) do
put 'courses/:course_id/disable_post_to_sis', action: 'disable_post_to_sis', as: :disable_post_to_sis_course_assignments
end
end
2011-02-01 09:57:29 +08:00
end