Added base profile page, navbar, changed some href binding

This commit is contained in:
neviyn 2021-05-07 11:20:23 +01:00
parent e4dd1c243e
commit 4e7643f976
9 changed files with 145 additions and 6 deletions

View File

@ -7,12 +7,14 @@ import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.multipart.MultipartFile
import java.security.MessageDigest
import java.util.*
import javax.validation.Valid
import javax.validation.constraints.NotEmpty
@Controller
@ -78,6 +80,37 @@ class ImageController
}
@Controller
@RequestMapping("/user")
class MemberController
@Autowired constructor(
val memberRepository: MemberRepository
) {
@GetMapping
fun memberDetails(@AuthenticationPrincipal userDetails: CustomUserDetails, model: Model) : String {
val user = DisplayUser(userDetails.getId(), userDetails.username, userDetails.getEmail(), "", "")
model.addAttribute("userData", user)
return "user"
}
@PostMapping
fun updateLoggedInUser(@Valid @ModelAttribute userData: DisplayUser, @AuthenticationPrincipal userDetails: CustomUserDetails, model: Model): String {
if (userData.id == userDetails.getId() && passwordEncoder().matches(userData.oldPassword, userDetails.password)) {
val user = memberRepository.findById(userDetails.getId()).get()
user.email = userData.email
if (userData.password.isNotEmpty()) user.password = passwordEncoder().encode(userData.password)
memberRepository.save(user)
model.addAttribute("message", "Your profile has been updated")
} else {
model.addAttribute("error", "Incorrect existing password")
}
model.addAttribute("userData", DisplayUser(userData.id, userData.username, userData.email, userData.password, ""))
return "user"
}
}
@Controller
@RequestMapping("/upload")
class UploadController

View File

@ -0,0 +1,12 @@
package uk.co.neviyn.booru
import javax.validation.constraints.NotBlank
import javax.validation.constraints.Positive
data class DisplayUser(
@field:Positive val id: Long,
val username: String,
val email: String,
val password: String,
@field:NotBlank val oldPassword: String
)

View File

@ -21,7 +21,7 @@ class SecurityConfig
val userDetailsService: CustomUserDetailsService
) : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http.authorizeRequests().antMatchers("/upload").hasAuthority("USER")
http.authorizeRequests().antMatchers("/upload/**", "/user/**").hasAuthority("USER")
.anyRequest().permitAll().and()
.formLogin().loginPage("/login").permitAll().and()
.logout().logoutSuccessUrl("/").permitAll().and()
@ -50,6 +50,10 @@ constructor(
override fun isCredentialsNonExpired(): Boolean = true
override fun isEnabled(): Boolean = member.enabled
fun getId(): Long = member.id
fun getEmail(): String = member.email
}
@Service

View File

@ -1,5 +1,5 @@
<!DOCTYPE HTML>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<body>
<div th:fragment="header" th:remove="tag">
<meta charset="UTF-8">
@ -10,5 +10,33 @@
<script th:src="@{/webjars/bootstrap/5.0.0-beta3/js/bootstrap.bundle.min.js}"></script>
<link th:href="@{/webjars/bootstrap-icons/1.4.1/font/bootstrap-icons.css}" rel="stylesheet">
</div>
<div th:fragment="navbar">
<form id="logoutForm" method="POST" th:action="@{/logout}">
<input name="${_csrf.parameterName}" type="hidden" value="${_csrf.token}"/>
</form>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">
Booru
</a>
<button aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler"
data-bs-target="#navbarNavAltMarkup" data-bs-toggle="collapse" type="button">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav me-auto">
<a class="nav-link" th:href="${#mvc.url('IC#getGalleryPage').build()}">Posts</a>
<a class="nav-link" th:href="${#mvc.url('UC#showUploadPage').build()}">Upload</a>
<a class="nav-link" th:href="${#mvc.url('MC#memberDetails').build()}">My Account</a>
</div>
<div sec:authorize="isAuthenticated()" class="d-flex">
<span sec:authentication="name" class="navbar-text"></span>
<a class="nav-link" onclick="document.forms['logoutForm'].submit()" style="cursor: pointer"><i
class="bi bi-box-arrow-right me-1"></i>Logout</a>
</div>
</div>
</div>
</nav>
</div>
</body>
</html>

