diff --git a/.rubocop.yml b/.rubocop.yml index 42f280c..795ded7 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,18 +1,23 @@ -inherit_from: .rubocop_todo.yml +require: + - rubocop-rails + AllCops: DisplayCopNames: true - TargetRubyVersion: 2.4 - Include: - - Rakefile - - lib/**/*.rake + TargetRubyVersion: 2.7 + SuggestExtensions: false + NewCops: enable Exclude: - - Gemfile - - Appraisals - - rails-letsencrypt.gemspec - - lib/generators/lets_encrypt/templates/migration.rb + - gemfiles/* - spec/dummy/**/* + - lib/generators/lets_encrypt/templates/* + Rails: Enabled: true + +Naming/FileName: + Exclude: + - lib/rails-letsencrypt.rb + Metrics/BlockLength: Exclude: - spec/**/*.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml deleted file mode 100644 index 84a0984..0000000 --- a/.rubocop_todo.yml +++ /dev/null @@ -1,61 +0,0 @@ -# This configuration was generated by -# `rubocop --auto-gen-config` -# on 2017-05-11 16:33:13 +0800 using RuboCop version 0.48.1. -# The point is for the user to remove these configuration records -# one by one as the offenses are removed from the code base. -# Note that changes in the inspected code, or installation of new -# versions of RuboCop, may require this file to be generated again. - -# Offense count: 1 -Lint/AmbiguousBlockAssociation: - Exclude: - - 'app/models/lets_encrypt/certificate.rb' - -# Offense count: 4 -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. -# URISchemes: http, https -Metrics/LineLength: - Max: 92 - -# Offense count: 1 -# Cop supports --auto-correct. -Style/BlockComments: - Exclude: - - 'spec/spec_helper.rb' - -# Offense count: 1 -# Configuration parameters: ExpectMatchingDefinition, Regex, IgnoreExecutableScripts, AllowedAcronyms. -# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS -Style/FileName: - Exclude: - - 'lib/rails-letsencrypt.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -Style/MutableConstant: - Exclude: - - 'lib/letsencrypt/version.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: SupportedStyles. -# SupportedStyles: use_perl_names, use_english_names -Style/SpecialGlobalVars: - EnforcedStyle: use_perl_names - -# Offense count: 18 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline. -# SupportedStyles: single_quotes, double_quotes -Style/StringLiterals: - Exclude: - - 'rails-letsencrypt.gemspec' - - 'spec/rails_helper.rb' - -# Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, SupportedStyles. -# SupportedStyles: final_newline, final_blank_line -Style/TrailingBlankLines: - Exclude: - - 'rails-letsencrypt.gemspec' diff --git a/Appraisals b/Appraisals index 0cf81bc..8312aee 100644 --- a/Appraisals +++ b/Appraisals @@ -1,21 +1,21 @@ # frozen_string_literal: true appraise 'rails6' do - gem "railties", "~> 6.1" - gem "actionmailer", "~> 6.1" - gem "actionpack", "~> 6.1" - gem "actionview", "~> 6.1" - gem "activemodel", "~> 6.1" - gem "activerecord", "~> 6.1" - gem "activesupport", "~> 6.1" + gem 'railties', '~> 6.1' + gem 'actionmailer', '~> 6.1' + gem 'actionpack', '~> 6.1' + gem 'actionview', '~> 6.1' + gem 'activemodel', '~> 6.1' + gem 'activerecord', '~> 6.1' + gem 'activesupport', '~> 6.1' end appraise 'rails7' do - gem "railties", "~> 7" - gem "actionmailer", "~> 7" - gem "actionpack", "~> 7" - gem "actionview", "~> 7" - gem "activemodel", "~> 7" - gem "activerecord", "~> 7" - gem "activesupport", "~> 7" + gem 'railties', '~> 7' + gem 'actionmailer', '~> 7' + gem 'actionpack', '~> 7' + gem 'actionview', '~> 7' + gem 'activemodel', '~> 7' + gem 'activerecord', '~> 7' + gem 'activesupport', '~> 7' end diff --git a/Gemfile b/Gemfile index fb78959..5f8ea76 100644 --- a/Gemfile +++ b/Gemfile @@ -1,4 +1,5 @@ # frozen_string_literal: true + source 'https://rubygems.org' # Declare your gem's dependencies in lets_encrypt.gemspec. @@ -13,4 +14,9 @@ gemspec # To use a debugger # gem 'byebug', group: [:development, :test] +gem 'appraisal' +gem 'rspec-rails' +gem 'rubocop', '~> 1.57.2' +gem 'rubocop-rails' +gem 'simplecov', '~> 0.16.1' gem 'sqlite3' diff --git a/app/controllers/lets_encrypt/verifications_controller.rb b/app/controllers/lets_encrypt/verifications_controller.rb index 5453d56..fe09304 100644 --- a/app/controllers/lets_encrypt/verifications_controller.rb +++ b/app/controllers/lets_encrypt/verifications_controller.rb @@ -7,7 +7,8 @@ module LetsEncrypt class VerificationsController < ApplicationController def show return render_verification_string if certificate.present? - render plain: 'Verification not found', status: 404 + + render plain: 'Verification not found', status: :not_found end protected diff --git a/app/jobs/lets_encrypt/renew_certificates_job.rb b/app/jobs/lets_encrypt/renew_certificates_job.rb index 4b543aa..87f1f76 100644 --- a/app/jobs/lets_encrypt/renew_certificates_job.rb +++ b/app/jobs/lets_encrypt/renew_certificates_job.rb @@ -8,6 +8,7 @@ class RenewCertificatesJob < ApplicationJob def perform LetsEncrypt.certificate_model.renewable.each do |certificate| next if certificate.renew + certificate.update(renew_after: 1.day.from_now) end end diff --git a/app/models/concerns/lets_encrypt/certificate_issuable.rb b/app/models/concerns/lets_encrypt/certificate_issuable.rb index a07ffa2..c0863a7 100644 --- a/app/models/concerns/lets_encrypt/certificate_issuable.rb +++ b/app/models/concerns/lets_encrypt/certificate_issuable.rb @@ -9,9 +9,7 @@ module CertificateIssuable def issue logger.info "Getting certificate for #{domain}" create_certificate - # rubocop:disable Metrics/LineLength logger.info "Certificate issued for #{domain} (expires on #{expires_at}, will renew after #{renew_after})" - # rubocop:enable Metrics/LineLength true end @@ -30,12 +28,16 @@ def create_certificate order.finalize(csr: csr) sleep 1 while order.status == 'processing' fullchain = order.certificate.split("\n\n") + assign_new_certificate(fullchain) + save! + end + + def assign_new_certificate(fullchain) cert = OpenSSL::X509::Certificate.new(fullchain.shift) self.certificate = cert.to_pem self.intermediaries = fullchain.join("\n\n") self.expires_at = cert.not_after self.renew_after = (expires_at - 1.month) + rand(10).days - save! end end end diff --git a/app/models/concerns/lets_encrypt/certificate_verifiable.rb b/app/models/concerns/lets_encrypt/certificate_verifiable.rb index 0b2db5d..22a25a3 100644 --- a/app/models/concerns/lets_encrypt/certificate_verifiable.rb +++ b/app/models/concerns/lets_encrypt/certificate_verifiable.rb @@ -52,16 +52,16 @@ def check_verify_status true end - def retry_on_verify_error(e) + def retry_on_verify_error(error) @retries ||= 0 - if e.is_a?(Acme::Client::Error::BadNonce) && @retries < 5 + if error.is_a?(Acme::Client::Error::BadNonce) && @retries < 5 @retries += 1 logger.info "#{domain}: Bad nounce encountered. Retrying (#{@retries} of 5 attempts)" sleep 1 verify else logger.info "#{domain}: Error: #{e.class} (#{e.message})" - return false + false end end end diff --git a/app/models/lets_encrypt/certificate.rb b/app/models/lets_encrypt/certificate.rb index 9cc8489..fafafdc 100644 --- a/app/models/lets_encrypt/certificate.rb +++ b/app/models/lets_encrypt/certificate.rb @@ -22,7 +22,7 @@ module LetsEncrypt # index_letsencrypt_certificates_on_domain (domain) # index_letsencrypt_certificates_on_renew_after (renew_after) # - class Certificate < ActiveRecord::Base + class Certificate < ApplicationRecord include CertificateVerifiable include CertificateIssuable @@ -33,8 +33,8 @@ class Certificate < ActiveRecord::Base scope :expired, -> { where('expires_at <= ?', Time.zone.now) } before_create -> { self.key = OpenSSL::PKey::RSA.new(4096).to_s } - after_save -> { save_to_redis }, if: -> { LetsEncrypt.config.use_redis? && active? } after_destroy -> { delete_from_redis }, if: -> { LetsEncrypt.config.use_redis? && active? } + after_save -> { save_to_redis }, if: -> { LetsEncrypt.config.use_redis? && active? } # Returns false if certificate is not issued. # diff --git a/bin/rails b/bin/rails index b685479..b5bbca4 100755 --- a/bin/rails +++ b/bin/rails @@ -4,11 +4,11 @@ # This command will automatically be run when you run "rails" with Rails gems # installed from the root of your application. -ENGINE_ROOT = File.expand_path('../..', __FILE__) -ENGINE_PATH = File.expand_path('../../lib/letsencrypt/engine', __FILE__) +ENGINE_ROOT = File.expand_path('..', __dir__) +ENGINE_PATH = File.expand_path('../lib/letsencrypt/engine', __dir__) # Set up gems listed in the Gemfile. -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) require 'rails/all' diff --git a/gemfiles/rails6.gemfile b/gemfiles/rails6.gemfile index 09e4545..da92a6e 100644 --- a/gemfiles/rails6.gemfile +++ b/gemfiles/rails6.gemfile @@ -2,6 +2,11 @@ source "https://rubygems.org" +gem "appraisal" +gem "rspec-rails" +gem "rubocop", "~> 1.57.2" +gem "rubocop-rails" +gem "simplecov", "~> 0.16.1" gem "sqlite3" gem "railties", "~> 6.1" gem "actionmailer", "~> 6.1" diff --git a/gemfiles/rails6.gemfile.lock b/gemfiles/rails6.gemfile.lock index 44867b6..4f90a97 100644 --- a/gemfiles/rails6.gemfile.lock +++ b/gemfiles/rails6.gemfile.lock @@ -56,12 +56,13 @@ GEM bundler rake thor (>= 0.14.0) - base64 (0.1.1) + ast (2.4.2) + base64 (0.2.0) builder (3.2.4) concurrent-ruby (1.2.2) connection_pool (2.4.1) crass (1.0.6) - date (3.3.3) + date (3.3.4) diff-lcs (1.5.0) docile (1.4.0) erubi (1.12.0) @@ -77,6 +78,7 @@ GEM i18n (1.14.1) concurrent-ruby (~> 1.0) json (2.6.3) + language_server-protocol (3.17.0.3) loofah (2.21.4) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -87,24 +89,24 @@ GEM net-smtp method_source (1.0.0) mini_mime (1.1.5) - mini_portile2 (2.8.5) minitest (5.20.0) net-imap (0.4.4) date net-protocol net-pop (0.1.2) net-protocol - net-protocol (0.2.1) + net-protocol (0.2.2) timeout net-smtp (0.4.0) net-protocol - nokogiri (1.15.4) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) nokogiri (1.15.4-x86_64-darwin) racc (~> 1.4) nokogiri (1.15.4-x86_64-linux) racc (~> 1.4) + parallel (1.23.0) + parser (3.2.2.4) + ast (~> 2.4.1) + racc racc (1.7.3) rack (2.2.8) rack-test (2.1.0) @@ -122,11 +124,14 @@ GEM method_source rake (>= 12.2) thor (~> 1.0) + rainbow (3.1.1) rake (13.1.0) redis (5.0.8) redis-client (>= 0.17.0) redis-client (0.18.0) connection_pool + regexp_parser (2.8.2) + rexml (3.2.6) rspec-core (3.12.2) rspec-support (~> 3.12.0) rspec-expectations (3.12.3) @@ -144,24 +149,40 @@ GEM rspec-mocks (~> 3.12) rspec-support (~> 3.12) rspec-support (3.12.1) + rubocop (1.57.2) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.2.2.4) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.30.0) + parser (>= 3.2.1.0) + rubocop-rails (2.22.1) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.33.0, < 2.0) + ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) - sqlite3 (1.6.8) - mini_portile2 (~> 2.8.0) sqlite3 (1.6.8-x86_64-darwin) sqlite3 (1.6.8-x86_64-linux) thor (1.3.0) - timeout (0.4.0) + timeout (0.4.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) + unicode-display_width (2.5.0) zeitwerk (2.6.12) PLATFORMS - ruby x86_64-darwin-22 x86_64-linux @@ -176,6 +197,8 @@ DEPENDENCIES rails-letsencrypt! railties (~> 6.1) rspec-rails + rubocop (~> 1.57.2) + rubocop-rails simplecov (~> 0.16.1) sqlite3 diff --git a/gemfiles/rails7.gemfile b/gemfiles/rails7.gemfile index 5cd5d6a..7d4b25d 100644 --- a/gemfiles/rails7.gemfile +++ b/gemfiles/rails7.gemfile @@ -2,6 +2,11 @@ source "https://rubygems.org" +gem "appraisal" +gem "rspec-rails" +gem "rubocop", "~> 1.57.2" +gem "rubocop-rails" +gem "simplecov", "~> 0.16.1" gem "sqlite3" gem "railties", "~> 7" gem "actionmailer", "~> 7" diff --git a/gemfiles/rails7.gemfile.lock b/gemfiles/rails7.gemfile.lock index 78c35b4..65f75bb 100644 --- a/gemfiles/rails7.gemfile.lock +++ b/gemfiles/rails7.gemfile.lock @@ -66,16 +66,17 @@ GEM bundler rake thor (>= 0.14.0) - base64 (0.1.1) + ast (2.4.2) + base64 (0.2.0) bigdecimal (3.1.4) builder (3.2.4) concurrent-ruby (1.2.2) connection_pool (2.4.1) crass (1.0.6) - date (3.3.3) + date (3.3.4) diff-lcs (1.5.0) docile (1.4.0) - drb (2.1.1) + drb (2.2.0) ruby2_keywords erubi (1.12.0) faraday (2.7.11) @@ -94,6 +95,7 @@ GEM rdoc reline (>= 0.3.8) json (2.6.3) + language_server-protocol (3.17.0.3) loofah (2.21.4) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -103,7 +105,6 @@ GEM net-pop net-smtp mini_mime (1.1.5) - mini_portile2 (2.8.5) minitest (5.20.0) mutex_m (0.2.0) net-imap (0.4.4) @@ -111,17 +112,18 @@ GEM net-protocol net-pop (0.1.2) net-protocol - net-protocol (0.2.1) + net-protocol (0.2.2) timeout net-smtp (0.4.0) net-protocol - nokogiri (1.15.4) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) nokogiri (1.15.4-x86_64-darwin) racc (~> 1.4) nokogiri (1.15.4-x86_64-linux) racc (~> 1.4) + parallel (1.23.0) + parser (3.2.2.4) + ast (~> 2.4.1) + racc psych (5.1.1.1) stringio racc (1.7.3) @@ -148,6 +150,7 @@ GEM rake (>= 12.2) thor (~> 1.0, >= 1.2.2) zeitwerk (~> 2.6) + rainbow (3.1.1) rake (13.1.0) rdoc (6.6.0) psych (>= 4.0.0) @@ -155,8 +158,10 @@ GEM redis-client (>= 0.17.0) redis-client (0.18.0) connection_pool + regexp_parser (2.8.2) reline (0.3.9) io-console (~> 0.5) + rexml (3.2.6) rspec-core (3.12.2) rspec-support (~> 3.12.0) rspec-expectations (3.12.3) @@ -174,26 +179,42 @@ GEM rspec-mocks (~> 3.12) rspec-support (~> 3.12) rspec-support (3.12.1) + rubocop (1.57.2) + json (~> 2.3) + language_server-protocol (>= 3.17.0) + parallel (~> 1.10) + parser (>= 3.2.2.4) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.1, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.30.0) + parser (>= 3.2.1.0) + rubocop-rails (2.22.1) + activesupport (>= 4.2.0) + rack (>= 1.1) + rubocop (>= 1.33.0, < 2.0) + ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) simplecov (0.16.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) - sqlite3 (1.6.8) - mini_portile2 (~> 2.8.0) sqlite3 (1.6.8-x86_64-darwin) sqlite3 (1.6.8-x86_64-linux) stringio (3.0.8) thor (1.3.0) - timeout (0.4.0) + timeout (0.4.1) tzinfo (2.0.6) concurrent-ruby (~> 1.0) + unicode-display_width (2.5.0) webrick (1.8.1) zeitwerk (2.6.12) PLATFORMS - ruby x86_64-darwin-22 x86_64-linux @@ -208,6 +229,8 @@ DEPENDENCIES rails-letsencrypt! railties (~> 7) rspec-rails + rubocop (~> 1.57.2) + rubocop-rails simplecov (~> 0.16.1) sqlite3 diff --git a/lib/generators/lets_encrypt/install_generator.rb b/lib/generators/lets_encrypt/install_generator.rb index 171e45d..658094b 100644 --- a/lib/generators/lets_encrypt/install_generator.rb +++ b/lib/generators/lets_encrypt/install_generator.rb @@ -10,7 +10,7 @@ module Generators class InstallGenerator < ::Rails::Generators::Base include ::Rails::Generators::Migration - source_root File.expand_path('../templates', __FILE__) + source_root File.expand_path('templates', __dir__) def self.next_migration_number(path) ActiveRecord::Generators::Base.next_migration_number(path) diff --git a/lib/generators/lets_encrypt/register_generator.rb b/lib/generators/lets_encrypt/register_generator.rb index 33b2781..e496c5d 100644 --- a/lib/generators/lets_encrypt/register_generator.rb +++ b/lib/generators/lets_encrypt/register_generator.rb @@ -26,26 +26,24 @@ def setup_environment end def generate_key - # rubocop:disable Metrics/LineLength key_path = ask("Where you to save private key [#{LetsEncrypt.private_key_path}]:", path: true) - # rubocop:enable Metrics/LineLength key_path = LetsEncrypt.private_key_path if key_path.blank? return unless file_collision(key_path) - FileUtils.rm(key_path) if File.exist?(key_path) + + FileUtils.rm_f(key_path) LetsEncrypt.config.use_env_key = false LetsEncrypt.config.private_key_path = key_path LetsEncrypt.load_private_key - # rubocop:disable Metrics/LineLength say "Your privated key is saved in #{key_path}, make sure setup configure for your rails.", :yellow - # rubocop:enable Metrics/LineLength end def register_email email = ask('What email you want to register:') return say('Email is inavlid!', :red) if email.blank? + LetsEncrypt.register(email) say 'Register successed, don\'t forget backup your private key', :green end diff --git a/lib/letsencrypt.rb b/lib/letsencrypt.rb index 5d8f378..e2b124f 100644 --- a/lib/letsencrypt.rb +++ b/lib/letsencrypt.rb @@ -32,14 +32,15 @@ def private_key end def load_private_key - return ENV['LETSENCRYPT_PRIVATE_KEY'] if config.use_env_key + return ENV.fetch('LETSENCRYPT_PRIVATE_KEY', nil) if config.use_env_key return File.open(private_key_path) if File.exist?(private_key_path) + generate_private_key end # Get current using Let's Encrypt endpoint def directory - @endpoint ||= config.use_staging? ? ENDPOINT_STAGING : ENDPOINT + @directory ||= config.use_staging? ? ENDPOINT_STAGING : ENDPOINT end # Register a Let's Encrypt account @@ -56,12 +57,12 @@ def register(email) end def private_key_path - config.private_key_path || Rails.root.join('config', 'letsencrypt.key') + config.private_key_path || Rails.root.join('config/letsencrypt.key') end def generate_private_key key = OpenSSL::PKey::RSA.new(4096) - File.open(private_key_path, 'w') { |f| f.write(key.to_s) } + File.write(private_key_path, key.to_s) logger.info "Created new private key for Let's Encrypt" key end diff --git a/lib/letsencrypt/logger_proxy.rb b/lib/letsencrypt/logger_proxy.rb index 875b29b..816435b 100644 --- a/lib/letsencrypt/logger_proxy.rb +++ b/lib/letsencrypt/logger_proxy.rb @@ -15,10 +15,10 @@ def add_tags(*tags) @tags = @tags.uniq end - def tag(logger) + def tag(logger, &block) if logger.respond_to?(:tagged) current_tags = tags - logger.formatter.current_tags - logger.tagged(*current_tags) { yield } + logger.tagged(*current_tags, &block) else yield end diff --git a/lib/letsencrypt/redis.rb b/lib/letsencrypt/redis.rb index 5bb2045..ac402b8 100644 --- a/lib/letsencrypt/redis.rb +++ b/lib/letsencrypt/redis.rb @@ -11,6 +11,7 @@ def connection # Save certificate into redis. def save(cert) return unless cert.key.present? && cert.bundle.present? + LetsEncrypt.logger.info "Save #{cert.domain}'s certificate (bundle) to redis" connection.set "#{cert.domain}.key", cert.key connection.set "#{cert.domain}.crt", cert.bundle @@ -19,6 +20,7 @@ def save(cert) # Delete certificate from redis. def delete(cert) return unless cert.key.present? && cert.certificate.present? + LetsEncrypt.logger.info "Delete #{cert.domain}'s certificate from redis" connection.del "#{cert.domain}.key" connection.del "#{cert.domain}.crt" diff --git a/lib/tasks/letsencrypt_tasks.rake b/lib/tasks/letsencrypt_tasks.rake index 8b31132..eb30233 100644 --- a/lib/tasks/letsencrypt_tasks.rake +++ b/lib/tasks/letsencrypt_tasks.rake @@ -1,7 +1,7 @@ # frozen_string_literal: true namespace :letsencrypt do - desc "Renew certificates that already expired or expiring soon" + desc 'Renew certificates that already expired or expiring soon' task renew: :environment do count = 0 failed = 0 diff --git a/rails-letsencrypt.gemspec b/rails-letsencrypt.gemspec index 5cd7ca4..fd7ac85 100644 --- a/rails-letsencrypt.gemspec +++ b/rails-letsencrypt.gemspec @@ -1,35 +1,33 @@ # frozen_string_literal: true -$:.push File.expand_path("../lib", __FILE__) +$LOAD_PATH.push File.expand_path('lib', __dir__) # Maintain your gem's version: -require "letsencrypt/version" +require 'letsencrypt/version' # Describe your gem and declare its dependencies: Gem::Specification.new do |s| - s.name = "rails-letsencrypt" + s.name = 'rails-letsencrypt' s.version = LetsEncrypt::VERSION - s.authors = ["蒼時弦也"] - s.email = ["elct9620@frost.tw"] - s.homepage = "https://github.com/elct9620/rails-letsencrypt" + s.authors = ['蒼時弦也'] + s.email = ['elct9620@frost.tw'] + s.homepage = 'https://github.com/elct9620/rails-letsencrypt' s.summary = "The Let's Encrypt certificate manager for rails" s.description = "The Let's Encrypt certificate manager for rails" - s.license = "MIT" + s.license = 'MIT' - s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] - s.require_paths = ["lib"] + s.files = Dir['{app,config,db,lib}/**/*', 'MIT-LICENSE', 'Rakefile', 'README.md'] + s.require_paths = ['lib'] - s.add_dependency "railties", ">= 6.1" - s.add_dependency "actionmailer", ">= 6.1" - s.add_dependency "actionpack", ">= 6.1" - s.add_dependency "actionview", ">= 6.1" - s.add_dependency "activemodel", ">= 6.1" - s.add_dependency "activerecord", ">= 6.1" - s.add_dependency "activesupport", ">= 6.1" - s.add_dependency "acme-client", "~> 2.0.0" - s.add_dependency "redis" - - s.add_development_dependency "appraisal" - s.add_development_dependency "rspec-rails" - s.add_development_dependency "simplecov", "~> 0.16.1" + s.required_ruby_version = '>= 2.7.0' + s.add_dependency 'acme-client', '~> 2.0.0' + s.add_dependency 'actionmailer', '>= 6.1' + s.add_dependency 'actionpack', '>= 6.1' + s.add_dependency 'actionview', '>= 6.1' + s.add_dependency 'activemodel', '>= 6.1' + s.add_dependency 'activerecord', '>= 6.1' + s.add_dependency 'activesupport', '>= 6.1' + s.add_dependency 'railties', '>= 6.1' + s.add_dependency 'redis' + s.metadata['rubygems_mfa_required'] = 'true' end diff --git a/spec/controllers/lets_encrypt/verifications_controller_spec.rb b/spec/controllers/lets_encrypt/verifications_controller_spec.rb index d2d275a..dcb1569 100644 --- a/spec/controllers/lets_encrypt/verifications_controller_spec.rb +++ b/spec/controllers/lets_encrypt/verifications_controller_spec.rb @@ -4,7 +4,9 @@ RSpec.describe LetsEncrypt::VerificationsController, type: :controller do routes { LetsEncrypt::Engine.routes } - class OtherModel < LetsEncrypt::Certificate + + before do + stub_const('LetsEncrypt::Certificate', Class.new(LetsEncrypt::Certificate)) end it 'returns 404 status when no valid verification path found' do @@ -12,7 +14,6 @@ class OtherModel < LetsEncrypt::Certificate expect(response.status).to eq(404) end - describe 'has certificate' do context 'with default model' do let!(:certificate) do diff --git a/spec/letsencrypt/configuration_spec.rb b/spec/letsencrypt/configuration_spec.rb index d5a2842..e1520fd 100644 --- a/spec/letsencrypt/configuration_spec.rb +++ b/spec/letsencrypt/configuration_spec.rb @@ -18,15 +18,16 @@ end describe 'customize certificate model' do - class OtherModel < LetsEncrypt::Certificate - after_update :success + before(:each) do + stub_const('OtherModel', Class.new(LetsEncrypt::Certificate)) - def success - 'success' + OtherModel.after_update :success + OtherModel.class_eval do + def success + 'success' + end end - end - before(:each) do LetsEncrypt.config.certificate_model = 'OtherModel' allow(LetsEncrypt).to receive(:certificate_model).and_return(OtherModel) LetsEncrypt.certificate_model.create( diff --git a/spec/letsencrypt/generators/lets_encrypt/install_generator_spec.rb b/spec/letsencrypt/generators/lets_encrypt/install_generator_spec.rb index fceb86b..26e4594 100644 --- a/spec/letsencrypt/generators/lets_encrypt/install_generator_spec.rb +++ b/spec/letsencrypt/generators/lets_encrypt/install_generator_spec.rb @@ -6,7 +6,7 @@ RSpec.describe LetsEncrypt::Generators::InstallGenerator do before(:all) do - @dummy_class = Class.new(::Rails::Generators::TestCase) do + @dummy_class = Class.new(Rails::Generators::TestCase) do tests LetsEncrypt::Generators::InstallGenerator destination Rails.root.join('tmp') end @@ -17,6 +17,6 @@ end it do - @generator.assert_migration "db/migrate/create_letsencrypt_certificates.rb", /def change/ + @generator.assert_migration 'db/migrate/create_letsencrypt_certificates.rb', /def change/ end end diff --git a/spec/letsencrypt/generators/lets_encrypt/register_generator_spec.rb b/spec/letsencrypt/generators/lets_encrypt/register_generator_spec.rb index 21b8baf..c06db28 100644 --- a/spec/letsencrypt/generators/lets_encrypt/register_generator_spec.rb +++ b/spec/letsencrypt/generators/lets_encrypt/register_generator_spec.rb @@ -6,7 +6,7 @@ RSpec.describe LetsEncrypt::Generators::RegisterGenerator do before(:all) do - @dummy_class = Class.new(::Rails::Generators::TestCase) do + @dummy_class = Class.new(Rails::Generators::TestCase) do tests LetsEncrypt::Generators::RegisterGenerator destination Rails.root.join('tmp') end diff --git a/spec/letsencrypt/redis_spec.rb b/spec/letsencrypt/redis_spec.rb index 1cd2d93..b020f54 100644 --- a/spec/letsencrypt/redis_spec.rb +++ b/spec/letsencrypt/redis_spec.rb @@ -3,25 +3,25 @@ require 'rails_helper' RSpec.describe LetsEncrypt::Redis do - let(:redis) { double(::Redis) } + let(:redis) { double(Redis) } let(:domain) { 'example.com' } let(:certificate) do LetsEncrypt::Certificate.new(domain: domain, key: '', certificate: '') end before(:each) do - allow(::Redis).to receive(:new).and_return(redis) + allow(Redis).to receive(:new).and_return(redis) end after do # Reset connection because redis double will work only for single example - LetsEncrypt::Redis.instance_variable_set("@connection", nil) + LetsEncrypt::Redis.instance_variable_set('@connection', nil) end describe '#save' do it 'saves certificate into redis' do - certificate.key = "KEY" - certificate.certificate = "CERTIFICATE" + certificate.key = 'KEY' + certificate.certificate = 'CERTIFICATE' expect(redis).to receive(:set).with("#{domain}.key", an_instance_of(String)) expect(redis).to receive(:set).with("#{domain}.crt", an_instance_of(String)) LetsEncrypt::Redis.save(certificate) @@ -36,8 +36,8 @@ describe '#delete' do it 'deletes certificate from redis' do - certificate.key = "KEY" - certificate.certificate = "CERTIFICATE" + certificate.key = 'KEY' + certificate.certificate = 'CERTIFICATE' expect(redis).to receive(:del).with("#{domain}.key") expect(redis).to receive(:del).with("#{domain}.crt") LetsEncrypt::Redis.delete(certificate) diff --git a/spec/letsencrypt_spec.rb b/spec/letsencrypt_spec.rb index 4ea5a3f..a4d288a 100644 --- a/spec/letsencrypt_spec.rb +++ b/spec/letsencrypt_spec.rb @@ -23,7 +23,7 @@ end describe '#register' do - let(:acme_client) { double(::Acme::Client) } + let(:acme_client) { double(Acme::Client) } let(:acme_account) { double } it 'register new account to Let\'s Encrypt' do @@ -39,9 +39,9 @@ end describe 'certificate_model' do - class OtherModel < LetsEncrypt::Certificate - end before do + stub_const('OtherModel', Class.new(LetsEncrypt::Certificate)) + LetsEncrypt.config.certificate_model = 'OtherModel' allow(LetsEncrypt).to receive(:certificate_model) { LetsEncrypt.config.certificate_model.constantize } end diff --git a/spec/models/lets_encrypt/certificate_spec.rb b/spec/models/lets_encrypt/certificate_spec.rb index e338e0f..3d17873 100644 --- a/spec/models/lets_encrypt/certificate_spec.rb +++ b/spec/models/lets_encrypt/certificate_spec.rb @@ -13,8 +13,7 @@ LetsEncrypt.config.save_to_redis = false mock_cert.public_key = key.public_key - mock_cert.sign(key, OpenSSL::Digest::SHA256.new) - + mock_cert.sign(key, OpenSSL::Digest.new('SHA256')) end describe '#active?' do @@ -90,7 +89,7 @@ describe '#verify' do subject(:cert) { LetsEncrypt::Certificate.new(domain: 'example.com') } - let(:acme_client) { double(::Acme::Client) } + let(:acme_client) { double(Acme::Client) } let(:acme_order) { double } let(:acme_authorization) { double } let(:acme_challenge) { double } @@ -104,12 +103,10 @@ allow(acme_authorization).to receive(:http).and_return(acme_challenge) allow(acme_challenge).to receive(:reload) - # rubocop:disable Metrics/LineLength allow(acme_challenge).to receive(:filename).and_return('.well-known/acme-challenge/path').at_least(1).times allow(acme_challenge).to receive(:file_content).and_return('content').at_least(1).times allow(acme_challenge).to receive(:request_validation).and_return(true).at_least(1).times - # rubocop:enable Metrics/LineLength end describe 'when status is valid' do @@ -118,7 +115,6 @@ it { is_expected.to have_attributes(verify: true) } end - describe 'when status is pending to valid' do before do allow(acme_challenge).to receive(:status).and_return('pending') @@ -130,7 +126,7 @@ describe 'when Acme::Client::Error is raised' do before do - allow(acme_challenge).to receive(:status).and_raise(::Acme::Client::Error::BadNonce) + allow(acme_challenge).to receive(:status).and_raise(Acme::Client::Error::BadNonce) allow(acme_challenge).to receive(:status).and_return('valid') end @@ -141,7 +137,7 @@ describe '#issue' do subject(:cert) { LetsEncrypt::Certificate.new(domain: 'example.com', key: key) } - let(:acme_client) { double(::Acme::Client) } + let(:acme_client) { double(Acme::Client) } let(:acme_order) { double } let(:mock_cert) { OpenSSL::X509::Certificate.new } @@ -151,7 +147,7 @@ mock_cert.subject = OpenSSL::X509::Name.parse('CN=example.com/C=EE') mock_cert.not_before = Time.zone.now mock_cert.not_after = 1.month.from_now - mock_cert.sign(key, OpenSSL::Digest::SHA256.new) + mock_cert.sign(key, OpenSSL::Digest.new('SHA256')) allow(LetsEncrypt).to receive(:client).and_return(acme_client) allow(acme_client).to receive(:new_order).and_return(acme_order) diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 3d4f397..c1f57bb 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -3,9 +3,9 @@ # This file is copied to spec/ when you run 'rails generate rspec:install' require 'spec_helper' ENV['RAILS_ENV'] ||= 'test' -require File.expand_path('../dummy/config/environment', __FILE__) +require File.expand_path('dummy/config/environment', __dir__) # Prevent database truncation if the environment is production -abort("The Rails environment is running in production mode!") if Rails.env.production? +abort('The Rails environment is running in production mode!') if Rails.env.production? require 'rspec/rails' # Add additional requires below this line. Rails is not loaded until this point! @@ -22,19 +22,16 @@ # directory. Alternatively, in the individual `*_spec.rb` files, manually # require only the support files necessary. # -Dir[File.expand_path("../../spec/support/**/*.rb", __FILE__)].each { |f| require f } - -# rubocop:disable Metrics/LineLength -ActiveRecord::Migrator.migrations_paths = [File.expand_path("../../spec/dummy/db/migrate", __FILE__)] -# rubocop:enable Metrics/LineLength +Dir[File.expand_path('../spec/support/**/*.rb', __dir__)].sort.each { |f| require f } +ActiveRecord::Migrator.migrations_paths = [File.expand_path('../spec/dummy/db/migrate', __dir__)] # Checks for pending migrations before tests are run. # If you are not using ActiveRecord, you can remove this line. ActiveRecord::Migration.maintain_test_schema! RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures - config.fixture_path = "#{::Rails.root}/spec/fixtures" + config.fixture_path = Rails.root.join('spec/fixtures').to_s # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c88b77a..f8a6674 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -21,7 +21,7 @@ SimpleCov.start do formatter SimpleCov::Formatter::MultiFormatter.new( [ - SimpleCov::Formatter::HTMLFormatter, + SimpleCov::Formatter::HTMLFormatter ] ) @@ -69,53 +69,51 @@ # triggering implicit auto-inclusion in groups with matching metadata. config.shared_context_metadata_behavior = :apply_to_host_groups -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # This allows you to limit a spec run to individual examples or groups - # you care about by tagging them with `:focus` metadata. When nothing - # is tagged with `:focus`, all examples get run. RSpec also provides - # aliases for `it`, `describe`, and `context` that include `:focus` - # metadata: `fit`, `fdescribe` and `fcontext`, respectively. - config.filter_run_when_matching :focus - - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = 'spec/examples.txt' - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ - # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode - config.disable_monkey_patching! - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = 'doc' - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # Run specs in random order to surface order dependencies. If you find an - # order dependency and want to debug it, you can fix the order by providing - # the seed, which is printed after each run. - # --seed 1234 - config.order = :random - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end + # The settings below are suggested to provide a good initial experience + # with RSpec, but feel free to customize to your heart's content. + # # This allows you to limit a spec run to individual examples or groups + # # you care about by tagging them with `:focus` metadata. When nothing + # # is tagged with `:focus`, all examples get run. RSpec also provides + # # aliases for `it`, `describe`, and `context` that include `:focus` + # # metadata: `fit`, `fdescribe` and `fcontext`, respectively. + # config.filter_run_when_matching :focus + # + # # Allows RSpec to persist some state between runs in order to support + # # the `--only-failures` and `--next-failure` CLI options. We recommend + # # you configure your source control system to ignore this file. + # config.example_status_persistence_file_path = 'spec/examples.txt' + # + # # Limits the available syntax to the non-monkey patched syntax that is + # # recommended. For more details, see: + # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + # config.disable_monkey_patching! + # + # # Many RSpec users commonly either run the entire suite or an individual + # # file, and it's useful to allow more verbose output when running an + # # individual spec file. + # if config.files_to_run.one? + # # Use the documentation formatter for detailed output, + # # unless a formatter has already been configured + # # (e.g. via a command-line flag). + # config.default_formatter = 'doc' + # end + # + # # Print the 10 slowest examples and example groups at the + # # end of the spec run, to help surface which specs are running + # # particularly slow. + # config.profile_examples = 10 + # + # # Run specs in random order to surface order dependencies. If you find an + # # order dependency and want to debug it, you can fix the order by providing + # # the seed, which is printed after each run. + # # --seed 1234 + # config.order = :random + # + # # Seed global randomization in this process using the `--seed` CLI option. + # # Setting this allows you to use `--seed` to deterministically reproduce + # # test failures related to randomization by passing the same `--seed` value + # # as the one that triggered the failure. + # Kernel.srand config.seed end