diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000..8f4bed69c2 --- /dev/null +++ b/.env.example @@ -0,0 +1,8 @@ +# Copy to .env and fill in real values for local development. .env is gitignored -- +# never commit real values here or in .env itself. + +# Google OAuth client id used by the login/signup and password-reset OAuth flows +# (see the comment on google_client_id in _config.yml for why this isn't just +# hardcoded there). Ask a maintainer for the real value -- it's the same one +# production uses, stored as a GitHub Actions repository secret for CI. +GOOGLE_CLIENT_ID= diff --git a/.github/workflows/jekyll-gh-pages.yml b/.github/workflows/jekyll-gh-pages.yml index ee6b66e0b5..fb77a80b46 100644 --- a/.github/workflows/jekyll-gh-pages.yml +++ b/.github/workflows/jekyll-gh-pages.yml @@ -101,6 +101,16 @@ jobs: echo "baseurl: \"$BASEURL\"" > _config.override.yml + # google_client_id must never be committed to the repo (see the comment on + # it in _config.yml) -- injected here from a repository secret instead, + # into the same gitignored override file used for baseurl above. Requires + # a repo admin to add the GOOGLE_CLIENT_ID secret in Settings > Secrets and + # variables > Actions; the site builds fine without it, the Google sign-in + # button just won't render until it's set. + if [ -n "${{ secrets.GOOGLE_CLIENT_ID }}" ]; then + echo "google_client_id: \"${{ secrets.GOOGLE_CLIENT_ID }}\"" >> _config.override.yml + fi + - name: Generate dynamic SASS imports run: | source venv/bin/activate diff --git a/Makefile b/Makefile index 5ca228928c..7c5dbe1614 100644 --- a/Makefile +++ b/Makefile @@ -480,11 +480,13 @@ bundle-install: fi # Start Jekyll server (no auto-watch, we control rebuilds manually) -# Supports optional _config.local.yml override for local settings (e.g. baseurl) +# Supports optional _config.local.yml override for local settings (e.g. baseurl, +# google_client_id -- see scripts/generate_local_config_override.sh and .env.example) jekyll-serve: bundle-install @touch /tmp/.notebook_watch_marker @rm -f /tmp/.jekyll_rebuild_trigger - bundle exec jekyll serve -H $(HOST) -P $(PORT) --no-watch > $(LOG_FILE) 2>&1 & + @./scripts/generate_local_config_override.sh + bundle exec jekyll serve -H $(HOST) -P $(PORT) --no-watch --config _config.yml,_config.local.yml > $(LOG_FILE) 2>&1 & @make wait-for-server # Common server wait logic diff --git a/_config.yml b/_config.yml index 680b6c3f74..f6098b9037 100644 --- a/_config.yml +++ b/_config.yml @@ -20,8 +20,17 @@ description: "Class of 2026" owner_name: Open Coding Society github_username: open-coding-society github_repo: "pages" -baseurl: "" +baseurl: "" future: true +# google_client_id is intentionally NOT set here -- per John Mortensen's review on +# PR #1371, it must not be committed to the public repo. It's injected at build time +# into a gitignored override config instead: locally into _config.local.yml via +# scripts/generate_local_config_override.sh reading .env (see .env.example), in CI +# into _config.override.yml via the "Compute and apply baseurl" step in +# .github/workflows/jekyll-gh-pages.yml (which already generates that file for +# baseurl) reading a repository secret. Either way, assets/js/api/config.js's +# GOOGLE_CLIENT_ID and login.md's #g_id_onload data-client_id pull the same +# google_client_id key via Liquid -- one source of truth, just never a committed one. # Exclude from Jekyll watch - these are processed by our conversion scripts # This prevents double-regeneration when saving notebooks/docx files diff --git a/_layouts/profile.html b/_layouts/profile.html index b19f088105..49cb09a16f 100644 --- a/_layouts/profile.html +++ b/_layouts/profile.html @@ -58,11 +58,8 @@

Personal Information

- - + + Forgot your password?
@@ -1317,7 +1314,6 @@

Selection Failed

const uidInput = document.getElementById("uidChangeInput"); const emailInput = document.getElementById("emailChangeInput"); const sidInput = document.getElementById("sidChangeInput"); - const passwordInput = document.getElementById("password"); const kasmInput = document.getElementById("kasmChangeInput"); const schoolInput = document.getElementById("schoolChangeInput"); @@ -1326,7 +1322,6 @@

Selection Failed

const uid = uidInput.value.trim(); const email = emailInput.value.trim(); const sid = sidInput.value.trim(); - const password = passwordInput.value.trim(); const kasmServerNeeded = kasmInput ? kasmInput.checked : undefined; const school = schoolInput.value; @@ -1422,26 +1417,6 @@

