Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Commit

Permalink
Removed is_teacher and is_admin, changed to role enum (#127)
Browse files Browse the repository at this point in the history
* Removed is_teacher and is_admin, changed to role enum

* sql enum type

* usage of enum and fixed sql

* made role serializable

* clean

* docs

* fixed user patch

* args vs json

* test
  • Loading branch information
JibrilExe authored Mar 26, 2024
1 parent e770091 commit 71eb3d4
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 138 deletions.
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

0 comments on commit 71eb3d4

Please sign in to comment.