Skip to content

Commit

Permalink
work on feedbacks and records
Browse files Browse the repository at this point in the history
  • Loading branch information
Dainii committed Feb 15, 2024
1 parent 0bad1b5 commit a5ed3d3
Show file tree
Hide file tree
Showing 26 changed files with 660 additions and 120 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/rubyonrails.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ jobs:
# Add or replace database setup steps here
- name: Set up database schema
run: bin/rails db:schema:load
- name: Load seed on DB
run: bin/rails db:seed
# Add or replace test runners here
- name: Run tests
run: bin/bundle exec rspec spec/
Expand Down
3 changes: 3 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ Metrics/ClassLength:
Metrics/BlockLength:
Max: 40

Metrics/AbcSize:
Enabled: false

Metrics/MethodLength:
Exclude:
- 'db/migrate/*.rb'
Expand Down
1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ group :development, :test do
gem 'shoulda-matchers'

gem 'simplecov', require: false
gem 'simplecov-cobertura', require: false
end

group :development do
Expand Down
4 changes: 0 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,6 @@ GEM
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-cobertura (2.1.0)
rexml
simplecov (~> 0.19)
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.4)
solid_queue (0.2.1)
Expand Down Expand Up @@ -346,7 +343,6 @@ DEPENDENCIES
rubocop-rspec
shoulda-matchers
simplecov
simplecov-cobertura
solid_queue
stimulus-rails
tailwindcss-rails
Expand Down
20 changes: 3 additions & 17 deletions app/jobs/process_report_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,13 @@ class ProcessReportJob < ApplicationJob
queue_as :default

def perform(feedback)
# Parse the XML report and save it as json
feedback.raw_content = JSON.parse(Crack::XML.parse(feedback.report.download).to_json)
feedback.save

return unless feedback.persisted?

feedback.report_id = feedback.raw_content['feedback']['report_metadata']['report_id'].to_f
feedback.parse_xml_report

feedback.begin_date = Time.at(feedback.raw_content['feedback']['report_metadata']['date_range']['begin'].to_i).utc
feedback.end_date = Time.at(feedback.raw_content['feedback']['report_metadata']['date_range']['end'].to_i).utc
return if feedback.raw_content.empty?

feedback.organization = Organization.find_or_create_by(
name: feedback.raw_content['feedback']['report_metadata']['org_name']
)

feedback.domain = Domain.find_or_create_by(
name: feedback.raw_content['feedback']['policy_published']['domain']
)
feedback.extract_data

feedback.processed = true

feedback.save
end
end
68 changes: 68 additions & 0 deletions app/models/feedback.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,74 @@
class Feedback < ApplicationRecord
belongs_to :domain, optional: true
belongs_to :organization, optional: true
has_many :records, dependent: :destroy

has_one_attached :report

def parse_xml_report
# Parse the XML report and save it as json
self.raw_content = JSON.parse(Crack::XML.parse(report.download).to_json)

save
end

def extract_data
extract_report_id
extract_dates
extract_organization
extract_domain
extract_policy_published
extract_records

save
end

def fully_valid?
records.all?(&:fully_valid?)
end

def partially_valid?
records.any?(&:fully_valid?)
end

private

def extract_report_id
self.report_id = raw_content['feedback']['report_metadata']['report_id']
end

def extract_dates
self.begin_date = Time.at(raw_content['feedback']['report_metadata']['date_range']['begin'].to_i).utc
self.end_date = Time.at(raw_content['feedback']['report_metadata']['date_range']['end'].to_i).utc
end

def extract_organization
self.organization = Organization.find_or_create_by(
name: raw_content['feedback']['report_metadata']['org_name']
)
end

def extract_domain
self.domain = Domain.find_or_create_by(
name: raw_content['feedback']['policy_published']['domain']
)
end

def extract_policy_published
self.policy_published = raw_content['feedback']['policy_published'].except('domain')
end

def extract_records
return if raw_content.dig('feedback', 'record').empty?

