Add login flow
This commit is contained in:
@@ -6,6 +6,8 @@ import {
|
||||
} from "next-auth";
|
||||
import { type Adapter } from "next-auth/adapters";
|
||||
import GitHubProvider from "next-auth/providers/github";
|
||||
import EmailProvider from "next-auth/providers/email";
|
||||
import GoogleProvider from "next-auth/providers/google";
|
||||
|
||||
import { env } from "~/env";
|
||||
import { db } from "~/server/db";
|
||||
@@ -48,6 +50,9 @@ export const authOptions: NextAuthOptions = {
|
||||
}),
|
||||
},
|
||||
adapter: PrismaAdapter(db) as Adapter,
|
||||
pages: {
|
||||
signIn: "/login",
|
||||
},
|
||||
providers: [
|
||||
/**
|
||||
* ...add more providers here.
|
||||
@@ -61,6 +66,21 @@ export const authOptions: NextAuthOptions = {
|
||||
GitHubProvider({
|
||||
clientId: env.GITHUB_ID,
|
||||
clientSecret: env.GITHUB_SECRET,
|
||||
allowDangerousEmailAccountLinking: true,
|
||||
}),
|
||||
GoogleProvider({
|
||||
clientId: env.GOOGLE_CLIENT_ID,
|
||||
clientSecret: env.GOOGLE_CLIENT_SECRET,
|
||||
allowDangerousEmailAccountLinking: true,
|
||||
}),
|
||||
EmailProvider({
|
||||
from: "no-reply@splitpro.app",
|
||||
async sendVerificationRequest({ identifier: email, url, token }) {
|
||||
await sendSignUpEmail(email, token, url);
|
||||
},
|
||||
async generateVerificationToken() {
|
||||
return Math.random().toString(36).substring(2, 7).toLowerCase();
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
@@ -73,6 +93,7 @@ export const authOptions: NextAuthOptions = {
|
||||
export const getServerAuthSession = () => getServerSession(authOptions);
|
||||
|
||||
import { createHash } from "crypto";
|
||||
import { sendSignUpEmail } from "./mailer";
|
||||
|
||||
/**
|
||||
* Hashes a token using SHA-256.
|
||||
|
57
apps/web/src/server/mailer.ts
Normal file
57
apps/web/src/server/mailer.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { env } from "~/env";
|
||||
|
||||
export async function sendSignUpEmail(
|
||||
email: string,
|
||||
token: string,
|
||||
url: string
|
||||
) {
|
||||
const { host } = new URL(url);
|
||||
|
||||
if (env.NODE_ENV === "development") {
|
||||
console.log("Sending sign in email", email, url, token);
|
||||
return;
|
||||
}
|
||||
|
||||
const subject = "Sign in to Unsend";
|
||||
const text = `Hey,\n\nYou can sign in to Unsend by clicking the below URL:\n${url}\n\nYou can also use this OTP: ${token}\n\nThanks,\nUnsend Team`;
|
||||
const html = `<p>Hey,</p> <p>You can sign in to Unsend by clicking the below URL:</p><p><a href="${url}">Sign in to ${host}</a></p><p>You can also use this OTP: <b>${token}</b></p<br /><br /><p>Thanks,</p><p>Unsend Team</p>`;
|
||||
|
||||
await sendMail(email, subject, text, html);
|
||||
}
|
||||
|
||||
async function sendMail(
|
||||
email: string,
|
||||
subject: string,
|
||||
text: string,
|
||||
html: string
|
||||
) {
|
||||
if (env.UNSEND_API_KEY && env.UNSEND_URL) {
|
||||
const resp = await fetch(`${env.UNSEND_URL}/emails`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${env.UNSEND_API_KEY}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
from: "no-reply@auth.unsend.dev",
|
||||
to: email,
|
||||
subject,
|
||||
text,
|
||||
html,
|
||||
}),
|
||||
});
|
||||
|
||||
if (resp.status === 200) {
|
||||
console.log("Email sent using unsend");
|
||||
return;
|
||||
} else {
|
||||
console.log(
|
||||
"Error sending email using unsend, so fallback to resend",
|
||||
resp.status,
|
||||
resp.statusText
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error("UNSEND_API_KEY or UNSEND_URL not found");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user