Selection Failed

} } - // save password (both backends, logs out) - if (password) { - try { - await Promise.all([ - putUpdate({ - URL: pythonURI + "/api/user", - body: { password }, - message: 'password-message' - }), - postUpdate({ - URL: javaURI + "/api/person/update", - body: { password } - }) - ]); - needsLogout = true; - } catch (e) { - console.error("error saving password:", e.message); - } - } - // save kasm server status (both backends) if ( typeof kasmServerNeeded !== "undefined" && @@ -1511,7 +1486,7 @@

Selection Failed

// handle reload or logout if needed if (needsLogout) { - alert("you updated your github id or password, so you will be logged out. remember your new credentials!"); + alert("you updated your github id, so you will be logged out. remember your new credentials!"); window.location.href = '{{site.baseurl}}'; } else if (needsReload) { window.location.reload(); diff --git a/_sass/open-coding/elements/forms/passwordvalidation.scss b/_sass/open-coding/elements/forms/passwordvalidation.scss index b2c6ced620..a0d015c26c 100644 --- a/_sass/open-coding/elements/forms/passwordvalidation.scss +++ b/_sass/open-coding/elements/forms/passwordvalidation.scss @@ -19,6 +19,11 @@ $validation-focus-color: #6366f1 !default; box-shadow: 0 0 0 1px $validation-error-color !important; } +.password-length { + border-color: $validation-error-color !important; + box-shadow: 0 0 0 1px $validation-error-color !important; +} + // Validation message styling .validation-message { font-size: 0.8rem; diff --git a/assets/js/api/config.js b/assets/js/api/config.js index c5394b8747..99e0ea63f2 100644 --- a/assets/js/api/config.js +++ b/assets/js/api/config.js @@ -21,6 +21,10 @@ if (location.hostname === "localhost" || location.hostname === "127.0.0.1") { javaURI = "https://spring.opencodingsociety.com"; } +// Shared across the signup, login, and password-reset OAuth flows (login.md, +// support.md) so the client_id only needs updating in one place. +export const GOOGLE_CLIENT_ID = "{{ site.google_client_id }}"; + export var javaWebSocketURI; if (location.hostname === "localhost" || location.hostname === "127.0.0.1") { javaWebSocketURI = "http://localhost:8589"; diff --git a/navigation/authentication/login.md b/navigation/authentication/login.md index 296da6aede..0440a53fd8 100644 --- a/navigation/authentication/login.md +++ b/navigation/authentication/login.md @@ -25,6 +25,9 @@ show_reading_time: false

+

+ Forgot your password? +

@@ -38,7 +41,7 @@ show_reading_time: false
You must use an email ending in @stu.powayusd.com or @powayusd.com

@@ -120,12 +123,11 @@ show_reading_time: false
+ + + + +
+ +
+ ← Back to Login +
+
+ + +
+
+

Let's Reset Your Password

+
+
+
+ +
+

+ +

+
+
+

+ Sign in with your @stu.powayusd.com school Google account to verify it's you. +

+
+
+ +
+
+
+ +
+
+ +
+

+

+ +

+
+

+
+ ← Back +
+
+
+ + diff --git a/scripts/generate_local_config_override.sh b/scripts/generate_local_config_override.sh new file mode 100755 index 0000000000..89f5cefc5d --- /dev/null +++ b/scripts/generate_local_config_override.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Writes _config.local.yml (gitignored -- see Makefile's jekyll-serve comment, this +# is the file it already documents as "optional _config.local.yml override for local +# settings") from local .env values that must never be committed to the repo -- +# currently just GOOGLE_CLIENT_ID (see .env.example and the comment on +# google_client_id in _config.yml). Mirrors the same idea +# .github/workflows/jekyll-gh-pages.yml uses for CI (its own _config.override.yml, +# generated fresh each run there), just sourced from a local .env instead of a +# repository secret. Safe to run even with no .env present: writes a file with +# google_client_id left unset, and Jekyll serves fine without it (the Google sign-in +# button just won't render). +set -euo pipefail + +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +if [ -f .env ]; then + set -a + # shellcheck disable=SC1091 + source .env + set +a +fi + +{ + echo "# Auto-generated by scripts/generate_local_config_override.sh -- do not edit" + echo "# or commit; re-run this script (or just start-dev.sh) after editing .env." + if [ -n "${GOOGLE_CLIENT_ID:-}" ]; then + echo "google_client_id: \"${GOOGLE_CLIENT_ID}\"" + fi +} > _config.local.yml