-
Notifications
You must be signed in to change notification settings - Fork 522
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
FEAT: Add IPFS / Pinata avatar upload (#971)
* Add IPFS / Pinata avatar upload * fix build: deprecated config
- Loading branch information
Showing
9 changed files
with
121 additions
and
80 deletions.
There are no files selected for viewing
62 changes: 62 additions & 0 deletions
62
apps/web/app/(basenames)/api/basenames/avatar/ipfsUpload/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { pinata } from 'apps/web/src/utils/pinata'; | ||
import { NextResponse, NextRequest } from 'next/server'; | ||
|
||
export const ALLOWED_IMAGE_TYPE = [ | ||
'image/svg+xml', | ||
'image/png', | ||
'image/jpeg', | ||
'image/webp', | ||
'image/gif', | ||
]; | ||
|
||
export const MAX_IMAGE_SIZE_IN_MB = 1; // max 1mb | ||
|
||
export async function POST(request: NextRequest) { | ||
try { | ||
// Rerrer validation | ||
const requestUrl = new URL(request.url); | ||
|
||
// Username must be provided | ||
const username = requestUrl.searchParams.get('username'); | ||
if (!username) return NextResponse.json({ error: 'Invalid request' }, { status: 500 }); | ||
|
||
// Must have a referer | ||
const referer = request.headers.get('referer'); | ||
if (!referer) return NextResponse.json({ error: 'Invalid request' }, { status: 500 }); | ||
|
||
// referer can only be us | ||
// TODO: Won't work on vercel previews | ||
const refererUrl = new URL(referer); | ||
const allowedReferersHosts = ['localhost:3000', 'base.org']; | ||
if (!allowedReferersHosts.includes(refererUrl.host)) { | ||
return NextResponse.json({ error: 'Invalid request' }, { status: 500 }); | ||
} | ||
|
||
const data = await request.formData(); | ||
const file: File | null = data.get('file') as unknown as File; | ||
|
||
// Validation: file is present in request | ||
if (!file) return NextResponse.json({ error: 'No file uploaded' }, { status: 500 }); | ||
|
||
// Validation: file is an image | ||
if (!ALLOWED_IMAGE_TYPE.includes(file.type)) | ||
return NextResponse.json({ error: 'Invalid file type' }, { status: 500 }); | ||
|
||
// Validation: file is less than 1mb | ||
const bytes = file.size; | ||
const bytesToMegaBytes = bytes / (1024 * 1024); | ||
if (bytesToMegaBytes > MAX_IMAGE_SIZE_IN_MB) | ||
return NextResponse.json({ error: 'File is too large' }, { status: 500 }); | ||
|
||
// Upload | ||
const uploadData = await pinata.upload.file(file, { | ||
groupId: '765ab5e4-0bc3-47bb-9d6a-35b308291009', | ||
metadata: { | ||
name: username, | ||
}, | ||
}); | ||
return NextResponse.json(uploadData, { status: 200 }); | ||
} catch (e) { | ||
return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -114,6 +114,7 @@ const contentSecurityPolicy = { | |
'https://translate.googleapis.com', // Let user translate our website | ||
'https://sdk-api.neynar.com/', // Neymar API | ||
'https://unpkg.com/@lottiefiles/[email protected]/dist/dotlottie-player.wasm', // lottie player | ||
`https://${process.env.NEXT_PUBLIC_PINATA_GATEWAY_URL}`, | ||
], | ||
'frame-ancestors': ["'self'", baseXYZDomains], | ||
'form-action': ["'self'", baseXYZDomains], | ||
|
@@ -127,6 +128,7 @@ const contentSecurityPolicy = { | |
'https://ipfs.io', // ipfs ens avatar resolution | ||
'https://cloudflare-ipfs.com', // ipfs Cloudfare ens avatar resolution | ||
'https://zku9gdedgba48lmr.public.blob.vercel-storage.com', // basename avatar upload to vercel blob | ||
`https://${process.env.NEXT_PUBLIC_PINATA_GATEWAY_URL}`, | ||
], | ||
}; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { PinataSDK } from 'pinata'; | ||
|
||
export const pinata = new PinataSDK({ | ||
pinataJwt: `${process.env.PINATA_API_KEY}`, | ||
pinataGateway: `${process.env.NEXT_PUBLIC_PINATA_GATEWAY_URL}`, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters