castle_devise 0.4.3 → 0.7.0

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.
@@ -1,17 +1,18 @@
1
- # This file was generated by Appraisal
2
-
3
1
  source "https://rubygems.org"
4
2
 
5
3
  gem "actionmailer"
6
4
  gem "activerecord"
5
+ gem "byebug"
7
6
  gem "railties", "~> 7.0"
8
7
  gem "rake"
9
8
  gem "rspec"
10
9
  gem "rspec-rails"
11
10
  gem "simplecov"
12
11
  gem "standard"
13
- gem "sqlite3"
12
+ gem "sqlite3", "~> 1.7"
14
13
  gem "vcr"
15
14
  gem "webmock"
15
+ gem "mutex_m"
16
+ gem "logger"
16
17
 
17
18
  gemspec path: "../"
@@ -0,0 +1,18 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "actionmailer"
4
+ gem "activerecord"
5
+ gem "byebug"
6
+ gem "railties", "~> 7.1"
7
+ gem "rake"
8
+ gem "rspec"
9
+ gem "rspec-rails"
10
+ gem "simplecov"
11
+ gem "standard"
12
+ gem "sqlite3", "~> 1.7"
13
+ gem "vcr"
14
+ gem "webmock"
15
+ gem "mutex_m"
16
+ gem "logger"
17
+
18
+ gemspec path: "../"
@@ -0,0 +1,18 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "actionmailer"
4
+ gem "activerecord"
5
+ gem "byebug"
6
+ gem "railties", "~> 7.2"
7
+ gem "rake"
8
+ gem "rspec"
9
+ gem "rspec-rails"
10
+ gem "simplecov"
11
+ gem "standard"
12
+ gem "sqlite3", "~> 1.7"
13
+ gem "vcr"
14
+ gem "webmock"
15
+ gem "mutex_m"
16
+ gem "logger"
17
+
18
+ gemspec path: "../"
@@ -0,0 +1,18 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "actionmailer"
4
+ gem "activerecord"
5
+ gem "byebug"
6
+ gem "railties", "~> 8.0.0"
7
+ gem "rake"
8
+ gem "rspec"
9
+ gem "rspec-rails"
10
+ gem "simplecov"
11
+ gem "standard"
12
+ gem "sqlite3"
13
+ gem "vcr"
14
+ gem "webmock"
15
+ gem "mutex_m"
16
+ gem "logger"
17
+
18
+ gemspec path: "../"
@@ -0,0 +1,17 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "actionmailer"
4
+ gem "activerecord"
5
+ gem "byebug"
6
+ gem "devise", "~> 5.0"
7
+ gem "railties", "~> 8.1.0"
8
+ gem "rake"
9
+ gem "rspec"
10
+ gem "rspec-rails"
11
+ gem "simplecov"
12
+ gem "standard"
13
+ gem "sqlite3"
14
+ gem "vcr"
15
+ gem "webmock"
16
+
17
+ gemspec path: "../"
@@ -1,20 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/configurable"
4
3
  require "logger"
5
4
 
6
5
  module CastleDevise
7
- # Configuration object using {ActiveSupport::Configurable}
6
+ # Plain Ruby configuration object for CastleDevise.
7
+ #
8
+ # Previously this used +ActiveSupport::Configurable+, which is deprecated
9
+ # and slated for removal in Rails 8.2.
8
10
  class Configuration
9
- include ActiveSupport::Configurable
10
-
11
11
  # @!attribute api_secret
12
12
  # @return [String] Your API secret
13
- config_accessor(:api_secret)
13
+ attr_accessor :api_secret
14
14
 
15
- # @!attribute app_id
16
- # @return [String] Your Castle App ID
17
- config_accessor(:app_id)
15
+ # @!attribute publishable_key
16
+ # @return [String] Publishable key passed to @castleio/castle-js as { pk: }
17
+ attr_accessor :publishable_key
18
18
 
19
19
  # @!attribute monitoring_mode
20
20
  # When CastleDevise is in monitoring mode, it sends requests to Castle
@@ -25,27 +25,41 @@ module CastleDevise
25
25
  # from logging in/registering.
26
26
  #
27
27
  # @return [true, false] whether to act on deny requests or not
28
- config_accessor(:monitoring_mode) { false }
29
-
30
- # @!attribute logger
31
- # @return [Logger] A Logger instance. You might want to use Rails.logger here.
32
- config_accessor(:logger) { Logger.new("/dev/null") }
28
+ attr_accessor :monitoring_mode
33
29
 
