Browse Source

Upgrade to Rails 7.2

master
aeris 3 months ago
parent
commit
d4be6af200
  1. 8
      .gitignore
  2. 2
      .ruby-version
  3. 45
      Gemfile
  4. 1
      app/assets/config/manifest.js
  5. 3
      app/assets/javascripts/application.coffee
  6. 22
      app/assets/javascripts/matomo.js
  7. 166
      app/assets/stylesheets/application.scss.erb
  8. 0
      app/assets/stylesheets/check.scss
  9. 0
      app/assets/stylesheets/https.scss
  10. 36
      app/assets/stylesheets/site.scss.erb
  11. 0
      app/assets/stylesheets/smtp.scss
  12. 0
      app/assets/stylesheets/ssh.scss
  13. 0
      app/assets/stylesheets/tls.scss
  14. 3
      app/assets/stylesheets/xmpp.scss
  15. 446
      app/helpers/check_helper.rb
  16. 189
      app/javascript/css/application.scss
  17. 0
      app/javascript/images/donorbox.png
  18. 1
      app/javascript/packs/application.js
  19. 57
      app/views/application/_headers.erb
  20. 4
      app/views/application/_matomo.erb
  21. 2
      app/views/check/show.html.erb
  22. 156
      app/views/check/show.html.erb.bak
  23. 28
      app/views/layouts/application.html.erb
  24. 33
      app/views/site/index.html.erb
  25. 26
      app/views/site/suite_index.html.erb
  26. 38
      app/views/ssh/index.html.erb
  27. 12
      app/views/ssh/show.html.erb
  28. 37
      app/views/tls/index.html.erb
  29. 82
      babel.config.js
  30. 115
      bin/bundle
  31. 9
      bin/enqueue
  32. 11
      bin/rails
  33. 9
      bin/rake
  34. 18
      bin/webpack
  35. 18
      bin/webpack-dev-server
  36. 50
      config/application.rb
  37. 6
      config/boot.rb
  38. 2
      config/environment.rb
  39. 79
      config/environments/development.rb
  40. 63
      config/environments/production.rb
  41. 45
      config/environments/test.rb
  42. 9
      config/initializers/assets.rb
  43. 26
      config/initializers/content_security_policy.rb
  44. 8
      config/initializers/filter_parameter_logging.rb
  45. 3
      config/initializers/generators.rb
  46. 8
      config/initializers/inflections.rb
  47. 117
      config/initializers/new_framework_defaults_7_0.rb
  48. 11
      config/initializers/permissions_policy.rb
  49. 5
      config/webpack/development.js
  50. 3
      config/webpack/environment.js
  51. 5
      config/webpack/production.js
  52. 5
      config/webpack/test.js
  53. 92
      config/webpacker.yml
  54. 2
      db/schema.rb
  55. 17
      package.json
  56. 12
      postcss.config.js

8
.gitignore

@ -16,3 +16,11 @@ Gemfile.lock
/deploy.sh
/.excluded
/vendor/bundle/
/public/packs
/public/packs-test
/node_modules
/yarn-error.log
yarn-debug.log*
.yarn-integrity
yarn.lock

2
.ruby-version

@ -1 +1 @@
2.3.8-cryptcheck
3.1.1

45
Gemfile

@ -1,22 +1,25 @@
ruby '2.3.8'
source 'https://rubygems.org'
gem 'rails', '~> 5.2.4'
gem 'puma', '~> 3.11'
gem 'bootsnap', '>= 1.1.0', require: false
gem 'rails', '~> 7.0'
gem 'puma'
gem 'bootsnap', require: false
gem 'dotenv-rails'
gem 'sentry-raven', "~> 2.12"
gem 'webpacker'
gem 'sentry-ruby'
gem 'sentry-rails'
gem 'sentry-sidekiq'
gem 'pg'
gem 'sidekiq'
gem 'gush', github: 'aeris/gush', branch: :master
gem 'sidekiq-workflow', git: 'https://git.imirhil.fr/aeris/sidekiq-workflow.git', branch: :master
gem 'simpleidn'
gem 'http_accept_language'
gem 'recursive-open-struct'
gem 'uglifier', '>= 1.3.0'
gem 'sass-rails', '~> 5.0'
gem 'coffee-rails', '~> 4.2'
gem 'uglifier'
gem 'sass-rails'
gem 'jquery-rails'
gem 'bootstrap-sass'
gem 'font-awesome-sass'
@ -24,22 +27,18 @@ gem 'font-awesome-sass'
gem 'cryptcheck', '~> 2.0.0', path: '../engine'
group :development do
gem 'web-console', '>= 3.3.0'
gem 'listen', '>= 3.0.5', '< 3.2'
gem 'awesome_print'
gem 'rerun'
gem 'foreman'
gem 'amazing_print'
gem 'listen'
gem 'spring'
gem 'spring-watcher-listen', '~> 2.0.0'
gem 'pry-rails'
gem 'pry-byebug'
gem 'spring-watcher-listen'
gem 'better_errors'
gem 'binding_of_caller'
gem 'better_errors'
gem 'binding_of_caller'
gem 'guard', require: false
gem 'guard-rails', require: false
gem 'guard-livereload', require: false
gem 'rack-livereload'
gem 'guard', require: false
gem 'guard-rails', require: false
gem 'guard-livereload', require: false
gem 'rack-livereload'
end

1
app/assets/config/manifest.js

@ -0,0 +1 @@
//= link_tree ../images

3
app/assets/javascripts/application.coffee

@ -1,3 +0,0 @@
##= require jquery
##= require bootstrap/dropdown
##= require_tree .

22
app/assets/javascripts/matomo.js

