codeword 0.2.0.beta3 → 0.2.0.beta4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f6ffa70037e0cddb9a44c6fc47a7bd9e8f903570f3e78a2961221d25cd465e5b
4
- data.tar.gz: 500afbda48f4632781878ef18b174505b1380b1d1afa86dd85e9f56c70d4b053
3
+ metadata.gz: cb390e385a9ce1fe7f4e8f987be5e02d1542795d209d74d282887f93cbc03c33
4
+ data.tar.gz: 9f53cfbc92b062d4c531d025535f93213ac7bebed588233aa37b7c7036501764
5
5
  SHA512:
6
- metadata.gz: dd9703d78d830e6127fe13f77160d6ce6279b16f427a17283a100fb885934f5c97ffc6a345442b09e54c8fde882fee14474fef5e9e171d70dc90ad3133c0cd57
7
- data.tar.gz: ef8fef69c8596dbb4f978f969841251de17ec1f87f245c4afc65254211f5ecac9e7ef94c48813b9f82e9c6f034b41c37c8904e805056f50b639cf5ec34316271
6
+ metadata.gz: 966df1e8a10079976ff0efe940935c67a634ae0de335d702e6c74a8af314d88c18d1beb97edf7dbdeb93e09e1c5e305ed355ae898a1799879d33c701b019cc5b
7
+ data.tar.gz: a62f1f572a373e268f661bfedfab93049f85ec034d07547735a7b5049d8920defd71a82aad11dba4137ae905278c3de4500eb94c4225ddefe2ce2b35aa0a3f97
data/CHANGELOG.md CHANGED
@@ -1,9 +1,15 @@
1
1
  ## [Unreleased]
2
2
 
3
+ - BREAKING: Only support namespaced Rails credentials under `codeword` (e.g. `codeword.codeword`, `codeword.hint`, `codeword.cookie_lifetime_in_weeks`)
3
4
  - BREAKING: Drop support for Rails < 7.2
4
5
  - BREAKING: Rename `check_for_codeword` to `require_codeword!`
5
6
  - BREAKING: Deprecate Rails secrets in favor of Rails credentials
6
- - BREAKING: Drop support for Rails < 6.0
7
+ - BREAKING: Remove lowercase ENV variable support (only uppercase ENV variables are now supported)
8
+
9
+ - Prevent open redirects by using `allow_other_host: false`
10
+ - Harden cookie with `httponly: true`, `same_site: :lax`, and `secure: request.ssl?`
11
+ - `codeword_cookie_lifetime` now returns an `ActiveSupport::Duration`; cookie expiry uses `from_now`
12
+ - Updated crawler detection regex (removed duplicate `spider` and generic `click` token)
7
13
 
8
14
  ## [0.1.1] - 2021-12-17
9
15
 
data/README.md CHANGED
@@ -21,22 +21,22 @@ gem 'codeword'
21
21
  mount Codeword::Engine, at: '/codeword'
22
22
  ```
23
23
 
24
- 4. Include the `Codeword` module in your application_controller.rb file and check for codeword:
24
+ 4. Include the `Codeword::Authentication` module in your application_controller.rb file and check for codeword:
25
25
 
26
26
  ```ruby
27
27
  # app/controllers/application_controller.rb
28
28
  class ApplicationController < ActionController::Base
29
- include Codeword
29
+ include Codeword::Authentication
30
30
 
31
31
  before_action :require_codeword!
32
32
  end
33
33
  ```
34
34
 
35
- 5. Skip the check for codeword in the controller(s) you would like to restrict:
35
+ 5. Skip the check for codeword in the controller(s) you would like to allow:
36
36
 
37
37
  ```ruby
38
38
  class APIController < ApplicationController
39
- skip_before_action :require_codeword!, raise: false
39
+ skip_before_action :require_codeword!
40
40
  end
41
41
  ```
42
42
 
@@ -56,17 +56,11 @@ ENV['CODEWORD_HINT'] = 'Something that you do not tell everyone.'
56
56
 
57
57
  You can add your codeword via Rails credentials in your `credentials.yml.enc` file (`$ bin/rails credentials:edit`):
58
58
 
59
- ```yml
60
- codeword: "love"
61
- codeword_hint: "Pepé Le Pew"
62
- ```
63
-
64
- Alternately, credentials in Rails >= 5.2 may be organized under the `codeword` namespace:
65
-
66
59
  ```yml