34
30
  # @!attribute before_request_hooks
35
31
  # @return [Array<Proc>] Array of procs that will get called before a request to the Castle API
36
- config_accessor(:before_request_hooks) { [] }
32
+ attr_accessor :before_request_hooks
37
33
 
38
34
  # @!attribute after_request_hooks
39
35
  # @return [Array<Proc>] Array of procs that will get called after a request to the Castle API
40
- config_accessor(:after_request_hooks) { [] }
36
+ attr_accessor :after_request_hooks
37
+
38
+ attr_writer :logger, :castle_sdk_facade_class, :castle_client
39
+
40
+ def initialize
41
+ @monitoring_mode = false
42
+ @before_request_hooks = []
43
+ @after_request_hooks = []
44
+ end
45
+
46
+ # @!attribute logger
47
+ # @return [Logger] A Logger instance. You might want to use Rails.logger here.
48
+ def logger
49
+ @logger ||= Logger.new(File::NULL)
50
+ end
41
51
 
42
52
  # @!attribute castle_sdk_facade_class
43
53
  # @return [Class] Castle API implementation
44
- config_accessor(:castle_sdk_facade_class) { ::CastleDevise::SdkFacade }
54
+ def castle_sdk_facade_class
55
+ @castle_sdk_facade_class ||= ::CastleDevise::SdkFacade
56
+ end
45
57
 
46
58
  # @!attribute castle_client
47
- # @return [Class] Castle SDK client
48
- config_accessor(:castle_client) { ::Castle::Client.new }
59
+ # @return [Castle::Client] Castle SDK client
60
+ def castle_client
61
+ @castle_client ||= ::Castle::Client.new
62
+ end
49
63
 
50
64
  # Adds a new before_request hook
51
65
  # @param blk [Proc]
@@ -0,0 +1,48 @@
1
+ (function () {
2
+ var CastleGlobal = window.Castle || window["@castleio/castle-js"];
3
+ var pk = __CASTLE_DEVISE_PK__;
4
+ if (!window.__castleDevise && CastleGlobal && typeof CastleGlobal.configure === "function") {
5
+ window.__castleDevise = CastleGlobal.configure({ pk: pk });
6
+ }
7
+
8
+ window.castleDeviseOnFormSubmit = function (event) {
9
+ var client = window.__castleDevise || window.Castle || window["@castleio/castle-js"];
10
+ // 2.x exposes injectTokenOnSubmit; 3.x only has createRequestToken on the configured instance.
11
+ if (client && typeof client.injectTokenOnSubmit === "function") {
12
+ return client.injectTokenOnSubmit(event);
13
+ }
14
+ if (!client || typeof client.createRequestToken !== "function") {
15
+ event.preventDefault();
16
+ return false;
17
+ }
18
+ var form = event.target;
19
+ if (form.getAttribute("data-castle-submitting") === "1") {
20
+ return true;
21
+ }
22
+ event.preventDefault();
23
+ client.createRequestToken().then(function (token) {
24
+ var field = form.querySelector('input[name="castle_request_token"]');
25
+ if (!field) {
26
+ field = document.createElement("input");
27
+ field.type = "hidden";
28
+ field.name = "castle_request_token";
29
+ form.appendChild(field);
30
+ }
31
+ field.value = token || "";
32
+ form.setAttribute("data-castle-submitting", "1");
33
+ if (typeof form.requestSubmit === "function") {
34
+ form.requestSubmit();
35
+ } else {
36
+ form.submit();
37
+ }
38
+ }).catch(function () {
39
+ form.setAttribute("data-castle-submitting", "1");
40
+ if (typeof form.requestSubmit === "function") {
41
+ form.requestSubmit();
42
+ } else {
43
+ form.submit();
44
+ }
45
+ });
46
+ return false;
47
+ };
48
+ })();
@@ -4,13 +4,23 @@ module CastleDevise
4
4
  module Helpers
5
5
  # Methods defined here will be available in all your views.
6
6
  module CastleHelper
