gitrob 0.0.6 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +30 -7
  3. data/.rspec +0 -1
  4. data/.rubocop.yml +55 -0
  5. data/.travis.yml +4 -0
  6. data/CHANGELOG.md +42 -0
  7. data/CONTRIBUTING.md +137 -9
  8. data/Gemfile +11 -1
  9. data/Guardfile +42 -0
  10. data/LICENSE.txt +17 -18
  11. data/README.md +79 -29
  12. data/Rakefile +6 -0
  13. data/bin/console +34 -0
  14. data/bin/setup +7 -0
  15. data/db/migrations/001_create_assessments.rb +19 -0
  16. data/db/migrations/002_create_github_access_tokens.rb +11 -0
  17. data/db/migrations/003_create_owners.rb +24 -0
  18. data/db/migrations/004_create_repositories.rb +23 -0
  19. data/db/migrations/005_create_blobs.rb +16 -0
  20. data/db/migrations/006_create_flags.rb +13 -0
  21. data/db/migrations/007_create_comparisons.rb +17 -0
  22. data/db/migrations/008_create_blobs_comparisons.rb +8 -0
  23. data/db/migrations/009_create_comparisons_repositories.rb +8 -0
  24. data/db/migrations/010_create_comparisons_owners.rb +8 -0
  25. data/exe/gitrob +6 -0
  26. data/gitrob.gemspec +25 -18
  27. data/lib/gitrob/blob_observer.rb +103 -0
  28. data/lib/gitrob/cli/command.rb +58 -0
  29. data/lib/gitrob/cli/commands/accept_terms_of_use.rb +61 -0
  30. data/lib/gitrob/cli/commands/analyze/analysis.rb +75 -0
  31. data/lib/gitrob/cli/commands/analyze/gathering.rb +101 -0
  32. data/lib/gitrob/cli/commands/analyze.rb +63 -0
  33. data/lib/gitrob/cli/commands/banner.rb +25 -0
  34. data/lib/gitrob/cli/commands/configure.rb +123 -0
  35. data/lib/gitrob/cli/commands/server.rb +21 -0
  36. data/lib/gitrob/cli/progress_bar.rb +47 -0
  37. data/lib/gitrob/cli.rb +213 -0
  38. data/lib/gitrob/github/client_manager.rb +46 -0
  39. data/lib/gitrob/github/data_manager.rb +121 -0
  40. data/lib/gitrob/jobs/assessment.rb +12 -0
  41. data/lib/gitrob/jobs/comparison.rb +55 -0
  42. data/lib/gitrob/models/assessment.rb +96 -0
  43. data/lib/gitrob/models/blob.rb +50 -0
  44. data/lib/gitrob/models/comparison.rb +15 -0
  45. data/lib/gitrob/models/flag.rb +15 -0
  46. data/lib/gitrob/models/github_access_token.rb +17 -0
  47. data/lib/gitrob/models/owner.rb +23 -0
  48. data/lib/gitrob/models/repository.rb +20 -0
  49. data/lib/gitrob/utils.rb +19 -0
  50. data/lib/gitrob/version.rb +1 -1
  51. data/lib/gitrob/web_app.rb +292 -0
  52. data/lib/gitrob.rb +30 -113
  53. data/public/css/bootstrap.min.css +11 -0
  54. data/public/css/main.css +130 -0
  55. data/public/css/tomorrow-night.css +75 -0
  56. data/public/fonts/glyphicons-halflings-regular.eot +0 -0
  57. data/public/fonts/glyphicons-halflings-regular.svg +273 -214
  58. data/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  59. data/public/fonts/glyphicons-halflings-regular.woff +0 -0
  60. data/public/fonts/glyphicons-halflings-regular.woff2 +0 -0
  61. data/public/images/blob_spinner.gif +0 -0
  62. data/public/images/gear_spinner.gif +0 -0
  63. data/public/js/bootstrap.min.js +7 -0
  64. data/public/js/highlight.pack.js +2 -0
  65. data/public/js/highlight.worker.js +13 -0
  66. data/public/js/jquery-2.1.4.min.js +4 -0
  67. data/public/js/main.js +239 -0
  68. data/public/robots.txt +2 -0
  69. data/signatures.json +541 -0
  70. data/views/assessments/_assessments.erb +57 -0
  71. data/views/assessments/_comparable_assessments.erb +38 -0
  72. data/views/assessments/_comparisons.erb +111 -0
  73. data/views/assessments/compare.erb +22 -0
  74. data/views/assessments/findings.erb +55 -0
  75. data/views/assessments/repositories.erb +35 -0
  76. data/views/assessments/show.erb +1 -0
  77. data/views/assessments/users.erb +46 -0
  78. data/views/blobs/show.erb +37 -0
  79. data/views/comparisons/show.erb +125 -0
  80. data/views/errors/internal_server_error.erb +9 -0
  81. data/views/errors/not_found.erb +5 -0
  82. data/views/index.erb +43 -28
  83. data/views/layout.erb +38 -12
  84. data/views/repositories/show.erb +49 -0
  85. data/views/users/show.erb +54 -0
  86. metadata +217 -106
  87. data/bin/gitrob +0 -260
  88. data/lib/gitrob/github/blob.rb +0 -41
  89. data/lib/gitrob/github/http_client.rb +0 -127
  90. data/lib/gitrob/github/organization.rb +0 -99
  91. data/lib/gitrob/github/repository.rb +0 -72
  92. data/lib/gitrob/github/user.rb +0 -84
  93. data/lib/gitrob/observers/sensitive_files.rb +0 -83
  94. data/lib/gitrob/progressbar.rb +0 -52
  95. data/lib/gitrob/util.rb +0 -11
  96. data/lib/gitrob/webapp.rb +0 -76
  97. data/models/blob.rb +0 -35
  98. data/models/finding.rb +0 -14
  99. data/models/organization.rb +0 -32
  100. data/models/repo.rb +0 -22
  101. data/models/user.rb +0 -28
  102. data/patterns.json +0 -394
  103. data/public/javascripts/bootstrap.min.js +0 -7
  104. data/public/javascripts/gitrob.js +0 -75
  105. data/public/javascripts/jquery-2.1.1.min.js +0 -4
  106. data/public/javascripts/lang-apollo.js +0 -2
  107. data/public/javascripts/lang-basic.js +0 -3
  108. data/public/javascripts/lang-clj.js +0 -18
  109. data/public/javascripts/lang-css.js +0 -2
  110. data/public/javascripts/lang-dart.js +0 -3
  111. data/public/javascripts/lang-erlang.js +0 -2
  112. data/public/javascripts/lang-go.js +0 -1
  113. data/public/javascripts/lang-hs.js +0 -2
  114. data/public/javascripts/lang-lisp.js +0 -3
  115. data/public/javascripts/lang-llvm.js +0 -1
  116. data/public/javascripts/lang-lua.js +0 -2
  117. data/public/javascripts/lang-matlab.js +0 -6
  118. data/public/javascripts/lang-ml.js +0 -2
  119. data/public/javascripts/lang-mumps.js +0 -2
  120. data/public/javascripts/lang-n.js +0 -4
  121. data/public/javascripts/lang-pascal.js +0 -3
  122. data/public/javascripts/lang-proto.js +0 -1
  123. data/public/javascripts/lang-r.js +0 -2
  124. data/public/javascripts/lang-rd.js +0 -1
  125. data/public/javascripts/lang-scala.js +0 -2
  126. data/public/javascripts/lang-sql.js +0 -2
  127. data/public/javascripts/lang-tcl.js +0 -3
  128. data/public/javascripts/lang-tex.js +0 -1
  129. data/public/javascripts/lang-vb.js +0 -2
  130. data/public/javascripts/lang-vhdl.js +0 -3
  131. data/public/javascripts/lang-wiki.js +0 -2
  132. data/public/javascripts/lang-xq.js +0 -3
  133. data/public/javascripts/lang-yaml.js +0 -2
  134. data/public/javascripts/prettify.js +0 -30
  135. data/public/javascripts/run_prettify.js +0 -34
  136. data/public/stylesheets/bootstrap.min.css +0 -7
  137. data/public/stylesheets/bootstrap.min.css.vanilla +0 -5
  138. data/public/stylesheets/gitrob.css +0 -88
  139. data/public/stylesheets/prettify.css +0 -51
  140. data/spec/lib/gitrob/observers/sensitive_files_spec.rb +0 -691
  141. data/spec/spec_helper.rb +0 -127
  142. data/views/blob.erb +0 -22
  143. data/views/organization.erb +0 -126
  144. data/views/repository.erb +0 -51
  145. data/views/user.erb +0 -51
