summaryrefslogtreecommitdiff
path: root/spring-boot/10-role-based-security/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'spring-boot/10-role-based-security/src/main')
-rw-r--r--spring-boot/10-role-based-security/src/main/java/com/example/spring/security/controllers/UserController.java67
-rw-r--r--spring-boot/10-role-based-security/src/main/java/com/example/spring/security/controllers/UserForm.java27
-rw-r--r--spring-boot/10-role-based-security/src/main/java/com/example/spring/security/repository/UserRepository.java6
-rw-r--r--spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/CustomUserDetailsService.java1
-rw-r--r--spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/UserService.java12
-rw-r--r--spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/UserServiceImpl.java49
-rw-r--r--spring-boot/10-role-based-security/src/main/resources/templates/error.html12
-rw-r--r--spring-boot/10-role-based-security/src/main/resources/templates/error/403.html12
-rw-r--r--spring-boot/10-role-based-security/src/main/resources/templates/layout/main.html2
-rw-r--r--spring-boot/10-role-based-security/src/main/resources/templates/security/user-form.html22
-rw-r--r--spring-boot/10-role-based-security/src/main/resources/templates/security/users.html30
11 files changed, 235 insertions, 5 deletions
diff --git a/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/controllers/UserController.java b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/controllers/UserController.java
new file mode 100644
index 0000000..d9f5fdd
--- /dev/null
+++ b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/controllers/UserController.java
@@ -0,0 +1,67 @@
+package com.example.spring.security.controllers;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import com.example.spring.security.entity.User;
+import com.example.spring.security.repository.UserRepository;
+import com.example.spring.security.service.UserService;
+
+import jakarta.validation.Valid;
+
+@Controller
+public class UserController {
+
+ @Autowired
+ private UserService userService;
+
+ @GetMapping("/security/users")
+ @PreAuthorize("hasRole('ADMIN')")
+ public String showUsers(Model model) {
+ List<User> users = userService.findAll();
+
+ model.addAttribute("users", users);
+
+ return "security/users";
+ }
+
+ @GetMapping("/security/user/update/{id}")
+ @PreAuthorize("hasRole('ADMIN')")
+ public String showEditForm(@PathVariable Long id, Model model) {
+ Optional<User> userOpt = userService.findById(id);
+
+ User user = userOpt.get();
+
+ UserForm form = new UserForm();
+ form.setId(user.getId());
+ form.setUsername(user.getUsername());
+ form.setDescription(user.getDescription());
+
+ model.addAttribute("userForm", form);
+
+ return "security/user-form";
+ }
+
+ @PostMapping("/security/user/update")
+ @PreAuthorize("hasRole('ADMIN')")
+ public String updateUser(@Valid @ModelAttribute UserForm userForm, BindingResult bindingResult,
+ Model model) {
+ if (bindingResult.hasErrors()) {
+ return "security/user-form";
+ }
+
+ userService.updateUser(userForm.getId(), userForm.getDescription());
+
+ return "redirect:/security/users";
+ }
+}
diff --git a/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/controllers/UserForm.java b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/controllers/UserForm.java
new file mode 100644
index 0000000..8df4932
--- /dev/null
+++ b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/controllers/UserForm.java
@@ -0,0 +1,27 @@
+package com.example.spring.security.controllers;
+
+public class UserForm {
+
+ private Long id;
+ private String username;
+ private String description;
+
+ public Long getId() {
+ return id;
+ }
+ public void setId(Long id) {
+ this.id = id;
+ }
+ public String getUsername() {
+ return username;
+ }
+ public void setUsername(String username) {
+ this.username = username;
+ }
+ public String getDescription() {
+ return description;
+ }
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
diff --git a/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/repository/UserRepository.java b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/repository/UserRepository.java
index f67039c..24cf579 100644
--- a/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/repository/UserRepository.java
+++ b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/repository/UserRepository.java
@@ -2,12 +2,12 @@ package com.example.spring.security.repository;
import java.util.Optional;
-import org.springframework.data.repository.ListCrudRepository;
+import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.spring.security.entity.User;
@Repository
-public interface UserRepository extends ListCrudRepository<User, Long> {
+public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
-}
+} \ No newline at end of file
diff --git a/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/CustomUserDetailsService.java b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/CustomUserDetailsService.java
index cdced4a..1795109 100644
--- a/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/CustomUserDetailsService.java
+++ b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/CustomUserDetailsService.java
@@ -21,5 +21,4 @@ public class CustomUserDetailsService implements UserDetailsService {
return userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
}
-
} \ No newline at end of file
diff --git a/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/UserService.java b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/UserService.java
new file mode 100644
index 0000000..a4e18be
--- /dev/null
+++ b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/UserService.java
@@ -0,0 +1,12 @@
+package com.example.spring.security.service;
+
+import java.util.List;
+import java.util.Optional;
+
+import com.example.spring.security.entity.User;
+
+public interface UserService {
+ public Optional<User> findById(Long id);
+ public List<User> findAll();
+ public void updateUser(Long userId, String description);
+}
diff --git a/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/UserServiceImpl.java b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/UserServiceImpl.java
new file mode 100644
index 0000000..0d44d21
--- /dev/null
+++ b/spring-boot/10-role-based-security/src/main/java/com/example/spring/security/service/UserServiceImpl.java
@@ -0,0 +1,49 @@
+package com.example.spring.security.service;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Sort;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Service;
+
+import com.example.spring.security.entity.User;
+import com.example.spring.security.repository.UserRepository;
+
+import jakarta.transaction.Transactional;
+
+@Service
+public class UserServiceImpl implements UserService {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Override
+ public Optional<User> findById(Long id) {
+ return userRepository.findById(id);
+ }
+
+ @Override
+ public List<User> findAll() {
+ return userRepository.findAll(Sort.by(Sort.Direction.ASC, "username"));
+ }
+
+ @PreAuthorize("hasRole('ADMIN')")
+ @Transactional
+ @Override
+ public void updateUser(Long id, String description) {
+ // Do whatever the work needed.
+ // ...
+
+ Optional<User> userOpt = userRepository.findById(id);
+
+ User user = userOpt.get();
+
+ user.setDescription(description);
+
+ // NO userRepository.save(user) IS ACTUALLY REQUIRED HERE since the method
+ // has been annotated with @Transactional!
+ // Transaction commits -> Hibernate issues the SQL UPDATE.
+ }
+}
diff --git a/spring-boot/10-role-based-security/src/main/resources/templates/error.html b/spring-boot/10-role-based-security/src/main/resources/templates/error.html
new file mode 100644
index 0000000..ea5a329
--- /dev/null
+++ b/spring-boot/10-role-based-security/src/main/resources/templates/error.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html xmlns:th="http://thymeleaf.org">
+<head>
+ <title>Error Occurred</title>
+</head>
+<body>
+ <h1>An error occurred!</h1>
+ <p>Status: <span th:text="${status}">500</span></p>
+ <p>Message: <span th:text="${message}">Error Message</span></p>
+ <p>Timestamp: <span th:text="${timestamp}">Date</span></p>
+</body>
+</html> \ No newline at end of file
diff --git a/spring-boot/10-role-based-security/src/main/resources/templates/error/403.html b/spring-boot/10-role-based-security/src/main/resources/templates/error/403.html
new file mode 100644
index 0000000..c1db2c0
--- /dev/null
+++ b/spring-boot/10-role-based-security/src/main/resources/templates/error/403.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html xmlns:th="http://thymeleaf.org">
+<head>
+ <title>Error Occurred</title>
+</head>
+<body>
+ <h1>You have no permission!</h1>
+ <p>Status: <span th:text="${status}">500</span></p>
+ <p>Message: <span th:text="${message}">Error Message</span></p>
+ <p>Timestamp: <span th:text="${timestamp}">Date</span></p>
+</body>
+</html> \ No newline at end of file
diff --git a/spring-boot/10-role-based-security/src/main/resources/templates/layout/main.html b/spring-boot/10-role-based-security/src/main/resources/templates/layout/main.html
index df96fc5..0b20361 100644
--- a/spring-boot/10-role-based-security/src/main/resources/templates/layout/main.html
+++ b/spring-boot/10-role-based-security/src/main/resources/templates/layout/main.html
@@ -18,7 +18,7 @@
<ul>
<li><a th:href="@{/}">Home</a></li>
<li><a th:href="@{/contact}">Contact Us</a></li>
- <li sec:authorize="hasRole('ADMIN')"><a th:href="@{/admin}">Admin</a></li>
+ <li sec:authorize="hasRole('ADMIN')"><a th:href="@{/security/users}">Users</a></li>
<li sec:authorize="isAuthenticated()"><a th:href="@{/profile/{name}(name=${#authentication.name})}">Profile</a></li>
<li sec:authorize="isAuthenticated()"><a th:href="@{/logout}">Logout</a></li>
</ul>
diff --git a/spring-boot/10-role-based-security/src/main/resources/templates/security/user-form.html b/spring-boot/10-role-based-security/src/main/resources/templates/security/user-form.html
new file mode 100644
index 0000000..a27ae7d
--- /dev/null
+++ b/spring-boot/10-role-based-security/src/main/resources/templates/security/user-form.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org"
+ th:replace="~{layout/main :: layout(title='User', content=~{::main})}">
+
+<body>
+ <main>
+ <form th:action="@{/security/user/update}" th:object="${userForm}" method="post">
+ <!-- Hidden field binds the "id" property seamlessly -->
+ <input type="hidden" th:field="*{id}" />
+
+ <div class="form-field-container">
+ <label>Description</label>
+ <textarea th:field="*{description}" placeholder="Description"></textarea>
+ <div class="validation-error" th:if="${#fields.hasErrors('description')}" th:errors="*{description}"></div>
+ </div>
+
+ <button type="submit">Save</button>
+ </form>
+ </main>
+</body>
+
+</html> \ No newline at end of file
diff --git a/spring-boot/10-role-based-security/src/main/resources/templates/security/users.html b/spring-boot/10-role-based-security/src/main/resources/templates/security/users.html
new file mode 100644
index 0000000..81752c8
--- /dev/null
+++ b/spring-boot/10-role-based-security/src/main/resources/templates/security/users.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html xmlns:th="http://www.thymeleaf.org"
+ th:replace="~{layout/main :: layout(title='Users', content=~{::main})}">
+
+<body>
+ <main>
+ <table>
+ <thead>
+ <tr>
+ <th>ID</th>
+ <th>Username</th>
+ <th>Description</th>
+ <th>Edit</th>
+ </tr>
+ </thead>
+ <tbody>
+ <!-- th:each loops over the "userss" list sent by the controller -->
+ <tr th:each="user : ${users}">
+ <!-- th:text updates the cell contents dynamically -->
+ <td th:text="${user.id}">1</td>
+ <td th:text="${user.username}">Username</td>
+ <td th:text="${user.description}">User description</td>
+ <td><a th:href="@{/security/user/update/{id}(id=${user.id})}">Edit</a></td>
+ </tr>
+ </tbody>
+ </table>
+ </main>
+</body>
+
+</html> \ No newline at end of file