diff --git a/src/main/java/org/to/telegramfinalproject/Client/SidebarAction.java b/src/main/java/org/to/telegramfinalproject/Client/SidebarAction.java index 8ad934a..4a16145 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/SidebarAction.java +++ b/src/main/java/org/to/telegramfinalproject/Client/SidebarAction.java @@ -9,4 +9,4 @@ public enum SidebarAction { SETTINGS, FEATURES, Q_AND_A -} +} \ No newline at end of file diff --git a/src/main/java/org/to/telegramfinalproject/Client/SidebarHandler.java b/src/main/java/org/to/telegramfinalproject/Client/SidebarHandler.java index 7edae86..c042c7a 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/SidebarHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Client/SidebarHandler.java @@ -1,5 +1,6 @@ package org.to.telegramfinalproject.Client; +import org.json.JSONException; import org.json.JSONObject; import java.util.Scanner; @@ -51,7 +52,13 @@ public class SidebarHandler { return; } - JSONObject profile = response.getJSONObject("data"); + JSONObject profile; + try { + profile = response.getJSONObject("data"); + } catch (JSONException e) { + System.out.println("Received malformed profile data from server."); + return; + } String profileName = profile.optString("profile_name", "NOT-AVAILABLE"); String userId = profile.optString("user_id", "NOT-AVAILABLE"); @@ -63,7 +70,7 @@ public class SidebarHandler { System.out.println("===== My Profile ====="); System.out.println("Profile Picture URL : " + profilePictureUrl); System.out.println("Profile Name : " + profileName); - System.out.println("User ID : " + userId); + System.out.println("User ID : @" + userId); System.out.println("Status : " + status); System.out.println("Bio : " + bio); System.out.println("======================"); @@ -103,19 +110,117 @@ public class SidebarHandler { } private void editProfileName() { + System.out.println("Enter your new profile name:"); + String newProfileName = scanner.nextLine().trim(); + // Step 1: Validate input + while (newProfileName.trim().isEmpty()) { + System.out.println("Profile name cannot be empty. Enter another name."); + newProfileName = scanner.nextLine().trim(); + } + + // Step 2: Create request + JSONObject request = new JSONObject(); + request.put("action", "edit_profile_name"); + request.put("new_profile_name", newProfileName); + + // Step 3: Send request and receive response + JSONObject response = ActionHandler.sendWithResponse(request); + + // Step 4: Handle response + if (response == null || !response.optString("status", "fail").equals("success")) { + System.out.println("Failed to update profile name."); + } else { + System.out.println("Profile name updated successfully!"); + } } private void editUserId() { + while (true) { + System.out.println("Enter your new user ID: "); + String newUserId = scanner.nextLine().trim(); + if (newUserId.isEmpty()) { + System.out.println("User ID cannot be empty."); + continue; + } + + if (newUserId.contains(" ")) { + System.out.println("User ID cannot contain spaces."); + continue; + } + + if (!newUserId.matches("^[a-zA-Z0-9_]+$")) { + System.out.println("User ID can only contain letters, digits, and underscores."); + continue; + } + + // Send to server + JSONObject request = new JSONObject(); + request.put("action", "edit_user_id"); + request.put("new_user_id", newUserId); + JSONObject response = ActionHandler.sendWithResponse(request); + + if (response.getString("status").equals("success")) { + System.out.println("User ID updated successfully."); + break; + } else { + // Server-side error message (e.g., ID already exists) + System.out.println(response.getString("message")); + } + } } private void editBio() { + System.out.println("Enter your new bio:"); + String newBio = scanner.nextLine().trim(); + // Limit the bio length + if (newBio.length() > 70) { + System.out.println("Bio cannot be more than 70 characters."); + return; + } + + JSONObject request = new JSONObject(); + request.put("action", "edit_bio"); + request.put("new_bio", newBio); + + JSONObject response = ActionHandler.sendWithResponse(request); + + if (response.getString("status").equals("success")) { + System.out.println("Bio updated successfully."); + } else { + System.out.println(response.getString("message")); + } } private void editProfilePictureUrl() { + while (true) { + System.out.println("Enter new profile picture URL (or leave empty to remove):"); + String newImageUrl = scanner.nextLine().trim(); + if (newImageUrl.contains(" ")) { + System.out.println("URL cannot contain spaces."); + continue; + } + + if (!newImageUrl.isEmpty() && !newImageUrl.matches("^(http|https)://.*$")) { + System.out.println("Invalid URL format. Please enter a valid HTTP/HTTPS link."); + continue; + } + + JSONObject request = new JSONObject(); + request.put("action", "edit_profile_picture"); + request.put("new_image_url", newImageUrl); + JSONObject response = ActionHandler.sendWithResponse(request); + + if (response.getString("status").equals("success")) { + System.out.println("Bio updated successfully."); + } else { + System.out.println(response.getString("message")); + } + break; + } } private void createNewGroup() { diff --git a/src/main/java/org/to/telegramfinalproject/Database/userDatabase.java b/src/main/java/org/to/telegramfinalproject/Database/userDatabase.java index 6064500..dc9d7dc 100644 --- a/src/main/java/org/to/telegramfinalproject/Database/userDatabase.java +++ b/src/main/java/org/to/telegramfinalproject/Database/userDatabase.java @@ -152,7 +152,7 @@ public class userDatabase { } public boolean save(User user) { - String query = "INSERT INTO users (user_id, internal_uuid, username, password, profile_name) VALUES (?, ?, ?, ?, ?)"; + String query = "INSERT INTO users (user_id, internal_uuid, username, password, profile_name, bio, image_url) VALUES (?, ?, ?, ?, ?, ?, ?)"; try { boolean var5; @@ -165,6 +165,8 @@ public class userDatabase { stmt.setString(3, user.getUsername()); stmt.setString(4, user.getPassword()); stmt.setString(5, user.getProfile_name()); + stmt.setString(6, user.getBio()); + stmt.setString(7, user.getImage_url()); var5 = stmt.executeUpdate() > 0; } @@ -223,7 +225,7 @@ public class userDatabase { } private User extractUser(ResultSet rs) throws SQLException { - return new User(rs.getString("user_id"), UUID.fromString(rs.getString("internal_uuid")), rs.getString("username"), rs.getString("password"), rs.getString("profile_name")); + return new User(rs.getString("user_id"), UUID.fromString(rs.getString("internal_uuid")), rs.getString("username"), rs.getString("password"), rs.getString("profile_name"), rs.getString("bio"), rs.getString("image_url")); } public boolean deleteByUUID(UUID uuid) { @@ -288,7 +290,9 @@ public class userDatabase { UUID.fromString(rs.getString("internal_uuid")), rs.getString("username"), rs.getString("password"), - rs.getString("profile_name") + rs.getString("profile_name"), + rs.getString("bio"), + rs.getString("image_url") ); user.setBio(rs.getString("bio")); diff --git a/src/main/java/org/to/telegramfinalproject/Models/User.java b/src/main/java/org/to/telegramfinalproject/Models/User.java index 73ac635..a8d9e29 100644 --- a/src/main/java/org/to/telegramfinalproject/Models/User.java +++ b/src/main/java/org/to/telegramfinalproject/Models/User.java @@ -22,12 +22,14 @@ public class User { private List unreadMessages; private List chatList; - public User(String user_id, UUID internal_uuid, String username, String password, String profile_name) { + public User(String user_id, UUID internal_uuid, String username, String password, String profile_name, String bio, String image_url) { this.user_id = user_id; this.internal_uuid = internal_uuid; this.username = username; this.password = password; this.profile_name = profile_name; + this.bio = bio; + this.image_url = image_url; } public void setUser_id(String user_id) { diff --git a/src/main/java/org/to/telegramfinalproject/Server/AuthService.java b/src/main/java/org/to/telegramfinalproject/Server/AuthService.java index 1534c46..f50da87 100644 --- a/src/main/java/org/to/telegramfinalproject/Server/AuthService.java +++ b/src/main/java/org/to/telegramfinalproject/Server/AuthService.java @@ -20,7 +20,7 @@ public class AuthService { } else { UUID uuid = UUID.randomUUID(); password = PasswordHashing.hash(password); - User user = new User(user_id, uuid, username, password, profile_name); + User user = new User(user_id, uuid, username, password, profile_name, "", ""); return this.userDb.save(user); } } else { diff --git a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java index 6affe43..50769b4 100644 --- a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java @@ -1722,6 +1722,62 @@ public class ClientHandler implements Runnable { break; } + case "edit_profile_name": { + // Validate input + if (!requestJson.has("new_profile_name")) { + response = new ResponseModel("error", "Missing new profile name."); + break; + } + + String user_id = this.currentUser.getUser_id(); + String newProfileName = requestJson.getString("new_profile_name"); + + response = SidebarService.updateProfileName(user_id, newProfileName); + break; + } + + case "edit_user_id": { + // Validate input + if (!requestJson.has("new_user-id")) { + response = new ResponseModel("error", "Missing new user ID."); + break; + } + + String currentUserId = this.currentUser.getUser_id(); + String newUserId = requestJson.getString("new_user_id"); + + response = SidebarService.updateUserId(currentUserId, newUserId); + break; + } + + case "edit_bio": { + // Validate input + if (!requestJson.has("new_bio")) { + response = new ResponseModel("error", "Missing new bio."); + break; + } + + String currentUserId = this.currentUser.getUser_id(); + String newBio = requestJson.getString("new_bio").trim(); + + response = SidebarService.updateBio(currentUserId, newBio); + break; + } + + case "edit_profile_picture": { + // Validate input + if (!requestJson.has("new_image_url")) { + response = new ResponseModel("error", "Missing new image url."); + break; + } + + String currentUserId = this.currentUser.getUser_id(); + String newImageUrl = requestJson.getString("new_image_url").trim(); + + response = SidebarService.updateProfilePicture(currentUserId, newImageUrl); + break; + } + default: response = new ResponseModel("error", "Unknown action: " + action); } diff --git a/src/main/java/org/to/telegramfinalproject/Server/SidebarService.java b/src/main/java/org/to/telegramfinalproject/Server/SidebarService.java index eb67f6f..920e195 100644 --- a/src/main/java/org/to/telegramfinalproject/Server/SidebarService.java +++ b/src/main/java/org/to/telegramfinalproject/Server/SidebarService.java @@ -2,8 +2,11 @@ package org.to.telegramfinalproject.Server; import org.json.JSONObject; import org.to.telegramfinalproject.Database.userDatabase; +import org.to.telegramfinalproject.Models.ResponseModel; import org.to.telegramfinalproject.Models.User; +import java.util.Objects; + public class SidebarService { private static userDatabase userDB = new userDatabase(); @@ -25,33 +28,128 @@ public class SidebarService { return profile; } - // Updates one or more profile fields for the user - public static JSONObject updateUserProfile(String userId, JSONObject updateData) { - return null; + // Changes the user's profile picture + public static ResponseModel updateProfilePicture(String userId, String newImageUrl) { + User user = userDB.findByUserId(userId); + if (user == null) { + return new ResponseModel("error", "User not found."); + } + + String currentUrl = user.getImage_url(); + if (Objects.equals(currentUrl, newImageUrl)) { + return new ResponseModel("error", "No changes made. Profile picture is the same."); + } + + user.setImage_url(newImageUrl); // Can be null + boolean success = userDB.updateByUUID(user.getInternal_uuid(), user); + + if (success) { + return new ResponseModel("success", "Profile picture updated successfully."); + } else { + user.setImage_url(currentUrl); + return new ResponseModel("error", "Failed to update profile picture."); + } } - // Changes the user's profile picture - public static JSONObject changeProfilePicture(String userId, byte[] imageData) { - return null; + // Changes user's bio + public static ResponseModel updateBio(String userId, String newBio) { + if (newBio.length() > 70) { + return new ResponseModel("error", "Bio is too long."); + } + + User user = userDB.findByUserId(userId); + if (user == null) { + return new ResponseModel("error", "User not found."); + } + + String currentBio = user.getBio(); + if (Objects.equals(currentBio, newBio)) { + return new ResponseModel("error", "No changes made. Bio is the same."); + } + + user.setBio(newBio); + boolean success = userDB.updateByUUID(user.getInternal_uuid(), user); + + if (success) { + return new ResponseModel("success", "Bio updated successfully."); + } else { + user.setBio(currentBio); + return new ResponseModel("error", "Failed to update bio."); + } } // Changes user-id - public static JSONObject updateUserId(String userId, String newUserId) { - return null; - } + public static ResponseModel updateUserId(String currentUserId, String newUserId) { + if (newUserId == null || newUserId.trim().isEmpty()) { + return new ResponseModel("error", "User ID cannot be empty."); + } - // (Optional) Changes username - public static JSONObject updateUserName(String userId, String newUserName) { - return null; + newUserId = newUserId.trim(); + + if (newUserId.contains(" ")) { + return new ResponseModel("error", "User ID cannot contain spaces."); + } + + if (!newUserId.matches("^[a-zA-Z0-9_]+$")) { + return new ResponseModel("error", "User ID can only contain letters, digits, and underscores."); + } + + if (userDB.findByUserId(newUserId) != null) { + return new ResponseModel("error", "This user ID is already taken."); + } + + User user = userDB.findByUserId(currentUserId); + if (user == null) { + return new ResponseModel("error", "User not found."); + } + + if (Objects.equals(currentUserId, newUserId)) { + return new ResponseModel("error", "No changes made. User ID is the same."); + } + + user.setUser_id(newUserId); + + boolean saved = userDB.updateByUUID(user.getInternal_uuid(), user); + if (saved) { + return new ResponseModel("success", "User ID updated successfully."); + } else { + user.setUser_id(currentUserId); + return new ResponseModel("error", "Failed to update user ID due to server error."); + } } // Changes user's profile name - public static JSONObject updateProfileName(String userId, String newProfileName) { - return null; + public static ResponseModel updateProfileName(String userId, String newProfileName) { + if (newProfileName == null || newProfileName.trim().isEmpty()) { + return new ResponseModel("error", "Invalid input."); // Invalid input (empty or just spaces) + } + + // Fetch the user from database + User user = userDB.findByUserId(userId); + if (user == null) { + return new ResponseModel("error", "User not found."); // User doesn't exist + } + + String oldName = user.getProfile_name(); + if (Objects.equals(oldName, newProfileName)) { + return new ResponseModel("error", "No changes made. Profile name is the same."); + } + + // Only set the profile name *after* successful DB update + user.setProfile_name(newProfileName); + + boolean saved = userDB.updateByUUID(user.getInternal_uuid(), user); + + if (saved) { + return new ResponseModel("success", "Profile name updated successfully."); + } else { + user.setProfile_name(oldName); + return new ResponseModel("error", "Failed to update profile name."); + } } - // Changes or sets the user's date of birth - public static JSONObject updateDateOfBirth(String userId, String newDateOfBirth) { - return null; + // Changes username + public static boolean updateUserName(String userId, String newUserName) { + return false; } } \ No newline at end of file