Created
May 5, 2024 12:12
-
-
Save juliusmarminge/6e74be9e76bdce89c6a68a9a9a69ef58 to your computer and use it in GitHub Desktop.
An Auth.js EdgeDB Adapter with support for webauthn
This file contains hidden or 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
import type { Adapter, AdapterAccount } from "next-auth/adapters"; | |
import { edgedb } from "~/db/client"; | |
import e from "@edgedb"; | |
export const edgedbAdapter = { | |
createUser: async ({ id, ...data }) => { | |
const user = await e | |
.select(e.insert(e.User, { ...data }), (user) => user["*"]) | |
.run(edgedb); | |
return user; | |
}, | |
deleteUser: async (id) => { | |
await e | |
.delete(e.User, (user) => ({ | |
filter_single: e.op(user.id, "=", e.uuid(id)), | |
})) | |
.run(edgedb); | |
}, | |
getUser: async (id) => { | |
const user = await e | |
.select(e.User, (user) => ({ | |
...user["*"], | |
filter_single: e.op(user.id, "=", e.uuid(id)), | |
})) | |
.run(edgedb); | |
return user; | |
}, | |
getUserByAccount: async ({ provider, providerAccountId }) => { | |
const account = await e | |
.select(e.Account, (account) => ({ | |
user: e.User["*"], | |
filter_single: e.op( | |
e.op(account.provider, "=", provider), | |
"and", | |
e.op(account.providerAccountId, "=", providerAccountId), | |
), | |
})) | |
.run(edgedb); | |
return account?.user ?? null; | |
}, | |
getUserByEmail: async (email) => { | |
const user = await e | |
.select(e.User, (user) => ({ | |
...user["*"], | |
filter_single: e.op(user.email, "=", email), | |
})) | |
.run(edgedb); | |
return user; | |
}, | |
updateUser: async ({ id, ...data }) => { | |
const user = await e | |
.select( | |
e.update(e.User, (user) => ({ | |
set: data, | |
filter_single: e.op(user.id, "=", e.uuid(id)), | |
})), | |
(user) => user["*"], | |
) | |
.run(edgedb); | |
if (!user) throw "user not found"; | |
return user; | |
}, | |
createSession: async ({ userId, ...data }) => { | |
const session = await e | |
.select( | |
e.insert(e.Session, { | |
...data, | |
user: e.select(e.User, (user) => ({ | |
filter_single: e.op(user.id, "=", e.uuid(userId)), | |
})), | |
}), | |
(session) => session["*"], | |
) | |
.run(edgedb); | |
return session; | |
}, | |
deleteSession: async (sessionToken) => { | |
await e | |
.delete(e.Session, (session) => ({ | |
filter_single: e.op(session.sessionToken, "=", sessionToken), | |
})) | |
.run(edgedb); | |
}, | |
getSessionAndUser: async (sessionToken) => { | |
const session = await e | |
.select(e.Session, (session) => ({ | |
...session["*"], | |
user: e.User["*"], | |
filter_single: e.op(session.sessionToken, "=", sessionToken), | |
})) | |
.run(edgedb); | |
if (!session) return null; | |
const { user, ...sessionData } = session; | |
return { user, session: sessionData }; | |
}, | |
updateSession: async ({ sessionToken, ...data }) => { | |
const session = await e | |
.select( | |
e.update(e.Session, (session) => ({ | |
set: data, | |
filter_single: e.op(session.sessionToken, "=", sessionToken), | |
})), | |
(session) => session["*"], | |
) | |
.run(edgedb); | |
if (!session) throw "session not found"; | |
return session; | |
}, | |
linkAccount: async ({ userId, ...data }) => { | |
await e | |
.insert(e.Account, { | |
...data, | |
user: e.select(e.User, (user) => ({ | |
filter_single: e.op(user.id, "=", e.uuid(userId)), | |
})), | |
}) | |
.run(edgedb); | |
}, | |
unlinkAccount: async ({ provider, providerAccountId }) => { | |
await e | |
.delete(e.Account, (account) => ({ | |
filter_single: e.op( | |
e.op(account.provider, "=", provider), | |
"and", | |
e.op(account.providerAccountId, "=", providerAccountId), | |
), | |
})) | |
.run(edgedb); | |
}, | |
getAccount: async (providerAccountId, provider) => { | |
const account = await e | |
.select(e.Account, (account) => ({ | |
...account["*"], | |
filter_single: e.op( | |
e.op(account.provider, "=", provider), | |
"and", | |
e.op(account.providerAccountId, "=", providerAccountId), | |
), | |
})) | |
.run(edgedb); | |
return (account as AdapterAccount) ?? null; | |
}, | |
createVerificationToken: async (data) => { | |
const token = await e | |
.select( | |
e.insert(e.VerificationToken, { | |
...data, | |
}), | |
(vt) => vt["*"], | |
) | |
.run(edgedb); | |
return token; | |
}, | |
useVerificationToken: async ({ identifier, token }) => { | |
const usedToken = await e | |
.select( | |
e.delete(e.VerificationToken, (vt) => ({ | |
filter_single: e.op( | |
e.op(vt.identifier, "=", identifier), | |
"and", | |
e.op(vt.token, "=", token), | |
), | |
})), | |
(vt) => vt["*"], | |
) | |
.run(edgedb); | |
return usedToken; | |
}, | |
createAuthenticator: async ({ userId, ...data }) => { | |
const authenticator = await e | |
.select( | |
e.insert(e.Authenticators, { | |
...data, | |
user: e.select(e.User, (user) => ({ | |
filter_single: e.op(user.id, "=", e.uuid(userId)), | |
})), | |
}), | |
(auth) => auth["*"], | |
) | |
.run(edgedb); | |
const { id: _, ...rest } = authenticator; | |
return rest; | |
}, | |
getAuthenticator: async (credentialId) => { | |
const authenticator = await e | |
.select(e.Authenticators, (auth) => ({ | |
...auth["*"], | |
filter_single: e.op(auth.credentialID, "=", credentialId), | |
})) | |
.run(edgedb); | |
return authenticator ?? null; | |
}, | |
listAuthenticatorsByUserId: async (userId) => { | |
const auths = await e | |
.select(e.Authenticators, (auth) => ({ | |
...auth["*"], | |
filter: e.op(auth.userId, "=", e.uuid(userId)), | |
})) | |
.run(edgedb); | |
return auths; | |
}, | |
updateAuthenticatorCounter: async (credentialId, counter) => { | |
const authenticator = await e | |
.select( | |
e.update(e.Authenticators, (auth) => ({ | |
set: { counter }, | |
filter_single: e.op(auth.credentialID, "=", credentialId), | |
})), | |
(auth) => auth["*"], | |
) | |
.run(edgedb); | |
if (!authenticator) throw "authenticator not found"; | |
return authenticator; | |
}, | |
} satisfies Adapter; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment