aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-02-05 17:07:32 +0000
committerMohamedBassem <me@mbassem.com>2024-02-05 17:07:32 +0000
commitb7fc3344e3f3c898388831dbfad084cebdd64bb3 (patch)
treed3f5e282ad2edb001120665d3244cd623ec3e888
parent61b08abf0083f7aeb646fe588d673c72cd8b5493 (diff)
downloadkarakeep-b7fc3344e3f3c898388831dbfad084cebdd64bb3.tar.zst
Init NextAuth
-rw-r--r--.env.sample8
-rw-r--r--.gitignore3
-rw-r--r--app/api/auth/[...nextauth]/route.tsx21
-rw-r--r--app/page.tsx112
-rwxr-xr-xbun.lockbbin144265 -> 149654 bytes
-rw-r--r--components/auth/login.tsx17
-rw-r--r--components/auth/logout.tsx12
-rw-r--r--lib/config.ts20
-rw-r--r--package.json2
-rw-r--r--prisma/migrations/20240205153748_add_users/migration.sql56
-rw-r--r--prisma/migrations/migration_lock.toml3
-rw-r--r--prisma/schema.prisma45
12 files changed, 194 insertions, 105 deletions
diff --git a/.env.sample b/.env.sample
new file mode 100644
index 00000000..a48054f0
--- /dev/null
+++ b/.env.sample
@@ -0,0 +1,8 @@
+DATABASE_URL="file:./dev.db"
+NEXTAUTH_URL=
+NEXTAUTH_SECRET=
+
+# Oauth
+AUTHENTIK_ID=
+AUTHENTIK_SECRET=
+AUTHENTIK_ISSUER=
diff --git a/.gitignore b/.gitignore
index fd3dbb57..5bcde103 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts
+
+# The sqlite database
+prisma/*dev.db*
diff --git a/app/api/auth/[...nextauth]/route.tsx b/app/api/auth/[...nextauth]/route.tsx
new file mode 100644
index 00000000..b9decb30
--- /dev/null
+++ b/app/api/auth/[...nextauth]/route.tsx
@@ -0,0 +1,21 @@
+import NextAuth from "next-auth"
+import { PrismaAdapter } from "@next-auth/prisma-adapter"
+import AuthentikProvider from "next-auth/providers/authentik";
+import { PrismaClient } from "@prisma/client"
+import serverConfig from "@/lib/config";
+
+const prisma = new PrismaClient()
+
+let providers = [];
+
+if (serverConfig.auth.authentik) {
+ providers.push(AuthentikProvider(serverConfig.auth.authentik));
+}
+
+const handler = NextAuth({
+ // Configure one or more authentication providers
+ adapter: PrismaAdapter(prisma),
+ providers: providers,
+});
+
+export { handler as GET, handler as POST }
diff --git a/app/page.tsx b/app/page.tsx
index dc191aa8..2df40508 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,112 +1,14 @@
-import Image from "next/image";
+import { LoginButton } from "../components/auth/login";
+import { LogoutButton } from "../components/auth/logout";
export default function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
- <div className="z-10 max-w-5xl w-full items-center justify-between font-mono text-sm lg:flex">
- <p className="fixed left-0 top-0 flex w-full justify-center border-b border-gray-300 bg-gradient-to-b from-zinc-200 pb-6 pt-8 backdrop-blur-2xl dark:border-neutral-800 dark:bg-zinc-800/30 dark:from-inherit lg:static lg:w-auto lg:rounded-xl lg:border lg:bg-gray-200 lg:p-4 lg:dark:bg-zinc-800/30">
- Get started by editing&nbsp;
- <code className="font-mono font-bold">app/page.tsx</code>
- </p>
- <div className="fixed bottom-0 left-0 flex h-48 w-full items-end justify-center bg-gradient-to-t from-white via-white dark:from-black dark:via-black lg:static lg:h-auto lg:w-auto lg:bg-none">
- <a
- className="pointer-events-none flex place-items-center gap-2 p-8 lg:pointer-events-auto lg:p-0"
- href="https://vercel.com?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
- target="_blank"
- rel="noopener noreferrer"
- >
- By{" "}
- <Image
- src="/vercel.svg"
- alt="Vercel Logo"
- className="dark:invert"
- width={100}
- height={24}
- priority
- />
- </a>
- </div>
- </div>
-
- <div className="relative flex place-items-center before:absolute before:h-[300px] before:w-full sm:before:w-[480px] before:-translate-x-1/2 before:rounded-full before:bg-gradient-radial before:from-white before:to-transparent before:blur-2xl before:content-[''] after:absolute after:-z-20 after:h-[180px] after:w-full sm:after:w-[240px] after:translate-x-1/3 after:bg-gradient-conic after:from-sky-200 after:via-blue-200 after:blur-2xl after:content-[''] before:dark:bg-gradient-to-br before:dark:from-transparent before:dark:to-blue-700 before:dark:opacity-10 after:dark:from-sky-900 after:dark:via-[#0141ff] after:dark:opacity-40 before:lg:h-[360px] z-[-1]">
- <Image
- className="relative dark:drop-shadow-[0_0_0.3rem_#ffffff70] dark:invert"
- src="/next.svg"
- alt="Next.js Logo"
- width={180}
- height={37}
- priority
- />
- </div>
-
- <div className="mb-32 grid text-center lg:max-w-5xl lg:w-full lg:mb-0 lg:grid-cols-4 lg:text-left">
- <a
- href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
- className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2 className={`mb-3 text-2xl font-semibold`}>
- Docs{" "}
- <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
- -&gt;
- </span>
- </h2>
- <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
- Find in-depth information about Next.js features and API.
- </p>
- </a>
-
- <a
- href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
- className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2 className={`mb-3 text-2xl font-semibold`}>
- Learn{" "}
- <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
- -&gt;
- </span>
- </h2>
- <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
- Learn about Next.js in an interactive course with&nbsp;quizzes!
- </p>
- </a>
-
- <a
- href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
- className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2 className={`mb-3 text-2xl font-semibold`}>
- Templates{" "}
- <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
- -&gt;
- </span>
- </h2>
- <p className={`m-0 max-w-[30ch] text-sm opacity-50`}>
- Explore starter templates for Next.js.
- </p>
- </a>
-
- <a
- href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
- className="group rounded-lg border border-transparent px-5 py-4 transition-colors hover:border-gray-300 hover:bg-gray-100 hover:dark:border-neutral-700 hover:dark:bg-neutral-800/30"
- target="_blank"
- rel="noopener noreferrer"
- >
- <h2 className={`mb-3 text-2xl font-semibold`}>
- Deploy{" "}
- <span className="inline-block transition-transform group-hover:translate-x-1 motion-reduce:transform-none">
- -&gt;
- </span>
- </h2>
- <p className={`m-0 max-w-[30ch] text-sm opacity-50 text-balance`}>
- Instantly deploy your Next.js site to a shareable URL with Vercel.
- </p>
- </a>
+ <div>
+ <LoginButton />
+ <br />
+ <br />
+ <LogoutButton />
</div>
</main>
);
diff --git a/bun.lockb b/bun.lockb
index 5b2333a2..d92fb9ed 100755
--- a/bun.lockb
+++ b/bun.lockb
Binary files differ
diff --git a/components/auth/login.tsx b/components/auth/login.tsx
new file mode 100644
index 00000000..4cd55546
--- /dev/null
+++ b/components/auth/login.tsx
@@ -0,0 +1,17 @@
+"use client";
+import { signIn } from "next-auth/react";
+
+export const LoginButton = () => {
+ return (
+ <button
+ className="btn btn-primary"
+ onClick={() =>
+ signIn(undefined, {
+ callbackUrl: "/",
+ })
+ }
+ >
+ Sign in
+ </button>
+ );
+};
diff --git a/components/auth/logout.tsx b/components/auth/logout.tsx
new file mode 100644
index 00000000..87391c84
--- /dev/null
+++ b/components/auth/logout.tsx
@@ -0,0 +1,12 @@
+"use client";
+import { signOut } from "next-auth/react";
+
+export const LogoutButton = () => {
+ return (
+ <button className="btn btn-ghost normal-case" onClick={() => signOut({
+ callbackUrl: "/",
+ })}>
+ Sign Out
+ </button>
+ );
+};
diff --git a/lib/config.ts b/lib/config.ts
new file mode 100644
index 00000000..ef86cb5a
--- /dev/null
+++ b/lib/config.ts
@@ -0,0 +1,20 @@
+function buildAuthentikConfig() {
+ let {id, secret, issuer} = process.env;
+ if (!id || !secret || !issuer) {
+ return undefined;
+ }
+
+ return {
+ clientId: id,
+ clientSecret: secret,
+ issuer: issuer,
+ };
+}
+
+const serverConfig = {
+ auth: {
+ authentik: buildAuthentikConfig(),
+ }
+};
+
+export default serverConfig;
diff --git a/package.json b/package.json
index ae7deb01..02b42959 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,9 @@
"lint": "next lint"
},
"dependencies": {
+ "@next-auth/prisma-adapter": "^1.0.7",
"next": "14.1.0",
+ "next-auth": "^4.24.5",
"prisma": "^5.9.1",
"react": "^18",
"react-dom": "^18"
diff --git a/prisma/migrations/20240205153748_add_users/migration.sql b/prisma/migrations/20240205153748_add_users/migration.sql
new file mode 100644
index 00000000..cbf47073
--- /dev/null
+++ b/prisma/migrations/20240205153748_add_users/migration.sql
@@ -0,0 +1,56 @@
+-- CreateTable
+CREATE TABLE "Account" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "userId" TEXT NOT NULL,
+ "type" TEXT NOT NULL,
+ "provider" TEXT NOT NULL,
+ "providerAccountId" TEXT NOT NULL,
+ "refresh_token" TEXT,
+ "access_token" TEXT,
+ "expires_at" INTEGER,
+ "token_type" TEXT,
+ "scope" TEXT,
+ "id_token" TEXT,
+ "session_state" TEXT,
+ CONSTRAINT "Account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateTable
+CREATE TABLE "Session" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "sessionToken" TEXT NOT NULL,
+ "userId" TEXT NOT NULL,
+ "expires" DATETIME NOT NULL,
+ CONSTRAINT "Session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateTable
+CREATE TABLE "User" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "name" TEXT,
+ "email" TEXT,
+ "emailVerified" DATETIME,
+ "image" TEXT
+);
+
+-- CreateTable
+CREATE TABLE "VerificationToken" (
+ "identifier" TEXT NOT NULL,
+ "token" TEXT NOT NULL,
+ "expires" DATETIME NOT NULL
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Account_provider_providerAccountId_key" ON "Account"("provider", "providerAccountId");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Session_sessionToken_key" ON "Session"("sessionToken");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "VerificationToken_token_key" ON "VerificationToken"("token");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "VerificationToken_identifier_token_key" ON "VerificationToken"("identifier", "token");
diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml
new file mode 100644
index 00000000..e5e5c470
--- /dev/null
+++ b/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (i.e. Git)
+provider = "sqlite" \ No newline at end of file
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
index e0020544..0789cab8 100644
--- a/prisma/schema.prisma
+++ b/prisma/schema.prisma
@@ -9,3 +9,48 @@ datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
+
+model Account {
+ id String @id @default(cuid())
+ userId String
+ type String
+ provider String
+ providerAccountId String
+ refresh_token String?
+ access_token String?
+ expires_at Int?
+ token_type String?
+ scope String?
+ id_token String?
+ session_state String?
+
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+
+ @@unique([provider, providerAccountId])
+}
+
+model Session {
+ id String @id @default(cuid())
+ sessionToken String @unique
+ userId String
+ expires DateTime
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+}
+
+model User {
+ id String @id @default(cuid())
+ name String?
+ email String? @unique
+ emailVerified DateTime?
+ image String?
+ accounts Account[]
+ sessions Session[]
+}
+
+model VerificationToken {
+ identifier String
+ token String @unique
+ expires DateTime
+
+ @@unique([identifier, token])
+}