codeword 0.2.0.beta2 → 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: 58628581dfc6ebc297114f5d05ca82b625d1f777eb28fb66cb83caf818b5337b
4
- data.tar.gz: a554b130eb17b6fe35e60ecb7bd6d318b1c43e61665ed8438e1b6476c4e4b985
3
+ metadata.gz: cb390e385a9ce1fe7f4e8f987be5e02d1542795d209d74d282887f93cbc03c33
4
+ data.tar.gz: 9f53cfbc92b062d4c531d025535f93213ac7bebed588233aa37b7c7036501764
5
5
  SHA512:
6
- metadata.gz: f76067c4a6e801c693e970c60ea94179fb35d8e4d03f1c52cd6fcfdf2735a87004357d4490d296d3ebcd380b859e89ce894165098a74a49aec39806b6e04caed
7
- data.tar.gz: a3c85b0d037a52c7df10bbad807e2f05e6a71fd4e030f4dff514c93ddb5f7c6d20303235aed514064310d828878219d04385ec37ec84818e74add0a42a2b3a3a
6
+ metadata.gz: 966df1e8a10079976ff0efe940935c67a634ae0de335d702e6c74a8af314d88c18d1beb97edf7dbdeb93e09e1c5e305ed355ae898a1799879d33c701b019cc5b
7
+ data.tar.gz: a62f1f572a373e268f661bfedfab93049f85ec034d07547735a7b5049d8920defd71a82aad11dba4137ae905278c3de4500eb94c4225ddefe2ce2b35aa0a3f97
data/CHANGELOG.md CHANGED
@@ -1,7 +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`)
4
+ - BREAKING: Drop support for Rails < 7.2
5
+ - BREAKING: Rename `check_for_codeword` to `require_codeword!`
3
6
  - BREAKING: Deprecate Rails secrets in favor of Rails credentials
4
- - 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)
5
13
 
6
14
  ## [0.1.1] - 2021-12-17
7
15
 
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2021 Dan Kim
3
+ Copyright (c) 2025 Dan Kim
4
4
  Copyright (c) 2013 gb Studio, llc
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
data/README.md CHANGED
@@ -17,9 +17,29 @@ gem 'codeword'
17
17
  3. Mount the engine in your application’s routes file (usually first, for best results):
18
18
 
19
19
  ```ruby
20
+ # config/routes.rb
20
21
  mount Codeword::Engine, at: '/codeword'
21
22
  ```
22
23
 
24
+ 4. Include the `Codeword::Authentication` module in your application_controller.rb file and check for codeword:
25
+
26
+ ```ruby
27
+ # app/controllers/application_controller.rb
28
+ class ApplicationController < ActionController::Base
29
+ include Codeword::Authentication
30
+
31
+ before_action :require_codeword!
32
+ end
33
+ ```
34
+
35
+ 5. Skip the check for codeword in the controller(s) you would like to allow:
36
+
37
+ ```ruby
38
+ class APIController < ApplicationController
39
+ skip_before_action :require_codeword!
40
+ end
41
+ ```
42
+
23
43
  ## Usage
24
44
 
25
45
  To set a codeword, define CODEWORD in your environments/your_environment.rb file like so:
@@ -36,17 +56,11 @@ ENV['CODEWORD_HINT'] = 'Something that you do not tell everyone.'
36
56
 
37
57
  You can add your codeword via Rails credentials in your `credentials.yml.enc` file (`$ bin/rails credentials:edit`):
38
58
 
39
- ```yml
40
- codeword: 'love'
41
- codeword_hint: 'Pepé Le Pew'
42
- ```
43
-
44
- Alternately, credentials in Rails >= 5.2 may be organized under the `codeword` namespace:
45
-
46
59
  ```yml
47
60
  codeword:
48
- codeword: 'love'
49
- hint: 'Pepé Le Pew'
61
+ codeword: "love"
62
+ hint: "Pepé Le Pew"
63
+ cookie_lifetime_in_weeks: 4
50
64
  ```
51
65
 
52
66
  **Codewords are not case-sensitive, by design. Keep it simple.**
@@ -60,13 +74,13 @@ codeword:
60
74
  2. In your application_controller.rb file, add:
61
75
 
62
76
  ```ruby
63
- skip_before_action :check_for_codeword, raise: false
77
+ skip_before_action :require_codeword!, raise: false
64
78
  ```
65
79
 
66
80
  4. In the controller(s) you would like to restrict:
67
81
 
68
82
  ```ruby
