Gemfile Changes

@@ -6,3 +6,4 @@ git_source(:github) do
6 +gem 'carrierwave'

Gemfile.lock Changes

@@ -112,6 +112,7 @@ GEM
112 + carrierwave (3.1.2)
@@ -288,6 +289,7 @@ DEPENDENCIES
289 + carrierwave

app/controllers/log_redaction_controller.rb Added

@@ -0,0 +1,30 @@
1 +class LogRedactionController < AdminController
2 +def redact
3 + selected_log = TransformationLog.find(params[:id])
4 + current_text = selected_log.log.to_s
5 +
6 +# Remove any emails from the log by splitting into chunks and redacting
7 +# any suspicious-looking chunks
8 + chunks = current_text.split(' ')
9 + redacted_chunks = []
10 + emailish = %r{
11 + [a-z0-9._%+-]+ # username
12 + @
13 + [a-z0-9.-]+.[a-z]{2,} # domain
14 + }ix
15 + chunks.each do
16 + redacted_chunks << chunk.gsub(emailish, '[REDACTED]')
17 +end
18 + updated_text = redacted_chunks.join(' ')
19 +
20 +# NOTE: Need to escape single quotes with "''" to avoid SQL syntax error
21 +RawLog.where(transformation_log_id: params[:id]).update_all("log = '#{updated_text.gsub("'", "''")}'")
22 +
23 + flash[:notice] = "Redacted log #{params[:id]}"
24 + redirect_to log_path(params[:id])
25 +rescue => e
26 +Rails.logger.error("Log redaction failed for #{params[:id]} because #{e.message}")
27 + flash[:notice] = "Redacted log #{params[:id]}"
28 + redirect_to logs_path
29 +end
30 +end

app/views/logs/show.html.haml Changed

@@ -35,6 +35,8 @@
35 + .m-b-xs
36 + = link_to 'Redact Log', redact_log_path(@log), class:'btn-fw btn btn-outline b-warning text-warning btn-sm'

config/routes.rb Changed

@@ -47,6 +47,8 @@ Rails.application.routes.draw do
47 + get 'logs/:id/redact', to: 'log_redaction#redact', as: :redact_log
48 +

spec/controllers/log_redaction_controller_spec.rb Added

@@ -0,0 +1,21 @@
1 +require 'rails_helper'
2 +
3 +RSpec.describe LogRedactionController do
4 + login_user
5 +
6 + let!(:transformation_log) do
7 +FactoryGirl.create(
8 +:log,
9 +log: 'Customer jane@example.com triggered token TOKENVALUE999 for export'
10 + )
11 +end
12 +
13 + it 'redacts log content', aggregate_failures: true do
14 + get :redact, params: { id: transformation_log.id }
15 + transformation_log.reload
16 +
17 + expect(response).to redirect_to(log_path(transformation_log))
18 + expect(transformation_log.log).to include('[REDACTED]')
19 + expect(transformation_log.log).not_to include('jane@example.com')
20 +end
21 +end
22 +