1
+ package io.study.kotlinapiserver.api.domain.member.application
2
+
3
+ import io.study.kotlinapiserver.api.domain.member.domain.MemberDomainService
4
+ import io.study.kotlinapiserver.api.domain.member.domain.dto.request.MemberResetPasswordRequest
5
+ import io.study.kotlinapiserver.api.domain.member.domain.event.ResetPasswordEvent
6
+ import io.study.kotlinapiserver.web.base.event.Events
7
+ import org.springframework.stereotype.Service
8
+ import org.springframework.transaction.annotation.Transactional
9
+ import java.security.SecureRandom
10
+ import java.util.*
11
+
12
+ @Service
13
+ @Transactional(readOnly = true )
14
+ class MemberResetService (
15
+
16
+ private val memberDomainService : MemberDomainService ,
17
+
18
+ ) {
19
+ companion object {
20
+ private const val VALID_CHARACTERS = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
21
+ private const val SPECIAL_CHARACTERS = " !@#$%^&*()\\ -_=+"
22
+ private const val MAX_SPECIAL_CHARACTER = 3 ;
23
+ private const val MIN_LENGTH = 8 ;
24
+ private const val MAX_LENGTH = 16 ;
25
+ }
26
+
27
+ @Transactional
28
+ fun resetPassword (request : MemberResetPasswordRequest ) {
29
+ val tempPassword = createTempPassword()
30
+
31
+ memberDomainService.resetPassword(MemberResetPasswordRequest (request.email, tempPassword))
32
+
33
+ /* * 비밀번호 변경 메일 전송 **/
34
+ publishResetPasswordSuccessEmailEvent(tempPassword, request.email)
35
+ }
36
+
37
+ private fun createTempPassword (): String {
38
+ val random = SecureRandom ()
39
+ val passwordLength = MIN_LENGTH + random.nextInt(MAX_LENGTH - MIN_LENGTH + 1 )
40
+ val password = StringBuilder (passwordLength)
41
+
42
+ val specialCharacterLength = addSpecialCharacters(password)
43
+ addValidCharacters(specialCharacterLength, passwordLength, password)
44
+
45
+ return shufflePassword(password)
46
+ }
47
+
48
+ private fun publishResetPasswordSuccessEmailEvent (
49
+ password : String ,
50
+ registeredEmail : String ,
51
+ ) {
52
+ Events .raise(ResetPasswordEvent .of(password, registeredEmail))
53
+ }
54
+
55
+ private fun shufflePassword (password : StringBuilder ): String {
56
+ val map = password.toList()
57
+ Collections .shuffle(map)
58
+ return map.joinToString(" " )
59
+ }
60
+
61
+ private fun addSpecialCharacters (password : StringBuilder ): Int {
62
+ val random = SecureRandom ()
63
+ val specialCharacterLength = random.nextInt(MAX_SPECIAL_CHARACTER ) + 1
64
+
65
+ for (i in 0 until specialCharacterLength) {
66
+ password.append(SPECIAL_CHARACTERS [random.nextInt(SPECIAL_CHARACTERS .length)])
67
+ }
68
+
69
+ return specialCharacterLength
70
+ }
71
+
72
+ private fun addValidCharacters (
73
+ specialCharacterLength : Int ,
74
+ passwordLength : Int ,
75
+ password : StringBuilder
76
+ ) {
77
+ val random = SecureRandom ()
78
+ for (i in specialCharacterLength until passwordLength) {
79
+ val index = random.nextInt(VALID_CHARACTERS .length)
80
+ password.append(VALID_CHARACTERS [index])
81
+ }
82
+ }
83
+ }
0 commit comments