Skip to content

Commit

Permalink
Merge pull request #52 from chingu-voyages/user-roles
Browse files Browse the repository at this point in the history
added User model, user route & checkRole controller. Added middleware function.
  • Loading branch information
tdkent authored Nov 25, 2024
2 parents 3922dbf + af7c4bc commit 45dcf30
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 27 deletions.
3 changes: 3 additions & 0 deletions client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ Create a `.env` file in the root of the `client` directory:
```
SERVER_URL=http://localhost:4000/
NEXT_PUBLIC_LACITY_KEY=[key]
GOOGLE_CLIENT_ID=[key]
GOOGLE_CLIENT_SECRET=[key]
AUTH_SECRET=[key]
```

Note: `NEXT_PUBLIC_` is a necessary prefix for any environment variable exposed to the browser.
Expand Down
31 changes: 20 additions & 11 deletions client/app/admin-dashboard/page.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
import { Suspense } from "react";
import { CircularProgress, Typography } from "@mui/material";
import ReservationTable from "../../components/admin_dashboard/ReservationTable";
import Map from "../../components/admin_dashboard/Map";
import { getServerSession } from "next-auth";
import { authOptions } from "@/auth";
import { redirect } from "next/navigation";

export default function AdminDashboardView() {
return (
<div>
<Typography variant="h1">Reservations:</Typography>
<Suspense fallback={<CircularProgress />}>
<ReservationTable />
<Map />
</Suspense>
</div>
);
export default async function AdminDashboardView() {
const session = await getServerSession(authOptions);
if (!session) {
return <p>You must be an admin to view this page.</p>;
}
if (session.user.role === "admin") {
return (
<div>
<Typography variant="h1">Reservations:</Typography>
<Suspense fallback={<CircularProgress />}>
<ReservationTable />
</Suspense>
</div>
);
} else {
return redirect("/form");
}
}
2 changes: 1 addition & 1 deletion client/app/landingPage/page.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"use client";
"use client"

import { Stack, Typography } from "@mui/material/";
import SignInCard from "@/components/signInCard";
Expand Down
22 changes: 13 additions & 9 deletions client/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import GoogleProviders from "next-auth/providers/google";
import { serverUrl } from "./constants";
import NextAuth from "next-auth";


export const authOptions = {
// Configure one or more authentication providers
providers: [
Expand All @@ -11,8 +10,13 @@ export const authOptions = {
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
async profile(profile) {
// action to server
const res = await fetch(serverUrl + "user")
const {role} = await res.json()
const res = await fetch(serverUrl + "user", {
headers: {
"x-user-email": profile.email,
},
});
const role = await res.json();
console.log(role);
return {
id: profile.sub,
email: profile.email,
Expand All @@ -23,15 +27,15 @@ export const authOptions = {
],
callbacks: {
jwt({ token, user }) {
if(user) token.role = user.role
return token
if (user) token.role = user.role;
return token;
},
session({ session, token }) {
session.user.role = token.role
return session
}
session.user.role = token.role;
return session;
},
},
secret: process.env.AUTH_SECRET,
};

export default NextAuth(authOptions)
export default NextAuth(authOptions);
6 changes: 4 additions & 2 deletions client/components/signInCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import {
import GoogleIcon from "@mui/icons-material/Google";
import { signIn } from "next-auth/react";

export default function SignInCard() {
export default async function SignInCard() {

const handleSubmit = () => {
const profile = signIn("google")
signIn("google")
}

return (
<Card variant="outlined" sx={{ minWidth: 375, p: 2 }}>
<CardMedia
Expand Down
21 changes: 21 additions & 0 deletions client/middleware.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { NextResponse } from "next/server";
import { withAuth } from "next-auth/middleware";

export default withAuth(
// `withAuth` augments your `Request` with the user's token.
function middleware(req) {
if (req.nextauth.token.role === "admin"){
return NextResponse.redirect(new URL("/admin-dashboard", req.nextUrl));
}
else {
return NextResponse.redirect(new URL("/form", req.nextUrl));
}
},
{
callbacks: {
authorized: ({ token }) => token.id !== null,
},
}
);

export const config = { matcher: ["/landingPage"] };
7 changes: 3 additions & 4 deletions server/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import mongoose from "mongoose";
import connectDb from "./config/db.js";
import { port, dbConnectStr } from "./config/env.js";
import appointmentsRouter from "./routes/appointments.routes.js";
import userRouter from "./routes/user.route.js";

const app = express();

Expand All @@ -16,6 +17,8 @@ app.use(bodyParser.json());
//! enable all CORS requests
app.use(cors());

app.use("/user", userRouter);
app.use("/form", formRouter);
app.use("/appointments", appointmentsRouter);

app.use("/database-health", async (_, res) => {
Expand All @@ -27,10 +30,6 @@ app.use("/database-health", async (_, res) => {
}
});

app.use("/user", (req, res) => {
return res.json({ role: "admin" });
});

app.use((_, res, next) => {
res.status(404);
next({ message: "Endpoint not found" });
Expand Down
20 changes: 20 additions & 0 deletions server/src/controllers/user.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import User from "../models/user.model.js";

export async function checkRole(req, res) {
// grab currently logged in user's profile data from results
console.log(JSON.stringify(req.headers))
const email = req.headers["x-user-email"];
console.log("email:", email)
const user = await User.findOne({
email: email,
});
if (user) {
if (user.role === "admin") {
res.json(user.role);
}
}
else {
res.json({ role: "user" })
}

}
10 changes: 10 additions & 0 deletions server/src/models/user.model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import mongoose from "mongoose";

const userSchema = new mongoose.Schema({
email: String,
role: String,
});

const User = mongoose.model("User", userSchema, "users");

export default User;
8 changes: 8 additions & 0 deletions server/src/routes/user.route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Router } from "express";
import { checkRole } from "../controllers/user.controller.js";

const router = Router();

router.get("/", checkRole);

export default router;

0 comments on commit 45dcf30

Please sign in to comment.