Skip to content

Commit

Permalink
Merge pull request #201 from hackclub/save-dev-pr-0
Browse files Browse the repository at this point in the history
Add API routes
  • Loading branch information
leomcelroy authored Dec 8, 2023
2 parents 94a5811 + c12feaa commit cd61398
Show file tree
Hide file tree
Showing 10 changed files with 647 additions and 2 deletions.
6 changes: 4 additions & 2 deletions astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@astrojs/preact": "^3.0.0",
"@astrojs/tailwind": "^5.0.2",
"@astrojs/ts-plugin": "^1.1.3",
"@astrojs/vercel": "^3.6.0",
"@astrojs/vercel": "^5.2.0",
"@codemirror/commands": "^6.2.4",
"@codemirror/lang-javascript": "^6.1.9",
"@codemirror/language": "^6.8.0",
Expand All @@ -27,15 +27,17 @@
"@lezer/common": "^1.0.3",
"@replit/codemirror-vim": "^6.0.14",
"@rollup/browser": "^3.26.0",
"@sendgrid/mail": "^7.7.0",
"acorn": "^8.11.2",
"astro": "^3.1.1",
"classnames": "^2.3.2",
"cm6-theme-basic-dark": "^0.2.0",
"codemirror": "^6.0.1",
"firebase": "^10.3.1",
"firebase-admin": "^11.10.1",
"firebase-admin": "^11.11.1",
"js-beautify": "^1.14.9",
"marked": "^7.0.4",
"nanoid": "^5.0.3",
"preact": "^10.6.5",
"source-map-js": "^1.0.2",
"tailwindcss": "^3.0.24",
Expand Down
62 changes: 62 additions & 0 deletions astro/src/lib/utils/recaptcha.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
export const recaptchaKeyId = ''

export const executeCaptcha = (action: string): Promise<string> =>
new Promise((resolve, reject) => {
grecaptcha.enterprise.ready(() => {
grecaptcha.enterprise
.execute(recaptchaKeyId, { action })
.then(resolve, reject)
})
})

interface CaptchaAssessment {
tokenProperties: {
valid: boolean
hostname: string
action: string
createTime: string
}
riskAnalysis: {
score: number
reasons: string[]
}
event: {
token: string
siteKey: string
expectedAction: string
}
name: string
}