@ -1,22 +0,0 @@
var _paq = window._paq || [];
document.addEventListener('DOMContentLoaded', function() {
const { matomoUrl: url, matomoSite: site } = document.documentElement.dataset
console.log(url, site);
if ( url == undefined || site == undefined ) return;
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
_paq.push(['setTrackerUrl', url]);
_paq.push(['setSiteId', site]);
const d = document,
g = d.createElement('script'),
s = d.getElementsByTagName('script')[0]
g.type = 'text/javascript'
g.async = true
g.defer = true
g.src = url
s.parentNode.insertBefore(g, s)
})

166
app/assets/stylesheets/application.scss.erb

@ -1,166 +0,0 @@
//= require_tree .
//= require_self
@import 'bootstrap-sprockets';
@import 'bootstrap';
@import 'bootstrap/variables';
@import 'bootstrap/mixins';
@import 'bootstrap/normalize';
@import 'bootstrap/scaffolding';
@import 'bootstrap/type';
@import 'bootstrap/grid';
@import 'bootstrap/tables';
@import 'bootstrap/forms';
@import 'bootstrap/buttons';
@import 'bootstrap/dropdowns';
@import 'bootstrap/navs';
@import 'bootstrap/navbar';
@import 'bootstrap/progress-bars';
@import 'bootstrap/labels';
@import 'bootstrap/badges';
@import 'bootstrap/alerts';
@import 'bootstrap/utilities';
@import 'bootstrap/responsive-utilities';
@import 'font-awesome-sprockets';
@import 'font-awesome';
* {
box-sizing: border-box;
}
$navbar-offset: $navbar-height + 10px;
body {
padding-top: $navbar-offset;
}
:target:before {
display: block;
content: " ";
margin-top: -$navbar-offset;
height: $navbar-offset;
visibility: hidden;
}
.label-error, .progress-bar-error {
background-color: #000;
}
.label-critical, .progress-bar-critical {
background-color: #000;
}
table.center {
td {
text-align: center;
&.left {
text-align: left;
}
}
}
td.error {
background-color: #ddd;
}
td.primary {
background-color: $state-info-bg;
}
<% unless Rails.env == 'production' %>
.translation_missing {
border: 1px solid red;
}
<% end %>
.progress-bar-default {
background-color: $label-default-bg;
}
.progress {
margin: 0;
}
#check,
#ssh_check,
#tls_check {
margin-top: 100px;
}
$color-critical: #d9534f;
$color-error: #e4804e;
$color-warning: #f0ad4e;
$color-good: #beb052;
$color-best: #8db457;
$color-great: #5cb85c;
.label-state-critical {
background-color: $color-critical;
}
.label-state-error {
background-color: $color-error;
}
.label-state-warning {
background-color: $color-warning;
color: $text-color;
}
.label-state-good {
background-color: $color-good;
color: $text-color;
}
.label-state-best {
background-color: $color-best;
}
.label-state-great {
background-color: $color-great;
}
.label-state-default {
background-color: $label-default-bg;
}
.label-state-success {
background-color: $label-success-bg;
}
$lighten-alert: 35%;
.alert-critical {
background-color: lighten($color-critical, $lighten-alert);
color: $color-critical;
border-color: $color-critical;
}
.alert-error {
background-color: lighten($color-error, $lighten-alert);
color: $color-error;
border-color: $color-error;
}
.alert-warning {
background-color: lighten($color-warning, $lighten-alert);
color: $color-warning;
border-color: $color-warning;
}
.alert-good {
background-color: lighten($color-good, $lighten-alert);
color: $color-good;
border-color: $color-good;
}
.alert-best {
background-color: lighten($color-best, $lighten-alert);
color: $color-best;
border-color: $color-best;
}
.alert-great {
background-color: lighten($color-great, $lighten-alert);
color: $color-great;
border-color: $color-great;
}

0
app/assets/stylesheets/check.scss

0
app/assets/stylesheets/https.scss

36
app/assets/stylesheets/site.scss.erb

@ -1,36 +0,0 @@
#about, #help {
margin-bottom: 20px;
}
#about, #help .scoring {
p {
font-size: 1.25em;
}
}
#donorbox {
background: #2d81c5 url(<%= image_path 'donorbox.png' %>) no-repeat 18px center;
color: #fff;
text-decoration: none;
font-family: Verdana, sans-serif;
display: inline-block;
font-size: 16px;
padding: 13px 17px 13px 56px;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 0 #1f5a89;
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
}
#liberapay, #donorbox, #paypal {
img {
height: 50px;
max-width: 140px;
}
}
table.scoring img {
width: 30px;
}

0
app/assets/stylesheets/smtp.scss

0
app/assets/stylesheets/ssh.scss

0
app/assets/stylesheets/tls.scss

3
app/assets/stylesheets/xmpp.scss

@ -1,3 +0,0 @@
// Place all the styles related to the Xmpp controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

446
app/helpers/check_helper.rb

