diff --git a/apps/outline-vpn/.env.example b/apps/outline-vpn/.env.example new file mode 100644 index 000000000..57dd96fe0 --- /dev/null +++ b/apps/outline-vpn/.env.example @@ -0,0 +1,3 @@ +NEXT_PUBLIC_GOOGLE_CLIENT_ID= +NEXT_PUBLIC_GOOGLE_CLIENT_SECRET= +NEXT_PUBLIC_ALLOWED_EMAILS=kevin.koech@codeforafrica.org,koechkevin92@gmail.com diff --git a/apps/outline-vpn/README.md b/apps/outline-vpn/README.md index c4033664f..33320ba55 100644 --- a/apps/outline-vpn/README.md +++ b/apps/outline-vpn/README.md @@ -5,21 +5,14 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next First, run the development server: ```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev +pnpm dev --filter="outline-vpn" + ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - ## Learn More To learn more about Next.js, take a look at the following resources: @@ -28,9 +21,3 @@ To learn more about Next.js, take a look at the following resources: - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! - -## Deploy on Vercel - -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/apps/outline-vpn/package.json b/apps/outline-vpn/package.json index 2f4abf082..8e30af15a 100644 --- a/apps/outline-vpn/package.json +++ b/apps/outline-vpn/package.json @@ -17,6 +17,7 @@ "@mui/material": "^5.14.20", "@react-oauth/google": "^0.12.1", "google-auth-library": "^9.6.3", + "jwt-decode": "^4.0.0", "next": "14.1.0", "react": "^18", "react-dom": "^18" diff --git a/apps/outline-vpn/src/app/dashboard/page.tsx b/apps/outline-vpn/src/app/dashboard/page.tsx index 5cd35975a..5046b2539 100644 --- a/apps/outline-vpn/src/app/dashboard/page.tsx +++ b/apps/outline-vpn/src/app/dashboard/page.tsx @@ -1,13 +1,12 @@ import Dashboard from "@/outline-vpn/app/components/Dashboard"; import { getUsers, getHeaderProps } from "@/outline-vpn/app/data"; -import { logoutUser } from "../utils"; +import { redirect } from "next/navigation"; export async function Page(): Promise { const users = await getUsers(); const header = await getHeaderProps(); - - if (!header) { - return null; + if (!header || !users) { + return redirect("/"); } return ; } diff --git a/apps/outline-vpn/src/middleware.ts b/apps/outline-vpn/src/middleware.ts index 2f9041ed8..b3b2403ce 100644 --- a/apps/outline-vpn/src/middleware.ts +++ b/apps/outline-vpn/src/middleware.ts @@ -1,14 +1,21 @@ import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; import { cookies } from "next/headers"; +import { jwtDecode } from "jwt-decode"; +import { GoogleUser } from "@/outline-vpn/app/types"; export async function middleware(request: NextRequest) { + const allowedEmails = + process.env.NEXT_PUBLIC_ALLOWED_EMAILS?.split(",") ?? []; const url = request.nextUrl.clone(); try { const cookie = cookies().get("token") ?? {}; const { value: token } = cookie as any; - if (token) { - return NextResponse.next(); + const { email } = jwtDecode(token) as GoogleUser; + if (email) { + if (allowedEmails.includes(email)) { + return NextResponse.next(); + } } url.pathname = "/"; return NextResponse.redirect(url); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a45f09415..d7c80952a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -552,6 +552,9 @@ importers: google-auth-library: specifier: ^9.6.3 version: 9.6.3 + jwt-decode: + specifier: ^4.0.0 + version: 4.0.0 next: specifier: 14.1.0 version: 14.1.0(react-dom@18.2.0)(react@18.2.0)