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

Removed is_teacher and is_admin, changed to role enum #127

Merged
merged 10 commits into from
Mar 26, 2024
Merged
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
5 changes: 3 additions & 2 deletions backend/db_construct.sql
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
CREATE TYPE role AS ENUM ('STUDENT', 'TEACHER', 'ADMIN');

CREATE TYPE submission_status AS ENUM ('SUCCESS', 'LATE', 'FAIL', 'RUNNING');

CREATE TABLE users (
uid VARCHAR(255),
is_teacher BOOLEAN,
is_admin BOOLEAN,
role role NOT NULL,
PRIMARY KEY(uid)
);

Expand Down
36 changes: 12 additions & 24 deletions backend/project/endpoints/index/OpenAPI_Object.json
Original file line number Diff line number Diff line change
Expand Up @@ -1374,14 +1374,11 @@
"uid": {
"type": "string"
},
"is_teacher": {
"type": "boolean"
},
"is_admin": {
"type": "boolean"
"role": {
"type": "enum"
}
},
"required": ["uid", "is_teacher", "is_admin"]
"required": ["uid", "role"]
}
}
}
Expand All @@ -1399,14 +1396,11 @@
"uid": {
"type": "string"
},
"is_teacher": {
"type": "boolean"
},
"is_admin": {
"type": "boolean"
"role": {
"type": "enum"
}
},
"required": ["uid", "is_teacher", "is_admin"]
"required": ["uid", "role"]
}
}
}
Expand Down Expand Up @@ -1451,14 +1445,11 @@
"uid": {
"type": "string"
},
"is_teacher": {
"type": "boolean"
},
"is_admin": {
"type": "boolean"
"role": {
"type": "enum"
}
},
"required": ["uid", "is_teacher", "is_admin"]
"required": ["uid", "role"]
}
}
}
Expand Down Expand Up @@ -1487,14 +1478,11 @@
"schema": {
"type": "object",
"properties": {
"is_teacher": {
"type": "boolean"
},
"is_admin": {
"type": "boolean"
"role": {
"type": "role"
}
},
"required": ["is_teacher", "is_admin"]
"required": ["role"]
}
}
}
Expand Down
45 changes: 20 additions & 25 deletions backend/project/endpoints/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from sqlalchemy.exc import SQLAlchemyError

from project import db
from project.models.user import User as userModel
from project.models.user import User as userModel, Role
from project.utils.authentication import login_required, authorize_user, \
authorize_admin, not_allowed

Expand All @@ -29,16 +29,13 @@ def get(self):
"""
try:
query = userModel.query
is_teacher = request.args.get('is_teacher')
is_admin = request.args.get('is_admin')

if is_teacher is not None:
query = query.filter(userModel.is_teacher == (is_teacher.lower() == 'true'))

if is_admin is not None:
query = query.filter(userModel.is_admin == (is_admin.lower() == 'true'))
role = request.args.get("role")
if role is not None:
role = Role[role.upper()]
query = query.filter(userModel.role == role)

users = query.all()
users = [user.to_dict() for user in users]

result = jsonify({"message": "Queried all users", "data": users,
"url":f"{API_URL}/users", "status_code": 200})
Expand All @@ -54,26 +51,25 @@ def post(self):
It should create a new user and return a success message.
"""
uid = request.json.get('uid')
is_teacher = request.json.get('is_teacher')
is_admin = request.json.get('is_admin')
role = request.json.get("role")
role = Role[role.upper()] if role is not None else None
url = f"{API_URL}/users"

if is_teacher is None or is_admin is None or uid is None:
if role is None or uid is None:
return {
"message": "Invalid request data!",
"correct_format": {
"uid": "User ID (string)",
"is_teacher": "Teacher status (boolean)",
"is_admin": "Admin status (boolean)"
},"url": url
"role": "User role (string)"
},"url": f"{API_URL}/users"
}, 400
try:
user = db.session.get(userModel, uid)
if user is not None:
# Bad request, error code could be 409 but is rarely used
return {"message": f"User {uid} already exists"}, 400
# Code to create a new user in the database using the uid, is_teacher, and is_admin
new_user = userModel(uid=uid, is_teacher=is_teacher, is_admin=is_admin)
# Code to create a new user in the database using the uid and role
new_user = userModel(uid=uid, role=role)
db.session.add(new_user)
db.session.commit()
return jsonify({"message": "User created successfully!",
Expand All @@ -99,7 +95,7 @@ def get(self, user_id):
if user is None:
return {"message": "User not found!","url": f"{API_URL}/users"}, 404

return jsonify({"message": "User queried","data":user,
return jsonify({"message": "User queried","data":user.to_dict(),
"url": f"{API_URL}/users/{user.uid}", "status_code": 200})
except SQLAlchemyError:
return {"message": "An error occurred while fetching the user",
Expand All @@ -114,22 +110,21 @@ def patch(self, user_id):
dict: A dictionary containing the message indicating the success
or failure of the update.
"""
is_teacher = request.json.get('is_teacher')
is_admin = request.json.get('is_admin')
role = request.json.get("role")
role = Role[role.upper()] if role is not None else None
try:
user = db.session.get(userModel, user_id)
if user is None:
return {"message": "User not found!","url": f"{API_URL}/users"}, 404

if is_teacher is not None:
user.is_teacher = is_teacher
if is_admin is not None:
user.is_admin = is_admin
if role is not None:
user.role = role

# Save the changes to the database
db.session.commit()
return jsonify({"message": "User updated successfully!",
"data": user, "url": f"{API_URL}/users/{user.uid}", "status_code": 200})
"data": user.to_dict(),
"url": f"{API_URL}/users/{user.uid}", "status_code": 200})
except SQLAlchemyError:
# every exception should result in a rollback
db.session.rollback()
Expand Down
23 changes: 18 additions & 5 deletions backend/project/models/user.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
"""User model"""

from enum import Enum
from dataclasses import dataclass
from sqlalchemy import Boolean, Column, String
from sqlalchemy import Column, String, Enum as EnumField
from project.db_in import db

class Role(Enum):
"""This class defines the roles of a user"""
STUDENT = 0
TEACHER = 1
ADMIN = 2

@dataclass
class User(db.Model):
"""This class defines the users table,
a user has a uid,
is_teacher and is_admin booleans because a user
a user has a uid and a role, a user
can be either a student,admin or teacher"""

__tablename__ = "users"
uid: str = Column(String(255), primary_key=True)
is_teacher: bool = Column(Boolean)
is_admin: bool = Column(Boolean)
role: Role = Column(EnumField(Role), nullable=False)
def to_dict(self):
"""
Converts a User to a serializable dict
"""
return {
'uid': self.uid,
'role': self.role.name, # Convert the enum to a string
}
Loading