Skip to content

Commit cffa889

Browse files
committed
Add invisible captcha for registration and newsletter forms
Extracts a module for using the invisible captcha view helper with Phlex. Since the helper makes uses of "concat" and "session" I also had to use the Phlex Rails macro convention for registering access to those helper methods. We also need to deal with invisible captcha for specs; currently disabling timing and spinner checks. We also need to deal with the gem for wasm because we reference it in an initializer.
1 parent 6fffa44 commit cffa889

File tree

9 files changed

+54
-11
lines changed

9 files changed

+54
-11
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ gem "rouge", group: [:default, :wasm] # Pure Ruby syntaix highlighter [https://g
3535
gem "sitepress-rails", group: [:default, :wasm] # Static site generator for Rails [https://sitepress.cc/getting-started/rails]
3636
gem "phlex-rails", group: [:default, :wasm] # An object-oriented alternative to ActionView for Ruby on Rails. [https://github.com/phlex-ruby/phlex-rails]
3737
gem "commonmarker", require: false
38+
gem "invisible_captcha", group: [:default, :wasm] # Unobtrusive and flexible spam protection for Rails apps [https://github.com/markets/invisible_captcha]
3839

3940
gem "bootsnap", require: false # Reduces boot times through caching; required in config/boot.rb [https://github.com/Shopify/bootsnap]
4041

Gemfile.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,8 @@ GEM
237237
inline_svg (1.9.0)
238238
activesupport (>= 3.0)
239239
nokogiri (>= 1.6)
240+
invisible_captcha (2.3.0)
241+
rails (>= 5.2)
240242
io-console (0.7.2)
241243
irb (1.13.1)
242244
rdoc (>= 4.0.0)
@@ -562,6 +564,7 @@ DEPENDENCIES
562564
fog-aws
563565
honeybadger
564566
inline_svg
567+
invisible_captcha
565568
js
566569
letter_opener
567570
litestream

app/controllers/users/newsletter_subscriptions_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
class Users::NewsletterSubscriptionsController < ApplicationController
2+
invisible_captcha only: [:create]
3+
24
# TODO: Implement singular resource index action for logged in user
35
# before_action :authenticate_user!, only: [:index]
46

app/controllers/users/registrations_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# frozen_string_literal: true
22

33
class Users::RegistrationsController < ApplicationController
4+
invisible_captcha only: [:create]
5+
46
before_action :feature_enabled!
57
before_action :redirect_if_authenticated, only: [:create, :new]
68
before_action :authenticate_user!, only: [:edit, :update, :destroy]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module Concerns::HasInvisibleCaptcha
2+
extend ActiveSupport::Concern
3+
4+
included do
5+
# The following modules are needed to make Phlex components work with invisible_captcha
6+
include InvisibleCaptcha::ViewHelpers
7+
include Phlex::Rails::Helpers::ContentTag
8+
include Phlex::Rails::Helpers::Request
9+
include Phlex::Rails::Helpers::LabelTag
10+
include Phlex::Rails::Helpers::TextFieldTag
11+
include Phlex::Rails::Helpers::HiddenFieldTag
12+
13+
extend Phlex::Rails::HelperMacros
14+
# @!method session(...)
15+
register_value_helper :session
16+
# @!method concat(...)
17+
register_value_helper :concat
18+
end
19+
end

app/views/users/newsletter_subscriptions/form.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,21 @@ class Users::NewsletterSubscriptions::Form < ApplicationComponent
44
include Phlex::Rails::Helpers::Object
55
include Phlex::Rails::Helpers::Routes
66

7+
include Concerns::HasInvisibleCaptcha
8+
79
def initialize(newsletter_subscription:)
810
@newsletter_subscription = newsletter_subscription
911
end
1012

1113
def view_template
1214
form_with model: @newsletter_subscription.subscriber, url: form_url, class: "lg:w-1/2" do |f|
15+
invisible_captcha
1316
div(class: "flex flex-row items-center mt-2") do
1417
div(class: "flex-grow mr-2") do
1518
whitespace
1619
plain f.email_field :email,
1720
type: :email,
18-
autocomplete: "email",
21+
autocomplete: "off",
1922
placeholder: "[email protected]",
2023
class:
2124
"flex-1 rounded bg-white/5 py-1.5 pl-3 sm:leading-6 focus-ring focus:ring-0 ring-1 ring-inset ring-white/10 w-full lg:min-w-[36ch] "

app/views/users/registrations/new_view.rb

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
class Users::Registrations::NewView < ApplicationView
2+
include Concerns::HasInvisibleCaptcha
3+
24
def initialize(user:)
35
@user = user
46
end
@@ -7,34 +9,33 @@ def view_template
79
render Layouts::FrontDoorForm.new(title: "Create a new account") do |layout|
810
layout.form_with model: @user,
911
url: users_registration_path do |form|
10-
if form.object.errors.any?
11-
ul do
12-
form.object.errors.full_messages.each do |message|
13-
li { message }
14-
end
15-
end
16-
end
12+
invisible_captcha
1713
fieldset do
1814
layout.form_label form, :email, "Email address"
1915
layout.form_field form, :email_field, :email,
20-
autocomplete: "email",
16+
autocomplete: "off",
2117
required: true
2218
end
2319
fieldset do
2420
layout.form_label form, :password
2521
layout.form_field form, :password_field, :password,
2622
type: "password",
27-
autocomplete: "current-password",
23+
autocomplete: "off",
2824
required: true
2925
end
3026
fieldset do
3127
layout.form_label form, :password_confirmation
3228
layout.form_field form, :password_field, :password_confirmation,
3329
type: "password",
34-
autocomplete: "current-password",
30+
autocomplete: "off",
3531
required: true
3632
end
3733
layout.form_button form, "Sign up"
34+
if form.object.errors.any?
35+
div(class: "bg-error callout") do
36+
plain form.object.errors.full_messages.join(". ")
37+
end
38+
end
3839
end
3940
end
4041
end

config/application_wasm.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
require "sitepress-rails"
2929
require "phlex-rails"
3030
require "inline_svg"
31+
require "invisible_captcha"
3132

3233
module Joy
3334
class Application < Rails::Application
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
require "invisible_captcha"
2+
3+
InvisibleCaptcha.setup do |config|
4+
# We need to deal with invisible captcha for specs
5+
# https://github.com/markets/invisible_captcha?tab=readme-ov-file#testing-your-controllers
6+
if Rails.env.test?
7+
config.timestamp_enabled = false
8+
config.spinner_enabled = false
9+
config.honeypots = ["my_honeypot_field"]
10+
end
11+
end

0 commit comments

Comments
 (0)