Prevent usernmaes ilike existing ones (case-insensitive)

This commit is contained in:
MartinBraquet
2026-02-15 16:57:46 +01:00
parent e28263ff1f
commit c46fc2a5bd
3 changed files with 39 additions and 33 deletions

View File

@@ -41,7 +41,7 @@ export const getUserByUsername = async (
const res = await pg.oneOrNone(
`select *
from users
where username = $1`,
where username ilike $1`,
username
)

View File

@@ -49,7 +49,7 @@ export const RequiredProfileUserForm = (props: {
profileCreatedAlready?: boolean
}) => {
const {user, onSubmit, profileCreatedAlready, setProfile, profile, isSubmitting} = props
const {updateUsername, updateDisplayName, userInfo, updateUserState} = useEditableUserInfo(user)
const {updateDisplayName, userInfo, updateUserState, updateUsername} = useEditableUserInfo(user)
const [step, setStep] = useState<number>(0)
const t = useT()
@@ -100,7 +100,7 @@ export const RequiredProfileUserForm = (props: {
<div className="text-ink-500 mb-6 text-lg">
{t('profile.basics.subtitle', 'Write your own bio, your own way.')}
</div>}
<Col className={'gap-8 pb-[env(safe-area-inset-bottom)]'}>
<Col className={'gap-8 pb-[env(safe-area-inset-bottom)] w-fit'}>
{step === 0 && <Col>
<label className={clsx(labelClassName)}>
{t('profile.basics.display_name', 'Display name')}
@@ -128,14 +128,13 @@ export const RequiredProfileUserForm = (props: {
</label>
<Row className={'items-center gap-2'}>
<Input
disabled={loadingUsername}
// disabled={loadingUsername}
type="text"
placeholder="Username"
value={username}
onChange={(e) => {
updateUserState({username: e.target.value || ''})
updateUserState({username: e.target.value || '', errorUsername: ''})
}}
onBlur={updateUsername}
/>
{loadingUsername && <LoadingIndicator className={'ml-2'}/>}
</Row>
@@ -163,13 +162,19 @@ export const RequiredProfileUserForm = (props: {
{onSubmit && (
<Row className={'justify-end'}>
<Button
disabled={!canContinue || isSubmitting}
disabled={!canContinue || isSubmitting || loadingUsername}
loading={isSubmitting}
onClick={() => {
if (step === 1) {
onSubmit()
} else {
setStep(1)
onClick={async () => {
let success = true
if (step === 0) {
success = await updateUsername()
}
if (success) {
if (step === 1) {
onSubmit()
} else {
setStep(1)
}
}
}}
>

View File

@@ -1,8 +1,8 @@
import { useState } from 'react'
import { cleanDisplayName, cleanUsername } from 'common/util/clean-username'
import { APIError } from 'common/api/utils'
import { User } from 'common/user'
import { updateUser } from 'web/lib/api'
import {useState} from 'react'
import {cleanDisplayName, cleanUsername} from 'common/util/clean-username'
import {APIError} from 'common/api/utils'
import {User} from 'common/user'
import {updateUser} from 'web/lib/api'
type UserInfoState = {
name: string
@@ -24,19 +24,19 @@ export const useEditableUserInfo = (user: User) => {
})
const updateUserState = (newState: Partial<UserInfoState>) => {
setUserInfo((prevState) => ({ ...prevState, ...newState }))
setUserInfo((prevState) => ({...prevState, ...newState}))
}
const updateDisplayName = async () => {
const newName = cleanDisplayName(userInfo.name)
if (newName === user.name) return
updateUserState({ loadingName: true, errorName: '' })
if (!newName) return updateUserState({ name: user.name })
updateUserState({loadingName: true, errorName: ''})
if (!newName) return updateUserState({name: user.name})
try {
await updateUser({ name: newName })
updateUserState({ errorName: '', name: newName })
await updateUser({name: newName})
updateUserState({errorName: '', name: newName})
} catch (reason) {
updateUserState({
errorName: (reason as APIError).message,
@@ -44,33 +44,34 @@ export const useEditableUserInfo = (user: User) => {
})
}
updateUserState({ loadingName: false })
updateUserState({loadingName: false})
}
const updateUsername = async () => {
const newUsername = cleanUsername(userInfo.username)
if (newUsername === user.username) return
// console.log({newUsername})
if (newUsername === user.username) return true
updateUserState({ loadingUsername: true, errorUsername: '' })
updateUserState({loadingUsername: true, errorUsername: ''})
let success = true
try {
await updateUser({ username: newUsername })
updateUserState({ errorUsername: '', username: newUsername })
await updateUser({username: newUsername})
updateUserState({errorUsername: ''})
user.username = newUsername
} catch (reason) {
updateUserState({
errorUsername: (reason as APIError).message,
username: user.username,
})
updateUserState({errorUsername: (reason as APIError).message})
success = false
}
updateUserState({ loadingUsername: false })
updateUserState({loadingUsername: false})
return success
}
return {
userInfo,
updateDisplayName,
updateUsername,
updateUserState,
updateUsername,
}
}