Module: Studio::LinkToken
- Defined in:
- lib/studio/link_token.rb
Overview
Pure-Ruby helpers behind the Studio::Link model — token minting, the kind rules, and the input sanitizers. Kept free of ActiveRecord so it loads (and unit-tests) without a database, mirroring the other lib/studio/*.rb pure classes. The AR model (app/models/studio/link.rb) delegates to this.
Constant Summary collapse
- KINDS =
The kinds of link that share the studio_links table + the /l/
entry point. magic_link — single-use, short-lived passwordless sign-in / sign-up referral — reusable, non-expiring share link owned by a User %w[magic_link referral].freeze
- SINGLE_USE_KINDS =
Kinds burned on first successful consume. Referral links are reusable, so they are deliberately NOT single-use.
%w[magic_link].freeze
- TOKEN_BYTES =
THE HOUSE TOKEN STANDARD: 12 random bytes → exactly 16 URL-safe characters (e.g. "PP-PDbEj5V3-aNh4"). 96 bits of entropy — short enough that the whole link fits on one line of an email, far too large to brute-force, especially for a single-use token that expires in minutes.
16 sits mid-range in the house bound of 10-20 characters (TOKEN_LENGTH_ BOUNDS), which is the number a reader should sanity-check a link against. urlsafe_base64 emits 4 characters per 3 bytes with no padding, so the length is exact, not approximate — every token is the same width.
12- TOKEN_LENGTH =
16- TOKEN_LENGTH_BOUNDS =
(10..20).freeze
- TOKEN_FORMAT =
/\A[A-Za-z0-9_-]+\z/
Class Method Summary collapse
-
.generate ⇒ Object
A fresh URL-safe token.
- .kind?(kind) ⇒ Boolean
- .normalize_email(email) ⇒ Object
-
.sanitize_path(path) ⇒ Object
Only same-origin absolute paths survive; protocol-relative ("//evil"), absolute URLs, and blanks collapse to nil so callers fall back to a safe default redirect.
- .single_use?(kind) ⇒ Boolean
Class Method Details
.generate ⇒ Object
A fresh URL-safe token. urlsafe_base64 emits only [A-Za-z0-9_-], so the token satisfies the %r[^/]+ route constraint and survives URL generation without extra encoding.
40 41 42 |
# File 'lib/studio/link_token.rb', line 40 def generate SecureRandom.urlsafe_base64(TOKEN_BYTES) end |
.kind?(kind) ⇒ Boolean
44 45 46 |
# File 'lib/studio/link_token.rb', line 44 def kind?(kind) KINDS.include?(kind.to_s) end |
.normalize_email(email) ⇒ Object
52 53 54 |
# File 'lib/studio/link_token.rb', line 52 def normalize_email(email) email.to_s.strip.downcase end |
.sanitize_path(path) ⇒ Object
Only same-origin absolute paths survive; protocol-relative ("//evil"), absolute URLs, and blanks collapse to nil so callers fall back to a safe default redirect. Mirrors the MagicLink service's sanitizer.
59 60 61 62 |
# File 'lib/studio/link_token.rb', line 59 def sanitize_path(path) p = path.to_s p.start_with?("/") && !p.start_with?("//") ? p : nil end |
.single_use?(kind) ⇒ Boolean
48 49 50 |
# File 'lib/studio/link_token.rb', line 48 def single_use?(kind) SINGLE_USE_KINDS.include?(kind.to_s) end |