From df610ae52e2652d17f28153cbf90b315874b40df Mon Sep 17 00:00:00 2001 From: Raygen Rupe Date: Fri, 26 Jun 2026 08:17:50 -0600 Subject: [PATCH 1/7] skip_setup_flow --- app/controllers/application_controller.rb | 14 + app/controllers/sessions_controller.rb | 23 +- app/controllers/users_controller.rb | 7 +- .../pages/WakatimeSetup/Index.svelte | 390 +++++++++++------- reset.sh | 21 + 5 files changed, 304 insertions(+), 151 deletions(-) create mode 100755 reset.sh diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 80bbbf4cf..949e6cf6d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -53,6 +53,20 @@ 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 + 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!" diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 1cde0c5df..0890272f4 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -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) @@ -22,13 +22,15 @@ def hca_create session[:return_data] = preserved_return_data if preserved_return_data notice = "Successfully signed in with Hack Club Auth! Welcome!" - if @user.previously_new_record? - redirect_to my_wakatime_setup_path, notice: notice - elsif session[:return_data]&.dig("url").present? - redirect_to session[:return_data].delete("url"), notice: notice - else - redirect_to root_path, notice: notice - end + # if @user.previously_new_record? + # redirect_to my_wakatime_setup_path, notice: notice + # elsif session[:return_data]&.dig("url").present? + # redirect_to session[:return_data].delete("url"), notice: notice + # else + # redirect_to root_path, notice: notice + # end + + redirect_to my_wakatime_setup_path, notice: notice else redirect_to root_path, alert: "Failed to authenticate with Hack Club Auth!" end @@ -71,7 +73,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] @@ -234,9 +236,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 diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 0d79c1b49..5cffc2182 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -7,13 +7,18 @@ class UsersController < InertiaController def wakatime_setup api_key = ensure_api_key + skipping = session.dig(:return_data, "skip_setup_flow") || params[:skip_setup_flow].present? + + # Clear so it doesn't persist across future visits + session[:return_data]&.delete("skip_setup_flow") if skipping render inertia: "WakatimeSetup/Index", props: { current_user_api_key: api_key.token, setup_os: detect_setup_os(request.user_agent).to_s, # Full URL (with host) is shown to users in their config file, so we # build it server-side rather than via js_from_routes. - api_url: api_hackatime_v1_url + api_url: api_hackatime_v1_url, + skip_setup_flow: skipping } end diff --git a/app/javascript/pages/WakatimeSetup/Index.svelte b/app/javascript/pages/WakatimeSetup/Index.svelte index e5162e764..e81188cd7 100644 --- a/app/javascript/pages/WakatimeSetup/Index.svelte +++ b/app/javascript/pages/WakatimeSetup/Index.svelte @@ -1,6 +1,7 @@ - Configure Hackatime - Step 1 + {skip_setup_flow + ? "Setup Complete - Step 4" + : "Configure Hackatime - Step 1"}
- - -
- - {#snippet success({ timeAgo })} -
-

- Setup complete! -

-

- Heartbeat detected {timeAgo}. + + + {#if skip_setup_flow} +

+
+ +
+

No code editor setup needed

+

+ 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 + My Setup on your dashboard.

-
- {/snippet} - +
-
- - - -
+
+

You're all set!

+

+ Hackatime is configured and tracking your code. +

- {#if activeSection === "mac-linux"} -
-
-

Configure Hackatime

-

{macLinuxSubtitle}

-
+
+

Fair Play Policy

+

+ Hackatime tracks the time you genuinely spend writing code. Fraud + means trying to make it look like you're coding when you are not, + including using scripts, bots, manipulated heartbeats, spoofed + editor activity, or API abuse. +

+

+ We have a zero-tolerance policy for fraud. Attempting to cheat the + system can result in a permanent ban from + Hackatime and all Hack Club events. Read the full policy on the + + >Fraud page. +

+

+ Hack Club is a non-profit running on donations, so please keep + your activity honest and respect the community. +

-
- -
-

Using GitHub Codespaces?

-

- Look for the Terminal tab at the bottom of your - window. If you don't see it, press - Ctrl+`. -

+
+
-
- -

- Search for "Terminal" in Spotlight (Mac) or your applications - menu. + +

+
+ {:else} +
+ + {#snippet success({ timeAgo })} +
+

+ Setup complete! +

+

+ Heartbeat detected {timeAgo}.

- - -
-
-
+ +
+ {/snippet} + -
- -
+
+ + +
- {/if} - {#if activeSection === "windows"} -
-
-

Configure Hackatime

-

{windowsSubtitle}

-
+ {#if activeSection === "mac-linux"} +
+
+

Configure Hackatime

+

{macLinuxSubtitle}

+
-
- -

- Press Win+R, type powershell, and press Enter. -

-
- -

- Right-click in PowerShell to paste the command. -

-
-
-
+
+ +
+

+ Using GitHub Codespaces? +

+

+ Look for the Terminal tab at the bottom of + your window. If you don't see it, press + Ctrl+`. +

+
+
-
- +
+ +

+ Search for "Terminal" in Spotlight (Mac) or your applications + menu. +

+
+ +
+
+
+ +
+ +
-
- {/if} + {/if} + + {#if activeSection === "windows"} +
+
+

Configure Hackatime

+

{windowsSubtitle}

+
- {#if activeSection === "advanced"} -
-
-

Configure Hackatime

-

{macLinuxSubtitle}

+
+ +

+ Press Win+R, type powershell, and press Enter. +

+
+ +

+ Right-click in PowerShell to paste the command. +

+
+
+
+ +
+ +
+ {/if} -
-

- Create or edit ~/.wakatime.cfg - with the following content: -

+ {#if activeSection === "advanced"} +
+
+

Configure Hackatime

+

{macLinuxSubtitle}

+
+ +
+

+ Create or edit ~/.wakatime.cfg + with the following content: +

+
+ +
+ {/if} - +
+ Skip to next step
- {/if} - -
- Skip to next step
-
+ {/if}
diff --git a/reset.sh b/reset.sh new file mode 100755 index 000000000..008c78d0d --- /dev/null +++ b/reset.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +docker compose restart db + +docker compose exec web rails db:reset + +docker compose exec web rails runner " +OauthApplication.create!( + id: 2, + confidential: true, + name: 'sd', + owner_id: 1, + owner_type: 'User', + redirect_to_hca_login: false, + redirect_uri: 'http://localhost:3001/auth/hackatime/callback', + scopes: 'profile read', + secret: '168L3q9SgZogm5jySI106nnbZI8FBFJ1hT6_FvqRG4w', + uid: '1urYGmQAvkxu23-I9gx4xpnrEy7U12b6ZlXAHxyg6Mo', + verified: true +) +" From 16fbfd62dcc93e019b9f66510fe097857225ef04 Mon Sep 17 00:00:00 2001 From: Raygen Rupe Date: Fri, 26 Jun 2026 09:41:06 -0600 Subject: [PATCH 2/7] fix auth redirect --- app/controllers/users_controller.rb | 4 +++- app/javascript/pages/WakatimeSetup/Index.svelte | 16 ++++++++++++---- reset.sh | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 5cffc2182..db538e260 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -18,7 +18,9 @@ def wakatime_setup # Full URL (with host) is shown to users in their config file, so we # build it server-side rather than via js_from_routes. api_url: api_hackatime_v1_url, - skip_setup_flow: skipping + skip_setup_flow: skipping, + return_url: skipping ? session.dig(:return_data, "url") : nil, + return_button_text: skipping ? (session.dig(:return_data, "button_text") || "Done") : nil } end diff --git a/app/javascript/pages/WakatimeSetup/Index.svelte b/app/javascript/pages/WakatimeSetup/Index.svelte index e81188cd7..5dc2fac74 100644 --- a/app/javascript/pages/WakatimeSetup/Index.svelte +++ b/app/javascript/pages/WakatimeSetup/Index.svelte @@ -15,10 +15,18 @@ setup_os: string; api_url: string; skip_setup_flow?: boolean; + return_url?: string; + return_button_text?: string; } - let { current_user_api_key, setup_os, api_url, skip_setup_flow }: Props = - $props(); + let { + current_user_api_key, + setup_os, + api_url, + skip_setup_flow, + return_url, + return_button_text, + }: Props = $props(); let agreed = $state(false); @@ -155,13 +163,13 @@
diff --git a/reset.sh b/reset.sh index 008c78d0d..240c946e7 100755 --- a/reset.sh +++ b/reset.sh @@ -14,7 +14,7 @@ OauthApplication.create!( redirect_to_hca_login: false, redirect_uri: 'http://localhost:3001/auth/hackatime/callback', scopes: 'profile read', - secret: '168L3q9SgZogm5jySI106nnbZI8FBFJ1hT6_FvqRG4w', + secret: '61IuM8ndjSKV-tbIy3kwk4euagajbzjf8w-m0wuu6Do', uid: '1urYGmQAvkxu23-I9gx4xpnrEy7U12b6ZlXAHxyg6Mo', verified: true ) From 8547c3dec8cbedae240b79a936c9219958c12c15 Mon Sep 17 00:00:00 2001 From: Raygen Rupe Date: Fri, 26 Jun 2026 09:41:22 -0600 Subject: [PATCH 3/7] remove debug script --- reset.sh | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100755 reset.sh diff --git a/reset.sh b/reset.sh deleted file mode 100755 index 240c946e7..000000000 --- a/reset.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -docker compose restart db - -docker compose exec web rails db:reset - -docker compose exec web rails runner " -OauthApplication.create!( - id: 2, - confidential: true, - name: 'sd', - owner_id: 1, - owner_type: 'User', - redirect_to_hca_login: false, - redirect_uri: 'http://localhost:3001/auth/hackatime/callback', - scopes: 'profile read', - secret: '61IuM8ndjSKV-tbIy3kwk4euagajbzjf8w-m0wuu6Do', - uid: '1urYGmQAvkxu23-I9gx4xpnrEy7U12b6ZlXAHxyg6Mo', - verified: true -) -" From 024c838ebc933caeab82504d0fa91ae37c6d3f65 Mon Sep 17 00:00:00 2001 From: Raygen Rupe Date: Fri, 26 Jun 2026 10:11:19 -0600 Subject: [PATCH 4/7] fmt --- app/javascript/pages/WakatimeSetup/Index.svelte | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/javascript/pages/WakatimeSetup/Index.svelte b/app/javascript/pages/WakatimeSetup/Index.svelte index 5dc2fac74..4aff59a92 100644 --- a/app/javascript/pages/WakatimeSetup/Index.svelte +++ b/app/javascript/pages/WakatimeSetup/Index.svelte @@ -82,20 +82,20 @@ {#if skip_setup_flow}
-
+
-

No code editor setup needed

+

+ No code editor setup needed +

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 + set up a code editor right now. If you'd like to connect one + later, you can always do so from Date: Fri, 26 Jun 2026 10:35:17 -0600 Subject: [PATCH 5/7] fix hca_create issue --- app/controllers/sessions_controller.rb | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 0890272f4..1adabee74 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -22,15 +22,14 @@ def hca_create session[:return_data] = preserved_return_data if preserved_return_data notice = "Successfully signed in with Hack Club Auth! Welcome!" - # if @user.previously_new_record? - # redirect_to my_wakatime_setup_path, notice: notice - # elsif session[:return_data]&.dig("url").present? - # redirect_to session[:return_data].delete("url"), notice: notice - # else - # redirect_to root_path, notice: notice - # end - - redirect_to my_wakatime_setup_path, notice: notice + if @user.previously_new_record? + redirect_to my_wakatime_setup_path, notice: notice + elsif session[:return_data]&.dig("url").present? + redirect_to session[:return_data].delete("url"), notice: notice + else + redirect_to root_path, notice: notice + end + else redirect_to root_path, alert: "Failed to authenticate with Hack Club Auth!" end From 87be8d1fa951e3936e70120855c46e2d5b079105 Mon Sep 17 00:00:00 2001 From: Raygen Rupe Date: Sat, 27 Jun 2026 06:53:05 -0600 Subject: [PATCH 6/7] remove whitespace + remove debug log + change fair play policy --- app/controllers/sessions_controller.rb | 1 - app/javascript/pages/WakatimeSetup/Index.svelte | 8 ++------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index 1adabee74..52284e623 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -29,7 +29,6 @@ def hca_create else redirect_to root_path, notice: notice end - else redirect_to root_path, alert: "Failed to authenticate with Hack Club Auth!" end diff --git a/app/javascript/pages/WakatimeSetup/Index.svelte b/app/javascript/pages/WakatimeSetup/Index.svelte index 4aff59a92..8304b880e 100644 --- a/app/javascript/pages/WakatimeSetup/Index.svelte +++ b/app/javascript/pages/WakatimeSetup/Index.svelte @@ -62,10 +62,6 @@ const advancedCfg = $derived( `[settings]\napi_url = ${api_url}\napi_key = ${current_user_api_key}\nheartbeat_rate_limit_seconds = 30`, ); - - onMount(() => { - console.log(current_user_api_key, setup_os, api_url, skip_setup_flow); - }); @@ -114,8 +110,8 @@

Fair Play Policy

- Hackatime tracks the time you genuinely spend writing code. Fraud - means trying to make it look like you're coding when you are not, + Hackatime tracks the time you actually work on projects. Fraud + means trying to make it look like you're working when you are not, including using scripts, bots, manipulated heartbeats, spoofed editor activity, or API abuse.

From b9911c3c686d831fdcd4959738cc5c44e8daf738 Mon Sep 17 00:00:00 2001 From: Mahad Kalam Date: Sun, 28 Jun 2026 21:41:27 +0100 Subject: [PATCH 7/7] Cleanup? --- app/controllers/application_controller.rb | 1 + app/controllers/users_controller.rb | 23 +- .../pages/WakatimeSetup/Index.svelte | 394 ++++++------------ .../pages/WakatimeSetup/Step4.svelte | 34 +- 4 files changed, 186 insertions(+), 266 deletions(-) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 949e6cf6d..ebb5896da 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -62,6 +62,7 @@ def build_return_data(continue_url) 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 } diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index db538e260..1ca8d5a2a 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -6,21 +6,21 @@ class UsersController < InertiaController before_action :require_admin, only: [ :update_trust_level ] def wakatime_setup - api_key = ensure_api_key - skipping = session.dig(:return_data, "skip_setup_flow") || params[:skip_setup_flow].present? - - # Clear so it doesn't persist across future visits - session[:return_data]&.delete("skip_setup_flow") if skipping + # 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, # Full URL (with host) is shown to users in their config file, so we # build it server-side rather than via js_from_routes. - api_url: api_hackatime_v1_url, - skip_setup_flow: skipping, - return_url: skipping ? session.dig(:return_data, "url") : nil, - return_button_text: skipping ? (session.dig(:return_data, "button_text") || "Done") : nil + api_url: api_hackatime_v1_url } end @@ -35,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" } diff --git a/app/javascript/pages/WakatimeSetup/Index.svelte b/app/javascript/pages/WakatimeSetup/Index.svelte index 8304b880e..e5162e764 100644 --- a/app/javascript/pages/WakatimeSetup/Index.svelte +++ b/app/javascript/pages/WakatimeSetup/Index.svelte @@ -1,7 +1,6 @@ - {skip_setup_flow - ? "Setup Complete - Step 4" - : "Configure Hackatime - Step 1"} + Configure Hackatime - Step 1
- - - {#if skip_setup_flow} -
-
- -
-

- No code editor setup needed -

-

- 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 - My Setup on your dashboard. + + +

+ + {#snippet success({ timeAgo })} +
+

+ Setup complete! +

+

+ Heartbeat detected {timeAgo}.

+
-
+ {/snippet} + -
-

You're all set!

-

- Hackatime is configured and tracking your code. -

- -
-

Fair Play Policy

-

- Hackatime tracks the time you actually work on projects. Fraud - means trying to make it look like you're working when you are not, - including using scripts, bots, manipulated heartbeats, spoofed - editor activity, or API abuse. -

-

- We have a zero-tolerance policy for fraud. Attempting to cheat the - system can result in a permanent ban from - Hackatime and all Hack Club events. Read the full policy on the - - >Fraud page. -

-

- Hack Club is a non-profit running on donations, so please keep - your activity honest and respect the community. -

+
+ + + +
-
- -
+ {#if activeSection === "mac-linux"} +
+
+

Configure Hackatime

+

{macLinuxSubtitle}

- -
-
- {:else} -
- - {#snippet success({ timeAgo })} -
-

- Setup complete! -

-

- Heartbeat detected {timeAgo}. + +

+

Using GitHub Codespaces?

+

+ Look for the Terminal tab at the bottom of your + window. If you don't see it, press + Ctrl+`.

- -
- {/snippet} - - -
- - - -
- - {#if activeSection === "mac-linux"} -
-
-

Configure Hackatime

-

{macLinuxSubtitle}

-
- -
- -
-

- Using GitHub Codespaces? -

-

- Look for the Terminal tab at the bottom of - your window. If you don't see it, press - Ctrl+`. -

-
-
- -
- -

- Search for "Terminal" in Spotlight (Mac) or your applications - menu. -

-
- -
-
+
-
- -
+
+ +

+ Search for "Terminal" in Spotlight (Mac) or your applications + menu. +

+
+ +
+
- {/if} - {#if activeSection === "windows"} -
-
-

Configure Hackatime

-

{windowsSubtitle}

-
+
+ +
+
+ {/if} -
- -

- Press Win+R, type powershell, and press Enter. -

-
- -

- Right-click in PowerShell to paste the command. -

-
-
-
+ {#if activeSection === "windows"} +
+
+

Configure Hackatime

+

{windowsSubtitle}

+
-
- -
+
+ +

+ Press Win+R, type powershell, and press Enter. +

+
+ +

+ Right-click in PowerShell to paste the command. +

+
+
- {/if} - {#if activeSection === "advanced"} -
-
-

Configure Hackatime

-

{macLinuxSubtitle}

-
+
+ +
+
+ {/if} -
-

- Create or edit ~/.wakatime.cfg - with the following content: -

-
+ {#if activeSection === "advanced"} +
+
+

Configure Hackatime

+

{macLinuxSubtitle}

+
- +
+

+ Create or edit ~/.wakatime.cfg + with the following content: +

- {/if} -
- Skip to next step +
+ {/if} + +
+ Skip to next step
- {/if} +
diff --git a/app/javascript/pages/WakatimeSetup/Step4.svelte b/app/javascript/pages/WakatimeSetup/Step4.svelte index 95d443157..4cbef06c9 100644 --- a/app/javascript/pages/WakatimeSetup/Step4.svelte +++ b/app/javascript/pages/WakatimeSetup/Step4.svelte @@ -1,14 +1,17 @@ @@ -21,6 +24,33 @@
+ {#if hardware} +
+ +
+

+ No code editor setup needed +

+

+ 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 + My Setup on your dashboard. +

+
+
+ {/if} +

You're all set!

@@ -45,7 +75,7 @@ rel="noreferrer" class="underline font-semibold" > - >Fraud page.