osa 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1008becc098b639309f218c9f763e57d4d01f201b28fd105c478cd46534de913
4
- data.tar.gz: 2c285065f454aeaa7fcc1f9dd6f72e92d3423dbe292d06ef36afba6a8db6f9eb
3
+ metadata.gz: b3bc9c2b204260bd0cecd1650fdbfca0676c53e6e44c59aef8926caf9a5f0246
4
+ data.tar.gz: f32d6566bc6195847fc12fe680f8c22e6cbfe91f587bc7a35937efb1582eaccc
5
5
  SHA512:
6
- metadata.gz: 4b53ba423fc0b0da3bc8f49188d34370cf49d12e968a13a436ffaa6c849dceddedcf10c7e2b833d7316dbc0045fe487c44891b6eb50b98fb63477f63b8542a0e
7
- data.tar.gz: ba063539fe384116422310df5a0d3a14c324a0560674932dd39998951d433236fb929a86aae981895adff04a29d71d0780c8fc4a2a9d11fa817359ad56c10ff0
6
+ metadata.gz: 76462c72b811ecb6b2224725ec954aa3ff3c6d2fc99a4cc91ae66698d72de709c740683ce6c4690095853199c7ef67c836ddc0bf6c0d3c4eb33751ee0fec3058
7
+ data.tar.gz: f4e79f61caa68f2c1ecd646ffa3d127070addf334f827bb33066bfdefc1e44f8b2986b6983c120c94867fa907e65184fd679ef73ad0eaa6b1b34f49956d5393d
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- osa (0.2.1)
4
+ osa (0.2.2)
5
5
  activerecord (~> 6.0)
6
6
  faraday (~> 1.1)
7
7
  mail (~> 2.7.1)
@@ -37,7 +37,7 @@ GEM
37
37
  mail (2.7.1)
38
38
  mini_mime (>= 0.1.1)
39
39
  mini_mime (1.0.2)
40
- minitest (5.14.3)
40
+ minitest (5.14.4)
41
41
  multi_json (1.15.0)
42
42
  multipart-post (2.1.1)
43
43
  mustermann (1.1.1)
@@ -6,6 +6,7 @@ require 'osa/util/db'
6
6
  class DashboardServer < Sinatra::Base
7
7
  set :views, File.absolute_path(File.dirname(__FILE__) + '/../views')
8
8
  set :port, ENV['SERVER_PORT'] || 8080
9
+ after { ActiveRecord::Base.connection.close }
9
10
 
10
11
  get '/' do
11
12
  erb :index
@@ -54,7 +55,11 @@ class DashboardServer < Sinatra::Base
54
55
  end
55
56
 
56
57
  get '/api/stats/spammers' do
57
- spammers = OSA::Report.select('sender_domain as domain', 'COUNT(*) as count').limit(50).order(count: :desc).group(:sender_domain)
58
+ spammers = OSA::Report.select('sender_domain as domain', 'COUNT(*) as count')
59
+ unless params[:interval].blank?
60
+ spammers = spammers.where('received_at > ?', Time.now - params[:interval].to_i.days)
61
+ end
62
+ spammers = spammers.limit(50).order(count: :desc).group(:sender_domain)
58
63
  json spammers
59
64
  end
60
65
 
@@ -63,6 +68,9 @@ class DashboardServer < Sinatra::Base
63
68
  unless params[:spammer].blank?
64
69
  historical_data = historical_data.where(sender: params[:spammer]).or(OSA::Report.where(sender_domain: params[:spammer]))
65
70
  end
71
+ unless params[:interval].blank?
72
+ historical_data = historical_data.where('received_at > ?', Time.now - params[:interval].to_i.days)
73
+ end
66
74
  json historical_data.group(:date)
67
75
  end
68
76
  end
@@ -21,13 +21,26 @@ def resolve_blacklist(mail_id, email_address, domain, context, dns_blacklists)
21
21
  dns_blacklists.find { |bl| bl.blacklisted?(ip) }&.server
22
22
  end
23
23
 
