Isitha Tennakoon commited on
Commit
0383459
·
1 Parent(s): e398af3

Basic Key Gen Client working

Browse files
keygenServer/client/.dockerignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ node_modules
2
+ .next
3
+ .git
4
+ .env*
5
+ .dockerignore
6
+ Dockerfile
7
+ README.md
keygenServer/client/.gitignore ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2
+
3
+ # dependencies
4
+ /node_modules
5
+ /.pnp
6
+ .pnp.*
7
+ .yarn/*
8
+ !.yarn/patches
9
+ !.yarn/plugins
10
+ !.yarn/releases
11
+ !.yarn/versions
12
+
13
+ # testing
14
+ /coverage
15
+
16
+ # next.js
17
+ /.next/
18
+ /out/
19
+
20
+ # production
21
+ /build
22
+
23
+ # misc
24
+ .DS_Store
25
+ *.pem
26
+
27
+ # debug
28
+ npm-debug.log*
29
+ yarn-debug.log*
30
+ yarn-error.log*
31
+ .pnpm-debug.log*
32
+
33
+ # env files (can opt-in for committing if needed)
34
+ .env*
35
+
36
+ # vercel
37
+ .vercel
38
+
39
+ # typescript
40
+ *.tsbuildinfo
41
+ next-env.d.ts
keygenServer/client/Dockerfile ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Build stage
2
+ FROM node:20-alpine AS builder
3
+
4
+ WORKDIR /app
5
+
6
+ # Copy package files
7
+ COPY package*.json ./
8
+
9
+ # Install dependencies
10
+ RUN npm ci
11
+
12
+ # Copy source code
13
+ COPY . .
14
+
15
+ # Build application
16
+ RUN npm run build
17
+
18
+ # Production stage
19
+ FROM node:20-alpine AS runner
20
+
21
+ WORKDIR /app
22
+
23
+ # Set to production environment
24
+ ENV NODE_ENV=production
25
+
26
+ # Copy necessary files from builder
27
+ COPY --from=builder /app/package*.json ./
28
+ COPY --from=builder /app/.next ./.next
29
+ COPY --from=builder /app/public ./public
30
+ COPY --from=builder /app/next.config.ts ./
31
+
32
+ # Install production dependencies only
33
+ RUN npm ci --omit=dev
34
+
35
+ # Expose the port Next.js runs on
36
+ EXPOSE 3000
37
+
38
+ # Start the application
39
+ CMD ["npm", "start"]
keygenServer/client/README.md ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
2
+
3
+ ## Getting Started
4
+
5
+ First, run the development server:
6
+
7
+ ```bash
8
+ npm run dev
9
+ # or
10
+ yarn dev
11
+ # or
12
+ pnpm dev
13
+ # or
14
+ bun dev
15
+ ```
16
+
17
+ Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18
+
19
+ You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
20
+
21
+ This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
22
+
23
+ ## Learn More
24
+
25
+ To learn more about Next.js, take a look at the following resources:
26
+
27
+ - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28
+ - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29
+
30
+ You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
31
+
32
+ ## Deploy on Vercel
33
+
34
+ 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.
35
+
36
+ Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
keygenServer/client/app/favicon.ico ADDED
keygenServer/client/app/globals.css ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import "tailwindcss";
2
+
3
+ :root {
4
+ --background: #ffffff;
5
+ --foreground: #171717;
6
+ }
7
+
8
+ @theme inline {
9
+ --color-background: var(--background);
10
+ --color-foreground: var(--foreground);
11
+ --font-sans: var(--font-geist-sans);
12
+ --font-mono: var(--font-geist-mono);
13
+ }
14
+
15
+ @media (prefers-color-scheme: dark) {
16
+ :root {
17
+ --background: #0a0a0a;
18
+ --foreground: #ededed;
19
+ }
20
+ }
21
+
22
+ body {
23
+ background: var(--background);
24
+ color: var(--foreground);
25
+ font-family: Arial, Helvetica, sans-serif;
26
+ }
keygenServer/client/app/layout.tsx ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Metadata } from "next";
2
+ import { Geist, Geist_Mono } from "next/font/google";
3
+ import "./globals.css";
4
+
5
+ const geistSans = Geist({
6
+ variable: "--font-geist-sans",
7
+ subsets: ["latin"],
8
+ });
9
+
10
+ const geistMono = Geist_Mono({
11
+ variable: "--font-geist-mono",
12
+ subsets: ["latin"],
13
+ });
14
+
15
+ export const metadata: Metadata = {
16
+ title: "Create Next App",
17
+ description: "Generated by create next app",
18
+ };
19
+
20
+ export default function RootLayout({
21
+ children,
22
+ }: Readonly<{
23
+ children: React.ReactNode;
24
+ }>) {
25
+ return (
26
+ <html lang="en">
27
+ <body
28
+ className={`${geistSans.variable} ${geistMono.variable} antialiased`}
29
+ >
30
+ {children}
31
+ </body>
32
+ </html>
33
+ );
34
+ }
keygenServer/client/app/main/page.tsx ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client';
2
+ import { useEffect, useState } from 'react';
3
+ import { auth } from '@/lib/firebase';
4
+ import { useRouter } from 'next/navigation';
5
+
6
+ export default function MainPage() {
7
+ const [loading, setLoading] = useState(true);
8
+ const [userEmail, setUserEmail] = useState('');
9
+ const [userDisplayName, setUserDisplayName] = useState('');
10
+ const [apiKey, setApiKey] = useState('');
11
+ const [error, setError] = useState('');
12
+ const router = useRouter();
13
+
14
+ useEffect(() => {
15
+ const unsub = auth.onAuthStateChanged((user) => {
16
+ if (!user) {
17
+ router.push('/');
18
+ } else {
19
+ setUserEmail(user.email || 'Unknown user');
20
+ setUserDisplayName(user.displayName || 'Unknown user');
21
+ setLoading(false);
22
+ }
23
+ });
24
+ return () => unsub();
25
+ }, []);
26
+
27
+ const generateApiKey = async () => {
28
+ try {
29
+ const response = await fetch('http://localhost:3001/api/addKey', {
30
+ method: 'POST',
31
+ headers: {
32
+ 'Content-Type': 'application/json',
33
+ },
34
+ body: JSON.stringify({ email: userEmail }),
35
+ });
36
+
37
+ if (!response.ok) {
38
+ throw new Error('Failed to generate API key');
39
+ }
40
+
41
+ const data = await response.json();
42
+ setApiKey(data.apiKey);
43
+ setError('');
44
+ } catch (err) {
45
+ setError('Failed to generate API key');
46
+ console.error('Error:', err);
47
+ }
48
+ };
49
+
50
+ if (loading) return <p>Loading...</p>;
51
+
52
+ return (
53
+ <main className="p-4">
54
+ <h1 className="text-xl mb-4">Welcome, {userDisplayName}!</h1>
55
+
56
+ <div className="space-y-4">
57
+ <button
58
+ onClick={generateApiKey}
59
+ className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
60
+ >
61
+ Generate API Key
62
+ </button>
63
+
64
+ {apiKey && (
65
+ <div className="mt-4 p-4 bg-gray-100 rounded">
66
+ <p className="font-semibold">Your API Key:</p>
67
+ <code className="block mt-2 p-2 bg-white rounded border">{apiKey}</code>
68
+ </div>
69
+ )}
70
+
71
+ {error && (
72
+ <div className="mt-4 p-4 bg-red-100 text-red-700 rounded">
73
+ {error}
74
+ </div>
75
+ )}
76
+
77
+ <button
78
+ onClick={() => auth.signOut().then(() => router.push('/'))}
79
+ className="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded"
80
+ >
81
+ Logout
82
+ </button>
83
+ </div>
84
+ </main>
85
+ );
86
+ }
keygenServer/client/app/middleware.ts ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ // middleware.ts
2
+ import { NextRequest, NextResponse } from 'next/server';
3
+
4
+ export function middleware(req: NextRequest) {
5
+ const isAuth = req.cookies.get('auth')?.value;
6
+ if (!isAuth && req.nextUrl.pathname.startsWith('/main')) {
7
+ return NextResponse.redirect(new URL('/', req.url));
8
+ }
9
+ }
keygenServer/client/app/page.tsx ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client';
2
+ import { auth, googleProvider } from '@/lib/firebase';
3
+ import { signInWithPopup } from 'firebase/auth';
4
+ import { useRouter } from 'next/navigation';
5
+
6
+ export default function LoginPage() {
7
+ const router = useRouter();
8
+
9
+ const signInWithGoogle = async () => {
10
+ try {
11
+ await signInWithPopup(auth, googleProvider);
12
+ router.push('/main');
13
+ } catch (err) {
14
+ alert('Login failed');
15
+ console.error(err);
16
+ }
17
+ };
18
+
19
+ return (
20
+ <main className="p-4">
21
+ <h1 className="text-xl mb-4">Sign In</h1>
22
+ <button onClick={signInWithGoogle} className="bg-blue-500 text-white px-4 py-2 rounded">
23
+ Sign in with Google
24
+ </button>
25
+ </main>
26
+ );
27
+ }
28
+
keygenServer/client/eslint.config.mjs ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { dirname } from "path";
2
+ import { fileURLToPath } from "url";
3
+ import { FlatCompat } from "@eslint/eslintrc";
4
+
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+
8
+ const compat = new FlatCompat({
9
+ baseDirectory: __dirname,
10
+ });
11
+
12
+ const eslintConfig = [
13
+ ...compat.extends("next/core-web-vitals", "next/typescript"),
14
+ ];
15
+
16
+ export default eslintConfig;
keygenServer/client/next.config.ts ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import type { NextConfig } from "next";
2
+
3
+ const nextConfig: NextConfig = {
4
+ /* config options here */
5
+ };
6
+
7
+ export default nextConfig;
keygenServer/client/package.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "client",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start",
9
+ "lint": "next lint"
10
+ },
11
+ "dependencies": {
12
+ "firebase": "^11.9.0",
13
+ "next": "15.3.3",
14
+ "react": "^19.0.0",
15
+ "react-dom": "^19.0.0"
16
+ },
17
+ "devDependencies": {
18
+ "@eslint/eslintrc": "^3",
19
+ "@tailwindcss/postcss": "^4",
20
+ "@types/node": "^20",
21
+ "@types/react": "^19",
22
+ "@types/react-dom": "^19",
23
+ "eslint": "^9",
24
+ "eslint-config-next": "15.3.3",
25
+ "tailwindcss": "^4",
26
+ "typescript": "^5"
27
+ }
28
+ }
keygenServer/client/postcss.config.mjs ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ const config = {
2
+ plugins: ["@tailwindcss/postcss"],
3
+ };
4
+
5
+ export default config;
keygenServer/client/tsconfig.json ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "preserve",
15
+ "incremental": true,
16
+ "plugins": [
17
+ {
18
+ "name": "next"
19
+ }
20
+ ],
21
+ "paths": {
22
+ "@/*": ["./*"]
23
+ }
24
+ },
25
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26
+ "exclude": ["node_modules"]
27
+ }
keygenServer/client/yarn.lock ADDED
The diff for this file is too large to render. See raw diff