Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change password #140

Merged
merged 4 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion http/login.http
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
POST localhost:8080/login
POST localhost:8080/api/auth/login
Content-Type: application/json

{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,43 @@
package com.tistory.shanepark.dutypark.admin.controller

import com.tistory.shanepark.dutypark.member.domain.dto.MemberDto
import com.tistory.shanepark.dutypark.member.service.MemberService
import com.tistory.shanepark.dutypark.member.service.RefreshTokenService
import com.tistory.shanepark.dutypark.security.domain.dto.RefreshTokenDto
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Sort
import org.springframework.data.web.PageableDefault
import org.springframework.data.web.SortDefault
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/admin/api/")
class AdminController(
private val refreshTokenService: RefreshTokenService
private val refreshTokenService: RefreshTokenService,
private val memberService: MemberService,
) {
@GetMapping("/refresh-tokens")
fun findAllRefreshTokens(): List<RefreshTokenDto> {
return refreshTokenService.findAllWithMemberOrderByLastUsedDesc()
}

@GetMapping("/members")
fun members(
@PageableDefault(page = 0, size = 10)
@SortDefault(sort = ["name"], direction = Sort.Direction.ASC)
page: Pageable,
@RequestParam(required = false, defaultValue = "") name: String,
): Page<MemberDto> {
return memberService.searchMembers(page, name)
}

@GetMapping("/members-all")
fun findAllMembers(): List<MemberDto> {
return memberService.findAll()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class ViewExceptionControllerAdvice {

@ExceptionHandler
fun notAuthorizedHandler(e: DutyparkAuthException, request: HttpServletRequest): ModelAndView {
val redirectUrl = "redirect:/login?referer=" + URLEncoder.encode(request.requestURI, "UTF-8")
val redirectUrl = "redirect:/auth/login?referer=" + URLEncoder.encode(request.requestURI, "UTF-8")
return ModelAndView(redirectUrl)
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tistory.shanepark.dutypark.member.repository

import com.tistory.shanepark.dutypark.member.domain.entity.Member
import com.tistory.shanepark.dutypark.security.domain.entity.RefreshToken
import org.springframework.data.jpa.repository.EntityGraph
import org.springframework.data.jpa.repository.JpaRepository
Expand All @@ -17,6 +18,8 @@ interface RefreshTokenRepository : JpaRepository<RefreshToken, Long> {
@EntityGraph(attributePaths = ["member"])
fun findAllByMemberIdOrderByLastUsedDesc(id: Long): List<RefreshToken>

fun findAllByMember(member: Member): List<RefreshToken>

fun findAllByValidUntilIsBefore(now: LocalDateTime): List<RefreshToken>

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.tistory.shanepark.dutypark.member.service

import com.tistory.shanepark.dutypark.common.exceptions.DutyparkAuthException
import com.tistory.shanepark.dutypark.member.domain.entity.Member
import com.tistory.shanepark.dutypark.member.repository.MemberRepository
import com.tistory.shanepark.dutypark.member.repository.RefreshTokenRepository
import com.tistory.shanepark.dutypark.security.config.JwtConfig
Expand Down Expand Up @@ -63,4 +64,10 @@ class RefreshTokenService(
return refreshTokenRepository.findAllWithMemberOrderByLastUsedDesc().map { RefreshTokenDto.of(it) }
}

fun revokeAllRefreshTokensByMember(member: Member) {
val findAllByMember = refreshTokenRepository.findAllByMember(member)
log.info("Revoked {} refresh tokens of member {}", findAllByMember.size, member.email)
refreshTokenRepository.deleteAll(findAllByMember)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.tistory.shanepark.dutypark.member.service.RefreshTokenService
import com.tistory.shanepark.dutypark.security.config.JwtConfig
import com.tistory.shanepark.dutypark.security.domain.dto.LoginDto
import com.tistory.shanepark.dutypark.security.domain.dto.LoginMember
import com.tistory.shanepark.dutypark.security.domain.dto.PasswordChangeDto
import com.tistory.shanepark.dutypark.security.domain.entity.RefreshToken
import com.tistory.shanepark.dutypark.security.service.AuthService
import jakarta.servlet.http.HttpServletRequest
Expand All @@ -17,6 +18,7 @@ import org.springframework.ui.Model
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/api/auth")
class AuthController(
private val authService: AuthService,
private val refreshTokenService: RefreshTokenService,
Expand All @@ -25,7 +27,7 @@ class AuthController(
) {
private val log = org.slf4j.LoggerFactory.getLogger(AuthController::class.java)

@PostMapping("/login")
@PostMapping("login")
fun login(
@RequestBody loginDto: LoginDto,
model: Model,
Expand Down Expand Up @@ -85,6 +87,18 @@ class AuthController(
}
}

@PutMapping("password")
fun changePassword(
@Login loginMember: LoginMember,
@RequestBody(required = true) param: PasswordChangeDto
): ResponseEntity<String> {
if (loginMember.id != param.memberId && !loginMember.isAdmin) {
throw DutyparkAuthException("You are not authorized to change this password")
}
authService.changePassword(param, loginMember.isAdmin)
return ResponseEntity.ok().body("Password Changed")
}

@GetMapping("/status")
fun loginStatus(
@Login(required = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import jakarta.servlet.http.HttpSession
import org.springframework.http.HttpHeaders
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.annotation.CookieValue
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RequestMapping

@Controller
@RequestMapping("/auth")
class AuthViewController : ViewController() {

@GetMapping("/login")
@GetMapping("login")
fun loginPage(
@CookieValue(name = "rememberMe", required = false) rememberMe: String?,
@RequestHeader(HttpHeaders.REFERER, required = false) referer: String?,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.tistory.shanepark.dutypark.security.domain.dto

data class PasswordChangeDto(
val memberId: Long,
val currentPassword: String?,
val newPassword: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class AdminAuthFilter : Filter {
log.info("$loginMember is not admin.")
response.sendError(HttpServletResponse.SC_FORBIDDEN)
}
response.sendRedirect("/login")
response.sendRedirect("/auth/login")
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.tistory.shanepark.dutypark.member.repository.MemberRepository
import com.tistory.shanepark.dutypark.member.service.RefreshTokenService
import com.tistory.shanepark.dutypark.security.domain.dto.LoginDto
import com.tistory.shanepark.dutypark.security.domain.dto.LoginMember
import com.tistory.shanepark.dutypark.security.domain.dto.PasswordChangeDto
import com.tistory.shanepark.dutypark.security.domain.entity.RefreshToken
import com.tistory.shanepark.dutypark.security.domain.enums.TokenStatus
import jakarta.servlet.http.Cookie
Expand Down Expand Up @@ -79,4 +80,24 @@ class AuthService(
response.addCookie(cookie)
}

fun changePassword(param: PasswordChangeDto, byAdmin: Boolean = false) {
val member = memberRepository.findById(param.memberId).orElseThrow {
log.info("change password failed. member not exist:${param.memberId}")
throw DutyparkAuthException("존재하지 않는 회원입니다.")
}

if (!byAdmin) {
val passwordMatch = passwordEncoder.matches(param.currentPassword, member.password)
if (!passwordMatch) {
log.info("change password failed. password not match:${param.memberId}")
throw DutyparkAuthException("비밀번호가 일치하지 않습니다.")
}
}

member.password = passwordEncoder.encode(param.newPassword)
refreshTokenService.revokeAllRefreshTokensByMember(member)

log.info("Member password changed. member:${param.memberId}")
}

}
10 changes: 3 additions & 7 deletions src/main/resources/static/css/base.css
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
@font-face {
src: url('../fonts/NexonMaplestoryLight.woff2') format('woff2');
font-display: swap;
font-family: 'NexonMaplestory';
font-weight: 300;
font-style: normal;
src: url('https://cdn.jsdelivr.net/gh/webfontworld/NexonMaplestory/NexonMaplestoryLight.eot');
src: url('https://cdn.jsdelivr.net/gh/webfontworld/NexonMaplestory/NexonMaplestoryLight.eot?#iefix') format('embedded-opentype'),
url('https://cdn.jsdelivr.net/gh/webfontworld/NexonMaplestory/NexonMaplestoryLight.woff2') format('woff2'),
url('https://cdn.jsdelivr.net/gh/webfontworld/NexonMaplestory/NexonMaplestoryLight.woff') format('woff'),
url('https://cdn.jsdelivr.net/gh/webfontworld/NexonMaplestory/NexonMaplestoryLight.ttf') format("truetype");
font-display: swap;
}

[v-cloak] {
display: none;
}

body {
font-family: NexonMaplestory;
font-family: NexonMaplestory, sans-serif;
--bs-body-font-family: NexonMaplestory;
}

Expand Down
Binary file not shown.
Loading
Loading