if raw_content['feedback']['record'].instance_of?(Hash)
record = records.new
record.update_from_hash(raw_content['feedback']['record'])
elsif raw_content['feedback']['record'].instance_of?(Array)
raw_content['feedback']['record'].each do |raw_record|
record = records.new
record.update_from_hash(raw_record)
end
end
end
end
31 changes: 31 additions & 0 deletions app/models/record.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

class Record < ApplicationRecord
belongs_to :feedback

def update_from_hash(raw_record)
self.source_ip = raw_record.dig('row', 'source_ip')
self.count = raw_record.dig('row', 'count').to_i
self.policy_evaluated = raw_record.dig('row', 'policy_evaluated')
self.identifiers = raw_record['identifiers']
self.auth_results = raw_record['auth_results']

save
end

def dkim_valid?
auth_results.dig('dkim', 'result') == 'pass'
end

def spf_valid?
auth_results.dig('spf', 'result') == 'pass'
end

def fully_valid?
dkim_valid? && spf_valid?
end

def partially_valid?
dkim_valid? || spf_valid?
end
end
2 changes: 1 addition & 1 deletion app/views/domains/_feedback.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</td>
<td class="py-5 text-right">
<div class="flex justify-end">
<a href="#" class="text-sm font-medium leading-6 text-indigo-600 hover:text-indigo-500">View<span class="hidden sm:inline"> transaction</span><span class="sr-only">, invoice #00012, Reform</span></a>
<a href="#" class="text-sm font-medium leading-6 text-indigo-600 hover:text-indigo-500">View<span class="hidden sm:inline"> feedback</span><span class="sr-only">, invoice #00012, Reform</span></a>
</div>
<div class="mt-1 text-xs leading-5 text-gray-500">Report-ID <span class="text-gray-900"><%= feedback.report_id %></span></div>
</td>
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20240210225602_add_policy_published_to_feedback.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddPolicyPublishedToFeedback < ActiveRecord::Migration[7.1]
def change
add_column :feedbacks, :policy_published, :json
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class ChangeFeedbackReportIDtoString < ActiveRecord::Migration[7.1]
def change
change_column :feedbacks, :report_id, :string
end
end
14 changes: 14 additions & 0 deletions db/migrate/20240212114627_create_records.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class CreateRecords < ActiveRecord::Migration[7.1]
def change
create_table :records do |t|
t.belongs_to :feedback, null: false, foreign_key: true
t.string :source_ip
t.integer :count
t.json :policy_evaluated
t.json :identifiers
t.json :auth_results

t.timestamps
end
end
end
18 changes: 16 additions & 2 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,26 @@
# MovieGenre.find_or_create_by!(name: genre_name)
# end

Feedback.create!(
feedback = Feedback.create!(
report: {
io: Rails.root.join('spec', 'examples', 'reports', 'report_google.com.xml').open,
filename: 'report_google.com.xml'
}
)
ProcessReportJob.perform_later(feedback)

Feedback.create!(
feedback = Feedback.create!(
report: {
io: Rails.root.join('spec', 'examples', 'reports', 'report_outlook.com.xml').open,
filename: 'report_outlook.com.xml'
}
)
ProcessReportJob.perform_later(feedback)

Domain.create!(
name: 'domain2.test'
feedback = Feedback.create!(
report: {
io: Rails.root.join('spec', 'examples', 'reports', 'report_infomaniak.com.xml').open,
filename: 'report_infomaniak.com.xml'
}
)
ProcessReportJob.perform_later(feedback)
24 changes: 24 additions & 0 deletions spec/controllers/domains_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe DomainsController do
context 'with an unauthenticated user' do
describe 'GET /' do
before do
get :index
end

it { is_expected.to respond_with(200) }
end

describe 'GET /domains/:id' do
before do
get :show, params: { id: Domain.create!(name: 'controller.domain').id }
end

it { is_expected.to respond_with(200) }
it { is_expected.to use_before_action(:set_domain) }
end
end
end
15 changes: 15 additions & 0 deletions spec/controllers/home_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe HomeController do
describe 'GET /' do
context 'with an unauthenticated user' do
before do
get :index
end

it { is_expected.to respond_with(200) }
end
end
end
Loading

0 comments on commit a5ed3d3

Please sign in to comment.