@ -1,226 +1,224 @@
module CheckHelper
private def __label(value, color, state=true)
color = :default unless color
color = "state-#{color}" if state
"<span class=\"label label-#{color}\">#{value}</span>"
end
def label(value, color, state=true)
__label(value, color, state).html_safe
end
def cell(value, color, state=true)
"<td class=\"label-state-#{color}\">#{value}</td>".html_safe
end
def labels(level, states, state=true)
states.each_pair.collect do |name, value|
color = if value.nil?
:default
elsif ::CryptCheck::State.bad? level
value ? :danger : :success
else
value ? :success : :danger
end
__label name, color, state
end.join(' ').html_safe
end
def states(states)
::CryptCheck::State.collect do |level|
states[level].each_pair
.select { |_, v| v == true }
.collect { |name, _| __label name, level }
end.flatten(1).join(' ').html_safe
end
def rank_color(rank)
case rank
when :'A+', :A
:great
when :'B+', :B
:best
when :'C+', :C
:good
when :D
nil
when :E
:warning
when :F
:error
else
:critical
end
end
def rank_label(rank)
l = %i(0 V T X).include? rank
label rank, rank_color(rank), !l
end
def protocol_label(protocol)
label protocol.to_sym, protocol.status
end
def protocol_labels(protocols)
protocols.collect { |p| protocol_label p }.join("\n").html_safe
end
def key_label(key)
return label('Aucune', :error) unless key
label "#{key[:type].upcase} #{key[:size]} bits", key_color(key)
end
def key_labels(keys)
return label('Aucune', :error) if keys.empty?
keys.sort { |a, b| -1 * (a[:size] <=> b[:size]) }.collect { |k| key_label k }.join("\n").html_safe
end
def cipher_size_label(cipher)
size = cipher.size if cipher.is_a? CryptCheck::Tls::Cipher
label "#{size} bits", cipher_color(size)
end
def key_color(key)
case key[:size]
when nil then
:default
when 0...1024 then
:error
when 1024...2048 then
:danger
when 2048...4096 then
:warning
else
:success
end
end
def cipher_color(key)
case key
when nil then
:default
when 0...128 then
:error
when 112...128 then
:danger
when 128...256 then
:success
else
:primary
end
end
def cipher_name_label(cipher)
status = cipher.status
status = :success if status == :good
label("&nbsp;", status) + "&nbsp;#{cipher.name}".html_safe
end
def cipher_labels(cipher)
cipher.state.collect { |c, ls| ls.collect { |l| label l.upcase, c } }
.flatten(1).join("\n").html_safe
end
def cipher_kex_type_cell(kex)
color = case kex
when :ecdh then
nil
when :dh then
:warning
when :rsa then
:error
else
:critical
end
kex ||= 'None'
cell kex.to_s.upcase, color
end
def cipher_kex_size_cell(kex)
color = key_color kex
cell kex&.[](:size), color
end
def cipher_auth_type_cell(auth)
color = case auth
when :ecdsa, :rsa then
nil
else
:critical
end
auth ||= 'None'
cell auth.to_s.upcase, color
end
def cipher_auth_size_cell(auth)
color = key_color auth
cell auth&.[](:size), color
end
def cipher_enc_type_cell(enc)
color = case enc
when :chacha20
:success
when nil, :rc4
:critical
end
enc ||= 'NONE'
cell enc.to_s.upcase, color
end
def cipher_enc_block_size_cell(enc)
color = case
when enc == :stream
nil
when enc.nil?
nil
when enc <= 64
:critical
when enc < 128
:error
end
cell enc, color
end
def cipher_enc_key_size_cell(enc)
color = case
when enc.nil?
nil
when enc < 128
:critical
end
cell enc, color
end
def cipher_enc_mode_cell(enc)
color = case enc
when :gcm, :ccm, :aead
:success
end
cell enc.to_s.upcase, color
end
def cipher_mac_type_cell(mac)
color = case mac
when :poly1305 then
:success
when :sha384, :sha256 then
nil
when :sha1 then
:warning
else
:critical
end
cell mac.to_s.upcase, color
end
def cipher_mac_size_cell(mac)
cell mac, nil
end
def cipher_pfs_cell(pfs)
return cell 'PFS', nil if pfs
cell 'No PFS', :error
end
private def __label(value, color, state = true)
color = :default unless color
color = "state-#{color}" if state
"<span class=\"badge badge-#{color}\">#{value}</span>"
end
def label(value, color, state = true)
__label(value, color, state).html_safe
end
def cell(value, color, state = true)
"<td class=\"badge-state-#{color}\">#{value}</td>".html_safe
end
def labels(level, states, state = true)
states.each_pair.collect do |name, value|
color = if value.nil?
:default
elsif ::CryptCheck::State.bad? level
value ? :danger : :success
else
value ? :success : :danger
end
__label name, color, state
end.join(' ').html_safe
end
def states(states)
::CryptCheck::State.collect do |level|
states[level].each_pair
.select { |_, v| v == true }
.collect { |name, _| __label name, level }
end.flatten(1).join(' ').html_safe
end
def rank_color(rank)
case rank
when :'A+', :A
:great
when :'B+', :B
:best
when :'C+', :C
:good
when :D
nil
when :E
:warning
when :F
:error
else
:critical
end
end
def rank_label(rank)
l = %i(0 V T X).include? rank
label rank, rank_color(rank), !l
end
def protocol_label(protocol)
label protocol.to_sym, protocol.status
end
def protocol_labels(protocols)
protocols.collect { |p| protocol_label p }.join("\n").html_safe
end
def key_label(key)
return label('Aucune', :error) unless key
label "#{key[:type].upcase} #{key[:size]} bits", key_color(key)
end
def key_labels(keys)
return label('Aucune', :error) if keys.empty?
keys.sort { |a, b| -1 * (a[:size] <=> b[:size]) }.collect { |k| key_label k }.join("\n").html_safe
end
def cipher_size_label(cipher)
size = cipher.size if cipher.is_a? CryptCheck::Tls::Cipher
label "#{size} bits", cipher_color(size)
end
def key_color(key)
case key[:size]
when nil then
:default
when 0...1024 then
:error
when 1024...2048 then
:danger
when 2048...4096 then
:warning
else
:success
end
end
def cipher_color(key)
case key
when nil then
:default
when 0...128 then
:error
when 112...128 then
:danger
when 128...256 then
:success
else
:primary
end
end
def cipher_name_label(cipher)
status = cipher.status
status = :success if status == :good
label("&nbsp;", status) + "&nbsp;#{cipher.name}".html_safe
end
def cipher_labels(cipher)
cipher.state.collect { |c, ls| ls.collect { |l| label l.upcase, c } }
.flatten(1).join("\n").html_safe
end
def cipher_kex_type_cell(kex)
color = case kex
when :ecdh
:success
when :dh
:warning
when :rsa
:error
else
:critical
end
kex ||= 'None'
cell kex.to_s.upcase, color
end
def cipher_kex_size_cell(kex)
color = key_color kex
cell kex&.[](:size), color
end
def cipher_auth_type_cell(auth)
color = case auth
when :ecdsa
:success
when :rsa
:default
else
:critical
end
auth ||= 'None'
cell auth.to_s.upcase, color
end
def cipher_auth_size_cell(auth)
color = key_color auth
cell auth&.[](:size), color
end
def cipher_enc_type_cell(enc)
color = case enc
when :chacha20
:success
when nil, :rc4
:critical
end
enc ||= 'NONE'
cell enc.to_s.upcase, color
end
def cipher_enc_block_size_cell(enc)
color = case
when :stream
:default
when enc <= 64
:critical
when enc < 128
:error
end
cell enc, color
end
def cipher_enc_key_size_cell(enc)
color = case
when enc < 128
:critical
end
cell enc, color
end
def cipher_enc_mode_cell(enc)
color = case enc
when :gcm, :ccm, :aead
:success
end
cell enc.to_s.upcase, color
end
def cipher_mac_type_cell(mac)
color = case mac
when :poly1305
:success
when :sha384, :sha256
:default
when :sha1
:warning
else
:critical
end
cell mac.to_s.upcase, color
end
def cipher_mac_size_cell(mac)
cell mac, :default
end
def cipher_pfs_cell(pfs)
return cell 'PFS', nil if pfs
cell 'No PFS', :error
end
end

