This commit is contained in:
2026-06-02 19:41:39 +07:00
parent 7350e3ebb2
commit 5ce3860502
11 changed files with 194 additions and 7 deletions

View File

@@ -22,9 +22,12 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-webmvc' implementation 'org.springframework.boot:spring-boot-starter-webmvc'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test' testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test'
testImplementation 'org.springframework.boot:spring-boot-starter-thymeleaf-test' testImplementation 'org.springframework.boot:spring-boot-starter-thymeleaf-test'
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test' testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
testImplementation 'org.springframework.security:spring-security-test'
runtimeOnly 'com.mysql:mysql-connector-j' runtimeOnly 'com.mysql:mysql-connector-j'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
// Source: https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf // Source: https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf

View File

@@ -0,0 +1,34 @@
package com.example.server_site_api.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 1. Authorize HTTP requests based on URL patterns
.authorizeHttpRequests(auth -> auth
.requestMatchers("/", "/public/**", "/auth/**").permitAll() // all bat dau voi public se mo
.requestMatchers("/users/create-new").hasRole("ADMIN") // phai co role admin moi co the truy cap
.anyRequest().authenticated() // tat ca api con lai deu require login
)
.formLogin(form -> form
.loginPage("/auth/login")
.loginProcessingUrl("/login_submit")
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
}

View File

@@ -0,0 +1,15 @@
package com.example.server_site_api.controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller()
@RequestMapping("auth")
public class AuthController {
@GetMapping("login")
public String loadLoginPage() {
return "Login";
}
}

View File

@@ -2,14 +2,14 @@ package com.example.server_site_api.controllers;
import com.example.server_site_api.models.Users; import com.example.server_site_api.models.Users;
import com.example.server_site_api.servies.UserService; import com.example.server_site_api.servies.UserService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import java.util.Optional;
import java.util.List;
@Controller @Controller
@RequestMapping("users") @RequestMapping("users")
@@ -18,10 +18,49 @@ public class UserController {
@Autowired @Autowired
private UserService us; private UserService us;
@GetMapping("/create-new")
private String formNewUser(Model model) {
model.addAttribute("user", new Users());
return "FormNewUser";
}
@GetMapping("/delete/{id}")
private String deleteUser(@PathVariable("id") long id) {
System.out.println("id" + id);
us.deleteUser(id);
return "redirect:/users";
}
@GetMapping("/edit/{id}")
private String editUser(@PathVariable("id") long id, Model model) {
System.out.println("id da vao " + id);
Optional<Users> usersOptional = us.findById(id);
if(usersOptional.isPresent()) {
Users editUser = usersOptional.get();
model.addAttribute("editUser", editUser);
}
return "FormEditUser";
}
@GetMapping @GetMapping
private String loadUserManagerPage(Model model) { private String loadUserManagerPage(Model model) {
model.addAttribute("users", us.getAllUsers()); model.addAttribute("users", us.getAllUsers());
System.out.println(us.getAllUsers());
return "UserManager"; return "UserManager";
} }
@PostMapping("save")
private String saveEditUser(@ModelAttribute("editUser") Users user) {
System.out.println("user" + user);
us.createNewUser(user);
return "redirect:/users";
}
@PostMapping()
private String saveUser(@ModelAttribute("user") Users user) {
us.createNewUser(user);
return "redirect:/users";
}
} }

View File

@@ -55,7 +55,7 @@ public class Users {
} }
public String getGender() { public String getGender() {
return gender; return this.gender;
} }
public Integer getAge() { public Integer getAge() {

View File

@@ -0,0 +1,26 @@
package com.example.server_site_api.servies;
import com.example.server_site_api.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class CustomUserDetialService implements UserDetailsService {
@Autowired
UserRepository ur;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return User
.withUsername("user")
.password("{noop}123123")
.roles("ADMIN")
.build();
}
}

View File

@@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
import java.util.Optional;
@Service @Service
public class UserService { public class UserService {
@@ -15,4 +16,16 @@ public class UserService {
public List<Users> getAllUsers() { public List<Users> getAllUsers() {
return ur.findAll(); return ur.findAll();
} }
public Users createNewUser(Users newUser) {
return ur.save(newUser);
}
public void deleteUser(long userId) {
ur.deleteById(userId);
}
public Optional<Users> findById(Long id) {
return ur.findById(id);
}
} }

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Edit User</title>
</head>
<body>
<form th:object="${editUser}" method="post" th:action="@{/users/save}">
<input th:text="${editUser.getId()}" th:field="*{id}" hidden>
<input th:text="${editUser.getUsername()}" type="text" th:field="*{username}" placeholder="nhap username">
<input th:text="${editUser.getPassword()}" type="text" th:field="*{password}" placeholder="nhap password">
<input th:text="${editUser.getGender()}" type="text" th:field="*{gender}" placeholder="nhap gender">
<input th:text="${editUser.getAge()}" type="text" th:field="*{age}" placeholder="nhap age">
<button>save</button>
</form>
</body>
</html>

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Tao New User</title>
</head>
<body>
<form th:object="${user}" method="post" th:action="@{/users}">
<input type="text" th:field="*{username}" placeholder="nhap username">
<input type="text" th:field="*{password}" placeholder="nhap password">
<input type="text" th:field="*{gender}" placeholder="nhap gender">
<input type="text" th:field="*{age}" placeholder="nhap age">
<button>save</button>
</form>
</body>
</html>

View File

@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h2>Form Login By Me</h2>
<form th:action="@{/login_submit}" method="post">
<input name="username" placeholder="username" required>
<input name="password" placeholder="password" required>
<button>Login</button>
</form>
</body>
</html>

View File

@@ -15,6 +15,7 @@
<th>password</th> <th>password</th>
<th>gender</th> <th>gender</th>
<th>age</th> <th>age</th>
<th>tools</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -23,10 +24,16 @@
<td th:text="${u.getId()}"></td> <td th:text="${u.getId()}"></td>
<td th:text="${u.getUsername()}"></td> <td th:text="${u.getUsername()}"></td>
<td th:text="${u.getPassword()}"></td> <td th:text="${u.getPassword()}"></td>
<td th:text="${u.getGender().equals('male')} ? 'nam' : 'nu'"></td> <td th:text="${u.getGender()}"></td>
<td th:text="${u.getAge()}"></td> <td th:text="${u.getAge()}"></td>
<td>
<a th:href="'/users/delete/' + ${u.getId()}">delete</a>
<a th:href="'/users/edit/' + ${u.getId()}">edit</a>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<a href="/users/create-new">Tao Moi</a>
</body> </body>
</html> </html>