forked from aeris/cryptcheck-rails
Compare commits
8 Commits
ae0223186c
...
d1eed36b6e
Author | SHA1 | Date |
---|---|---|
|
d1eed36b6e | 3 months ago |
|
a815f1c168 | 4 months ago |
|
896664af07 | 4 months ago |
|
3316d1f98a | 4 months ago |
|
de51a93fde | 4 months ago |
|
5760e3b4dd | 4 months ago |
|
4826c679e8 | 5 months ago |
|
4914bf1764 | 5 months ago |
42 changed files with 944 additions and 148 deletions
@ -0,0 +1,3 @@ |
|||
--require spec_helper |
|||
--format progress |
|||
--format html --out tmp/rspec.html |
@ -1,4 +1,4 @@ |
|||
web: bundle exec guard -i |
|||
webpack: bundle exec webpack-dev-server |
|||
webpack: bundle exec bin/webpack-dev-server |
|||
sidekiq: bundle exec sidekiq -q default |
|||
sidekiq_1_0: BUNDLE_GEMFILE=Gemfile-2.3 bin/sidekiq 1.0 -q tls_1_0 |
|||
|
@ -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.where(name: "grades_for_#{service}").order(date: :desc).first.data |
|||
render json: json, status: :ok |
|||
end |
|||
end |
|||
end |
|||
|
|||
def ciphers |
|||
service = params.fetch :id |
|||
render json: Stat.where(name: "ciphers_for_#{service}").order(date: :desc).first.data |
|||
end |
|||
|
|||
def tls |
|||
service = params.fetch :id |
|||
render json: Stat.where(name: "tls_for_#{service}").order(date: :desc).first.data |
|||
end |
|||
end |
@ -0,0 +1,2 @@ |
|||
module StatisticsHelper |
|||
end |
@ -0,0 +1,5 @@ |
|||
$dark: #3f4853; |
|||
|
|||
$link-color: #135262; |
|||
|
|||
$nav-pills-link-active-bg: #535d6c; |
@ -0,0 +1,44 @@ |
|||
document.addEventListener("DOMContentLoaded", () => { |
|||
if (document.getElementById("pills-tab")) { |
|||
let background = [ |
|||
'#d9534f', // bad
|
|||
'#5cb85c' // good
|
|||
] |
|||
|
|||
for (const service of ["https", "smtp", "tls", "xmpp"]) { |
|||
const name = service.replace(/^\w/, c => c.toUpperCase()) |
|||
const canvas = document.getElementById(`ciphers${name}Chart`).getContext('2d') |
|||
const chart = new Chart(canvas, { |
|||
type: 'doughnut', options: { |
|||
interaction: { |
|||
intersect: false, mode: 'dataset', |
|||
}, |
|||
animations: { |
|||
tension: { |
|||
duration: 100, |
|||
easing: 'linear', |
|||
from: 1, |
|||
to: 0, |
|||
loop: false |
|||
} |
|||
}, |
|||
} |
|||
}) |
|||
|
|||
fetch(`/statistics/${service}/ciphers.json`).then((response) => { |
|||
if (response.status === 200) { |
|||
response.json().then((data) => { |
|||
console.info(data) |
|||
const labels = Object.keys(data) |
|||
const dataset = Object.values(data) |
|||
chart.data.labels = labels |
|||
chart.data.datasets = [{ |
|||
label: 'Number of request', data: dataset, backgroundColor: background |
|||
}] |
|||
chart.update() |
|||
}) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
}) |
@ -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,73 @@ |
|||
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) => { |
|||
console.info(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() |
|||
}) |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
) |
|||
; |
@ -0,0 +1,46 @@ |
|||
document.addEventListener("DOMContentLoaded", () => { |
|||
if (document.getElementById("pills-tab")) { |
|||
let background = [ |
|||
'#d9534f', // ssl
|
|||
'#beb052', // tls
|
|||
'#beb052', // tls
|
|||
'#5cb85c' // tls1_2_only
|
|||
] |
|||
|
|||
for (const service of ["https", "smtp", "tls", "xmpp"]) { |
|||
const name = service.replace(/^\w/, c => c.toUpperCase()) |
|||
const canvas = document.getElementById(`tls${name}Chart`).getContext('2d') |
|||
const chart = new Chart(canvas, { |
|||
type: 'doughnut', options: { |
|||
interaction: { |
|||
intersect: false, mode: 'dataset', |
|||
}, |
|||
animations: { |
|||
tension: { |
|||
duration: 100, |
|||
easing: 'linear', |
|||
from: 1, |
|||
to: 0, |
|||
loop: false |
|||
} |
|||
}, |
|||
} |
|||
}) |
|||
|
|||
fetch(`/statistics/${service}/tls.json`).then((response) => { |
|||
if (response.status === 200) { |
|||
response.json().then((data) => { |
|||
console.info(data) |
|||
const labels = Object.keys(data) |
|||
const dataset = Object.values(data) |
|||
chart.data.labels = labels |
|||
chart.data.datasets = [{ |
|||
label: 'Number of request', data: dataset, backgroundColor: background |
|||
}] |
|||
chart.update() |
|||
}) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
}) |
@ -1 +1,10 @@ |
|||
import 'css/application' |
|||
|
|||
import 'bootstrap' |
|||
import Chart from 'chart.js/auto' |
|||
import ChartDataLabels from 'chartjs-plugin-datalabels' |
|||
global.Chart = Chart |
|||
Chart.register(ChartDataLabels) |
|||
|
|||
import 'js/stats/ciphers' |
|||
import 'js/stats/tls' |
@ -1,36 +1,36 @@ |
|||
class Analysis < ApplicationRecord |
|||
enum service: %i[https smtp xmpp tls ssh].collect { |e| [e, e.to_s] }.to_h |
|||
validates :service, presence: true |
|||
validates :host, presence: true |
|||
enum service: %i[https smtp xmpp tls ssh].collect { |e| [e, e.to_s] }.to_h |
|||
validates :service, presence: true |
|||
validates :host, presence: true |
|||
|
|||
def self.[](service, host, args) |
|||
key = self.key service, host, args |
|||
self.find_by key |
|||
end |
|||
def self.[](service, host, args) |
|||
key = self.key service, host, args |
|||
self.find_by key |
|||
end |
|||
|
|||
def self.pending!(service, host, args) |
|||
key = self.key service, host, args |
|||
analysis = self.find_or_create_by! key |
|||
analysis.pending! |
|||
end |
|||
def self.pending!(service, host, args) |
|||
key = self.key service, host, args |
|||
analysis = self.find_or_create_by! key |
|||
analysis.pending! |
|||
end |
|||
|
|||
def pending! |
|||
self.update! pending: true |
|||
self |
|||
end |
|||
def pending! |
|||
self.update! pending: true |
|||
self |
|||
end |
|||
|
|||
def self.post!(service, host, args, result) |
|||
analysis = self[service, host, args] |
|||
analysis.post! result |
|||
end |
|||
def self.post!(service, host, args, result) |
|||
analysis = self[service, host, args] |
|||
analysis.post! result |
|||
end |
|||
|
|||
def post!(result) |
|||
self.update! pending: false, result: result |
|||
end |
|||
def post!(result) |
|||
self.update! pending: false, result: result |
|||
end |
|||
|
|||
private |
|||
private |
|||
|
|||
def self.key(service, host, args) |
|||
{ service: service, host: host, args: args } |
|||
end |
|||
def self.key(service, host, args) |
|||
{ service: service, host: host, args: args } |
|||
end |
|||
end |
|||
|
@ -0,0 +1,10 @@ |
|||
class Stat < ApplicationRecord |
|||
def self.create!(name, data, date = Date.today) |
|||
self.delete_by name: name, date: date |
|||
super name: name, date: date, data: data |
|||
end |
|||
|
|||
def self.[](name) |
|||
self.where(name: name).order(date: :desc).limit(1).first |
|||
end |
|||
end |
@ -0,0 +1,7 @@ |
|||
<div> |
|||
Nombre de recherche <%= params[:service] %> : <%= @services.size %> |
|||
</div> |
|||
|
|||
<div> |
|||
<canvas id="gradesChart"></canvas> |
|||
</div> |
@ -0,0 +1,117 @@ |
|||
<% colors = { |
|||
"A+" => '#5cb85c', |
|||
"good" => '#5cb85c', |
|||
"A" => '#5cb85c', |
|||
"B+" => '#8db457', |
|||
"B" => '#8db457', |
|||
"C+" => '#beb052', |
|||
"C" => '#beb052', |
|||
"D" => '#6c757d', |
|||
"E" => '#f0ad4e', |
|||
"F" => '#e4804e', |
|||
"G" => '#d9534f', |
|||
"bad" => '#d9534f' } %> |
|||
|
|||
<ul class="nav nav-pills nav-fill" id="pills-tab" role="tab-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="pill" aria-controls="nav-<%= service %>" aria-selected="true"> |
|||
<%= service.to_s.upcase %> |
|||
</button> |
|||
</li> |
|||
<% end %> |
|||
</ul> |
|||
|
|||
<div class="tab-content p-2" 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="tabpanel" aria-labelledby="nav-<%= service %>-pill"> |
|||
<h2>Grades for service <%= service.to_s.upcase %></h2> |
|||
|
|||
|
|||
<% grades = Stat.where(name: "grades_for_#{service}").order(date: :desc).first |
|||
total = grades.data.collect { _2 }.sum %> |
|||
|
|||
<p>Over <%= total %> URL tested with a grade.</p> |
|||
|
|||
<div class="cumulative-datas"> |
|||
<% left = 0 |
|||
percent_total = 100 |
|||
grades.data.sort_by(&:first).each do |grade, number| |
|||
%> |
|||
<% unless %w(T V).include?(grade) |
|||
percent = (number.to_f / total.to_f) * 100.0 |
|||
color = colors[grade] |
|||
if percent > 1 %> |
|||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: <%= color %>;"> |
|||
<%= "#{grade}: #{percent.round}% (#{number})" %> |
|||
</div> |
|||
<% left += percent.round |
|||
end |
|||
end |
|||
end |
|||
percent = percent_total - left %> |
|||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: gray;"> |
|||
<%= "other: #{percent.round}%" %> |
|||
</div> |
|||
</div> |
|||
|
|||
<h2>Ciphers for service <%= service.to_s.upcase %></h2> |
|||
|
|||
<% ciphers = Stat.where(name: "ciphers_for_#{service}").order(date: :desc).first |
|||
total = ciphers.data.collect { _2 }.sum |
|||
%> |
|||
<p>Over <%= total %> URL tested with a cipher.</p> |
|||
|
|||
<div class="cumulative-datas"> |
|||
<% left = 0 |
|||
percent_total = 100 |
|||
ciphers.data.sort_by(&:first).each do |grade, number| |
|||
%> |
|||
<% |
|||
percent = (number.to_f / total.to_f) * 100.0 |
|||
color = colors[grade] %> |
|||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: <%= color %>;"> |
|||
<%= "#{grade.capitalize}: #{percent.round}% (#{number})" %> |
|||
</div> |
|||
<% left += percent.round |
|||
end |
|||
percent = percent_total - left |
|||
if percent > 0 %> |
|||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: gray;"> |
|||
<%= "Other: #{percent.round}%" %> |
|||
</div> |
|||
<% end %> |
|||
</div> |
|||
|
|||
<h2>TLS for service <%= service.to_s.upcase %></h2> |
|||
|
|||
<% tls = Stat.where(name: "tls_for_#{service}").order(date: :desc).first |
|||
total = tls.data.collect { _2 }.sum |
|||
%> |
|||
<p>Over <%= total %> URL tested with TLS.</p> |
|||
|
|||
<div class="cumulative-datas"> |
|||
<% left = 0 |
|||
percent_total = 100 |
|||
tls.data.sort_by(&:first).each do |grade, number| |
|||
%> |
|||
<% |
|||
percent = (number.to_f / total.to_f) * 100.0 |
|||
color = colors[grade] %> |
|||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: gray;"> |
|||
<%= "#{grade.capitalize}: #{percent.round}% (#{number})" %> |
|||
</div> |
|||
<% left += percent.round |
|||
end |
|||
percent = percent_total - left |
|||
if percent > 0 %> |
|||
<div class="cumulative-data" style="left: <%= left %>; width: <%= percent.round %>%; background-color: gray;"> |
|||
<%= "Other: #{percent.round}%" %> |
|||
</div> |
|||
<% end %> |
|||
</div> |
|||
</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") |
@ -0,0 +1,96 @@ |
|||
#!./bin/rails runner |
|||
|
|||
# Profit from open class to add stats methods only on this script |
|||
class Analysis |
|||
def grade |
|||
return if self.pending |
|||
grades = self.result.collect { _1['grade'] }.compact |
|||
CryptCheck::Grade.worst grades |
|||
end |
|||
|
|||
def tls |
|||
return if self.pending |
|||
return unless (result = self.result) |
|||
protocols = result.collect { |r| r.dig('handshakes', 'protocols') |
|||
&.collect { |p| p['protocol'].to_sym } } |
|||
.compact.flatten.uniq |
|||
|
|||
return :ssl if %i[SSLv2 SSLv3].any? { protocols.include? _1 } |
|||
return :tls unless protocols.include? :TLSv1_2 |
|||
return :tls1_2 unless protocols == %i[TLSv1_2] |
|||
:tls1_2_only |
|||
end |
|||
|
|||
def ciphers |
|||
return if self.pending |
|||
return unless (result = self.result) |
|||
status = result.collect do |r| |
|||
r.dig('handshakes', 'ciphers')&.collect do |c| |
|||
s = CryptCheck::Tls::Cipher |
|||
.new(nil, c.fetch('name')).status |
|||
CryptCheck::State.good_or_bad s |
|||
end |
|||
end.compact.flatten.uniq |
|||
|
|||
return :bad unless status.include? :bad |
|||
:good |
|||
end |
|||
|
|||
def pfs |
|||
return if self.pending |
|||
return unless (result = self.result) |
|||
ciphers = result.collect do |r| |
|||
r.dig('handshakes', 'ciphers')&.collect do |c| |
|||
CryptCheck::Tls::Cipher |
|||
.new(nil, c.fetch('name')) |
|||
.pfs? |
|||
end |
|||
end.compact.flatten.uniq |
|||
|
|||
return :no_pfs unless ciphers.include? true |
|||
return :pfs unless ciphers == [true] |
|||
:pfs_only |
|||
end |
|||
end |
|||
|
|||
services = Analysis.group(:service).count |
|||
Stat.create! :request_per_service, services |
|||
|
|||
%i[https smtp tls xmpp].each do |service| |
|||
services = Analysis.where service: service, pending: false |
|||
|
|||
grades = Hash.new 0 |
|||
tls = %i[tls1_2_only tls1_2 tls ssl].to_h { [_1, 0] } |
|||
ciphers = %i[good bad].to_h { [_1, 0] } |
|||
pfs = %i[pfs_only pfs no_pfs].to_h { [_1, 0] } |
|||
|
|||
services.each do |service| |
|||
if (g = service.grade) |
|||
grades[g] += 1 |
|||
end |
|||
|
|||
if (t = service.tls) |
|||
tls[t] += 1 |
|||
end |
|||
|
|||
if (c = service.ciphers) |
|||
ciphers[c] += 1 |
|||
end |
|||
|
|||
if (p = service.pfs) |
|||
pfs[p] += 1 |
|||
end |
|||
end |
|||
|
|||
ap "grades_for_#{service}" => grades |
|||
Stat.create! "grades_for_#{service}", grades |
|||
|
|||
ap "tls_for_#{service}" => tls |
|||
Stat.create! "tls_for_#{service}", tls |
|||
|
|||
ap "ciphers_for_#{service}" => ciphers |
|||
Stat.create! "ciphers_for_#{service}", ciphers |
|||
|
|||
ap "pfs_for_#{service}" => pfs |
|||
Stat.create! "pfs_for_#{service}", pfs |
|||
end |
@ -0,0 +1,11 @@ |
|||
class CreateStats < ActiveRecord::Migration[7.0] |
|||
def change |
|||
create_table :stats, id: :uuid do |t| |
|||
t.string :name |
|||
t.date :date |
|||
t.jsonb :data |
|||
end |
|||
|
|||
add_index :stats, %i[name] |
|||
end |
|||
end |
@ -0,0 +1,65 @@ |
|||
require 'rails_helper' |
|||
|
|||
describe Stat do |
|||
before do |
|||
Stat.delete_all |
|||
end |
|||
|
|||
describe '#create!' do |
|||
it 'must create stats if not existing' do |
|||
name = 'foo' |
|||
today = Date.today |
|||
data = { 'bar' => 'baz' } |
|||
expect { Stat.create! name, data } |
|||
.to change { Stat.count }.from(0).to(1) |
|||
stat = Stat.first |
|||
expect(stat.name).to eq name |
|||
expect(stat.date).to eq today |
|||
expect(stat.data).to eq data |
|||
end |
|||
|
|||
it 'must delete existing date if exist' do |
|||
name = 'foo' |
|||
today = Date.today |
|||
data = { 'bar' => 'baz' } |
|||
expect { Stat.create! name, data } |
|||
.to change { Stat.count }.from(0).to(1) |
|||
|
|||
data = { 'bar' => 'qux' } |
|||
expect { Stat.create! name, data } |
|||
.to_not change { Stat.count } |
|||
|
|||
stat = Stat.first |
|||
expect(stat.name).to eq name |
|||
expect(stat.date).to eq today |
|||
expect(stat.data).to eq data |
|||
end |
|||
end |
|||
|
|||
describe '#[]' do |
|||
it 'must retrieve the youngest data' do |
|||
name = 'foo' |
|||
|
|||
stat = Stat[name] |
|||
expect(stat).to be_nil |
|||
|
|||
data = { 'bar' => 'baz' } |
|||
date = Date.new 1970, 1, 1 |
|||
Stat.create! name, data, date |
|||
|
|||
stat = Stat[name] |
|||
expect(stat).to_not be_nil |
|||
expect(stat.date).to eq date |
|||
expect(stat.data).to eq data |
|||
|
|||
data = { 'bar' => 'qux' } |
|||
date = Date.new 1970, 1, 2 |
|||
Stat.create! name, data, date |
|||
|
|||
stat = Stat[name] |
|||
expect(stat).to_not be_nil |
|||
expect(stat.date).to eq date |
|||
expect(stat.data).to eq data |
|||
end |
|||
end |
|||
end |
@ -0,0 +1,64 @@ |
|||
# This file is copied to spec/ when you run 'rails generate rspec:install' |
|||
require 'spec_helper' |
|||
ENV['RAILS_ENV'] ||= 'test' |
|||
require_relative '../config/environment' |
|||
# Prevent database truncation if the environment is production |
|||
abort("The Rails environment is running in production mode!") if Rails.env.production? |
|||
require 'rspec/rails' |
|||
# Add additional requires below this line. Rails is not loaded until this point! |
|||
|
|||
# Requires supporting ruby files with custom matchers and macros, etc, in |
|||
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are |
|||
# run as spec files by default. This means that files in spec/support that end |
|||
# in _spec.rb will both be required and run as specs, causing the specs to be |
|||
# run twice. It is recommended that you do not name files matching this glob to |
|||
# end with _spec.rb. You can configure this pattern with the --pattern |
|||
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. |
|||
# |
|||
# The following line is provided for convenience purposes. It has the downside |
|||
# of increasing the boot-up time by auto-requiring all files in the support |
|||
# directory. Alternatively, in the individual `*_spec.rb` files, manually |
|||
# require only the support files necessary. |
|||
# |
|||
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } |
|||
|
|||
# Checks for pending migrations and applies them before tests are run. |
|||
# If you are not using ActiveRecord, you can remove these lines. |
|||
begin |
|||
ActiveRecord::Migration.maintain_test_schema! |
|||
rescue ActiveRecord::PendingMigrationError => e |
|||
puts e.to_s.strip |
|||
exit 1 |
|||
end |
|||
RSpec.configure do |config| |
|||
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures |
|||
config.fixture_path = "#{::Rails.root}/spec/fixtures" |
|||
|
|||
# If you're not using ActiveRecord, or you'd prefer not to run each of your |
|||
# examples within a transaction, remove the following line or assign false |
|||
# instead of true. |
|||
config.use_transactional_fixtures = true |
|||
|
|||
# You can uncomment this line to turn off ActiveRecord support entirely. |
|||
# config.use_active_record = false |
|||
|
|||
# RSpec Rails can automatically mix in different behaviours to your tests |
|||
# based on their file location, for example enabling you to call `get` and |
|||
# `post` in specs under `spec/controllers`. |
|||
# |
|||
# You can disable this behaviour by removing the line below, and instead |
|||
# explicitly tag your specs with their type, e.g.: |
|||
# |
|||
# RSpec.describe UsersController, type: :controller do |
|||
# # ... |
|||
# end |
|||
# |
|||
# The different available types are documented in the features, such as in |
|||
# https://relishapp.com/rspec/rspec-rails/docs |
|||
config.infer_spec_type_from_file_location! |
|||
|
|||
# Filter lines from Rails gems in backtraces. |
|||
config.filter_rails_from_backtrace! |
|||
# arbitrary gems may also be filtered via: |
|||
# config.filter_gems_from_backtrace("gem name") |
|||
end |
@ -0,0 +1,94 @@ |
|||
# This file was generated by the `rails generate rspec:install` command. Conventionally, all |
|||
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. |
|||
# The generated `.rspec` file contains `--require spec_helper` which will cause |
|||
# this file to always be loaded, without a need to explicitly require it in any |
|||
# files. |
|||
# |
|||
# Given that it is always loaded, you are encouraged to keep this file as |
|||
# light-weight as possible. Requiring heavyweight dependencies from this file |
|||
# will add to the boot time of your test suite on EVERY test run, even for an |
|||
# individual file that may not need all of that loaded. Instead, consider making |
|||
# a separate helper file that requires the additional dependencies and performs |
|||
# the additional setup, and require it from the spec files that actually need |
|||
# it. |
|||
# |
|||
# See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration |
|||
RSpec.configure do |config| |
|||
# rspec-expectations config goes here. You can use an alternate |
|||
# assertion/expectation library such as wrong or the stdlib/minitest |
|||
# assertions if you prefer. |
|||
config.expect_with :rspec do |expectations| |
|||
# This option will default to `true` in RSpec 4. It makes the `description` |
|||
# and `failure_message` of custom matchers include text for helper methods |
|||
# defined using `chain`, e.g.: |
|||
# be_bigger_than(2).and_smaller_than(4).description |
|||
# # => "be bigger than 2 and smaller than 4" |
|||
# ...rather than: |
|||
# # => "be bigger than 2" |
|||
expectations.include_chain_clauses_in_custom_matcher_descriptions = true |
|||
end |
|||
|
|||
# rspec-mocks config goes here. You can use an alternate test double |
|||
# library (such as bogus or mocha) by changing the `mock_with` option here. |
|||
config.mock_with :rspec do |mocks| |
|||
# Prevents you from mocking or stubbing a method that does not exist on |
|||
# a real object. This is generally recommended, and will default to |
|||
# `true` in RSpec 4. |
|||
mocks.verify_partial_doubles = true |
|||
end |
|||
|
|||
# This option will default to `:apply_to_host_groups` in RSpec 4 (and will |
|||
# have no way to turn it off -- the option exists only for backwards |
|||
# compatibility in RSpec 3). It causes shared context metadata to be |
|||
# inherited by the metadata hash of host groups and examples, rather than |
|||
# triggering implicit auto-inclusion in groups with matching metadata. |
|||
config.shared_context_metadata_behavior = :apply_to_host_groups |
|||
|
|||
# The settings below are suggested to provide a good initial experience |
|||
# with RSpec, but feel free to customize to your heart's content. |
|||
=begin |
|||
# This allows you to limit a spec run to individual examples or groups |
|||
# you care about by tagging them with `:focus` metadata. When nothing |
|||
# is tagged with `:focus`, all examples get run. RSpec also provides |
|||
# aliases for `it`, `describe`, and `context` that include `:focus` |
|||
# metadata: `fit`, `fdescribe` and `fcontext`, respectively. |
|||
config.filter_run_when_matching :focus |
|||
|
|||
# Allows RSpec to persist some state between runs in order to support |
|||
# the `--only-failures` and `--next-failure` CLI options. We recommend |
|||
# you configure your source control system to ignore this file. |
|||
config.example_status_persistence_file_path = "spec/examples.txt" |
|||
|
|||
# Limits the available syntax to the non-monkey patched syntax that is |
|||
# recommended. For more details, see: |
|||
# https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode |
|||
config.disable_monkey_patching! |
|||
|
|||
# Many RSpec users commonly either run the entire suite or an individual |
|||
# file, and it's useful to allow more verbose output when running an |
|||
# individual spec file. |
|||
if config.files_to_run.one? |
|||
# Use the documentation formatter for detailed output, |
|||
# unless a formatter has already been configured |
|||
# (e.g. via a command-line flag). |
|||
config.default_formatter = "doc" |
|||
end |
|||
|
|||
# Print the 10 slowest examples and example groups at the |
|||
# end of the spec run, to help surface which specs are running |
|||
# particularly slow. |
|||
config.profile_examples = 10 |
|||
|
|||
# Run specs in random order to surface order dependencies. If you find an |
|||
# order dependency and want to debug it, you can fix the order by providing |
|||
# the seed, which is printed after each run. |
|||
# --seed 1234 |
|||
config.order = :random |
|||
|
|||
# Seed global randomization in this process using the `--seed` CLI option. |
|||
# Setting this allows you to use `--seed` to deterministically reproduce |
|||
# test failures related to randomization by passing the same `--seed` value |
|||
# as the one that triggered the failure. |
|||
Kernel.srand config.seed |
|||
=end |
|||
end |
@ -1,4 +0,0 @@ |
|||
require 'test_helper' |
|||
|
|||
class CheckControllerTest < ActionController::TestCase |
|||
end |
@ -1,4 +0,0 @@ |
|||
require 'test_helper' |
|||
|
|||
class HttpsControllerTest < ActionController::TestCase |
|||
end |
@ -1,4 +0,0 @@ |
|||
require 'test_helper' |
|||
|
|||
class SiteControllerTest < ActionController::TestCase |
|||
end |
@ -1,4 +0,0 @@ |
|||
require 'test_helper' |
|||
|
|||
class SmtpControllerTest < ActionController::TestCase |
|||
end |
@ -1,4 +0,0 @@ |
|||
require 'test_helper' |
|||
|
|||
class SshControllerTest < ActionController::TestCase |
|||
end |
@ -1,19 +0,0 @@ |
|||
require 'test_helper' |
|||
|
|||
class TlsControllerTest < ActionController::TestCase |
|||
test "should get index" do |
|||
get :index |
|||
assert_response :success |
|||
end |
|||
|
|||
test "should get show" do |
|||
get :show |
|||
assert_response :success |
|||
end |
|||
|
|||
test "should get refresh" do |
|||
get :refresh |
|||
assert_response :success |
|||
end |
|||
|
|||
end |
@ -1,4 +0,0 @@ |
|||
require 'test_helper' |
|||
|
|||
class XmppControllerTest < ActionController::TestCase |
|||
end |
@ -1,3 +0,0 @@ |
|||
ENV['RAILS_ENV'] ||= 'test' |
|||
require File.expand_path('../../config/environment', __FILE__) |
|||
require 'rails/test_help' |
Loading…
Reference in new issue