-
Notifications
You must be signed in to change notification settings - Fork 315
Expand file tree
/
Copy pathroute.ts
More file actions
51 lines (46 loc) · 1.75 KB
/
Copy pathroute.ts
File metadata and controls
51 lines (46 loc) · 1.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
'use server';
import { minidenticon } from 'minidenticons';
import { NextRequest } from 'next/server';
import { apiHandler } from '@/lib/apiHandler';
import { isServiceError } from '@/lib/utils';
import { withOptionalAuth } from '@/middleware/withAuth';
// Resolves an email to an avatar image. If the email belongs to a Sourcebot
// user in the requester's org and that user has a profile image set, the
// request is redirected to that URL. Otherwise a minidenticon SVG is returned.
//
// We never 4xx on this endpoint — even if the requester is unauthenticated or
// the user isn't found, we serve the identicon so the avatar visually renders.
export const GET = apiHandler(async (request: NextRequest) => {
const email = request.nextUrl.searchParams.get('email');
if (!email) {
return new Response('Missing email parameter', { status: 400 });
}
const lookup = await withOptionalAuth(async ({ org, prisma }) => {
return prisma.user.findFirst({
where: {
email,
orgs: { some: { orgId: org.id } },
},
select: { image: true },
});
});
if (!isServiceError(lookup) && lookup?.image) {
return new Response(null, {
status: 302,
headers: {
'Location': lookup.image,
'Cache-Control': 'public, max-age=300',
},
});
}
// Fallback: identicons are deterministic from the email so they can be
// cached aggressively.
const svg = minidenticon(email, 50, 50);
return new Response(svg, {
status: 200,
headers: {
'Content-Type': 'image/svg+xml',
'Cache-Control': 'public, max-age=31536000, immutable',
},
});
}, { track: false });