Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
15 changes: 15 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,21 @@ def safe_return_url(url)
url
end

# Build a return_data hash from a continue URL, extracting known query
# params (like skip_setup_flow) so they survive auth redirects.
def build_return_data(continue_url)
url = safe_return_url(continue_url)
return {} if url.blank?

data = { "url" => url }
query = Rack::Utils.parse_query(URI.parse(url).query.to_s)
data["skip_setup_flow"] = true if query.key?("skip_setup_flow")
data["button_text"] = query["button_text"] if query["button_text"].present?
data
rescue URI::InvalidURIError
{ "url" => url }
end

def authenticate_user!
unless user_signed_in?
redirect_to signin_path(continue: request.fullpath), alert: "Please sign in first!"
Expand Down
7 changes: 3 additions & 4 deletions app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class SessionsController < ApplicationController
def hca_new
session[:return_data] = { "url" => safe_return_url(params[:continue].presence) } if params[:continue].present?
session[:return_data] = build_return_data(params[:continue]) if params[:continue].present?
Rails.logger.info("Sessions return data: #{session[:return_data]}")
redirect_uri = url_for(action: :hca_create, only_path: false)

Expand Down Expand Up @@ -71,7 +71,7 @@ def slack_create
if slack_state&.dig("close_window")
redirect_to close_window_path
elsif @user.previously_new_record?
session[:return_data] = { "url" => continue_url }
session[:return_data] = build_return_data(continue_url)
redirect_to my_wakatime_setup_path, notice: notice
elsif continue_url.present?
redirect_to continue_url, notice: notice # codeql[rb/url-redirection]
Expand Down Expand Up @@ -234,9 +234,8 @@ def token
valid_token.mark_used!
reset_session
session[:user_id] = valid_token.user_id
session[:return_data] = valid_token.return_data || {}

continue_url = safe_return_url(valid_token.continue_param)
session[:return_data] = (valid_token.return_data || {}).merge(build_return_data(continue_url))
if continue_url.present?
redirect_to continue_url, notice: "Successfully signed in!" # codeql[rb/url-redirection]
else
Expand Down
14 changes: 13 additions & 1 deletion app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@ class UsersController < InertiaController
before_action :require_admin, only: [ :update_trust_level ]

def wakatime_setup
api_key = ensure_api_key
# Hardware-program users skip editor setup and go straight to the
# "you're all set" page (step 4). Persist the flag so it survives the
# redirect even when it arrived as a bare query param.
if session.dig(:return_data, "skip_setup_flow") || params[:skip_setup_flow].present?
session[:return_data] = (session[:return_data] || {}).merge("skip_setup_flow" => true)
return redirect_to my_wakatime_setup_step_4_path
end

api_key = ensure_api_key
render inertia: "WakatimeSetup/Index", props: {
current_user_api_key: api_key.token,
setup_os: detect_setup_os(request.user_agent).to_s,
Expand All @@ -28,7 +35,12 @@ def wakatime_setup_step_3
end

def wakatime_setup_step_4
hardware = session.dig(:return_data, "skip_setup_flow").present?
# Clear so it doesn't persist across future visits
session[:return_data]&.delete("skip_setup_flow")

render inertia: "WakatimeSetup/Step4", props: {
hardware: hardware,
return_url: session.dig(:return_data, "url"),
return_button_text: session.dig(:return_data, "button_text") || "Done"
}
Expand Down
34 changes: 32 additions & 2 deletions app/javascript/pages/WakatimeSetup/Step4.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
<script lang="ts">
import { Checkbox } from "bits-ui";
import { Link } from "@inertiajs/svelte";
import { Icon, InformationCircle } from "svelte-hero-icons";
import Button from "../../components/Button.svelte";
import Stepper from "./Stepper.svelte";

interface Props {
return_url?: string;
return_button_text: string;
hardware?: boolean;
}

let { return_url, return_button_text }: Props = $props();
let { return_url, return_button_text, hardware = false }: Props = $props();

let agreed = $state(false);
</script>
Expand All @@ -21,6 +24,33 @@
<div class="max-w-2xl mx-auto px-4">
<Stepper currentStep={4} />

{#if hardware}
<div
class="bg-blue/5 border border-blue/20 rounded-xl p-5 mb-6 flex gap-3"
>
<Icon
src={InformationCircle}
size="22"
class="text-blue shrink-0 mt-0.5"
/>
<div class="text-sm">
<p class="font-semibold text-blue mb-1">
No code editor setup needed
</p>
<p class="text-secondary">
Since you're joining through a hardware program, you don't need to
set up a code editor right now. If you'd like to connect one later,
you can always do so from
<Link
href="/my/wakatime_setup"
class="text-primary underline hover:text-primary/80"
>My&nbsp;Setup</Link
> on your dashboard.
</p>
</div>
</div>
{/if}

<div class="bg-dark border border-darkless rounded-xl p-6 text-center">
<h1 class="text-lg font-bold mb-2">You're all set!</h1>
<p class="mb-8 text-sm">
Expand All @@ -45,7 +75,7 @@
rel="noreferrer"
class="underline font-semibold"
>
>Fraud page</a
Fraud page</a
>.
</p>
<p class="text-sm mt-3">
Expand Down