diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b86695..a08d08d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,8 +8,8 @@ you through it. ## Setup ```bash -git clone https://github.com//.git -cd /web +git clone https://github.com/ScalerOpenSourceLabsOrg/scaleropensourcelabs.com.git +cd scaleropensourcelabs.com/web npm install npm run dev # http://localhost:3000 # port 3000 is often taken; use `npm run dev -- -p 3001` diff --git a/web/components/JoinGate.tsx b/web/components/JoinGate.tsx index c8ef92e..1a52410 100644 --- a/web/components/JoinGate.tsx +++ b/web/components/JoinGate.tsx @@ -241,8 +241,10 @@ function Gate() {

Sign-in is not set up here.

This deployment has no Firebase configuration, so registration is switched off. - If you are running the site locally, see web/.env.example. If you - are seeing this on the live site, that is a bug — please tell us. + When sign-in is available, only students with an @{DOMAIN} + address can register. If you are running the site locally, see{" "} + web/.env.example. If you are seeing this on the live site, that is a + bug — please tell us.

Email the organisers diff --git a/web/scripts/smoke.mjs b/web/scripts/smoke.mjs index 7c3b4df..0e671e5 100644 --- a/web/scripts/smoke.mjs +++ b/web/scripts/smoke.mjs @@ -205,34 +205,38 @@ await pg.waitForTimeout(700); // deleted. The page held an anonymous application form for a spell; membership is an // @sst.scaler.com address, which is the one thing that form could not check, so the door // and the test are the same act now. +const joinState = await pg.evaluate(() => { + const text = document.querySelector("main")?.innerText ?? ""; + return { + configured: /continue with google|sign in with your college account/i.test(text), + unconfigured: /sign-in is not set up here/i.test(text), + hasFormFields: + document.querySelectorAll("main input, main select, main textarea").length > 0, + statesDomain: /sst\.scaler\.com/i.test(text), + }; +}); + +// CI intentionally runs without Firebase configuration. In that environment /join must +// show the honest "not configured" state instead of a fake sign-in control. In a configured +// deployment it must show the real college-account sign-in gate. Both states must remain +// form-free. ok( - "join offers sign-in, not a form", - (await pg.evaluate(() => - /continue with google/i.test(document.querySelector("main")?.innerText ?? ""), - )), + "join shows a valid gate state", + joinState.configured || joinState.unconfigured, ); -// THE ASSERTION THAT WOULD CATCH A REGRESSION HERE. A form reappearing on this page is -// the specific thing this change removed, so its absence is checked rather than assumed — -// zero inputs of any kind in the main column. ok( "and no application fields survive on the page", - (await pg.evaluate( - () => document.querySelectorAll("main input, main select, main textarea").length, - )) === 0, + !joinState.hasFormFields, ); ok( "join keeps ?path in the URL", new URL(pg.url()).searchParams.get("path") === "program-track", ); -// THE DOMAIN RULE IS ON THE PAGE, not just in the rules. It is the whole membership test -// and the one sentence a reader cannot afford to skim past, so a copy pass that removed it -// would leave people signing in with a personal Gmail and being refused with no warning. -ok( - "and states the one address that can register", - (await pg.evaluate(() => - /sst\.scaler\.com/i.test(document.querySelector("main")?.innerText ?? ""), - )), -); +// The domain rule is important in both states: a configured gate explains the membership +// requirement, while the unconfigured state explains what will be required once auth is +// available. +ok("and states the one address that can register", joinState.statesDomain); + // The form must NOT be reachable without signing in. This is a UI assertion, not a // security one — the boundary is firestore.rules — but a form rendering to a signed-out // visitor would mean the gate had broken open.