diff --git a/src/main/java/stirling/software/SPDF/config/security/InitialSetup.java b/src/main/java/stirling/software/SPDF/config/security/InitialSetup.java index 31d1f9bc..bf0d694e 100644 --- a/src/main/java/stirling/software/SPDF/config/security/InitialSetup.java +++ b/src/main/java/stirling/software/SPDF/config/security/InitialSetup.java @@ -20,9 +20,9 @@ public class InitialSetup { if(initialUsername != null && initialPassword != null) { userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId()); } -// else { -// userService.saveUser("admin", "password", Role.ADMIN.getRoleId()); -// } + else { + userService.saveUser("admin", "password", Role.ADMIN.getRoleId()); + } } } } diff --git a/src/main/java/stirling/software/SPDF/config/security/UserService.java b/src/main/java/stirling/software/SPDF/config/security/UserService.java index 7dab8d67..5a28e776 100644 --- a/src/main/java/stirling/software/SPDF/config/security/UserService.java +++ b/src/main/java/stirling/software/SPDF/config/security/UserService.java @@ -134,7 +134,7 @@ public class UserService { } public boolean usernameExists(String username) { - return userRepository.findByUsername(username) != null; + return userRepository.findByUsername(username).isPresent(); } public boolean hasUsers() { @@ -158,5 +158,21 @@ public class UserService { } } + public Optional findByUsername(String username) { + return userRepository.findByUsername(username); + } + + public void changeUsername(User user, String newUsername) { + user.setUsername(newUsername); + userRepository.save(user); + } + + public void changePassword(User user, String newPassword) { + user.setPassword(passwordEncoder.encode(newPassword)); + userRepository.save(user); + } + public boolean isPasswordCorrect(User user, String currentPassword) { + return passwordEncoder.matches(currentPassword, user.getPassword()); + } } diff --git a/src/main/java/stirling/software/SPDF/controller/api/UserController.java b/src/main/java/stirling/software/SPDF/controller/api/UserController.java index 771955e8..cd1be5a0 100644 --- a/src/main/java/stirling/software/SPDF/controller/api/UserController.java +++ b/src/main/java/stirling/software/SPDF/controller/api/UserController.java @@ -3,6 +3,7 @@ package stirling.software.SPDF.controller.api; import java.security.Principal; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -17,8 +18,11 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import stirling.software.SPDF.config.security.UserService; import stirling.software.SPDF.model.User; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; @Controller public class UserController { @@ -26,6 +30,9 @@ public class UserController { @Autowired private UserService userService; + @Autowired + private PasswordEncoder passwordEncoder; + @PostMapping("/register") public String register(@RequestParam String username, @RequestParam String password, Model model) { if(userService.usernameExists(username)) { @@ -37,6 +44,59 @@ public class UserController { return "redirect:/login?registered=true"; } + @PostMapping("/change-username") + public ResponseEntity changeUsername(Principal principal, @RequestParam String currentPassword, @RequestParam String newUsername, HttpServletRequest request, HttpServletResponse response) { + if (principal == null) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body("User not authenticated."); + } + + Optional userOpt = userService.findByUsername(principal.getName()); + + if(userOpt == null || userOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found."); + } + User user = userOpt.get(); + + if(!userService.isPasswordCorrect(user, currentPassword)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Current password is incorrect."); + } + + if(userService.usernameExists(newUsername)) { + return ResponseEntity.status(HttpStatus.CONFLICT).body("New username already exists."); + } + + userService.changeUsername(user, newUsername); + + // Logout using Spring's utility + new SecurityContextLogoutHandler().logout(request, response, null); + + + return ResponseEntity.ok("Username updated successfully."); + } + + @PostMapping("/change-password") + public ResponseEntity changePassword(Principal principal, @RequestParam String currentPassword, @RequestParam String newPassword, HttpServletRequest request, HttpServletResponse response) { + if (principal == null) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body("User not authenticated."); + } + + Optional userOpt = userService.findByUsername(principal.getName()); + + if(userOpt == null || userOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found."); + } + User user = userOpt.get(); + if(!userService.isPasswordCorrect(user, currentPassword)) { + return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Current password is incorrect."); + } + + userService.changePassword(user, passwordEncoder.encode(newPassword)); + + // Logout using Spring's utility + new SecurityContextLogoutHandler().logout(request, response, null); + + return ResponseEntity.ok("Password updated successfully."); + } @PostMapping("/updateUserSettings") public String updateUserSettings(HttpServletRequest request, Principal principal) { diff --git a/src/main/java/stirling/software/SPDF/model/Authority.java b/src/main/java/stirling/software/SPDF/model/Authority.java index bb8e1d6e..8be853ea 100644 --- a/src/main/java/stirling/software/SPDF/model/Authority.java +++ b/src/main/java/stirling/software/SPDF/model/Authority.java @@ -33,7 +33,7 @@ public class Authority { private String authority; @ManyToOne - @JoinColumn(name = "username") + @JoinColumn(name = "user_id") private User user; public Long getId() { diff --git a/src/main/java/stirling/software/SPDF/model/User.java b/src/main/java/stirling/software/SPDF/model/User.java index 40d71da1..c2b80e83 100644 --- a/src/main/java/stirling/software/SPDF/model/User.java +++ b/src/main/java/stirling/software/SPDF/model/User.java @@ -9,6 +9,8 @@ import jakarta.persistence.Column; import jakarta.persistence.ElementCollection; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.MapKeyColumn; import jakarta.persistence.OneToMany; @@ -21,8 +23,12 @@ import java.util.HashSet; @Table(name = "users") public class User { - @Id - @Column(name = "username") + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_id") + private Long id; + + @Column(name = "username", unique = true) private String username; @Column(name = "password") @@ -40,11 +46,19 @@ public class User { @ElementCollection @MapKeyColumn(name = "setting_key") @Column(name = "setting_value") - @CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "username")) + @CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id")) private Map settings = new HashMap<>(); // Key-value pairs of settings. + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + public String getApiKey() { return apiKey; } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e52f939e..bf594bfc 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -16,9 +16,9 @@ server.error.include-stacktrace=always server.error.include-exception=true server.error.include-message=always -#logging.level.org.springframework.web=DEBUG -#logging.level.org.springframework=DEBUG -#logging.level.org.springframework.security=DEBUG +logging.level.org.springframework.web=DEBUG +logging.level.org.springframework=DEBUG +logging.level.org.springframework.security=DEBUG login.enabled=true diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties index 083c0716..5b211262 100644 --- a/src/main/resources/messages_en_GB.properties +++ b/src/main/resources/messages_en_GB.properties @@ -56,8 +56,8 @@ settings.downloadOption.3=Download file settings.zipThreshold=Zip files when the number of downloaded files exceeds settings.accountSettings=Account Settings -settings.adminSettings=Admin - View/Add Users -settings.userSettings=User Settings +settings.adminSettings=Admin Settings- View and Add Users +settings.userControlSettings=User Control Settings settings.changeUsername=New Username settings.changeUsernameButton=Change Username settings.password=Confirmation Password diff --git a/src/main/resources/templates/account.html b/src/main/resources/templates/account.html index 96421b5e..1b2bb894 100644 --- a/src/main/resources/templates/account.html +++ b/src/main/resources/templates/account.html @@ -20,6 +20,7 @@

Welcome User!

+

Change username?

@@ -28,8 +29,8 @@
- - + +
@@ -42,8 +43,8 @@

Change Password?

- - + +
@@ -177,13 +178,9 @@
- - + +
- - - -
@@ -276,11 +273,15 @@ - +
diff --git a/src/main/resources/templates/addUsers.html b/src/main/resources/templates/addUsers.html index ccd7e44b..fbff33e6 100644 --- a/src/main/resources/templates/addUsers.html +++ b/src/main/resources/templates/addUsers.html @@ -14,11 +14,8 @@
-

User Settings

-
- - -

Welcome User!

+

User Control Settings

+ diff --git a/src/main/resources/templates/fragments/navbar.html b/src/main/resources/templates/fragments/navbar.html index 74ab9383..07ecd772 100644 --- a/src/main/resources/templates/fragments/navbar.html +++ b/src/main/resources/templates/fragments/navbar.html @@ -339,11 +339,14 @@
- - - - - +