24
+ def extract_email_address(mail)
25
+ email_address = mail['sender']['emailAddress']['address']
26
+ return email_address unless email_address.nil?
27
+
28
+ # Sometimes the SMTP From header is misformatted and the email address is
29
+ # parsed as part of the name by Outlook. Try to extract the email address
30
+ # from the name.
31
+ sender_name = mail['sender']['emailAddress']['name']
32
+ return nil if sender_name.nil?
33
+
34
+ sender_name.scan(/<(.+@.+)>/).first&.first
35
+ end
36
+
24
37
  while continue
25
38
  mails = context.graph_client.mails(context.config.junk_folder_id)
26
39
  continue = false
27
40
  loop do
28
41
  break if mails.nil?
29
42
  mails['value'].each do |mail|
30
- email_address = mail['sender']['emailAddress']['address']
43
+ email_address = extract_email_address(mail)
31
44
  next if email_address.nil?
32
45
  domain = PublicSuffix.domain(email_address.split('@', 2)[1])
33
46
 
data/lib/osa/util/db.rb CHANGED
@@ -25,7 +25,7 @@ module OSA
25
25
 
26
26
  class DnsBlacklist < ActiveRecord::Base
27
27
  def blacklisted?(ip)
28
- ::Resolv.getaddress("#{ip}.#{server}") != "0.0.0.0"
28
+ ::Resolv.getaddress("#{ip}.#{server}") != '0.0.0.0'
29
29
  rescue ::Resolv::ResolvError
30
30
  return false
31
31
  end
data/lib/osa/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module OSA
3
- VERSION = '0.2.1'
3
+ VERSION = '0.2.2'
4
4
  end
@@ -77,6 +77,15 @@
77
77
  <!-- ./col -->
78
78
  </div>
79
79
 
80
+ <div class="row">
81
+ <div id="interval-btn-group" class="btn-group">
82
+ <button onclick="updateInterval(this, '')" type="button" class="btn btn-info active">All time</button>
83
+ <button onclick="updateInterval(this, '1')" type="button" class="btn btn-info">1 day</button>
84
+ <button onclick="updateInterval(this, '7')" type="button" class="btn btn-info">7 days</button>
85
+ <button onclick="updateInterval(this, '30')" type="button" class="btn btn-info">30 days</button>
86
+ </div>
87
+ </div>
88
+
80
89
  <div class="row">
81
90
  <div class="card">
82
91
  <div class="card-header">
@@ -136,6 +145,21 @@
136
145
 
137
146
  <script>
138
147
  let totalReportCount = 0;
148
+ let interval = "";
149
+
150
+ function updateInterval(element, newInterval) {
151
+ interval = newInterval;
152
+ let children = Array.from(document.getElementById("interval-btn-group").children);
153
+ console.log(children);
154
+ children.forEach((child) => {
155
+ if (child === element) {
156
+ child.classList.add("active");
157
+ } else {
158
+ child.classList.remove("active");
159
+ }
160
+ });
161
+ update();
162
+ }
139
163
 
140
164
  function sec2time(timeInSeconds) {
141
165
  const time = parseFloat(timeInSeconds).toFixed(3);
@@ -179,7 +203,7 @@
179
203
  }
180
204
 
181
205
  async function updateSpammers() {
182
- const response = await fetch('/api/stats/spammers');
206
+ const response = await fetch(`/api/stats/spammers?interval=${interval}`);
183
207
  if (response.ok) {
184
208
  const body = await response.json();
185
209
 
@@ -270,7 +294,7 @@
270
294
  const historicalChart = createHistoricalChart();
271
295
 
272
296
  async function updateHistoricalChart() {
273
- const response = await fetch("/api/stats/reports/historical");
297
+ const response = await fetch(`/api/stats/reports/historical?interval=${interval}`);
274
298
  if (response.ok) {
275
299
  const body = await response.json();
276
300
 
@@ -285,11 +309,11 @@
285
309
 
286
310
  function update() {
287
311
  updateStats()
288
- .then(updateSpammers)
289
- .then(updateHistoricalChart)
290
- .then(() => {
291
- setTimeout(update, 10 * 60 * 1000);
292
- })
312
+ .then(updateSpammers)
313
+ .then(updateHistoricalChart)
314
+ .then(() => {
315
+ setTimeout(update, 10 * 60 * 1000);
316
+ })
293
317
  }
294
318
 
295
319
  update();
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: osa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moray Baruh
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-20 00:00:00.000000000 Z
11
+ date: 2021-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord