Class: Studio::LinksController

Inherits:
ApplicationController
  • Object
show all
Includes:
LinkConsumption
Defined in:
app/controllers/studio/links_controller.rb

Overview

The short-token link entry point — GET/POST /l/, the only magic-link door the engine draws. Dispatches by Studio::Link#kind:

magic_link → scanner-safe confirm interstitial (GET, inert) that auto-POSTs
           to #consume, the ONLY place the single-use token is burned +
           the recipient is signed in / signed up.
referral   → idempotent: capture attribution into a cookie + redirect to
           the link's target (or root). Reusable + safe to prefetch, so
           GET does the work (no POST step).

Every decision about what a magic-link click DOES lives in Studio::LinkConsumption / Studio::LinkResolution, not here — including the invariant that a dead link leaves the visitor's session untouched.

Namespaced (not top-level Links) because mcritchie-studio already owns a public /links linktree (top-level LinksController). Apps needing richer post-consume routing (contest landing, picks rehydration, age-gate) define their own Studio::LinksController and reuse Studio::Link + the Studio::LinkConsumption building blocks.

Instance Method Summary collapse

Instance Method Details

#consumeObject

POST /l/:token — authoritative magic-link consume. Only magic_link kinds are consumable here; referral links are reusable and handled entirely on GET, so a referral token scoped out below reads as an unknown token.



47
48
49
50
# File 'app/controllers/studio/links_controller.rb', line 47

def consume
  response.set_header("Referrer-Policy", "strict-origin")
  consume_magic_link(Studio::Link.magic_links.find_by(token: params[:token]))
end

#showObject

GET /l/:token



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'app/controllers/studio/links_controller.rb', line 28

def show
  response.set_header("Referrer-Policy", "strict-origin")
  @link = Studio::Link.find_by(token: params[:token])

  if @link&.kind == "referral"
    capture_referral(@link)
    return redirect_to(@link.target || root_path)
  end

  # A magic link, or a token with no row behind it. preview_magic_link is
  # inert — it never burns — and settles a dead link itself rather than
  # sending the visitor through a spinner that only POSTs to learn the same.
  @token = params[:token]
  render :confirm if preview_magic_link(@link&.kind == "magic_link" ? @link : nil) == :live
end