Skip to content

RBAC System#10

Open
cadencheng888 wants to merge 4 commits intomainfrom
feature/rbac-system
Open

RBAC System#10
cadencheng888 wants to merge 4 commits intomainfrom
feature/rbac-system

Conversation

@cadencheng888
Copy link
Collaborator

@cadencheng888 cadencheng888 commented Mar 2, 2026

Describe your changes

Implements role-based access control system to assign users the right roles that contain the right permissions.

Issue ticket number and link

#10

Checklist before requesting a review

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • I tested my code by adding unit tests
  • I tested my code by adding integration tests
  • This change requires a documentation update

Copy link
Collaborator

@arnavjk007 arnavjk007 left a comment

Choose a reason for hiding this comment

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

This is a good starting point, but we need to also implement the permissions and a getSession() function that can be called from all services which will return true or false if they are allowed to use that service. For example, a viewer should NOT be able to delete items or listings so if they call a DELETE api for those services, it should not work since our getSession() will say that they do not have perms. More detailsare in the notion task

Copy link
Collaborator

@arnavjk007 arnavjk007 left a comment

Choose a reason for hiding this comment

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

Look at comments

lib/rbac.ts Outdated
}

await connectToDatabase();
const user = await User.findOne({ email: session.user.email });
Copy link
Collaborator

Choose a reason for hiding this comment

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

If we do use the User schema, how would we verify that the person is from UCSD? The Google sign in was one way, but we may have to modify the User DB as well to verify that the user is from UCSD.

Copy link
Collaborator

Choose a reason for hiding this comment

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

also add .lean() at the end

models/User.ts Outdated
first: string;
last: string;
};
permissions: Role[];
Copy link
Collaborator

Choose a reason for hiding this comment

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

we can have this as role: Role

models/User.ts Outdated
// mongoose schema to valid the data
const userSchema = new Schema<IUser>({

ucsdId: { type: String }, // ucsd pid
Copy link
Collaborator

Choose a reason for hiding this comment

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

needs some restrictions like this:
ucsdId: { type: String, required: true, unique: true },

models/User.ts Outdated

labs: [
{
labId: { type: String, required: true },
Copy link
Collaborator

Choose a reason for hiding this comment

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

We have a labs table so this should be, labId: { type: Schema.Types.ObjectId, ref: "Lab", required: true },

models/User.ts Outdated
notificationPreferences: { // default notification preferences
email: { type: Boolean, default: true },
inApp: { type: Boolean, default: true },
sms: { type: Boolean, default: true },
Copy link
Collaborator

Choose a reason for hiding this comment

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

we can turn off sms by default

models/User.ts Outdated
safety: {
trainingCompleted: string[];
clearanceLevel: string;
lastReviwedAt: Date;
Copy link
Collaborator

Choose a reason for hiding this comment

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

typo

models/User.ts Outdated

// describes what one lab membership looks like
export interface ILabMembership {
labId: string;
Copy link
Collaborator

Choose a reason for hiding this comment

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

we have a lab schema and table so it should reference that like: labId: { type: Schema.Types.ObjectId, ref: "Lab", required: true },

lib/rbac.ts Outdated
const session = await auth();

if (!session?.user?.email) {
return { allowed: false, user: null };
Copy link
Collaborator

Choose a reason for hiding this comment

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

is it possible to add a "reason" field so when there is an error we know why it erroed? like here its unauthenticated

Copy link
Collaborator

@arnavjk007 arnavjk007 left a comment

Choose a reason for hiding this comment

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

Some changes to user schema to check for @UCSD in email. Also add unit tests for the user creation, deletion.. etc. Remember to do git pull from main and git merge main before doing unit tests.

Also major change, we need GET POST PUT and DELETE for users so we would have to create a service file and route file like:
app/api/user/route.ts & services/user/uses.ts

import mongoose, { Schema, Document, Types } from "mongoose";

export type Role = "PI" | "LAB_MANAGER" | "RESEARCHER" | "VIEWER";

Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: we can have this setup for status as well like export type Status = "ACTIVE" | "INACTIVE" | "SUSPENDED";

department: string;
phone: string;
}
status: "ACTIVE" | "INACTIVE" | "SUSPENDED";
Copy link
Collaborator

Choose a reason for hiding this comment

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

status: Status

const userSchema = new Schema<IUser>({

ucsdId: { type: String, required: true, unique: true }, // ucsd pid
email: { type: String, required: true, unique: true }, // ucsd email
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should check here if the email is @UCSD domain by using regex and match like this:
email: {
type: String,
required: true,
unique: true,
lowercase: true,
trim: true,
match: [/^\S+@ucsd.edu$/, "Must be a valid UCSD email (@ucsd.edu)"],
},

{
timestamps: true,
});

Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's also add a index so we can query by labId and get all users in that lab.
userSchema.index({ "labs.labId": 1 });

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