feat: validate names when *changing* them, too
This commit is contained in:
parent
c60429d884
commit
7d25d12722
|
@ -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 renderMarkdown from "$lib/api/markdown";
|
||||||
import ReportButton from "./ReportButton.svelte";
|
import ReportButton from "./ReportButton.svelte";
|
||||||
import ProfileLink from "./ProfileLink.svelte";
|
import ProfileLink from "./ProfileLink.svelte";
|
||||||
|
import { memberNameRegex } from "$lib/api/regex";
|
||||||
|
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
||||||
|
@ -58,7 +59,6 @@
|
||||||
memberPage = memberPage + 1;
|
memberPage = memberPage + 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const memberNameRegex = /^[^@\\?!#\/\\\\[\]\"'$%&()+<=>^|~`,]{1,100}$/;
|
|
||||||
let modalOpen = false;
|
let modalOpen = false;
|
||||||
let toggleModal = () => (modalOpen = !modalOpen);
|
let toggleModal = () => (modalOpen = !modalOpen);
|
||||||
let newMemberName = "";
|
let newMemberName = "";
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from "$app/navigation";
|
||||||
import type { APIError, MeUser } from "$lib/api/entities";
|
import type { APIError, MeUser } from "$lib/api/entities";
|
||||||
import { apiFetch } from "$lib/api/fetch";
|
import { apiFetch } from "$lib/api/fetch";
|
||||||
|
import { usernameRegex } from "$lib/api/regex";
|
||||||
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
||||||
import { userStore } from "$lib/store";
|
import { userStore } from "$lib/store";
|
||||||
import { addToast } from "$lib/toast";
|
import { addToast } from "$lib/toast";
|
||||||
|
@ -43,7 +44,6 @@
|
||||||
let deleteCancelled: boolean;
|
let deleteCancelled: boolean;
|
||||||
let deleteError: APIError | null;
|
let deleteError: APIError | null;
|
||||||
|
|
||||||
const usernameRegex = /^[\w-.]{2,40}$/;
|
|
||||||
let username: string;
|
let username: string;
|
||||||
let usernameValid = true;
|
let usernameValid = true;
|
||||||
$: usernameValid = usernameRegex.test(username);
|
$: usernameValid = usernameRegex.test(username);
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
||||||
import type { PageData } from "./$types";
|
import type { PageData } from "./$types";
|
||||||
import { addToast, delToast } from "$lib/toast";
|
import { addToast, delToast } from "$lib/toast";
|
||||||
|
import { memberNameRegex } from "$lib/api/regex";
|
||||||
|
|
||||||
const MAX_AVATAR_BYTES = 1_000_000;
|
const MAX_AVATAR_BYTES = 1_000_000;
|
||||||
|
|
||||||
|
@ -51,6 +52,9 @@
|
||||||
let pronouns: Pronoun[] = window.structuredClone(data.member.pronouns);
|
let pronouns: Pronoun[] = window.structuredClone(data.member.pronouns);
|
||||||
let fields: Field[] = window.structuredClone(data.member.fields);
|
let fields: Field[] = window.structuredClone(data.member.fields);
|
||||||
|
|
||||||
|
let memberNameValid = true;
|
||||||
|
$: memberNameValid = memberNameRegex.test(name);
|
||||||
|
|
||||||
let avatar: string | null;
|
let avatar: string | null;
|
||||||
let avatar_files: FileList | null;
|
let avatar_files: FileList | null;
|
||||||
|
|
||||||
|
@ -277,7 +281,9 @@
|
||||||
tooltip="Back to member"
|
tooltip="Back to member"
|
||||||
/>
|
/>
|
||||||
{#if modified}
|
{#if modified}
|
||||||
<Button color="success" on:click={() => updateMember()}>Save changes</Button>
|
<Button color="success" on:click={() => updateMember()} disabled={!memberNameValid}
|
||||||
|
>Save changes</Button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
<Button color="danger" on:click={toggleDeleteOpen}
|
<Button color="danger" on:click={toggleDeleteOpen}
|
||||||
>Delete {data.member.display_name ?? data.member.name}</Button
|
>Delete {data.member.display_name ?? data.member.name}</Button
|
||||||
|
@ -353,6 +359,9 @@
|
||||||
<FormGroup floating label="Name">
|
<FormGroup floating label="Name">
|
||||||
<Input bind:value={name} />
|
<Input bind:value={name} />
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
{#if !memberNameValid}
|
||||||
|
<p class="text-danger-emphasis mb-2">That member name is not valid.</p>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<FormGroup floating label="Display name">
|
<FormGroup floating label="Display name">
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import { goto } from "$app/navigation";
|
import { goto } from "$app/navigation";
|
||||||
import { type MeUser, userAvatars, type APIError, MAX_MEMBERS } from "$lib/api/entities";
|
import { type MeUser, userAvatars, type APIError, MAX_MEMBERS } from "$lib/api/entities";
|
||||||
import { apiFetchClient } from "$lib/api/fetch";
|
import { apiFetchClient } from "$lib/api/fetch";
|
||||||
|
import { usernameRegex } from "$lib/api/regex";
|
||||||
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
||||||
import FallbackImage from "$lib/components/FallbackImage.svelte";
|
import FallbackImage from "$lib/components/FallbackImage.svelte";
|
||||||
import { userStore } from "$lib/store";
|
import { userStore } from "$lib/store";
|
||||||
|
@ -12,6 +13,8 @@
|
||||||
export let data: PageData;
|
export let data: PageData;
|
||||||
|
|
||||||
let username = data.user.name;
|
let username = data.user.name;
|
||||||
|
let usernameValid = true;
|
||||||
|
$: usernameValid = usernameRegex.test(username);
|
||||||
let error: APIError | null = null;
|
let error: APIError | null = null;
|
||||||
|
|
||||||
let deleteOpen = false;
|
let deleteOpen = false;
|
||||||
|
@ -60,13 +63,23 @@
|
||||||
<Button
|
<Button
|
||||||
color="secondary"
|
color="secondary"
|
||||||
on:click={() => changeUsername()}
|
on:click={() => changeUsername()}
|
||||||
disabled={username === data.user.name}>Change username</Button
|
disabled={username === data.user.name || !usernameValid}>Change username</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
{#if username !== data.user.name}
|
{#if username !== data.user.name}
|
||||||
<p class="text-muted">
|
<p class="text-muted">
|
||||||
<Icon name="info-circle-fill" /> Changing your username will make any existing links to your
|
<Icon name="info-circle-fill" aria-hidden /> Changing your username will make any existing
|
||||||
or your members' profiles invalid.
|
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>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
{#if error}
|
{#if error}
|
||||||
|
|
Loading…
Reference in New Issue