189
app/javascript/css/application.scss

@ -0,0 +1,189 @@
//@import "~bootstrap/scss/bootstrap";
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins";
@import "~bootstrap/scss/utilities";
@import "~bootstrap/scss/root";
@import "~bootstrap/scss/reboot";
//@import "~bootstrap/scss/type";
//@import "~bootstrap/scss/images";
@import "~bootstrap/scss/containers";
@import "~bootstrap/scss/grid";
@import "~bootstrap/scss/tables";
@import "~bootstrap/scss/forms";
@import "~bootstrap/scss/buttons";
//@import "~bootstrap/scss/transitions";
//@import "~bootstrap/scss/dropdown";
//@import "~bootstrap/scss/button-group";
@import "~bootstrap/scss/nav";
@import "~bootstrap/scss/navbar";
//@import "~bootstrap/scss/card";
//@import "~bootstrap/scss/accordion";
//@import "~bootstrap/scss/breadcrumb";
//@import "~bootstrap/scss/pagination";
@import "~bootstrap/scss/badge";
@import "~bootstrap/scss/alert";
@import "~bootstrap/scss/progress";
//@import "~bootstrap/scss/list-group";
//@import "~bootstrap/scss/close";
//@import "~bootstrap/scss/toasts";
//@import "~bootstrap/scss/modal";
//@import "~bootstrap/scss/tooltip";
//@import "~bootstrap/scss/popover";
//@import "~bootstrap/scss/carousel";
//@import "~bootstrap/scss/spinners";
//@import "~bootstrap/scss/offcanvas";
//@import "~bootstrap/scss/placeholders";
//@import "~bootstrap/scss/helpers";
@import "~bootstrap/scss/utilities/api";
$fa-font-path: "~font-awesome/fonts";
@import "~font-awesome/scss/font-awesome";
.badge-error, .progress-bar-error {
background-color: #000;
}
.badge-critical, .progress-bar-critical {
background-color: #000;
}
table.center {
td {
text-align: center;
&.left {
text-align: left;
}
}
}
td.error {
background-color: #ddd;
}
.progress {
margin: 0;
}
#check,
#ssh_check,
#tls_check {
margin-top: 100px;
}
$color-critical: #d9534f;
$color-error: #e4804e;
$color-warning: #f0ad4e;
$color-good: #beb052;
$color-best: #8db457;
$color-great: #5cb85c;
.badge-state-critical, td.badge-state-critical {
background-color: $color-critical;
}
.badge-state-error, td.badge-state-error {
background-color: $color-error;
}
.badge-state-warning, td.badge-state-warning {
background-color: $color-warning;
}
.badge-state-good, td.badge-state-good {
background-color: $color-good;
}
.badge-state-best, td.badge-state-best {
background-color: $color-best;
}
.badge-state-great, td.badge-state-great {
background-color: $color-great;
}
.badge-state-default {
background-color: $secondary;
}
.badge-state-success, td.badge-state-success {
background-color: $color-great;
}
$lighten-alert: 35%;
.alert-critical {
background-color: lighten($color-critical, $lighten-alert);
color: $color-critical;
border-color: $color-critical;
}
.alert-error {
background-color: lighten($color-error, $lighten-alert);
color: $color-error;
border-color: $color-error;
}
.alert-warning {
background-color: lighten($color-warning, $lighten-alert);
color: $color-warning;
border-color: $color-warning;
}
.alert-good {
background-color: lighten($color-good, $lighten-alert);
color: $color-good;
border-color: $color-good;
}
.alert-best {
background-color: lighten($color-best, $lighten-alert);
color: $color-best;
border-color: $color-best;
}
.alert-great {
background-color: lighten($color-great, $lighten-alert);
color: $color-great;
border-color: $color-great;
}
table.scoring img {
width: 30px;
}
#about, #help {
margin-bottom: 20px;
}
#about, #help .scoring {
p {
font-size: 1.25em;
}
}
#donorbox {
background: #2d81c5 url("../images/donorbox.png") no-repeat 18px center;
color: #fff;
text-decoration: none;
font-family: Verdana, sans-serif;
display: inline-block;
font-size: 16px;
padding: 13px 17px 13px 56px;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
box-shadow: 0 1px 0 0 #1f5a89;
text-shadow: 0 1px rgba(0, 0, 0, 0.3);
}
#liberapay, #donorbox, #paypal {
img {
height: 50px;
max-width: 140px;
}
}

