mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-06-08 11:37:25 +00:00
login working
This commit is contained in:
parent
7d51fcc4dc
commit
2d4a11b94d
6 changed files with 56 additions and 26 deletions
|
|
@ -31,6 +31,9 @@ import {
|
||||||
* - Force re-login after role/permission changes
|
* - Force re-login after role/permission changes
|
||||||
* - Audit trail of login activity
|
* - Audit trail of login activity
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// We extend
|
||||||
|
|
||||||
export default function DrizzleEmailAdapter(
|
export default function DrizzleEmailAdapter(
|
||||||
db: any,
|
db: any,
|
||||||
tables: {
|
tables: {
|
||||||
|
|
@ -54,6 +57,7 @@ export default function DrizzleEmailAdapter(
|
||||||
name: u.firstName ?? null,
|
name: u.firstName ?? null,
|
||||||
image: u.image ?? null,
|
image: u.image ?? null,
|
||||||
emailVerified: u.emailVerified ?? null,
|
emailVerified: u.emailVerified ?? null,
|
||||||
|
onboarded: u.onboarded ?? false,
|
||||||
});
|
});
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
|
|
@ -181,6 +185,7 @@ export default function DrizzleEmailAdapter(
|
||||||
async createVerificationToken(
|
async createVerificationToken(
|
||||||
token: VerificationToken
|
token: VerificationToken
|
||||||
): Promise<VerificationToken> {
|
): Promise<VerificationToken> {
|
||||||
|
console.log("Creating verification token for:", token.identifier);
|
||||||
const [created] = await db
|
const [created] = await db
|
||||||
.insert(verificationTokens)
|
.insert(verificationTokens)
|
||||||
.values({
|
.values({
|
||||||
|
|
|
||||||
|
|
@ -113,8 +113,8 @@ export const AuthOptions: NextAuthOptions = {
|
||||||
.where(eq(users.email, normalisedEmail));
|
.where(eq(users.email, normalisedEmail));
|
||||||
|
|
||||||
if (!dbUser) {
|
if (!dbUser) {
|
||||||
console.warn(`User not found for ${normalisedEmail} after sign-in.`);
|
console.log("New user sign up for email:", normalisedEmail);
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link OAuth ID if missing (helps for older accounts)
|
// Link OAuth ID if missing (helps for older accounts)
|
||||||
|
|
@ -134,11 +134,7 @@ export const AuthOptions: NextAuthOptions = {
|
||||||
|
|
||||||
// Pass bigint ID into NextAuth session/jwt
|
// Pass bigint ID into NextAuth session/jwt
|
||||||
user.dbId = dbUser.id.toString();
|
user.dbId = dbUser.id.toString();
|
||||||
|
user.onboarded = dbUser.onboarded ?? false;
|
||||||
// If the user isn't onboarded yet, redirect to onboarding
|
|
||||||
if (!dbUser.onboarded) {
|
|
||||||
return "/onboarding";
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -154,6 +150,10 @@ export const AuthOptions: NextAuthOptions = {
|
||||||
if (user?.dbId) {
|
if (user?.dbId) {
|
||||||
token.dbId = user.dbId;
|
token.dbId = user.dbId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fetch onboarding status from user
|
||||||
|
if (user?.onboarded !== undefined) token.onboarded = user.onboarded;
|
||||||
|
|
||||||
return token;
|
return token;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -171,6 +171,7 @@ export const AuthOptions: NextAuthOptions = {
|
||||||
* Redirect users after login
|
* Redirect users after login
|
||||||
*/
|
*/
|
||||||
async redirect({ baseUrl }) {
|
async redirect({ baseUrl }) {
|
||||||
|
// If the user has not onboarded, send them to onboarding
|
||||||
return `${baseUrl}/home`;
|
return `${baseUrl}/home`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
export default function VerifyRequestPage() {
|
|
||||||
return (
|
|
||||||
<div className="flex h-screen items-center justify-center bg-gray-50">
|
|
||||||
<div className="text-center">
|
|
||||||
<h1 className="text-2xl font-semibold text-brandblue mb-2">
|
|
||||||
Check your email
|
|
||||||
</h1>
|
|
||||||
<p className="text-gray-600">
|
|
||||||
We’ve sent you a sign-in link. Click it to finish logging in.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -19,12 +19,17 @@ export default function EmailSignInButton({
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setStatus("sending");
|
setStatus("sending");
|
||||||
|
|
||||||
|
console.log("BEFOERE SIGN IN");
|
||||||
|
console.log("window.location.origin:", window.location.origin);
|
||||||
const res = await signIn("email", { email, redirect: false });
|
const res = await signIn("email", { email, redirect: false });
|
||||||
|
console.log("AFTER SIGN IN");
|
||||||
|
|
||||||
if (res?.error) {
|
if (res?.error) {
|
||||||
setError("You are not a valid user.");
|
setError("You are not a valid user.");
|
||||||
setStatus("idle");
|
setStatus("idle");
|
||||||
|
console.log("Error signing in:", res.error);
|
||||||
} else {
|
} else {
|
||||||
|
console.log("Sign-in link sent to:", email);
|
||||||
setError(undefined);
|
setError(undefined);
|
||||||
setStatus("sent");
|
setStatus("sent");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,44 @@
|
||||||
|
import { NextResponse } from "next/server";
|
||||||
|
import type { NextRequest } from "next/server";
|
||||||
|
import { getToken } from "next-auth/jwt";
|
||||||
|
|
||||||
|
export async function middleware(req: NextRequest) {
|
||||||
|
const token = await getToken({ req });
|
||||||
|
const { pathname } = req.nextUrl;
|
||||||
|
|
||||||
|
// If no session, send user to sign-in page
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.redirect(new URL("/", req.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
const userEmail = token.email || "";
|
||||||
|
|
||||||
|
// Internal users (bypass onboarding)
|
||||||
|
// const isInternal = userEmail.endsWith("@domna.homes");
|
||||||
|
|
||||||
|
// Not onboarded and not internal
|
||||||
|
if (token.onboarded === false && pathname !== "/onboarding") {
|
||||||
|
return NextResponse.redirect(new URL("/onboarding", req.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Already onboarded but tries to go back to onboarding page
|
||||||
|
if (token.onboarded === true && pathname === "/onboarding") {
|
||||||
|
return NextResponse.redirect(new URL("/home", req.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything else allowed
|
||||||
|
return NextResponse.next();
|
||||||
|
}
|
||||||
|
|
||||||
export const config = {
|
export const config = {
|
||||||
matcher: [
|
matcher: [
|
||||||
|
// Protect only your app’s authenticated areas
|
||||||
"/home/:path*",
|
"/home/:path*",
|
||||||
"/portfolio/:path*",
|
"/portfolio/:path*",
|
||||||
"/search/:path*",
|
"/search/:path*",
|
||||||
"/addresses/:path",
|
"/addresses/:path*",
|
||||||
"/due-considerations/:path",
|
"/due-considerations/:path*",
|
||||||
"/eco-spreadsheet/:path",
|
"/eco-spreadsheet/:path*",
|
||||||
|
"/onboarding", // add onboarding itself
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export { default } from "next-auth/middleware";
|
|
||||||
|
|
|
||||||
1
src/types/next-auth.d.ts
vendored
1
src/types/next-auth.d.ts
vendored
|
|
@ -10,5 +10,6 @@ declare module "next-auth" {
|
||||||
}
|
}
|
||||||
interface User {
|
interface User {
|
||||||
dbId: string;
|
dbId: string;
|
||||||
|
onboarded: boolean;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue