Improved service handle validation logic (#7657)

* fix validation logic for 3p pdses

* fix bad import

* add service handle validation test
This commit is contained in:
Samuel Newman
2025-02-06 14:55:57 +00:00
committed by GitHub
parent 00c08ba525
commit 1db2668a96
5 changed files with 51 additions and 10 deletions
+42
View File
@@ -0,0 +1,42 @@
import {IsValidHandle, validateServiceHandle} from '#/lib/strings/handles'
describe('handle validation', () => {
const valid = [
['ali', 'bsky.social'],
['alice', 'bsky.social'],
['a-lice', 'bsky.social'],
['a-----lice', 'bsky.social'],
['123', 'bsky.social'],
['123456789012345678', 'bsky.social'],
['alice', 'custom-pds.com'],
['alice', 'my-custom-pds-with-long-name.social'],
['123456789012345678', 'my-custom-pds-with-long-name.social'],
]
it.each(valid)(`should be valid: %s.%s`, (handle, service) => {
const result = validateServiceHandle(handle, service)
expect(result.overall).toEqual(true)
})
const invalid = [
['al', 'bsky.social', 'frontLength'],
['-alice', 'bsky.social', 'hyphenStartOrEnd'],
['alice-', 'bsky.social', 'hyphenStartOrEnd'],
['%%%', 'bsky.social', 'handleChars'],
['1234567890123456789', 'bsky.social', 'frontLength'],
[
'1234567890123456789',
'my-custom-pds-with-long-name.social',
'frontLength',
],
['al', 'my-custom-pds-with-long-name.social', 'frontLength'],
['a'.repeat(300), 'toolong.com', 'totalLength'],
] satisfies [string, string, keyof IsValidHandle][]
it.each(invalid)(
`should be invalid: %s.%s due to %s`,
(handle, service, expectedError) => {
const result = validateServiceHandle(handle, service)
expect(result.overall).toEqual(false)
expect(result[expectedError]).toEqual(false)
},
)
})
+3 -4
View File
@@ -42,10 +42,9 @@ export interface IsValidHandle {
}
// More checks from https://github.com/bluesky-social/atproto/blob/main/packages/pds/src/handle/index.ts#L72
export function validateHandle(
export function validateServiceHandle(
str: string,
userDomain: string,
isServiceHandle?: boolean,
): IsValidHandle {
const fullHandle = createFullHandle(str, userDomain)
@@ -53,8 +52,8 @@ export function validateHandle(
handleChars:
!str || (VALIDATE_REGEX.test(fullHandle) && !str.includes('.')),
hyphenStartOrEnd: !str.startsWith('-') && !str.endsWith('-'),
frontLength: str.length >= 3,
totalLength: fullHandle.length <= (isServiceHandle ? 30 : 253),
frontLength: str.length >= 3 && str.length <= 18,
totalLength: fullHandle.length <= 253,
}
return {
@@ -17,8 +17,8 @@ import {useMutation, useQueryClient} from '@tanstack/react-query'
import {HITSLOP_10} from '#/lib/constants'
import {cleanError} from '#/lib/strings/errors'
import {createFullHandle, validateServiceHandle} from '#/lib/strings/handles'
import {sanitizeHandle} from '#/lib/strings/handles'
import {createFullHandle, validateHandle} from '#/lib/strings/handles'
import {useFetchDid, useUpdateHandleMutation} from '#/state/queries/handle'
import {RQKEY as RQKEY_PROFILE} from '#/state/queries/profile'
import {useServiceQuery} from '#/state/queries/service'
@@ -172,7 +172,7 @@ function ProvidedHandlePage({
const host = serviceInfo.availableUserDomains[0]
const validation = useMemo(
() => validateHandle(subdomain, host, true),
() => validateServiceHandle(subdomain, host),
[subdomain, host],
)
+3 -3
View File
@@ -7,7 +7,7 @@ import {logEvent} from '#/lib/statsig/statsig'
import {
createFullHandle,
maxServiceHandleLength,
validateHandle,
validateServiceHandle,
} from '#/lib/strings/handles'
import {useAgent} from '#/state/session'
import {ScreenTransition} from '#/screens/Login/ScreenTransition'
@@ -37,7 +37,7 @@ export function StepHandle() {
value: handle,
})
const newValidCheck = validateHandle(handle, state.userDomain)
const newValidCheck = validateServiceHandle(handle, state.userDomain)
if (!newValidCheck.overall) {
return
}
@@ -97,7 +97,7 @@ export function StepHandle() {
})
}, [dispatch, state.activeStep])
const validCheck = validateHandle(draftValue, state.userDomain, true)
const validCheck = validateServiceHandle(draftValue, state.userDomain)
return (
<ScreenTransition>
<View style={[a.gap_lg]}>
+1 -1
View File
@@ -3,7 +3,7 @@
"compilerOptions": {
"jsx": "react-jsx",
"module": "esnext",
"types": ["node"],
"types": ["node", "jest"],
"paths": {
"#/*": ["./src/*"],
"lib/*": ["./src/lib/*"],