생각보다 test code의 작성이 빨리 끝나 도전과제인 admin 권한 부여에 도전해 보았다.
- ADMIN 회원으로 등급업하는 기능
- 초기 ADMIN 회원은 하나가 존재하고 ADMIN 회원은 일반회원의 권한을 ADMIN으로 승격시킬 수 있다.
- ADMIN 회원이 로그인 시 자신이 쓴 글이 아닌 글에 대해 수정, 삭제 가능
밑의 두가지 기능은 이미 진행하였기 때문에, USER 회원을 ADMIN으로 등급업 하는 기능을 추가하였다.
등급업이 가능한 유저는 ADMIN 유저이다.
1. Configuration
SecurityConfig
@EnableWebSecurity
@Configuration
@RequiredArgsConstructor
//WebSecurityConfigurerAdapter 는 이후 SpringBoot에서 잘 안쓰게 됨
public class SecurityConfig {
private final UserService userService;
@Value("${jwt.token.secret}")
private String secretKey;
...
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.httpBasic().disable()
.csrf().disable()
.cors().and()
.exceptionHandling()
.authenticationEntryPoint(new CustomAuthenticationEntryPoint())
.and()
.authorizeRequests()
.antMatchers(PERMIT_URL_ARRAY).permitAll()
.antMatchers(HttpMethod.POST,"/api/**").authenticated() // post는 인가자만 허용
.antMatchers(HttpMethod.DELETE,"/api/**").authenticated() // delete는 인가자만 허용
.antMatchers(HttpMethod.PUT,"/api/**").authenticated() // put는 인가자만 허용 (글 수정)
.antMatchers("/api/v1/users/**/role/change").authenticated() // role 수정
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // jwt사용하는 경우 씀
.and()
.addFilterBefore(new JwtTokenFilter(userService, secretKey), UsernamePasswordAuthenticationFilter.class) //UserNamePasswordAuthenticationFilter적용하기 전에 JWTTokenFilter를 적용
.build();
}
}
역할을 수정하는 URL에는 일단 로그인 한 유저만 접근할 수 있도록 권한 부여를 해 주었다. .antMatchers("/api/v1/users/**/role/change").authenticated()
나중에 service에서 userRole을 검증하지 않고, filter에서 검증할 수 있는 방법이 있다면 찾아보고, 리팩토링 해야 할 듯 하다.
2. Service
UserService
@Service
@RequiredArgsConstructor
@Slf4j
public class UserService {
private final UserRepository userRepository;
private final BCryptPasswordEncoder encoder;
...
public UserDto changeUserRole(Integer userId, String adminUserName) {
//admin userName이 존재하는가
User adminUser = userRepository.findByUserName(adminUserName)
.orElseThrow(()-> new AppException(ErrorCode.NOT_FOUNDED_USER_NAME, ""));
//adminUser의 유저 권한이 ADMIN이 아니면 exception
if(adminUser.getRole() != UserRole.ADMIN) {
throw new AppException(ErrorCode.INVALID_PERMISSION ,"");
}
//권한 바꿀 user의 userName이 존재하는가
User user = userRepository.findById(userId)
.orElseThrow(()-> new AppException(ErrorCode.NOT_FOUNDED_USER_NAME, ""));
//admin 권한 부여
user.setRole(UserRole.ADMIN);
User savedUser = userRepository.saveAndFlush(user);
return UserDto.builder()
.id(savedUser.getId())
.userName(savedUser.getUserName())
.role(savedUser.getRole())
.build();
}
}
유저의 역할을 바꿀 수 있는 로직을 추가하였다.
- controller에서 넘겨받은 adminUserName (로그인 한 유저)를 통해 db에 검색하고, 없으면 exception 발생
- adminUser (로그인 한 유저)의 userRole 이 ADMIN이 아니면 exception 발생
- controller에서 넘겨받은 usrId (권한 수정할 유저)를 통해 db에 검색하고, 없으면 exception 발생
- set method (@setter를 User에 추가)를 통해 권한 변경
- controller에 UserDto return
3. Controller
UserController
@RestController
@RequestMapping("/api/v1/users/")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
...
//role 변경
@GetMapping("/{userId}/role/change")
public Response<UserRoleChangeResponse> roleChange(@PathVariable Integer userId, Authentication authentication) {
String adminUserName = authentication.getName();
UserDto userDto = userService.changeUserRole(userId, adminUserName);
return Response.success(new UserRoleChangeResponse("ADMIN 부여 완료", userId));
}
}
유저의 역할을 바꿀 수 있는 controller를 추가하였다. 변경을 원하는 userId를 URL에서 받는다.
- 로그인 한 유저의 userName과 변경을 원하는 user의 id를 service에 넘겨준다.
- service에서 로직이 실행되어 exception이 발생하지 않으면 넘겨준 UserDto의 id와 성공 메세지를 출력한다.
userRole을 Authentication에서 뽑아 낼 까 했지만, service에서 검증하는 것이 나을 것 같다는 생각이 들었다.
뽑아낸 userRole의 형태가 Collection에 들어가있고, stream으로 뽑아내서 비교하는 것이 번거롭다...
<Reference>
https://jason-moon.tistory.com/132
개인 프로젝트의 중간 점검 기한이 다 되었다.
원래 UI까지 추가해 보고자 하였으나,
중간중간 생각보다 시간을 잡아 먹었던 과정들 (ci/cd 추가, jwt token filter exception 추가, test code 작성)이 꽤 많아 시간이 부족하여 시도하지 못하였다.
만약 최종 점검 전에 시간이 남는다면 시도해 볼 듯 하다... api만 출력되는 것은 보는 맛이 부족한 듯 하다...
또한, 코드 리팩토링 시간에 시간이 된다면, 위의 기능 (ADMIN 권한 부여)에 대한 test code도 추가해야 할 듯 하다.
제출 시간이 임박하여 웹에 직접 돌려 테스트밖에 하지 못하였다...
수업 시간에는 다소 따라치기 바빴던 코드들을 백지상태에서 직접 짜보고 에러들을 직접 경험해 보면서, 이제는 조금 자신감이 생긴 듯 하다.
갈 길이 멀었지만, 모르는 부분은 차근차근 공부해봐야겠다는 생각이 들었다.
<AWS EC2 배포 URL>
http://ec2-3-35-225-29.ap-northeast-2.compute.amazonaws.com:8080/swagger-ui/#/
<전체 Reference>
'프로젝트 > 멋사 개인 프로젝트 (mutsa-SNS)' 카테고리의 다른 글
[15] 3주차/4주차 미션 개요 (0) | 2023.01.03 |
---|---|
[14] mutsa-SNS 7일차 - 코드 리펙토링 (0) | 2022.12.28 |
[12] mutsa-SNS 6일차 - (1) Post 삭제, 수정 Test Code 추가 (0) | 2022.12.27 |
[11] mutsa-SNS 5일차 - (2) Post 삭제, 수정 기능 추가 (0) | 2022.12.26 |
[10] mutsa-SNS 5일차 - (1) Post 조회 기능 TestCode 추가 (0) | 2022.12.26 |