change user and pass
This commit is contained in:
parent
d7307665b3
commit
86f71ffb93
10 changed files with 125 additions and 34 deletions
|
@ -20,9 +20,9 @@ public class InitialSetup {
|
||||||
if(initialUsername != null && initialPassword != null) {
|
if(initialUsername != null && initialPassword != null) {
|
||||||
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
|
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
|
||||||
}
|
}
|
||||||
// else {
|
else {
|
||||||
// userService.saveUser("admin", "password", Role.ADMIN.getRoleId());
|
userService.saveUser("admin", "password", Role.ADMIN.getRoleId());
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ public class UserService {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean usernameExists(String username) {
|
public boolean usernameExists(String username) {
|
||||||
return userRepository.findByUsername(username) != null;
|
return userRepository.findByUsername(username).isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasUsers() {
|
public boolean hasUsers() {
|
||||||
|
@ -158,5 +158,21 @@ public class UserService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<User> 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package stirling.software.SPDF.controller.api;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
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 org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import stirling.software.SPDF.config.security.UserService;
|
import stirling.software.SPDF.config.security.UserService;
|
||||||
import stirling.software.SPDF.model.User;
|
import stirling.software.SPDF.model.User;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class UserController {
|
public class UserController {
|
||||||
|
@ -26,6 +30,9 @@ public class UserController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserService userService;
|
private UserService userService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
@PostMapping("/register")
|
@PostMapping("/register")
|
||||||
public String register(@RequestParam String username, @RequestParam String password, Model model) {
|
public String register(@RequestParam String username, @RequestParam String password, Model model) {
|
||||||
if(userService.usernameExists(username)) {
|
if(userService.usernameExists(username)) {
|
||||||
|
@ -37,6 +44,59 @@ public class UserController {
|
||||||
return "redirect:/login?registered=true";
|
return "redirect:/login?registered=true";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/change-username")
|
||||||
|
public ResponseEntity<String> 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<User> 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<String> 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<User> 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")
|
@PostMapping("/updateUserSettings")
|
||||||
public String updateUserSettings(HttpServletRequest request, Principal principal) {
|
public String updateUserSettings(HttpServletRequest request, Principal principal) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class Authority {
|
||||||
private String authority;
|
private String authority;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "username")
|
@JoinColumn(name = "user_id")
|
||||||
private User user;
|
private User user;
|
||||||
|
|
||||||
public Long getId() {
|
public Long getId() {
|
||||||
|
|
|
@ -9,6 +9,8 @@ import jakarta.persistence.Column;
|
||||||
import jakarta.persistence.ElementCollection;
|
import jakarta.persistence.ElementCollection;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
|
import jakarta.persistence.GeneratedValue;
|
||||||
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.MapKeyColumn;
|
import jakarta.persistence.MapKeyColumn;
|
||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
|
@ -21,8 +23,12 @@ import java.util.HashSet;
|
||||||
@Table(name = "users")
|
@Table(name = "users")
|
||||||
public class User {
|
public class User {
|
||||||
|
|
||||||
@Id
|
@Id
|
||||||
@Column(name = "username")
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "user_id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "username", unique = true)
|
||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
@Column(name = "password")
|
@Column(name = "password")
|
||||||
|
@ -40,11 +46,19 @@ public class User {
|
||||||
@ElementCollection
|
@ElementCollection
|
||||||
@MapKeyColumn(name = "setting_key")
|
@MapKeyColumn(name = "setting_key")
|
||||||
@Column(name = "setting_value")
|
@Column(name = "setting_value")
|
||||||
@CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "username"))
|
@CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id"))
|
||||||
private Map<String, String> settings = new HashMap<>(); // Key-value pairs of settings.
|
private Map<String, String> settings = new HashMap<>(); // Key-value pairs of settings.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
public String getApiKey() {
|
public String getApiKey() {
|
||||||
return apiKey;
|
return apiKey;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@ server.error.include-stacktrace=always
|
||||||
server.error.include-exception=true
|
server.error.include-exception=true
|
||||||
server.error.include-message=always
|
server.error.include-message=always
|
||||||
|
|
||||||
#logging.level.org.springframework.web=DEBUG
|
logging.level.org.springframework.web=DEBUG
|
||||||
#logging.level.org.springframework=DEBUG
|
logging.level.org.springframework=DEBUG
|
||||||
#logging.level.org.springframework.security=DEBUG
|
logging.level.org.springframework.security=DEBUG
|
||||||
|
|
||||||
login.enabled=true
|
login.enabled=true
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,8 @@ settings.downloadOption.3=Download file
|
||||||
settings.zipThreshold=Zip files when the number of downloaded files exceeds
|
settings.zipThreshold=Zip files when the number of downloaded files exceeds
|
||||||
|
|
||||||
settings.accountSettings=Account Settings
|
settings.accountSettings=Account Settings
|
||||||
settings.adminSettings=Admin - View/Add Users
|
settings.adminSettings=Admin Settings- View and Add Users
|
||||||
settings.userSettings=User Settings
|
settings.userControlSettings=User Control Settings
|
||||||
settings.changeUsername=New Username
|
settings.changeUsername=New Username
|
||||||
settings.changeUsernameButton=Change Username
|
settings.changeUsernameButton=Change Username
|
||||||
settings.password=Confirmation Password
|
settings.password=Confirmation Password
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
<!-- At the top of the user settings -->
|
<!-- At the top of the user settings -->
|
||||||
<h3 class="text-center">Welcome <span th:text="${username}">User</span>!</h3>
|
<h3 class="text-center">Welcome <span th:text="${username}">User</span>!</h3>
|
||||||
|
|
||||||
|
|
||||||
<!-- Change Username Form -->
|
<!-- Change Username Form -->
|
||||||
<h4>Change username?</h4>
|
<h4>Change username?</h4>
|
||||||
<form action="/change-username" method="post">
|
<form action="/change-username" method="post">
|
||||||
|
@ -28,8 +29,8 @@
|
||||||
<input type="text" class="form-control" name="newUsername" id="newUsername" placeholder="New Username">
|
<input type="text" class="form-control" name="newUsername" id="newUsername" placeholder="New Username">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password" th:text="#{settings.password}">Password</label>
|
<label for="currentPassword" th:text="#{settings.password}">Password</label>
|
||||||
<input type="password" class="form-control" name="password" id="password" placeholder="Password">
|
<input type="password" class="form-control" name="currentPassword" id="currentPassword" placeholder="Password">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button type="submit" class="btn btn-primary" th:text="#{settings.changeUsernameButton}">Change Username</button>
|
<button type="submit" class="btn btn-primary" th:text="#{settings.changeUsernameButton}">Change Username</button>
|
||||||
|
@ -42,8 +43,8 @@
|
||||||
<h4>Change Password?</h4>
|
<h4>Change Password?</h4>
|
||||||
<form action="/change-password" method="post">
|
<form action="/change-password" method="post">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="oldPassword" th:text="#{settings.oldPassword}">Old Password</label>
|
<label for="currentPassword" th:text="#{settings.oldPassword}">Old Password</label>
|
||||||
<input type="password" class="form-control" name="oldPassword" id="oldPassword" placeholder="Old Password">
|
<input type="password" class="form-control" name="currentPassword" id="currentPassword" placeholder="Old Password">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="newPassword" th:text="#{settings.newPassword}">New Password</label>
|
<label for="newPassword" th:text="#{settings.newPassword}">New Password</label>
|
||||||
|
@ -177,13 +178,9 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="buttons-container mt-3 text-center">
|
<div class="buttons-container mt-3 text-center">
|
||||||
<button id="syncToBrowser" class="btn btn-primary btn-sm">Sync Account to Web Browser</button>
|
<button id="syncToBrowser" class="btn btn-primary btn-sm">Sync Account -> Browser</button>
|
||||||
<button id="syncToAccount" class="btn btn-secondary btn-sm">Sync Web Browser to Account</button>
|
<button id="syncToAccount" class="btn btn-secondary btn-sm">Sync Account <- Browser</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a th:if="${role == 'ROLE_ADMIN'}" href="addUsers" target="_blank">
|
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary" th:text="#{settings.adminSettings}">Admin Settings</button>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -276,11 +273,15 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Sign Out Button -->
|
|
||||||
<div class="form-group mt-4">
|
<div class="form-group mt-4">
|
||||||
<a href="/logout">
|
<a href="/logout">
|
||||||
<button type="button" class="btn btn-danger" th:text="#{settings.signOut}">Sign Out</button>
|
<button type="button" class="btn btn-danger" th:text="#{settings.signOut}">Sign Out</button>
|
||||||
</a>
|
</a>
|
||||||
|
<a th:if="${role == 'ROLE_ADMIN'}" href="addUsers" target="_blank">
|
||||||
|
<button type="button" class="btn btn-info" th:text="#{settings.adminSettings}">Admin Settings</button>
|
||||||
|
</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -14,11 +14,8 @@
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
|
|
||||||
<!-- User Settings Title -->
|
<!-- User Settings Title -->
|
||||||
<h2 class="text-center" th:text="#{settings.accountSettings}">User Settings</h2>
|
<h2 class="text-center" th:text="#{settings.userControlSettings}">User Control Settings</h2>
|
||||||
<hr>
|
|
||||||
|
|
||||||
<!-- At the top of the user settings -->
|
|
||||||
<h3 class="text-center">Welcome <span th:text="${username}">User</span>!</h3>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -339,11 +339,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="account" target="_blank">
|
<div th:if="${@loginEnabled}">
|
||||||
<button type="button" class="btn btn-sm btn-outline-primary" th:text="#{settings.accountSettings}">Account Settings</button>
|
<a href="account" target="_blank">
|
||||||
</a>
|
<button type="button" class="btn btn-sm btn-outline-primary" th:text="#{settings.accountSettings}">Account Settings</button>
|
||||||
|
</a>
|
||||||
|
<a href="/logout">
|
||||||
|
<button type="button" class="btn btn-danger" th:text="#{settings.signOut}">Sign Out</button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-dismiss="modal" th:text="#{close}"></button>
|
<button type="button" class="btn btn-secondary" data-dismiss="modal" th:text="#{close}"></button>
|
||||||
|
|
Loading…
Reference in a new issue