69
- before_action :check_for_codeword
83
+ before_action :require_codeword!
70
84
  ```
71
85
 
72
86
  ### Link it with no typing:
@@ -1,8 +1,8 @@
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
- skip_before_action :check_for_codeword
5
+ skip_before_action :require_codeword!, raise: false
6
6
 
7
7
  def unlock
8
8
  user_agent = request.env['HTTP_USER_AGENT'].presence
@@ -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
@@ -6,9 +6,9 @@ Gem::Specification.new do |spec|
6
6
  spec.name = 'codeword'
7
7
  spec.version = Codeword::VERSION
8
8
  spec.authors = ['Dan Kim', 'gb Studio']
9
- spec.email = ['itsdanya@gmail.com']
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'
@@ -21,10 +21,10 @@ Gem::Specification.new do |spec|
21
21
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
22
22
  end
23
23
 
24
- spec.add_dependency 'rails', '>= 6.1'
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,9 +1,5 @@
1
1
  module Codeword
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Codeword
4
-
5
- initializer 'codeword.app_controller' do |_app|
6
- ActiveSupport.on_load(:action_controller) { include Codeword }
7
- end
8
4
  end
9
5
  end
@@ -1,3 +1,3 @@
1
1
  module Codeword
2
- VERSION = '0.2.0.beta2'.freeze
2
+ VERSION = '0.2.0.beta4'.freeze
3
3
  end
data/lib/codeword.rb CHANGED
@@ -1,51 +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
- included do
9
- before_action :check_for_codeword
10
- end
11
-
12
- def self.from_config(setting)
13
- store = Rails.application.credentials
14
-
15
- store.codeword.respond_to?(:fetch) &&
16
- store.codeword.fetch(setting, store.public_send("codeword_#{setting}")) ||
17
- store.public_send("codeword_#{setting}") || store.public_send(setting)
18
- end
19
-
20
- private
21
-
22
- def check_for_codeword
23
- return unless respond_to?(:codeword) && codeword_code
24
- return if cookies[:codeword].present? && cookies[:codeword] == codeword_code.to_s.downcase
25
-
26
- redirect_to codeword.unlock_path(
27
- return_to: request.fullpath.split('?codeword')[0],
28
- codeword: params[:codeword]
29
- )
30
- end
31
-
32
- def cookie_lifetime
33
- @cookie_lifetime ||=
34
- ENV['COOKIE_LIFETIME_IN_WEEKS'] ||
35
- ENV['cookie_lifetime_in_weeks'] ||
36
- Codeword.from_config(:cookie_lifetime_in_weeks)
37
- end
38
-
39
- def codeword_code
40
- @codeword_code ||= ENV['CODEWORD'] || ENV['codeword'] || Codeword.from_config(:codeword)
41
- end
42
-
43
- def codeword_cookie_lifetime
44
- seconds = (cookie_lifetime.to_f * 1.week).to_i
45
- if seconds.positive?
46
- seconds
47
- else
48
- 5.years
49
- end
50
- end
51
8
  end
data/mise.toml ADDED
@@ -0,0 +1,2 @@
1
+ [tools]
2
+ ruby = "3.4.5"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codeword
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.beta2
4
+ version: 0.2.0.beta4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Kim
8
8
  - gb Studio
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-02-05 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '6.1'
19
+ version: '7.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '6.1'
26
+ version: '7.2'
27
27
  - !ruby/object:Gem::Dependency
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,25 +72,24 @@ 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.
86
86
  email:
87
- - itsdanya@gmail.com
87
+ - git@dan.kim
88
88
  executables: []
89
89
  extensions: []
90
90
  extra_rdoc_files: []
91
91
  files:
92
92
  - ".gitignore"
93
- - ".ruby-version"
94
93
  - CHANGELOG.md
95
94
  - Gemfile
96
95
  - LICENSE.txt
@@ -107,10 +106,12 @@ files:
107
106
  - codeword.gemspec
108
107
  - config/routes.rb
109
108
  - lib/codeword.rb
109
+ - lib/codeword/authentication.rb
110
+ - lib/codeword/configuration.rb
110
111
  - lib/codeword/engine.rb
111
112
  - lib/codeword/version.rb
113
+ - mise.toml
112
114
  - screenshot.png
113
- - script/rails
114
115
  homepage: https://github.com/dankimio/codeword
115
116
  licenses:
116
117
  - MIT
@@ -132,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
133
  - !ruby/object:Gem::Version
133
134
  version: '0'
134
135
  requirements: []
135
- rubygems_version: 3.6.2
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/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 3.4.1
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'