UNPKG

@decked/payload-auth-plugin

Version:
136 lines (123 loc) 3.41 kB
import { BasePayload, PayloadRequest } from "payload" import { UserNotFound } from "../errors/consoleErrors.js" import { AccountInfo } from "../../types.js" import { hashCode } from "../utils/hash.js" import { createSessionCookies, invalidateOAuthCookies, } from "../utils/cookies.js" import { sessionResponse } from "../utils/session.js" import { UserNotFoundAPIError } from "../errors/apiErrors.js" type Collections = { accountsCollectionSlug: string usersCollectionSlug: string } export class PayloadSession { readonly #collections: Collections readonly #allowSignUp: boolean constructor(collections: Collections, allowSignUp?: boolean) { this.#collections = collections this.#allowSignUp = !!allowSignUp } async #upsertAccount( accountInfo: AccountInfo, scope: string, issuerName: string, payload: BasePayload, ) { let userID: string | number const userQueryResults = await payload.find({ collection: this.#collections.usersCollectionSlug, where: { email: { equals: accountInfo.email, }, }, }) if (userQueryResults.docs.length === 0) { if (!this.#allowSignUp) { return new UserNotFoundAPIError() } const newUser = await payload.create({ collection: this.#collections.usersCollectionSlug, data: { email: accountInfo.email, emailVerified: true, password: hashCode(accountInfo.email + payload.secret).toString(), }, }) userID = newUser.id } else { userID = userQueryResults.docs[0].id as string } const accounts = await payload.find({ collection: this.#collections.accountsCollectionSlug, where: { sub: { equals: accountInfo.sub }, }, }) const data: Record<string, unknown> = { scope, name: accountInfo.name, picture: accountInfo.picture, } if (issuerName === "Passkey" && accountInfo.passKey) { data["passkey"] = { ...accountInfo.passKey, } } if (accounts.docs.length > 0) { data["sub"] = accountInfo.sub data["issuerName"] = issuerName data["user"] = userID await payload.update({ collection: this.#collections.accountsCollectionSlug, where: { id: { equals: accounts.docs[0].id, }, }, data, }) } else { data["sub"] = accountInfo.sub data["issuerName"] = issuerName data["user"] = userID await payload.create({ collection: this.#collections.accountsCollectionSlug, data, }) } return userID } async createSession( accountInfo: AccountInfo, scope: string, issuerName: string, request: PayloadRequest, clientOrigin: string, ) { const { payload } = request const userID = await this.#upsertAccount( accountInfo, scope, issuerName, payload, ) const fieldsToSign = { id: userID, email: accountInfo.email, collection: this.#collections.usersCollectionSlug, } let cookies: string[] = [] cookies = [ ...(await createSessionCookies( `${payload.config.cookiePrefix!}-token`, payload.secret, fieldsToSign, )), ] cookies = invalidateOAuthCookies(cookies) return sessionResponse(cookies, clientOrigin) } }