gems-status 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -39,9 +39,9 @@ class GemsCompositeCommand < GemsCommand
39
39
  @checkers.each do |check_object|
40
40
  Utils::log_debug "checking #{check_object.class.name}"
41
41
  @results[@target].sort.each do |k, gems|
42
- @checker_results[k] = "" unless @checker_results[k]
43
42
  gems.each do |gem|
44
43
  if !check_object.check?(gem)
44
+ @checker_results[k] = "" unless @checker_results[k]
45
45
  @checker_results[gem.name] << "
46
46
  <br/>#{gem.name} #{gem.version} #{gem.origin}: <br/>
47
47
  #{check_object.description} "
@@ -103,7 +103,6 @@ class GemsCompositeCommand < GemsCommand
103
103
  comments = nil
104
104
  end
105
105
  ViewResults::print_results(k, @results, @target, checker_results, comments)
106
- @checker_results.delete(k)
107
106
  @comments.delete(k)
108
107
  end
109
108
  ViewResults::print_tail(@checker_results, @comments)
@@ -1,3 +1,3 @@
1
1
  module GemsStatusMetadata
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.0"
3
3
  end
@@ -1,3 +1,4 @@
1
+ require "gmail"
1
2
  require "json"
2
3
  require "open-uri"
3
4
 
@@ -9,24 +10,93 @@ require "gems-status/scm_security_messages"
9
10
 
10
11
  class NotASecurityAlertChecker < GemChecker
11
12
  def initialize(conf)
12
- Utils::check_parameters('NotASecurityAlertChecker', conf, ["fixed", "source_repos"])
13
+ Utils::check_parameters('NotASecurityAlertChecker', conf, ["fixed", "source_repos", "email_username", "email_password", "mailing_lists", "email_to"])
13
14
  @fixed = conf["fixed"]
14
15
  @source_repos = conf["source_repos"]
15
16
  @security_messages = {}
17
+ @email_username = conf["email_username"]
18
+ @email_password = conf["email_password"]
19
+ @mailing_lists = conf["mailing_lists"]
20
+ @email_to = conf["email_to"]
21
+ @emails = {}
22
+ download_emails
16
23
  end
17
24
 
18
- def check?(gem)
19
- @security_messages = {}
25
+ def download_emails
26
+ #TODO: only download new emails and keep the old ones in a database
27
+ #puts "Security email alerts from #{mailing_list} #{gmail.inbox.count(:unread, :to => mailing_list}"
28
+ Gmail.new(@email_username, @email_password) do |gmail|
29
+ @mailing_lists.each do |mailing_list|
30
+ @emails[mailing_list] = []
31
+ Utils::log_debug "Security email alerts from #{mailing_list} #{gmail.inbox.count( :to => mailing_list)}"
32
+ #TODO: only read new emails
33
+ #gmail.inbox.emails(:unread, :to => "rubyonrails-security@googlegroups.com").each do |email|
34
+ gmail.inbox.emails(:to => mailing_list).each do |email|
35
+ Utils::log_debug "Read #{email.subject}"
36
+ @emails[mailing_list] << email
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def send_emails(gem)
43
+ return if @security_messages.length == 0
44
+ #gems.origin == gems.gems_url if we are looking to an upstream gem,
45
+ #for example in rubygems.org. We only care about our application gems.
46
+ return if gem.origin == gem.gems_url
47
+ mssg = ""
48
+ mssg = "#{gem.name} #{gem.version} : #{gem.origin} \n"
49
+ @security_messages.each do |k,v|
50
+ mssg = mssg + "\n #{v}"
51
+ end
52
+ email_receiver = @email_to
53
+ Gmail.new(@email_username, @email_password) do |gmail|
54
+ gmail.deliver do
55
+ to email_receiver
56
+ subject "[gems-status] security alerts for #{gem.name}"
57
+ text_part do
58
+ body mssg
59
+ end
60
+ end
61
+ end
62
+ Utils::log_debug "Email sent to #{@email_to} "
63
+ Utils::log_debug "with body #{mssg} "
64
+ end
65
+
66
+ def look_in_scm(gem)
20
67
  version = gem.version
21
68
  source_repo = source_repo(gem)
22
69
  if ! source_repo
23
70
  Utils::log_error gem.name, "Not source URL for #{gem.name}"
24
- @security_messages = {gem.name => "Not source URL for #{gem.name}"}
25
- return false
71
+ return
26
72
  end
27
73
  Utils::log_debug "Source URL for #{gem.name} #{source_repo}"
28
74
  look_for_security_messages(gem.name, source_repo)
