Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[33] api 별 유저 권한체크 #40

Merged
merged 12 commits into from
Oct 18, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,26 @@ public class AddressFacade {
private final UserService userService;

public void create(AddressRequestDto.Create dto) {
User user = userService.getUser(dto.getUserId());
User user = userService.getUser(dto.getUserAuthId());
if (dto.getIsPrimary()) {
addressService.updatePrimary(user, Boolean.FALSE);
}
AddressResponseDto.Get.of(addressService.createAddress(dto, user));
}

public AddressResponseDto.Get get(Long addressId, Long userId) {
User user = userService.getUser(userId);
public AddressResponseDto.Get get(Long addressId, String userAuthId) {
User user = userService.getUser(userAuthId);
return AddressResponseDto.Get.of(addressService.getAddress(addressId, user));
}

public Page<AddressResponseDto.Get> getList(Long userId, int page, int pageSize) {
User user = userService.getUser(userId);
public Page<AddressResponseDto.Get> getList(String userAuthId, int page, int pageSize) {
User user = userService.getUser(userAuthId);
Page<Address> addressPage = addressService.getAddressesByUser(user, PageRequest.of(page, pageSize));
return AddressResponseDto.Get.of(addressPage);
}

public void delete(Long userId, Long addressId) {
User user = userService.getUser(userId);
public void delete(String userAuthId, Long addressId) {
User user = userService.getUser(userAuthId);
addressService.deleteAddress(addressId, user);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class AddressRequestDto {
@Builder
@ToString
public static class Create {
private Long userId;
private String userAuthId;
private String phoneNumber;
private String addressType;
private String postalCode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class AddressResponseDto {
@Builder
@ToString
public static class Get {
private Long id;
private String phoneNumber;
private String addressType;
private String postalCode;
Expand All @@ -22,6 +23,7 @@ public static class Get {

public static Get of(Address address) {
return Get.builder()
.id(address.getId())
.phoneNumber(address.getPhoneNumber())
.addressType(address.getAddressType())
.postalCode(address.getPostalCode())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import org.example.commerce_site.application.cart.dto.CartResponseDto;
import org.example.commerce_site.application.product.ProductService;
import org.example.commerce_site.application.user.UserService;
import org.example.commerce_site.domain.Product;
import org.example.commerce_site.domain.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
Expand All @@ -18,23 +20,23 @@ public class CartFacade {
private final ProductService productService;

public void create(CartRequestDto.Create dto) {
userService.getUser(dto.getUserId());
productService.getProduct(dto.getProductId());
cartService.create(dto);
User user = userService.getUser(dto.getUserAuthId());
Product product = productService.getProduct(dto.getProductId());
cartService.create(dto, user, product);
}

public void delete(CartRequestDto.Delete dto) {
userService.getUser(dto.getUserId());
cartService.delete(dto);
User user = userService.getUser(dto.getUserAuthId());
cartService.delete(dto, user);
}

public void update(CartRequestDto.Update dto) {
userService.getUser(dto.getUserId());
cartService.update(dto);
User user = userService.getUser(dto.getUserAuthId());
cartService.update(dto, user);
}

public Page<CartResponseDto.Get> getList(Long userId, int page, int size) {
userService.getUser(userId);
return cartService.getList(userId, PageRequest.of(page, size));
public Page<CartResponseDto.Get> getList(String userAuthId, int page, int size) {
User user = userService.getUser(userAuthId);
return cartService.getList(user.getId(), PageRequest.of(page, size));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import org.example.commerce_site.common.exception.CustomException;
import org.example.commerce_site.common.exception.ErrorCode;
import org.example.commerce_site.domain.Cart;
import org.example.commerce_site.domain.Product;
import org.example.commerce_site.domain.User;
import org.example.commerce_site.infrastructure.cart.CartRepository;
import org.example.commerce_site.infrastructure.cart.CustomCartRepository;
import org.springframework.data.domain.Page;
Expand All @@ -24,32 +26,32 @@ public class CartService {
private final CustomCartRepository customCartRepository;

@Transactional
public void create(CartRequestDto.Create dto) {
public void create(CartRequestDto.Create dto, User user, Product product) {
if (dto.getQuantity() == 0) {
throw new CustomException(ErrorCode.QUANTITY_IS_ZERO);
}
cartRepository.findByUserIdAndProductId(dto.getUserId(), dto.getProductId()).ifPresentOrElse(
cartRepository.findByUserIdAndProductId(user.getId(), product.getId()).ifPresentOrElse(
cart -> cart.addQuantity(dto.getQuantity()),
() -> cartRepository.save(CartRequestDto.Create.toEntity(dto))
() -> cartRepository.save(CartRequestDto.Create.toEntity(dto, user.getId()))
);
}

@Transactional
public void delete(CartRequestDto.Delete dto) {
public void delete(CartRequestDto.Delete dto, User user) {
dto.getProductIds().forEach(productId -> {
cartRepository.deleteByUserIdAndProductId(dto.getUserId(), productId);
cartRepository.deleteByUserIdAndProductId(user.getId(), productId);
});
}

@Transactional
public void update(CartRequestDto.Update dto) {
public void update(CartRequestDto.Update dto, User user) {
HashMap<Long, Long> productIdAndQuantity = dto.getProductsMap();

if (productIdAndQuantity.values().stream().anyMatch(quantity -> quantity == 0)) {
throw new CustomException(ErrorCode.QUANTITY_IS_ZERO);
}

List<Cart> cartList = cartRepository.findByUserIdAndProductIdIn(dto.getUserId(), productIdAndQuantity.keySet());
List<Cart> cartList = cartRepository.findByUserIdAndProductIdIn(user.getId(), productIdAndQuantity.keySet());
cartList.forEach(cart -> {
Long newQuantity = productIdAndQuantity.get(cart.getProductId());
cart.updateQuantity(newQuantity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ public class CartRequestDto {
@Builder
@ToString
public static class Create {
private Long userId;
private String userAuthId;
private Long productId;
private Long quantity;

public static Cart toEntity(Create dto) {
public static Cart toEntity(Create dto, Long userId) {
return Cart.builder()
.userId(dto.getUserId())
.userId(userId)
.productId(dto.getProductId())
.quantity(dto.getQuantity())
.build();
Expand All @@ -31,15 +31,15 @@ public static Cart toEntity(Create dto) {
@Builder
@ToString
public static class Update {
private Long userId;
private String userAuthId;
private HashMap<Long, Long> productsMap;
}

@Getter
@Builder
@ToString
public static class Delete {
private Long userId;
private String userAuthId;
private List<Long> productIds;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ public Partner getPartner(Long partnerId) {
);
}

@Transactional(readOnly = true)
public Partner getPartner(String partnerAuthId) {
return partnerRepository.findByAuthId(partnerAuthId).orElseThrow(
() -> new CustomException(ErrorCode.PARTNER_NOT_FOUND)
);
}

@Transactional
public void updatePartnerStatusActive(UserRequestDto.Create dto) {
Partner partner = partnerRepository.findByEmail(dto.getEmail()).orElseThrow(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@ public class ProductFacade {
private final PartnerService partnerService;

public void createProduct(ProductRequestDto.Create dto) {
Partner partner = partnerService.getPartner(dto.getPartnerAuthId());
Category category = categoryService.getCategoryById(dto.getCategoryId());
productService.create(dto, category);
productService.create(dto, category, partner.getId());
}

public void updateProduct(Long productId, ProductRequestDto.Put dto) {
Partner partner = partnerService.getPartner(dto.getPartnerAuthId());
Product product = productService.getProduct(productId);

if (!product.getPartnerId().equals(dto.getPartnerId())) {
if (!product.getPartnerId().equals(partner.getId())) {
throw new CustomException(ErrorCode.PRODUCT_ACCESS_DENIED);
}

Expand All @@ -44,8 +46,15 @@ public void updateProduct(Long productId, ProductRequestDto.Put dto) {
productService.update(product, dto, category);
}

public void deleteProduct(Long productId) {
productService.delete(productService.getProduct(productId));
public void deleteProduct(Long productId, String partnerAuthId) {
Partner partner = partnerService.getPartner(partnerAuthId);
Product product = productService.getProduct(productId);

if (!product.getPartnerId().equals(partner.getId())) {
throw new CustomException(ErrorCode.PRODUCT_ACCESS_DENIED);
}

productService.delete(product);
}

public ProductResponseDto.Get getProduct(Long productId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public class ProductService {
private final CustomProductRepository customProductRepository;

@Transactional
public Product create(ProductRequestDto.Create productRequest, Category category) {
return productRepository.save(ProductRequestDto.Create.toEntity(productRequest, category));
public Product create(ProductRequestDto.Create productRequest, Category category, Long partnerId) {
return productRepository.save(ProductRequestDto.Create.toEntity(productRequest, category, partnerId));
}

@Transactional(readOnly = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ public class ProductRequestDto {
@Builder
@ToString
public static class Create {
private Long partnerId;
private String partnerAuthId;
private Long categoryId;
private String name;
private String description;
private Long price;
private Long stockQuantity;

public static Product toEntity(ProductRequestDto.Create dto, Category category) {
public static Product toEntity(ProductRequestDto.Create dto, Category category, Long partnerId) {
return Product.builder()
.partnerId(dto.getPartnerId())
.partnerId(partnerId)
.category(category)
.name(dto.getName())
.description(dto.getDescription())
Expand All @@ -37,7 +37,7 @@ public static Product toEntity(ProductRequestDto.Create dto, Category category)
@Builder
@ToString
public static class Put {
private Long partnerId;
private String partnerAuthId;
private Long categoryId;
private String name;
private String description;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public GroupedOpenApi categoryOpenApi() {

@Bean
public GroupedOpenApi addressOpenApi() {
String[] paths = {"/address/**"};
String[] paths = {"/addresses/**"};
return GroupedOpenApi.builder().group("ADDRESS API").pathsToMatch(paths).build();
}

Expand Down
28 changes: 28 additions & 0 deletions src/main/java/org/example/commerce_site/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
package org.example.commerce_site.config;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.example.commerce_site.config.filter.UserIdFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class SecurityConfig {
private final AuthExcludeProperties authExcludeProperties;

Expand All @@ -33,6 +46,7 @@ protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(this::extractAuthorities);

http
.csrf(AbstractHttpConfigurer::disable)
Expand All @@ -50,4 +64,18 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti

return http.build();
}

private Collection<GrantedAuthority> extractAuthorities(Jwt jwt) {
var resourceAccess = (Map<String, Object>)jwt.getClaim("resource_access");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

권한을 jwt에서 받아올 때, 관리 측면에서 신경써줘야 할 부분이 있을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

토큰 만료 시간을 짧게 설정해서 탈취되더라도 오랫동안 사용되지 않게 합니다.
role 이 변경되었는데 기존 발급받은 토큰의 재사용을 막기 위해 api 서버에서 DB 체크를 추가로 합니다

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

db 체크를 추가로 하면, 토큰에 role을 집어넣을 필요가 없는거 아닌가요?

var roles = (Map<String, Object>)resourceAccess.get("oauth2-client-app");

if (roles != null) {
var roleList = (List<String>)roles.get("roles");
return roleList.stream()
.map(role -> new SimpleGrantedAuthority(role))
.collect(Collectors.toList());
}

return List.of();
}
}
4 changes: 2 additions & 2 deletions src/main/java/org/example/commerce_site/domain/Category.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@Entity
@Getter
@Builder
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "categories")
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/example/commerce_site/domain/Partner.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
import jakarta.persistence.Enumerated;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

@Entity
@Getter
@Builder
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "partners")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@
@Repository
public interface PartnerRepository extends JpaRepository<Partner, Long> {
Optional<Partner> findByEmail(String email);

Optional<Partner> findByAuthId(String partnerAuthId);
}
Loading
Loading