parent
4280db5e4c
commit
b79153d477
@ -0,0 +1,3 @@ |
||||
--require spec_helper |
||||
--format progress |
||||
--format html --out tmp/rspec.html |
@ -0,0 +1,23 @@ |
||||
class StatisticsController < ApplicationController |
||||
TODAY = Date.today |
||||
|
||||
def show |
||||
service = params.fetch :id |
||||
respond_to do |format| |
||||
format.json do |
||||
json = Stat["grades_for_#{service}"].data |
||||
render json: json, status: :ok |
||||
end |
||||
end |
||||
end |
||||
|
||||
def ciphers |
||||
service = params.fetch :id |
||||
render json: Stat["ciphers_for_#{service}"].data |
||||
end |
||||
|
||||
def tls |
||||
service = params.fetch :id |
||||
render json: Stat["tls_for_#{service}"].data |
||||
end |
||||
end |
@ -0,0 +1,14 @@ |
||||
class StatsController < ApplicationController |
||||
@@sites = YAML.load_file Rails.root.join 'config/sites.yml' |
||||
|
||||
def banks |
||||
sites :banks |
||||
end |
||||
|
||||
private |
||||
|
||||
def sites(name) |
||||
@sites = @@sites.fetch name.to_s |
||||
render 'stats/sites' |
||||
end |
||||
end |
@ -0,0 +1,2 @@ |
||||
module StatisticsHelper |
||||
end |
@ -0,0 +1,40 @@ |
||||
document.addEventListener("DOMContentLoaded", () => { |
||||
let gradesChart = document.getElementById('gradesChart').getContext('2d') |
||||
|
||||
let background = [ |
||||
'rgba(255, 99, 132, 1)', |
||||
'rgba(54, 162, 235, 1)', |
||||
'rgba(255, 206, 86, 1)', |
||||
'rgba(75, 192, 192, 1)', |
||||
'rgba(153, 102, 255, 1)', |
||||
'rgba(255, 159, 64, 1)' |
||||
] |
||||
|
||||
let createGradesChart = new Chart(gradesChart, { |
||||
type: 'bar' |
||||
}) |
||||
|
||||
let generateGraphs = function () { |
||||
fetch(window.location.href, { |
||||
method: "GET", |
||||
headers: { |
||||
"Accept": "application/json", |
||||
"Content-Type": "application/json", |
||||
}, |
||||
}).then((response) => { |
||||
response.json().then((data) => { |
||||
if (response.status === 200) { |
||||
createGradesChart.data.labels = data["labels"] |
||||
createGradesChart.data.datasets = [{ |
||||
label: 'Number', |
||||
data: data["dataset"], |
||||
backgroundColor: background |
||||
}] |
||||
createGradesChart.update() |
||||
} |
||||
}) |
||||
}); |
||||
} |
||||
|
||||
generateGraphs() |
||||
}); |
@ -0,0 +1,72 @@ |
||||
document.addEventListener("DOMContentLoaded", () => { |
||||
let background = [ |
||||
'#5cb85c', // A+
|
||||
'#5cb85c', // A
|
||||
'#8db457', // B+
|
||||
'#8db457', // B
|
||||
'#beb052', // C+
|
||||
'#beb052', // C
|
||||
'#6c757d', // D
|
||||
'#f0ad4e', // E
|
||||
'#e4804e', // F
|
||||
'#d9534f' // G
|
||||
] |
||||
|
||||
for (const service of ["https", "smtp", "tls", "xmpp"]) { |
||||
const name = service.replace(/^\w/, c => c.toUpperCase()) |
||||
console.info(`grades${name}Chart`) |
||||
const canvas = document.getElementById(`grades${name}Chart`).getContext('2d') |
||||
// const chart = new Chart(canvas, {
|
||||
// type: 'pie',
|
||||
// options: {
|
||||
// interaction: {
|
||||
// intersect: false,
|
||||
// mode: 'dataset',
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
const chart = new Chart(canvas, { |
||||
type: 'bar', |
||||
options: { |
||||
interaction: { |
||||
intersect: false, |
||||
mode: 'dataset', |
||||
}, |
||||
plugins: { |
||||
datalabels: { |
||||
anchor: 'end', |
||||
align: 'top', |
||||
formatter: ((value, context) => { |
||||
const index = context.dataIndex |
||||
const keys = Object.keys(context.dataset.data) |
||||
value = context.dataset.data[keys[index]] |
||||
return value |
||||
}), |
||||
color: "black", |
||||
font: { |
||||
weight: "bold", |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}) |
||||
|
||||
fetch(`/statistics/${service}.json`).then((response) => { |
||||
if (response.status === 200) { |
||||
response.json().then((data) => { |
||||
const labels = ["A+", "A", "B+", "B", "C+", "C", "D", "E", "F", "G"] |
||||
const dataset = JSON.parse(JSON.stringify(data, labels, 0)) |
||||
chart.data.labels = labels |
||||
chart.data.datasets = [{ |
||||
label: 'Number of request', |
||||
data: dataset, |
||||
backgroundColor: background |
||||
}] |
||||
chart.update() |
||||
}) |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
) |
||||
; |
@ -1 +1,8 @@ |
||||
import 'css/application' |
||||
|
||||
import Chart from 'chart.js/auto' |
||||
import ChartDataLabels from 'chartjs-plugin-datalabels' |
||||
global.Chart = Chart |
||||
Chart.register(ChartDataLabels) |
||||
|
||||
import 'js/stats/grades' |
||||
|
@ -0,0 +1,24 @@ |
||||
class Matomo |
||||
module Helpers |
||||
def matomo_tag |
||||
config = Matomo |
||||
return unless config.enabled? |
||||
render partial: 'matomo', locals: { config: config } |
||||
end |
||||
end |
||||
|
||||
cattr_reader :url, :path, :site |
||||
|
||||
def self.load |
||||
@@url = ENV['MATOMO_URL'] |
||||
@@site = ENV['MATOMO_SITE'] |
||||
@@disabled = ENV['MATOMO_DISABLED'] |
||||
end |
||||
|
||||
def self.enabled? |
||||
@@disabled.nil? && self.url && self.site |
||||
end |
||||
|
||||
ActionView::Base.include Helpers |
||||
self.load |
||||
end |
@ -0,0 +1,164 @@ |
||||
<% colors = { |
||||
"A+" => 'great', |
||||
"good" => 'great', |
||||
"A" => 'great', |
||||
"B+" => 'best', |
||||
"B" => 'best', |
||||
"C+" => 'good', |
||||
"C" => 'good', |
||||
"D" => 'effort', |
||||
"E" => 'warning', |
||||
"F" => 'error', |
||||
"G" => 'critical', |
||||
"bad" => 'critical', |
||||
"ssl" => 'critical', |
||||
"tls" => 'error', |
||||
"tls1_2" => 'effort', |
||||
"tls1_2_only" => 'great' |
||||
} %> |
||||
|
||||
<ul class="nav nav-pills nav-fill" id="pills-tab" role="Navigation stats list"> |
||||
<% %i[https smtp tls xmpp].each do |service| %> |
||||
<li class="nav-item" role="presentation"> |
||||
<button class="nav-link<%= " active btn-dark" if service.to_s == "https" %>" |
||||
id="nav-<%= service %>-pill" data-bs-toggle="pill" |
||||
data-bs-target="#nav-<%= service %>" type="button" role="Button to show <%= service %> stats" aria-controls="nav-<%= service %>" aria-selected="true"> |
||||
<%= service.to_s.upcase %> |
||||
</button> |
||||
</li> |
||||
<% end %> |
||||
</ul> |
||||
|
||||
<div class="tab-content p-2 mb-4" id="nav-pillsContent"> |
||||
<% %i[https smtp tls xmpp].each do |service| %> |
||||
<div class="tab-pane fade show <%= "active" if service.to_s == "https" %>" |
||||
id="nav-<%= service %>" role="<%= service.to_s %>> stats" |
||||
aria-labelledby="nav-<%= service %>-pill"> |
||||
<h2>Grades for service <%= service.to_s.upcase %></h2> |
||||
|
||||
<% |
||||
grades = Stat["grades_for_#{service}"] |
||||
total = grades.data.collect { _2 }.sum |
||||
%> |
||||
|
||||
<p>Over <%= total %> URL tested with a grade.</p> |
||||
|
||||
<table class="table table-bordered table-striped"> |
||||
<thead class="bg-dark text-light"> |
||||
<tr> |
||||
<th>Grade</th> |
||||
<th>Percent</th> |
||||
<th>Number</th> |
||||
<th>Visual</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<% sorted_grades = grades.data.keys.sort &CryptCheck::Grade.method(:compare) |
||||
sorted_grades.each do |grade| |
||||
unless %w(T V).include?(grade) |
||||
number = grades.data[grade].to_i |
||||
percent = (number.to_f / total.to_f) * 100.0 |
||||
color = CryptCheck::Grade::GRADE_STATUS.fetch grade.to_sym %> |
||||
<tr> |
||||
<td><%= grade %></td> |
||||
<td><%= percent.round %>%</td> |
||||
<td><%= number %></td> |
||||
<td> |
||||
<div class="progress bg-light"> |
||||
<div class="progress-bar progress-<%= color %> border-dark" |
||||
style="width: <%= percent.round %>%" role="progressbar" |
||||
aria-valuenow="<%= percent.round %>" aria-valuemin="0" |
||||
aria-valuemax="100"></div> |
||||
</div> |
||||
</td> |
||||
</tr> |
||||
<% end |
||||
end %> |
||||
</tbody> |
||||
</table> |
||||
|
||||
<h2>Ciphers for service <%= service.to_s.upcase %></h2> |
||||
|
||||
<% |
||||
ciphers = Stat["ciphers_for_#{service}"] |
||||
total = ciphers.data.collect { _2 }.sum |
||||
%> |
||||
<p>Over <%= total %> URL tested with a cipher.</p> |
||||
|
||||
<table class="table table-bordered table-striped"> |
||||
<thead class="bg-dark text-light"> |
||||
<tr> |
||||
<th>Grade</th> |
||||
<th>Percent</th> |
||||
<th>Number</th> |
||||
<th>Visual</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<% sorted_grades = ciphers.data.keys.sort &CryptCheck::Grade.method(:compare) |
||||
sorted_grades.each do |grade| |
||||
number = ciphers.data[grade] |
||||
percent = (number.to_f / total.to_f) * 100.0 |
||||
color = colors[grade] |
||||
%> |
||||
<tr> |
||||
<td><%= grade.capitalize %></td> |
||||
<td><%= percent.round %>%</td> |
||||
<td><%= number %></td> |
||||
<td> |
||||
<div class="progress bg-light"> |
||||
<div class="progress-bar progress-<%= color %>" |
||||
style="width: <%= percent.round %>%" role="progressbar" |
||||
aria-valuenow="<%= percent.round %>" aria-valuemin="0" |
||||
aria-valuemax="100"></div> |
||||
</div> |
||||
</td> |
||||
</tr> |
||||
<% end %> |
||||
</tbody> |
||||
</table> |
||||
|
||||
<h2>TLS for service <%= service.to_s.upcase %></h2> |
||||
|
||||
<% tls = Stat["tls_for_#{service}"] |
||||
total = tls.data.collect { _2 }.sum |
||||
%> |
||||
<p>Over <%= total %> URL tested with TLS.</p> |
||||
|
||||
<table class="table table-bordered table-striped"> |
||||
<thead class="bg-dark text-light"> |
||||
<tr> |
||||
<th>Grade</th> |
||||
<th>Percent</th> |
||||
<th>Number</th> |
||||
<th>Visual</th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<% |
||||
sorted_grades = tls.data.keys.sort &CryptCheck::Grade.method(:compare) |
||||
sorted_grades.each do |grade| |
||||
number = tls.data[grade] |
||||
percent = (number.to_f / total.to_f) * 100.0 |
||||
color = colors[grade] |
||||
%> |
||||
<tr> |
||||
<td><%= grade.capitalize %></td> |
||||
<td><%= percent.round %>%</td> |
||||
<td><%= number %></td> |
||||
<td> |
||||
<div class="progress bg-light"> |
||||
<div class="progress-bar progress-<%= color %>" |
||||
style="width: <%= percent.round %>%" role="progressbar" |
||||
aria-valuenow="<%= percent.round %>" aria-valuemin="0" |
||||
aria-valuemax="100"></div> |
||||
</div> |
||||
</td> |
||||
</tr> |
||||
<% end %> |
||||
</tbody> |
||||
</table> |
||||
|
||||
</div> |
||||
<% end %> |
||||
</div> |
@ -0,0 +1,167 @@ |
||||
<% colors = { |
||||
"A+" => 'great', |
||||
"good" => 'great', |
||||
"A" => 'great', |
||||
"B+" => 'best', |
||||
"B" => 'best', |
||||
"C+" => 'good', |
||||
"C" => 'good', |
||||
"D" => 'effort', |
||||
"E" => 'warning', |
||||
"F" => 'error', |
||||
"G" => 'critical', |
||||
"bad" => 'critical', |
||||
"ssl" => 'critical', |
||||
"tls" => 'error', |
||||
"tls1_2" => 'effort', |
||||
"tls1_2_only" => 'great' |
||||
} %> |
||||
|
||||
<ul class="nav nav-pills nav-fill" id="pills-tab" role="Navigation stats list"> |
||||
<% %i[https smtp tls xmpp].each do |service| %> |
||||
<li class="nav-item" role="presentation"> |
||||
<button class="nav-link<%= " active btn-dark" if service.to_s == "https" %>" |
||||
id="nav-<%= service %>-pill" data-bs-toggle="pill" |
||||
data-bs-target="#nav-<%= service %>" type="button" role="Button to show <%= service %> stats" aria-controls="nav-<%= service %>" aria-selected="true"> |
||||
<%= service.to_s.upcase %> |
||||
</button> |
||||
</li> |
||||
<% end %> |
||||
</ul> |
||||
|
||||
<div class="tab-content p-2 mb-4" id="nav-pillsContent"> |
||||
<% %i[https smtp tls xmpp].each do |service| %> |
||||
<div class="tab-pane fade show <%= "active" if service.to_s == "https" %>" |
||||
id="nav-<%= service %>" role="<%= service.to_s %>> stats" |
||||
aria-labelledby="nav-<%= service %>-pill"> |
||||
<h2>Grades for service <%= service.to_s.upcase %></h2> |
||||
|
||||
<% |
||||
grades = Stat["grades_for_#{service}"] |
||||
total = grades.data.collect { _2 }.sum |
||||
%> |
||||
|
||||
<p>Over <%= total %> URL tested with a grade.</p> |
||||
|
||||
<table class="table table-bordered table-striped"> |
||||
<thead class="bg-dark text-light"> |
||||
<tr> |
||||
<th>Grade</th> |
||||
<th>Count</th> |
||||
<th></th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<% sorted_grades = grades.data.keys.sort &CryptCheck::Grade.method(:compare) |
||||
sorted_grades.each do |grade| |
||||
unless %w(T V).include?(grade) |
||||
count = grades.data[grade].to_i |
||||
percent = (count.to_f / total.to_f) * 100.0 |
||||
color = CryptCheck::Grade::GRADE_STATUS.fetch grade.to_sym %> |
||||
<tr> |
||||
<td class="col-4"><%= grade.capitalize %></td> |
||||
<td class="col-4"><%= count %> |
||||
(<%= percent.round %>%) |
||||
</td> |
||||
<td class="col-4"> |
||||
<div class="progress bg-light"> |
||||
<div class="progress-bar progress-<%= color %> border-dark" |
||||
style="width: <%= percent.round %>%" role="progressbar" |
||||
aria-valuenow="<%= percent.round %>" aria-valuemin="0" |
||||
aria-valuemax="100"></div> |
||||
</div> |
||||
</td> |
||||
</tr> |
||||
<% end |
||||
end %> |
||||
</tbody> |
||||
</table> |
||||
|
||||
<h2>Ciphers for service <%= service.to_s.upcase %></h2> |
||||
|
||||
<% |
||||
name = "ciphers_for_#{service}" |
||||
ciphers = Stat[name] |
||||
total = ciphers.data.collect { _2 }.sum |
||||
%> |
||||
<p>Over <%= total %> URL tested with a cipher.</p> |
||||
|
||||
<table class="table table-bordered table-striped"> |
||||
<thead class="bg-dark text-light"> |
||||
<tr> |
||||
<%= content_tag :th, t(:'.ciphers.title') %> |
||||
<th>Count</th> |
||||
<th></th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<% |
||||
ciphers = ciphers.data |
||||
%w[good bad].each do |grade| |
||||
count = ciphers.fetch grade |
||||
percent = (count.to_f / total.to_f) * 100.0 |
||||
color = colors[grade] |
||||
%> |
||||
<tr> |
||||
<td class="col-4"><%= t ".ciphers.#{grade}" %></td> |
||||
<td class="col-4"><%= count %> (<%= percent.round %> |
||||
%) |
||||
</td> |
||||
<td class="col-4"> |
||||
<div class="progress bg-light"> |
||||
<div class="progress-bar progress-<%= color %>" |
||||
style="width: <%= percent.round %>%" role="progressbar" |
||||
aria-valuenow="<%= percent.round %>" aria-valuemin="0" |
||||
aria-valuemax="100"></div> |
||||
</div> |
||||
</td> |
||||
</tr> |
||||
<% end %> |
||||
</tbody> |
||||
</table> |
||||
|
||||
<h2>TLS for service <%= service.to_s.upcase %></h2> |
||||
|
||||
<% |
||||
name = "tls_for_#{service}" |
||||
tls = Stat[name] |
||||
total = tls.data.collect { _2 }.sum |
||||
%> |
||||
<p>Over <%= total %> URL tested with TLS.</p> |
||||
|
||||
<table class="table table-bordered table-striped"> |
||||
<thead class="bg-dark text-light"> |
||||
<tr> |
||||
<%= content_tag :th, t(:'.tls.title') %> |
||||
<th>Count</th> |
||||
<th></th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<% |
||||
tls = tls.data |
||||
%w[tls1_2_only tls1_2 tls ssl].each do |grade| |
||||
count = tls.fetch grade |
||||
percent = (count.to_f / total.to_f) * 100.0 |
||||
color = colors[grade] |
||||
%> |
||||
<tr> |
||||
<td class="col-4"><%= t ".tls.#{grade}" %></td> |
||||
<td class="col-4"><%= count %> (<%= percent.round %> |
||||
%) |
||||
</td> |
||||
<td class="col-4"> |
||||
<div class="progress bg-light"> |
||||
<div class="progress-bar progress-<%= color %>" |
||||
style="width: <%= percent.round %>%" role="progressbar" |
||||
aria-valuenow="<%= percent.round %>" aria-valuemin="0" |
||||
aria-valuemax="100"></div> |
||||
</div> |
||||
</td> |
||||
</tr> |
||||
<% end %> |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
<% end %> |
||||
</div> |
@ -0,0 +1,29 @@ |
||||
#!/usr/bin/env ruby |
||||
# frozen_string_literal: true |
||||
|
||||
# |
||||
# This file was generated by Bundler. |
||||
# |
||||
# The application 'rspec' is installed as part of a gem, and |
||||
# this file is here to facilitate running it. |
||||
# |
||||
|
||||
require "pathname" |
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", |
||||
Pathname.new(__FILE__).realpath) |
||||
|
||||
bundle_binstub = File.expand_path("../bundle", __FILE__) |
||||
|
||||
if File.file?(bundle_binstub) |
||||
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ |
||||
load(bundle_binstub) |
||||
else |
||||
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. |
||||
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") |
||||
end |
||||
end |
||||
|
||||
require "rubygems" |
||||
require "bundler/setup" |
||||
|
||||
load Gem.bin_path("rspec-core", "rspec") |
Loading…
Reference in new issue