7
- # Creates a <script> tag that includes our c.js script from a CDN.
8
- # You have to make sure that your app_id is valid, otherwise the script won't work.
9
- #
10
- # You shouldn't call this method if you bundle our c.js script with your other
11
- # JS packages.
7
+ BOOTSTRAP_JS = File.read(File.expand_path("castle_devise.js", __dir__)).freeze
8
+ # 3.x UMD is named @castleio/castle-js, so seed module.exports as window.Castle before the script tag.
9
+ UMD_SHIM = <<~JS
10
+ if (!window.Castle) {
11
+ window.exports = window.exports || {};
12
+ window.module = window.module || { exports: window.exports };
13
+ window.Castle = window.module.exports;
14
+ }
15
+ JS
16
+
17
+ DEFAULT_UMD_SRC = "/vendor/castle-js/castle.umd.js"
18
+
19
+ # Loads castle.umd.js and configures it with { pk: }. Pass src: to use a
20
+ # different UMD URL, or src: nil when the host app already loaded the SDK.
12
21
  #
13
- # You should put this in the <head> section of your page:
22
+ # @param src [String, nil] URL or path of castle.umd.js (keep workers in the same directory)
23
+ # @return [String]
14
24
  #
15
25
  # @example
16
26
  # # app/views/layouts/application.html.erb
@@ -21,14 +31,18 @@ module CastleDevise
21
31
  # <title>Your app title</title>
22
32
  #
23
33
  # <!-- the rest of your layout -->
24
- def castle_javascript_tag
25
- javascript_include_tag(
26
- "https://cdn.castle.io/v2/castle.js?#{CastleDevise.configuration.app_id}"
27
- )
34
+ def castle_javascript_tag(src: DEFAULT_UMD_SRC)
35
+ parts = []
36
+ if src
37
+ parts << javascript_tag(UMD_SHIM)
38
+ parts << javascript_include_tag(src)
39
+ end
40
+ parts << javascript_tag(castle_js_bootstrap)
41
+ safe_join(parts)
28
42
  end
29
43
 
30
- # Puts an inline <script> tag that includes a "castle_devise_token" field
31
- # within the current form.
44
+ # onsubmit handler that mints castle_request_token via 2.x injectTokenOnSubmit
45
+ # or 2.x/3.x createRequestToken.
32
46
  #
33
47
  # @example
34
48
  # <%= form_for(resource, as: resource_name, url: sessions_path(resource_name), html: { onsubmit: castle_on_form_submit }) do |f| %>
@@ -38,7 +52,13 @@ module CastleDevise
38
52
  #
39
53
  # @return [String]
40
54
  def castle_on_form_submit
41
- "typeof(_castle)=='undefined'?event.preventDefault():_castle('onFormSubmit', event)"
55
+ "castleDeviseOnFormSubmit(event)"
56
+ end
57
+
58
+ private
59
+
60
+ def castle_js_bootstrap
61
+ BOOTSTRAP_JS.sub("__CASTLE_DEVISE_PK__", CastleDevise.configuration.publishable_key.to_json)
42
62
  end
43
63
  end
44
64
  end
@@ -63,6 +63,6 @@ Warden::Manager.before_failure do |env, opts|
63
63
  context: context
64
64
  )
65
65
  rescue Castle::Error => e
66
- CastleDevise.logger.error("[CastleDevise] filter($login, $failed): #{e}")
66
+ CastleDevise.logger.warn("[CastleDevise] filter($login, $failed): #{e}")
67
67
  end
68
68
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CastleDevise
4
- VERSION = "0.4.3"
4
+ VERSION = "0.7.0"
5
5
  end
data/mise.toml ADDED
@@ -0,0 +1,11 @@
1
+ [tasks.install]
2
+ description = "Install Ruby gems"
3
+ run = "bundle install"
4
+
5
+ [tasks.test]
6
+ description = "Run the RSpec suite"
7
+ run = "bundle exec rspec"
8
+
9
+ [tasks.lint]
10
+ description = "Run Standard Ruby"
11
+ run = "bundle exec standardrb"
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: castle_devise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kacper Madej
8
8
  - Dawid Libiszewski
9
+ - Bartosz Knapik
9
10
  - Johan Brissmyr
10
- autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2023-07-11 00:00:00.000000000 Z
13
+ date: 1980-01-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - ">="
20
20
  - !ruby/object:Gem::Version
21
- version: '5.0'
21
+ version: '6.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - ">="
27
27
  - !ruby/object:Gem::Version
28
- version: '5.0'
28
+ version: '6.0'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: castle-rb
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -35,7 +35,7 @@ dependencies:
35
35
  version: '7.2'
36
36
  - - "<"
37
37
  - !ruby/object:Gem::Version
38
- version: '8.0'
38
+ version: '10.0'
39
39
  type: :runtime
40
40
  prerelease: false
41
41
  version_requirements: !ruby/object:Gem::Requirement