29
75
  filter_security_messages_already_fixed(gem.version)
76
+ end
77
+
78
+ def look_in_emails(gem)
79
+ @emails.each do |listname, emails|
80
+ emails.each do |email|
81
+ if listname.include?(gem.name)
82
+ @security_messages[Utils::next_key(gem.name)] = email.subject
83
+ Utils::log_debug "looking for security emails: listname matches gem #{gem.name}: #{listname}"
84
+ next
85
+ end
86
+ if email.subject.include?(gem.name)
87
+ @security_messages[Utils::next_key(gem.name)] = email.subject
88
+ Utils::log_debug "looking for security emails: subject matches gem #{gem.name}: #{email.subject}"
89
+ next
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ def check?(gem)
96
+ @security_messages = {}
97
+ look_in_scm(gem)
98
+ look_in_emails(gem)
99
+ send_emails(gem)
30
100
  return @security_messages.length == 0
31
101
  end
32
102
 
@@ -42,6 +112,7 @@ class NotASecurityAlertChecker < GemChecker
42
112
  private
43
113
 
44
114
  def filter_security_messages_already_fixed(version)
115
+ #TODO: let's use a database instead of having the info in yaml file
45
116
  @security_messages.delete_if do |k,v|
46
117
  @fixed[k] && Gem::Version.new(@fixed[k]) <= version
47
118
  end
@@ -1,6 +1,5 @@
1
1
  class ScmCheckMessages
2
2
  MAX_RETRIES = 3
3
- @@keys = {}
4
3
 
5
4
  def check_messages(name, source_repo, message_checker, counter = 0)
6
5
  begin
@@ -33,10 +32,7 @@ private
33
32
  end
34
33
 
35
34
  def next_key(name)
36
- @@keys[name] = 0 unless @@keys[name]
37
- key = name + @@keys[name].to_s
38
- @@keys[name] = @@keys[name] + 1
39
- return key
35
+ return Utils::next_key(name)
40
36
  end
41
37
 
42
38
  def message(commit)
@@ -5,11 +5,19 @@ class Utils
5
5
  attr_accessor :errors
6
6
  @@errors = {}
7
7
  @@md5_sums = {}
8
+ @@keys = {}
8
9
 
9
10
  def Utils.errors
10
11
  return @@errors
11
12
  end
12
-
13
+
14
+ def Utils.next_key(name)
15
+ @@keys[name] = 0 unless @@keys[name]
16
+ key = name + @@keys[name].to_s
17
+ @@keys[name] = @@keys[name] + 1
18
+ return key
19
+ end
20
+
13
21
  def Utils.check_parameters(classname, conf, parameters)
14
22
  if !conf['classname'] then
15
23
  raise "trying to initialize #{classname} when parameter classname does not exists"
@@ -3,9 +3,9 @@ require 'gems-status/gems_status_metadata'
3
3
  require 'gems-status/utils'
4
4
 
5
5
  class ViewResults
6
- @@patched = 0
7
- @@outdated = 0
8
- @@up_to_date = 0
6
+ @@patched = []
7
+ @@outdated = []
8
+ @@up_to_date = []
9
9
 
10
10
  def ViewResults.print_description(ids)
11
11
  puts "
@@ -47,18 +47,20 @@ class ViewResults
47
47
  <p> At the end there are the errors, checks and comments that do not apply to any of the gems. Look them carefully.
48
48
  </p>
49
49
  <p>
50
+ There is a summary at the end.
51
+ </p>
50
52
  You should run gems-status periodically until the lists of errors, patched, outdated and checks are gone.
51
53
  </p>
52
54
  "
53
55
  end
54
56
 
55
- def ViewResults.update_summary(name_color)
56
- if name_color == "alert"
57
- @@patched += 1
58
- elsif name_color == "warning"
59
- @@outdated += 1
57
+ def ViewResults.update_summary(gem_name, status)
58
+ if status == "alert"
59
+ @@patched << gem_name
60
+ elsif status == "warning"
61
+ @@outdated << gem_name
60
62
  else
61
- @@up_to_date += 1
63
+ @@up_to_date << gem_name
62
64
  end
63
65
  end
64
66
 
@@ -116,9 +118,9 @@ class ViewResults
116
118
  md5 = gem.md5
117
119
  end
118
120
  end
119
- puts "<tr><td width='50%'><span class='#{name_color}'>#{k.upcase}</span></td><td width='10%'>version</td><td width='40%'>md5</td></tr>"
121
+ puts "<tr><td width='50%'><span class='#{name_color}'><a name=\"#{k}\" />#{k}</span></td><td width='10%'>version</td><td width='40%'>md5</td></tr>"
120
122
  puts html_string
