Skip to content
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
VITE_CLERK_PUBLISHABLE_KEY=pk_test_123

VITE_CLERK_SIGN_IN_URL=/sign_in
VITE_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL=/dashboard
VITE_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL=/dashboard
VITE_CLERK_PUBLISHABLE_KEY=pk_test_123
35 changes: 34 additions & 1 deletion app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

class SessionsController < InertiaController
skip_before_action :authenticate_user!, only: %i[ new ]
skip_before_action :authenticate_user!, only: %i[ new create sign_up create_signup ]

def new
if user_signed_in?
Expand All @@ -10,6 +10,39 @@ def new
end
end

def create
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need create

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the create method as it was unnecessary. The POST /sign_in endpoint isn't needed since Clerk manages authentication through its own frontend flow. Changes in commit 012a1d2.

# Handle Clerk token and create Rails session
clerk_token = params[:clerk_token]

if clerk_token.present?
# The token verification is handled by the Clerk middleware
# If we reach here, the user is authenticated
head :ok
else
head :unauthorized
end
end

def sign_up
if user_signed_in?
flash[:notice] = "You are already signed in"
redirect_to root_path
end
end

def create_signup
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need create_signup. this does not do anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the create_signup method as it was unnecessary. Clerk handles authentication entirely on the frontend through the __session cookie, so POST endpoints for token validation aren't part of the standard flow. Changes in commit 012a1d2.

# Handle Clerk token and create Rails session for sign-up
clerk_token = params[:clerk_token]

if clerk_token.present?
# The token verification is handled by the Clerk middleware
# If we reach here, the user is authenticated
head :ok
else
head :unauthorized
end
end

def switch
# renders the account selector page
end
Expand Down
65 changes: 65 additions & 0 deletions app/frontend/pages/sessions/sign_up.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { SignUp, useAuth } from "@clerk/clerk-react"
import { Head, router } from "@inertiajs/react"
import { useEffect } from "react"

import AuthLayout from "@/layouts/auth-layout"

export default function SignUpPage() {
const { getToken, isSignedIn } = useAuth()

useEffect(() => {
const createSession = async () => {
if (isSignedIn) {
try {
const token = await getToken()
if (token) {
// Post the clerk token to our backend to create a session
await fetch("/sign_up", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token":
document
.querySelector('meta[name="csrf-token"]')
?.getAttribute("content") ?? "",
},
body: JSON.stringify({ clerk_token: token }),
})

// Redirect after successful session creation
router.visit("/dashboard")
}
} catch (error) {
console.error("Failed to create session:", error)
}
}
}

void createSession()
}, [isSignedIn, getToken])

return (
<AuthLayout
title="Welcome"
description="Create your account to get started"
>
<Head title="Sign up" />

<div className="flex justify-center">
<SignUp routing="path" path="/sign_up" fallbackRedirectUrl="/switch" />
</div>

<div className="text-muted-foreground mt-6 text-center text-xs">
By clicking continue, you agree to our{" "}
<a href="#" className="hover:text-primary underline underline-offset-4">
Terms of Service
</a>{" "}
and{" "}
<a href="#" className="hover:text-primary underline underline-offset-4">
Privacy Policy
</a>
.
</div>
</AuthLayout>
)
}
14 changes: 12 additions & 2 deletions app/frontend/routes/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* @file Generated by js-routes 2.3.5. Based on Rails 8.0.2 routes of InertiaRailsShadcnStarter::Application.
* @version 8768cfd61fbd4e0dcca2080f637cacf221d79cdb73f8a56ffaa8cbaa3268a4fe
* @file Generated by js-routes 2.3.5. Based on Rails 8.0.2.1 routes of InertiaRailsShadcnStarter::Application.
* @version 06c66b0089ef8669a19a912743babeb60c949a23bf292fe7b05b04587232096c
* @see https://github.com/railsware/js-routes
*/
declare type Optional<T> = {
Expand Down Expand Up @@ -406,6 +406,16 @@ export const signInPath: ((
options?: {format?: OptionalRouteParameter} & RouteOptions
) => string) & RouteHelperExtras;

/**
* Generates rails route to
* /sign_up(.:format)
* @param {object | undefined} options
* @returns {string} route path
*/
export const signUpPath: ((
options?: {format?: OptionalRouteParameter} & RouteOptions
) => string) & RouteHelperExtras;

/**
* Generates rails route to
* /switch(.:format)
Expand Down
12 changes: 10 additions & 2 deletions app/frontend/routes/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* @file Generated by js-routes 2.3.5. Based on Rails 8.0.2 routes of InertiaRailsShadcnStarter::Application.
* @version 8768cfd61fbd4e0dcca2080f637cacf221d79cdb73f8a56ffaa8cbaa3268a4fe
* @file Generated by js-routes 2.3.5. Based on Rails 8.0.2.1 routes of InertiaRailsShadcnStarter::Application.
* @version 06c66b0089ef8669a19a912743babeb60c949a23bf292fe7b05b04587232096c
* @see https://github.com/railsware/js-routes
*/
// eslint-disable-next-line
Expand Down Expand Up @@ -792,6 +792,14 @@ export const settingsAppearancePath = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7
*/
export const signInPath = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7,"/"],[2,[6,"sign_in"],[1,[2,[8,"."],[3,"format"]]]]]);

/**
* Generates rails route to
* /sign_up(.:format)
* @param {object | undefined} options
* @returns {string} route path
*/
export const signUpPath = /*#__PURE__*/ __jsr.r({"format":{}}, [2,[7,"/"],[2,[6,"sign_up"],[1,[2,[8,"."],[3,"format"]]]]]);

/**
* Generates rails route to
* /switch(.:format)
Expand Down
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

Rails.application.routes.draw do
get "sign_in", to: "sessions#new", as: :sign_in
post "sign_in", to: "sessions#create"
get "sign_up", to: "sessions#sign_up", as: :sign_up
post "sign_up", to: "sessions#create_signup"
get "switch", to: "sessions#switch", as: :switch_account

# Clerk webhook endpoint
Expand Down
51 changes: 51 additions & 0 deletions spec/requests/sessions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,57 @@
end
end

describe "GET /sign_up" do
context "when user is not signed in" do
it "returns http success" do
get sign_up_url
expect(response).to have_http_status(:success)
end
end

context "when user is already signed in" do
before { sign_in_as user }

it "redirects to root with notice" do
get sign_up_url
expect(response).to redirect_to(root_path)
expect(flash[:notice]).to eq("You are already signed in")
end
end
end

describe "POST /sign_in" do
context "with valid clerk token" do
it "returns success" do
post "/sign_in", params: {clerk_token: "valid_token"}
expect(response).to have_http_status(:ok)
end
end

context "without clerk token" do
it "returns unauthorized" do
post "/sign_in", params: {}
expect(response).to have_http_status(:unauthorized)
end
end
end

describe "POST /sign_up" do
context "with valid clerk token" do
it "returns success" do
post "/sign_up", params: {clerk_token: "valid_token"}
expect(response).to have_http_status(:ok)
end
end

context "without clerk token" do
it "returns unauthorized" do
post "/sign_up", params: {}
expect(response).to have_http_status(:unauthorized)
end
end
end

describe "GET /switch" do
context "when user is signed in" do
before { sign_in_as user }
Expand Down