@@ -45,7 +45,7 @@ dependencies:
45
45
  version: '7.2'
46
46
  - - "<"
47
47
  - !ruby/object:Gem::Version
48
- version: '8.0'
48
+ version: '10.0'
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: devise
51
51
  requirement: !ruby/object:Gem::Requirement
@@ -55,7 +55,7 @@ dependencies:
55
55
  version: 4.3.0
56
56
  - - "<"
57
57
  - !ruby/object:Gem::Version
58
- version: '5.0'
58
+ version: '6.0'
59
59
  type: :runtime
60
60
  prerelease: false
61
61
  version_requirements: !ruby/object:Gem::Requirement
@@ -65,25 +65,11 @@ dependencies:
65
65
  version: 4.3.0
66
66
  - - "<"
67
67
  - !ruby/object:Gem::Version
68
- version: '5.0'
69
- - !ruby/object:Gem::Dependency
70
- name: appraisal
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 2.3.0
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 2.3.0
68
+ version: '6.0'
83
69
  description: castle_devise provides out-of-the-box protection against bot registrations
84
70
  and account takeover attacks.
85
71
  email:
86
- - kacper@castle.io
72
+ - team@castle.io
87
73
  executables: []
88
74
  extensions: []
89
75
  extra_rdoc_files: []
@@ -91,8 +77,10 @@ files:
91
77
  - ".github/workflows/lint.yml"
92
78
  - ".github/workflows/specs.yml"
93
79
  - ".gitignore"
80
+ - ".octocov.yml"
94
81
  - ".rspec"
95
- - Appraisals
82
+ - ".standard.yml"
83
+ - ".tool-versions"
96
84
  - CHANGELOG.md
97
85
  - Gemfile
98
86
  - Gemfile.lock
@@ -105,10 +93,15 @@ files:
105
93
  - gemfiles/rails_6.0.gemfile
106
94
  - gemfiles/rails_6.1.gemfile
107
95
  - gemfiles/rails_7.0.gemfile
96
+ - gemfiles/rails_7.1.gemfile
97
+ - gemfiles/rails_7.2.gemfile
98
+ - gemfiles/rails_8.0.gemfile
99
+ - gemfiles/rails_8.1.gemfile
108
100
  - lib/castle_devise.rb
109
101
  - lib/castle_devise/configuration.rb
110
102
  - lib/castle_devise/context.rb
111
103
  - lib/castle_devise/controllers/helpers.rb
104
+ - lib/castle_devise/helpers/castle_devise.js
112
105
  - lib/castle_devise/helpers/castle_helper.rb
113
106
  - lib/castle_devise/hooks/castle_protectable.rb
114
107
  - lib/castle_devise/models/castle_protectable.rb
@@ -118,6 +111,7 @@ files:
118
111
  - lib/castle_devise/rails.rb
119
112
  - lib/castle_devise/sdk_facade.rb
120
113
  - lib/castle_devise/version.rb
114
+ - mise.toml
121
115
  homepage: https://github.com/castle/castle_devise
122
116
  licenses:
123
117
  - MIT
@@ -125,7 +119,6 @@ metadata:
125
119
  homepage_uri: https://github.com/castle/castle_devise
126
120
  source_code_uri: https://github.com/castle/castle_devise
127
121
  changelog_uri: https://github.com/castle/castle_devise/CHANGELOG.md
128
- post_install_message:
129
122
  rdoc_options: []
130
123
  require_paths:
131
124
  - lib
@@ -133,15 +126,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
133
126
  requirements:
134
127
  - - ">="
135
128
  - !ruby/object:Gem::Version
136
- version: 2.5.0
129
+ version: 3.2.0
137
130
  required_rubygems_version: !ruby/object:Gem::Requirement
138
131
  requirements:
139
132
  - - ">="
140
133
  - !ruby/object:Gem::Version
141
134
  version: '0'
142
135
  requirements: []
143
- rubygems_version: 3.3.3
144
- signing_key:
136
+ rubygems_version: 3.6.9
145
137
  specification_version: 4
146
138
  summary: Integrates Castle with Devise
147
139
  test_files: []
data/Appraisals DELETED
@@ -1,11 +0,0 @@
1
- appraise "rails-6.0" do
2
- gem "railties", "~> 6.0.4"
3
- end
4
-
5
- appraise "rails-6.1" do
6
- gem "railties", "~> 6.1.4"
7
- end
8
-
9
- appraise "rails-7.0" do
10
- gem "railties", "~> 7.0"
11
- end