Added gravatar support in case of no avatar
This commit is contained in:
19
.env.example
Normal file
19
.env.example
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# General
|
||||||
|
NEXT_PUBLIC_BASE_URL=http://localhost:3000
|
||||||
|
|
||||||
|
# Database
|
||||||
|
PG_USER=dev
|
||||||
|
PG_PASSWORD=dev
|
||||||
|
PG_HOST=localhost
|
||||||
|
PG_PORT=5433
|
||||||
|
PG_DATABASE=dev
|
||||||
|
|
||||||
|
# Auth
|
||||||
|
BETTER_AUTH_SECRET=
|
||||||
|
BETTER_AUTH_URL=http://localhost:3000
|
||||||
|
AUTHENTIK_CLIENT_ID=
|
||||||
|
AUTHENTIK_CLIENT_SECRET=
|
||||||
|
AUTHENTIK_DISCOVERY_URL=
|
||||||
|
|
||||||
|
# other
|
||||||
|
GRAVATAR_API_KEY=
|
||||||
@@ -4,11 +4,30 @@ import { nextCookies } from "better-auth/next-js"
|
|||||||
import { genericOAuth } from "better-auth/plugins"
|
import { genericOAuth } from "better-auth/plugins"
|
||||||
import { db } from "../drizzle/db"
|
import { db } from "../drizzle/db"
|
||||||
import { env } from "../env/server"
|
import { env } from "../env/server"
|
||||||
|
import { getGravatar } from "../gravatar"
|
||||||
|
|
||||||
export const auth = betterAuth({
|
export const auth = betterAuth({
|
||||||
database: drizzleAdapter(db, {
|
database: drizzleAdapter(db, {
|
||||||
provider: "pg"
|
provider: "pg"
|
||||||
}),
|
}),
|
||||||
|
databaseHooks: {
|
||||||
|
user: {
|
||||||
|
create: {
|
||||||
|
before: async (user) => {
|
||||||
|
if (user.image) return
|
||||||
|
|
||||||
|
const newImage = await getGravatar(user.email)
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: {
|
||||||
|
...user,
|
||||||
|
image: newImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
nextCookies(),
|
nextCookies(),
|
||||||
genericOAuth({
|
genericOAuth({
|
||||||
|
|||||||
3
src/lib/env/server.ts
vendored
3
src/lib/env/server.ts
vendored
@@ -12,7 +12,8 @@ export const env = createEnv({
|
|||||||
BETTER_AUTH_URL: z.string().min(1),
|
BETTER_AUTH_URL: z.string().min(1),
|
||||||
AUTHENTIK_CLIENT_ID: z.string().min(1),
|
AUTHENTIK_CLIENT_ID: z.string().min(1),
|
||||||
AUTHENTIK_CLIENT_SECRET: z.string().min(1),
|
AUTHENTIK_CLIENT_SECRET: z.string().min(1),
|
||||||
AUTHENTIK_DISCOVERY_URL: z.string().min(1)
|
AUTHENTIK_DISCOVERY_URL: z.string().min(1),
|
||||||
|
GRAVATAR_API_KEY: z.string().min(1)
|
||||||
},
|
},
|
||||||
createFinalSchema: (schema) => {
|
createFinalSchema: (schema) => {
|
||||||
return z.object(schema).transform(s => {
|
return z.object(schema).transform(s => {
|
||||||
|
|||||||
28
src/lib/gravatar.ts
Normal file
28
src/lib/gravatar.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import crypto from "node:crypto"
|
||||||
|
import { env } from "./env/server"
|
||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
|
const gravatarSchema = z.object({
|
||||||
|
avatar_url: z.string().url(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export async function getGravatar(email: string) {
|
||||||
|
const baseUrl = "https://api.gravatar.com/v3/profiles"
|
||||||
|
const formattedEmail = email.trim().toLowerCase()
|
||||||
|
const hash = crypto.createHash('sha256').update(formattedEmail).digest('hex')
|
||||||
|
|
||||||
|
const res = await fetch(`${baseUrl}/${hash}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${env.GRAVATAR_API_KEY}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!res.ok) return null
|
||||||
|
|
||||||
|
const json = await res.json()
|
||||||
|
const { success, data } = gravatarSchema.safeParse(json)
|
||||||
|
|
||||||
|
if (!success) return null
|
||||||
|
|
||||||
|
return data.avatar_url
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user