gitrob 0.0.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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