@@ -0,0 +1,96 @@
1
+ module Gitrob
2
+ module Models
3
+ class Assessment < Sequel::Model
4
+ set_allowed_columns :name, :endpoint, :site, :verify_ssl, :finished
5
+
6
+ one_to_many :github_access_tokens
7
+ one_to_many :owners
8
+ one_to_many :repositories
9
+ one_to_many :blobs
10
+ one_to_many :flags
11
+ one_to_many :primary_comparisons,
12
+ :class => :"Gitrob::Models::Comparison",
13
+ :key => :primary_assessment_id
14
+ one_to_many :secondary_comparisons,
15
+ :class => :"Gitrob::Models::Comparison",
16
+ :key => :secondary_assessment_id
17
+
18
+ def validate
19
+ super
20
+ validates_presence [:endpoint, :site, :verify_ssl]
21
+ end
22
+
23
+ def name
24
+ values[:name] || fallback_name
25
+ end
26
+
27
+ def save_owner(owner)
28
+ owner = Gitrob::Utils.symbolize_hash_keys(owner.to_hash)
29
+ allowed_columns = Gitrob::Models::Owner.allowed_columns
30
+ owner[:github_id] = owner.delete(:id)
31
+ data = owner.select { |k, _v| allowed_columns.include?(k.to_sym) }
32
+ owner = Gitrob::Models::Owner.new(data)
33
+ self.owners_count += 1
34
+ add_owner(owner)
35
+ end
36
+
37
+ def save_repository(repository, owner)
38
+ repository = Gitrob::Utils.symbolize_hash_keys(repository.to_hash)
39
+ allowed_columns = Gitrob::Models::Repository.allowed_columns
40
+ repository[:github_id] = repository.delete(:id)
41
+ data = repository.select { |k, _v| allowed_columns.include?(k.to_sym) }
42
+ repository = Gitrob::Models::Repository.new(data)
43
+ repository.owner = owner
44
+ self.repositories_count += 1
45
+ repository.owner.repositories_count += 1
46
+ repository.owner.save
47
+ add_repository(repository)
48
+ end
49
+
50
+ def save_blob(blob, repository, owner)
51
+ allowed_columns = Gitrob::Models::Blob.allowed_columns
52
+ data = blob.select { |k, _v| allowed_columns.include?(k.to_sym) }
53
+ blob = Gitrob::Models::Blob.new(data)
54
+ blob.repository = repository
55
+ blob.owner = owner
56
+ self.blobs_count += 1
57
+ blob.owner.blobs_count += 1
58
+ blob.owner.save
59
+ blob.repository.blobs_count += 1
60
+ blob.repository.save
61
+ add_blob(blob)
62
+ end
63
+
64
+ def save_github_access_token(token)
65
+ add_github_access_token(
66
+ Gitrob::Models::GithubAccessToken.new(:token => token)
67
+ )
68
+ end
69
+
70
+ def comparable_assessments
71
+ owner_ids = owners.map(&:github_id)
72
+ comparison_ids = primary_comparisons_dataset
73
+ .select_map(:secondary_assessment_id) +
74
+ secondary_comparisons_dataset
75
+ .select_map(:primary_assessment_id)
76
+ self.class
77
+ .where("id NOT IN ?", [id] + comparison_ids)
78
+ .where(:finished => true, :deleted => false)
79
+ .order(:created_at)
80
+ .eager(:owners).reverse.all.select do |a|
81
+ !(a.owners.map(&:github_id) & owner_ids).empty?
82
+ end
83
+ end
84
+
85
+ def comparable_assessment?(assessment)
86
+ comparable_assessments.map(&:id).include?(assessment.id)
87
+ end
88
+
89
+ private
90
+
91
+ def fallback_name
92
+ reload.values[:created_at].strftime("%A, %d %b %Y %H:%M")
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,50 @@
1
+ module Gitrob
2
+ module Models
3
+ class Blob < Sequel::Model
4
+ set_allowed_columns :path, :size, :sha
5
+
6
+ SHA_REGEX = /[a-f0-9]{40}/
7
+ TEST_BLOB_INDICATORS = %w(test spec fixture mock stub fake demo sample)
8
+ LARGE_BLOB_THRESHOLD = 102_400
9
+
10
+ one_to_many :flags
11
+ many_to_one :repository
12
+ many_to_one :owner
13
+ many_to_one :assessment
14
+ many_to_many :comparisons
15
+
16
+ def validate
17
+ super
18
+ validates_presence [:path, :size, :sha]
19
+ validates_format SHA_REGEX, :sha
20
+ end
21
+
22
+ def filename
23
+ File.basename(path)
24
+ end
25
+
26
+ def extension
27
+ File.extname(path)[1..-1]
28
+ end
29
+
30
+ def test_blob?
31
+ TEST_BLOB_INDICATORS.each do |indicator|
32
+ return true if path.downcase.include?(indicator)
33
+ end
34
+ false
35
+ end
36
+
37
+ def html_url
38
+ "#{repository.html_url}/blob/#{repository.default_branch}/#{path}"
39
+ end
40
+
41
+ def history_html_url
42
+ "#{repository.html_url}/commits/#{repository.default_branch}/#{path}"
43
+ end
44
+
45
+ def large?
46
+ size.to_i > LARGE_BLOB_THRESHOLD
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,15 @@
1
+ module Gitrob
2
+ module Models
3
+ class Comparison < Sequel::Model
4
+ set_allowed_columns :primary_assessment, :secondary_assessment
5
+
6
+ many_to_one :primary_assessment,
7
+ :class => :"Gitrob::Models::Assessment"
8
+ many_to_one :secondary_assessment,
9
+ :class => :"Gitrob::Models::Assessment"
10
+ many_to_many :blobs
11
+ many_to_many :repositories
12
+ many_to_many :owners
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Gitrob
2
+ module Models
3
+ class Flag < Sequel::Model
4
+ set_allowed_columns :caption, :description, :assessment
5
+
6
+ many_to_one :blob
7
+ many_to_one :assessment
8
+
9
+ def validate
10
+ super
11
+ validates_presence [:caption]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module Gitrob
2
+ module Models
3
+ class GithubAccessToken < Sequel::Model
4
+ set_allowed_columns :token
5
+
6
+ TOKEN_REGEX = /[a-f0-9]{40}/
7
+
8
+ many_to_one :assessment
9
+
10
+ def validate
11
+ super
12
+ validates_presence [:token]
13
+ validates_format TOKEN_REGEX, :token
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ module Gitrob
2
+ module Models
3
+ class Owner < Sequel::Model
4
+ set_allowed_columns :github_id, :login, :type, :url,
5
+ :html_url, :avatar_url, :name, :blog,
6
+ :location, :email, :bio
7
+
8
+ ALLOWED_TYPES = %w(User Organization)
9
+
10
+ one_to_many :repositories
11
+ one_to_many :blobs
12
+ many_to_one :assessment
13
+ many_to_many :comparisons
14
+
15
+ def validate
16
+ super
17
+ validates_presence [:github_id, :login, :type, :url,
18
+ :html_url, :avatar_url]
19
+ validates_includes ALLOWED_TYPES, :type
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module Gitrob
2
+ module Models
3
+ class Repository < Sequel::Model
4
+ set_allowed_columns :github_id, :name, :full_name, :description,
5
+ :private, :url, :html_url, :homepage, :size,
6
+ :default_branch
7
+
8
+ one_to_many :blobs
9
+ many_to_one :assessment
10
+ many_to_one :owner
11
+ many_to_many :comparisons
12
+
13
+ def validate
14
+ super
15
+ validates_presence [:github_id, :name, :full_name, :private,
16
+ :url, :html_url, :size, :default_branch]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Gitrob
2
+ module Utils
3
+ def self.pluralize(count, singular, plural)
4
+ if count == 1
5
+ "#{count} #{singular}"
6
+ else
7
+ "#{count} #{plural}"
8
+ end
9
+ end
10
+
11
+ def self.symbolize_hash_keys(hash)
12
+ symbolized = {}
13
+ hash.each_pair do |k, v|
14
+ symbolized[k.to_sym] = v
15
+ end
16
+ symbolized
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module Gitrob
2
- VERSION = "0.0.6"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -0,0 +1,292 @@
1
+ require "sinatra/base"
2
+ require "thin"
3
+
4
+ module Gitrob
5
+ class WebApp < Sinatra::Base
6
+ CONTENT_SECURITY_POLICY = "default-src *; script-src 'self'; " \
7
+ "style-src 'self' 'unsafe-inline'; " \
8
+ "font-src 'self'; connect-src 'self'"
9
+
10
+ set :server, :thin
11
+ set :environment, :production
12
+ set :logging, false
13
+ set :sessions, true
14
+ set :app_file, __FILE__
15
+ set :root, File.expand_path("#{File.dirname(__FILE__)}/../../")
16
+ set :public_folder, proc { File.join(root, "public") }
17
+ set :views, proc { File.join(root, "views") }
18
+ set :run, proc { false }
19
+
20
+ helpers do
21
+ HUMAN_PREFIXES = %w(TB GB MB KB B).freeze
22
+
23
+ alias_method :h, :escape_html
24
+
25
+ def number_to_human_size(number)
26
+ s = number.to_f
27
+ i = HUMAN_PREFIXES.length - 1
28
+ while s > 512 && i > 0
29
+ i -= 1
30
+ s /= 1024
31
+ end
32
+ ((s > 9 || s.modulo(1) < 0.1 ? "%d" : "%.1f") % s) + "<strong>#{HUMAN_PREFIXES[i]}</strong>" # rubocop:disable Metrics/LineLength
33
+ end
34
+
35
+ def format_path(path)
36
+ dirname = File.dirname(path)
37
+ basename = File.basename(path)
38
+ if dirname == "."
39
+ "<strong>#{h basename}</strong>"
40
+ else
41
+ "#{h ellipsisize(dirname, 60, 25)}/<strong>#{h basename}</strong>"
42
+ end
43
+ end
44
+
45
+ def ellipsisize(string, minimum_length=4, edge_length=3)
46
+ return string if string.length < minimum_length || string.length <= edge_length * 2 # rubocop:disable Metrics/LineLength
47
+ edge = "." * edge_length
48
+ mid_length = string.length - edge_length * 2
49
+ string.gsub(/(#{edge}).{#{mid_length},}(#{edge})/, '\1...\2')
50
+ end
51
+
52
+ def format_url(url)
53
+ return url if url.start_with?("http")
54
+ "http://#{url}"
55
+ end
56
+
57
+ def protect_from_request_forgery!
58
+ session[:csrf] ||= SecureRandom.hex(32)
59
+ halt(403, "CSRF attack prevented") if csrf_attack?
60
+ end
61
+
62
+ def csrf_token_from_request
63
+ csrf_token = env["HTTP_X_CSRF_TOKEN"] || params["_csrf"]
64
+ halt(403, "CSRF token not present in request") if csrf_token.to_s.empty?
65
+ csrf_token
66
+ end
67
+
68
+ def csrf_attack?
69
+ !request.safe? && csrf_token_from_request != session[:csrf]
70
+ end
71
+
72
+ def find_assessment(id)
73
+ Gitrob::Models::Assessment.first(
74
+ :id => id.to_i,
75
+ :finished => true,
76
+ :deleted => false
77
+ ) || halt(404)
78
+ end
79
+
80
+ def find_comparison(id)
81
+ Gitrob::Models::Comparison.first(
82
+ :id => id.to_i,
83
+ :finished => true,
84
+ :deleted => false
85
+ ) || halt(404)
86
+ end
87
+ end
88
+
89
+ before do
90
+ response.headers["Content-Security-Policy"] = CONTENT_SECURITY_POLICY
91
+ response.headers["X-Content-Type-Options"] = "nosniff"
92
+ response.headers["X-XSS-Protection"] = "1; mode=block"
93
+ response.headers["X-Frame-Options"] = "deny"
94
+ protect_from_request_forgery!
95
+ end
96
+
97
+ get "/" do
98
+ @assessments =
99
+ Gitrob::Models::Assessment
100
+ .where(:deleted => false)
101
+ .order(:created_at)
102
+ .reverse.all
103
+ erb :index
104
+ end
105
+
106
+ get "/assessments/_table" do
107
+ @assessments =
108
+ Gitrob::Models::Assessment
109
+ .where(:deleted => false)
110
+ .order(:created_at)
111
+ .reverse.all
112
+ erb :"assessments/_assessments", :layout => false
113
+ end
114
+
115
+ post "/assessments" do
116
+ if params[:assessment][:verify_ssl]
117
+ verify_ssl = true
118
+ else
119
+ verify_ssl = false
120
+ end
121
+ options = {
122
+ :endpoint => params[:assessment][:endpoint],
123
+ :site => params[:assessment][:site],
124
+ :verify_ssl => verify_ssl,
125
+ :access_tokens => params[:assessment][:github_access_tokens]
126
+ }
127
+
128
+ Gitrob::Jobs::Assessment.perform_async(
129
+ params[:assessment][:targets],
130
+ options
131
+ )
132
+ status 202 # Accepted
133
+ end
134
+
135
+ get "/assessments/:id" do
136
+ redirect "/assessments/#{params[:id].to_i}/findings"
137
+ end
138
+
139
+ delete "/assessments/:id" do
140
+ @assessment = Gitrob::Models::Assessment.first(
141
+ :id => params[:id].to_i,
142
+ :deleted => false
143
+ ) || halt(404)
144
+ @assessment.deleted = true
145
+ @assessment.save
146
+ @assessment.destroy
147
+ end
148
+
149
+ get "/assessments/:id/findings" do
150
+ @assessment = find_assessment(params[:id])
151
+ @findings = @assessment.blobs_dataset.where("flags_count != 0")
152
+ .order(:path).eager(:repository, :flags).all
153
+ erb :"assessments/findings"
154
+ end
155
+
156
+ get "/assessments/:id/users" do
157
+ @assessment = find_assessment(params[:id])
158
+ @owners = @assessment.owners_dataset.order(:type)
159
+ erb :"assessments/users"
160
+ end
161
+
162
+ get "/assessments/:id/repositories" do
163
+ @assessment = find_assessment(params[:id])
164
+ @repositories = @assessment.repositories_dataset.order(:full_name).all
165
+ erb :"assessments/repositories"
166
+ end
167
+
168
+ get "/assessments/:id/compare" do
169
+ @assessment = find_assessment(params[:id])
170
+ @primary_comparisons = @assessment.primary_comparisons_dataset
171
+ .order(:created_at)
172
+ .reverse.all
173
+ @secondary_comparisons = @assessment.secondary_comparisons_dataset
174
+ .order(:created_at)
175
+ .reverse.all
176
+ @assessments = @assessment.comparable_assessments
177
+ erb :"assessments/compare"
178
+ end
179
+
180
+ get "/assessments/:id/compare/_comparables" do
181
+ @assessment = find_assessment(params[:id])
182
+ @assessments = @assessment.comparable_assessments
183
+ erb :"assessments/_comparable_assessments", :layout => false
184
+ end
185
+
186
+ get "/assessments/:id/compare/_comparisons" do
187
+ @assessment = find_assessment(params[:id])
188
+ @primary_comparisons = @assessment.primary_comparisons_dataset
189
+ .order(:created_at)
190
+ .reverse.all
191
+ @secondary_comparisons = @assessment.secondary_comparisons_dataset
192
+ .order(:created_at)
193
+ .reverse.all
194
+ erb :"assessments/_comparisons", :layout => false
195
+ end
196
+
197
+ get "/users/:id" do
198
+ @owner = Gitrob::Models::Owner.first(:id => params[:id].to_i) || halt(404)
199
+ @assessment = @owner.assessment
200
+ @repositories = @owner.repositories_dataset.order(:name).all
201
+ erb :"users/show", :layout => !request.xhr?
202
+ end
203
+
204
+ get "/repositories/:id" do
205
+ @repository = Gitrob::Models::Repository.first(
206
+ :id => params[:id].to_i
207
+ ) || halt(404)
208
+ @assessment = @repository.assessment
209
+ @blobs = @repository.blobs_dataset.order(:path).eager(:flags).all
210
+ erb :"repositories/show"
211
+ end
212
+
213
+ get "/blobs/:id" do
214
+ @blob = Gitrob::Models::Blob.first(:id => params[:id].to_i) || halt(404)
215
+ @assessment = @blob.assessment
216
+
217
+ if !@blob.large?
218
+ client_manager = Gitrob::Github::ClientManager.new(
219
+ :endpoint => @assessment.endpoint,
220
+ :site => @assessment.site,
221
+ :ssl => {
222
+ :verify => @assessment.verify_ssl
223
+ },
224
+ :access_tokens => @assessment.github_access_tokens.map(&:token)
225
+ )
226
+ @content = Base64.decode64(
227
+ client_manager.sample.repos.contents.get(
228
+ @blob.repository.owner.login,
229
+ @blob.repository.name,
230
+ @blob.path).content
231
+ )
232
+ else
233
+ @content = nil
234
+ end
235
+
236
+ erb :"blobs/show", :layout => false
237
+ end
238
+
239
+ post "/comparisons" do
240
+ @assessment = find_assessment(params[:assessment_id])
241
+ @other_assessment = find_assessment(params[:other_assessment_id])
242
+
243
+ if @assessment.created_at > @other_assessment.created_at
244
+ Gitrob::Jobs::Comparison.perform_async(
245
+ @assessment, @other_assessment)
246
+ else
247
+ Gitrob::Jobs::Comparison.perform_async(
248
+ @other_assessment, @assessment)
249
+ end
250
+ status 202 # Accepted
251
+ end
252
+
253
+ get "/comparisons/:id" do
254
+ @comparison = find_comparison(params[:id])
255
+ @blobs = @comparison.blobs_dataset.order(:path)
256
+ .eager(:flags, :repository).all
257
+ @repositories = @comparison.repositories_dataset.order(:full_name).all
258
+ @owners = @comparison.owners_dataset.order(:type).all
259
+ erb :"comparisons/show"
260
+ end
261
+
262
+ delete "/comparisons/:id" do
263
+ @comparison = Gitrob::Models::Comparison.first(
264
+ :id => params[:id].to_i,
265
+ :deleted => false
266
+ ) || halt(404)
267
+ @comparison.deleted = true
268
+ @comparison.save
269
+ @comparison.destroy
270
+ end
271
+
272
+ not_found do
273
+ status 404
274
+ erb :"errors/not_found"
275
+ end
276
+
277
+ error do
278
+ status 500
279
+ @error = env["sinatra.error"]
280
+ @error_details = JSON.pretty_generate(
281
+ :error => @error.class.to_s,
282
+ :message => @error.message,
283
+ :backtrace => @error.backtrace,
284
+ :request_method => env["REQUEST_METHOD"],
285
+ :request_path => env["REQUEST_PATH"],
286
+ :referer => env["HTTP_REFERER"],
287
+ :gitrob_version => Gitrob::VERSION
288
+ )
289
+ erb :"errors/internal_server_error"
290
+ end
291
+ end
292
+ end