mirror of
https://github.com/System-End/site.git
synced 2026-04-19 22:05:11 +00:00
Merge pull request #1 from hackclub/airtable-based-login
Setup airtable based login fields & redirect
This commit is contained in:
commit
b64edae3e8
2 changed files with 113 additions and 0 deletions
53
pages/api/arcade/showcase/login/[token].js
Normal file
53
pages/api/arcade/showcase/login/[token].js
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import AirtablePlus from "airtable-plus"
|
||||
|
||||
const airtable = new AirtablePlus({
|
||||
apiKey: process.env.AIRTABLE_API_KEY,
|
||||
baseID: 'app4kCWulfB02bV8Q',
|
||||
tableName: "Users"
|
||||
})
|
||||
|
||||
async function getUserFromLogin(loginToken) {
|
||||
|
||||
// only alphanumeric & '-' characters are allowed in the token
|
||||
const safeLoginToken = loginToken.replace(/[^a-zA-Z0-9-]/g, '')
|
||||
|
||||
const results = await airtable.read({
|
||||
filterByFormula: `{Login Token} = '${safeLoginToken}'`,
|
||||
maxRecords: 1
|
||||
})
|
||||
|
||||
return results[0]
|
||||
}
|
||||
|
||||
async function scrubLoginToken(userID) {
|
||||
console.log(`Scrubbing login token for user ${userID}`)
|
||||
await airtable.update(userID, {
|
||||
'Login Token': ''
|
||||
})
|
||||
}
|
||||
|
||||
export default async function handler(req, res) {
|
||||
if (req.method !== 'POST') {
|
||||
return res.status(405).json({ error: "Method not allowed" })
|
||||
}
|
||||
|
||||
const { token } = req.query
|
||||
if (!token) {
|
||||
return res.status(400).json({ error: "Token is required" })
|
||||
}
|
||||
|
||||
const user = await getUserFromLogin(token)
|
||||
if (!user) {
|
||||
return res.status(404).json({ error: "User not found" })
|
||||
}
|
||||
|
||||
const authToken = user.fields['Auth Token']
|
||||
if (!authToken) {
|
||||
return res.status(500).json({ error: "Auth Token not found" })
|
||||
}
|
||||
|
||||
await scrubLoginToken(user.id)
|
||||
|
||||
// return back the user's AuthToken
|
||||
res.status(200).json({ authToken })
|
||||
}
|
||||
60
pages/arcade/showcase/login/[token].js
Normal file
60
pages/arcade/showcase/login/[token].js
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
|
||||
const sample = arr => arr[Math.floor(Math.random() * arr.length)]
|
||||
const languages = "Python Rust COBOL Wasm tailwind ".split(" ")
|
||||
const tinyEyes = [
|
||||
"if you can see this, you're too close",
|
||||
"what are you looking at, tiny-eyes?",
|
||||
"I see you",
|
||||
"What is this, a website for ants?",
|
||||
"plz help, my font size has fallen and it can't get up",
|
||||
"*small loading sounds*"
|
||||
]
|
||||
const flavorText = [
|
||||
`I would've been faster written in ${sample(languages)}`,
|
||||
'Wait your turn!',
|
||||
'Form an orderly queue!',
|
||||
"I'm a teapo– WAIT WRONG ENDPOINT",
|
||||
"GET outta here with that request!",
|
||||
"PUT that request back where it came from or so help me",
|
||||
"POST haste!",
|
||||
"TODO: Delete this message",
|
||||
<p style={{fontSize: "3px"}}>{sample(tinyEyes)}</p>,
|
||||
"Caution: objects in loading box are slower than they appear",
|
||||
"Caution: wet pixels, do not touch",
|
||||
"*Fax machine noises*",
|
||||
]
|
||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
||||
const LoginPage = ({token}) => {
|
||||
const [ status, setStatus ] = useState('Loading...')
|
||||
useEffect(async () => {
|
||||
const minWaitTime = sleep(3 * 1000)
|
||||
const response = fetch(`/api/arcade/showcase/login/${token}`, {method: 'POST'})
|
||||
const data = response.json()
|
||||
const [ _wait, _data ] = await Promise.all([minWaitTime, data])
|
||||
|
||||
if (data.error) {
|
||||
setStatus(data.error)
|
||||
} else {
|
||||
setStatus("Redirecting!")
|
||||
window.localStorage.setItem('arcade.authToken', data.authToken)
|
||||
await sleep(250)
|
||||
window.location.href = '/arcade/showcase/my'
|
||||
}
|
||||
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>{status}</p>
|
||||
<p><em>{sample(flavorText)}</em></p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default LoginPage
|
||||
|
||||
export function getServerSideProps(context) {
|
||||
const { token } = context.query
|
||||
return { props: { token } }
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue