Skip to content
Closed
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
26 changes: 26 additions & 0 deletions components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,16 @@ export function Navbar({ invertColors = false }: { invertColors?: boolean }) {
);
})}

<a
href="https://auth.hackclub.com/login"
className="nav-link"
style={ls(false)}
onMouseEnter={hIn}
onMouseLeave={hOut}
>
{t("login")}
</a>

<ThemeToggle />

<a
Expand Down Expand Up @@ -491,6 +501,22 @@ export function Navbar({ invertColors = false }: { invertColors?: boolean }) {
>
{tc("joinCommunity")}
</a>
<a
href="https://auth.hackclub.com/login"
className="mobile-nav-item"
onClick={closeMenu}
style={{
fontFamily: F,
fontSize: 20,
color: txt,
textDecoration: "none",
textAlign: "center",
marginTop: 4,
display: "block",
}}
>
{t("login")}
</a>
<div className="mobile-nav-item" style={{ display: "flex", justifyContent: "center" }}>
<ThemeToggle />
</div>
Expand Down
2 changes: 1 addition & 1 deletion lib/send-auth.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export function getAuthUrl(email?: string) {
const url = new URL("https://slack.hackclub.com/slides/0");
const t = email?.trim();
if (t) url.searchParams.set("email", encodeURIComponent(t));
if (t) url.searchParams.set("email", t);
return url.toString();
}

Expand Down
3 changes: 2 additions & 1 deletion messages/az.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"conduct": "Davranış qaydaları",
"privacy": "Məxfilik və şərtlər",
"safety": "Təhlükəsizlik",
"donate": "İanə et"
"donate": "İanə et",
"login": "Daxil ol"
},
"Footer": {
"tagline": "Yeniyetmələrdən yeniyetmələr üçün.",
Expand Down
3 changes: 2 additions & 1 deletion messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"privacy": "Datenschutz und Nutzungsbedingungen",
"safety": "Sicherheit",
"donate": "Spenden",
"parents": "Eltern"
"parents": "Eltern",
"login": "Anmelden"
},
"Footer": {
"tagline": "Für Jugendliche, von Jugendlichen.",
Expand Down
3 changes: 2 additions & 1 deletion messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"conduct": "Code of Conduct",
"privacy": "Privacy & Terms",
"safety": "Safety",
"donate": "Donate"
"donate": "Donate",
"login": "Log in"
},
"Footer": {
"tagline": "For teens, by teens.",
Expand Down
3 changes: 2 additions & 1 deletion messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"conduct": "Código de conducta",
"privacy": "Privacidad y términos",
"safety": "Seguridad",
"donate": "Donar"
"donate": "Donar",
"login": "Iniciar sesión"
},
"Footer": {
"tagline": "Para adolescentes, por adolescentes.",
Expand Down
3 changes: 2 additions & 1 deletion messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"conduct": "Code de conduite",
"privacy": "Confidentialité et conditions",
"safety": "Sécurité",
"donate": "Faire un don"
"donate": "Faire un don",
"login": "Connexion"
},
"Footer": {
"tagline": "Par des ados, pour des ados.",
Expand Down
3 changes: 2 additions & 1 deletion messages/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"conduct": "कोड ऑफ़ कंडक्ट",
"privacy": "प्राइवेसी और शर्तें",
"safety": "सेफ़्टी",
"donate": "दान करें"
"donate": "दान करें",
"login": "लॉग इन"
},
"Footer": {
"tagline": "टीनएजर्स के लिए, टीनएजर्स द्वारा।",
Expand Down
3 changes: 2 additions & 1 deletion messages/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"conduct": "Codice di condotta",
"privacy": "Privacy e termini",
"safety": "Sicurezza",
"donate": "Dona"
"donate": "Dona",
"login": "Accedi"
},
"Footer": {
"tagline": "Per teenager, da teenager.",
Expand Down
3 changes: 2 additions & 1 deletion messages/namespaces/de/00-core.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"privacy": "Datenschutz und Nutzungsbedingungen",
"safety": "Sicherheit",
"donate": "Spenden",
"parents": "Eltern"
"parents": "Eltern",
"login": "Anmelden"
},
"Footer": {
"tagline": "Für Jugendliche, von Jugendlichen.",
Expand Down
3 changes: 2 additions & 1 deletion messages/namespaces/en/00-core.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"conduct": "Code of Conduct",
"privacy": "Privacy & Terms",
"safety": "Safety",
"donate": "Donate"
"donate": "Donate",
"login": "Log in"
},
"Footer": {
"tagline": "For teens, by teens.",
Expand Down
3 changes: 2 additions & 1 deletion messages/namespaces/hi/00-core.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"conduct": "कोड ऑफ़ कंडक्ट",
"privacy": "प्राइवेसी और शर्तें",
"safety": "सेफ़्टी",
"donate": "दान करें"
"donate": "दान करें",
"login": "लॉग इन"
},
"Footer": {
"tagline": "टीनएजर्स के लिए, टीनएजर्स द्वारा।",
Expand Down
3 changes: 2 additions & 1 deletion messages/namespaces/ru/00-core.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"conduct": "Кодекс поведения",
"privacy": "Конфиденциальность и условия",
"safety": "Безопасность",
"donate": "Поддержать"
"donate": "Поддержать",
"login": "Войти"
},
"Footer": {
"tagline": "Подростками — для подростков.",
Expand Down
3 changes: 2 additions & 1 deletion messages/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@
"conduct": "Кодекс поведения",
"privacy": "Конфиденциальность и условия",
"safety": "Безопасность",
"donate": "Поддержать"
"donate": "Поддержать",
"login": "Войти"
},
"Footer": {
"tagline": "Подростками — для подростков.",
Expand Down
46 changes: 46 additions & 0 deletions tests/send-auth.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { describe, expect, test } from "bun:test";
import { getAuthUrl } from "@/lib/send-auth";

describe("getAuthUrl parameter encoding", () => {
test("correctly encodes standard email address without double encoding", () => {
const rawEmail = "orpheus@hackclub.com";
const urlString = getAuthUrl(rawEmail);
const parsed = new URL(urlString);

expect(parsed.origin + parsed.pathname).toBe("https://slack.hackclub.com/slides/0");
expect(parsed.searchParams.get("email")).toBe("orpheus@hackclub.com");
expect(urlString).toContain("email=orpheus%40hackclub.com");
expect(urlString).not.toContain("%2540");
});

test("correctly handles plus-addressed email without double encoding", () => {
const rawEmail = "orpheus+test@hackclub.com";
const urlString = getAuthUrl(rawEmail);
const parsed = new URL(urlString);

expect(parsed.searchParams.get("email")).toBe("orpheus+test@hackclub.com");
expect(urlString).toContain("email=orpheus%2Btest%40hackclub.com");
expect(urlString).not.toContain("%252B");
expect(urlString).not.toContain("%2540");
});

test("trims leading and trailing whitespace from email", () => {
const rawEmail = " orpheus@hackclub.com ";
const urlString = getAuthUrl(rawEmail);
const parsed = new URL(urlString);

expect(parsed.searchParams.get("email")).toBe("orpheus@hackclub.com");
expect(urlString).not.toContain("%20");
expect(urlString).not.toContain("+hackclub");
});

test("omits email parameter when email is empty or missing", () => {
expect(new URL(getAuthUrl()).searchParams.has("email")).toBe(false);
expect(getAuthUrl()).toBe("https://slack.hackclub.com/slides/0");
expect(new URL(getAuthUrl("")).searchParams.has("email")).toBe(false);
expect(getAuthUrl("")).toBe("https://slack.hackclub.com/slides/0");
expect(new URL(getAuthUrl(" ")).searchParams.has("email")).toBe(false);
expect(getAuthUrl(" ")).toBe("https://slack.hackclub.com/slides/0");
});
});