katalyst-google-apis 1.0.3 → 1.0.4

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: 0eb512d72774ba49f273ba054b61696b23336dbc764a6dae5d3c3b5de233b703
4
- data.tar.gz: 6728db2369e837dbac22b07cf7c96ffe3acdea71ac3751279663affd52d3f201
3
+ metadata.gz: a82e7a488e59d05637fc0db55a0050f6e7f6227e097133ea736103ba57b3e277
4
+ data.tar.gz: 518ec79c1b5a9a627e4dec75bd4e0c8e0bf681c1dec52d3a0fcb717476fc5d0d
5
5
  SHA512:
6
- metadata.gz: ad86fb05d296e9c5630ac0314aa2bec980a255880664d828d35bead1587e29580876abd67c7b04991fb3612172028e1cd393cd322b3ac633983ae2516eb84a72
7
- data.tar.gz: 855fd145e885dd1749a9decdf6e2ed2ba7c2bca1196dcf1fc87fbc8c7fc38b8d8139e6a2995760d1d671c516a52a40adeb7dcf9e4138f2e3c223ea3889f0572f
6
+ metadata.gz: 235d78f336ef65fa265d94c2f163298df57d40508c8ae22ae91c55ccaae1f220bbeadaa1d849cf4cbff644a7734359ddee8f6458e89e04ac67ff05d69d16e769
7
+ data.tar.gz: 590c079916e8b3b790c37341ceb092bbce01df57b438221cf78a9666f35b1bd28420aadc120ad4d4bfa7342c536760569273cce1d2a1a0a73565b48f8ba2ddf8
@@ -10,9 +10,13 @@ enterprise.ready = (f) => {
10
10
  (config["fns"] ||= []).push(f);
11
11
  };
12
12
 
13
- function init() {
14
- if (document.head.querySelector("script[src*='recaptcha/enterprise']"))
13
+ /**
14
+ * Inject recaptcha enterprise script into the head, unless it is already there.
15
+ */
16
+ function injectRecaptchaScripts() {
17
+ if (document.head.querySelector("script[src*='recaptcha/enterprise']")) {
15
18
  return;
19
+ }
16
20
 
17
21
  const script = document.createElement("script");
18
22
  script.setAttribute(
@@ -26,20 +30,94 @@ function init() {
26
30
  }
27
31
 
28
32
  export default class RecaptchaController extends Controller {
33
+ static values = {
34
+ siteKey: String,
35
+ action: String,
36
+ response: String,
37
+ widgetId: String,
38
+ };
39
+
29
40
  connect() {
30
- init();
41
+ injectRecaptchaScripts();
42
+
43
+ enterprise.ready(this.attachRecaptcha);
44
+ }
45
+
46
+ disconnect() {
47
+ enterprise.ready(this.detachRecaptcha);
48
+ }
49
+
50
+ /**
51
+ * Prevent turbo morph events from updating the dom inside this element.
52
+ * Instead, remove the temporary container and re-initialize recaptcha.
53
+ *
54
+ * Recaptcha does not allow the same response to be validated twice so we
55
+ * always need to ask the user to re-complete the recaptcha.
56
+ *
57
+ * @param e {Event}
58
+ */
59
+ morph(e) {
60
+ e.preventDefault();
31
61
 
32
62
  enterprise.ready(() => {
33
- enterprise.render(this.element, {
34
- sitekey: this.element.dataset.sitekey,
35
- action: this.element.dataset.action,
36
- callback: (response) => {
37
- this.responseTarget.value = response;
38
- },
39
- });
63
+ this.detachRecaptcha();
64
+ this.responseValue = "";
65
+ this.attachRecaptcha();
66
+ });
67
+ }
68
+
69
+ /**
70
+ * Respond to an update to the recaptcha challenge.
71
+ *
72
+ * @param response {String}
73
+ */
74
+ responseValueChanged(response) {
75
+ this.responseTarget.value = response;
76
+ }
77
+
78
+ /**
79
+ * Renders the recaptcha widget inside the temporary container.
80
+ */
81
+ attachRecaptcha = () => {
82
+ this.widgetIdValue = enterprise.render(this.containerTarget, {
83
+ sitekey: this.siteKeyValue,
84
+ action: this.actionValue,
85
+ callback: this.recaptchaResponse,
40
86
  });
87
+ };
88
+
89
+ /**
90
+ * Detach the input from recaptcha.js and remove the temporary container.
91
+ */
92
+ detachRecaptcha = () => {
93
+ enterprise.reset(this.widgetIdValue);
94
+ this.widgetIdValue = "";
95
+ this.containerTarget.remove();
96
+ };
97
+
98
+ /**
99
+ * Handles callbacks from recaptcha when the user has completed the challenge.
100
+ */
101
+ recaptchaResponse = (response) => {
102
+ this.responseValue = response;
103
+ };
104
+
105
+ /**
106
+ * @returns {HTMLDivElement} creates or returns a temporary div for holding the recaptcha inputs
107
+ */
108
+ get containerTarget() {
109
+ let container = this.element.firstElementChild;
110
+ if (container) return container;
111
+
112
+ container = document.createElement("div");
113
+ container.dataset.turboTemporary = "";
114
+ this.element.appendChild(container);
115
+ return container;
41
116
  }
42
117
 
118
+ /**
119
+ * @returns {HTMLInputElement} the hidden input that will submit the recaptcha response
120
+ */
43
121
  get responseTarget() {
44
122
  return this.element.nextElementSibling;
45
123
  }
@@ -4,12 +4,39 @@ module Katalyst
4
4
  module GoogleApis
5
5
  module FormBuilder
6
6
  def recaptcha_field(attribute = :recaptcha_token, action: object_name,
7
- sitekey: GoogleApis.config.recaptcha.site_key)
7
+ site_key: GoogleApis.config.recaptcha.site_key)
8
8
  safe_join([
9
- content_tag(:div, "", data: { action:, controller: "recaptcha", sitekey: }),
9
+ RecaptchaField.new(action:, attribute:, site_key:).render(self),
10
10
  hidden_field(attribute),
11
11
  ])
12
12
  end
13
+
14
+ class RecaptchaField
15
+ attr_reader :action, :attribute, :site_key
16
+
17
+ def initialize(action:, attribute:, site_key:)
18
+ # rubocop:disable Rails/HelperInstanceVariable
19
+ @action = action
20
+ @attribute = attribute
21
+ @site_key = site_key
22
+ # rubocop:enable Rails/HelperInstanceVariable
23
+ end
24
+
25
+ def render(template)
26
+ template.tag.div(data:)
27
+ end
28
+
29
+ private
30
+
31
+ def data
32
+ {
33
+ controller: "recaptcha",
34
+ action: "turbo:before-morph-element->recaptcha#morph",
35
+ recaptcha_action_value: action,
36
+ recaptcha_site_key_value: site_key,
37
+ }
38
+ end
39
+ end
13
40
  end
14
41
  end
15
42
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katalyst-google-apis
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katalyst Interactive
@@ -24,7 +24,7 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0'
26
26
  - !ruby/object:Gem::Dependency
27
- name: curb
27
+ name: aws-sdk-core
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
@@ -38,7 +38,7 @@ dependencies:
38
38
  - !ruby/object:Gem::Version
39
39
  version: '0'
40
40
  - !ruby/object:Gem::Dependency
41
- name: aws-sdk-core
41
+ name: curb
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - ">="