diff --git a/frontend/src/lib/api/regex.ts b/frontend/src/lib/api/regex.ts new file mode 100644 index 0000000..a8f30e6 --- /dev/null +++ b/frontend/src/lib/api/regex.ts @@ -0,0 +1,2 @@ +export const memberNameRegex = /^[^@\\?!#/\\\\[\]"'$%&()+<=>^|~`,]{1,100}$/; +export const usernameRegex = /^[\w-.]{2,40}$/; diff --git a/frontend/src/routes/@[username]/+page.svelte b/frontend/src/routes/@[username]/+page.svelte index a6e24b7..0e9c5c4 100644 --- a/frontend/src/routes/@[username]/+page.svelte +++ b/frontend/src/routes/@[username]/+page.svelte @@ -33,6 +33,7 @@ import renderMarkdown from "$lib/api/markdown"; import ReportButton from "./ReportButton.svelte"; import ProfileLink from "./ProfileLink.svelte"; + import { memberNameRegex } from "$lib/api/regex"; export let data: PageData; @@ -58,7 +59,6 @@ memberPage = memberPage + 1; }; - const memberNameRegex = /^[^@\\?!#\/\\\\[\]\"'$%&()+<=>^|~`,]{1,100}$/; let modalOpen = false; let toggleModal = () => (modalOpen = !modalOpen); let newMemberName = ""; diff --git a/frontend/src/routes/auth/login/CallbackPage.svelte b/frontend/src/routes/auth/login/CallbackPage.svelte index df9b950..8ef4db3 100644 --- a/frontend/src/routes/auth/login/CallbackPage.svelte +++ b/frontend/src/routes/auth/login/CallbackPage.svelte @@ -2,6 +2,7 @@ import { goto } from "$app/navigation"; import type { APIError, MeUser } from "$lib/api/entities"; import { apiFetch } from "$lib/api/fetch"; + import { usernameRegex } from "$lib/api/regex"; import ErrorAlert from "$lib/components/ErrorAlert.svelte"; import { userStore } from "$lib/store"; import { addToast } from "$lib/toast"; @@ -43,7 +44,6 @@ let deleteCancelled: boolean; let deleteError: APIError | null; - const usernameRegex = /^[\w-.]{2,40}$/; let username: string; let usernameValid = true; $: usernameValid = usernameRegex.test(username); diff --git a/frontend/src/routes/edit/member/[id]/+page.svelte b/frontend/src/routes/edit/member/[id]/+page.svelte index e149fef..0c87316 100644 --- a/frontend/src/routes/edit/member/[id]/+page.svelte +++ b/frontend/src/routes/edit/member/[id]/+page.svelte @@ -32,6 +32,7 @@ import ErrorAlert from "$lib/components/ErrorAlert.svelte"; import type { PageData } from "./$types"; import { addToast, delToast } from "$lib/toast"; + import { memberNameRegex } from "$lib/api/regex"; const MAX_AVATAR_BYTES = 1_000_000; @@ -51,6 +52,9 @@ let pronouns: Pronoun[] = window.structuredClone(data.member.pronouns); let fields: Field[] = window.structuredClone(data.member.fields); + let memberNameValid = true; + $: memberNameValid = memberNameRegex.test(name); + let avatar: string | null; let avatar_files: FileList | null; @@ -277,7 +281,9 @@ tooltip="Back to member" /> {#if modified} - + {/if} + {#if !memberNameValid} +

That member name is not valid.

+ {/if}
diff --git a/frontend/src/routes/settings/+page.svelte b/frontend/src/routes/settings/+page.svelte index 8a1352a..d30819f 100644 --- a/frontend/src/routes/settings/+page.svelte +++ b/frontend/src/routes/settings/+page.svelte @@ -2,6 +2,7 @@ import { goto } from "$app/navigation"; import { type MeUser, userAvatars, type APIError, MAX_MEMBERS } from "$lib/api/entities"; import { apiFetchClient } from "$lib/api/fetch"; + import { usernameRegex } from "$lib/api/regex"; import ErrorAlert from "$lib/components/ErrorAlert.svelte"; import FallbackImage from "$lib/components/FallbackImage.svelte"; import { userStore } from "$lib/store"; @@ -12,6 +13,8 @@ export let data: PageData; let username = data.user.name; + let usernameValid = true; + $: usernameValid = usernameRegex.test(username); let error: APIError | null = null; let deleteOpen = false; @@ -60,13 +63,23 @@ Change username
{#if username !== data.user.name}

- Changing your username will make any existing links to your - or your members' profiles invalid. + Changing your username will make any existing + links to your or your members' profiles invalid. +
+ Your username must be unique, be at most 40 characters long, and only contain letters from + the basic English alphabet, dashes, underscores, and periods. Your username is used as part + of your profile link, you can set a separate display name. + {#if !usernameValid} +
+ That username is not valid. + {/if}

{/if} {#if error}