0
app/assets/images/donorbox.png → app/javascript/images/donorbox.png

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

1
app/javascript/packs/application.js

@ -0,0 +1 @@
import 'css/application'

57
app/views/application/_headers.erb

@ -1,39 +1,18 @@
<header>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<span>
<%= link_to 'CryptCheck', root_path, class: %i(navbar-brand) %>
</span>
</div>
<ul class="nav navbar-nav">
<li><%= link_to 'HTTPS / SMTP / XMPP', root_path %></li>
<li><%= link_to 'TLS', tls_path %></li>
<li><%= link_to 'SSH', ssh_path %></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to t('User agent compatibility'), suite_path %></li>
<li><%= link_to t('Supported cipher suites'), ciphers_path %></li>
<li><%= link_to t('Help'), help_path %></li>
<li><%= link_to t('About'), about_path %></li>
<!--
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
Hall of f/sh·ame
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="#">Misc</a></li>
<li><a href="#">Syndicats</a></li>
<li><a href="#">SecureDrop</a></li>
<li><a href="#">Presse</a></li>
<li><a href="#">Top 500 Alexa</a></li>
<li><a href="#">Porn</a></li>
<li><a href="#">US gov</a></li>
</ul>
</li>
-->
</ul>
</div>
</nav>
</header>
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4">
<div class="container-fluid">
<%= link_to 'CryptCheck', root_path, class: %i(navbar-brand) %>
<ul class="navbar-nav mr-auto me-auto mb-2 mb-lg-0">
<li class="nav-item"><%= link_to 'HTTPS / SMTP / XMPP', root_path, class: %i(nav-link) %></li>
<li class="nav-item"><%= link_to 'TLS', tls_path, class: %i(nav-link) %></li>
<li class="nav-item"><%= link_to 'SSH', ssh_path, class: %i(nav-link) %></li>
</ul>
<ul class="navbar-nav mr-auto ms-auto mb-2 mb-lg-0">
<li class="nav-item"><%= link_to t('User agent compatibility'), suite_path, class: %i(nav-link) %></li>
<li class="nav-item"><%= link_to t('Supported cipher suites'), ciphers_path, class: %i(nav-link) %></li>
<li class="nav-item"><%= link_to t('Help'), help_path, class: %i(nav-link) %></li>
<li class="nav-item"><%= link_to t('About'), about_path, class: %i(nav-link) %></li>
</ul>
</div>
</nav>

4
app/views/application/_matomo.erb

@ -1,4 +0,0 @@
<noscript>
<img src="<%= config.url %>?idsite=<%= config.site %>&amp;rec=1" style="border:0;" alt=""/>
</noscript>

2
app/views/check/show.html.erb

@ -8,7 +8,7 @@
</div>
<% if Time.now - @analysis.updated_at >= Rails.configuration.refresh_delay %>
<div class="col-sm-1">
<%= link_to t('Refresh'), { action: :refresh }, class: %i(btn btn-default) %>
<%= link_to t('Refresh'), { action: :refresh }, class: %i(btn btn-outline-secondary) %>
</div>
<% end %>
</div>

156
app/views/check/show.html.erb.bak

