From 47eaac76ff32b0f4e336da2d60782f03f7bc4c67 Mon Sep 17 00:00:00 2001
From: Po-Chun Chiu <57251712+EiffelFly@users.noreply.github.com>
Date: Fri, 22 Sep 2023 16:59:02 +0800
Subject: [PATCH] feat(auth): Unauthenticated user will be block by our
auth-guard (#555)
Because
- User without authenticated can not use the services
This commit
- Unauthenticated user will be block by our auth-guard
---
public/images/auth-page-bg-strip.svg | 40 +++++++++++
src/components/AuthPageBase.tsx | 65 ++++++++++++++++++
src/components/LoginForm.tsx | 78 ++++++++++++++++++++++
src/components/index.ts | 2 +
src/lib/auth/index.ts | 1 +
src/lib/auth/withMiddlewareAuthRequired.ts | 67 +++++++++++++++++++
src/lib/index.ts | 1 +
src/middleware.ts | 13 ++++
src/pages/login.tsx | 25 +++++++
9 files changed, 292 insertions(+)
create mode 100644 public/images/auth-page-bg-strip.svg
create mode 100644 src/components/AuthPageBase.tsx
create mode 100644 src/components/LoginForm.tsx
create mode 100644 src/lib/auth/index.ts
create mode 100644 src/lib/auth/withMiddlewareAuthRequired.ts
create mode 100644 src/middleware.ts
create mode 100644 src/pages/login.tsx
diff --git a/public/images/auth-page-bg-strip.svg b/public/images/auth-page-bg-strip.svg
new file mode 100644
index 0000000000..83984675e3
--- /dev/null
+++ b/public/images/auth-page-bg-strip.svg
@@ -0,0 +1,40 @@
+
+
+
\ No newline at end of file
diff --git a/src/components/AuthPageBase.tsx b/src/components/AuthPageBase.tsx
new file mode 100644
index 0000000000..93bf9eb743
--- /dev/null
+++ b/src/components/AuthPageBase.tsx
@@ -0,0 +1,65 @@
+import { Logo } from "@instill-ai/design-system";
+import Image from "next/image";
+
+export const AuthPageBase = ({ children }: { children: React.ReactNode }) => {
+ return
{children}
;
+};
+
+const Container = ({ children }: { children: React.ReactNode }) => {
+ return {children}
;
+};
+
+const Content = ({ children }: { children: React.ReactNode }) => {
+ return (
+
+
+
+
+
+
+
+
+ Meet{" "}
+
+ Instill Cloud
+
+
+
+ The Backbone for All Your AI Needs
+
+
+
+ A no-code/low-code platform to build AI-first applications to
+ process your text, image, video and audio in minutes
+
+
+
+
+
+
+ © Instill AI 2023
+
+
+
+
+
+
+
+ );
+};
+
+AuthPageBase.Container = Container;
+AuthPageBase.Content = Content;
diff --git a/src/components/LoginForm.tsx b/src/components/LoginForm.tsx
new file mode 100644
index 0000000000..02f4747bfd
--- /dev/null
+++ b/src/components/LoginForm.tsx
@@ -0,0 +1,78 @@
+import { Button, Form, Input } from "@instill-ai/design-system";
+import * as z from "zod";
+import { useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
+
+const LoginFormSchema = z.object({
+ username: z.string(),
+ password: z.string(),
+});
+
+export const LoginForm = () => {
+ const form = useForm>({
+ resolver: zodResolver(LoginFormSchema),
+ });
+
+ function onSubmit(data: z.infer) {
+ alert(JSON.stringify(data));
+ }
+
+ return (
+
+
+
+ );
+};
diff --git a/src/components/index.ts b/src/components/index.ts
index 5b98ccf670..1ca842d8f1 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -1,5 +1,7 @@
+export * from "./AuthPageBase";
export * from "./ConsoleCorePageHead";
export * from "./Sidebar";
export * from "./ErrorBoundary";
+export * from "./LoginForm";
export * from "./ModelReadmeMarkdown";
export * from "./OnboardingForm";
diff --git a/src/lib/auth/index.ts b/src/lib/auth/index.ts
new file mode 100644
index 0000000000..0c92cb7c95
--- /dev/null
+++ b/src/lib/auth/index.ts
@@ -0,0 +1 @@
+export * from "./withMiddlewareAuthRequired";
diff --git a/src/lib/auth/withMiddlewareAuthRequired.ts b/src/lib/auth/withMiddlewareAuthRequired.ts
new file mode 100644
index 0000000000..faf40016eb
--- /dev/null
+++ b/src/lib/auth/withMiddlewareAuthRequired.ts
@@ -0,0 +1,67 @@
+import { NextMiddleware, NextResponse } from "next/server";
+
+export type WithMiddlewareAuthRequiredOptions = {
+ middleware?: NextMiddleware;
+};
+
+export function withMiddlewareAuthRequired(
+ props?: NextMiddleware | WithMiddlewareAuthRequiredOptions
+): NextMiddleware {
+ return async function wrappedMiddleware(...args) {
+ const [req] = args;
+ let middleware: NextMiddleware | undefined;
+ const { pathname, origin } = req.nextUrl;
+
+ if (typeof props === "function") {
+ middleware = props;
+ } else if (props?.middleware) {
+ middleware = props.middleware;
+ }
+
+ const ignorePaths = ["/_next", "/favicon.ico"];
+ if (ignorePaths.some((p) => pathname.startsWith(p))) {
+ return;
+ }
+
+ const authRes = NextResponse.next();
+ const sessionCookie = req.cookies.get("instill-ai-session");
+ const session = JSON.parse(sessionCookie?.value || "{}");
+
+ if (!session.access_token) {
+ if (pathname.startsWith("/api")) {
+ return NextResponse.json(
+ {
+ error: "not_authenticated",
+ description:
+ "The user does not have an active session or is not authenticated",
+ },
+ { status: 401 }
+ );
+ }
+ return NextResponse.redirect(new URL("/login", origin));
+ }
+
+ const providedMiddlewareRes = await (middleware && middleware(...args));
+
+ if (providedMiddlewareRes) {
+ const nextRes = new NextResponse(
+ providedMiddlewareRes.body,
+ providedMiddlewareRes
+ );
+ const cookies = authRes.cookies.getAll();
+ if ("cookies" in providedMiddlewareRes) {
+ for (const cookie of providedMiddlewareRes.cookies.getAll()) {
+ nextRes.cookies.set(cookie);
+ }
+ }
+ for (const cookie of cookies) {
+ if (!nextRes.cookies.get(cookie.name)) {
+ nextRes.cookies.set(cookie);
+ }
+ }
+ return nextRes;
+ } else {
+ return authRes;
+ }
+ };
+}
diff --git a/src/lib/index.ts b/src/lib/index.ts
index 852b0a5577..b6d432a3b5 100644
--- a/src/lib/index.ts
+++ b/src/lib/index.ts
@@ -1,2 +1,3 @@
+export * from "./auth";
export * from "./mgmtRoleOptions";
export * from "./useTrackingToken";
diff --git a/src/middleware.ts b/src/middleware.ts
new file mode 100644
index 0000000000..49aa953454
--- /dev/null
+++ b/src/middleware.ts
@@ -0,0 +1,13 @@
+import { withMiddlewareAuthRequired } from "./lib";
+
+export default withMiddlewareAuthRequired();
+
+export const config = {
+ matcher: [
+ "/resources/:path*",
+ "/dashboard/:path*",
+ "/model-hub/:path*",
+ "/pipelines/:path*",
+ "/settings/:path*",
+ ],
+};
diff --git a/src/pages/login.tsx b/src/pages/login.tsx
new file mode 100644
index 0000000000..2e68dce9d8
--- /dev/null
+++ b/src/pages/login.tsx
@@ -0,0 +1,25 @@
+import { NextPageWithLayout } from "./_app";
+import { AuthPageBase, LoginForm } from "@/components";
+
+const LoginPage: NextPageWithLayout = () => {
+ return (
+
+
+ Login
+
+
+
+ );
+};
+
+LoginPage.getLayout = (page) => {
+ return (
+
+
+ {page}
+
+
+ );
+};
+
+export default LoginPage;