From 6c6bdea57f72797b340db6d2d1f66104e43e07b7 Mon Sep 17 00:00:00 2001 From: Adam Setch Date: Sat, 18 May 2024 16:19:31 -0400 Subject: [PATCH] refactor(auth): extract validation logic --- src/routes/LoginEnterprise.tsx | 19 +++++++------- src/routes/LoginWithToken.tsx | 10 +++---- src/utils/auth.test.ts | 48 ++++++++++++++++++++++++++++++++++ src/utils/auth.ts | 14 ++++++++++ 4 files changed, 74 insertions(+), 17 deletions(-) diff --git a/src/routes/LoginEnterprise.tsx b/src/routes/LoginEnterprise.tsx index a91c7e0ec..2067d6ec8 100644 --- a/src/routes/LoginEnterprise.tsx +++ b/src/routes/LoginEnterprise.tsx @@ -15,7 +15,12 @@ import { Button } from '../components/fields/Button'; import { FieldInput } from '../components/fields/FieldInput'; import { AppContext } from '../context/App'; import type { AuthOptions } from '../types'; -import { getNewOAuthAppURL } from '../utils/auth'; +import { + getNewOAuthAppURL, + isValidClientId, + isValidHostname, + isValidToken, +} from '../utils/auth'; import Constants from '../utils/constants'; interface IValues { @@ -34,25 +39,19 @@ export const validate = (values: IValues): IFormErrors => { const errors: IFormErrors = {}; if (!values.hostname) { errors.hostname = 'Required'; - } else if ( - !/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/i.test( - values.hostname, - ) - ) { + } else if (!isValidHostname(values.hostname)) { errors.hostname = 'Invalid hostname.'; } if (!values.clientId) { - // 20 errors.clientId = 'Required'; - } else if (!/^[A-Z0-9]{20}$/i.test(values.clientId)) { + } else if (!isValidClientId(values.clientId)) { errors.clientId = 'Invalid client id.'; } if (!values.clientSecret) { - // 40 errors.clientSecret = 'Required'; - } else if (!/^[A-Z0-9]{40}$/i.test(values.clientSecret)) { + } else if (!isValidToken(values.clientSecret)) { errors.clientSecret = 'Invalid client secret.'; } diff --git a/src/routes/LoginWithToken.tsx b/src/routes/LoginWithToken.tsx index 919706d54..60b0930a7 100644 --- a/src/routes/LoginWithToken.tsx +++ b/src/routes/LoginWithToken.tsx @@ -15,7 +15,7 @@ import type { AuthTokenOptions } from '../types'; import { Constants } from '../utils/constants'; import { Button } from '../components/fields/Button'; -import { getNewTokenURL } from '../utils/auth'; +import { getNewTokenURL, isValidHostname, isValidToken } from '../utils/auth'; interface IValues { token?: string; @@ -31,17 +31,13 @@ export const validate = (values: IValues): IFormErrors => { const errors: IFormErrors = {}; if (!values.token) { errors.token = 'Required'; - } else if (!/^[A-Z0-9_]{40}$/i.test(values.token)) { + } else if (!isValidToken(values.token)) { errors.token = 'Invalid token.'; } if (!values.hostname) { errors.hostname = 'Required'; - } else if ( - !/^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/i.test( - values.hostname, - ) - ) { + } else if (!isValidHostname(values.hostname)) { errors.hostname = 'Invalid hostname.'; } diff --git a/src/utils/auth.test.ts b/src/utils/auth.test.ts index e92ac835c..d2e904a74 100644 --- a/src/utils/auth.test.ts +++ b/src/utils/auth.test.ts @@ -167,4 +167,52 @@ describe('utils/auth.tsx', () => { ).toBeTruthy(); }); }); + + describe('isValidHostname', () => { + it('should validate hostname - github cloud', () => { + expect(auth.isValidHostname('github.com')).toBeTruthy(); + }); + + it('should validate hostname - github enterprise server', () => { + expect(auth.isValidHostname('github.gitify.io')).toBeTruthy(); + }); + + it('should invalidate hostname - empty', () => { + expect(auth.isValidHostname('')).toBeFalsy(); + }); + + it('should invalidate hostname - invalid', () => { + expect(auth.isValidHostname('github')).toBeFalsy(); + }); + }); + + describe('isValidClientId', () => { + it('should validate client id - valid', () => { + expect(auth.isValidClientId('1234567890_ASDFGHJKL')).toBeTruthy(); + }); + + it('should validate client id - empty', () => { + expect(auth.isValidClientId('')).toBeFalsy(); + }); + + it('should validate client id - invalid', () => { + expect(auth.isValidClientId('1234567890asdfg')).toBeFalsy(); + }); + }); + + describe('isValidToken', () => { + it('should validate token - valid', () => { + expect( + auth.isValidToken('1234567890_asdfghjklPOIUYTREWQ0987654321'), + ).toBeTruthy(); + }); + + it('should validate token - empty', () => { + expect(auth.isValidToken('')).toBeFalsy(); + }); + + it('should validate token - invalid', () => { + expect(auth.isValidToken('1234567890asdfg')).toBeFalsy(); + }); + }); }); diff --git a/src/utils/auth.ts b/src/utils/auth.ts index fba2e2c01..62a052bac 100644 --- a/src/utils/auth.ts +++ b/src/utils/auth.ts @@ -167,3 +167,17 @@ export function getNewOAuthAppURL(hostname: string): string { return newOAuthAppURL.toString(); } + +export function isValidHostname(hostname: string) { + return /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$/i.test( + hostname, + ); +} + +export function isValidClientId(clientId: string) { + return /^[A-Z0-9_]{20}$/i.test(clientId); +} + +export function isValidToken(token: string) { + return /^[A-Z0-9_]{40}$/i.test(token); +}