@ -1,156 +0,0 @@
<div class="container">
<div class="row">
<div class="col-sm-11">
<h1>
[<%= self.type.to_s.upcase %>] <%= @host %> <span class="small">(<%= l @result.date %>)</span>
</h1>
</div>
<% if Time.now - @result.date >= Rails.configuration.refresh_delay %>
<div class="col-sm-1">
<%= link_to t('Refresh'), {action: :refresh}, class: %i(btn btn-default) %>
</div>
<% end %>
</div>
<%
@result.hosts.each do |host|
if host.error
error, host = host.error, host.host
%>
<div class="row">
<div class="col-sm-12">
<h2><%= host.name %> - <%= host.ip %> : <%= host.port %></h2>
<%= t 'Error during analysis:' %>
<span class="label label-error"><%= error %></span>
</div>
</div>
<%
else
host, grade, handshake = host.host, host.grade, host.handshake
%>
<div class="row">
<div class="col-sm-12">
<h2><%= host.name %> - <%= host.ip %> : <%= host.port %></h2>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<table class="table table-bordered table-condensed table-striped">
<thead>
<tr>
<th colspan="2">
Scores
<%= rank_label grade.rank %>
</th>
</tr>
</thead>
<tbody>
<%
{ 'Protocol' => 'protocol',
'Key exchange' => 'key_exchange',
'Cipher' => 'cipher_strengths',
'Overall' => 'score'}.each do |name, v| %>
<tr>
<th class="col-sm-4"><%= t name %></th>
<td class="col-sm-8"><%= score_progress grade.details[v] %></td>
</tr>
<% end %>
</tbody>
</table>
</div>
<div class="col-sm-6">
<table class="table table-bordered table-condensed table-striped">
<tbody>
<tr>
<th class="col-sm-4"><%= t 'Protocols' %></th>
<td class="col-sm-8"><%= protocol_labels handshake.protocols %></td>
</tr>
<tr>
<th><%= t 'Keys' %></th>
<td>
<p><%= t 'Certificates:' %> <%= key_label handshake[:key] %></p>
<p>Diffie Hellman : <%= key_labels handshake.dh %></p>
</td>
</tr>
<% { 'Good practices' => :success,
'Warning' => :warning,
'Critical' => :danger,
'Fatal' => :error }.each do |name, color|
names = grade[color]
next if names.nil? or names.empty?
%>
<tr>
<th><%= t name %></th>
<td>
<% names.each do |name| %>
<span class="label label-<%= color %>"><%= name.upcase %></span>
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<table class="table table-bordered table-condensed table-striped center">
<thead>
<tr>
<th rowspan="2"><%= t 'Name' %></th>
<th colspan="2"><%= t 'Key exchange' %></th>
<th colspan="2"><%= t 'Authentication' %></th>
<th colspan="4"><%= t 'Encryption' %></th>
<th colspan="2"><%= t 'MAC' %></th>
<th rowspan="2"><%= t 'PFS' %></th>
</tr>
<tr>
<th><%= t 'Type' %></th>
<th><%= t 'Key size' %></th>
<th><%= t 'Type' %></th>
<th><%= t 'Key size' %></th>
<th><%= t 'Type' %></th>
<th><%= t 'Key size' %></th>
<th><%= t 'Block size' %></th>
<th><%= t 'Mode' %></th>
<th><%= t 'Type' %></th>
<th><%= t 'Size' %></th>
</tr>
</thead>
<tbody>
<% CryptCheck::Tls::Server::EXISTING_METHODS.each do |protocol|
ciphers = CryptCheck::Tls::Cipher.sort(handshake.ciphers.select { |c| c.protocol == protocol.to_s }
.collect { |c| CryptCheck::Tls::Cipher.new protocol, [c.name, nil, c[:size]], c.dh, handshake[:key] })
unless ciphers.empty? %>
<tr>
<th colspan="12"><%= protocol_label protocol %></th>
</tr>
<% ciphers.each do |cipher|
params = cipher.params
kex = params[:kex]
auth = params[:auth]
enc = params[:enc]
mac = params[:mac]
pfs = params[:pfs]
%>
<tr>
<th><%= cipher_name_label cipher %></th>
<%= cipher_kex_type_cell kex&.first %>
<%= cipher_kex_size_cell kex&.last %>
<%= cipher_auth_type_cell auth&.first %>
<%= cipher_auth_size_cell auth&.last %>
<%= cipher_enc_type_cell enc&.first %>
<%= cipher_enc_key_size_cell enc&.[] 1 %>
<%= cipher_enc_block_size_cell enc&.[] 2 %>
<%= cipher_enc_mode_cell enc&.last %>
<%= cipher_mac_type_cell mac&.first %>
<%= cipher_mac_size_cell mac&.last %>
<%= cipher_pfs_cell pfs %>
</tr>
<% end end end %>
</tbody>
</table>
</div>
</div>
<% end
end %>
</div>

28
app/views/layouts/application.html.erb

@ -1,17 +1,17 @@
<!DOCTYPE html>
<% data = Matomo.enabled? ? { matomo_url: Matomo.url, matomo_site: Matomo.site } : {} %>
<%= content_tag :html, data: data do %>
<head>
<title>CryptCheck</title>
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= javascript_include_tag 'application' %>
<%= csrf_meta_tags %>
<%= yield :head %>
</head>
<body>
<%= render partial: 'headers' %>
<html>
<head>
<title>CryptCheck</title>
<%= stylesheet_pack_tag 'application', media: 'all' %>
<%= javascript_pack_tag 'application' %>
<%= csrf_meta_tags %>
<%= yield :head %>
</head>
<body>
<%= render partial: 'headers' %>
<main class="container">
<%= render partial: 'flash' %>
<%= yield %>
<%= render partial: 'matomo', locals: { config: Matomo } if Matomo.enabled? %>
</body>
<% end %>
</main>
</body>
</html>

33
app/views/site/index.html.erb

@ -1,20 +1,17 @@
<div id="check" class="container">
<div class="row">
<div class="col-sm-12">
<h1><%= t 'Check your domain' %></h1>
<%= form_tag root_path do %>
<div class="form-group">
<div class="col-sm-8">
<%= text_field_tag :host, nil, class: %i(form-control input-lg), placeholder: 'your-site.com' %>
</div>
<div class="col-sm-2">
<%= select_tag :type, options_for_select({'HTTPS' => :https, 'SMTP' => :smtp, 'XMPP' => :xmpp}), class: %i(form-control input-lg) %>
</div>
<div class="col-sm-2">
<%= submit_tag t('Test me!'), class: %i(form-control btn btn-primary input-lg pull-right) %>
</div>
</div>
<% end %>
<h1><%= t 'Check your domain' %></h1>
<%= form_tag root_path, class: %i[container-fluid] do %>
<div class="row input-group input-group-lg mb-3">
<div class="col input-group-lg">
<%= text_field_tag :host, nil, class: %i[form-control],
placeholder: 'your-site.com', required: true %>
</div>
<div class="col-auto input-group-lg">
<%= select_tag :type, options_for_select({ 'HTTPS' => :https, 'SMTP' => :smtp, 'XMPP' => :xmpp }), class: %i[form-select] %>
</div>
<div class="col-auto input-group-lg">
<%= submit_tag t('Test me!'), class: %i[btn btn-outline-primary] %>
</div>
</div>
</div>
<% end %>

