diff --git a/app/controllers/admin/forms_controller.rb b/app/controllers/admin/forms_controller.rb index 7656b4725..c2977ee2d 100644 --- a/app/controllers/admin/forms_controller.rb +++ b/app/controllers/admin/forms_controller.rb @@ -6,6 +6,8 @@ module Admin class FormsController < AdminController respond_to :html, :js + before_action :set_paper_trail_whodunnit + skip_before_action :verify_authenticity_token, only: [:js] before_action :set_form_for_auth_check, only: [:example], prepend: true # Only bypass authentication for example preview when this is a template form diff --git a/app/controllers/admin/question_options_controller.rb b/app/controllers/admin/question_options_controller.rb index cacb8d8dc..f1fdd2f09 100644 --- a/app/controllers/admin/question_options_controller.rb +++ b/app/controllers/admin/question_options_controller.rb @@ -2,6 +2,7 @@ module Admin class QuestionOptionsController < AdminController + before_action :set_paper_trail_whodunnit before_action :set_question, only: %i[new create create_other show edit update destroy sort] before_action :set_question_option, only: %i[show edit update destroy] diff --git a/app/controllers/admin/questions_controller.rb b/app/controllers/admin/questions_controller.rb index d75dddcf5..359842b0a 100644 --- a/app/controllers/admin/questions_controller.rb +++ b/app/controllers/admin/questions_controller.rb @@ -2,6 +2,7 @@ module Admin class QuestionsController < AdminController + before_action :set_paper_trail_whodunnit before_action :set_form, only: %i[create show edit update sort destroy] before_action :set_question, only: %i[show edit update destroy] diff --git a/app/models/form.rb b/app/models/form.rb index c998f7bcb..1f29bf96d 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -4,6 +4,7 @@ class Form < ApplicationRecord include AASM + has_paper_trail belongs_to :organization belongs_to :service, optional: true diff --git a/app/models/question.rb b/app/models/question.rb index 12cb7780c..47c69f033 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class Question < ApplicationRecord + has_paper_trail + belongs_to :form, counter_cache: true belongs_to :form_section has_many :question_options, dependent: :destroy diff --git a/app/models/question_option.rb b/app/models/question_option.rb index f8aa35cd8..685637675 100644 --- a/app/models/question_option.rb +++ b/app/models/question_option.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class QuestionOption < ApplicationRecord + has_paper_trail + belongs_to :question before_validation :set_default_value_from_text diff --git a/spec/controllers/admin/forms_controller_spec.rb b/spec/controllers/admin/forms_controller_spec.rb index bf5f890c8..55895328a 100644 --- a/spec/controllers/admin/forms_controller_spec.rb +++ b/spec/controllers/admin/forms_controller_spec.rb @@ -182,6 +182,14 @@ put :update, params: { id: form.to_param, form: valid_attributes }, session: valid_session expect(response).to redirect_to delivery_admin_form_path(form) end + + it 'records a version attributed to the current user' do + form = Form.create! valid_attributes + put :update, params: { id: form.to_param, form: { name: 'Audited Form Name' } }, session: valid_session + form.reload + expect(form.versions.last.event).to eq('update') + expect(form.versions.last.whodunnit).to eq(admin.id.to_s) + end end context 'with invalid params' do diff --git a/spec/controllers/admin/question_options_controller_spec.rb b/spec/controllers/admin/question_options_controller_spec.rb index fda1bd52e..5c4ccee0c 100644 --- a/spec/controllers/admin/question_options_controller_spec.rb +++ b/spec/controllers/admin/question_options_controller_spec.rb @@ -131,6 +131,16 @@ put :update, params: { id: question_option.to_param, question_option: valid_attributes }, session: valid_session expect(response).to redirect_to(question_option) end + + it 'records a version attributed to the current user' do + form = FactoryBot.create(:form, :open_ended_form, organization:) + question = FactoryBot.create(:question, form:, form_section: form.form_sections.first, question_type: 'checkbox', answer_field: 'answer_02') + question_option = QuestionOption.create!(question:, text: 'Option 1', position: 1) + put :update, params: { form_id: form.short_uuid, question_id: question.id, id: question_option.to_param, question_option: { text: 'Updated option text' } }, session: valid_session, format: :js + question_option.reload + expect(question_option.versions.last.event).to eq('update') + expect(question_option.versions.last.whodunnit).to eq(admin.id.to_s) + end end context 'with invalid params' do diff --git a/spec/controllers/admin/questions_controller_spec.rb b/spec/controllers/admin/questions_controller_spec.rb index 705351961..607ad2952 100644 --- a/spec/controllers/admin/questions_controller_spec.rb +++ b/spec/controllers/admin/questions_controller_spec.rb @@ -115,6 +115,15 @@ put :update, params: { id: question.to_param, question: valid_attributes }, session: valid_session expect(response).to redirect_to(question) end + + it 'records a version attributed to the current user' do + form = FactoryBot.create(:form, :open_ended_form, organization:) + question = form.questions.first + put :update, params: { form_id: form.short_uuid, id: question.to_param, question: { text: 'Audited question text' } }, session: valid_session + question.reload + expect(question.versions.last.event).to eq('update') + expect(question.versions.last.whodunnit).to eq(admin.id.to_s) + end end context 'with invalid params' do diff --git a/spec/models/form_spec.rb b/spec/models/form_spec.rb index 15287c74c..31e79ff9f 100644 --- a/spec/models/form_spec.rb +++ b/spec/models/form_spec.rb @@ -378,4 +378,25 @@ end end end + + describe 'versioning' do + it 'records a version when a form is created' do + new_form = FactoryBot.create(:form, organization:) + expect(new_form.versions.count).to eq(1) + expect(new_form.versions.last.event).to eq('create') + end + + it 'records a version with a changeset when a form is updated' do + form.update!(name: 'Updated Form Name') + expect(form.versions.last.event).to eq('update') + expect(form.versions.last.changeset).to have_key('name') + expect(form.versions.last.changeset['name'].last).to eq('Updated Form Name') + end + + it 'records a version when a form is destroyed' do + new_form = FactoryBot.create(:form, organization:) + new_form.destroy! + expect(new_form.versions.last.event).to eq('destroy') + end + end end diff --git a/spec/models/question_option_spec.rb b/spec/models/question_option_spec.rb index f557a0ee5..4f30ba99e 100644 --- a/spec/models/question_option_spec.rb +++ b/spec/models/question_option_spec.rb @@ -54,4 +54,25 @@ expect(@question_option2.errors.messages).to eq({ question_option: ["only one 'other_option' can be true for a question"] }) end end + + describe 'versioning' do + let!(:question_option) { QuestionOption.create!(text: 'Option 1', question: option_question, position: 1) } + + it 'records a version when a question option is created' do + expect(question_option.versions.count).to eq(1) + expect(question_option.versions.last.event).to eq('create') + end + + it 'records a version with a changeset when a question option is updated' do + question_option.update!(text: 'Updated option text') + expect(question_option.versions.last.event).to eq('update') + expect(question_option.versions.last.changeset).to have_key('text') + expect(question_option.versions.last.changeset['text'].last).to eq('Updated option text') + end + + it 'records a version when a question option is destroyed' do + question_option.destroy! + expect(question_option.versions.last.event).to eq('destroy') + end + end end diff --git a/spec/models/question_spec.rb b/spec/models/question_spec.rb index f84e8f8cc..2344f3991 100644 --- a/spec/models/question_spec.rb +++ b/spec/models/question_spec.rb @@ -126,4 +126,24 @@ end end end + + describe 'versioning' do + it 'records a version when a question is created' do + created_question = FactoryBot.create(:question, form:, form_section: form.form_sections.first, answer_field: 'answer_02') + expect(created_question.versions.count).to eq(1) + expect(created_question.versions.last.event).to eq('create') + end + + it 'records a version with a changeset when a question is updated' do + question.update!(text: 'Updated question text') + expect(question.versions.last.event).to eq('update') + expect(question.versions.last.changeset).to have_key('text') + expect(question.versions.last.changeset['text'].last).to eq('Updated question text') + end + + it 'records a version when a question is destroyed' do + question.destroy! + expect(question.versions.last.event).to eq('destroy') + end + end end