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

added User model, user route & checkRole controller. Added middleware function. #52

Merged
merged 4 commits into from
Nov 25, 2024

Conversation

jesslane94
Copy link
Contributor

Sorry for the big PR, I will try to be cognizant of that next time. Make sure you have the Google Client/Secrets I shared in Discord in your client env.

-Server:

  1. configured User model with email and role.
  2. Added user route for checking the role to our DB of the person logging in.
  3. checkRole controller for making a query to the Users collection to check if email is marked as an admin. (have to put these documents in yourself, for easy testing use my DB as your MY_TEST_DB variable in your server env file.) If they are an admin, send that back in the result, if not, set their role as "resident."

-Client:

  1. Added middleware file to redirect user during Google Auth request. Checks if token id exists, and if it does, then the function will run -> user is redirected to admin-dashboard if their role is admin, and form if it is not.
  2. The call to our server on the /user route is made in auth.js. This sends a header with the current users email to check against the database.
  3. I did wrap the admin dashboard in a wrapper based on if the current session user role is admin, although I'm sure there's a way to not have to do this with nextauth.

-To Do:

  1. Sign out button on NavBar
  2. More robust error handling/rerouting if something goes wrong. I haven't messed with it enough.
  3. As mentioned above, not sure if I need the wrapper on admin-dashboard component. need to test.

email: String,
role: String,
});

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The model should include the user's Google ID. role should probably include an enum of acceptable values "user" and "admin". There should also be a one-to-many relationship between User and Appointment established in both models.

const userSchema = new mongoose.Schema({
  googleId: { type: String, required: true },
  email: { type: String, required: true },
  role: { type: String, enum:  ["user", "admin"], required: true },
  appointments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Appointment' }]
});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh true, I think I'll change resident to just user as well. and when I was looking at your PR i thought there'd probably be overlap with appointments. Thanks for this!

);
export default async function AdminDashboardView() {
const session = await getServerSession(authOptions)
if (session.user.role == "admin") {
Copy link
Contributor

@tdkent tdkent Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use strict equality operator in JS ===

Also note that this line will crash the app if session is null. Until a redirect is in place, use conditional rendering for this scenario.

const {role} = await res.json()
const res = await fetch(serverUrl + "user", {
headers: {
"x-user-email": profile.email,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is okay for now, but it makes more sense to include the user's google id in their session, and send that to the backend to check roles, fetch forms, etc., instead of their email. Users can change the email associated with their account, but their ID is constant.

Copy link
Contributor Author

@jesslane94 jesslane94 Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! Will add in next iteration.

@@ -2,7 +2,6 @@ import GoogleProviders from "next-auth/providers/google";
import { serverUrl } from "./constants";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should probably use the server-only package to ensure it can never be exposed in the browser

else {
res.json({ role: "resident" })
}

Copy link
Contributor

@tdkent tdkent Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a good idea to wrap async methods in a try-catch to cleanly handle errors.

This method should be updated later to create a new user if they don't already exist, with a default role of "user" or "resident", and then return the entire user object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh that makes sense! Will also make a note to do.

tdkent
tdkent previously approved these changes Nov 25, 2024
Copy link
Contributor

@tdkent tdkent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, impressive work adding role-based authorization to the app! However, I am a little confused by the mix of both middleware and getServerSession hooks? Can this functionality not be consolidated into middleware.js?

I'm also a little unsure why we still have a "/landingPage" view? I have been assuming that page's content would be moved to the index route "/" and replace what's currently there. The auth form could be conditionally rendered based on whether the user has a session. This would eliminate the need for the redirect currently used in middleware.js.

@jesslane94
Copy link
Contributor Author

jesslane94 commented Nov 25, 2024

Overall, impressive work adding role-based authorization to the app! However, I am a little confused by the mix of both middleware and getServerSession hooks? Can this functionality not be consolidated into middleware.js?

I'm also a little unsure why we still have a "/landingPage" view? I have been assuming that page's content would be moved to the index route "/" and replace what's currently there. The auth form could be conditionally rendered based on whether the user has a session. This would eliminate the need for the redirect currently used in middleware.js.

Yeah, I was thinking about this (my To Do no. 3 is related)! I realized after I pushed this that the wrapper seemed a little redundant or unnecessary... It was also kind of code from when I was figuring out things to be honest! I will check if I can just take that out and let the middleware do its thing in the next sprint I suppose!

And agree on the landing page situation, I think it does need to replace the index page. Can definitely add to the list of things I/someone in the group can do!

@tdkent tdkent merged commit 45dcf30 into main Nov 25, 2024
@tdkent tdkent deleted the user-roles branch November 25, 2024 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants