Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142import { Events, setupAnalytics } from "@openstatus/analytics";import { db, eq } from "@openstatus/db";import { user } from "@openstatus/db/src/schema";import { WelcomeEmail, sendEmail } from "@openstatus/emails";import type { DefaultSession } from "next-auth";import NextAuth from "next-auth";import { headers } from "next/headers";
import { adapter } from "./adapter";import { GitHubProvider, GoogleProvider, ResendProvider } from "./providers";
export type { DefaultSession };
export const { handlers, signIn, signOut, auth } = NextAuth({ // debug: true, adapter, providers: process.env.NODE_ENV === "development" || process.env.SELF_HOST === "true" ? [GitHubProvider, GoogleProvider, ResendProvider] : [GitHubProvider, GoogleProvider], callbacks: { async redirect({ url, baseUrl }) { // Allow relative URLs, but not protocol-relative `//evil.com` which the // browser would resolve off-origin. if (url.startsWith("/") && !url.startsWith("//")) { return `${baseUrl}${url}`; } // Same-origin absolute URLs only โ compare parsed origins, not a string // prefix, so `https://<baseUrl>.evil.com` cannot pass as trusted. // Preserves the original callback URL so invite links keep working. try { if (new URL(url).origin === new URL(baseUrl).origin) { return url; } } catch { // malformed url โ fall through to baseUrl } return baseUrl; }, async signIn(params) { // We keep updating the user info when we loggin in
if (params.account?.provider === "google") { if (!params.profile) return true; if (Number.isNaN(Number(params.user.id))) return true;
await db .update(user) .set({ firstName: params.profile.given_name, lastName: params.profile.family_name || "", photoUrl: params.profile.picture, // keep the name in sync name: `${params.profile.given_name} ${ params.profile.family_name || "" }`.trim(), updatedAt: new Date(), }) .where(eq(user.id, Number(params.user.id))) .run(); } if (params.account?.provider === "github") { if (!params.profile) return true; if (Number.isNaN(Number(params.user.id))) return true;
await db .update(user) .set({ name: params.profile.name, photoUrl: String(params.profile.avatar_url), updatedAt: new Date(), }) .where(eq(user.id, Number(params.user.id))) .run(); }
// REMINDER: only used in dev mode if (params.account?.provider === "resend") { if (Number.isNaN(Number(params.user.id))) return true; await db .update(user) .set({ updatedAt: new Date() }) .where(eq(user.id, Number(params.user.id))) .run(); }
return true; }, async session(params) { return params.session; }, }, events: { // That should probably done in the callback method instead async createUser(params) { if (!params.user.id || !params.user.email) { throw new Error("User id & email is required"); }
// this means the user has already been created with clerk if (params.user.tenantId) return;
await sendEmail({ from: "Thibault from OpenStatus <thibault@openstatus.dev>", subject: "Welcome to OpenStatus.", to: [params.user.email], react: WelcomeEmail(), });
const analytics = await setupAnalytics({ userId: `usr_${params.user.id}`, email: params.user.email, location: (await headers()).get("x-forwarded-for") ?? undefined, userAgent: (await headers()).get("user-agent") ?? undefined, });
await analytics.track(Events.CreateUser); },
async signIn(params) { if (params.isNewUser) return; if (!params.user.id || !params.user.email) return;
const analytics = await setupAnalytics({ userId: `usr_${params.user.id}`, email: params.user.email, location: (await headers()).get("x-forwarded-for") ?? undefined, userAgent: (await headers()).get("user-agent") ?? undefined, });
await analytics.track(Events.SignInUser); }, }, pages: { signIn: "/login", newUser: "/onboarding", }, // basePath: "/api/auth", // default is `/api/auth` // secret: process.env.AUTH_SECRET, // default is `AUTH_SECRET` debug: process.env.NODE_ENV === "development",});