feat: validate names when *changing* them, too
This commit is contained in:
parent
c60429d884
commit
7d25d12722
5 changed files with 30 additions and 6 deletions
2
frontend/src/lib/api/regex.ts
Normal file
2
frontend/src/lib/api/regex.ts
Normal file
|
@ -0,0 +1,2 @@
|
|||
export const memberNameRegex = /^[^@\\?!#/\\\\[\]"'$%&()+<=>^|~`,]{1,100}$/;
|
||||
export const usernameRegex = /^[\w-.]{2,40}$/;
|
|
@ -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 = "";
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}
|
||||
<Button color="success" on:click={() => updateMember()}>Save changes</Button>
|
||||
<Button color="success" on:click={() => updateMember()} disabled={!memberNameValid}
|
||||
>Save changes</Button
|
||||
>
|
||||
{/if}
|
||||
<Button color="danger" on:click={toggleDeleteOpen}
|
||||
>Delete {data.member.display_name ?? data.member.name}</Button
|
||||
|
@ -353,6 +359,9 @@
|
|||
<FormGroup floating label="Name">
|
||||
<Input bind:value={name} />
|
||||
</FormGroup>
|
||||
{#if !memberNameValid}
|
||||
<p class="text-danger-emphasis mb-2">That member name is not valid.</p>
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
<FormGroup floating label="Display name">
|
||||
|
|
|
@ -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 @@
|
|||
<Button
|
||||
color="secondary"
|
||||
on:click={() => changeUsername()}
|
||||
disabled={username === data.user.name}>Change username</Button
|
||||
disabled={username === data.user.name || !usernameValid}>Change username</Button
|
||||
>
|
||||
</div>
|
||||
{#if username !== data.user.name}
|
||||
<p class="text-muted">
|
||||
<Icon name="info-circle-fill" /> Changing your username will make any existing links to your
|
||||
or your members' profiles invalid.
|
||||
<Icon name="info-circle-fill" aria-hidden /> Changing your username will make any existing
|
||||
links to your or your members' profiles invalid.
|
||||
<br />
|
||||
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}
|
||||
<br />
|
||||
<span class="text-danger-emphasis"
|
||||
><Icon name="exclamation-triangle-fill" aria-hidden /> That username is not valid.</span
|
||||
>
|
||||
{/if}
|
||||
</p>
|
||||
{/if}
|
||||
{#if error}
|
||||
|
|
Loading…
Reference in a new issue