diff --git a/app/controllers/quizzes/quiz_submission_events_api_controller.rb b/app/controllers/quizzes/quiz_submission_events_api_controller.rb index 19deee55a34..cbf3af66ada 100644 --- a/app/controllers/quizzes/quiz_submission_events_api_controller.rb +++ b/app/controllers/quizzes/quiz_submission_events_api_controller.rb @@ -43,8 +43,8 @@ class Quizzes::QuizSubmissionEventsApiController < ApplicationController include ::Filters::Quizzes include ::Filters::QuizSubmissions - before_action :require_user, - :require_context, + before_action :require_user, only: [:index] + before_action :require_context, :require_quiz, :require_active_quiz_submission diff --git a/app/models/quizzes/quiz_submission.rb b/app/models/quizzes/quiz_submission.rb index e3dabac0434..c1faa37b8fd 100644 --- a/app/models/quizzes/quiz_submission.rb +++ b/app/models/quizzes/quiz_submission.rb @@ -102,10 +102,19 @@ class Quizzes::QuizSubmission < ActiveRecord::Base state :preview end + def unenrolled_user_can_read?(user, session) + course = quiz.course + !quiz.graded? && course.available? && course.unenrolled_user_can_read?(user, session) + end + set_policy do given { |user| user && user.id == self.user_id } can :read + # allow anonymous users take ungraded quizzes from a public course + given { |user, session| unenrolled_user_can_read?(user, session) } + can :record_events + given { |user| user && user.id == self.user_id && end_date_is_valid? } can :record_events diff --git a/spec/apis/v1/quizzes/quiz_submission_events_api_spec.rb b/spec/apis/v1/quizzes/quiz_submission_events_api_spec.rb index 9d1a4d29483..bca471e0e35 100644 --- a/spec/apis/v1/quizzes/quiz_submission_events_api_spec.rb +++ b/spec/apis/v1/quizzes/quiz_submission_events_api_spec.rb @@ -117,6 +117,24 @@ describe Quizzes::QuizSubmissionEventsApiController, type: :request do @quiz_submission = @quiz.quiz_submissions.create!(user: @user, workflow_state: 'settings_only') expect(api_create({raw: true}, {'quiz_submission_events' => events_data})).to eq 404 end + + context 'for an ungraded quiz in a public course' do + before do + @course.is_public = true + @course.is_public_to_auth_users = true + @course.save! + @quiz.quiz_type = 'practice_quiz' + @quiz.save! + end + + it 'should respond with no_content success' do + student_in_course + @user = @teacher + @quiz_submission = @quiz.quiz_submissions.last + api_create({raw: true}, {}) + assert_status(204) + end + end end describe 'GET /courses/:course_id/quizzes/:quiz_id/submissions/:id/events [index]' do diff --git a/spec/models/quizzes/quiz_submission_spec.rb b/spec/models/quizzes/quiz_submission_spec.rb index 95957c8cfb5..a3c5c1e85dd 100644 --- a/spec/models/quizzes/quiz_submission_spec.rb +++ b/spec/models/quizzes/quiz_submission_spec.rb @@ -905,6 +905,23 @@ describe Quizzes::QuizSubmission do expect(qs.grants_right?(@teacher, :update_scores)).to eq true expect(qs.grants_right?(@teacher, :add_attempts)).to eq true end + + it "does not take events from an anonymous user" do + course_with_student(:active_all => true) + @quiz = @course.quizzes.create! + qs = @quiz.generate_submission(@user) + expect(qs.grants_right?(nil, :record_events)).to be_falsey + end + + it "can take events for any users for a ungraded quiz in a public course" do + course_with_student(:active_all => true) + @course.is_public = true + @course.is_public_to_auth_users = true + @course.save! + @quiz = @course.quizzes.create!(quiz_type: 'practice_quiz') + qs = @quiz.generate_submission(@user) + expect(qs.grants_right?(nil, { user_id: nil }, :record_events)).to be_truthy + end end describe "#question" do