In the PostController, I added an isOwner method to check if the user performing the update is the owner of the post. To implement this check, I created a existsByUuidAndUserEmail repository method in the BaseRepository
However, I later realized that a similar check is required in the CommentController to verify if the user updating the comment is the owner. While I could write a separate isOwner method for comments, it doesn’t make sense because the logic would essentially be the same as the existing isOwner method.
Technically, I could use the existing isOwner method for the CommentController as well, but it feels illogical in terms of code readability since the isOwner method relies on PostRepository, because here I’m dealing with comments. Someone reading the code might think, “A check for comments was done, but the PostRepository was used for it.”
I couldn’t come up with a better solution. So What would you recommend as the best solution that adheres to SOLID principles and avoids code duplication?
@Service
@AllArgsConstructor
public class AuthServiceImpl implements AuthService {
@Override
public boolean isOwner(UUID uuid) {
String currentUserEmail = SecurityContextHolder.getContext().getAuthentication().getName();
return postRepository.existsByUuidAndUserEmail(uuid, currentUserEmail);
}
}
PostController
@RestController
@RequestMapping("api/post")
public class PostController extends BaseControllerImpl<
PostResponseDTO,
PostRequestDTO,
PostService> {
private final PostService postService;
public PostController(PostService postService) {
super(postService);
this.postService = postService;
}
@Override
@PreAuthorize("@authService.isOwner(#uuid)
public ResponseEntity<PostResponseDTO> update(@PathVariable UUID uuid, @Valid @RequestBody PostRequestDTO requestDTO) {
return super.update(uuid, requestDTO);
}
}
BaseControllerImpl
@AllArgsConstructor
public abstract class BaseControllerImpl<
DTO extends BaseDTO,
RequestDTO,
Service extends BaseService<DTO, RequestDTO>>
implements BaseController<DTO, RequestDTO> {
private final Service getService;
@Override
public ResponseEntity<DTO> update(@PathVariable UUID uuid, @Valid @RequestBody RequestDTO requestDTO) {
if (getService.update(uuid, requestDTO) != null) {
return new ResponseEntity<>(getService.update(uuid, requestDTO), HttpStatus.OK);
} else {
return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
}
}
}
Repository:
@Repository
public interface PostRepository extends BaseRepository<PostEntity> {}
@NoRepositoryBean
public interface BaseRepository<T> extends JpaRepository<T, Long>, JpaSpecificationExecutor<T> {
boolean existsByUuidAndUserEmail(UUID uuid, String email);
}