121
- update_summary(name_color)
123
+ update_summary(k, name_color)
122
124
  puts "</table>"
123
125
  puts "</p>"
124
126
  if checker_results
@@ -145,7 +147,7 @@ class ViewResults
145
147
  <style>
146
148
  body
147
149
  {
148
- font-size: 100%;
150
+ font-size: 90%;
149
151
  }
150
152
  h1
151
153
  {
@@ -155,7 +157,8 @@ class ViewResults
155
157
  h2
156
158
  {
157
159
  font-size: 100%;
158
- font-weight: bold;
160
+ font-style: italic;
161
+ font-weight: normal;
159
162
  }
160
163
  .gem_name
161
164
  {
@@ -186,19 +189,19 @@ class ViewResults
186
189
  .errors
187
190
  {
188
191
  color: #ff0000;
189
- font-size: 80%;
192
+ font-size: 100%;
190
193
  font-style: italic;
191
194
  }
192
195
  .check
193
196
  {
194
197
  color: #a0a0a0;
195
- font-size: 80%;
198
+ font-size: 100%;
196
199
  font-style: italic;
197
200
  }
198
201
  .comment
199
202
  {
200
203
  color: #a0a0a0;
201
- font-size: 80%;
204
+ font-size: 100%;
202
205
  font-style: italic;
203
206
  }
204
207
  .table_results
@@ -210,24 +213,48 @@ class ViewResults
210
213
  <body>"
211
214
  end
212
215
 
213
- def ViewResults.print_hash(desc, data, style)
216
+ def ViewResults.print_hash(desc, data, style, anchor = false)
214
217
  return if !data or data.length == 0
215
218
  puts "<p>"
216
219
  puts "<h2>#{desc}: #{data.length}</h2>"
217
- data.each {|k,v| puts "<span class='#{style}'>#{k.upcase} : #{v}</span><br/>"}
220
+ data.each do |k,v|
221
+ if anchor
222
+ puts "<a href=\"\##{k}\"><span class='#{style}'>#{k}</span></a>"
223
+ else
224
+ puts "<span class='#{style}'>#{k}</span>"
225
+ end
226
+ puts "<span class='#{style}'> #{v}</span><br/>"
227
+
228
+ end
218
229
  puts "</p>"
219
230
  end
220
231
 
221
232
  def ViewResults.print_summary
222
- puts "<h2>summary</h2>"
223
- puts "patched/errored: #{@@patched} outdated: #{@@outdated} up-to-date: #{@@up_to_date}"
233
+ puts "<a name='summary'/><h1>Summary</h1>"
234
+ puts "<p><h2>patched/errored</h2>"
235
+ puts "<ul>"
236
+ @@patched.each do |p|
237
+ puts "<li><a href=\"\##{p}\">#{p}</a>"
238
+ end
239
+ puts "</ul></p>"
240
+ puts "<p><h2>outdated #{@@outdated.length}</h2>"
241
+ @@outdated.each do |p|
242
+ puts "<li><a href=\"\##{p}\">#{p}</a>"
243
+ end
244
+ puts "</ul></p>"
245
+ puts "<p> <h2>up-to-date #{@@up_to_date.length}</h2>"
246
+ @@up_to_date.each do |p|
247
+ puts "<li><a href=\"\##{p}\">#{p}</a>"
248
+ end
249
+ puts "</ul></p>"
224
250
  end
225
251
 
226
252
  def ViewResults.print_tail(checker_results, comments)
227
- self.print_hash("checks", checker_results, "check")
253
+ puts "<h1>Others</h1>"
228
254
  self.print_hash("comments", comments, "comment")
229
255
  self.print_hash("errors", Utils::errors, "errors")
230
256
  self.print_summary
257
+ self.print_hash("checks", checker_results, "summary", true)
231
258
  date = Time.now.strftime('%a %b %d %H:%M:%S %Z %Y')
232
259
  puts "<p class='footer'>run by <a href=\"https://github.com/jordimassaguerpla/gems-status\">gems-status</a> - #{date} - version: #{GemsStatusMetadata::VERSION}</p>
233
260
  </body>
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gems-status
3
3
  version: !ruby/object:Gem::Version
4
- hash: 63
4
+ hash: 59
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 8
8
+ - 9
9
9
  - 0
10
- version: 0.8.0
10
+ version: 0.9.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jordi Massaguer Pla
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-06-18 00:00:00 Z
18
+ date: 2012-06-27 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: xml-simple