Skip to content

Commit bd79fda

Browse files
authored
feat: 어드민 기능 구현 (#44)
* refactor: UserDetails 생성 시 PrincipalDetails 사용하도록 변경 * feat: 어드민 전체 회원 조회 구현 * feat: 어드민 특정 회원 삭제 구현
1 parent d9027fa commit bd79fda

File tree

6 files changed

+131
-6
lines changed

6 files changed

+131
-6
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.amcamp.domain.admin.api;
2+
3+
import com.amcamp.domain.admin.application.AdminService;
4+
import com.amcamp.domain.admin.dto.response.MemberInfoResponse;
5+
import lombok.RequiredArgsConstructor;
6+
import org.springframework.http.ResponseEntity;
7+
import org.springframework.web.bind.annotation.*;
8+
9+
import java.util.List;
10+
11+
@RestController
12+
@RequiredArgsConstructor
13+
@RequestMapping("/admin")
14+
public class AdminController {
15+
16+
private final AdminService adminService;
17+
18+
@GetMapping("/members")
19+
public List<MemberInfoResponse> memberListInfo() {
20+
return adminService.getMemberList();
21+
}
22+
23+
@DeleteMapping("/members/{memberId}")
24+
public ResponseEntity<Void> memberDelete(@PathVariable Long memberId) {
25+
adminService.deleteMember(memberId);
26+
return ResponseEntity.ok().build();
27+
}
28+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.amcamp.domain.admin.application;
2+
3+
import com.amcamp.domain.admin.dto.response.MemberInfoResponse;
4+
import com.amcamp.domain.member.dao.MemberRepository;
5+
import com.amcamp.domain.member.domain.Member;
6+
import com.amcamp.global.error.exception.CustomException;
7+
import com.amcamp.global.error.exception.ErrorCode;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.stereotype.Service;
10+
import org.springframework.transaction.annotation.Transactional;
11+
12+
import java.util.List;
13+
14+
@Transactional
15+
@Service
16+
@RequiredArgsConstructor
17+
public class AdminService {
18+
19+
private final MemberRepository memberRepository;
20+
21+
@Transactional(readOnly = true)
22+
public List<MemberInfoResponse> getMemberList() {
23+
return memberRepository.findAll()
24+
.stream()
25+
.map(MemberInfoResponse::from)
26+
.toList();
27+
}
28+
29+
public void deleteMember(Long memberId) {
30+
Member member = memberRepository.findById(memberId)
31+
.orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND));
32+
33+
memberRepository.delete(member);
34+
}
35+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.amcamp.domain.admin.dto.response;
2+
3+
import com.amcamp.domain.member.domain.Member;
4+
import com.amcamp.domain.member.domain.MemberRole;
5+
6+
public record MemberInfoResponse(
7+
Long memberId,
8+
String nickname,
9+
String profileImageUrl,
10+
MemberRole role) {
11+
public static MemberInfoResponse from(Member member) {
12+
return new MemberInfoResponse(member.getId(), member.getNickname(), member.getProfileImageUrl(), member.getRole());
13+
}
14+
}

src/main/java/com/amcamp/global/config/security/WebSecurityConfig.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws
3939
http.authorizeHttpRequests(
4040
auth ->
4141
auth
42+
.requestMatchers("/admin/**")
43+
.hasRole("ADMIN")
4244
.requestMatchers("/**")
4345
.permitAll()
4446
.anyRequest()

src/main/java/com/amcamp/global/security/JwtAuthenticationFilter.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import org.springframework.http.HttpHeaders;
1515
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
1616
import org.springframework.security.core.context.SecurityContextHolder;
17-
import org.springframework.security.core.userdetails.User;
1817
import org.springframework.security.core.userdetails.UserDetails;
1918
import org.springframework.web.filter.OncePerRequestFilter;
2019
import org.springframework.web.util.WebUtils;
@@ -71,11 +70,7 @@ protected void doFilterInternal(
7170
}
7271

7372
private void setAuthenticationToken(Long memberId, MemberRole role) {
74-
UserDetails userDetails =
75-
User.withUsername(memberId.toString())
76-
.authorities(role.toString())
77-
.password("")
78-
.build();
73+
UserDetails userDetails = new PrincipalDetails(memberId, role);
7974

8075
UsernamePasswordAuthenticationToken token =
8176
new UsernamePasswordAuthenticationToken(
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.amcamp.global.security;
2+
3+
import com.amcamp.domain.member.domain.MemberRole;
4+
import lombok.AllArgsConstructor;
5+
import org.springframework.security.core.GrantedAuthority;
6+
import org.springframework.security.core.userdetails.UserDetails;
7+
8+
import java.util.Collection;
9+
import java.util.Collections;
10+
11+
@AllArgsConstructor
12+
public class PrincipalDetails implements UserDetails {
13+
14+
private final Long memberId;
15+
private final MemberRole memberRole;
16+
17+
@Override
18+
public Collection<? extends GrantedAuthority> getAuthorities() {
19+
return Collections.singletonList((GrantedAuthority) () -> "ROLE_" + memberRole.toString());
20+
}
21+
22+
@Override
23+
public String getPassword() {
24+
return null;
25+
}
26+
27+
@Override
28+
public String getUsername() {
29+
return memberId.toString();
30+
}
31+
32+
@Override
33+
public boolean isAccountNonExpired() {
34+
return true;
35+
}
36+
37+
@Override
38+
public boolean isAccountNonLocked() {
39+
return true;
40+
}
41+
42+
@Override
43+
public boolean isCredentialsNonExpired() {
44+
return true;
45+
}
46+
47+
@Override
48+
public boolean isEnabled() {
49+
return true;
50+
}
51+
}

0 commit comments

Comments
 (0)