11package com .featureprobe .api .service ;
22
33import com .featureprobe .api .auth .UserPasswordAuthenticationToken ;
4+ import com .featureprobe .api .base .constants .MessageKey ;
45import com .featureprobe .api .base .enums .ResourceType ;
56import com .featureprobe .api .base .enums .RoleEnum ;
6- import com .featureprobe .api .base .exception .PasswordErrorException ;
7+ import com .featureprobe .api .base .exception .ForbiddenException ;
78import com .featureprobe .api .base .exception .ResourceConflictException ;
89import com .featureprobe .api .base .exception .ResourceNotFoundException ;
910import com .featureprobe .api .dto .MemberCreateRequest ;
1415import com .featureprobe .api .entity .Member ;
1516import com .featureprobe .api .mapper .MemberMapper ;
1617import com .featureprobe .api .repository .MemberRepository ;
17- import lombok . AllArgsConstructor ;
18+ import com . featureprobe . api . util . PageRequestUtil ;
1819import lombok .extern .slf4j .Slf4j ;
1920import org .apache .commons .lang3 .StringUtils ;
2021import org .springframework .data .domain .Page ;
21- import org .springframework .data .domain .PageRequest ;
2222import org .springframework .data .domain .Pageable ;
2323import org .springframework .data .domain .Sort ;
2424import org .springframework .data .jpa .domain .Specification ;
2525import org .springframework .security .core .context .SecurityContextHolder ;
2626import org .springframework .security .crypto .bcrypt .BCryptPasswordEncoder ;
27+ import org .springframework .security .crypto .password .PasswordEncoder ;
2728import org .springframework .stereotype .Service ;
2829import org .springframework .transaction .annotation .Transactional ;
2930
30- import javax .persistence .criteria .CriteriaBuilder ;
31- import javax .persistence .criteria .CriteriaQuery ;
32- import javax .persistence .criteria .Predicate ;
33- import javax .persistence .criteria .Root ;
34- import java .util .ArrayList ;
3531import java .util .Date ;
3632import java .util .List ;
33+ import java .util .Optional ;
3734import java .util .stream .Collectors ;
3835
3936
4037@ Slf4j
41- @ AllArgsConstructor
4238@ Service
4339public class MemberService {
4440
4541 private MemberRepository memberRepository ;
4642
43+ private PasswordEncoder passwordEncoder ;
44+
45+ public MemberService (MemberRepository memberRepository ) {
46+ this .memberRepository = memberRepository ;
47+ this .passwordEncoder = new BCryptPasswordEncoder ();
48+ }
49+
4750 @ Transactional (rollbackFor = Exception .class )
4851 public List <MemberResponse > create (MemberCreateRequest createRequest ) {
49- List <Member > members = new ArrayList <>();
50- createRequest .getAccounts ().stream ().forEach (account -> {
51- if (memberRepository .findByAccountIncludeDeleted (account ).isPresent ()) {
52- throw new ResourceConflictException (ResourceType .MEMBER );
53- }
54- members .add (newMember (account , createRequest .getPassword ()));
55- });
56- List <Member > saveMembers = memberRepository .saveAll (members );
57- return saveMembers .stream ().map (item ->
52+ List <Member > savedMembers = memberRepository .saveAll (newNumbers (createRequest ));
53+
54+ return savedMembers .stream ().map (item ->
5855 MemberMapper .INSTANCE .entityToResponse (item )).collect (Collectors .toList ());
5956 }
6057
58+ private List <Member > newNumbers (MemberCreateRequest createRequest ) {
59+ return createRequest .getAccounts ()
60+ .stream ()
61+ .filter (this ::notExistsAccount )
62+ .map (account -> newMember (account , createRequest .getPassword ())).collect (Collectors .toList ());
63+ }
64+
65+ private boolean notExistsAccount (String account ) {
66+ if (memberRepository .findByAccountIncludeDeleted (account ).isPresent ()) {
67+ throw new ResourceConflictException (ResourceType .MEMBER );
68+ }
69+ return true ;
70+ }
71+
6172 private Member newMember (String account , String password ) {
6273 Member member = new Member ();
6374 member .setAccount (account );
@@ -68,73 +79,88 @@ private Member newMember(String account, String password) {
6879
6980 @ Transactional (rollbackFor = Exception .class )
7081 public MemberResponse update (MemberUpdateRequest updateRequest ) {
71- UserPasswordAuthenticationToken authentication =
72- (UserPasswordAuthenticationToken ) SecurityContextHolder .getContext ().getAuthentication ();
73- Member member = memberRepository .findByAccount (updateRequest .getAccount ())
74- .orElseThrow (() -> new ResourceNotFoundException (ResourceType .MEMBER , updateRequest .getAccount ()));
82+ verifyAdminPrivileges ();
83+
84+ Member member = findMemberByAccount (updateRequest .getAccount ());
7585 MemberMapper .INSTANCE .mapEntity (updateRequest , member );
76- if (authentication .isAdmin ()) {
77- return MemberMapper .INSTANCE .entityToResponse (memberRepository .save (member ));
78- }
79- return null ;
86+ return MemberMapper .INSTANCE .entityToResponse (memberRepository .save (member ));
8087 }
8188
8289 @ Transactional (rollbackFor = Exception .class )
8390 public MemberResponse modifyPassword (MemberModifyPasswordRequest modifyPasswordRequest ) {
84- UserPasswordAuthenticationToken authentication =
85- (UserPasswordAuthenticationToken ) SecurityContextHolder .getContext ().getAuthentication ();
86- Member member = memberRepository .findByAccount (authentication .getAccount ())
87- .orElseThrow (() -> new ResourceNotFoundException (ResourceType .MEMBER , authentication .getAccount ()));
88- if (new BCryptPasswordEncoder ().matches (modifyPasswordRequest .getOldPassword (), member .getPassword ())) {
89- member .setPassword (new BCryptPasswordEncoder ().encode (modifyPasswordRequest .getNewPassword ()));
90- return MemberMapper .INSTANCE .entityToResponse (memberRepository .save (member ));
91- } else {
92- throw new PasswordErrorException ();
91+ Member member = findLoggedInMember ();
92+ verifyPassword (modifyPasswordRequest .getOldPassword (), member .getPassword ());
93+
94+ member .setPassword (passwordEncoder .encode (modifyPasswordRequest .getNewPassword ()));
95+ return MemberMapper .INSTANCE .entityToResponse (memberRepository .save (member ));
96+ }
97+
98+ private void verifyPassword (String oldPassword , String newPassword ) {
99+ if (!passwordEncoder .matches (oldPassword , newPassword )) {
100+ throw new IllegalArgumentException (MessageKey .INVALID_OLD_PASSWORD );
93101 }
94102 }
95103
96104 @ Transactional (rollbackFor = Exception .class )
97105 public void updateVisitedTime (String account ) {
98- Member member = memberRepository . findByAccount (account )
99- . orElseThrow (() -> new ResourceNotFoundException ( ResourceType . MEMBER , account ));
106+ Member member = findMemberByAccount (account );
107+
100108 member .setVisitedTime (new Date ());
101109 memberRepository .save (member );
102110 }
103111
104112 @ Transactional (rollbackFor = Exception .class )
105113 public MemberResponse delete (String account ) {
114+ verifyAdminPrivileges ();
115+
116+ Member member = findMemberByAccount (account );
117+ member .setDeleted (true );
118+ return MemberMapper .INSTANCE .entityToResponse (memberRepository .save (member ));
119+ }
120+
121+ private void verifyAdminPrivileges () {
106122 UserPasswordAuthenticationToken authentication =
107123 (UserPasswordAuthenticationToken ) SecurityContextHolder .getContext ().getAuthentication ();
108- Member member = memberRepository .findByAccount (account ).orElseThrow (() ->
109- new ResourceNotFoundException (ResourceType .MEMBER , account ));
110- member .setDeleted (true );
111- if (authentication .isAdmin ()) {
112- return MemberMapper .INSTANCE .entityToResponse (memberRepository .save (member ));
124+
125+ if (authentication == null || !authentication .isAdmin ()) {
126+ throw new ForbiddenException ();
113127 }
114- return null ;
115- }
116-
117- public Page <MemberResponse > list (MemberSearchRequest searchRequest ) {
118- Pageable pageable = PageRequest .of (searchRequest .getPageIndex (), searchRequest .getPageSize (),
119- Sort .Direction .DESC , "createdTime" );
120- Specification <Member > spec = new Specification <Member >() {
121- @ Override
122- public Predicate toPredicate (Root <Member > root , CriteriaQuery <?> query , CriteriaBuilder cb ) {
123- if (StringUtils .isNotBlank (searchRequest .getKeyword ())) {
124- Predicate p0 = cb .like (root .get ("account" ), "%" + searchRequest .getKeyword () + "%" );
125- query .where (p0 );
126- }
127- return query .getRestriction ();
128- }
129- };
130- Page <Member > members = memberRepository .findAll (spec , pageable );
128+ }
129+
130+ public Page <MemberResponse > query (MemberSearchRequest searchRequest ) {
131+ Pageable pageable = PageRequestUtil .toPageable (searchRequest , Sort .Direction .DESC , "createdTime" );
132+ Page <Member > members = memberRepository .findAll (accountLike (searchRequest .getKeyword ()), pageable );
133+
131134 return members .map (item -> MemberMapper .INSTANCE .entityToResponse (item ));
132135 }
133136
134- public MemberResponse query (String account ) {
135- Member member = memberRepository .findByAccountIncludeDeleted (account )
136- .orElseThrow (() -> new ResourceNotFoundException (ResourceType .MEMBER , account ));
137+ private Specification <Member > accountLike (String account ) {
138+ if (StringUtils .isBlank (account )) {
139+ return null ;
140+ }
141+ return (root , query , criteriaBuilder ) -> criteriaBuilder .like (root .get ("account" ),
142+ "%" + account + "%" );
143+ }
144+
145+ public MemberResponse queryByAccount (String account ) {
146+ Member member = findMemberByAccount (account , true );
137147 return MemberMapper .INSTANCE .entityToResponse (member );
138148 }
139149
150+ private Member findLoggedInMember () {
151+ UserPasswordAuthenticationToken authentication =
152+ (UserPasswordAuthenticationToken ) SecurityContextHolder .getContext ().getAuthentication ();
153+
154+ return findMemberByAccount (authentication .getAccount ());
155+ }
156+
157+ private Member findMemberByAccount (String account ) {
158+ return findMemberByAccount (account , false );
159+ }
160+
161+ private Member findMemberByAccount (String account , boolean includeDeleted ) {
162+ Optional <Member > member = includeDeleted ? memberRepository .findByAccountIncludeDeleted (account ) :
163+ memberRepository .findByAccount (account );
164+ return member .orElseThrow (() -> new ResourceNotFoundException (ResourceType .MEMBER , account ));
165+ }
140166}
0 commit comments