diff --git a/deploy/.env.example b/deploy/.env.example index c1fcff0..a1995c3 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -2,9 +2,6 @@ DATASOURCE_URL=jdbc:mysql://mysql:3306/commercifydb?createDatabaseIfNotExist=true DATASOURCE_USERNAME=commercifyapp DATASOURCE_PASSWORD=password123! -STRIPE_SECRET_TEST_KEY= -STRIPE_WEBHOOK_SECRET= -STRIPE_WEBHOOK_ENDPOINT=https:///api/v2/payments/webhooks/stripe/callback JWT_SECRET_KEY= ADMIN_EMAIL=admin@commercify.app ADMIN_PASSWORD=admin @@ -18,4 +15,5 @@ MOBILEPAY_WEBHOOK_CALLBACK=https:///api/v2/payments/webhooks/mobile MAIL_USERNAME= MAIL_PASSWORD= MAIL_HOST=smtp.ethereal.email -MAIL_PORT=587 \ No newline at end of file +MAIL_PORT=587 +FRONTEND_HOST=http://localhost:3000 \ No newline at end of file diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 3769602..14c8330 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -8,7 +8,7 @@ services: - MYSQL_PASSWORD=password123! - MYSQL_ROOT_PASSWORD=rootpassword ports: - - "3307:3306" + - "3306:3306" healthcheck: test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ] timeout: 5s @@ -26,11 +26,9 @@ services: - "6091:6091" environment: - SPRING_PROFILES_ACTIVE=docker - - SPRING_DATASOURCE_URL=${DATASOURCE_URL} - - SPRING_DATASOURCE_USERNAME=${DATASOURCE_USERNAME} - - SPRING_DATASOURCE_PASSWORD=${DATASOURCE_PASSWORD} - - STRIPE_SECRET_TEST_KEY=${STRIPE_SECRET_TEST_KEY} - - STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET} + - SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3306/commercifydb?createDatabaseIfNotExist=true + - SPRING_DATASOURCE_USERNAME=root + - SPRING_DATASOURCE_PASSWORD=rootpassword - JWT_SECRET_KEY=${JWT_SECRET_KEY} - ADMIN_EMAIL=${ADMIN_EMAIL} - ADMIN_PASSWORD=${ADMIN_PASSWORD} @@ -45,6 +43,7 @@ services: - MAIL_PORT=${MAIL_PORT} - MAIL_USERNAME=${MAIL_USERNAME} - MAIL_PASSWORD=${MAIL_PASSWORD} + - FRONTEND_URL=${FRONTEND_URL} depends_on: mysql: condition: service_healthy diff --git a/pom.xml b/pom.xml index 9eec35d..50abac2 100644 --- a/pom.xml +++ b/pom.xml @@ -194,7 +194,8 @@ jackson2 module - com.zenfulcode.commercify.api.**.dto.** + + com.zenfulcode.commercify.**.dto.** diff --git a/src/main/java/com/zenfulcode/commercify/api/auth/AuthController.java b/src/main/java/com/zenfulcode/commercify/api/auth/AuthController.java index f73573c..e6041a5 100644 --- a/src/main/java/com/zenfulcode/commercify/api/auth/AuthController.java +++ b/src/main/java/com/zenfulcode/commercify/api/auth/AuthController.java @@ -10,7 +10,9 @@ import com.zenfulcode.commercify.auth.domain.exception.InvalidAuthenticationException; import com.zenfulcode.commercify.auth.domain.model.AuthenticatedUser; import com.zenfulcode.commercify.shared.interfaces.ApiResponse; +import com.zenfulcode.commercify.user.application.dto.response.UserProfileResponse; import com.zenfulcode.commercify.user.application.service.UserApplicationService; +import com.zenfulcode.commercify.user.domain.model.User; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -24,6 +26,7 @@ public class AuthController { private final AuthenticationApplicationService authService; private final UserApplicationService userService; + private final UserApplicationService userApplicationService; @PostMapping("/nextauth") public ResponseEntity> nextAuthSignIn(@RequestBody LoginRequest request) { @@ -52,10 +55,26 @@ public ResponseEntity> validateSession(@RequestHea } } + @GetMapping("/me") + public ResponseEntity> getCurrentUser(@RequestHeader("Authorization") String authHeader) { + // Extract token using a domain service method + String token = authService.extractTokenFromHeader(authHeader).orElseThrow(() -> new InvalidAuthenticationException("Invalid authorization header")); + + // Validate token through the application service + AuthenticatedUser authenticatedUser = authService.validateAccessToken(token); + + // Fetch full user entity from the database + User user = userApplicationService.getUser(authenticatedUser.getUserId()); + + // Map to response DTO + UserProfileResponse response = UserProfileResponse.fromUser(user); + + return ResponseEntity.ok(ApiResponse.success(response)); + } + @PostMapping("/signin") public ResponseEntity> login(@RequestBody LoginRequest request) { AuthenticationResult result = authService.authenticate(request.toCommand()); - AuthResponse response = AuthResponse.from(result); return ResponseEntity.ok(ApiResponse.success(response)); } diff --git a/src/main/java/com/zenfulcode/commercify/api/auth/dto/response/AuthResponse.java b/src/main/java/com/zenfulcode/commercify/api/auth/dto/response/AuthResponse.java index c299a80..7d3d3ba 100644 --- a/src/main/java/com/zenfulcode/commercify/api/auth/dto/response/AuthResponse.java +++ b/src/main/java/com/zenfulcode/commercify/api/auth/dto/response/AuthResponse.java @@ -1,33 +1,18 @@ package com.zenfulcode.commercify.api.auth.dto.response; import com.zenfulcode.commercify.auth.application.service.AuthenticationResult; -import com.zenfulcode.commercify.auth.domain.model.UserRole; - -import java.util.Set; -import java.util.stream.Collectors; +import com.zenfulcode.commercify.user.application.dto.response.UserProfileResponse; public record AuthResponse( String accessToken, String refreshToken, - String tokenType, - String userId, - String username, - String email, - Set roles + UserProfileResponse user ) { public static AuthResponse from(AuthenticationResult result) { - Set roles = result.user().getRoles().stream() - .map(UserRole::name) - .collect(Collectors.toSet()); - return new AuthResponse( result.accessToken(), result.refreshToken(), - "Bearer", - result.user().getUserId().toString(), - result.user().getUsername(), - result.user().getEmail(), - roles + UserProfileResponse.fromUser(result.userInfo()) ); } } \ No newline at end of file diff --git a/src/main/java/com/zenfulcode/commercify/api/auth/dto/response/NextAuthResponse.java b/src/main/java/com/zenfulcode/commercify/api/auth/dto/response/NextAuthResponse.java index 25b1a14..149eae4 100644 --- a/src/main/java/com/zenfulcode/commercify/api/auth/dto/response/NextAuthResponse.java +++ b/src/main/java/com/zenfulcode/commercify/api/auth/dto/response/NextAuthResponse.java @@ -1,5 +1,6 @@ package com.zenfulcode.commercify.api.auth.dto.response; +import com.zenfulcode.commercify.user.application.dto.response.UserProfileResponse; import com.zenfulcode.commercify.auth.application.service.AuthenticationResult; import com.zenfulcode.commercify.auth.domain.model.AuthenticatedUser; import com.zenfulcode.commercify.auth.domain.model.UserRole; @@ -7,9 +8,7 @@ import java.util.Set; public record NextAuthResponse( - String id, - String name, - String email, + UserProfileResponse user, String accessToken, String refreshToken, Set roles @@ -17,9 +16,7 @@ public record NextAuthResponse( public static NextAuthResponse from(AuthenticationResult result) { AuthenticatedUser user = result.user(); return new NextAuthResponse( - user.getUserId().toString(), - user.getUsername(), - user.getEmail(), + UserProfileResponse.fromUser(result.userInfo()), result.accessToken(), result.refreshToken(), user.getRoles() @@ -28,9 +25,7 @@ public static NextAuthResponse from(AuthenticationResult result) { public static NextAuthResponse fromUser(AuthenticatedUser user) { return new NextAuthResponse( - user.getUserId().toString(), - user.getUsername(), - user.getEmail(), + UserProfileResponse.fromAuthenticatedUser(user), null, null, user.getRoles() diff --git a/src/main/java/com/zenfulcode/commercify/api/order/OrderController.java b/src/main/java/com/zenfulcode/commercify/api/order/OrderController.java index 8ea7ffe..8c8be5a 100644 --- a/src/main/java/com/zenfulcode/commercify/api/order/OrderController.java +++ b/src/main/java/com/zenfulcode/commercify/api/order/OrderController.java @@ -58,6 +58,7 @@ public ResponseEntity> createOrder( return ResponseEntity.ok(ApiResponse.success(response)); } + // TODO: SUPER NOT SECURE AND NOT GOOD @GetMapping("/{orderId}") public ResponseEntity> getOrder( @PathVariable String orderId, diff --git a/src/main/java/com/zenfulcode/commercify/api/order/dto/response/OrderDetailsResponse.java b/src/main/java/com/zenfulcode/commercify/api/order/dto/response/OrderDetailsResponse.java index 0e53c6b..e27d8bb 100644 --- a/src/main/java/com/zenfulcode/commercify/api/order/dto/response/OrderDetailsResponse.java +++ b/src/main/java/com/zenfulcode/commercify/api/order/dto/response/OrderDetailsResponse.java @@ -14,6 +14,7 @@ public record OrderDetailsResponse( CustomerDetailsResponse customerDetails, AddressResponse shippingAddress, AddressResponse billingAddress, - Instant createdAt + Instant createdAt, + Instant updatedAt ) { } diff --git a/src/main/java/com/zenfulcode/commercify/api/order/mapper/OrderDtoMapper.java b/src/main/java/com/zenfulcode/commercify/api/order/mapper/OrderDtoMapper.java index c9dfedd..7fc1afe 100644 --- a/src/main/java/com/zenfulcode/commercify/api/order/mapper/OrderDtoMapper.java +++ b/src/main/java/com/zenfulcode/commercify/api/order/mapper/OrderDtoMapper.java @@ -86,7 +86,8 @@ public OrderDetailsResponse toResponse(OrderDetailsDTO dto) { toAddressResponse(dto.shippingAddress()), dto.billingAddress() != null ? toAddressResponse(dto.billingAddress()) : null, - dto.createdAt() + dto.createdAt(), + dto.updatedAt() ); } diff --git a/src/main/java/com/zenfulcode/commercify/api/product/dto/request/UpdateProductRequest.java b/src/main/java/com/zenfulcode/commercify/api/product/dto/request/UpdateProductRequest.java index df32707..215ab32 100644 --- a/src/main/java/com/zenfulcode/commercify/api/product/dto/request/UpdateProductRequest.java +++ b/src/main/java/com/zenfulcode/commercify/api/product/dto/request/UpdateProductRequest.java @@ -5,6 +5,7 @@ public record UpdateProductRequest( String name, String description, + String imageUrl, Integer stock, Money price, Boolean active diff --git a/src/main/java/com/zenfulcode/commercify/api/product/dto/response/ProductSummaryResponse.java b/src/main/java/com/zenfulcode/commercify/api/product/dto/response/ProductSummaryResponse.java index 9f5ed59..5728cd2 100644 --- a/src/main/java/com/zenfulcode/commercify/api/product/dto/response/ProductSummaryResponse.java +++ b/src/main/java/com/zenfulcode/commercify/api/product/dto/response/ProductSummaryResponse.java @@ -8,6 +8,7 @@ public record ProductSummaryResponse( String description, String imageUrl, Money price, - int stock + int stock, + boolean isActive ) { } diff --git a/src/main/java/com/zenfulcode/commercify/api/product/mapper/ProductDtoMapper.java b/src/main/java/com/zenfulcode/commercify/api/product/mapper/ProductDtoMapper.java index 79abe53..ea71f02 100644 --- a/src/main/java/com/zenfulcode/commercify/api/product/mapper/ProductDtoMapper.java +++ b/src/main/java/com/zenfulcode/commercify/api/product/mapper/ProductDtoMapper.java @@ -48,6 +48,7 @@ public UpdateProductCommand toCommand(ProductId productId, UpdateProductRequest ProductUpdateSpec updateSpec = new ProductUpdateSpec( request.name(), request.description(), + request.imageUrl(), request.stock(), request.price(), request.active() diff --git a/src/main/java/com/zenfulcode/commercify/api/product/mapper/ProductResponseMapper.java b/src/main/java/com/zenfulcode/commercify/api/product/mapper/ProductResponseMapper.java index e4dd6a1..fd04153 100644 --- a/src/main/java/com/zenfulcode/commercify/api/product/mapper/ProductResponseMapper.java +++ b/src/main/java/com/zenfulcode/commercify/api/product/mapper/ProductResponseMapper.java @@ -41,7 +41,8 @@ private ProductSummaryResponse toSummaryResponse(Product product) { product.getDescription(), product.getImageUrl(), product.getPrice(), - product.getStock() + product.getStock(), + product.isActive() ); } diff --git a/src/main/java/com/zenfulcode/commercify/api/users/UserController.java b/src/main/java/com/zenfulcode/commercify/api/users/UserController.java new file mode 100644 index 0000000..1992a55 --- /dev/null +++ b/src/main/java/com/zenfulcode/commercify/api/users/UserController.java @@ -0,0 +1,70 @@ +package com.zenfulcode.commercify.api.users; + +import com.zenfulcode.commercify.api.product.dto.response.PageInfo; +import com.zenfulcode.commercify.shared.interfaces.ApiResponse; +import com.zenfulcode.commercify.user.application.dto.request.PagedUserResponse; +import com.zenfulcode.commercify.user.application.dto.response.UserProfileResponse; +import com.zenfulcode.commercify.user.application.service.UserApplicationService; +import com.zenfulcode.commercify.user.domain.model.User; +import com.zenfulcode.commercify.user.domain.valueobject.UserId; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/v2/users") +@RequiredArgsConstructor +public class UserController { + private final UserApplicationService userApplicationService; + + @GetMapping + @PreAuthorize("hasRole('ADMIN')") + public ResponseEntity> getAllUsers( + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size, + @RequestParam(defaultValue = "id") String sortBy, + @RequestParam(defaultValue = "DESC") String sortDirection) { + + Sort.Direction direction = Sort.Direction.fromString(sortDirection.toUpperCase()); + PageRequest pageRequest = PageRequest.of(page, size, Sort.by(direction, sortBy)); + + Page usersPage = userApplicationService.getAllUsers(pageRequest); + PagedUserResponse response = toPagedResponse(usersPage); + + return ResponseEntity.ok(ApiResponse.success(response)); + } + + @GetMapping("/{userId}") + @PreAuthorize("hasRole('ADMIN')") + public ResponseEntity> getUserById(@PathVariable String userId) { + // Fetch user by ID from the database + User user = userApplicationService.getUser(UserId.of(userId)); + + // Map to response DTO + UserProfileResponse response = UserProfileResponse.fromUser(user); + + return ResponseEntity.ok(ApiResponse.success(response)); + } + + private PagedUserResponse toPagedResponse(Page userPage) { + List items = userPage.getContent() + .stream() + .map(UserProfileResponse::fromUser) + .toList(); + + PageInfo pageInfo = new PageInfo( + userPage.getNumber(), + userPage.getSize(), + userPage.getTotalElements(), + userPage.getTotalPages() + ); + + return new PagedUserResponse(items, pageInfo); + } +} diff --git a/src/main/java/com/zenfulcode/commercify/auth/application/service/AuthenticationApplicationService.java b/src/main/java/com/zenfulcode/commercify/auth/application/service/AuthenticationApplicationService.java index 83bd6c1..7635841 100644 --- a/src/main/java/com/zenfulcode/commercify/auth/application/service/AuthenticationApplicationService.java +++ b/src/main/java/com/zenfulcode/commercify/auth/application/service/AuthenticationApplicationService.java @@ -64,6 +64,8 @@ public AuthenticationResult authenticate(LoginCommand command) { Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(email, password)); AuthenticatedUser authenticatedUser = (AuthenticatedUser) authentication.getPrincipal(); + User user = userApplicationService.getUser(userId); + // Generate tokens String accessToken = tokenService.generateAccessToken(authenticatedUser); String refreshToken = tokenService.generateRefreshToken(authenticatedUser); @@ -71,7 +73,7 @@ public AuthenticationResult authenticate(LoginCommand command) { // Publish domain event eventPublisher.publish(new UserAuthenticatedEvent(this, userId, email, command.isGuest())); - return new AuthenticationResult(accessToken, refreshToken, authenticatedUser); + return new AuthenticationResult(accessToken, refreshToken, authenticatedUser, user); } @Transactional(readOnly = true) @@ -93,7 +95,7 @@ public AuthenticationResult refreshToken(String refreshToken) { String newAccessToken = tokenService.generateAccessToken(authenticatedUser); String newRefreshToken = tokenService.generateRefreshToken(authenticatedUser); - return new AuthenticationResult(newAccessToken, newRefreshToken, authenticatedUser); + return new AuthenticationResult(newAccessToken, newRefreshToken, authenticatedUser, user); } public Optional extractTokenFromHeader(String authHeader) { diff --git a/src/main/java/com/zenfulcode/commercify/auth/application/service/AuthenticationResult.java b/src/main/java/com/zenfulcode/commercify/auth/application/service/AuthenticationResult.java index d7dc84f..6327ef6 100644 --- a/src/main/java/com/zenfulcode/commercify/auth/application/service/AuthenticationResult.java +++ b/src/main/java/com/zenfulcode/commercify/auth/application/service/AuthenticationResult.java @@ -1,10 +1,12 @@ package com.zenfulcode.commercify.auth.application.service; import com.zenfulcode.commercify.auth.domain.model.AuthenticatedUser; +import com.zenfulcode.commercify.user.domain.model.User; public record AuthenticationResult( String accessToken, String refreshToken, - AuthenticatedUser user + AuthenticatedUser user, + User userInfo ) { } \ No newline at end of file diff --git a/src/main/java/com/zenfulcode/commercify/auth/domain/model/UserRole.java b/src/main/java/com/zenfulcode/commercify/auth/domain/model/UserRole.java index b4ec167..8d11714 100644 --- a/src/main/java/com/zenfulcode/commercify/auth/domain/model/UserRole.java +++ b/src/main/java/com/zenfulcode/commercify/auth/domain/model/UserRole.java @@ -3,6 +3,5 @@ public enum UserRole { ROLE_GUEST, ROLE_USER, - ROLE_ADMIN, - ROLE_MANAGER + ROLE_ADMIN } \ No newline at end of file diff --git a/src/main/java/com/zenfulcode/commercify/order/application/dto/OrderDetailsDTO.java b/src/main/java/com/zenfulcode/commercify/order/application/dto/OrderDetailsDTO.java index 212e367..2158800 100644 --- a/src/main/java/com/zenfulcode/commercify/order/application/dto/OrderDetailsDTO.java +++ b/src/main/java/com/zenfulcode/commercify/order/application/dto/OrderDetailsDTO.java @@ -21,7 +21,8 @@ public record OrderDetailsDTO(OrderId id, CustomerDetails customerDetails, Address shippingAddress, Address billingAddress, - Instant createdAt) { + Instant createdAt, + Instant updatedAt) { public static OrderDetailsDTO fromOrder(Order order) { return new OrderDetailsDTO( order.getId(), @@ -35,7 +36,8 @@ public static OrderDetailsDTO fromOrder(Order order) { order.getOrderShippingInfo().toCustomerDetails(), order.getOrderShippingInfo().toShippingAddress(), order.getOrderShippingInfo().toBillingAddress(), - order.getCreatedAt() + order.getCreatedAt(), + order.getUpdatedAt() ); } } diff --git a/src/main/java/com/zenfulcode/commercify/order/application/service/OrderApplicationService.java b/src/main/java/com/zenfulcode/commercify/order/application/service/OrderApplicationService.java index 15852fb..4fe85fa 100644 --- a/src/main/java/com/zenfulcode/commercify/order/application/service/OrderApplicationService.java +++ b/src/main/java/com/zenfulcode/commercify/order/application/service/OrderApplicationService.java @@ -128,4 +128,8 @@ public BigDecimal calculateTotalRevenue(CalculateTotalRevenueQuery query) { public int countOrdersInPeriod(CountOrdersInPeriodQuery query) { return orderDomainService.countOrdersInPeriod(query.startDate(), query.endDate()); } + + public void canCaptureOrder(OrderId orderId) { + orderDomainService.canCaptureOrder(orderId); + } } \ No newline at end of file diff --git a/src/main/java/com/zenfulcode/commercify/order/domain/service/OrderDomainService.java b/src/main/java/com/zenfulcode/commercify/order/domain/service/OrderDomainService.java index f7c6e72..d94d84d 100644 --- a/src/main/java/com/zenfulcode/commercify/order/domain/service/OrderDomainService.java +++ b/src/main/java/com/zenfulcode/commercify/order/domain/service/OrderDomainService.java @@ -155,4 +155,9 @@ public int countOrdersInPeriod(LocalDate startDate, LocalDate endDate) { return orderRepository.countOrders(start, end); } + + public void canCaptureOrder(OrderId orderId) { + Order order = getOrderById(orderId); + validationService.validateStatusTransition(order, OrderStatus.COMPLETED); + } } diff --git a/src/main/java/com/zenfulcode/commercify/payment/application/service/PaymentApplicationService.java b/src/main/java/com/zenfulcode/commercify/payment/application/service/PaymentApplicationService.java index 97fb755..3d27680 100644 --- a/src/main/java/com/zenfulcode/commercify/payment/application/service/PaymentApplicationService.java +++ b/src/main/java/com/zenfulcode/commercify/payment/application/service/PaymentApplicationService.java @@ -1,5 +1,6 @@ package com.zenfulcode.commercify.payment.application.service; +import com.zenfulcode.commercify.order.application.service.OrderApplicationService; import com.zenfulcode.commercify.payment.application.command.CapturePaymentCommand; import com.zenfulcode.commercify.payment.application.command.InitiatePaymentCommand; import com.zenfulcode.commercify.payment.application.dto.CaptureAmount; @@ -31,6 +32,7 @@ public class PaymentApplicationService { private final PaymentProviderFactory providerFactory; private final DefaultDomainEventPublisher eventPublisher; private final WebhookHandler webhookHandler; + private final OrderApplicationService orderApplicationService; @Transactional public InitializedPayment initiatePayment(InitiatePaymentCommand command) { @@ -79,6 +81,8 @@ public void handlePaymentCallback(PaymentProvider provider, WebhookPayload paylo // TODO: Make sure the capture currency is the same as the payment currency @Transactional public CapturedPayment capturePayment(CapturePaymentCommand command) { + orderApplicationService.canCaptureOrder(command.orderId()); + Payment payment = paymentDomainService.getPaymentByOrderId(command.orderId()); Money captureAmount = command.captureAmount() == null ? payment.getAmount() : command.captureAmount(); diff --git a/src/main/java/com/zenfulcode/commercify/product/domain/service/ProductDomainService.java b/src/main/java/com/zenfulcode/commercify/product/domain/service/ProductDomainService.java index 653281c..aa0e015 100644 --- a/src/main/java/com/zenfulcode/commercify/product/domain/service/ProductDomainService.java +++ b/src/main/java/com/zenfulcode/commercify/product/domain/service/ProductDomainService.java @@ -186,6 +186,15 @@ public void updateProduct(Product product, ProductUpdateSpec updateSpec) { } } + if (updateSpec.hasImageUrlUpdate()) { + if (updateSpec.imageUrl() == null || updateSpec.imageUrl().isBlank()) { + violations.add("Image URL cannot be empty"); + } else { + // TODO: Validate image URL format + product.setImageUrl(updateSpec.imageUrl()); + } + } + // If there are any violations, throw an exception if (!violations.isEmpty()) { throw new ProductValidationException(violations); diff --git a/src/main/java/com/zenfulcode/commercify/product/domain/valueobject/ProductUpdateSpec.java b/src/main/java/com/zenfulcode/commercify/product/domain/valueobject/ProductUpdateSpec.java index a5bc011..45b6f28 100644 --- a/src/main/java/com/zenfulcode/commercify/product/domain/valueobject/ProductUpdateSpec.java +++ b/src/main/java/com/zenfulcode/commercify/product/domain/valueobject/ProductUpdateSpec.java @@ -5,6 +5,7 @@ public record ProductUpdateSpec( String name, String description, + String imageUrl, Integer stock, Money price, Boolean active @@ -28,4 +29,8 @@ public boolean hasPriceUpdate() { public boolean hasActiveUpdate() { return active != null; } + + public boolean hasImageUrlUpdate() { + return imageUrl != null; + } } \ No newline at end of file diff --git a/src/main/java/com/zenfulcode/commercify/user/application/dto/request/PagedUserResponse.java b/src/main/java/com/zenfulcode/commercify/user/application/dto/request/PagedUserResponse.java new file mode 100644 index 0000000..3c5c543 --- /dev/null +++ b/src/main/java/com/zenfulcode/commercify/user/application/dto/request/PagedUserResponse.java @@ -0,0 +1,12 @@ +package com.zenfulcode.commercify.user.application.dto.request; + +import com.zenfulcode.commercify.api.product.dto.response.PageInfo; +import com.zenfulcode.commercify.user.application.dto.response.UserProfileResponse; + +import java.util.List; + +public record PagedUserResponse( + List items, + PageInfo pageInfo +) { +} diff --git a/src/main/java/com/zenfulcode/commercify/user/application/dto/response/UserProfileResponse.java b/src/main/java/com/zenfulcode/commercify/user/application/dto/response/UserProfileResponse.java new file mode 100644 index 0000000..dfa3862 --- /dev/null +++ b/src/main/java/com/zenfulcode/commercify/user/application/dto/response/UserProfileResponse.java @@ -0,0 +1,45 @@ +package com.zenfulcode.commercify.user.application.dto.response; + +import com.zenfulcode.commercify.auth.domain.model.AuthenticatedUser; +import com.zenfulcode.commercify.user.domain.model.User; +import com.zenfulcode.commercify.user.domain.model.UserStatus; + +import java.util.List; + +public record UserProfileResponse( + String id, + String email, + String firstName, + String lastName, + String phoneNumber, + String status, + List roles +) { + public static UserProfileResponse fromUser(User user) { + return new UserProfileResponse( + user.getId().toString(), + user.getEmail(), + user.getFirstName(), + user.getLastName(), + user.getPhoneNumber(), + user.getStatus().name(), + user.getRoles().stream() + .map(Enum::name) + .toList() + ); + } + + public static UserProfileResponse fromAuthenticatedUser(AuthenticatedUser user) { + return new UserProfileResponse( + user.getUserId().getId(), + user.getEmail(), + user.getUsername(), + "", + "", + UserStatus.ACTIVE.toString(), + user.getRoles().stream() + .map(Enum::name) + .toList() + ); + } +} diff --git a/src/main/java/com/zenfulcode/commercify/user/domain/model/UserRole.java b/src/main/java/com/zenfulcode/commercify/user/domain/model/UserRole.java index 7dbd5dd..de0f457 100644 --- a/src/main/java/com/zenfulcode/commercify/user/domain/model/UserRole.java +++ b/src/main/java/com/zenfulcode/commercify/user/domain/model/UserRole.java @@ -1,9 +1,7 @@ package com.zenfulcode.commercify.user.domain.model; public enum UserRole { - GUEST, // Guest user - USER, // Standard user - ADMIN, // Administrator - MANAGER, // Store manager - SUPPORT // Customer support + GUEST, + USER, + ADMIN } diff --git a/src/main/resources/application-docker.properties b/src/main/resources/application-docker.properties index 56b4d37..089311c 100644 --- a/src/main/resources/application-docker.properties +++ b/src/main/resources/application-docker.properties @@ -33,6 +33,6 @@ spring.mail.username=${MAIL_USERNAME} spring.mail.password=${MAIL_PASSWORD} spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true -frontend.host=${FRONTEND_HOST} +frontend.host=${FRONTEND_HOST:http://localhost:3000} # Application Configuration #logging.level.org.springframework.security=debug \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 3ad4c31..3b74d71 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -33,6 +33,7 @@ spring.mail.username=${MAIL_USERNAME} spring.mail.password=${MAIL_PASSWORD} spring.mail.properties.mail.smtp.auth=true spring.mail.properties.mail.smtp.starttls.enable=true -frontend.host=${FRONTEND_HOST} +frontend.host=${FRONTEND_HOST:http://localhost:3000} + # Application Configuration #logging.level.org.springframework.security=debug \ No newline at end of file