add endpoint for assignment audit events
This new endpoint returns all AnonymousOrModerationEvents related to the assignment and submission in question. closes GRADE-1576 Test Plan - Create an auditable (anonymous or moderated) assignment. - Make some changes to the assignment. - As a grader, grade that assignment via SpeedGrader. - Leave some comments. - Via Postman or similar, make a json GET request to the endpoint (courses/:course_id/assignments/:assignment_id/submissions/ :submission_id/audit_events) - Verify that all changes to the assignment, grades, and comments show up as events in the response under the key "audit_events". Change-Id: I3e122b0b6501d3be71cc5ab67ee791e1905facb2 Reviewed-on: https://gerrit.instructure.com/164590 Reviewed-by: Jeremy Neander <jneander@instructure.com> Reviewed-by: Keith T. Garner <kgarner@instructure.com> Tested-by: Jenkins QA-Review: Gary Mei <gmei@instructure.com> Product-Review: Keith T. Garner <kgarner@instructure.com>
This commit is contained in:
parent
9f2d62a16b
commit
cc015d9502
|
@ -287,6 +287,18 @@ class SubmissionsController < SubmissionsBaseController
|
|||
super
|
||||
end
|
||||
|
||||
def audit_events
|
||||
return render_unauthorized_action unless @context.grants_right?(@current_user, :view_audit_trail)
|
||||
audit_events = AnonymousOrModerationEvent.events_for_submission(
|
||||
assignment_id: params[:assignment_id],
|
||||
submission_id: params[:submission_id]
|
||||
)
|
||||
|
||||
respond_to do |format|
|
||||
format.json { render json: { audit_events: audit_events }, status: :ok }
|
||||
end
|
||||
end
|
||||
|
||||
def lookup_existing_attachments
|
||||
if params[:submission][:file_ids].is_a?(Array)
|
||||
attachment_ids = params[:submission][:file_ids]
|
||||
|
|
|
@ -100,6 +100,10 @@ class AnonymousOrModerationEvent < ApplicationRecord
|
|||
validate :payload_student_id_present
|
||||
end
|
||||
|
||||
def self.events_for_submission(assignment_id:, submission_id:)
|
||||
self.where(assignment_id: assignment_id, submission_id: [nil, submission_id]).order(:created_at)
|
||||
end
|
||||
|
||||
EVENT_TYPES.each do |event_type|
|
||||
scope event_type, -> { where(event_type: event_type) }
|
||||
end
|
||||
|
|
|
@ -283,6 +283,7 @@ CanvasRails::Application.routes.draw do
|
|||
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
|
||||
get :rubric
|
||||
resource :rubric_association, path: :rubric do
|
||||
|
|
|
@ -744,6 +744,76 @@ describe SubmissionsController do
|
|||
end
|
||||
end
|
||||
|
||||
describe "GET audit_events" do
|
||||
before(:once) do
|
||||
@course = Course.create!
|
||||
first_student = course_with_user("StudentEnrollment", course: @course, name: "First", active_all: true).user
|
||||
second_student = course_with_user("StudentEnrollment", course: @course, name: "Second", active_all: true).user
|
||||
@teacher = course_with_user("TeacherEnrollment", course: @course, name: "Teacher", active_all: true).user
|
||||
@assignment = @course.assignments.create!(name: "anonymous", anonymous_grading: true, updating_user: @teacher)
|
||||
@submission = @assignment.submissions.find_by!(user: first_student)
|
||||
@submission.submission_comments.create!(author: first_student, comment: "Student comment")
|
||||
@submission.submission_comments.create!(author: @teacher, comment: "Teacher comment")
|
||||
@unrelated_submission = @assignment.submissions.find_by!(user: second_student)
|
||||
@teacher.account.role_overrides.create!(permission: :view_audit_trail, role: teacher_role, enabled: true)
|
||||
end
|
||||
|
||||
before(:each) do
|
||||
user_session(@teacher)
|
||||
end
|
||||
|
||||
let(:params) do
|
||||
{
|
||||
assignment_id: @assignment.id,
|
||||
course_id: @course.id,
|
||||
submission_id: @submission.id
|
||||
}
|
||||
end
|
||||
|
||||
it "renders unauthorized if user does not have view_audit_trail permission" do
|
||||
@teacher.account.role_overrides.where(permission: :view_audit_trail).destroy_all
|
||||
get :audit_events, params: params, format: :json
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
|
||||
it "renders ok if user does have view_audit_trail permission" do
|
||||
get :audit_events, params: params, format: :json
|
||||
expect(response).to have_http_status(:ok)
|
||||
end
|
||||
|
||||
it "returns only related audit events" do
|
||||
@unrelated_submission.submission_comments.create!(author: @teacher, comment: "unrelated Teacher comment")
|
||||
@course.assignments.create!(name: "unrelated", anonymous_grading: true, updating_user: @teacher)
|
||||
get :audit_events, params: params, format: :json
|
||||
audit_events = json_parse(response.body).fetch("audit_events")
|
||||
expect(audit_events.count).to be 3
|
||||
end
|
||||
|
||||
it "returns the assignment audit events" do
|
||||
get :audit_events, params: params, format: :json
|
||||
assignment_audit_events = json_parse(response.body).fetch("audit_events").select do |event|
|
||||
event.fetch("anonymous_or_moderation_event").fetch("event_type").include?("assignment_")
|
||||
end
|
||||
expect(assignment_audit_events.count).to be 1
|
||||
end
|
||||
|
||||
it "returns the submission audit events" do
|
||||
get :audit_events, params: params, format: :json
|
||||
submission_audit_events = json_parse(response.body).fetch("audit_events").select do |event|
|
||||
event.fetch("anonymous_or_moderation_event").fetch("event_type").include?("submission_")
|
||||
end
|
||||
expect(submission_audit_events.count).to be 2
|
||||
end
|
||||
|
||||
it "returns the audit events in order of created at" do
|
||||
get :audit_events, params: params, format: :json
|
||||
audit_event_ids = json_parse(response.body).fetch("audit_events").map do |event|
|
||||
event.fetch("anonymous_or_moderation_event").fetch("id")
|
||||
end
|
||||
expect(audit_event_ids).to eql audit_event_ids.sort
|
||||
end
|
||||
end
|
||||
|
||||
describe "copy_attachments_to_submissions_folder" do
|
||||
before(:once) do
|
||||
course_with_student
|
||||
|
|
|
@ -100,4 +100,46 @@ describe AnonymousOrModerationEvent do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#events_for_submission" do
|
||||
let(:course) { Course.create! }
|
||||
let(:teacher) { course_with_user("TeacherEnrollment", name: "Teacher", course: course, active_all: true).user }
|
||||
let(:student) { course_with_user("StudentEnrollment", name: "Student", course: course, active_all: true).user }
|
||||
let(:assignment) { course.assignments.create!(name: "anonymous", anonymous_grading: true, updating_user: teacher) }
|
||||
let(:submission) { assignment.submit_homework(student, body: "please give good grade") }
|
||||
let(:events) do
|
||||
AnonymousOrModerationEvent.events_for_submission(assignment_id: assignment.id, submission_id: submission.id)
|
||||
end
|
||||
|
||||
before :each do
|
||||
submission.submission_comments.create!(author: teacher, comment: "no")
|
||||
end
|
||||
|
||||
it "includes AnonymousOrModerationEvents related to assignment and submission" do
|
||||
expect(events.count).to be 2
|
||||
end
|
||||
|
||||
it "includes AnonymousOrModerationEvents of event_type assignment_*" do
|
||||
assignment_events = events.select { |event| event.event_type.include?("assignment_") }
|
||||
expect(assignment_events.count).to be 1
|
||||
end
|
||||
|
||||
it "includes AnonymousOrModerationEvents of event_type submission_comment_*" do
|
||||
submission_comment_events = events.select { |event| event.event_type.include?("submission_comment_") }
|
||||
expect(submission_comment_events.count).to be 1
|
||||
end
|
||||
|
||||
it "does not include AnonymousOrModerationEvents not related to assignment" do
|
||||
expect {
|
||||
course.assignments.create!(name: "another assignment", anonymous_grading: true, updating_user: teacher)
|
||||
}.not_to change { events.count }
|
||||
end
|
||||
|
||||
it "does not include AnonymousOrModerationEvents not related to submission" do
|
||||
second_student = course_with_user("StudentEnrollment", name: "Student", course: course, active_all: true).user
|
||||
expect {
|
||||
assignment.submit_homework(second_student, body: "please give bad grade")
|
||||
}.not_to change { events.count }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue