DOCS LLMs

Abuse protection

RailsFast ships with several measures you can use to protect against abuse and bots / DDoS / scrapers / bad actors.

Cloudflare Turnstile (Captcha-like)

Cloudflare Turnstile is a widget, like the famous CAPTCHA, that validates whether the user is human or not. This is useful to prevent bots from automatically / massively submitting information to your app, for example.

As we saw in the auth section, all signup/login forms come already protected against abuse by Cloudflare Turnstile.

If you want to add Turnstile (Captcha-like) protection to any other form on any other page, you just need to add the cloudflare_turnstile element to your view:

<%= cloudflare_turnstile(theme: 'dark') %>

And then, in the corresponding controller action:

before_action :validate_cloudflare_turnstile, only: [:your_action]

Everything is configured in RailsFast so that these two lines are enough to add a fully functional Turnstile validation to any form in your app.

Two details worth knowing:

  • The cloudflare_turnstile helper attaches the railsfast--turnstile Stimulus controller that draws the widget and keeps it working across Turbo navigations. If you write the <div class="cf-turnstile"> markup by hand instead, add data-controller="railsfast--turnstile" to it yourself, or the widget never appears and the form is refused.
  • Inside the Hotwire Native apps the auth forms skip Turnstile on purpose (validate_cloudflare_turnstile_for_browser in ApplicationController): a single-use token would turn every corrected typo on a re-rendered native form into a false "not human" failure.

We leverage the rails_cloudflare_turnstile gem for this, in case you need more documentation in how to use it.

Creating the widget is a dashboard step

The cf CLI has no Turnstile command, so an agent that works only through cf cannot create the widget. Do it in the Cloudflare dashboard:

  1. Cloudflare dashboard → Turnstile → Add widget.
  2. Name: your app's name. Hostnames: example.com and www.example.com (add your staging hostnames too, if you have them).
  3. Widget mode: Managed. Click Create.
  4. Copy the site key and the secret key into the production block of your credentials:
production:
  cloudflare:
    turnstile:
      site_key: <the site key>
      secret_key: <the secret key>

If your API token has the Account → Turnstile → Edit permission, the raw API call in the Configuration agent lane does the same.

NOTE

Turnstile turns on only with real keys. Since template v1.15.1, a key that is blank or still the sample's placeholder counts as missing, so a credentials file copied from the sample keeps Turnstile off and the forms work. (The sample's unquoted 0xabc123 reaches the app as an integer; it is recognised too.) Before v1.15.1 the placeholders counted as present: Cloudflare refused every challenge, and nobody could sign up or log in. On an older template, keep the turnstile: block out of your credentials until you have the real keys. bin/railsfast doctor reports a production block still on the placeholders.

Throwaway and mistyped emails

Sign-up and every email change refuse throwaway inboxes and catch typos like gmail.con, with a "Did you mean …?" answer. See Email address checks.

Rate limiting

I recommend setting up any rate-limiting countermeasures in Cloudflare (it's more advanced and kills any request before it actually hits your Rails app), but in case you don't want to / can't do it, you still have a very solid and production-ready mechanisim to easily rate limit requests in your RailsFast apps.

Just add rate_limit to any controller:

class DemoController < ApplicationController
  rate_limit to: 3, within: 1.minute, by: -> { current_user.id }, only: :my_action
end

For example, the rule above will block users from submitting more than 3 requests per minute to the my_action endpoint.

Read more about rate_limit in the official RateLimiting docs.

User reports & blocking (opt-in)

If your app has user-generated content or user-to-user interaction, you'll eventually need Trust & Safety primitives: letting users report content and block each other, plus an admin review queue. That's what the moderate gem provides. Uncomment gem "moderate", ">= 1.0.0.beta1" in the Gemfile and follow the moderate README.