Merge branch 'rails6'

This commit is contained in:
Jérémy Lecour 2019-08-25 17:40:36 +02:00
commit 29ee6fae97
103 changed files with 3176 additions and 3203 deletions

View File

@ -1,18 +0,0 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": "> 1%",
"uglify": true
},
"useBuiltIns": true
}]
],
"plugins": [
"syntax-dynamic-import",
"transform-object-rest-spread",
["transform-class-properties", { "spec": true }]
]
}

1
.browserslistrc Normal file
View File

@ -0,0 +1 @@
defaults

10
.gitignore vendored
View File

@ -19,9 +19,6 @@
# Ignore uploaded files in development # Ignore uploaded files in development
/storage/* /storage/*
/node_modules
/yarn-error.log
/public/assets /public/assets
.byebug_history .byebug_history
@ -44,3 +41,10 @@ yarn-debug.log*
# OS file # OS file
.DS_Store .DS_Store
/public/packs
/public/packs-test
/node_modules
/yarn-error.log
yarn-debug.log*
.yarn-integrity

View File

@ -1,3 +0,0 @@
plugins:
postcss-import: {}
postcss-cssnext: {}

View File

@ -4,8 +4,8 @@
language: language:
- ruby - ruby
rvm: rvm:
- 2.3 ### Zeitwerk is not fully compatible with < 2.5.4
- 2.4 ### cf. https://github.com/Evolix/chexpire/pull/104
- 2.5 - 2.5
- 2.6 - 2.6
@ -23,8 +23,6 @@ services:
- mysql - mysql
before_install: before_install:
- gem update --system
- gem install bundler
- mysql -e 'CREATE DATABASE chexpire_test;' - mysql -e 'CREATE DATABASE chexpire_test;'
- cp config/database.travis.yml config/database.yml - cp config/database.travis.yml config/database.yml
- cp config/secrets.example.yml config/secrets.yml - cp config/secrets.example.yml config/secrets.yml
@ -37,6 +35,7 @@ install:
- bundle install - bundle install
- yarn install - yarn install
- rails db:create db:migrate - rails db:create db:migrate
- rails webpacker:compile
script: script:
- bundle exec rubocop - bundle exec rubocop

51
Gemfile
View File

@ -1,45 +1,44 @@
source 'https://rubygems.org' source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" } git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby '>= 2.3.3' ruby '>= 2.5.4'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.0' gem 'rails', '6.0.0'
gem 'rails-i18n', '~> 5.1' gem 'rails-i18n', '~> 6.0.0'
# Use mysql as the database for Active Record # Use mysql as the database for Active Record
gem 'mysql2', '>= 0.4.4', '< 0.6.0' gem 'mysql2', '>= 0.4.4', '< 0.6.0'
# Use Puma as the app server # Use Puma as the app server
gem 'puma', '~> 3.11' gem 'puma', '~> 4.0'
gem 'devise', '~> 4.4'
gem 'devise-i18n', '~> 1.6'
# responders 3 depends on Ruy >= 2.4.0, let's keep a 2.x for now
gem 'responders', '~> 2.4.1'
gem 'devise', '~> 4.7'
gem 'devise-i18n', '~> 1.8'
gem 'simple_form', '~> 4.0' gem 'simple_form', '~> 4.0'
gem 'pundit', '~> 1.1' gem 'pundit', '~> 1.1'
# Use SCSS for stylesheets # Use SCSS for stylesheets
# sass-rails 5.1 depends on Ruy >= 2.4.0, let's keep 5.0.7 for now gem 'sass-rails', '~> 5'
gem 'sass-rails', '5.0.7' # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
# Use Uglifier as compressor for JavaScript assets gem 'webpacker', '~> 4.0'
gem 'uglifier', '>= 1.3.0'
gem 'webpacker', '~> 3.5'
# See https://github.com/rails/execjs#readme for more supported runtimes # See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'mini_racer', platforms: :ruby # gem 'mini_racer', platforms: :ruby
# Use CoffeeScript for .coffee assets and views gem 'bootstrap', '~> 4.3.1'
# gem 'coffee-rails', '~> 4.2'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5' gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5' gem 'jbuilder', '~> 2.7'
# Use ActiveModel has_secure_password # Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
gem 'bcrypt', '~> 3.1.7' gem 'bcrypt', '~> 3.1.7'
# Use ActiveStorage variant # Use Active Storage variant
# gem 'mini_magick', '~> 4.8' # gem 'image_processing', '~> 1.2'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.2', require: false
gem 'rack-contrib' gem 'rack-contrib'
@ -55,12 +54,10 @@ gem 'has_scope'
gem 'logging' gem 'logging'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false
group :development, :test do group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console # Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'binding_of_caller' gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
# gem 'binding_of_caller'
gem 'pry-byebug' gem 'pry-byebug'
gem 'pry-rails' gem 'pry-rails'
@ -69,7 +66,7 @@ end
group :development do group :development do
# Access an interactive console on exception pages or by calling 'console' anywhere in the code. # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
gem 'web-console', '>= 3.3.0' gem 'web-console', '~> 4.0'
gem 'listen', '>= 3.0.5', '< 3.2' gem 'listen', '>= 3.0.5', '< 3.2'
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem 'spring' gem 'spring'
@ -95,7 +92,7 @@ end
group :test do group :test do
# Adds support for Capybara system testing and selenium driver # Adds support for Capybara system testing and selenium driver
gem 'capybara', '>= 2.15', '< 4.0' gem 'capybara', '>= 2.15'
gem 'selenium-webdriver' gem 'selenium-webdriver'
gem 'webdrivers' gem 'webdrivers'
gem 'launchy' gem 'launchy'

View File

@ -1,47 +1,61 @@
GEM GEM
remote: https://rubygems.org/ remote: https://rubygems.org/
specs: specs:
actioncable (5.2.3) actioncable (6.0.0)
actionpack (= 5.2.3) actionpack (= 6.0.0)
nio4r (~> 2.0) nio4r (~> 2.0)
websocket-driver (>= 0.6.1) websocket-driver (>= 0.6.1)
actionmailer (5.2.3) actionmailbox (6.0.0)
actionpack (= 5.2.3) actionpack (= 6.0.0)
actionview (= 5.2.3) activejob (= 6.0.0)
activejob (= 5.2.3) activerecord (= 6.0.0)
activestorage (= 6.0.0)
activesupport (= 6.0.0)
mail (>= 2.7.1)
actionmailer (6.0.0)
actionpack (= 6.0.0)
actionview (= 6.0.0)
activejob (= 6.0.0)
mail (~> 2.5, >= 2.5.4) mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
actionpack (5.2.3) actionpack (6.0.0)
actionview (= 5.2.3) actionview (= 6.0.0)
activesupport (= 5.2.3) activesupport (= 6.0.0)
rack (~> 2.0) rack (~> 2.0)
rack-test (>= 0.6.3) rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2) rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionview (5.2.3) actiontext (6.0.0)
activesupport (= 5.2.3) actionpack (= 6.0.0)
activerecord (= 6.0.0)
activestorage (= 6.0.0)
activesupport (= 6.0.0)
nokogiri (>= 1.8.5)
actionview (6.0.0)
activesupport (= 6.0.0)
builder (~> 3.1) builder (~> 3.1)
erubi (~> 1.4) erubi (~> 1.4)
rails-dom-testing (~> 2.0) rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3) rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (5.2.3) activejob (6.0.0)
activesupport (= 5.2.3) activesupport (= 6.0.0)
globalid (>= 0.3.6) globalid (>= 0.3.6)
activemodel (5.2.3) activemodel (6.0.0)
activesupport (= 5.2.3) activesupport (= 6.0.0)
activerecord (5.2.3) activerecord (6.0.0)
activemodel (= 5.2.3) activemodel (= 6.0.0)
activesupport (= 5.2.3) activesupport (= 6.0.0)
arel (>= 9.0) activestorage (6.0.0)
activestorage (5.2.3) actionpack (= 6.0.0)
actionpack (= 5.2.3) activejob (= 6.0.0)
activerecord (= 5.2.3) activerecord (= 6.0.0)
marcel (~> 0.3.1) marcel (~> 0.3.1)
activesupport (5.2.3) activesupport (6.0.0)
concurrent-ruby (~> 1.0, >= 1.0.2) concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
minitest (~> 5.1) minitest (~> 5.1)
tzinfo (~> 1.1) tzinfo (~> 1.1)
zeitwerk (~> 2.1, >= 2.1.8)
addressable (2.6.0) addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0) public_suffix (>= 2.0.2, < 4.0)
airbrussh (1.3.3) airbrussh (1.3.3)
@ -49,15 +63,18 @@ GEM
annotate (2.7.5) annotate (2.7.5)
activerecord (>= 3.2, < 7.0) activerecord (>= 3.2, < 7.0)
rake (>= 10.4, < 13.0) rake (>= 10.4, < 13.0)
arel (9.0.0)
ast (2.4.0) ast (2.4.0)
autoprefixer-rails (9.6.1.1)
execjs
bcrypt (3.1.13) bcrypt (3.1.13)
bcrypt_pbkdf (1.0.1) bcrypt_pbkdf (1.0.1)
bindex (0.8.1) bindex (0.8.1)
binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
bootsnap (1.4.4) bootsnap (1.4.4)
msgpack (~> 1.0) msgpack (~> 1.0)
bootstrap (4.3.1)
autoprefixer-rails (>= 9.1.0)
popper_js (>= 1.14.3, < 2)
sassc-rails (>= 2.0.0)
builder (3.2.3) builder (3.2.3)
byebug (11.0.1) byebug (11.0.1)
capistrano (3.11.0) capistrano (3.11.0)
@ -73,10 +90,10 @@ GEM
capistrano-rbenv (2.1.4) capistrano-rbenv (2.1.4)
capistrano (~> 3.1) capistrano (~> 3.1)
sshkit (~> 1.3) sshkit (~> 1.3)
capistrano3-puma (3.1.1) capistrano3-puma (4.0.0)
capistrano (~> 3.7) capistrano (~> 3.7)
capistrano-bundler capistrano-bundler
puma (~> 3.4) puma (~> 4.0)
capybara (3.28.0) capybara (3.28.0)
addressable addressable
mini_mime (>= 0.1.3) mini_mime (>= 0.1.3)
@ -92,11 +109,10 @@ GEM
concurrent-ruby (1.1.5) concurrent-ruby (1.1.5)
crass (1.0.4) crass (1.0.4)
database_cleaner (1.7.0) database_cleaner (1.7.0)
debug_inspector (0.0.3) devise (4.7.0)
devise (4.6.2)
bcrypt (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
railties (>= 4.1.0, < 6.0) railties (>= 4.1.0)
responders responders
warden (~> 1.2.3) warden (~> 1.2.3)
devise-i18n (1.8.1) devise-i18n (1.8.1)
@ -198,6 +214,7 @@ GEM
parallel (1.17.0) parallel (1.17.0)
parser (2.6.3.0) parser (2.6.3.0)
ast (~> 2.4.0) ast (~> 2.4.0)
popper_js (1.14.5)
powerpack (0.1.2) powerpack (0.1.2)
pry (0.12.2) pry (0.12.2)
coderay (~> 1.1.0) coderay (~> 1.1.0)
@ -208,7 +225,8 @@ GEM
pry-rails (0.3.9) pry-rails (0.3.9)
pry (>= 0.10.4) pry (>= 0.10.4)
public_suffix (3.1.1) public_suffix (3.1.1)
puma (3.12.1) puma (4.1.0)
nio4r (~> 2.0)
pundit (1.1.0) pundit (1.1.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
rack (2.0.7) rack (2.0.7)
@ -218,33 +236,35 @@ GEM
rack rack
rack-test (1.1.0) rack-test (1.1.0)
rack (>= 1.0, < 3) rack (>= 1.0, < 3)
rails (5.2.3) rails (6.0.0)
actioncable (= 5.2.3) actioncable (= 6.0.0)
actionmailer (= 5.2.3) actionmailbox (= 6.0.0)
actionpack (= 5.2.3) actionmailer (= 6.0.0)
actionview (= 5.2.3) actionpack (= 6.0.0)
activejob (= 5.2.3) actiontext (= 6.0.0)
activemodel (= 5.2.3) actionview (= 6.0.0)
activerecord (= 5.2.3) activejob (= 6.0.0)
activestorage (= 5.2.3) activemodel (= 6.0.0)
activesupport (= 5.2.3) activerecord (= 6.0.0)
activestorage (= 6.0.0)
activesupport (= 6.0.0)
bundler (>= 1.3.0) bundler (>= 1.3.0)
railties (= 5.2.3) railties (= 6.0.0)
sprockets-rails (>= 2.0.0) sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3) rails-dom-testing (2.0.3)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
nokogiri (>= 1.6) nokogiri (>= 1.6)
rails-html-sanitizer (1.2.0) rails-html-sanitizer (1.2.0)
loofah (~> 2.2, >= 2.2.2) loofah (~> 2.2, >= 2.2.2)
rails-i18n (5.1.3) rails-i18n (6.0.0)
i18n (>= 0.7, < 2) i18n (>= 0.7, < 2)
railties (>= 5.0, < 6) railties (>= 6.0.0, < 7)
railties (5.2.3) railties (6.0.0)
actionpack (= 5.2.3) actionpack (= 6.0.0)
activesupport (= 5.2.3) activesupport (= 6.0.0)
method_source method_source
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0) thor (>= 0.20.3, < 2.0)
rainbow (3.0.0) rainbow (3.0.0)
rake (12.3.3) rake (12.3.3)
rb-fsevent (0.10.3) rb-fsevent (0.10.3)
@ -253,9 +273,9 @@ GEM
rbnacl (4.0.2) rbnacl (4.0.2)
ffi ffi
regexp_parser (1.6.0) regexp_parser (1.6.0)
responders (2.4.1) responders (3.0.0)
actionpack (>= 4.2.0, < 6.0) actionpack (>= 5.0)
railties (>= 4.2.0, < 6.0) railties (>= 5.0)
rubocop (0.56.0) rubocop (0.56.0)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 2.5) parser (>= 2.5)
@ -271,12 +291,20 @@ GEM
sass-listen (4.0.0) sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4) rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7) rb-inotify (~> 0.9, >= 0.9.7)
sass-rails (5.0.7) sass-rails (5.1.0)
railties (>= 4.0.0, < 6) railties (>= 5.2.0)
sass (~> 3.1) sass (~> 3.1)
sprockets (>= 2.8, < 4.0) sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0) sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3) tilt (>= 1.1, < 3)
sassc (2.1.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
selenium-webdriver (3.142.3) selenium-webdriver (3.142.3)
childprocess (>= 0.5, < 2.0) childprocess (>= 0.5, < 2.0)
rubyzip (~> 1.2, >= 1.2.2) rubyzip (~> 1.2, >= 1.2.2)
@ -311,21 +339,19 @@ GEM
turbolinks-source (5.2.0) turbolinks-source (5.2.0)
tzinfo (1.2.5) tzinfo (1.2.5)
thread_safe (~> 0.1) thread_safe (~> 0.1)
uglifier (4.1.20)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.6.0) unicode-display_width (1.6.0)
warden (1.2.8) warden (1.2.8)
rack (>= 2.0.6) rack (>= 2.0.6)
web-console (3.7.0) web-console (4.0.1)
actionview (>= 5.0) actionview (>= 6.0.0)
activemodel (>= 5.0) activemodel (>= 6.0.0)
bindex (>= 0.4.0) bindex (>= 0.4.0)
railties (>= 5.0) railties (>= 6.0.0)
webdrivers (4.1.2) webdrivers (4.1.2)
nokogiri (~> 1.6) nokogiri (~> 1.6)
rubyzip (~> 1.0) rubyzip (~> 1.0)
selenium-webdriver (>= 3.0, < 4.0) selenium-webdriver (>= 3.0, < 4.0)
webpacker (3.6.0) webpacker (4.0.7)
activesupport (>= 4.2) activesupport (>= 4.2)
rack-proxy (>= 0.6.1) rack-proxy (>= 0.6.1)
railties (>= 4.2) railties (>= 4.2)
@ -336,6 +362,7 @@ GEM
chronic (>= 0.6.3) chronic (>= 0.6.3)
xpath (3.2.0) xpath (3.2.0)
nokogiri (~> 1.8) nokogiri (~> 1.8)
zeitwerk (2.1.9)
PLATFORMS PLATFORMS
ruby ruby
@ -344,23 +371,24 @@ DEPENDENCIES
annotate annotate
bcrypt (~> 3.1.7) bcrypt (~> 3.1.7)
bcrypt_pbkdf (>= 1.0, < 2.0) bcrypt_pbkdf (>= 1.0, < 2.0)
binding_of_caller bootsnap (>= 1.4.2)
bootsnap (>= 1.1.0) bootstrap (~> 4.3.1)
byebug
capistrano (~> 3.10) capistrano (~> 3.10)
capistrano-rails (~> 1.4) capistrano-rails (~> 1.4)
capistrano-rbenv capistrano-rbenv
capistrano3-puma capistrano3-puma
capybara (>= 2.15, < 4.0) capybara (>= 2.15)
database_cleaner database_cleaner
devise (~> 4.4) devise (~> 4.7)
devise-i18n (~> 1.6) devise-i18n (~> 1.8)
ed25519 (>= 1.2, < 2.0) ed25519 (>= 1.2, < 2.0)
factory_bot_rails (~> 5.0) factory_bot_rails (~> 5.0)
guard guard
guard-minitest guard-minitest
has_scope has_scope
hashie hashie
jbuilder (~> 2.5) jbuilder (~> 2.7)
kaminari kaminari
launchy launchy
letter_opener_web letter_opener_web
@ -372,15 +400,14 @@ DEPENDENCIES
open4 open4
pry-byebug pry-byebug
pry-rails pry-rails
puma (~> 3.11) puma (~> 4.0)
pundit (~> 1.1) pundit (~> 1.1)
rack-contrib rack-contrib
rails (~> 5.2.0) rails (= 6.0.0)
rails-i18n (~> 5.1) rails-i18n (~> 6.0.0)
rbnacl (>= 3.2, < 5.0) rbnacl (>= 3.2, < 5.0)
responders (~> 2.4.1)
rubocop (~> 0.56.0) rubocop (~> 0.56.0)
sass-rails (= 5.0.7) sass-rails (~> 5)
selenium-webdriver selenium-webdriver
simple_form (~> 4.0) simple_form (~> 4.0)
simplecov simplecov
@ -388,14 +415,13 @@ DEPENDENCIES
spring-watcher-listen (~> 2.0.0) spring-watcher-listen (~> 2.0.0)
turbolinks (~> 5) turbolinks (~> 5)
tzinfo-data tzinfo-data
uglifier (>= 1.3.0) web-console (~> 4.0)
web-console (>= 3.3.0)
webdrivers webdrivers
webpacker (~> 3.5) webpacker (~> 4.0)
whenever whenever
RUBY VERSION RUBY VERSION
ruby 2.3.3p222 ruby 2.6.3p62
BUNDLED WITH BUNDLED WITH
1.17.2 1.17.2

View File

@ -3,15 +3,15 @@
## Requirements ## Requirements
Chexpire requires : Chexpire requires :
* Ruby > 2.3.3 and Bundler * Ruby > 2.5.4 and Bundler
* NodeJS and Yarn * NodeJS and Yarn
* MySQL or MariaDB * MySQL or MariaDB
We are usually running Chexpire on typical POSIX servers like : We are usually running Chexpire on typical POSIX servers like :
- Linux Debian 9, Ruby 2.5.1, NodeJS 8.11 and MariaDB 10.1 - Linux Debian 9, Ruby 2.5.4, NodeJS 8.11 and MariaDB 10.1
- macOS High Sierra, Ruby 2.5.1, NodeJS 10.2.1 and MariaDB 10.2 - macOS High Sierra, Ruby 2.5.4, NodeJS 10.2.1 and MariaDB 10.2
It probably works on any system that supports Ruby >2.3, NodeJS >6 and MySQL >5.5. Feel free to report any unexpected incompatibilities. It probably works on any system that supports Ruby >= 2.5.4, NodeJS >= 6 and MySQL >= 5.5. Feel free to report any unexpected incompatibilities.
If you use rbenv, chruby or RVM, you can set your prefered Ruby version in the `.ruby-version` file at the root of the project. If you use rbenv, chruby or RVM, you can set your prefered Ruby version in the `.ruby-version` file at the root of the project.
@ -21,7 +21,7 @@ If you are familiar with Ansible, you can use our [Ansible roles](http://forge.e
[…] […]
roles: roles:
- mysql - mysql
- { role: rbenv, username: "{{ ansible_user }}", rbenv_ruby_version: "2.5.1" } - { role: rbenv, username: "{{ ansible_user }}", rbenv_ruby_version: "2.5.4" }
- { role: nodejs, nodejs_install_yarn: yes } - { role: nodejs, nodejs_install_yarn: yes }
[…] […]
``` ```
@ -34,7 +34,7 @@ If you want to do manual installations, you can use our Wiki documentations for
Execute `# bundle install` to install Ruby gems (including Rails itself). Execute `# bundle install` to install Ruby gems (including Rails itself).
Execute `# yarn install` to install Javascript/NodeJS packages. Execute `# yarn install --check-files` to install Javascript/NodeJS packages.
Depending on what is already installed on your OS or not, you might need to install a few system packages to be able to have everything working. Depending on what is already installed on your OS or not, you might need to install a few system packages to be able to have everything working.
@ -45,15 +45,21 @@ To use elliptic curve SSH keys, we need to have `libsodium` and its headers.
* on macOS with Homebrew : `# brew install libsodium`. * on macOS with Homebrew : `# brew install libsodium`.
## Rails configuration ## Application configuration
After cloning this repository, you have to create and edit a few files for your local development/test configuration. Theses files will be ignored by git. After cloning this repository, you have to create and edit a few files for your local development/test configuration. Theses files will be ignored by git.
### Environment variables
A handful of settings can be set by environment variables. If you use Heroku-like platforms they offer a simple way to set them.
If you use Rbenv, there is the `rbenv-vars` plugin. That is what we recommend on POSIX servers. You have to put an `.rbenv-vars` file at the root of the project. If you use Capistrano, put it in the shared directory and have it linked in the `current` directory at deploy time.
### Database configuration ### Database configuration
Create the file if missing : `cp config/database.example.yml config/database.yml`. If you change the settings in the `defaults` section it applies to the `development` and `test` sections. More information is available at "guides.rubyonrails.org":https://guides.rubyonrails.org/configuring.html#configuring-a-database Create the file if missing : `cp config/database.example.yml config/database.yml`. If you change the settings in the `defaults` section it applies to the `development` and `test` sections. More information is available at "guides.rubyonrails.org":https://guides.rubyonrails.org/configuring.html#configuring-a-database
Note that on Debian 9 with MariaDB, the database socket is at `/var/run/mysqld/mysqld.sock`, which is not the default in the configuration file. Note that on Debian 9+ with MariaDB, the database socket is at `/var/run/mysqld/mysqld.sock`, which is not the default in the configuration file.
### Rails secrets ### Rails secrets
@ -63,7 +69,7 @@ Create the file if missing : `cp config/secrets.example.yml config/secrets.yml`.
Create the file if missing : `cp config/chexpire.example.yml config/chexpire.yml`. Set at least the `mailer_default_from` and `host` variables. See other configuration overridable in `config/chexpire.defaults.yml`. Create the file if missing : `cp config/chexpire.example.yml config/chexpire.yml`. Set at least the `mailer_default_from` and `host` variables. See other configuration overridable in `config/chexpire.defaults.yml`.
## Database ## Database
You need databases for development and tests. You can create them like this (once connected to you MySQL server) : You need databases for development and tests. You can create them like this (once connected to you MySQL server) :
@ -75,8 +81,8 @@ MariaDB [none]> CREATE DATABASE `chexpire_test`;
If you don't want to use the default `root` MySQL user with no password, you can create users : If you don't want to use the default `root` MySQL user with no password, you can create users :
``` ```
MariaDB [none]> GRANT ALL PRIVILEGES ON `chexpire_development`.* TO `chexpire_development`@localhost IDENTIFIED BY 'MY_PASSWORD_FOR_DEV'; MariaDB [none]> GRANT ALL PRIVILEGES ON `chexpire_development%`.* TO `chexpire_development`@localhost IDENTIFIED BY 'MY_PASSWORD_FOR_DEV';
MariaDB [none]> GRANT ALL PRIVILEGES ON `chexpire_test`.* TO `chexpire_test`@localhost IDENTIFIED BY 'MY_PASSWORD_FOR_TEST'; MariaDB [none]> GRANT ALL PRIVILEGES ON `chexpire_test%`.* TO `chexpire_test`@localhost IDENTIFIED BY 'MY_PASSWORD_FOR_TEST';
MariaDB [none]> FLUSH PRIVILEGES; MariaDB [none]> FLUSH PRIVILEGES;
``` ```
@ -113,3 +119,17 @@ You can use the `script/to_staging` and/or `script/to_production` scripts.
* with `to_production` you deploy the `master` branch to production. * with `to_production` you deploy the `master` branch to production.
On the remote servers where the application will be deployed you have to copy the configuration files just as you've just did for your development setup. The files has to go in the `shared/config/` directory, relative to your `deploy_to` path. They will be symlinked to the proper destination by Capistrano. On the remote servers where the application will be deployed you have to copy the configuration files just as you've just did for your development setup. The files has to go in the `shared/config/` directory, relative to your `deploy_to` path. They will be symlinked to the proper destination by Capistrano.
If an `.rbenv-vars` file is found in the shared directory, it will be linked to help loading environment files (by Ruby via Rbenv, systemd…).
### systemd
If you want to use systemd to manage your Puma process, there are [a few different ways](https://github.com/puma/puma/blob/master/docs/systemd.md). We've prepared a systemd unit file (`config/deploy/puma-chexpire@.service`) but you can adjust to better suit your needs.
If you deploy your application to `/home/chexpire_<environment>`, the systemd unit can be used as a template, for example : `puma-chexpire@production.service`. This template is compatible with systemd actions like `systemctl stop puma-chexpire@production.service` and also with Capistrano tasks like `cap production puma:stop`.
To install the systemd unit :
```
$ cp config/deploy/puma-chexpire@.service /etc/systemd/system/puma-chexpire@.service
$ systemctl enable puma-chexpire@<environment>.service
```

View File

@ -1 +1,2 @@
//= link_tree ../images //= link_tree ../images
//= link_directory ../stylesheets .css

View File

@ -45,6 +45,6 @@ class ApplicationController < ActionController::Base
end end
def render_404 def render_404
render file: "#{Rails.root}/public/404", status: :not_found render file: "#{Rails.root}/public/404.html", status: :not_found
end end
end end

View File

@ -1,15 +0,0 @@
// Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
// License: GNU AGPL-3+ (see full text in LICENSE file)
$input-placeholder-color: #b9bbbb;
$enable-rounded: false;
$theme-colors: (
"primary": #118b83, //light-green
"secondary": #013d3a, //dark-green
"tertiary": #be0c04, //red
"quaternary": #d6b20e, // yellow
"success": #118b83, //light-green
"warning": #F6AE2D,
"danger": #be0c04, //red
"info": #2E86AB,
);

View File

@ -1,4 +0,0 @@
// Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
// License: GNU AGPL-3+ (see full text in LICENSE file)
import './index.scss';

View File

@ -6,27 +6,25 @@
// present in this directory. You're encouraged to place your actual application logic in // present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference // a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled. // that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
import Rails from 'rails-ujs'; require("@rails/ujs").start()
import Turbolinks from 'turbolinks'; require("turbolinks").start()
// require("@rails/activestorage").start()
// require("channels")
import 'bootstrap/js/dist/collapse'; import 'bootstrap'
import 'bootstrap/js/dist/dropdown'; import '../stylesheets/application'
import 'bootstrap/js/dist/button';
import 'bootstrap/js/dist/tooltip';
import '../scss';
import checkValidationInitialize from '../components/check_validation'; import checkValidationInitialize from '../components/check_validation';
Rails.start()
Turbolinks.start()
document.addEventListener("turbolinks:load", () => { document.addEventListener("turbolinks:load", () => {
$('[data-toggle="tooltip"]').tooltip(); $('[data-toggle="tooltip"]').tooltip();
checkValidationInitialize(); checkValidationInitialize();
}); });
// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)

View File

@ -0,0 +1,15 @@
// Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
// License: GNU AGPL-3+ (see full text in LICENSE file)
$input-placeholder-color: #b9bbbb;
$enable-rounded: false;
$theme-colors: (
"primary": #118b83, //light-green
"secondary": #013d3a, //dark-green
"tertiary": #be0c04, //red
"quaternary": #d6b20e, //yellow
"success": #118b83, //light-green
"warning": #F6AE2D, //orange
"danger": #be0c04, //red
"info": #2E86AB, //light-blue
);

View File

@ -1,10 +1,9 @@
// Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> @import '_custom';
// License: GNU AGPL-3+ (see full text in LICENSE file)
@import '_variables';
@import '~bootstrap/scss/bootstrap'; @import '~bootstrap/scss/bootstrap';
@import 'layout'; @import 'layout';
@import 'icons'; @import 'icons';
@import 'components/callouts'; @import 'components/callouts';
@import 'components/users'; @import 'components/users';
@import 'components/checks'; @import 'components/checks';

View File

@ -146,7 +146,7 @@ a.navbar-item.navbar-link {
.row { .row {
height: 100%; height: 100%;
} }
.homepage-img { .homepage-img {
border: 1px solid map-get($theme-colors, secondary); border: 1px solid map-get($theme-colors, secondary);
} }

View File

@ -1,4 +1,10 @@
class ApplicationJob < ActiveJob::Base class ApplicationJob < ActiveJob::Base
# Automatically retry jobs that encountered a deadlock
# retry_on ActiveRecord::Deadlocked
# Most jobs are safe to ignore if the underlying records are no longer available
# discard_on ActiveJob::DeserializationError
# from http://api.rubyonrails.org/classes/ActiveJob/Core.html # from http://api.rubyonrails.org/classes/ActiveJob/Core.html
attr_writer :attempt_number attr_writer :attempt_number

View File

@ -1,3 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file)
class SSLSyncJob < ApplicationJob class SSLSyncJob < ApplicationJob
queue_as :default queue_as :default

View File

@ -1,3 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file)
class WhoisSyncJob < ApplicationJob class WhoisSyncJob < ApplicationJob
queue_as :default queue_as :default

View File

@ -11,19 +11,15 @@ class NotificationsMailer < ApplicationMailer
end end
def domain_expires_soon def domain_expires_soon
@expire_in_days = Integer(@check.domain_expires_at.to_date - Date.today)
I18n.with_locale params&.fetch(:locale) { @check.user.locale } do I18n.with_locale params&.fetch(:locale) { @check.user.locale } do
subject = t(".subject", domain: @check.domain, count: @expire_in_days) subject = t(".subject", domain: @check.domain, count: @check.domain_expires_in_days)
mail subject: subject, to: @notification.recipient mail subject: subject, to: @notification.recipient
end end
end end
def ssl_expires_soon def ssl_expires_soon
@expire_in_days = Integer(@check.domain_expires_at.to_date - Date.today)
I18n.with_locale params&.fetch(:locale) { @check.user.locale } do I18n.with_locale params&.fetch(:locale) { @check.user.locale } do
subject = t(".subject", domain: @check.domain, count: @expire_in_days) subject = t(".subject", domain: @check.domain, count: @check.domain_expires_in_days)
mail subject: subject, to: @notification.recipient mail subject: subject, to: @notification.recipient
end end
end end

View File

@ -44,6 +44,8 @@ class Check < ApplicationRecord
enum kind: [:domain, :ssl] enum kind: [:domain, :ssl]
enum mode: [:auto, :manual] enum mode: [:auto, :manual]
# Those dates are written as UTC,
# but not converted back when read from the database
self.skip_time_zone_conversion_for_attributes = [ self.skip_time_zone_conversion_for_attributes = [
:domain_created_at, :domain_created_at,
:domain_updated_at, :domain_updated_at,
@ -82,7 +84,8 @@ class Check < ApplicationRecord
def days_from_last_success def days_from_last_success
return unless last_success_at.present? return unless last_success_at.present?
(Date.today - last_success_at.to_date).to_i # return the number of whole days
((Time.now - last_success_at) / (24 * 3600)).to_i
end end
def increment_consecutive_failures! def increment_consecutive_failures!
@ -104,6 +107,10 @@ class Check < ApplicationRecord
end end
end end
def domain_expires_in_days
Integer(domain_expires_at.to_date - Time.now.utc.to_date)
end
private private
def domain_created_at_past def domain_created_at_past

View File

@ -1,8 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "notifier/processor"
module Notifier module Notifier
class << self class << self
def process_all(configuration = nil) def process_all(configuration = nil)

View File

@ -1,6 +1,4 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "naught"
NullLogger = Naught.build NullLogger = Naught.build

View File

@ -1,13 +1,17 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "null_logger"
require "system_command"
require_relative "ssl/parser"
require_relative "ssl/response"
require_relative "ssl/errors"
module SSL module SSL
class Error < StandardError; end
class CommandError < Error; end
class ConfigurationError < Error; end
class ParserError < Error; end
class DomainNotMatchError < ParserError; end
class InvalidResponseError < ParserError; end
class InvalidDateError < ParserError; end
class << self class << self
def ask(domain, system_klass: SystemCommand, logger: NullLogger.new) def ask(domain, system_klass: SystemCommand, logger: NullLogger.new)
Service.new(domain, system_klass: system_klass, logger: logger).call Service.new(domain, system_klass: system_klass, logger: logger).call
@ -41,7 +45,7 @@ module SSL
result = command.execute result = command.execute
unless result.exit_status.zero? unless result.exit_status.zero?
fail SSLCommandError, "SSL command failed with status #{result.exit_status}" fail SSL::CommandError, "SSL command failed with status #{result.exit_status}"
end end
result result
@ -69,7 +73,7 @@ module SSL
def custom_check_http_args def custom_check_http_args
return nil unless configuration.check_http_args.present? return nil unless configuration.check_http_args.present?
fail SSLConfigurationError, "check_http_args option must be an array of argument." \ fail SSL::ConfigurationError, "check_http_args option must be an array of argument." \
unless configuration.check_http_args.is_a?(Array) unless configuration.check_http_args.is_a?(Array)
configuration.check_http_args configuration.check_http_args

View File

@ -1,14 +0,0 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file)
module SSL
class Error < StandardError; end
class SSLCommandError < Error; end
class SSLConfigurationError < Error; end
class ParserError < Error; end
class DomainNotMatchError < ParserError; end
class InvalidResponseError < ParserError; end
class InvalidDateError < ParserError; end
end

View File

@ -1,9 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "null_logger"
require "ssl/errors"
module SSL module SSL
class Parser class Parser
DATE_REGEX = /will expire on (.+)\./ DATE_REGEX = /will expire on (.+)\./

View File

@ -1,12 +1,10 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "open4"
require "null_logger"
SystemCommandResult = Struct.new(:command, :exit_status, :stdout, :stderr)
class SystemCommand class SystemCommand
Result = Struct.new(:command, :exit_status, :stdout, :stderr)
class NotAllowedError < StandardError; end
attr_reader :program attr_reader :program
attr_reader :args attr_reader :args
attr_reader :logger attr_reader :logger
@ -42,7 +40,7 @@ class SystemCommand
pid, _, stdout, stderr = Open4.popen4 cmd pid, _, stdout, stderr = Open4.popen4 cmd
_, status = Process.waitpid2 pid _, status = Process.waitpid2 pid
SystemCommandResult.new( Result.new(
syscmd, syscmd,
status.exitstatus || 255, status.exitstatus || 255,
stdout.read.strip, stdout.read.strip,

View File

@ -1,14 +1,17 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "null_logger"
require "domain_helper"
require "system_command"
require_relative "whois/parser"
require_relative "whois/response"
require_relative "whois/errors"
module Whois module Whois
class Error < StandardError; end
class CommandError < Error; end
class UnsupportedDomainError < Error; end
class DomainNotFoundError < Error; end
class ParserError < Error; end
class FieldNotFoundError < ParserError; end
class InvalidDateError < ParserError; end
class << self class << self
def ask(domain, system_klass: SystemCommand, logger: NullLogger.new) def ask(domain, system_klass: SystemCommand, logger: NullLogger.new)
Service.new(domain, system_klass: system_klass, logger: logger).call Service.new(domain, system_klass: system_klass, logger: logger).call
@ -39,7 +42,7 @@ module Whois
result = command.execute result = command.execute
unless result.exit_status.zero? unless result.exit_status.zero?
fail WhoisCommandError, "Whois command failed with status #{result.exit_status}" fail Whois::CommandError, "Whois command failed with status #{result.exit_status}"
end end
result result

View File

@ -1,14 +0,0 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file)
module Whois
class Error < StandardError; end
class WhoisCommandError < Error; end
class UnsupportedDomainError < Error; end
class DomainNotFoundError < Error; end
class ParserError < Error; end
class FieldNotFoundError < ParserError; end
class InvalidDateError < ParserError; end
end

View File

@ -1,16 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "null_logger"
require "whois/errors"
require "whois/parser/afilias"
require "whois/parser/afnic"
require "whois/parser/cira"
require "whois/parser/io"
require "whois/parser/neustar"
require "whois/parser/sonic"
require "whois/parser/verisign"
module Whois module Whois
module Parser module Parser
PARSERS = [ PARSERS = [

View File

@ -1,10 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "domain_helper"
require "whois/errors"
require_relative "base"
module Whois module Whois
module Parser module Parser
class Afilias < Base class Afilias < Base

View File

@ -1,10 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "domain_helper"
require "whois/errors"
require_relative "base"
module Whois module Whois
module Parser module Parser
class AFNIC < Base class AFNIC < Base

View File

@ -1,10 +1,7 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "null_logger"
require_relative "../response" require_relative "../response"
require_relative "../errors"
require_relative "entry_builder"
module Whois module Whois
module Parser module Parser

View File

@ -1,10 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "domain_helper"
require "whois/errors"
require_relative "base"
module Whois module Whois
module Parser module Parser
class CIRA < Base class CIRA < Base

View File

@ -1,8 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require_relative "base"
module Whois module Whois
module Parser module Parser
module Entry module Entry

View File

@ -1,8 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require_relative "base"
module Whois module Whois
module Parser module Parser
module Entry module Entry

View File

@ -1,8 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require_relative "base"
module Whois module Whois
module Parser module Parser
module Entry module Entry

View File

@ -1,10 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require_relative "entry/blank"
require_relative "entry/field"
require_relative "entry/text"
module Whois module Whois
module Parser module Parser
class EntryBuilder class EntryBuilder

View File

@ -1,10 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "domain_helper"
require "whois/errors"
require_relative "base"
module Whois module Whois
module Parser module Parser
class IO < Base class IO < Base

View File

@ -1,10 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "domain_helper"
require "whois/errors"
require_relative "base"
module Whois module Whois
module Parser module Parser
class Neustar < Base class Neustar < Base

View File

@ -1,10 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "domain_helper"
require "whois/errors"
require_relative "base"
module Whois module Whois
module Parser module Parser
class Sonic < Base class Sonic < Base

View File

@ -1,10 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "domain_helper"
require "whois/errors"
require_relative "base"
module Whois module Whois
module Parser module Parser
class Verisign < Base class Verisign < Base

View File

@ -33,7 +33,7 @@
</div> </div>
<div class="col-auto"> <div class="col-auto">
<%= link_to Octicons::Octicon.new("x").to_svg.html_safe, checks_path, class: "btn btn-danger btn-sm btn-outline-danger" %> <%= link_to Octicons::Octicon.new("x").to_svg.html_safe, checks_path, class: "btn btn-sm btn-outline-danger" %>
</div> </div>
</div> </div>

View File

@ -1,63 +1,62 @@
<% # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> %> <% # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> %>
<% # License: GNU AGPL-3+ (see full text in LICENSE file) %> <% # License: GNU AGPL-3+ (see full text in LICENSE file) %>
<nav class="navbar navbar-expand-lg navbar-dark justify-content-between"> <nav class="navbar navbar-expand-lg navbar-dark justify-content-between">
<div class="container-fluid"> <div class="container-fluid">
<%= link_to (user_signed_in? ? checks_path : root_path), class: "navbar-brand" do %> <%= link_to (user_signed_in? ? checks_path : root_path), class: "navbar-brand" do %>
<%= image_tag 'chexpire10.png', width: 200, alt: 'chexpire logo' %> <%= image_tag 'chexpire10.png', width: 200, alt: 'chexpire logo' %>
<% end %> <% end %>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<div class="collapse navbar-collapse" id="navbarSupportedContent"> <div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto"> <ul class="navbar-nav mr-auto">
<% if user_signed_in? %> <% if user_signed_in? %>
<li class="nav-item"> <li class="nav-item">
<%= link_to(t(".my_checks"), checks_path, class: "nav-link") %> <%= link_to(t(".my_checks"), checks_path, class: "nav-link") %>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<%= link_to(t(".new_domain_check"), new_check_path(kind: :domain), class: "nav-link") %> <%= link_to(t(".new_domain_check"), new_check_path(kind: :domain), class: "nav-link") %>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<%= link_to(t(".new_ssl_check"), new_check_path(kind: :ssl), class: "nav-link") %> <%= link_to(t(".new_ssl_check"), new_check_path(kind: :ssl), class: "nav-link") %>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<%= link_to(t(".my_notifications"), notifications_path, class: "nav-link") %> <%= link_to(t(".my_notifications"), notifications_path, class: "nav-link") %>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<%= link_to("GitHub", "https://github.com/Evolix/chexpire", class: "nav-link") %> <%= link_to("GitHub", "https://github.com/Evolix/chexpire", class: "nav-link") %>
</li> </li>
<% end %> <% end %>
</ul> </ul>
<div class="my-2 my-lg-0"> <div class="my-2 my-lg-0">
<% if user_signed_in? %> <% if user_signed_in? %>
<div class="navbar-item">
<div class="navbar-item"> <div class="dropdown">
<div class="dropdown"> <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <%= current_user.email %>
<%= current_user.email %> </a>
</a> <div class="dropdown-menu" aria-labelledby="navbarDropdown">
<div class="dropdown-menu" aria-labelledby="navbarDropdown"> <%= link_to edit_user_registration_path, class: "dropdown-item" do %>
<%= link_to edit_user_registration_path, class: "dropdown-item" do %>
<i class="fa fa-user"></i> <i class="fa fa-user"></i>
<%= t(".profile", default: "Profile") %> <%= t(".profile", default: "Profile") %>
<% end %> <% end %>
<%= link_to destroy_user_session_path, method: :delete, class: "dropdown-item" do %> <%= link_to destroy_user_session_path, method: :delete, class: "dropdown-item" do %>
<i class="fa fa-sign-out"></i> <i class="fa fa-sign-out"></i>
<%= t(".sign_out", default: "Sign out") %> <%= t(".sign_out", default: "Sign out") %>
<% end %> <% end %>
</div>
</div> </div>
</div> </div>
</div> <% else %>
<% else %> <!-- Login link (when logged out) -->
<!-- Login link (when logged out) --> <%= link_to t(".sign_in"), new_user_session_path, class: "navbar-item navbar-link" %>
<%= link_to t(".sign_in"), new_user_session_path, class: "navbar-item navbar-link" %> <%= link_to t(".sign_up"), new_user_registration_path, class: "navbar-item navbar-link" %>
<%= link_to t(".sign_up"), new_user_registration_path, class: "navbar-item navbar-link" %> <%= link_to "GitHub", "https://github.com/Evolix/chexpire", class: "navbar-item navbar-link" %>
<%= link_to "GitHub", "https://github.com/Evolix/chexpire", class: "navbar-item navbar-link" %> <% end %>
<% end %> </div>
</div> </div>
</div> </div>
</div>
</nav> </nav>

72
babel.config.js Normal file
View File

@ -0,0 +1,72 @@
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 && [
require('@babel/preset-env').default,
{
targets: {
node: 'current'
}
}
],
(isProductionEnv || isDevelopmentEnv) && [
require('@babel/preset-env').default,
{
forceAllTransforms: true,
useBuiltIns: 'entry',
corejs: 3,
modules: false,
exclude: ['transform-typeof-symbol']
}
]
].filter(Boolean),
plugins: [
require('babel-plugin-macros'),
require('@babel/plugin-syntax-dynamic-import').default,
isTestEnv && require('babel-plugin-dynamic-import-node'),
require('@babel/plugin-transform-destructuring').default,
[
require('@babel/plugin-proposal-class-properties').default,
{
loose: true
}
],
[
require('@babel/plugin-proposal-object-rest-spread').default,
{
useBuiltIns: true
}
],
[
require('@babel/plugin-transform-runtime').default,
{
helpers: false,
regenerator: true,
corejs: false
}
],
[
require('@babel/plugin-transform-regenerator').default,
{
async: false
}
]
].filter(Boolean)
}
}

View File

@ -1,3 +1,105 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) # frozen_string_literal: true
load Gem.bin_path('bundler', 'bundle')
#
# 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 || ">= 0.a"
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_version
@bundler_version ||= begin
env_var_version || cli_arg_version ||
lockfile_version || "#{Gem::Requirement.default}.a"
end
end
def load_bundler!
ENV["BUNDLE_GEMFILE"] ||= gemfile
# must dup string for RG < 1.8 compatibility
activate_bundler(bundler_version.dup)
end
def activate_bundler(bundler_version)
if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
bundler_version = "< 2"
end
gem_error = activation_error_handling do
gem "bundler", bundler_version
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_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
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

View File

@ -1,9 +1,4 @@
#!/usr/bin/env ruby #!/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__) APP_PATH = File.expand_path('../config/application', __dir__)
require_relative '../config/boot' require_relative '../config/boot'
require 'rails/commands' require 'rails/commands'

View File

@ -1,9 +1,4 @@
#!/usr/bin/env ruby #!/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_relative '../config/boot'
require 'rake' require 'rake'
Rake.application.run Rake.application.run

View File

@ -1,6 +1,5 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require 'fileutils' require 'fileutils'
include FileUtils
# path to your application root. # path to your application root.
APP_ROOT = File.expand_path('..', __dir__) APP_ROOT = File.expand_path('..', __dir__)
@ -9,24 +8,25 @@ def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==") system(*args) || abort("\n== Command #{args} failed ==")
end end
chdir APP_ROOT do FileUtils.chdir APP_ROOT do
# This script is a starting point to setup your application. # This script is a way to setup or update your development environment automatically.
# This script is idempotent, so that you can run it at anytime and get an expectable outcome.
# Add necessary setup steps to this file. # Add necessary setup steps to this file.
puts '== Installing dependencies ==' puts '== Installing dependencies =='
system! 'gem install bundler --conservative' system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install') system('bundle check') || system!('bundle install')
# Install JavaScript dependencies if using Yarn # Install JavaScript dependencies
# system('bin/yarn') # system('bin/yarn')
# puts "\n== Copying sample files ==" # puts "\n== Copying sample files =="
# unless File.exist?('config/database.yml') # unless File.exist?('config/database.yml')
# cp 'config/database.yml.sample', 'config/database.yml' # FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
# end # end
puts "\n== Preparing database ==" puts "\n== Preparing database =="
system! 'bin/rails db:setup' system! 'bin/rails db:prepare'
puts "\n== Removing old logs and tempfiles ==" puts "\n== Removing old logs and tempfiles =="
system! 'bin/rails log:clear tmp:clear' system! 'bin/rails log:clear tmp:clear'

View File

@ -1,6 +1,5 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
require 'fileutils' require 'fileutils'
include FileUtils
# path to your application root. # path to your application root.
APP_ROOT = File.expand_path('..', __dir__) APP_ROOT = File.expand_path('..', __dir__)
@ -9,7 +8,7 @@ def system!(*args)
system(*args) || abort("\n== Command #{args} failed ==") system(*args) || abort("\n== Command #{args} failed ==")
end end
chdir APP_ROOT do FileUtils.chdir APP_ROOT do
# This script is a way to update your development environment automatically. # This script is a way to update your development environment automatically.
# Add necessary update steps to this file. # Add necessary update steps to this file.
@ -17,15 +16,15 @@ chdir APP_ROOT do
system! 'gem install bundler --conservative' system! 'gem install bundler --conservative'
system('bundle check') || system!('bundle install') system('bundle check') || system!('bundle install')
# Install JavaScript dependencies if using Yarn # Install JavaScript dependencies
# system('bin/yarn') # system('bin/yarn')
puts "\n== Updating database ==" puts "\n== Updating database =="
system! 'bin/rails db:migrate' system! 'rails db:migrate'
puts "\n== Removing old logs and tempfiles ==" puts "\n== Removing old logs and tempfiles =="
system! 'bin/rails log:clear tmp:clear' system! 'rails log:clear tmp:clear'
puts "\n== Restarting application server ==" puts "\n== Restarting application server =="
system! 'bin/rails restart' system! 'rails restart'
end end

View File

@ -12,4 +12,8 @@ require "bundler/setup"
require "webpacker" require "webpacker"
require "webpacker/webpack_runner" require "webpacker/webpack_runner"
Webpacker::WebpackRunner.run(ARGV)
APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do
Webpacker::WebpackRunner.run(ARGV)
end

View File

@ -12,4 +12,8 @@ require "bundler/setup"
require "webpacker" require "webpacker"
require "webpacker/dev_server_runner" require "webpacker/dev_server_runner"
Webpacker::DevServerRunner.run(ARGV)
APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do
Webpacker::DevServerRunner.run(ARGV)
end

View File

@ -1,4 +1,4 @@
require_relative "boot" require_relative 'boot'
require "rails" require "rails"
# Pick the frameworks you want: # Pick the frameworks you want:
@ -7,6 +7,8 @@ require "active_job/railtie"
require "active_record/railtie" require "active_record/railtie"
require "active_storage/engine" require "active_storage/engine"
require "action_controller/railtie" require "action_controller/railtie"
# require "action_mailbox/engine"
# require "action_text/engine"
require "action_mailer/railtie" require "action_mailer/railtie"
require "action_view/railtie" require "action_view/railtie"
# require "action_cable/engine" # require "action_cable/engine"
@ -20,7 +22,7 @@ Bundler.require(*Rails.groups)
module Chexpire module Chexpire
class Application < Rails::Application class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version. # Initialize configuration defaults for originally generated Rails version.
config.load_defaults 5.2 config.load_defaults 6.0
# Settings in config/environments/* take precedence over those specified here. # Settings in config/environments/* take precedence over those specified here.
# Application configuration can go into files in config/initializers # Application configuration can go into files in config/initializers
@ -41,3 +43,6 @@ module Chexpire
config.chexpire = Hashie::Mash.new(config_for(:"chexpire.defaults").deep_merge(config_for(:chexpire))) config.chexpire = Hashie::Mash.new(config_for(:"chexpire.defaults").deep_merge(config_for(:chexpire)))
end end
end end
### Uncomment this to have zeitwerk debug log printed in stdout.
# Rails.autoloaders.logger = method(:puts)

View File

@ -24,12 +24,16 @@ set :repo_url, "https://github.com/Evolix/chexpire.git"
# Default value for :linked_files is [] # Default value for :linked_files is []
append :linked_files, append :linked_files,
".rbenv-vars",
"config/chexpire.yml", "config/chexpire.yml",
"config/database.yml", "config/database.yml",
"config/secrets.yml" "config/secrets.yml"
# Default value for linked_dirs is [] # Default value for linked_dirs is []
# append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system" # append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "public/system"
append :linked_dirs,
"tmp/pids",
"tmp/sockets"
# Default value for default_env is {} # Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" } # set :default_env, { path: "/opt/ruby/bin:$PATH" }

View File

@ -0,0 +1,21 @@
[Unit]
Description=Puma Server for Chexpire (%i)
After=network.target
[Service]
Type=forking
User=chexpire_%i
EnvironmentFile=/home/chexpire_%i/www/current/.rbenv-vars
Environment=RAILS_ENV=%i
WorkingDirectory=/home/chexpire_%i/www/current/
PIDFile=/home/chexpire_%i/www/shared/tmp/pids/puma.pid
ExecStart=/home/chexpire_%i/.rbenv/bin/rbenv exec bundle exec puma -C /home/chexpire_%i/www/current/config/puma.rb --daemon
ExecStop=/home/chexpire_%i/.rbenv/bin/rbenv exec bundle exec pumactl -F /home/chexpire_%i/www/current/config/puma.rb stop
ExecReload=/home/chexpire_%i/.rbenv/bin/rbenv exec bundle exec pumactl -F /home/chexpire_%i/www/current/config/puma.rb phased-restart
Restart=no
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@ -20,6 +20,7 @@ Rails.application.configure do
# Run rails dev:cache to toggle caching. # Run rails dev:cache to toggle caching.
if Rails.root.join('tmp', 'caching-dev.txt').exist? if Rails.root.join('tmp', 'caching-dev.txt').exist?
config.action_controller.perform_caching = true config.action_controller.perform_caching = true
config.action_controller.enable_fragment_cache_logging = true
config.cache_store = :memory_store config.cache_store = :memory_store
config.public_file_server.headers = { config.public_file_server.headers = {
@ -31,7 +32,7 @@ Rails.application.configure do
config.cache_store = :null_store config.cache_store = :null_store
end end
# Store uploaded files on the local file system (see config/storage.yml for options) # Store uploaded files on the local file system (see config/storage.yml for options).
config.active_storage.service = :local config.active_storage.service = :local
config.action_mailer.delivery_method = :letter_opener_web config.action_mailer.delivery_method = :letter_opener_web
@ -58,14 +59,14 @@ Rails.application.configure do
config.active_record.verbose_query_logs = true config.active_record.verbose_query_logs = true
# Debug mode disables concatenation and preprocessing of assets. # Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant intervals in view rendering with a large # This option may cause significant delays in view rendering with a large
# number of complex assets. # number of complex assets.
config.assets.debug = true config.assets.debug = true
# Suppress logger output for asset requests. # Suppress logger output for asset requests.
config.assets.quiet = true config.assets.quiet = true
# Raises error for missing translations # Raises error for missing translations.
# config.action_view.raise_on_missing_translations = true # config.action_view.raise_on_missing_translations = true
# Use an evented file watcher to asynchronously detect changes in source code, # Use an evented file watcher to asynchronously detect changes in source code,

View File

@ -24,15 +24,12 @@ Rails.application.configure do
# Apache or NGINX already handles this. # Apache or NGINX already handles this.
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
# Compress JavaScripts and CSS. # Compress CSS using a preprocessor.
config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :sass # config.assets.css_compressor = :sass
# Do not fallback to assets pipeline if a precompiled asset is missed. # Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false config.assets.compile = false
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
# Enable serving of images, stylesheets, and JavaScripts from an asset server. # Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = 'http://assets.example.com' # config.action_controller.asset_host = 'http://assets.example.com'
@ -40,7 +37,7 @@ Rails.application.configure do
# config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
# Store uploaded files on the local file system (see config/storage.yml for options) # Store uploaded files on the local file system (see config/storage.yml for options).
config.active_storage.service = :local config.active_storage.service = :local
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
@ -56,9 +53,9 @@ Rails.application.configure do
# Use a different cache store in production. # Use a different cache store in production.
# config.cache_store = :mem_cache_store # config.cache_store = :mem_cache_store
# Use a real queuing backend for Active Job (and separate queues per environment) # Use a real queuing backend for Active Job (and separate queues per environment).
# config.active_job.queue_adapter = :resque # config.active_job.queue_adapter = :resque
# config.active_job.queue_name_prefix = "chexpire_#{Rails.env}" # config.active_job.queue_name_prefix = "chexpire_production"
config.action_mailer.perform_caching = false config.action_mailer.perform_caching = false
@ -93,4 +90,25 @@ Rails.application.configure do
# Do not dump schema after migrations. # Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false config.active_record.dump_schema_after_migration = false
# Inserts middleware to perform automatic connection switching.
# The `database_selector` hash is used to pass options to the DatabaseSelector
# middleware. The `delay` is used to determine how long to wait after a write
# to send a subsequent read to the primary.
#
# The `database_resolver` class is used by the middleware to determine which
# database is appropriate to use based on the time delay.
#
# The `database_resolver_context` class is used by the middleware to set
# timestamps for the last write to the primary. The resolver uses the context
# class timestamps to determine how long to wait before reading from the
# replica.
#
# By default Rails will store a last write timestamp in the session. The
# DatabaseSelector middleware is designed as such you can define your own
# strategy for connection switching and pass that into the middleware through
# these configuration options.
# config.active_record.database_selector = { delay: 2.seconds }
# config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
# config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
end end

View File

@ -1,11 +1,7 @@
Rails.application.configure do Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb. # Settings specified here will take precedence over those in config/application.rb.
# The test environment is used exclusively to run your application's config.cache_classes = false
# test suite. You never need to work with it otherwise. Remember that
# your test database is "scratch space" for the test suite and is wiped
# and recreated between test runs. Don't rely on the data there!
config.cache_classes = true
# Do not eager load code on boot. This avoids loading your whole application # Do not eager load code on boot. This avoids loading your whole application
# just for the purpose of running a single test. If you are using a tool that # just for the purpose of running a single test. If you are using a tool that
@ -23,6 +19,7 @@ Rails.application.configure do
# Show full error reports and disable caching. # Show full error reports and disable caching.
config.consider_all_requests_local = true config.consider_all_requests_local = true
config.action_controller.perform_caching = false config.action_controller.perform_caching = false
config.cache_store = :null_store
# Raise exceptions instead of rendering exception templates. # Raise exceptions instead of rendering exception templates.
config.action_dispatch.show_exceptions = false config.action_dispatch.show_exceptions = false
@ -30,7 +27,7 @@ Rails.application.configure do
# Disable request forgery protection in test environment. # Disable request forgery protection in test environment.
config.action_controller.allow_forgery_protection = false config.action_controller.allow_forgery_protection = false
# Store uploaded files on the local file system in a temporary directory # Store uploaded files on the local file system in a temporary directory.
config.active_storage.service = :test config.active_storage.service = :test
config.action_mailer.perform_caching = false config.action_mailer.perform_caching = false
@ -45,6 +42,6 @@ Rails.application.configure do
# Print deprecation notices to the stderr. # Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr config.active_support.deprecation = :stderr
# Raises error for missing translations # Raises error for missing translations.
# config.action_view.raise_on_missing_translations = true # config.action_view.raise_on_missing_translations = true
end end

View File

@ -10,16 +10,24 @@ Rails.application.config.content_security_policy do |policy|
policy.img_src :self, :https, :data policy.img_src :self, :https, :data
policy.object_src :none policy.object_src :none
policy.script_src :self, :https policy.script_src :self, :https
policy.style_src :self, :https if Rails.env.development?
policy.style_src :self, :https, :blob
else
policy.style_src :self, :https
end
# If you are using webpack-dev-server then specify webpack-dev-server host
policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
# Specify URI for violation reports # Specify URI for violation reports
# policy.report_uri "/csp-violation-report-endpoint" # policy.report_uri "/csp-violation-report-endpoint"
policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
end end
# If you are using UJS then enable automatic nonce generation # If you are using UJS then enable automatic nonce generation
Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
# Set the nonce only to specific directives
# Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
# Report CSP violations to a specified URI # Report CSP violations to a specified URI
# For further information see the following documentation: # For further information see the following documentation:
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only

View File

@ -13,4 +13,7 @@
# These inflection rules are supported but not enabled by default: # These inflection rules are supported but not enabled by default:
ActiveSupport::Inflector.inflections(:en) do |inflect| ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'SSL' inflect.acronym 'SSL'
inflect.acronym 'AFNIC'
inflect.acronym 'CIRA'
inflect.acronym 'IO'
end end

View File

@ -0,0 +1,45 @@
# Be sure to restart your server when you modify this file.
#
# This file contains migration options to ease your Rails 6.0 upgrade.
#
# Once upgraded flip defaults one by one to migrate to the new default.
#
# Read the Guide for Upgrading Ruby on Rails for more info on each option.
# Don't force requests from old versions of IE to be UTF-8 encoded.
# Rails.application.config.action_view.default_enforce_utf8 = false
# Embed purpose and expiry metadata inside signed and encrypted
# cookies for increased security.
#
# This option is not backwards compatible with earlier Rails versions.
# It's best enabled when your entire app is migrated and stable on 6.0.
# Rails.application.config.action_dispatch.use_cookies_with_metadata = true
# Change the return value of `ActionDispatch::Response#content_type` to Content-Type header without modification.
# Rails.application.config.action_dispatch.return_only_media_type_on_content_type = false
# Return false instead of self when enqueuing is aborted from a callback.
# Rails.application.config.active_job.return_false_on_aborted_enqueue = true
# Send Active Storage analysis and purge jobs to dedicated queues.
# Rails.application.config.active_storage.queues.analysis = :active_storage_analysis
# Rails.application.config.active_storage.queues.purge = :active_storage_purge
# When assigning to a collection of attachments declared via `has_many_attached`, replace existing
# attachments instead of appending. Use #attach to add new attachments without replacing existing ones.
# Rails.application.config.active_storage.replace_on_assign_to_many = true
# Use ActionMailer::MailDeliveryJob for sending parameterized and normal mail.
#
# The default delivery jobs (ActionMailer::Parameterized::DeliveryJob, ActionMailer::DeliveryJob),
# will be removed in Rails 6.1. This setting is not backwards compatible with earlier Rails versions.
# If you send mail in the background, job workers need to have a copy of
# MailDeliveryJob to ensure all delivery jobs are processed properly.
# Make sure your entire app is migrated and stable on 6.0 before using this setting.
# Rails.application.config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob"
# Enable the same cache key to be reused when the object being cached of type
# `ActiveRecord::Relation` changes by moving the volatile information (max updated at and count)
# of the relation's cache key into the cache version to support recycling cache key.
# Rails.application.config.active_record.collection_cache_versioning = true

View File

@ -4,31 +4,48 @@
# the maximum value specified for Puma. Default is set to 5 threads for minimum # the maximum value specified for Puma. Default is set to 5 threads for minimum
# and maximum; this matches the default thread size of Active Record. # and maximum; this matches the default thread size of Active Record.
# #
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch("PORT") { 3000 }
# Specifies the `environment` that Puma will run in. # Specifies the `environment` that Puma will run in.
# rails_env = ENV.fetch("RAILS_ENV") { "development" }
environment ENV.fetch("RAILS_ENV") { "development" } environment rails_env
# Specifies the number of `workers` to boot in clustered mode. app_dir = File.expand_path("../..", __FILE__)
# Workers are forked webserver processes. If using threads and workers together directory app_dir
# the concurrency of the application would be max `threads` * `workers`. shared_dir = "#{app_dir}/tmp"
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }
# Use the `preload_app!` method when specifying a `workers` number. if %w[production staging].member?(rails_env)
# This directive tells Puma to first boot the application and load code # Logging
# before forking the application. This takes advantage of Copy On Write stdout_redirect "#{app_dir}/log/puma.stdout.log", "#{app_dir}/log/puma.stderr.log", true
# process behavior so workers use less memory.
#
# preload_app!
# Allow puma to be restarted by `rails restart` command. # Set master PID and state locations
plugin :tmp_restart pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
# Change to match your CPU core count
workers ENV.fetch("WEB_CONCURRENCY") { 2 }
preload_app!
# Set up socket location and port
bind "unix://#{shared_dir}/sockets/puma.sock"
port ENV.fetch("PORT") { 3000 }
before_fork do
ActiveRecord::Base.connection_pool.disconnect!
end
on_worker_boot do
ActiveSupport.on_load(:active_record) do
db_url = ENV.fetch('DATABASE_URL')
# puts "puma: connecting to DB at #{db_url}"
ActiveRecord::Base.establish_connection(db_url)
end
end
elsif rails_env == "development"
# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
port ENV.fetch("PORT") { 3000 }
plugin :tmp_restart
end

View File

@ -4,7 +4,7 @@
# In order to update the route map below, # In order to update the route map below,
# run `bundle exec annotate -r` after modifying this file # run `bundle exec annotate -r` after modifying this file
Rails.application.routes.draw do Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
resources :checks, except: [:show] do resources :checks, except: [:show] do
collection do collection do
@ -63,7 +63,7 @@ end
# rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show # rails_disk_service GET /rails/active_storage/disk/:encoded_key/*filename(.:format) active_storage/disk#show
# update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update # update_rails_disk_service PUT /rails/active_storage/disk/:encoded_token(.:format) active_storage/disk#update
# rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create # rails_direct_uploads POST /rails/active_storage/direct_uploads(.:format) active_storage/direct_uploads#create
# #
# Routes for LetterOpenerWeb::Engine: # Routes for LetterOpenerWeb::Engine:
# clear_letters DELETE /clear(.:format) letter_opener_web/letters#clear # clear_letters DELETE /clear(.:format) letter_opener_web/letters#clear
# delete_letter DELETE /:id(.:format) letter_opener_web/letters#destroy # delete_letter DELETE /:id(.:format) letter_opener_web/letters#destroy

View File

@ -1,6 +1,6 @@
%w[ Spring.watch(
.ruby-version ".ruby-version",
.rbenv-vars ".rbenv-vars",
tmp/restart.txt "tmp/restart.txt",
tmp/caching-dev.txt "tmp/caching-dev.txt"
].each { |path| Spring.watch(path) } )

View File

@ -1,12 +1,11 @@
const webpack = require('webpack')
const { environment } = require('@rails/webpacker') const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
environment.plugins.prepend('Provide', new webpack.ProvidePlugin({ environment.plugins.prepend('Provide', new webpack.ProvidePlugin({
$: 'jquery', $: 'jquery',
jQuery: 'jquery', jQuery: 'jquery',
Popper: ['popper.js', 'default'], Popper: ['popper.js', 'default'],
Util: "exports-loader?Util!bootstrap/js/dist/util", // Util: "exports-loader?Util!bootstrap/js/dist/util",
})) }))
module.exports = environment module.exports = environment

View File

@ -1,10 +1,13 @@
# Note: You must restart bin/webpack-dev-server for changes to take effect # Note: You must restart bin/webpack-dev-server for changes to take effect
default: &default default: &default
source_path: app/frontend source_path: app/javascript
source_entry_path: packs source_entry_path: packs
public_root_path: public
public_output_path: packs public_output_path: packs
cache_path: tmp/cache/webpacker cache_path: tmp/cache/webpacker
check_yarn_integrity: false
webpack_compile_output: false
# Additional paths webpack should lookup modules # Additional paths webpack should lookup modules
# ['app/assets', 'engine/foo/app/assets'] # ['app/assets', 'engine/foo/app/assets']
@ -13,7 +16,25 @@ default: &default
# Reload manifest.json on all requests so we reload latest compiled packs # Reload manifest.json on all requests so we reload latest compiled packs
cache_manifest: false cache_manifest: false
# Extract and emit a css file
extract_css: false
static_assets_extensions:
- .jpg
- .jpeg
- .png
- .gif
- .tiff
- .ico
- .svg
- .eot
- .otf
- .ttf
- .woff
- .woff2
extensions: extensions:
- .mjs
- .js - .js
- .sass - .sass
- .scss - .scss
@ -31,6 +52,9 @@ development:
<<: *default <<: *default
compile: true compile: true
# Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules
check_yarn_integrity: true
# Reference: https://webpack.js.org/configuration/dev-server/ # Reference: https://webpack.js.org/configuration/dev-server/
dev_server: dev_server:
https: false https: false
@ -48,7 +72,7 @@ development:
headers: headers:
'Access-Control-Allow-Origin': '*' 'Access-Control-Allow-Origin': '*'
watch_options: watch_options:
ignored: /node_modules/ ignored: '**/node_modules/**'
test: test:
@ -64,6 +88,9 @@ production:
# Production depends on precompilation of packs prior to booting for performance. # Production depends on precompilation of packs prior to booting for performance.
compile: false compile: false
# Extract and emit a css file
extract_css: true
# Cache manifest.json for performance # Cache manifest.json for performance
cache_manifest: true cache_manifest: true
@ -73,5 +100,8 @@ staging:
# Production depends on precompilation of packs prior to booting for performance. # Production depends on precompilation of packs prior to booting for performance.
compile: false compile: false
# Extract and emit a css file
extract_css: true
# Cache manifest.json for performance # Cache manifest.json for performance
cache_manifest: true cache_manifest: true

View File

@ -0,0 +1,10 @@
# This migration comes from active_storage (originally 20180723000244)
class AddForeignKeyConstraintToActiveStorageAttachmentsForBlobId < ActiveRecord::Migration[6.0]
def up
return if foreign_key_exists?(:active_storage_attachments, column: :blob_id)
if table_exists?(:active_storage_blobs)
add_foreign_key :active_storage_attachments, :active_storage_blobs, column: :blob_id
end
end
end

View File

@ -2,15 +2,15 @@
# of editing this file, please use the migrations feature of Active Record to # of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition. # incrementally modify your database, and then regenerate this schema definition.
# #
# Note that this schema.rb definition is the authoritative source for your # This file is the source Rails uses to define your schema when running `rails
# database schema. If you need to create the application database on another # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
# system, you should be using db:schema:load, not running all the migrations # be faster and is potentially less error prone than running all of your
# from scratch. The latter is a flawed and unsustainable approach (the more migrations # migrations from scratch. Old migrations may fail to apply correctly if those
# you'll amass, the slower it'll run and the greater likelihood for issues). # migrations use external dependencies or application code.
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_08_30_083927) do ActiveRecord::Schema.define(version: 2019_08_16_223645) do
create_table "check_logs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t| create_table "check_logs", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
t.bigint "check_id" t.bigint "check_id"

View File

@ -1,4 +0,0 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file)
class SystemCommandNotAllowedError < StandardError; end

View File

@ -1,8 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "null_logger"
namespace :checks do namespace :checks do
namespace :sync_dates do namespace :sync_dates do
task all: [:domain, :ssl] task all: [:domain, :ssl]

View File

@ -1,8 +1,6 @@
# Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr> # Copyright (C) 2018 Colin Darie <colin@darie.eu>, 2018 Evolix <info@evolix.fr>
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
# require "services/notifier"
namespace :notifications do namespace :notifications do
desc "Send all notifications after checks have been performend" desc "Send all notifications after checks have been performend"
task send_all: :environment do task send_all: :environment do

View File

@ -2,15 +2,18 @@
"name": "chexpire", "name": "chexpire",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@rails/webpacker": "3.5", "@rails/ujs": "^6.0.0-alpha",
"bootstrap": "^4.1.1", "@rails/webpacker": "^4.0.7",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"bootstrap": "4.3.1",
"exports-loader": "^0.7.0", "exports-loader": "^0.7.0",
"jquery": "^3.3.1", "jquery": "^3.4.1",
"popper.js": "^1.14.3", "popper.js": "^1.15.0",
"rails-ujs": "^5.2.0", "postcss-preset-env": "^6.7.0",
"turbolinks": "^5.1.1" "turbolinks": "^5.2.0"
}, },
"version": "0.1.0",
"devDependencies": { "devDependencies": {
"webpack-dev-server": "2.11.2" "webpack-dev-server": "^3.8.0"
} }
} }

12
postcss.config.js Normal file
View File

@ -0,0 +1,12 @@
module.exports = {
plugins: [
require('postcss-import'),
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
})
]
}

View File

@ -34,6 +34,7 @@ if [ "${confirmed}" != "y" ]; then
exit 1 exit 1
fi fi
echo "🚀 Deploying master to production !"
bundle exec cap production deploy bundle exec cap production deploy
echo "😎 Done !" echo "😎 Done !"

View File

@ -6,7 +6,15 @@
set -e set -e
[ -n "$DEBUG" ] && set -x [ -n "$DEBUG" ] && set -x
echo "👀 Fetching git repository information…"
git fetch origin --quiet
CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD`
echo "🚀 Deploying ${CURRENT_BRANCH} to staging !"
git branch -f staging git branch -f staging
git push --force origin staging git push --force origin staging
bundle exec cap staging deploy bundle exec cap staging deploy
echo "😎 Done !"

View File

@ -4,7 +4,7 @@
require "test_helper" require "test_helper"
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
driven_by :headless_chrome driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400]
def teardown def teardown
Warden.test_reset! Warden.test_reset!

View File

@ -2,7 +2,6 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "domain_helper"
class DomainHelperTest < ActiveSupport::TestCase class DomainHelperTest < ActiveSupport::TestCase
include DomainHelper include DomainHelper

View File

@ -5,64 +5,62 @@ require "test_helper"
class NotificationsMailerTest < ActionMailer::TestCase # rubocop:disable Metrics/ClassLength class NotificationsMailerTest < ActionMailer::TestCase # rubocop:disable Metrics/ClassLength
test "domain_expires_soon" do test "domain_expires_soon" do
check = create(:check, domain_expires_at: Time.new(2018, 6, 10, 12, 0, 5, "+02:00")) expiration_date = 8.days.from_now.utc
check = create(:check, domain_expires_at: expiration_date)
notification = build(:notification, interval: 10, recipient: "colin@example.org") notification = build(:notification, interval: 10, recipient: "colin@example.org")
check_notification = build(:check_notification, check: check, notification: notification) check_notification = build(:check_notification, check: check, notification: notification)
Date.stub :today, Date.new(2018, 6, 2) do mail = NotificationsMailer.with(check_notification: check_notification).domain_expires_soon
mail = NotificationsMailer.with(check_notification: check_notification).domain_expires_soon
assert_emails 1 do assert_emails 1 do
mail.deliver_now mail.deliver_now
end end
assert_match "domain.fr", mail.subject assert_match "domain.fr", mail.subject
assert_match "in 8 days", mail.subject assert_match "in 8 days", mail.subject
assert_equal ["colin@example.org"], mail.to assert_equal ["colin@example.org"], mail.to
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
parts = [mail.text_part.decode_body, mail.html_part.decode_body] parts = [mail.text_part.decode_body, mail.html_part.decode_body]
parts.each do |part| parts.each do |part|
assert_match "domain.fr", part assert_match "domain.fr", part
assert_match "Sun, 10 Jun 2018 10:00:05 +0000", part assert_match I18n.l(expiration_date, locale: :en), part
assert_match "10 days", part assert_match "10 days", part
assert_match "/checks/#{check.id}/edit", part assert_match "/checks/#{check.id}/edit", part
assert_no_match "comment", part assert_no_match "comment", part
assert_no_match "vendor", part assert_no_match "vendor", part
end
end end
end end
test "domain_expires_soon FR" do test "domain_expires_soon FR" do
expiration_date = 8.days.from_now.utc
check = create(:check, check = create(:check,
domain_expires_at: Time.new(2018, 6, 10, 12, 0, 5, "+02:00"), domain_expires_at: expiration_date,
user: build(:user, :fr)) user: build(:user, :fr))
notification = build(:notification, interval: 10, recipient: "colin@example.org") notification = build(:notification, interval: 10, recipient: "colin@example.org")
check_notification = build(:check_notification, check: check, notification: notification) check_notification = build(:check_notification, check: check, notification: notification)
Date.stub :today, Date.new(2018, 6, 2) do mail = NotificationsMailer.with(check_notification: check_notification).domain_expires_soon
mail = NotificationsMailer.with(check_notification: check_notification).domain_expires_soon
assert_emails 1 do assert_emails 1 do
mail.deliver_now mail.deliver_now
end end
assert_match "domain.fr", mail.subject assert_match "domain.fr", mail.subject
assert_match "dans 8 jours", mail.subject assert_match "dans 8 jours", mail.subject
assert_equal ["colin@example.org"], mail.to assert_equal ["colin@example.org"], mail.to
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
parts = [mail.text_part.decode_body, mail.html_part.decode_body] parts = [mail.text_part.decode_body, mail.html_part.decode_body]
parts.each do |part| parts.each do |part|
assert_match "domain.fr", part assert_match "domain.fr", part
assert_match "dim 10 juin 2018 10:00:05 +0000", part assert_match I18n.l(expiration_date, locale: :fr), part
assert_match "10 jours", part assert_match "10 jours", part
assert_match "/checks/#{check.id}/edit", part assert_match "/checks/#{check.id}/edit", part
assert_no_match "commentaire", part assert_no_match "commentaire", part
assert_no_match "fournisseur", part assert_no_match "fournisseur", part
end
end end
end end
@ -159,66 +157,64 @@ class NotificationsMailerTest < ActionMailer::TestCase # rubocop:disable Metrics
end end
test "ssl_expires_soon" do test "ssl_expires_soon" do
check = create(:check, :ssl, domain_expires_at: Time.new(2018, 6, 10, 12, 0, 5, "+02:00")) expiration_date = 8.days.from_now.utc
check = create(:check, :ssl, domain_expires_at: 8.days.from_now)
notification = build(:notification, interval: 10, recipient: "colin@example.org") notification = build(:notification, interval: 10, recipient: "colin@example.org")
check_notification = build(:check_notification, check: check, notification: notification) check_notification = build(:check_notification, check: check, notification: notification)
Date.stub :today, Date.new(2018, 6, 2) do mail = NotificationsMailer.with(check_notification: check_notification).ssl_expires_soon
mail = NotificationsMailer.with(check_notification: check_notification).ssl_expires_soon
assert_emails 1 do assert_emails 1 do
mail.deliver_now mail.deliver_now
end end
assert_match "domain.fr", mail.subject assert_match "domain.fr", mail.subject
assert_match "SSL", mail.subject assert_match "SSL", mail.subject
assert_match "in 8 days", mail.subject assert_match "in 8 days", mail.subject
assert_equal ["colin@example.org"], mail.to assert_equal ["colin@example.org"], mail.to
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
parts = [mail.text_part.decode_body, mail.html_part.decode_body] parts = [mail.text_part.decode_body, mail.html_part.decode_body]
parts.each do |part| parts.each do |part|
assert_match "domain.fr", part assert_match "domain.fr", part
assert_match "Sun, 10 Jun 2018 10:00:05 +0000", part assert_match I18n.l(expiration_date, locale: :en), part
assert_match "10 days", part assert_match "10 days", part
assert_match "/checks/#{check.id}/edit", part assert_match "/checks/#{check.id}/edit", part
assert_no_match "comment", part assert_no_match "comment", part
assert_no_match "vendor", part assert_no_match "vendor", part
end
end end
end end
test "ssl_expires_soon - FR" do test "ssl_expires_soon - FR" do
expiration_date = 8.days.from_now.utc
check = create(:check, :ssl, check = create(:check, :ssl,
domain_expires_at: Time.new(2018, 6, 10, 12, 0, 5, "+02:00"), domain_expires_at: expiration_date,
user: build(:user, :fr)) user: build(:user, :fr))
notification = build(:notification, interval: 10, recipient: "colin@example.org") notification = build(:notification, interval: 10, recipient: "colin@example.org")
check_notification = build(:check_notification, check: check, notification: notification) check_notification = build(:check_notification, check: check, notification: notification)
Date.stub :today, Date.new(2018, 6, 2) do mail = NotificationsMailer.with(check_notification: check_notification).ssl_expires_soon
mail = NotificationsMailer.with(check_notification: check_notification).ssl_expires_soon
assert_emails 1 do assert_emails 1 do
mail.deliver_now mail.deliver_now
end end
assert_match "domain.fr", mail.subject assert_match "domain.fr", mail.subject
assert_match "SSL", mail.subject assert_match "SSL", mail.subject
assert_match "dans 8 jours", mail.subject assert_match "dans 8 jours", mail.subject
assert_equal ["colin@example.org"], mail.to assert_equal ["colin@example.org"], mail.to
assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from assert_equal [Rails.configuration.chexpire.fetch("mailer_default_from")], mail.from
parts = [mail.text_part.decode_body, mail.html_part.decode_body] parts = [mail.text_part.decode_body, mail.html_part.decode_body]
parts.each do |part| parts.each do |part|
assert_match "domain.fr", part assert_match "domain.fr", part
assert_match "dim 10 juin 2018 10:00:05 +0000", part assert_match I18n.l(expiration_date, locale: :fr), part
assert_match "10 jours", part assert_match "10 jours", part
assert_match "/checks/#{check.id}/edit", part assert_match "/checks/#{check.id}/edit", part
assert_no_match "commentaire", part assert_no_match "commentaire", part
assert_no_match "fournisseur", part assert_no_match "fournisseur", part
end
end end
end end
end end

View File

@ -117,10 +117,28 @@ class CheckTest < ActiveSupport::TestCase
test "set mode before saving" do test "set mode before saving" do
check = build(:check, domain: "domain.fr") check = build(:check, domain: "domain.fr")
check.save! check.save!
assert check.auto? assert check.auto?
check.domain = "domain.xyz" check.domain = "domain.xyz"
check.save! check.save!
assert check.mode? assert check.mode?
end end
test "expiration in days (future)" do
check = create(:check, domain_expires_at: 1.week.from_now)
expected = 7
actual = check.domain_expires_in_days
assert_equal expected, actual
end
test "expiration in days (past)" do
check = create(:check, domain_expires_at: 1.week.ago)
expected = -7
actual = check.domain_expires_in_days
assert_equal expected, actual
end
end end

View File

@ -2,8 +2,6 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "check_logger"
require "system_command"
class CheckLoggerTest < ActiveSupport::TestCase class CheckLoggerTest < ActiveSupport::TestCase
setup do setup do
@ -20,7 +18,7 @@ class CheckLoggerTest < ActiveSupport::TestCase
end end
test "should log a success raw result command" do test "should log a success raw result command" do
result = SystemCommandResult.new("command", 0, "the result", "") result = SystemCommand::Result.new("command", 0, "the result", "")
assert_no_difference -> { CheckLog.where(check: @check).count } do assert_no_difference -> { CheckLog.where(check: @check).count } do
@logger.log :after_command, result @logger.log :after_command, result
@ -33,7 +31,7 @@ class CheckLoggerTest < ActiveSupport::TestCase
end end
test "should log a raw result command with an error" do test "should log a raw result command with an error" do
result = SystemCommandResult.new("command", 1, "optional stdout", "an error occured") result = SystemCommand::Result.new("command", 1, "optional stdout", "an error occured")
@logger.log :after_command, result @logger.log :after_command, result
assert_equal "optional stdout", @logger.check_log.raw_response assert_equal "optional stdout", @logger.check_log.raw_response
@ -43,7 +41,7 @@ class CheckLoggerTest < ActiveSupport::TestCase
end end
test "should log an error when there is not exit status" do test "should log an error when there is not exit status" do
result = SystemCommandResult.new("command", nil, nil, "an error") result = SystemCommand::Result.new("command", nil, nil, "an error")
@logger.log :after_command, result @logger.log :after_command, result
assert_nil @logger.check_log.raw_response assert_nil @logger.check_log.raw_response

View File

@ -2,7 +2,6 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "notifier"
class NotifierTest < ActiveSupport::TestCase class NotifierTest < ActiveSupport::TestCase
test "#process_all process expirable & failures notifications" do test "#process_all process expirable & failures notifications" do

View File

@ -2,8 +2,6 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "ssl/parser"
require "ssl/errors"
module SSL module SSL
class ParserTest < ActiveSupport::TestCase class ParserTest < ActiveSupport::TestCase
@ -11,7 +9,7 @@ module SSL
parser = Parser.new("ssl0.domain.org") parser = Parser.new("ssl0.domain.org")
domain = file_fixture("ssl/ssl0.domain.org.txt").read domain = file_fixture("ssl/ssl0.domain.org.txt").read
response = parser.parse(domain) response = parser.parse(domain)
assert_kind_of Response, response assert_kind_of SSL::Response, response
assert_equal Time.new(2028, 6, 10, 9, 14, 18, 0), response.expire_at assert_equal Time.new(2028, 6, 10, 9, 14, 18, 0), response.expire_at
assert response.expire_at.utc? assert response.expire_at.utc?
@ -21,7 +19,7 @@ module SSL
parser = Parser.new("ssl1.domain.org") parser = Parser.new("ssl1.domain.org")
domain = file_fixture("ssl/ssl1.domain.org.txt").read domain = file_fixture("ssl/ssl1.domain.org.txt").read
response = parser.parse(domain) response = parser.parse(domain)
assert_kind_of Response, response assert_kind_of SSL::Response, response
assert_equal Time.new(2022, 8, 6, 0, 57, 0, 0), response.expire_at assert_equal Time.new(2022, 8, 6, 0, 57, 0, 0), response.expire_at
assert response.expire_at.utc? assert response.expire_at.utc?

View File

@ -2,8 +2,6 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "ssl"
require "system_command"
module SSL module SSL
class ServiceTest < ActiveSupport::TestCase class ServiceTest < ActiveSupport::TestCase
@ -11,7 +9,7 @@ module SSL
result = OpenStruct.new(exit_status: 0) result = OpenStruct.new(exit_status: 0)
mock_system_klass("check_http", standard_args, result) do |system_klass| mock_system_klass("check_http", standard_args, result) do |system_klass|
service = Service.new("example.org", system_klass: system_klass) service = SSL::Service.new("example.org", system_klass: system_klass)
assert_equal result, service.run_command assert_equal result, service.run_command
end end
end end
@ -20,9 +18,9 @@ module SSL
result = OpenStruct.new(exit_status: 1) result = OpenStruct.new(exit_status: 1)
mock_system_klass("check_http", standard_args, result) do |system_klass| mock_system_klass("check_http", standard_args, result) do |system_klass|
service = Service.new("example.org", system_klass: system_klass) service = SSL::Service.new("example.org", system_klass: system_klass)
assert_raises SSLCommandError do assert_raises SSL::CommandError do
service.run_command service.run_command
end end
end end
@ -34,8 +32,8 @@ module SSL
stdout: file_fixture("ssl/ssl0.domain.org.txt").read, stdout: file_fixture("ssl/ssl0.domain.org.txt").read,
) )
service = Service.new("ssl0.domain.org") service = SSL::Service.new("ssl0.domain.org")
assert_kind_of Response, service.parse(result) assert_kind_of SSL::Response, service.parse(result)
end end
test "should uses the command line arguments of the configuration" do test "should uses the command line arguments of the configuration" do
@ -44,7 +42,7 @@ module SSL
expected_args = standard_args.concat ["-f", "-I 127.0.0.1"] expected_args = standard_args.concat ["-f", "-I 127.0.0.1"]
mock_system_klass("check_http", expected_args, result) do |system_klass| mock_system_klass("check_http", expected_args, result) do |system_klass|
service = Service.new("example.org", configuration: config, system_klass: system_klass) service = SSL::Service.new("example.org", configuration: config, system_klass: system_klass)
assert_equal result, service.run_command assert_equal result, service.run_command
end end
end end
@ -53,8 +51,8 @@ module SSL
black_hole = Naught.build(&:black_hole) black_hole = Naught.build(&:black_hole)
config = OpenStruct.new(check_http_args: "-f") config = OpenStruct.new(check_http_args: "-f")
assert_raises SSLConfigurationError do assert_raises SSL::ConfigurationError do
service = Service.new("example.org", configuration: config, system_klass: black_hole) service = SSL::Service.new("example.org", configuration: config, system_klass: black_hole)
service.run_command service.run_command
end end
end end
@ -64,7 +62,7 @@ module SSL
config = OpenStruct.new(check_http_path: "/usr/local/custom/path") config = OpenStruct.new(check_http_path: "/usr/local/custom/path")
mock_system_klass("/usr/local/custom/path", standard_args, result) do |sys| mock_system_klass("/usr/local/custom/path", standard_args, result) do |sys|
service = Service.new("example.org", configuration: config, system_klass: sys) service = SSL::Service.new("example.org", configuration: config, system_klass: sys)
assert_equal result, service.run_command assert_equal result, service.run_command
end end
end end

View File

@ -2,14 +2,13 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "system_command"
class SystemCommandTest < ActiveSupport::TestCase class SystemCommandTest < ActiveSupport::TestCase
test "should execute and log a command" do test "should execute and log a command" do
mock_logger = Minitest::Mock.new mock_logger = Minitest::Mock.new
expected_cmd = 'whois "example.org"' expected_cmd = 'whois "example.org"'
expected_result = SystemCommandResult.new( expected_result = SystemCommand::Result.new(
expected_cmd, expected_cmd,
0, 0,
"my result", "my result",

View File

@ -2,17 +2,14 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "whois/parser/afilias"
require "whois/response"
require "whois/errors"
module Whois module Whois
class AfiliasTest < ActiveSupport::TestCase class AfiliasTest < ActiveSupport::TestCase
test "should parse a whois response for .info" do test "should parse a whois response for .info" do
parser = Parser::Afilias.new("domain.info") parser = Whois::Parser::Afilias.new("domain.info")
whois_output = file_fixture("whois/domain.info.txt").read whois_output = file_fixture("whois/domain.info.txt").read
response = parser.parse(whois_output) response = parser.parse(whois_output)
assert_kind_of Response, response assert_kind_of Whois::Response, response
assert_equal Time.new(2006, 3, 25, 14, 1, 14, 0), response.created_at assert_equal Time.new(2006, 3, 25, 14, 1, 14, 0), response.created_at
assert response.created_at.utc? assert response.created_at.utc?
@ -22,7 +19,7 @@ module Whois
end end
test "should raises DomainNotFoundError for .info when domain is not registered" do test "should raises DomainNotFoundError for .info when domain is not registered" do
parser = Parser::Afilias.new("willneverexist.info") parser = Whois::Parser::Afilias.new("willneverexist.info")
not_found = file_fixture("whois/willneverexist.info.txt").read not_found = file_fixture("whois/willneverexist.info.txt").read
assert_raises DomainNotFoundError do assert_raises DomainNotFoundError do
@ -31,7 +28,7 @@ module Whois
end end
test "should raises InvalidDateError for .info when a date is not parsable" do test "should raises InvalidDateError for .info when a date is not parsable" do
parser = Parser::Afilias.new("domain.info") parser = Whois::Parser::Afilias.new("domain.info")
whois_output = file_fixture("whois/domain.info.txt").read whois_output = file_fixture("whois/domain.info.txt").read
whois_output.gsub!("2020-03-25T14:01:14Z", "not a date") whois_output.gsub!("2020-03-25T14:01:14Z", "not a date")
@ -41,10 +38,10 @@ module Whois
end end
test "should parse a whois response for .org" do test "should parse a whois response for .org" do
parser = Parser::Afilias.new("domain.org") parser = Whois::Parser::Afilias.new("domain.org")
domain_com = file_fixture("whois/domain.org.txt").read domain_com = file_fixture("whois/domain.org.txt").read
response = parser.parse(domain_com) response = parser.parse(domain_com)
assert_kind_of Response, response assert_kind_of Whois::Response, response
assert_equal Time.new(1995, 4, 30, 4, 0, 0, 0), response.created_at assert_equal Time.new(1995, 4, 30, 4, 0, 0, 0), response.created_at
assert response.created_at.utc? assert response.created_at.utc?
@ -54,7 +51,7 @@ module Whois
end end
test "should raises DomainNotFoundError for .org when domain is not registered" do test "should raises DomainNotFoundError for .org when domain is not registered" do
parser = Parser::Afilias.new("willneverexist.org") parser = Whois::Parser::Afilias.new("willneverexist.org")
not_found = file_fixture("whois/willneverexist.org.txt").read not_found = file_fixture("whois/willneverexist.org.txt").read
assert_raises DomainNotFoundError do assert_raises DomainNotFoundError do
@ -63,7 +60,7 @@ module Whois
end end
test "should raises InvalidDateError for .org when a date is not parsable" do test "should raises InvalidDateError for .org when a date is not parsable" do
parser = Parser::Afilias.new("domain.org") parser = Whois::Parser::Afilias.new("domain.org")
domain_com = file_fixture("whois/domain.org.txt").read domain_com = file_fixture("whois/domain.org.txt").read
domain_com.gsub!("2018-04-02T03:47:23Z", "not a date") domain_com.gsub!("2018-04-02T03:47:23Z", "not a date")

View File

@ -2,17 +2,14 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "whois/parser/afnic"
require "whois/response"
require "whois/errors"
module Whois module Whois
class AFNICTest < ActiveSupport::TestCase class AFNICTest < ActiveSupport::TestCase
test "should parse a whois response" do test "should parse a whois response" do
parser = Parser::AFNIC.new("domain.fr") parser = Whois::Parser::AFNIC.new("domain.fr")
domain_fr = file_fixture("whois/domain.fr.txt").read domain_fr = file_fixture("whois/domain.fr.txt").read
response = parser.parse(domain_fr) response = parser.parse(domain_fr)
assert_kind_of Response, response assert_kind_of Whois::Response, response
assert_equal Time.new(2004, 2, 18, 0, 0, 0, 0), response.created_at assert_equal Time.new(2004, 2, 18, 0, 0, 0, 0), response.created_at
assert response.created_at.utc? assert response.created_at.utc?
@ -22,7 +19,7 @@ module Whois
end end
test "should raises DomainNotFoundError when domain is not registered" do test "should raises DomainNotFoundError when domain is not registered" do
parser = Parser::AFNIC.new("willneverexist.fr") parser = Whois::Parser::AFNIC.new("willneverexist.fr")
not_found_fr = file_fixture("whois/willneverexist.fr.txt").read not_found_fr = file_fixture("whois/willneverexist.fr.txt").read
assert_raises DomainNotFoundError do assert_raises DomainNotFoundError do
@ -31,7 +28,7 @@ module Whois
end end
test "should raises InvalidDateError when a date is not in the expected format" do test "should raises InvalidDateError when a date is not in the expected format" do
parser = Parser::AFNIC.new("domain.fr") parser = Whois::Parser::AFNIC.new("domain.fr")
domain_fr = file_fixture("whois/domain.fr.txt").read domain_fr = file_fixture("whois/domain.fr.txt").read
domain_fr.gsub!("17/02/2019", "17-02-2019") domain_fr.gsub!("17/02/2019", "17-02-2019")

View File

@ -2,17 +2,14 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "whois/parser/cira"
require "whois/response"
require "whois/errors"
module Whois module Whois
class CIRATest < ActiveSupport::TestCase class CIRATest < ActiveSupport::TestCase
test "should parse a whois response for .ca" do test "should parse a whois response for .ca" do
parser = Parser::CIRA.new("domain.ca") parser = Whois::Parser::CIRA.new("domain.ca")
whois_output = file_fixture("whois/domain.ca.txt").read whois_output = file_fixture("whois/domain.ca.txt").read
response = parser.parse(whois_output) response = parser.parse(whois_output)
assert_kind_of Response, response assert_kind_of Whois::Response, response
assert_equal Time.new(2015, 3, 24, 9, 10, 16, 0), response.created_at assert_equal Time.new(2015, 3, 24, 9, 10, 16, 0), response.created_at
assert response.created_at.utc? assert response.created_at.utc?
@ -22,7 +19,7 @@ module Whois
end end
test "should raises DomainNotFoundError for .ca when domain is not registered" do test "should raises DomainNotFoundError for .ca when domain is not registered" do
parser = Parser::CIRA.new("willneverexist.ca") parser = Whois::Parser::CIRA.new("willneverexist.ca")
not_found = file_fixture("whois/willneverexist.ca.txt").read not_found = file_fixture("whois/willneverexist.ca.txt").read
assert_raises DomainNotFoundError do assert_raises DomainNotFoundError do
@ -31,7 +28,7 @@ module Whois
end end
test "should raises InvalidDateError for .ca when a date is not parsable" do test "should raises InvalidDateError for .ca when a date is not parsable" do
parser = Parser::CIRA.new("domain.ca") parser = Whois::Parser::CIRA.new("domain.ca")
whois_output = file_fixture("whois/domain.ca.txt").read whois_output = file_fixture("whois/domain.ca.txt").read
whois_output.gsub!("2015-03-24T09:10:16Z", "not a date") whois_output.gsub!("2015-03-24T09:10:16Z", "not a date")

View File

@ -2,17 +2,14 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "whois/parser/io"
require "whois/response"
require "whois/errors"
module Whois module Whois
class IOTest < ActiveSupport::TestCase class IOTest < ActiveSupport::TestCase
test "should parse a whois response for .io" do test "should parse a whois response for .io" do
parser = Parser::IO.new("domain.io") parser = Whois::Parser::IO.new("domain.io")
whois_output = file_fixture("whois/domain.io.txt").read whois_output = file_fixture("whois/domain.io.txt").read
response = parser.parse(whois_output) response = parser.parse(whois_output)
assert_kind_of Response, response assert_kind_of Whois::Response, response
assert_equal Time.new(2016, 7, 26, 6, 16, 0, 0), response.created_at assert_equal Time.new(2016, 7, 26, 6, 16, 0, 0), response.created_at
assert response.created_at.utc? assert response.created_at.utc?
@ -22,7 +19,7 @@ module Whois
end end
test "should raises DomainNotFoundError for .io when domain is not registered" do test "should raises DomainNotFoundError for .io when domain is not registered" do
parser = Parser::IO.new("willneverexist.io") parser = Whois::Parser::IO.new("willneverexist.io")
not_found = file_fixture("whois/willneverexist.io.txt").read not_found = file_fixture("whois/willneverexist.io.txt").read
assert_raises DomainNotFoundError do assert_raises DomainNotFoundError do
@ -31,7 +28,7 @@ module Whois
end end
test "should raises InvalidDateError for .io when a date is not parsable" do test "should raises InvalidDateError for .io when a date is not parsable" do
parser = Parser::IO.new("domain.io") parser = Whois::Parser::IO.new("domain.io")
whois_output = file_fixture("whois/domain.io.txt").read whois_output = file_fixture("whois/domain.io.txt").read
whois_output.gsub!("2016-07-26T06:16:00Z", "not a date") whois_output.gsub!("2016-07-26T06:16:00Z", "not a date")

View File

@ -2,17 +2,14 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "whois/parser/neustar"
require "whois/response"
require "whois/errors"
module Whois module Whois
class NeustarTest < ActiveSupport::TestCase class NeustarTest < ActiveSupport::TestCase
test "should parse a whois response for .us" do test "should parse a whois response for .us" do
parser = Parser::Neustar.new("domain.us") parser = Whois::Parser::Neustar.new("domain.us")
whois_output = file_fixture("whois/domain.us.txt").read whois_output = file_fixture("whois/domain.us.txt").read
response = parser.parse(whois_output) response = parser.parse(whois_output)
assert_kind_of Response, response assert_kind_of Whois::Response, response
assert_equal Time.new(2002, 4, 18, 15, 36, 40, 0), response.created_at assert_equal Time.new(2002, 4, 18, 15, 36, 40, 0), response.created_at
assert response.created_at.utc? assert response.created_at.utc?
@ -22,7 +19,7 @@ module Whois
end end
test "should raises DomainNotFoundError for .us when domain is not registered" do test "should raises DomainNotFoundError for .us when domain is not registered" do
parser = Parser::Neustar.new("willneverexist.us") parser = Whois::Parser::Neustar.new("willneverexist.us")
not_found = file_fixture("whois/willneverexist.us.txt").read not_found = file_fixture("whois/willneverexist.us.txt").read
assert_raises DomainNotFoundError do assert_raises DomainNotFoundError do
@ -31,7 +28,7 @@ module Whois
end end
test "should raises InvalidDateError for .us when a date is not parsable" do test "should raises InvalidDateError for .us when a date is not parsable" do
parser = Parser::Neustar.new("domain.us") parser = Whois::Parser::Neustar.new("domain.us")
whois_output = file_fixture("whois/domain.us.txt").read whois_output = file_fixture("whois/domain.us.txt").read
whois_output.gsub!("2018-06-02T00:05:41Z", "not a date") whois_output.gsub!("2018-06-02T00:05:41Z", "not a date")

View File

@ -2,17 +2,14 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "whois/parser/sonic"
require "whois/response"
require "whois/errors"
module Whois module Whois
class SonicTest < ActiveSupport::TestCase class SonicTest < ActiveSupport::TestCase
test "should parse a whois response for .so" do test "should parse a whois response for .so" do
parser = Parser::Sonic.new("domain.so") parser = Whois::Parser::Sonic.new("domain.so")
whois_output = file_fixture("whois/domain.so.txt").read whois_output = file_fixture("whois/domain.so.txt").read
response = parser.parse(whois_output) response = parser.parse(whois_output)
assert_kind_of Response, response assert_kind_of Whois::Response, response
assert_equal Time.new(2010, 10, 31, 0, 0, 0, 0), response.created_at assert_equal Time.new(2010, 10, 31, 0, 0, 0, 0), response.created_at
assert response.created_at.utc? assert response.created_at.utc?
@ -26,7 +23,7 @@ module Whois
end end
test "should raises DomainNotFoundError for .so when domain is not registered" do test "should raises DomainNotFoundError for .so when domain is not registered" do
parser = Parser::Sonic.new("willneverexist.so") parser = Whois::Parser::Sonic.new("willneverexist.so")
not_found = file_fixture("whois/willneverexist.so.txt").read not_found = file_fixture("whois/willneverexist.so.txt").read
assert_raises DomainNotFoundError do assert_raises DomainNotFoundError do
@ -35,7 +32,7 @@ module Whois
end end
test "should raises InvalidDateError for .so when a date is not parsable" do test "should raises InvalidDateError for .so when a date is not parsable" do
parser = Parser::Sonic.new("domain.so") parser = Whois::Parser::Sonic.new("domain.so")
whois_output = file_fixture("whois/domain.so.txt").read whois_output = file_fixture("whois/domain.so.txt").read
whois_output.gsub!("2010-10-31T00:00:00.0Z", "not a date") whois_output.gsub!("2010-10-31T00:00:00.0Z", "not a date")

View File

@ -2,17 +2,14 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "whois/parser/verisign"
require "whois/response"
require "whois/errors"
module Whois module Whois
class VerisignTest < ActiveSupport::TestCase class VerisignTest < ActiveSupport::TestCase
test "should parse a whois response" do test "should parse a whois response" do
parser = Parser::Verisign.new("domain.com") parser = Whois::Parser::Verisign.new("domain.com")
domain_com = file_fixture("whois/domain.com.txt").read domain_com = file_fixture("whois/domain.com.txt").read
response = parser.parse(domain_com) response = parser.parse(domain_com)
assert_kind_of Response, response assert_kind_of Whois::Response, response
assert_equal Time.new(1994, 7, 1, 4, 0, 0, 0), response.created_at assert_equal Time.new(1994, 7, 1, 4, 0, 0, 0), response.created_at
assert response.created_at.utc? assert response.created_at.utc?
@ -22,7 +19,7 @@ module Whois
end end
test "should raises DomainNotFoundError when domain is not registered" do test "should raises DomainNotFoundError when domain is not registered" do
parser = Parser::Verisign.new("willneverexist.com") parser = Whois::Parser::Verisign.new("willneverexist.com")
not_found_com = file_fixture("whois/willneverexist.com.txt").read not_found_com = file_fixture("whois/willneverexist.com.txt").read
assert_raises DomainNotFoundError do assert_raises DomainNotFoundError do
@ -31,7 +28,7 @@ module Whois
end end
test "should raises InvalidDateError when a date is not parsable" do test "should raises InvalidDateError when a date is not parsable" do
parser = Parser::Verisign.new("domain.com") parser = Whois::Parser::Verisign.new("domain.com")
domain_com = file_fixture("whois/domain.com.txt").read domain_com = file_fixture("whois/domain.com.txt").read
domain_com.gsub!("2018-02-13T18:33:26Z", "not a date") domain_com.gsub!("2018-02-13T18:33:26Z", "not a date")

View File

@ -2,8 +2,6 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "whois/parser"
require "whois/errors"
module Whois module Whois
class ParserTest < ActiveSupport::TestCase class ParserTest < ActiveSupport::TestCase

View File

@ -2,8 +2,6 @@
# License: GNU AGPL-3+ (see full text in LICENSE file) # License: GNU AGPL-3+ (see full text in LICENSE file)
require "test_helper" require "test_helper"
require "whois"
require "system_command"
module Whois module Whois
class ServiceTest < ActiveSupport::TestCase class ServiceTest < ActiveSupport::TestCase
@ -11,7 +9,7 @@ module Whois
result = OpenStruct.new(exit_status: 0) result = OpenStruct.new(exit_status: 0)
mock_system_klass("whois", "example.org", result) do |system_klass| mock_system_klass("whois", "example.org", result) do |system_klass|
service = Service.new("example.org", system_klass: system_klass) service = Whois::Service.new("example.org", system_klass: system_klass)
assert_equal result, service.run_command assert_equal result, service.run_command
end end
end end
@ -20,9 +18,9 @@ module Whois
result = OpenStruct.new(exit_status: 1) result = OpenStruct.new(exit_status: 1)
mock_system_klass("whois", "example.org", result) do |system_klass| mock_system_klass("whois", "example.org", result) do |system_klass|
service = Service.new("example.org", system_klass: system_klass) service = Whois::Service.new("example.org", system_klass: system_klass)
assert_raises WhoisCommandError do assert_raises Whois::CommandError do
service.run_command service.run_command
end end
end end
@ -34,8 +32,8 @@ module Whois
stdout: file_fixture("whois/domain.fr.txt").read, stdout: file_fixture("whois/domain.fr.txt").read,
) )
service = Service.new("domain.fr") service = Whois::Service.new("domain.fr")
assert_kind_of Response, service.parse(result) assert_kind_of Whois::Response, service.parse(result)
end end
def mock_system_klass(program, command_args, result) def mock_system_klass(program, command_args, result)

View File

@ -14,7 +14,7 @@ class ChecksTest < ApplicationSystemTestCase
choose "domain" choose "domain"
fill_and_valid_new_check create_new_check
end end
test "create a predefined domain check" do test "create a predefined domain check" do
@ -22,7 +22,7 @@ class ChecksTest < ApplicationSystemTestCase
refute page.has_css? "domain[kind]" refute page.has_css? "domain[kind]"
fill_and_valid_new_check create_new_check
end end
test "create a manual domain check" do test "create a manual domain check" do
@ -49,7 +49,7 @@ class ChecksTest < ApplicationSystemTestCase
refute page.has_css? "domain[kind]" refute page.has_css? "domain[kind]"
fill_and_valid_new_check create_new_check
end end
test "dettach a notification from a check" do test "dettach a notification from a check" do
@ -277,7 +277,7 @@ class ChecksTest < ApplicationSystemTestCase
# rubocop:disable Metrics/AbcSize # rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength # rubocop:disable Metrics/MethodLength
def fill_and_valid_new_check def create_new_check
domain = "domain-test.fr" domain = "domain-test.fr"
fill_in("check[domain]", with: domain) fill_in("check[domain]", with: domain)
@ -287,7 +287,7 @@ class ChecksTest < ApplicationSystemTestCase
fill_in("check[notifications_attributes][0][recipient]", with: recipient) fill_in("check[notifications_attributes][0][recipient]", with: recipient)
fill_in("check[notifications_attributes][0][interval]", with: 30) fill_in("check[notifications_attributes][0][interval]", with: 30)
click_button click_button I18n.t("helpers.submit.check.create")
assert_equal checks_path, page.current_path assert_equal checks_path, page.current_path

Some files were not shown because too many files have changed in this diff Show More