diff --git a/Gemfile.lock b/Gemfile.lock index bec62cc75..990d14bfb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -784,8 +784,8 @@ GEM PLATFORMS arm64-darwin-20 - arm64-darwin-22 arm64-darwin-21 + arm64-darwin-22 ruby x86_64-darwin-18 x86_64-darwin-20 diff --git a/app/controllers/devise_overrides/sessions_controller.rb b/app/controllers/devise_overrides/sessions_controller.rb index ace47a8b5..2659aeebf 100644 --- a/app/controllers/devise_overrides/sessions_controller.rb +++ b/app/controllers/devise_overrides/sessions_controller.rb @@ -37,3 +37,5 @@ class DeviseOverrides::SessionsController < DeviseTokenAuth::SessionsController @resource = user if user&.valid_sso_auth_token?(params[:sso_auth_token]) end end + +DeviseOverrides::SessionsController.prepend_mod_with('DeviseOverrides::SessionsController') diff --git a/app/models/automation_rule.rb b/app/models/automation_rule.rb index 0159ff846..7a9550bd3 100644 --- a/app/models/automation_rule.rb +++ b/app/models/automation_rule.rb @@ -77,4 +77,4 @@ class AutomationRule < ApplicationRecord end end -AutomationRule.include_mod_with('Audit::Inbox') +AutomationRule.include_mod_with('Audit::AutomationRule') diff --git a/app/models/user.rb b/app/models/user.rb index c50ab208e..6ff4fb61d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -166,3 +166,5 @@ class User < ApplicationRecord macros.personal.destroy_all end end + +User.include_mod_with('Audit::User') diff --git a/app/models/webhook.rb b/app/models/webhook.rb index f43c80548..4f0e32a43 100644 --- a/app/models/webhook.rb +++ b/app/models/webhook.rb @@ -38,4 +38,4 @@ class Webhook < ApplicationRecord end end -Webhook.include_mod_with('Audit::Inbox') +Webhook.include_mod_with('Audit::Webhook') diff --git a/enterprise/app/controllers/enterprise/devise_overrides/sessions_controller.rb b/enterprise/app/controllers/enterprise/devise_overrides/sessions_controller.rb new file mode 100644 index 000000000..e11e3fff9 --- /dev/null +++ b/enterprise/app/controllers/enterprise/devise_overrides/sessions_controller.rb @@ -0,0 +1,25 @@ +module Enterprise::DeviseOverrides::SessionsController + def render_create_success + create_audit_event('sign_in') + super + end + + def destroy + create_audit_event('sign_out') + super + end + + def create_audit_event(action) + return unless @resource + + associated_type = 'Account' + @resource.accounts.each do |account| + @resource.audits.create( + action: action, + user_id: @resource.id, + associated_id: account.id, + associated_type: associated_type + ) + end + end +end diff --git a/enterprise/app/models/enterprise/audit/user.rb b/enterprise/app/models/enterprise/audit/user.rb new file mode 100644 index 000000000..5d0276607 --- /dev/null +++ b/enterprise/app/models/enterprise/audit/user.rb @@ -0,0 +1,13 @@ +module Enterprise::Audit::User + extend ActiveSupport::Concern + + included do + audited only: [ + :availability, + :display_name, + :email, + :name + ] + audited associated_with: :account + end +end diff --git a/spec/enterprise/controllers/enterprise/devise_overrides/session_controller_spec.rb b/spec/enterprise/controllers/enterprise/devise_overrides/session_controller_spec.rb new file mode 100644 index 000000000..89f8794ee --- /dev/null +++ b/spec/enterprise/controllers/enterprise/devise_overrides/session_controller_spec.rb @@ -0,0 +1,53 @@ +require 'rails_helper' + +RSpec.describe 'Enterprise Audit API', type: :request do + let!(:account) { create(:account) } + let!(:user) { create(:user, password: 'Password1!', account: account) } + + describe 'POST /sign_in' do + it 'creates a sign_in audit event wwith valid credentials' do + params = { email: user.email, password: 'Password1!' } + + expect do + post new_user_session_url, + params: params, + as: :json + end.to change(Enterprise::AuditLog, :count).by(1) + + expect(response).to have_http_status(:success) + expect(response.body).to include(user.email) + + # Check if the sign_in event is created + user.reload + expect(user.audits.last.action).to eq('sign_in') + expect(user.audits.last.associated_id).to eq(account.id) + expect(user.audits.last.associated_type).to eq('Account') + end + + it 'will not create a sign_in audit event with invalid credentials' do + params = { email: user.email, password: 'invalid' } + expect do + post new_user_session_url, + params: params, + as: :json + end.not_to change(Enterprise::AuditLog, :count) + end + end + + describe 'DELETE /sign_out' do + context 'when it is an authenticated user' do + it 'signs out the user and creates an audit event' do + expect do + delete '/auth/sign_out', headers: user.create_new_auth_token + end.to change(Enterprise::AuditLog, :count).by(1) + expect(response).to have_http_status(:success) + + user.reload + + expect(user.audits.last.action).to eq('sign_out') + expect(user.audits.last.associated_id).to eq(account.id) + expect(user.audits.last.associated_type).to eq('Account') + end + end + end +end