UNPKG

@auth/pg-adapter

Version:

Postgres adapter for next-auth.

262 lines (248 loc) 7.55 kB
/** * <div style={{display: "flex", justifyContent: "space-between", alignItems: "center", padding: 16}}> * <p>An official <a href="https://www.postgresql.org/">PostgreSQL</a> adapter for Auth.js / NextAuth.js.</p> * <a href="https://www.postgresql.org/"> * <img style={{display: "block"}} src="/img/adapters/pg.svg" width="48" /> * </a> * </div> * * ## Installation * * ```bash npm2yarn * npm install next-auth @auth/pg-adapter pg * ``` * * @module @auth/pg-adapter */ import type { Adapter, AdapterUser, VerificationToken, AdapterSession, } from "@auth/core/adapters" import type { Pool } from "pg" export function mapExpiresAt(account: any): any { const expires_at: number = parseInt(account.expires_at) return { ...account, expires_at, } } export default function PostgresAdapter(client: Pool): Adapter { return { async createVerificationToken( verificationToken: VerificationToken ): Promise<VerificationToken> { const { identifier, expires, token } = verificationToken const sql = ` INSERT INTO verification_token ( identifier, expires, token ) VALUES ($1, $2, $3) ` await client.query(sql, [identifier, expires, token]) return verificationToken }, async useVerificationToken({ identifier, token, }: { identifier: string token: string }): Promise<VerificationToken> { const sql = `delete from verification_token where identifier = $1 and token = $2 RETURNING identifier, expires, token ` const result = await client.query(sql, [identifier, token]) return result.rowCount !== 0 ? result.rows[0] : null }, async createUser(user: Omit<AdapterUser, "id">) { const { name, email, emailVerified, image } = user const sql = ` INSERT INTO users (name, email, "emailVerified", image) VALUES ($1, $2, $3, $4) RETURNING id, name, email, "emailVerified", image` const result = await client.query(sql, [ name, email, emailVerified, image, ]) return result.rows[0] }, async getUser(id) { const sql = `select * from users where id = $1` try { const result = await client.query(sql, [id]) return result.rowCount === 0 ? null : result.rows[0] } catch { return null } }, async getUserByEmail(email) { const sql = `select * from users where email = $1` const result = await client.query(sql, [email]) return result.rowCount !== 0 ? result.rows[0] : null }, async getUserByAccount({ providerAccountId, provider, }): Promise<AdapterUser | null> { const sql = ` select u.* from users u join accounts a on u.id = a."userId" where a.provider = $1 and a."providerAccountId" = $2` const result = await client.query(sql, [provider, providerAccountId]) return result.rowCount !== 0 ? result.rows[0] : null }, async updateUser(user: Partial<AdapterUser>): Promise<AdapterUser> { const fetchSql = `select * from users where id = $1` const query1 = await client.query(fetchSql, [user.id]) const oldUser = query1.rows[0] const newUser = { ...oldUser, ...user, } const { id, name, email, emailVerified, image } = newUser const updateSql = ` UPDATE users set name = $2, email = $3, "emailVerified" = $4, image = $5 where id = $1 RETURNING name, id, email, "emailVerified", image ` const query2 = await client.query(updateSql, [ id, name, email, emailVerified, image, ]) return query2.rows[0] }, async linkAccount(account) { const sql = ` insert into accounts ( "userId", provider, type, "providerAccountId", access_token, expires_at, refresh_token, id_token, scope, session_state, token_type ) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) returning id, "userId", provider, type, "providerAccountId", access_token, expires_at, refresh_token, id_token, scope, session_state, token_type ` const params = [ account.userId, account.provider, account.type, account.providerAccountId, account.access_token, account.expires_at, account.refresh_token, account.id_token, account.scope, account.session_state, account.token_type, ] const result = await client.query(sql, params) return mapExpiresAt(result.rows[0]) }, async createSession({ sessionToken, userId, expires }) { if (userId === undefined) { throw Error(`userId is undef in createSession`) } const sql = `insert into sessions ("userId", expires, "sessionToken") values ($1, $2, $3) RETURNING id, "sessionToken", "userId", expires` const result = await client.query(sql, [userId, expires, sessionToken]) return result.rows[0] }, async getSessionAndUser(sessionToken: string | undefined): Promise<{ session: AdapterSession user: AdapterUser } | null> { if (sessionToken === undefined) { return null } const result1 = await client.query( `select * from sessions where "sessionToken" = $1`, [sessionToken] ) if (result1.rowCount === 0) { return null } const session: AdapterSession = result1.rows[0] const result2 = await client.query("select * from users where id = $1", [ session.userId, ]) if (result2.rowCount === 0) { return null } const user = result2.rows[0] return { session, user, } }, async updateSession( session: Partial<AdapterSession> & Pick<AdapterSession, "sessionToken"> ): Promise<AdapterSession | null | undefined> { const { sessionToken } = session const result1 = await client.query( `select * from sessions where "sessionToken" = $1`, [sessionToken] ) if (result1.rowCount === 0) { return null } const originalSession: AdapterSession = result1.rows[0] const newSession: AdapterSession = { ...originalSession, ...session, } const sql = ` UPDATE sessions set expires = $2 where "sessionToken" = $1 ` const result = await client.query(sql, [ newSession.sessionToken, newSession.expires, ]) return result.rows[0] }, async deleteSession(sessionToken) { const sql = `delete from sessions where "sessionToken" = $1` await client.query(sql, [sessionToken]) }, async unlinkAccount(partialAccount) { const { provider, providerAccountId } = partialAccount const sql = `delete from accounts where "providerAccountId" = $1 and provider = $2` await client.query(sql, [providerAccountId, provider]) }, async deleteUser(userId: string) { await client.query(`delete from users where id = $1`, [userId]) await client.query(`delete from sessions where "userId" = $1`, [userId]) await client.query(`delete from accounts where "userId" = $1`, [userId]) }, } }