export const assessCaptcha = async (
token: string,
expectedAction: string
): Promise<number> => {
const res = await fetch(
`https://recaptchaenterprise.googleapis.com/v1/projects/blot-db/assessments?key=${
import.meta.env.RECAPTCHA_API_KEY
}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
event: {
token,
siteKey: recaptchaKeyId,
expectedAction
}
})
}
)
if (!res.ok) throw new Error(`Failed to get captcha score (${res.status})`)

const assessment: CaptchaAssessment = await res.json()
if (!assessment.tokenProperties.valid)
throw new Error('Invalid captcha token')
if (assessment.event.expectedAction != expectedAction)
throw new Error('Invalid captcha action')
if (assessment.event.siteKey !== recaptchaKeyId)
throw new Error('Invalid captcha key')

return assessment.riskAnalysis.score
}
267 changes: 267 additions & 0 deletions astro/src/lib/utils/words.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
export const adjectives = [
'attractive',
'bald',
'beautiful',
'chubby',
'clean',
'dazzling',
'drab',
'elegant',
'fancy',
'fit',
'flabby',
'glamorous',
'gorgeous',
'handsome',
'long',
'magnificent',
'muscular',
'plain',
'plump',
'quaint',
'scruffy',
'shapely',
'short',
'skinny',
'stocky',
'ugly',
'unkempt',
'unsightly',
'ashy',
'careful',
'clever',
'famous',
'gifted',
'hallowed',
'helpful',
'important',
'inexpensive',
'mushy',
'powerful',
'rich',
'shy',
'tender',
'unimportant',
'uninterested',
'aggressive',
'agreeable',
'ambitious',
'brave',
'calm',
'delightful',
'eager',
'faithful',
'gentle',
'happy',
'jolly',
'kind',
'lively',
'nice',
'obedient',
'polite',
'proud',
'silly',
'thankful',
'victorious',
'witty',
'wonderful',
'zealous',
'chubby',
'crooked',
'skinny',
'colossal',
'microscopic',
'miniature',
'petite',
'scrawny',
'substantial',
'chilly',
'cool',
'breezy',
'bumpy',
'acidic',
'acrid',
'salty',
'greasy',
'crashing',
'deafening',
'echoing',
'hissing',
'howling',
'melodic',
'noisy',
'purring',
'quiet',
'raspy',
'rhythmic',
'screeching',
'squeaking',
'thundering',
'wailing',
'whining',
'whispering',
'tiny'
]
export const nouns = [
'bulbasaur',
'ivysaur',
'venusaur',
'charmander',
'charmeleon',
'charizard',
'squirtle',
'wartortle',
'blastoise',
'caterpie',
'metapod',
'butterfree',
'weedle',
'kakuna',
'beedrill',
'pidgey',
'pidgeotto',
'pidgeot',
'rattata',
'raticate',
'spearow',
'fearow',
'ekans',
'arbok',
'pikachu',
'raichu',
'sandshrew',
'sandslash',
'nidoran',
'nidorina',
'nidoqueen',
'nidoran',
'nidorino',
'nidoking',
'clefairy',
'clefable',
'vulpix',
'ninetales',
'jigglypuff',
'wigglytuff',
'zubat',
'golbat',
'oddish',
'gloom',
'vileplume',
'paras',
'parasect',
'venonat',
'venomoth',
'diglett',
'dugtrio',
'meowth',
'persian',
'psyduck',
'golduck',
'mankey',
'primeape',
'growlithe',
'arcanine',
'poliwag',
'poliwhirl',
'poliwrath',
'abra',
'kadabra',
'alakazam',
'machop',
'machoke',
'machamp',
'bellsprout',
'weepinbell',
'victreebel',
'tentacool',
'tentacruel',
'geodude',
'graveler',
'golem',
'ponyta',
'rapidash',
'slowpoke',
'slowbro',
'magnemite',
'magneton',
'doduo',
'dodrio',
'seel',
'dewgong',
'grimer',
'muk',
'shellder',
'cloyster',
'gastly',
'haunter',
'gengar',
'onix',
'drowzee',
'hypno',
'krabby',
'kingler',
'voltorb',
'electrode',
'exeggcute',
'exeggutor',
'cubone',
'marowak',
'hitmonlee',
'hitmonchan',
'lickitung',
'koffing',
'weezing',
'rhyhorn',
'rhydon',
'chansey',
'tangela',
'kangaskhan',
'horsea',
'seadra',
'goldeen',
'seaking',
'staryu',
'starmie',
'mime',
'scyther',
'jynx',
'electabuzz',
'magmar',
'pinsir',
'tauros',
'magikarp',
'gyarados',
'lapras',
'ditto',
'eevee',
'vaporeon',
'jolteon',
'flareon',
'porygon',
'omanyte',
'omastar',
'kabuto',
'kabutops',
'aerodactyl',
'snorlax',
'articuno',
'zapdos',
'moltres',
'dratini',
'dragonair',
'dragonite',
'mewtwo',
'mew',
'missingno'
]

export const generateName = () =>
adjectives[Math.floor(Math.random() * adjectives.length)] +
'_' +
nouns[Math.floor(Math.random() * nouns.length)]
export const isRandomName = (name: string): boolean => {
const split = name.split('_')
if (split.length !== 2) return false
return adjectives.includes(split[0]!) && nouns.includes(split[1]!)
}
29 changes: 29 additions & 0 deletions astro/src/pages/api/art/delete.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { APIRoute } from 'astro'
import { firestore, getArt, getSession } from '../../../db/account.ts'

export const POST: APIRoute = async ({ request, cookies }) => {
let artId: string
try {
const body = await request.json()
if (typeof body.artId !== 'string') throw 'Missing/invalid art id'
artId = body.artId
} catch (error) {
return new Response(
typeof error === 'string' ? error : 'Bad request body',
{ status: 400 }
)
}

const art = await getArt(artId)
if (!art) return new Response('Piece of art does not exist', { status: 404 })

const session = await getSession(cookies)
if (!session) return new Response('Unauthorized', { status: 401 })
if (session.user.id !== art.ownerId)
return new Response("Can't delete a piece of art you don't own", {
status: 403
})

await firestore.collection('art').doc(artId).delete()
return new Response(JSON.stringify({}), { status: 200 })
}
Loading

1 comment on commit cd61398

@vercel
Copy link

@vercel vercel bot commented on cd61398 Dec 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

blot – ./astro

blot-git-main.hackclub.dev
blot.hackclub.dev

Please sign in to comment.