feat: validate names when *changing* them, too

This commit is contained in:
Sam 2023-03-28 10:25:54 +02:00
parent c60429d884
commit 7d25d12722
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
5 changed files with 30 additions and 6 deletions

View file

@ -0,0 +1,2 @@
export const memberNameRegex = /^[^@\\?!#/\\\\[\]"'$%&()+<=>^|~`,]{1,100}$/;
export const usernameRegex = /^[\w-.]{2,40}$/;

View file

@ -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 = "";

View file

@ -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);

View file

@ -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">

View file

@ -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}