View File

@ -5,6 +5,7 @@
<title>Gallery</title>
</head>
<body>
<div th:replace="fragments :: navbar"></div>
<div class="container">
<div class="row">
<div class="col-2" th:each="image : ${imagePage.content}">

View File

@ -14,12 +14,16 @@
<div class="row">
<div class="col">
<p class="text-center">
<a href="/gallery" class="text-decoration-none">Browse all</a>
<a th:href="${#mvc.url('IC#getGalleryPage').build()}" class="text-decoration-none">Browse All</a>
<span class="text-secondary"> |</span>
<a th:href="${#mvc.url('UC#showUploadPage').build()}" class="text-decoration-none">Upload New</a>
<span class="text-secondary"> |</span>
<a th:href="${#mvc.url('MC#memberDetails').build()}" class="text-decoration-none">My Account</a>
</p>
</div>
</div>
<div class="row justify-content-center">
<form class="col-6 text-center" action="/gallery">
<form class="col-xs-12 col-sm-9 col-md-6 text-center" action="/gallery">
<!--suppress HtmlFormInputWithoutLabel -->
<input class="form-control" id="imageSearch" pattern="[a-zA-Z0-9\s_]*" placeholder="Ex: blue_eyes smile" type="search" name="tags">
<button class="btn btn-primary mt-1 w-25" type="submit">Search</button>

View File

@ -39,7 +39,7 @@
</div>
<div class="row justify-content-center mt-3">
<div class="col text-center">
<a class="btn btn-secondary btn-lg" href="/" role="button">Home</a>
<a class="btn btn-secondary btn-lg" th:href="${#mvc.url('BC#landingPage').build()}" role="button">Home</a>
</div>
</div>
</div>

View File

@ -5,6 +5,7 @@
<title>Upload</title>
</head>
<body>
<div th:replace="fragments :: navbar"></div>
<div class="container">
<div class="row justify-content-center">
<div class="col text-center">
@ -12,7 +13,7 @@
</div>
</div>
<div class="row justify-content-center">
<form action="/upload" class="mb-3 col-6 text-center" enctype="multipart/form-data" method="POST">
<form th:action="${#mvc.url('UC#uploadFile').build()}" class="mb-3 col-6 text-center" enctype="multipart/form-data" method="POST">
<input th:name="${_csrf.parameterName}" type="hidden" th:value="${_csrf.token}"/>
<label class="form-label" for="formFile">Image file</label>
<input class="form-control" id="formFile" name="file" type="file" th:accept="${@imageConfigurationProperties.typeListForFormFilter()}">

View File

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta th:replace="fragments :: header"/>
<title>My Account</title>
</head>
<body>
<div th:replace="fragments :: navbar"></div>
<div class="container">
<div class="row mt-3 justify-content-center">
<div class="col">
<h2 class="display-2 text-center mb-3">Profile</h2>
</div>
</div>
<form method="post" th:action="${#mvc.url('MC#updateLoggedInUser').build()}" th:object="${userData}">
<div class="row justify-content-center mb-3">
<div class="col-8">
<input th:field="*{id}" type="hidden"/>
<div class="input-group mb-3">
<span class="input-group-text">Username</span>
<input aria-label="Username" class="form-control" readonly th:field="*{username}" type="text">
</div>
<div class="input-group mb-3">
<span class="input-group-text">Email</span>
<input aria-label="Email" class="form-control" th:field="*{email}" type="text">
</div>
<div class="input-group mb-3">
<span class="input-group-text">Password</span>
<input aria-label="Password" class="form-control" th:field="*{password}" type="password">
</div>
<p>Please enter your existing password to update your profile.</p>
<div class="input-group mb-3">
<span class="input-group-text">Existing Password</span>
<input aria-label="Existing Password" class="form-control form-control-lg" th:field="*{oldPassword}"
type="password">
</div>
</div>
</div>
<div class="row justify-content-center">
<div class="col-2 d-grid">
<button class="btn btn-primary btn-lg" type="submit">Update</button>
</div>
</div>
</form>
<div class="row">
<div class="col text-center">
<span class="text-success" th:text="${message}"></span>
</div>
</div>
<div class="row">
<div class="col text-center">
<span class="has-error text-danger" th:text="${error}"></span>
</div>
</div>
</div>
</body>