Flow: enter email → magic link → verified → Stripe checkout → dashboard - SessionsController: new/create (send magic link), sent, verify, destroy - Customer model: generate_magic_token!, magic_token_valid?, verify_email! - Migration: magic_token, magic_token_expires_at, email_verified_at + unique indexes - CustomerMailer + mailer layout with magic link email (html + text) - CheckoutController: GET /checkout/start requires auth, passes customer_id as Stripe metadata; webhook finds customer by metadata and updates record - DashboardController: requires auth, uses current_customer from session - ApplicationController: current_customer, require_auth, redirect_after_auth (stores return_to so verify sends user back to where they were headed) - Resend gem + initializer; production uses :resend delivery method - Dev logs magic link URL to Rails logger instead of sending email - Pricing page: simple link to /checkout/start (no more JS fetch) - Layout: Sign in / Dashboard / Sign out nav links Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
48 lines
1.2 KiB
Ruby
48 lines
1.2 KiB
Ruby
class SessionsController < ApplicationController
|
|
def new
|
|
redirect_to dashboard_path if current_customer
|
|
end
|
|
|
|
def create
|
|
email = params[:email].to_s.strip.downcase
|
|
|
|
unless email.match?(URI::MailTo::EMAIL_REGEXP)
|
|
flash.now[:alert] = "Please enter a valid email address."
|
|
return render :new, status: :unprocessable_entity
|
|
end
|
|
|
|
customer = Customer.find_or_initialize_by(email: email)
|
|
customer.generate_magic_token!
|
|
|
|
CustomerMailer.magic_link(customer).deliver_now
|
|
|
|
# In development, log the link so you don't need a real email service
|
|
if Rails.env.development?
|
|
Rails.logger.info "MAGIC LINK: #{verify_url(token: customer.magic_token)}"
|
|
end
|
|
|
|
redirect_to login_sent_path
|
|
end
|
|
|
|
def sent
|
|
end
|
|
|
|
def verify
|
|
customer = Customer.find_by(magic_token: params[:token])
|
|
|
|
if customer.nil? || !customer.magic_token_valid?
|
|
flash[:alert] = "That link has expired or is invalid. Request a new one."
|
|
return redirect_to login_path
|
|
end
|
|
|
|
customer.verify_email!
|
|
session[:customer_id] = customer.id
|
|
|
|
redirect_after_auth
|
|
end
|
|
|
|
def destroy
|
|
session.delete(:customer_id)
|
|
redirect_to root_path
|
|
end
|
|
end
|