Skip to content

Commit 6c5ca25

Browse files
authored
Update all dependencies. (vercel#48)
2 parents 7477bca + a6ac1d3 commit 6c5ca25

32 files changed

+5658
-1821
lines changed

.env.example

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,6 @@
22
POSTGRES_URL=
33
POSTGRES_PRISMA_URL=
44
POSTGRES_URL_NON_POOLING=
5-
POSTGRES_USER=
6-
POSTGRES_HOST=
7-
POSTGRES_PASSWORD=
8-
POSTGRES_DATABASE=
95

106
# Generate one here: https://generate-secret.vercel.app/32 (only required for localhost)
11-
NEXTAUTH_SECRET=
7+
AUTH_SECRET=

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ yarn-error.log*
3434

3535
# vercel
3636
.vercel
37+
.env*.local

README.md

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
1-
<p align="center">
2-
<a href="https://nextjs-postgres-auth.vercel.app/">
3-
<img src="/public/logo.png" height="96">
4-
<h3 align="center">Next.js Prisma PostgreSQL Auth Starter</h3>
5-
</a>
6-
</p>
1+
# Next.js + PostgreSQL Auth Starter
72

8-
<p align="center">
9-
This is a <a href="https://nextjs.org/">Next.js</a> starter kit that uses <a href="https://next-auth.js.org/">Next-Auth</a> for simple email + password login<br/>
10-
<a href="https://www.prisma.io/">Prisma</a> as the ORM, and a <a href="https://vercel.com/postgres">Vercel Postgres</a> database to persist the data.</p>
11-
12-
<br/>
3+
This is a [Next.js](https://nextjs.org/) starter kit that uses [NextAuth.js](https://next-auth.js.org/) for simple email + password login, [Drizzle](https://orm.drizzle.team) as the ORM, and a [Neon Postgres](https://vercel.com/postgres) database to persist the data.
134

145
## Deploy Your Own
156

167
You can clone & deploy it to Vercel with one click:
178

18-
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?demo-title=Next.js%20Prisma%20PostgreSQL%20Auth%20Starter&demo-description=Simple%20Next.js%2013%20starter%20kit%20that%20uses%20Next-Auth%20for%20auth%20and%20Prisma%20PostgreSQL%20as%20a%20database.&demo-url=https%3A%2F%2Fnextjs-postgres-auth.vercel.app%2F&demo-image=%2F%2Fimages.ctfassets.net%2Fe5382hct74si%2F7rsVQ1ZBSiWe9JGO6FUeZZ%2F210cba91036ca912b2770e0bd5d6cc5d%2Fthumbnail.png&project-name=Next.js%%20Prisma%20PostgreSQL%20Auth%20Starter&repository-name=nextjs-postgres-auth-starter&repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnextjs-postgres-auth-starter&from=templates&skippable-integrations=1&env=NEXTAUTH_SECRET&envDescription=Generate%20a%20random%20secret%3A&envLink=https://generate-secret.vercel.app/&stores=%5B%7B"type"%3A"postgres"%7D%5D)
9+
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?demo-title=Next.js%20Prisma%20PostgreSQL%20Auth%20Starter&demo-description=Simple%20Next.js%2013%20starter%20kit%20that%20uses%20Next-Auth%20for%20auth%20and%20Prisma%20PostgreSQL%20as%20a%20database.&demo-url=https%3A%2F%2Fnextjs-postgres-auth.vercel.app%2F&demo-image=%2F%2Fimages.ctfassets.net%2Fe5382hct74si%2F7rsVQ1ZBSiWe9JGO6FUeZZ%2F210cba91036ca912b2770e0bd5d6cc5d%2Fthumbnail.png&project-name=Next.js%%20Prisma%20PostgreSQL%20Auth%20Starter&repository-name=nextjs-postgres-auth-starter&repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fnextjs-postgres-auth-starter&from=templates&skippable-integrations=1&env=AUTH_SECRET&envDescription=Generate%20a%20random%20secret%3A&envLink=https://generate-secret.vercel.app/&stores=%5B%7B"type"%3A"postgres"%7D%5D)
1910

2011
## Developing Locally
2112

@@ -30,9 +21,7 @@ npx create-next-app nextjs-typescript-starter --example "https://github.com/verc
3021
First, run the development server:
3122

3223
```bash
33-
npm run dev
34-
# or
35-
yarn dev
24+
pnpm dev
3625
```
3726

3827
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1 @@
1-
import NextAuth, { type NextAuthOptions } from "next-auth";
2-
import CredentialsProvider from "next-auth/providers/credentials";
3-
import prisma from "@/lib/prisma";
4-
import { compare } from "bcrypt";
5-
6-
export const authOptions: NextAuthOptions = {
7-
providers: [
8-
CredentialsProvider({
9-
credentials: {
10-
email: { label: "Email", type: "email" },
11-
password: { label: "Password", type: "password" }
12-
},
13-
async authorize(credentials) {
14-
const { email, password } = credentials ?? {}
15-
if (!email || !password) {
16-
throw new Error("Missing username or password");
17-
}
18-
const user = await prisma.user.findUnique({
19-
where: {
20-
email,
21-
},
22-
});
23-
// if user doesn't exist or password doesn't match
24-
if (!user || !(await compare(password, user.password))) {
25-
throw new Error("Invalid username or password");
26-
}
27-
return user;
28-
},
29-
}),
30-
],
31-
};
32-
33-
const handler = NextAuth(authOptions);
34-
35-
export { handler as GET, handler as POST };
1+
export { GET, POST } from 'app/auth';

app/api/auth/register/route.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

app/auth.config.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { NextAuthConfig } from 'next-auth';
2+
3+
export const authConfig = {
4+
pages: {
5+
signIn: '/login',
6+
},
7+
providers: [
8+
// added later in auth.ts since it requires bcrypt which is only compatible with Node.js
9+
// while this file is also used in non-Node.js environments
10+
],
11+
callbacks: {
12+
authorized({ auth, request: { nextUrl } }) {
13+
let isLoggedIn = !!auth?.user;
14+
let isOnDashboard = nextUrl.pathname.startsWith('/protected');
15+
16+
if (isOnDashboard) {
17+
if (isLoggedIn) return true;
18+
return false; // Redirect unauthenticated users to login page
19+
} else if (isLoggedIn) {
20+
return Response.redirect(new URL('/protected', nextUrl));
21+
}
22+
23+
return true;
24+
},
25+
},
26+
} satisfies NextAuthConfig;

app/auth.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import NextAuth from 'next-auth';
2+
import Credentials from 'next-auth/providers/credentials';
3+
import { compare } from 'bcrypt-ts';
4+
import { getUser } from 'app/db';
5+
import { authConfig } from 'app/auth.config';
6+
7+
export const {
8+
handlers: { GET, POST },
9+
auth,
10+
signIn,
11+
signOut,
12+
} = NextAuth({
13+
...authConfig,
14+
providers: [
15+
Credentials({
16+
async authorize({ email, password }: any) {
17+
let user = await getUser(email);
18+
if (user.length === 0) return null;
19+
let passwordsMatch = await compare(password, user[0].password!);
20+
if (passwordsMatch) return user[0] as any;
21+
},
22+
}),
23+
],
24+
});

app/db.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { drizzle } from 'drizzle-orm/postgres-js';
2+
import { pgTable, serial, varchar } from 'drizzle-orm/pg-core';
3+
import { eq } from 'drizzle-orm';
4+
import postgres from 'postgres';
5+
import { genSaltSync, hashSync } from 'bcrypt-ts';
6+
7+
// Optionally, if not using email/pass login, you can
8+
// use the Drizzle adapter for Auth.js / NextAuth
9+
// https://authjs.dev/reference/adapter/drizzle
10+
let client = postgres(`${process.env.POSTGRES_URL!}?sslmode=require`);
11+
let db = drizzle(client);
12+
13+
let users = pgTable('User', {
14+
id: serial('id').primaryKey(),
15+
email: varchar('email', { length: 64 }),
16+
password: varchar('password', { length: 64 }),
17+
});
18+
19+
export async function getUser(email: string) {
20+
return await db.select().from(users).where(eq(users.email, email));
21+
}
22+
23+
export async function createUser(email: string, password: string) {
24+
let salt = genSaltSync(10);
25+
let hash = hashSync(password, salt);
26+
27+
return await db.insert(users).values({ email, password: hash });
28+
}

app/form.tsx

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
export function Form({
2+
action,
3+
children,
4+
}: {
5+
action: any;
6+
children: React.ReactNode;
7+
}) {
8+
return (
9+
<form
10+
action={action}
11+
className="flex flex-col space-y-4 bg-gray-50 px-4 py-8 sm:px-16"
12+
>
13+
<div>
14+
<label
15+
htmlFor="email"
16+
className="block text-xs text-gray-600 uppercase"
17+
>
18+
Email Address
19+
</label>
20+
<input
21+
id="email"
22+
name="email"
23+
type="email"
24+
placeholder="[email protected]"
25+
autoComplete="email"
26+
required
27+
className="mt-1 block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-black focus:outline-none focus:ring-black sm:text-sm"
28+
/>
29+
</div>
30+
<div>
31+
<label
32+
htmlFor="password"
33+
className="block text-xs text-gray-600 uppercase"
34+
>
35+
Password
36+
</label>
37+
<input
38+
id="password"
39+
name="password"
40+
type="password"
41+
required
42+
className="mt-1 block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-black focus:outline-none focus:ring-black sm:text-sm"
43+
/>
44+
</div>
45+
{children}
46+
</form>
47+
);
48+
}
File renamed without changes.

0 commit comments

Comments
 (0)