diff --git a/studio/components/interfaces/Auth/Auth.constants.ts b/studio/components/interfaces/Auth/Auth.constants.ts index d7bb480d4ee..9a19233214a 100644 --- a/studio/components/interfaces/Auth/Auth.constants.ts +++ b/studio/components/interfaces/Auth/Auth.constants.ts @@ -1,8 +1,3 @@ -// [Joshen] Currently using the latter regex as the former is too strict, doesn't support -// localhost - if we can combine these 2 together that'll be great but my regex-foo isn't too strong - -// [MildTomato] Combined everything into domainRegex for now - // Regex from: https://stackoverflow.com/a/68002755/4807782 // modified to accept numbers in the body of domain though // examples of matches: @@ -10,12 +5,10 @@ // "www.vercel.com" // "uptime-monitor-fe.vercel.app" // "https://uptime-monitor-fe.vercel.app/" -const baseDomainRegex = - /^((ftp|http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+((\/)[\w#]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)?$/gm -// [Joshen] This regex allows for localhost as well, less strict -// [MildTomato] no longer used -const webRegex = /^(ftp|http|https):\/\/\w+(\.\w+)*(:[0-9]+)?\/?(\/[.\w]*)*$/i +// Supports wildcards, port numbers at the end, paths at the end and query params +const baseDomainRegex = + /^((ftp|http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_*-]+(\.[a-zA-Z0-9_*-]+)+((\/)[\w#]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)+(?:\.[a-z]+)*(?::\d+)?(?![^<]*(?:<\/\w+>|\/?>))(.*)?\/?(.)*?$/gm // iOS deep linking scheme https://benoitpasquier.com/deep-linking-url-scheme-ios/ const appRegex = /^[a-z0-9]+([.][a-z0-9]+)*:\/(\/[-a-z0-9._~!$&'()*+,;=:@%]+)+$/i diff --git a/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx b/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx index 54ce00e6280..34fe4a975ed 100644 --- a/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx +++ b/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx @@ -1,9 +1,8 @@ +import { Alert, Form, Input, Toggle } from '@supabase/ui' +import { observer } from 'mobx-react-lite' import { useEffect, useState } from 'react' import { number, object, string } from 'yup' -import { observer } from 'mobx-react-lite' -import { Form, Input, Toggle, Alert } from '@supabase/ui' -import { useStore } from 'hooks' import { FormActions, FormHeader, @@ -12,9 +11,10 @@ import { FormSectionContent, FormSectionLabel, } from 'components/ui/Forms' -import { defaultDisabledSmtpFormValues } from './SmtpForm.constants' +import { useStore } from 'hooks' import { domainRegex } from './../Auth.constants' -import { isSmtpEnabled, generateFormValues } from './SmtpForm.utils' +import { defaultDisabledSmtpFormValues } from './SmtpForm.constants' +import { generateFormValues, isSmtpEnabled } from './SmtpForm.utils' const SmtpForm = () => { const { authConfig, ui } = useStore() diff --git a/studio/tests/components/Auth/Auth.constants.test.js b/studio/tests/components/Auth/Auth.constants.test.js new file mode 100644 index 00000000000..e10824d0d1e --- /dev/null +++ b/studio/tests/components/Auth/Auth.constants.test.js @@ -0,0 +1,66 @@ +import { domainRegex } from 'components/interfaces/Auth/Auth.constants' + +describe('Auth.constants: domainRegex', () => { + test('should validate typical URLs', () => { + const mockInput1 = 'http://domain.com' + const output1 = domainRegex.test(mockInput1) + expect(output1).toBe(true) + + const mockInput2 = 'https://supabase.io' + const output2 = domainRegex.test(mockInput2) + expect(output2).toBe(true) + + const mockInput3 = 'https://new-domain-vercel.com' + const output3 = domainRegex.test(mockInput3) + expect(output3).toBe(true) + + const mockInput4 = 'www.test-domain.com' + const output4 = domainRegex.test(mockInput4) + expect(output4).toBe(true) + }) + test('should validate subdomains', () => { + const mockInput1 = 'https://app.supabase.com' + const output1 = domainRegex.test(mockInput1) + expect(output1).toBe(true) + }) + test('should validate localhost URLs', () => { + const mockInput1 = 'http://localhost:3000' + const output1 = domainRegex.test(mockInput1) + expect(output1).toBe(true) + }) + test('should validate URLs with query params', () => { + const mockInput1 = 'https://supabase.com?name=test' + const output1 = domainRegex.test(mockInput1) + expect(output1).toBe(true) + + const mockInput2 = 'https://supabase.com?name=test&description=hello&page=2' + const output2 = domainRegex.test(mockInput2) + expect(output2).toBe(true) + }) + test('should validate URLs with wildcards', () => { + const mockInput1 = 'https://supabase*.com' + const output1 = domainRegex.test(mockInput1) + expect(output1).toBe(true) + + const mockInput2 = 'https://supabase.com/*' + const output2 = domainRegex.test(mockInput2) + expect(output2).toBe(true) + }) + test('should invalidate invalid URLs', () => { + const mockInput1 = 'supabase' + const output1 = domainRegex.test(mockInput1) + expect(output1).toBe(false) + + const mockInput2 = 'mailto:test@gmail.com' + const output2 = domainRegex.test(mockInput2) + expect(output2).toBe(false) + + const mockInput4 = 'hello world.com' + const output4 = domainRegex.test(mockInput4) + expect(output4).toBe(false) + + const mockInput5 = 'email@domain.com' + const output5 = domainRegex.test(mockInput5) + expect(output5).toBe(false) + }) +})