26
app/views/site/suite_index.html.erb

@ -1,18 +1,14 @@
<div id="check" class="container">
<div class="row">
<div class="col-sm-12">
<h1><%= t 'User agent compatibility' %></h1>
<h2><%= t 'Cipher suite' %></h2>
<%= form_tag suite_path do %>
<div class="form-group">
<div class="col-sm-10">
<%= text_field_tag :suite, nil, class: %i(form-control input-lg), placeholder: 'EECDH+AES' %>
</div>
<div class="col-sm-2">
<%= submit_tag t('Test me!'), class: %i(form-control btn btn-primary input-lg pull-right) %>
</div>
</div>
<% end %>
<h1><%= t 'User agent compatibility' %></h1>
<h2><%= t 'Cipher suite' %></h2>
<%= form_tag suite_path, class: %i[container-fluid] do %>
<div class="row input-group input-group-lg mb-3">
<div class="col input-group-lg">
<%= text_field_tag :suite, nil, class: %i[form-control], placeholder: 'EECDH+AES' %>
</div>
<div class="col-auto input-group-lg">
<%= submit_tag t('Test me!'), class: %i[btn btn-outline-primary] %>
</div>
</div>
<% end %>
</div>

38
app/views/ssh/index.html.erb

@ -1,21 +1,21 @@
<div id="ssh_check" class="container">
<div class="row">
<div class="col-sm-12">
<h1><%= t 'Check your SSH server' %></h1>
<%= form_tag root_path do %>
<div class="form-group">
<div class="col-sm-8">
<%= text_field_tag :host, nil, class: %i(form-control input-lg), placeholder: 'your-site.com' %>
</div>
<div class="col-sm-2">
<%= text_field_tag :port, nil, class: %i(form-control input-lg), placeholder: 'port' %>
</div>
<div class="col-sm-2">
<%= hidden_field_tag :type, :ssh %>
<%= submit_tag t('Test me!'), class: %i(form-control btn btn-primary input-lg pull-right) %>
</div>
</div>
<% end %>
<h1><%= t 'Check your SSH server' %></h1>
<%= form_tag root_path, class: %i[container-fluid] do %>
<%= hidden_field_tag :type, :ssh %>
<div class="row input-group input-group-lg mb-3">
<div class="col input-group-lg">
<%= text_field_tag :host, nil, class: %i[form-control],
placeholder: 'your-site.com', required: true %>
</div>
<div class="col-auto input-group-lg">
<%= text_field_tag :port, nil, class: %i[form-control], placeholder: 'port',
type: :number, min: 0, max: 65535, required: true
%>
</div>
<div class="col-auto input-group-lg">
<%= submit_tag t('Test me!'), class: %i[btn btn-outline-primary] %>
</div>
</div>
</div>
<% end %>

12
app/views/ssh/show.html.erb

@ -2,17 +2,17 @@
<div class="row">
<div class="col-sm-11">
<h1>
[SSH] <%= @host %> <span class="small">(<%= l @result.date %>)</span>
[SSH] <%= @host %> <span class="small">(<%= l @analysis.updated_at %>)</span>
</h1>
</div>
<% if Time.now - @result.date >= Rails.configuration.refresh_delay %>
<% if Time.now - @analysis.updated_at >= Rails.configuration.refresh_delay %>
<div class="col-sm-1">
<%= link_to t('Refresh'), {action: :refresh}, class: %i(btn btn-default) %>
</div>
<% end %>
</div>
<%
@result.hosts.each do |host|
@result.each do |host|
if host.error
error, host = host.error, host.host
%>
@ -25,11 +25,11 @@
</div>
<%
else
host, server = host.host, host.handshake
server = host.handshakes
%>
<div class="row">
<div class="col-sm-12">
<h2><%= host.name %> - <%= host.ip %> : <%= host.port %></h2>
<h2><%= host.hostname %> - <%= host.ip %> : <%= host.port %></h2>
</div>
</div>
<div class="row">
@ -75,7 +75,7 @@
<tr>
<th><%= t 'Keys' %></th>
</tr>
<% server.key_.each do |key| %>
<% server.key.each do |key| %>
<tr>
<td><%= key_label key %></td>
</tr>

37
app/views/tls/index.html.erb

@ -1,21 +1,20 @@
<div id="tls_check" class="container">
<div class="row">
<div class="col-sm-12">
<h1><%= t 'Check your TLS server' %></h1>
<%= form_tag root_path do %>
<div class="form-group">
<div class="col-sm-8">
<%= text_field_tag :host, nil, class: %i(form-control input-lg), placeholder: 'your-site.com' %>
</div>
<div class="col-sm-2">
<%= text_field_tag :port, nil, class: %i(form-control input-lg), placeholder: 'port' %>
</div>
<div class="col-sm-2">
<%= hidden_field_tag :type, :tls %>
<%= submit_tag t('Test me!'), class: %i(form-control btn btn-primary input-lg pull-right) %>
</div>
</div>
<% end %>
<h1><%= t 'Check your TLS server' %></h1>
<%= form_tag root_path, class: %i[container-fluid] do %>
<%= hidden_field_tag :type, :tls %>
<div class="row input-group input-group-lg mb-3">
<div class="col input-group-lg">
<%= text_field_tag :host, nil, class: %i[form-control],
placeholder: 'your-site.com', required: true %>
</div>
<div class="col-auto input-group-lg">
<%= text_field_tag :port, nil, class: %i[form-control], placeholder: 'port',
type: :number, min: 0, max: 65535, required: true %>
</div>
<div class="col-auto input-group-lg">
<%= submit_tag t('Test me!'), class: %i[btn btn-outline-primary] %>
</div>
</div>
</div>
<% end %>

