diff --git a/django_project/myapp/templates/myapp/account.html b/django_project/myapp/templates/myapp/account.html index 8df43ed821325b1807c9bc7c046f364ceef7070e..aab98147dea2c8fe93ee2db170b032e35ef52b90 100644 --- a/django_project/myapp/templates/myapp/account.html +++ b/django_project/myapp/templates/myapp/account.html @@ -6,6 +6,7 @@ <h1>Account Page</h1> <p>Username: {{ user.username }}</p> <p>Email: {{ user.email }}</p> + <p>StudentId: {{user.studentid}}</p> <p><a href="{% url 'delete_account' %}">Delete Account</a></p> <p><a href="{% url 'logout' %}">Logout</a></p> {% endblock %} diff --git a/django_project/myapp/templates/myapp/register.html b/django_project/myapp/templates/myapp/register.html index 9bcfe10ab406c074ebc6ff3f36f843b265355a3b..f8943b581693736ee69a38857bc9b5ac4b74ffc5 100644 --- a/django_project/myapp/templates/myapp/register.html +++ b/django_project/myapp/templates/myapp/register.html @@ -27,6 +27,9 @@ <label for="id_password">Password:</label> <input type="password" name="password" id="id_password" required><br><br> + <label for="id_studentid">studentid:</label> + <input type="studentid" name="studentid" id="id_studentid" required><br><br> + <button type="submit">Register</button> </form> <p> diff --git a/django_project/myapp/views.py b/django_project/myapp/views.py index d5bf055563aaf9b4ed2c85aa5a81373045c59d10..68e6b173e844d50a5b45a1ed2b9b2d28d4636b4b 100644 --- a/django_project/myapp/views.py +++ b/django_project/myapp/views.py @@ -17,8 +17,8 @@ def init_db_view(request): def register_view(request): """ - Handles user registration. Expects POST with 'name', 'email', and 'password'. - Calls the Rust extension to create the user and then redirects to the login page. + Handles user registration. Expects POST with + 'name', 'email', 'password', 'username', and 'studentid'. """ db_url = settings.DATABASE_URL # Defined in settings.py context = {} @@ -28,22 +28,34 @@ def register_view(request): email = request.POST.get('email', '').strip() password = request.POST.get('password', '').strip() username = request.POST.get('username', '').strip() - if not name or not email or not password: - context['error'] = "Name, email, username and password are required." + studentid_str = request.POST.get('studentid', '').strip() + + # 1. Check required fields + if not all([name, email, password, username, studentid_str]): + context['error'] = "Name, email, username, student ID, and password are required." return render(request, 'myapp/register.html', context) - + + # 2. Try converting studentid to int try: - # Create the user with the hashed password via the Rust extension. - rust_crud_api.create_user(db_url, name, email, password, username) - # Redirect to the login page after successful registration. + studentid = int(studentid_str) + except ValueError: + context['error'] = "Student ID must be an integer." + return render(request, 'myapp/register.html', context) + + # 3. If the parse succeeded, call create_user in Rust + try: + rust_crud_api.create_user(db_url, name, email, password, username, studentid) + # 4. Redirect on success return redirect('login') except Exception as e: context['error'] = f"An error occurred: {str(e)}" return render(request, 'myapp/register.html', context) + # If GET or anything else, just render the registration page. return render(request, 'myapp/register.html', context) + def login_view(request): """ Handles user login by verifying credentials using the Rust extension. diff --git a/rust_crud_api/src/db/groups.rs b/rust_crud_api/src/db/groups.rs index 3425e87583d1b5dc0034022e07374e0c23181fa1..73e349227711c35c6b813a32b1e2135a678ff09f 100644 --- a/rust_crud_api/src/db/groups.rs +++ b/rust_crud_api/src/db/groups.rs @@ -82,6 +82,7 @@ pub fn get_group_members(db_url: &str, group_id: i32) -> PyResult<Vec<User>> { name: row.get(1), email: row.get(2), username: row.get(3), + studentid: row.get(4), }).collect(); Ok(users) diff --git a/rust_crud_api/src/db/init.rs b/rust_crud_api/src/db/init.rs index cf4d1c594190f72ab97fc15692da5e82834eb44f..12f9545840230dfe2f4883ff7ad29cfdb832e4e8 100644 --- a/rust_crud_api/src/db/init.rs +++ b/rust_crud_api/src/db/init.rs @@ -16,7 +16,8 @@ pub fn init_db(db_url: &str) -> PyResult<()> { name VARCHAR NOT NULL, email VARCHAR NOT NULL UNIQUE, password_hash VARCHAR NOT NULL, - username VARCHAR NOT NULL + username VARCHAR NOT NULL, + studentid INT NOT NULL UNIQUE ); CREATE TABLE IF NOT EXISTS groups ( id SERIAL PRIMARY KEY, diff --git a/rust_crud_api/src/db/users.rs b/rust_crud_api/src/db/users.rs index e430dfcdf68a25effd5af63bf156efba7d55c7b3..3689f1b482f97b204d769edec6325ca85d1fbdc8 100644 --- a/rust_crud_api/src/db/users.rs +++ b/rust_crud_api/src/db/users.rs @@ -9,17 +9,32 @@ fn pg_err(e: postgres::Error) -> PyErr { PyRuntimeError::new_err(e.to_string()) } - -/// Create a new user by inserting into the database. #[pyfunction] -pub fn create_user(db_url: &str, name: &str, email: &str, password: &str, username: &str) -> PyResult<()> { +pub fn create_user( + db_url: &str, name: &str, email: &str, password: &str, username: &str, studentid: i32,) -> PyResult<()> { let password_hash = hash_password(password)?; let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?; - client.execute( - "INSERT INTO users (name, email, password_hash, username) VALUES ($1, $2, $3, $4)", - &[&name, &email, &password_hash, &username] - ).map_err(pg_err)?; - Ok(()) + let result = client.execute( + "INSERT INTO users (name, email, password_hash, username, studentid) + VALUES ($1, $2, $3, $4, $5)", + &[&name, &email, &password_hash, &username, &studentid], + ); + + match result { + Ok(_) => { + Ok(()) + } + Err(e) => { + // Look for a Postgres UNIQUE violation (error code 23505) + if let Some(code) = e.code() { + if code.code() == "23505" { + return Err(PyRuntimeError::new_err("Student ID already exists.")); + } + } + // Otherwise, return the generic error + Err(pg_err(e)) + } + } } /// Retrieve a user by ID. Returns None if the user is not found. @@ -27,7 +42,7 @@ pub fn create_user(db_url: &str, name: &str, email: &str, password: &str, userna pub fn get_user(db_url: &str, user_id: i32) -> PyResult<Option<User>> { let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?; let row_opt = client.query_opt( - "SELECT id, name, email, username FROM users WHERE id = $1", + "SELECT id, name, email, username, studentid FROM users WHERE id = $1", &[&user_id] ).map_err(pg_err)?; @@ -37,6 +52,7 @@ pub fn get_user(db_url: &str, user_id: i32) -> PyResult<Option<User>> { name: row.get(1), email: row.get(2), username: row.get(3), + studentid: row.get(4), }; Ok(Some(user)) } else { @@ -48,7 +64,7 @@ pub fn get_user(db_url: &str, user_id: i32) -> PyResult<Option<User>> { #[pyfunction] pub fn get_all_users(db_url: &str) -> PyResult<Vec<User>> { let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?; - let rows = client.query("SELECT id, name, email, username FROM users", &[]) + let rows = client.query("SELECT id, name, email, username, studentid FROM users", &[]) .map_err(pg_err)?; let mut users = Vec::new(); @@ -58,6 +74,7 @@ pub fn get_all_users(db_url: &str) -> PyResult<Vec<User>> { name: row.get(1), email: row.get(2), username: row.get(3), + studentid: row.get(4), }); } Ok(users) diff --git a/rust_crud_api/src/models/user.rs b/rust_crud_api/src/models/user.rs index 6145fdd02952f836f0dca5915b99bb549f05a364..2b50363a945b46d6af3412e69f8c6620145b44e2 100644 --- a/rust_crud_api/src/models/user.rs +++ b/rust_crud_api/src/models/user.rs @@ -12,5 +12,7 @@ pub struct User { pub email: String, #[pyo3(get,set)] pub username: String, + #[pyo3(get,set)] + pub studentid: i32, }