67
60
  codeword:
68
61
  codeword: "love"
69
62
  hint: "Pepé Le Pew"
63
+ cookie_lifetime_in_weeks: 4
70
64
  ```
71
65
 
72
66
  **Codewords are not case-sensitive, by design. Keep it simple.**
@@ -1,6 +1,6 @@
1
1
  module Codeword
2
2
  class CodewordController < Codeword::ApplicationController
3
- CRAWLER_REGEX = /crawl|googlebot|slurp|spider|bingbot|tracker|click|parser|spider/
3
+ CRAWLER_REGEX = /crawl|googlebot|slurp|spider|bingbot|tracker|parser/
4
4
 
5
5
  skip_before_action :require_codeword!, raise: false
6
6
 
@@ -14,7 +14,7 @@ module Codeword
14
14
  if params[:codeword].present?
15
15
  @codeword = params[:codeword].to_s.downcase
16
16
  @return_to = params[:return_to]
17
- if @codeword == codeword_code.to_s.downcase
17
+ if @codeword == Codeword::Configuration.codeword_code.to_s.downcase
18
18
  set_cookie
19
19
  run_redirect
20
20
  else
@@ -28,15 +28,23 @@ module Codeword
28
28
  private
29
29
 
30
30
  def set_cookie
31
- cookies[:codeword] = { value: @codeword.to_s.downcase, expires: (Time.now + codeword_cookie_lifetime) }
31
+ cookies[:codeword] = {
32
+ value: @codeword.to_s.downcase,
33
+ expires: Codeword::Configuration.codeword_cookie_lifetime.from_now,
34
+ httponly: true,
35
+ secure: request.ssl?,
36
+ same_site: :lax
37
+ }
32
38
  end
33
39
 
34
40
  def run_redirect
35
41
  if @return_to.present?
36
- redirect_to @return_to.to_s
42
+ redirect_to @return_to.to_s, allow_other_host: false
37
43
  else
38
44
  redirect_to '/'
39
45
  end
46
+ rescue ActionController::Redirecting::UnsafeRedirectError
47
+ redirect_to '/'
40
48
  end
41
49
  end
42
50
  end
@@ -3,7 +3,7 @@
3
3
  module Codeword
4
4
  module CodewordHelper
5
5
  def codeword_hint
6
- @codeword_hint ||= ENV['CODEWORD_HINT'] || ENV['codeword_hint'] || ::Codeword.from_config(:hint)
6
+ @codeword_hint ||= ENV['CODEWORD_HINT'] || Codeword::Configuration.from_credentials(:hint)
7
7
  end
8
8
  end
9
9
  end
data/codeword.gemspec CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Dan Kim', 'gb Studio']
9
9
  spec.email = ['git@dan.kim']
10
10
 
11
- spec.summary = 'Lock staging servers from search engines and prying eyespec.'
11
+ spec.summary = 'Lock staging servers from search engines and prying eyes.'
12
12
  spec.description = 'A simple gem to more elegantly place a staging server or other in-progress application behind a basic codeword. It’s easy to implement, share with clients/collaborators, and more beautiful than the typical password-protection sheet.'
13
13
  spec.homepage = 'https://github.com/dankimio/codeword'
14
14
  spec.license = 'MIT'
@@ -23,8 +23,8 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.add_dependency 'rails', '>= 7.2'
25
25
 
26
- spec.add_development_dependency 'capybara', '~> 2.9'
26
+ spec.add_development_dependency 'capybara'
27
27
  spec.add_development_dependency 'debug'
28
28
  spec.add_development_dependency 'launchy', '~> 2.4'
29
- spec.add_development_dependency 'rspec-rails', '~> 6.0'
29
+ spec.add_development_dependency 'rspec-rails', '~> 7.0'
30
30
  end
@@ -0,0 +1,17 @@
1
+ module Codeword
2
+ module Authentication
3
+ extend ActiveSupport::Concern
4
+
5
+ def require_codeword!
6
+ return unless respond_to?(:codeword) && Codeword::Configuration.codeword_code
7
+ return if cookies[:codeword].present? && cookies[:codeword] == Codeword::Configuration.codeword_code.to_s.downcase
8
+
9
+ redirect_to codeword.unlock_path(
10
+ return_to: request.fullpath.split('?codeword')[0],
11
+ codeword: params[:codeword]
12
+ )
13
+ end
14
+
15
+ alias_method :check_for_codeword, :require_codeword!
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Codeword
4
+ module Configuration
5
+ def self.from_credentials(setting)
6
+ store = Rails.application.credentials
7
+
8
+ store.dig(:codeword, setting)
9
+ end
10
+
11
+ def self.cookie_lifetime
12
+ @cookie_lifetime ||=
13
+ ENV['COOKIE_LIFETIME_IN_WEEKS'] ||
14
+ from_credentials(:cookie_lifetime_in_weeks)
15
+ end
16
+
17
+ def self.codeword_code
18
+ @codeword_code ||= ENV['CODEWORD'] || from_credentials(:codeword)
19
+ end
20
+
21
+ def self.codeword_cookie_lifetime
22
+ weeks = cookie_lifetime.to_f
23
+ if weeks.positive?
24
+ weeks.weeks
25
+ else
26
+ 5.years
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,3 @@
1
1
  module Codeword
2
- VERSION = '0.2.0.beta3'.freeze
2
+ VERSION = '0.2.0.beta4'.freeze
3
3
  end
data/lib/codeword.rb CHANGED
@@ -1,49 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'codeword/engine'
4
+ require 'codeword/authentication'
5
+ require 'codeword/configuration'
4
6
 
5
7
  module Codeword
6
- extend ActiveSupport::Concern
7
-
8
- def self.from_config(setting)
9
- store = Rails.application.credentials
10
-
11
- store.codeword.respond_to?(:fetch) &&
12
- store.codeword.fetch(setting, store.public_send("codeword_#{setting}")) ||
13
- store.public_send("codeword_#{setting}") || store.public_send(setting)
14
- end
15
-
16
- private
17
-
18
- def require_codeword!
19
- return unless respond_to?(:codeword) && codeword_code
20
- return if cookies[:codeword].present? && cookies[:codeword] == codeword_code.to_s.downcase
21
-
22
- redirect_to codeword.unlock_path(
23
- return_to: request.fullpath.split('?codeword')[0],
24
- codeword: params[:codeword]
25
- )
26
- end
27
-
28
- alias_method :check_for_codeword, :require_codeword!
29
-
30
- def cookie_lifetime
31
- @cookie_lifetime ||=
32
- ENV['COOKIE_LIFETIME_IN_WEEKS'] ||
33
- ENV['cookie_lifetime_in_weeks'] ||
34
- Codeword.from_config(:cookie_lifetime_in_weeks)
35
- end
36
-
37
- def codeword_code
38
- @codeword_code ||= ENV['CODEWORD'] || ENV['codeword'] || Codeword.from_config(:codeword)
39
- end
40
-
41
- def codeword_cookie_lifetime
42
- seconds = (cookie_lifetime.to_f * 1.week).to_i
43
- if seconds.positive?
44
- seconds
45
- else
46
- 5.years
47
- end
48
- end
49
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codeword
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.beta3
4
+ version: 0.2.0.beta4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Kim
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: capybara
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '2.9'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '2.9'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: debug
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '6.0'
75
+ version: '7.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '6.0'
82
+ version: '7.0'
83
83
  description: A simple gem to more elegantly place a staging server or other in-progress
84
84
  application behind a basic codeword. It’s easy to implement, share with clients/collaborators,
85
85
  and more beautiful than the typical password-protection sheet.
@@ -106,11 +106,12 @@ files:
106
106
  - codeword.gemspec
107
107
  - config/routes.rb
108
108
  - lib/codeword.rb
109
+ - lib/codeword/authentication.rb
110
+ - lib/codeword/configuration.rb
109
111
  - lib/codeword/engine.rb
110
112
  - lib/codeword/version.rb
111
113
  - mise.toml
112
114
  - screenshot.png
113
- - script/rails
114
115
  homepage: https://github.com/dankimio/codeword
115
116
  licenses:
116
117
  - MIT
@@ -134,5 +135,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
135
  requirements: []
135
136
  rubygems_version: 3.7.1
136
137
  specification_version: 4
137
- summary: Lock staging servers from search engines and prying eyespec.
138
+ summary: Lock staging servers from search engines and prying eyes.
138
139
  test_files: []
data/script/rails DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
-
4
- ENGINE_ROOT = File.expand_path('..', __dir__)
5
- ENGINE_PATH = File.expand_path('../lib/codeword/engine', __dir__)
6
-
7
- require 'rails/all'
8
- require 'rails/engine/commands'