82
babel.config.js

@ -0,0 +1,82 @@
module.exports = function(api) {
var validEnv = ['development', 'test', 'production']
var currentEnv = api.env()
var isDevelopmentEnv = api.env('development')
var isProductionEnv = api.env('production')
var isTestEnv = api.env('test')
if (!validEnv.includes(currentEnv)) {
throw new Error(
'Please specify a valid `NODE_ENV` or ' +
'`BABEL_ENV` environment variables. Valid values are "development", ' +
'"test", and "production". Instead, received: ' +
JSON.stringify(currentEnv) +
'.'
)
}
return {
presets: [
isTestEnv && [
'@babel/preset-env',
{
targets: {
node: 'current'
}
}
],
(isProductionEnv || isDevelopmentEnv) && [
'@babel/preset-env',
{
forceAllTransforms: true,
useBuiltIns: 'entry',
corejs: 3,
modules: false,
exclude: ['transform-typeof-symbol']
}
]
].filter(Boolean),
plugins: [
'babel-plugin-macros',
'@babel/plugin-syntax-dynamic-import',
isTestEnv && 'babel-plugin-dynamic-import-node',
'@babel/plugin-transform-destructuring',
[
'@babel/plugin-proposal-class-properties',
{
loose: true
}
],
[
'@babel/plugin-proposal-object-rest-spread',
{
useBuiltIns: true
}
],
[
'@babel/plugin-proposal-private-methods',
{
loose: true
}
],
[
'@babel/plugin-proposal-private-property-in-object',
{
loose: true
}
],
[
'@babel/plugin-transform-runtime',
{
helpers: false
}
],
[
'@babel/plugin-transform-regenerator',
{
async: false
}
]
].filter(Boolean)
}
}

115
bin/bundle

@ -1,3 +1,114 @@
#!/usr/bin/env ruby
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
load Gem.bin_path('bundler', 'bundle')
# frozen_string_literal: true
#
# This file was generated by Bundler.
#
# The application 'bundle' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require "rubygems"
m = Module.new do
module_function
def invoked_as_script?
File.expand_path($0) == File.expand_path(__FILE__)
end
def env_var_version
ENV["BUNDLER_VERSION"]
end
def cli_arg_version
return unless invoked_as_script? # don't want to hijack other binstubs
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
bundler_version = nil
update_index = nil
ARGV.each_with_index do |a, i|
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
bundler_version = a
end
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
bundler_version = $1
update_index = i
end
bundler_version
end
def gemfile
gemfile = ENV["BUNDLE_GEMFILE"]
return gemfile if gemfile && !gemfile.empty?
File.expand_path("../../Gemfile", __FILE__)
end
def lockfile
lockfile =
case File.basename(gemfile)
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
else "#{gemfile}.lock"
end
File.expand_path(lockfile)
end
def lockfile_version
return unless File.file?(lockfile)
lockfile_contents = File.read(lockfile)
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
Regexp.last_match(1)
end
def bundler_requirement
@bundler_requirement ||=
env_var_version || cli_arg_version ||
bundler_requirement_for(lockfile_version)
end
def bundler_requirement_for(version)
return "#{Gem::Requirement.default}.a" unless version
bundler_gem_version = Gem::Version.new(version)
requirement = bundler_gem_version.approximate_recommendation
return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0")
requirement += ".a" if bundler_gem_version.prerelease?
requirement
end
def load_bundler!
ENV["BUNDLE_GEMFILE"] ||= gemfile
activate_bundler
end
def activate_bundler
gem_error = activation_error_handling do
gem "bundler", bundler_requirement
end
return if gem_error.nil?
require_error = activation_error_handling do
require "bundler/version"
end
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
exit 42
end
def activation_error_handling
yield
nil
rescue StandardError, LoadError => e
e
end
end
m.load_bundler!
if m.invoked_as_script?
load Gem.bin_path("bundler", "bundle")
end

9
bin/enqueue

@ -1,13 +1,14 @@
#!/usr/bin/env ruby
require 'bundler/setup'
ENV['RAILS_ENV'] ||= 'development'
require 'dotenv'
Dotenv.load ".env.#{ENV['RAILS_ENV']}", '.env'
if ENV['RAILS_ENV'] == 'development'
DIR = File.dirname File.dirname File.expand_path __FILE__
require File.join DIR, 'config/environment'
ENV['RAILS_ENV'] = 'test'
require 'sidekiq/testing/inline'
DIR = File.dirname File.dirname File.expand_path __FILE__
require File.join DIR, 'config/environment'
#ENV['RAILS_ENV'] = 'test'
#require 'sidekiq/testing/inline'
end
require 'sidekiq'

11
bin/rails

@ -1,9 +1,4 @@
#!/usr/bin/env ruby
begin
load File.expand_path('../spring', __FILE__)
rescue LoadError => e
raise unless e.message.include?('spring')
end
APP_PATH = File.expand_path('../config/application', __dir__)
require_relative '../config/boot'
require 'rails/commands'
APP_PATH = File.expand_path("../config/application", __dir__)
require_relative "../config/boot"
require "rails/commands"

9
bin/rake

@ -1,9 +1,4 @@
#!/usr/bin/env ruby
begin
load File.expand_path('../spring', __FILE__)
rescue LoadError => e
raise unless e.message.include?('spring')
end
require_relative '../config/boot'
require 'rake'
require_relative "../config/boot"
require "rake"
Rake.application.run

18
bin/webpack