the statusphere demo reworked into a vite/react app in a monorepo

allow PDS URLs in login

+19 -2
+18 -1
packages/appview/src/api/oauth.ts
··· 51 router.post('/oauth/initiate', async (req, res) => { 52 // Validate 53 const handle = req.body?.handle 54 - if (typeof handle !== 'string' || !isValidHandle(handle)) { 55 res.status(400).json({ error: 'Invalid handle' }) 56 return 57 } ··· 81 82 return router 83 }
··· 51 router.post('/oauth/initiate', async (req, res) => { 52 // Validate 53 const handle = req.body?.handle 54 + if ( 55 + typeof handle !== 'string' || 56 + !(isValidHandle(handle) || isValidUrl(handle)) 57 + ) { 58 res.status(400).json({ error: 'Invalid handle' }) 59 return 60 } ··· 84 85 return router 86 } 87 + 88 + function isValidUrl(url: string): boolean { 89 + try { 90 + const urlp = new URL(url) 91 + // http or https, no query params or path 92 + return ( 93 + (urlp.protocol === 'http:' || urlp.protocol === 'https:') && 94 + !urlp.search && 95 + !urlp.pathname 96 + ) 97 + } catch (error) { 98 + return false 99 + } 100 + }
+1 -1
packages/client/src/pages/LoginPage.tsx
··· 63 htmlFor="handle" 64 className="block mb-2 text-gray-700 dark:text-gray-300" 65 > 66 - Enter your Bluesky handle: 67 </label> 68 <input 69 id="handle"
··· 63 htmlFor="handle" 64 className="block mb-2 text-gray-700 dark:text-gray-300" 65 > 66 + Enter your Bluesky handle or ATProto PDS: 67 </label> 68 <input 69 id="handle"