/* eslint-disable unicorn/no-null */ import Joi from "joi"; import * as Hapi from "@hapi/hapi"; import { ResponseToolkit, ResponseObject } from "@hapi/hapi"; export interface LinkAccountPayload { userId: string; providerType: string; providerId: string; providerAccountId: string; refreshToken: string; accessToken: string; accessTokenExpires?: null; } export const register = async ( server: Hapi.Server, opts: any, auth?: string ): Promise => { const { tags, basePath, validators } = opts; const { session, user, userId, profile } = validators; server.route([ { method: "POST", path: `${basePath}/createUser`, options: { auth, tags, validate: { payload: profile, }, async handler( request: Hapi.Request, h: ResponseToolkit ): Promise { const payload: TProfile = request.payload as TProfile; const r = await opts .nextAuthAdapterFactory(request) .createUser(payload); return h.response(r as object); }, description: "Create a user from a profile", }, }, { method: "GET", path: `${basePath}/getUser/{userId}`, options: { auth, tags, validate: { params: { userId, }, }, async handler( request: Hapi.Request, h: ResponseToolkit ): Promise { const id = request.params.userId; const r = await opts.nextAuthAdapterFactory(request).getUser(id); if (!r) return h.response().code(404); return h.response(r as object); }, description: "Get a user by id", }, }, { method: "GET", path: `${basePath}/getUserByEmail/{userEmail}`, options: { auth, tags, validate: { params: { userEmail: Joi.string().email(), }, }, async handler( request: Hapi.Request, h: ResponseToolkit ): Promise { const email = request.params.userEmail; const r = await opts .nextAuthAdapterFactory(request) .getUserByEmail(email); if (!r) return h.response().code(404); return h.response(r as object); }, description: "Get a user by email", }, }, { method: "GET", path: `${basePath}/getUserByAccount/{provider}/{providerAccountId}`, options: { auth, tags, validate: { params: { provider: Joi.string(), providerAccountId: Joi.string(), }, }, async handler( request: Hapi.Request, h: ResponseToolkit ): Promise { const { provider, providerAccountId } = request.params; const r = await opts .nextAuthAdapterFactory(request) .getUserByAccount(provider, providerAccountId); if (!r) return h.response().code(404); return h.response(r as object); }, description: "Get a user by provider id and provider account id", }, }, { method: "PUT", path: `${basePath}/updateUser`, options: { auth, tags, validate: { payload: user, }, async handler( request: Hapi.Request, h: ResponseToolkit ): Promise { const payload: TUser = request.payload as TUser; const r = await opts .nextAuthAdapterFactory(request) .updateUser(payload); if (!r) return h.response().code(404); return h.response(r as object); }, description: "Update a user's data", }, }, { method: "PUT", path: `${basePath}/linkAccount`, options: { auth, tags, validate: { payload: Joi.object({ // https://next-auth.js.org/getting-started/upgrade-v4#schema-changes userId: Joi.string().required(), provider: Joi.string().required(), type: Joi.string().required(), providerAccountId: Joi.string().required(), refresh_token: Joi.string().optional().allow(null), access_token: Joi.string().optional().allow(null), expires_at: Joi.number().optional().allow(null), }).unknown(true), }, async handler( request: Hapi.Request, h: ResponseToolkit ): Promise { const { userId, providerId, providerType, providerAccountId, refreshToken, accessToken, accessTokenExpires, } = request.payload as LinkAccountPayload; await opts .nextAuthAdapterFactory(request) .linkAccount( userId, providerId, providerType, providerAccountId, refreshToken, accessToken, accessTokenExpires ); return h.response().code(204); }, description: "Link a provider account with a user", }, }, { method: "POST", path: `${basePath}/createSession`, options: { auth, tags, validate: { payload: Joi.object({ userId: Joi.string().required(), sessionToken: Joi.string().required(), expires: Joi.string().isoDate().required(), }), }, async handler( request: Hapi.Request, h: ResponseToolkit ): Promise { const payload: TUser = request.payload as TUser; const r = await opts .nextAuthAdapterFactory(request) .createSession(payload); return h.response(r as object); }, description: "Create a new session for a user", }, }, { method: "GET", path: `${basePath}/getSessionAndUser/{sessionToken}`, options: { auth, tags, validate: { params: { sessionToken: Joi.string(), }, }, async handler( request: Hapi.Request, h: ResponseToolkit ): Promise { const token = request.params.sessionToken; const r = await opts .nextAuthAdapterFactory(request) .getSessionAndUser(token); if (!r) return h.response().code(404); return h.response(r as object); }, description: "Get a session by its token", }, }, { method: "PUT", path: `${basePath}/updateSession`, options: { auth, tags, validate: { payload: session, }, async handler( request: Hapi.Request, h: ResponseToolkit ): Promise { const inputPayload = request.payload as any; const { expires } = inputPayload; const payload = { ...inputPayload, expires: new Date(expires), }; const force = Boolean(request.query.force); const r = await opts .nextAuthAdapterFactory(request) .updateSession(payload, force); if (!r) return h.response().code(204); return h.response(r as object); }, description: "Update a session for a user", }, }, { method: "DELETE", path: `${basePath}/deleteSession/{sessionToken}`, options: { auth, tags, validate: { params: { sessionToken: Joi.string(), }, }, async handler( request: Hapi.Request, h: ResponseToolkit ): Promise { const token = request.params.sessionToken; await opts.nextAuthAdapterFactory(request).deleteSession(token); return h.response().code(204); }, description: "Delete a user's session", }, }, ]); };