Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

utd student updates #129

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET= # Linux: `openssl rand -hex 32` or go to https://generate-secret.now.sh/32

KEYCLOAK_BASE_URL=
KEYCLOAK_REALM=
KEYCLOAK_CLIENT_ID=
KEYCLOAK_CLIENT_SECRET=
DATABASE_URL="file:./dev.db"
JWT_SECRET=""
API_URL="http://localhost:3000"
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ yarn dev
pnpm dev
```

Create a .env file and fill it with the your desired values. Ensure you edit the values in userStore.json to ensure that the jwt values can be interpreted with your JWT_SECRET.

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ services:
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_PASSWORD=password
volumes:
- db:/var/lib/postgresql/data
ports:
Expand Down
3,899 changes: 2,589 additions & 1,310 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,35 @@
"@fullcalendar/react": "^6.1.6",
"@fullcalendar/timegrid": "^6.1.6",
"@prisma/client": "^4.15.0",
"@types/react": "18.2.15",
"@types/react-dom": "18.0.11",
"eslint": "8.45.0",
"eslint-config-next": "13.4.12",
"formik": "^2.4.2",
"next": "13.4.1",
"jose": "^5.9.6",
"jsonwebtoken": "^9.0.2",
"jwt-decode": "^4.0.0",
"next": "^13.5.6",
"next-auth": "^4.22.1",
"nookies": "^2.5.2",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-toastify": "^9.1.3",
"zod-formik-adapter": "^1.2.0"
},
"devDependencies": {
"@acadarena/zod-prisma": "github:AcadArena/zod-prisma",
"@types/jsonwebtoken": "^9.0.7",
"@types/luxon": "^3.3.0",
"@types/node": "^18.16.18",
"@types/node": "18.19.67",
"@types/react": "18.3.12",
"autoprefixer": "^10.4.14",
"eslint-config-prettier": "^8.8.0",
"postcss": "^8.4.21",
"prisma": "^4.13.0",
"rrule": "^2.7.2",
"tailwindcss": "^3.3.2",
"ts-node": "^10.9.1",
"typescript": "^5.0.4"
"typescript": "5.7.2"
},
"prisma": {
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts"
Expand Down
Binary file added public/images/GBRYDp1akAA-ggX.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/TheLab_ms_bw2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/TheLab_ms_matrix2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 28 additions & 28 deletions public/images/glider.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 18 additions & 18 deletions src/components/access-denied.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { signIn } from "next-auth/react"
import Link from "next/link"
import Link from 'next/link';

export default function AccessDenied() {
return (
<>
<h1>Access Denied</h1>
<p>
<Link
href="/api/auth/signin"
onClick={(e) => {
e.preventDefault()
signIn()
}}
>
You must be signed in to view this page
</Link>
</p>
</>
)
console.log('Access Denied!!!!');
return (
<>
<h1>Access Denied</h1>
<p>
<Link
href="#"
onClick={(e) => {
e.preventDefault();
// Link to signin page
}}
>
You must be signed in to view this page
</Link>
</p>
</>
);
}
81 changes: 62 additions & 19 deletions src/components/header.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,43 @@
import Link from 'next/link';
import { useSession, signIn, signOut } from 'next-auth/react';
import Image from 'next/image';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faFacebookF, faMeetup, faTwitter, faLinkedinIn } from "@fortawesome/free-brands-svg-icons";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
faFacebookF,
faMeetup,
faTwitter,
faLinkedinIn,
} from '@fortawesome/free-brands-svg-icons';
import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import { fetchUser, handleSignIn, handleSignOut } from '../helpers/auth';

interface HeaderProps {
title: string;
}

export default function Header(props: HeaderProps) {
const { data: session } = useSession();
const [user, setUser] = useState<{ name: string; id: string } | null>(null);
const router = useRouter();

useEffect(() => {
const fetchData = async () => {
const userData = await fetchUser();
setUser(userData);
};
fetchData();
}, []);

const signIn = async () => {
router.push('/login');
};

const signOut = async () => {
if (await handleSignOut()) {
setUser(null);
router.push('/login');
}
};

return (
<header>
<nav
Expand All @@ -28,28 +56,43 @@ export default function Header(props: HeaderProps) {
/>
</Link>
</div>
<div className="lg:flex lg:flex lg:justify-center">
<div className="lg:flex lg:justify-center">
<div className="flex items-center">
{session ? (
<span className="text-sm font-semibold leading-6 text-gray-900 mr-3">
Welcome {session.user.name.split(' ')[0]},{' '}
<button onClick={() => signOut()}>Log out</button>
</span>
) : (
<span className="text-sm font-semibold leading-6 text-gray-900 mr-3">
Welcome Guest, <button onClick={() => signIn("keycloak")}>Log in</button>
</span>
)}
<a href="https://www.facebook.com/thelabms" className="text-gray-900 mr-2">
<span className="text-sm font-semibold leading-6 text-gray-900 mr-3">
{user ? (
<span className="text-sm font-semibold leading-6 text-gray-900 mr-3">
Welcome {user.name},{' '}
<button onClick={signOut}>Log out</button>
</span>
) : (
<span className="text-sm font-semibold leading-6 text-gray-900 mr-3">
Welcome Guest, <button onClick={signIn}>Log in</button>
</span>
)}
</span>

<a
href="https://www.facebook.com/thelabms"
className="text-gray-900 mr-2"
>
<FontAwesomeIcon icon={faFacebookF} />
</a>
<a href="https://www.meetup.com/thelab-ms" className="text-gray-900 mr-2">
<a
href="https://www.meetup.com/thelab-ms"
className="text-gray-900 mr-2"
>
<FontAwesomeIcon icon={faMeetup} />
</a>
<a href="https://twitter.com/thelab_ms" className="text-gray-900 mr-2">
<a
href="https://twitter.com/thelab_ms"
className="text-gray-900 mr-2"
>
<FontAwesomeIcon icon={faTwitter} />
</a>
<a href="https://www.linkedin.com/company/thelab-ms" className="text-gray-900 mr-2">
<a
href="https://www.linkedin.com/company/thelab-ms"
className="text-gray-900 mr-2"
>
<FontAwesomeIcon icon={faLinkedinIn} />
</a>
</div>
Expand Down
30 changes: 14 additions & 16 deletions src/components/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import type { ReactNode } from "react"
import Header from "./header"
import { ToastContainer } from "react-toastify";
import type { ReactNode } from 'react';
import Header from './header';
import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';

interface LayoutProps {
children: ReactNode;
headerText: string;
children: ReactNode;
headerText: string;
}

export default function Layout({ children, headerText }: LayoutProps) {
return (
<div className="mx-10">
<Header title={headerText} />
<div className="flex flex-col mx-auto" id="contents">
{children}
</div>
<ToastContainer />
</div>
)
return (
<div className="mx-10">
<Header title={headerText} />
<div className="flex flex-col mx-auto" id="contents">
{children}
</div>
<ToastContainer />
</div>
);
}
63 changes: 63 additions & 0 deletions src/helpers/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useRouter } from 'next/router';

// Fetch user session information
export const fetchUser = async () => {
try {
const response = await fetch('/api/auth/session', {
credentials: 'include',
});
if (response.ok) {
const data = await response.json();
return data.user;
}
} catch (error) {
console.error("Couldn't fetch user:", error);
}
return null;
};

// Handle user sign-in with fob ID
export const handleSignIn = async (fobid: string) => {
if (!fobid) {
alert('Fob ID is required for login.');
return;
}

try {
const response = await fetch('/api/kiosk/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify({ fobid: parseInt(fobid) }),
});

if (response.ok) {
// alert('Login successful!');
return true;
} else {
// ('Login failed. Please check your fob ID and try again.');
}
} catch (error) {
console.error('Error during login:', error);
alert('An error occurred during login. Please try again later.');
}
return false;
};

// Handle user sign-out
export const handleSignOut = async () => {
try {
const response = await fetch('/api/auth/signout', {
method: 'POST',
credentials: 'include',
});
if (response.ok) {
return true;
} else {
console.error('Sign out failed:', response.statusText);
}
} catch (error) {
console.error('Error signing out:', error);
}
return false;
};
Loading
Loading