This commit is contained in:
Anthony Stirling
2023-08-13 01:12:29 +01:00
parent ad5f057733
commit e791fee38b
15 changed files with 480 additions and 56 deletions

View File

@@ -14,9 +14,10 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import jakarta.annotation.PostConstruct;
import stirling.software.SPDF.utils.GeneralUtils;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
@SpringBootApplication
@EnableWebSecurity(debug = true)
@EnableWebSecurity()
@EnableGlobalMethodSecurity(prePostEnabled = true)
//@EnableScheduling
public class SPdfApplication {

View File

@@ -1,5 +1,6 @@
package stirling.software.SPDF.config;
import java.time.Duration;
import java.util.Locale;
import org.springframework.context.annotation.Bean;
@@ -10,9 +11,22 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.Refill;
@Configuration
public class Beans implements WebMvcConfigurer {
@Bean
public Bucket createRateLimitBucket() {
Refill refill = Refill.of(1000, Duration.ofDays(1));
Bandwidth limit = Bandwidth.classic(1000, refill).withInitialTokens(1000);
return Bucket4j.builder().addLimit(limit).build();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());

View File

@@ -1,12 +1,20 @@
package stirling.software.SPDF.controller.api;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import jakarta.servlet.http.HttpServletRequest;
import stirling.software.SPDF.config.security.UserService;
@Controller
@@ -25,4 +33,41 @@ public class UserController {
userService.saveUser(username, password);
return "redirect:/login?registered=true";
}
@PostMapping("/updateUserSettings")
public String updateUserSettings(HttpServletRequest request, Principal principal) {
Map<String, String[]> paramMap = request.getParameterMap();
Map<String, String> updates = new HashMap<>();
System.out.println("Received parameter map: " + paramMap);
for (Map.Entry<String, String[]> entry : paramMap.entrySet()) {
updates.put(entry.getKey(), entry.getValue()[0]);
}
System.out.println("Processed updates: " + updates);
// Assuming you have a method in userService to update the settings for a user
userService.updateUserSettings(principal.getName(), updates);
return "redirect:/account"; // Redirect to a page of your choice after updating
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/admin/saveUser")
public String saveUser(@RequestParam String username, @RequestParam String password, @RequestParam String role) {
userService.saveUser(username, password, role);
return "redirect:/addUsers"; // Redirect to account page after adding the user
}
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/admin/deleteUser/{username}")
public String deleteUser(@PathVariable String username) {
userService.deleteUser(username);
return "redirect:/addUsers";
}
}

View File

@@ -4,11 +4,13 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -16,16 +18,23 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.UserRepository;
@Controller
@Tag(name = "General", description = "General APIs")
public class GeneralWebController {
@@ -48,7 +57,69 @@ public class GeneralWebController {
return "login";
}
@Autowired
private UserRepository userRepository; // Assuming you have a repository for user operations
@Autowired
private UserService userService; // Assuming you have a repository for user operations
@PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/addUsers")
public String showAddUserForm(Model model) {
List<User> allUsers = userRepository.findAll();
model.addAttribute("users", allUsers);
return "addUsers";
}
@GetMapping("/account")
public String account(HttpServletRequest request, Model model, Authentication authentication) {
if (authentication == null || !authentication.isAuthenticated()) {
return "redirect:/";
}
if (authentication != null && authentication.isAuthenticated()) {
Object principal = authentication.getPrincipal();
if (principal instanceof UserDetails) {
// Cast the principal object to UserDetails
UserDetails userDetails = (UserDetails) principal;
// Retrieve username and other attributes
String username = userDetails.getUsername();
// Fetch user details from the database
Optional<User> user = userRepository.findByUsername(username); // Assuming findByUsername method exists
if (!user.isPresent()) {
// Handle error appropriately
return "redirect:/error"; // Example redirection in case of error
}
// Convert settings map to JSON string
ObjectMapper objectMapper = new ObjectMapper();
String settingsJson;
try {
settingsJson = objectMapper.writeValueAsString(user.get().getSettings());
} catch (JsonProcessingException e) {
// Handle JSON conversion error
e.printStackTrace();
return "redirect:/error"; // Example redirection in case of error
}
// Add attributes to the model
model.addAttribute("username", username);
model.addAttribute("role", user.get().getRolesAsString());
model.addAttribute("settings", settingsJson);
}
} else {
return "redirect:/";
}
return "account";
}
@GetMapping("/pipeline")
@Hidden
public String pipelineForm(Model model) {

View File

@@ -13,7 +13,19 @@ import jakarta.persistence.Table;
@Table(name = "authorities")
public class Authority {
@Id
public Authority() {
}
public Authority(String authority, User user) {
this.authority = authority;
this.user = user;
user.getAuthorities().add(this);
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

View File

@@ -0,0 +1,11 @@
package stirling.software.SPDF.model;
public final class Role {
public static final String ADMIN = "ROLE_ADMIN";
public static final String USER = "ROLE_USER";
public static final String LIMITED_API_USER = "ROLE_LIMITED_API_USER";
public static final String WEB_ONLY_USER = "ROLE_WEB_ONLY_USER";
}

View File

@@ -1,15 +1,22 @@
package stirling.software.SPDF.model;
import java.util.Set;
import java.util.stream.Collectors;
import jakarta.persistence.CascadeType;
import jakarta.persistence.CollectionTable;
import jakarta.persistence.Column;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.MapKeyColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.JoinColumn;
import java.util.Map;
import java.util.HashMap;
import java.util.HashSet;
@Entity
@Table(name = "users")
public class User {
@@ -25,7 +32,23 @@ public class User {
private boolean enabled;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user")
private Set<Authority> authorities;
private Set<Authority> authorities = new HashSet<>();
@ElementCollection
@MapKeyColumn(name = "setting_key")
@Column(name = "setting_value")
@CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "username"))
private Map<String, String> settings = new HashMap<>(); // Key-value pairs of settings.
public Map<String, String> getSettings() {
return settings;
}
public void setSettings(Map<String, String> settings) {
this.settings = settings;
}
public String getUsername() {
return username;
@@ -58,5 +81,19 @@ public class User {
public void setAuthorities(Set<Authority> authorities) {
this.authorities = authorities;
}
public void addAuthorities(Set<Authority> authorities) {
this.authorities.addAll(authorities);
}
public void addAuthority(Authority authorities) {
this.authorities.add(authorities);
}
public String getRolesAsString() {
return this.authorities.stream()
.map(Authority::getAuthority)
.collect(Collectors.joining(", "));
}
}