Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/admin")
Expand Down Expand Up @@ -37,8 +38,7 @@ public ResponseEntity<?> getAllUsers(@AuthenticationPrincipal User user) {

// Delete a user by ID, Admin only
@DeleteMapping("/users/{id}")
public ResponseEntity<?> deleteUser(@PathVariable Long id,
@AuthenticationPrincipal User user) {
public ResponseEntity<?> deleteUser(@PathVariable Long id, @AuthenticationPrincipal User user) {
if (user == null || user.getRole() != User.Role.ADMIN) {
return ResponseEntity.status(403).body("Forbidden");
}
Expand All @@ -60,22 +60,24 @@ public ResponseEntity<?> getAllOrders(@AuthenticationPrincipal User user) {

// Get a specific order by ID, Admin only
@GetMapping("/orders/{id}")
public ResponseEntity<?> getOrderById(@PathVariable Long id,
@AuthenticationPrincipal User user) {
public ResponseEntity<?> getOrderById(@PathVariable Long id, @AuthenticationPrincipal User user) {
if (user == null || user.getRole() != User.Role.ADMIN) {
return ResponseEntity.status(403).body("Forbidden");
}

return orderService.getOrderById(id)
.map(order -> ResponseEntity.ok(order))
.orElse(ResponseEntity.notFound().build());
Optional<Order> optional = orderService.getOrderById(id);

if (optional.isPresent()) {
return ResponseEntity.ok(optional.get());
} else {
return ResponseEntity.notFound().build();
}

}

// Update order status, Admin only
@PatchMapping("/orders/{id}/status")
public ResponseEntity<?> updateOrderStatus(@PathVariable Long id,
@RequestParam String status,
@AuthenticationPrincipal User user) {
public ResponseEntity<?> updateOrderStatus(@PathVariable Long id, @RequestParam String status, @AuthenticationPrincipal User user) {
if (user == null || user.getRole() != User.Role.ADMIN) {
return ResponseEntity.status(403).body("Forbidden");
}
Expand Down Expand Up @@ -109,8 +111,7 @@ public ResponseEntity<?> createAdmin(@RequestBody User newAdmin, @Authentication

// Delete admin by ID, Admin only
@DeleteMapping("/admins/{id}")
public ResponseEntity<?> deleteAdmin(@PathVariable Long id,
@AuthenticationPrincipal User currentUser) {
public ResponseEntity<?> deleteAdmin(@PathVariable Long id, @AuthenticationPrincipal User currentUser) {
if (currentUser == null || currentUser.getRole() != User.Role.ADMIN) {
return ResponseEntity.status(403).body("Forbidden");
}
Expand All @@ -119,8 +120,7 @@ public ResponseEntity<?> deleteAdmin(@PathVariable Long id,
return ResponseEntity.badRequest().body("You cannot delete yourself.");
}

User adminToDelete = userService.findById(id)
.orElse(null);
User adminToDelete = userService.findById(id).orElse(null);

if (adminToDelete == null || adminToDelete.getRole() != User.Role.ADMIN) {
return ResponseEntity.badRequest().body("Admin not found.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/orders")
Expand All @@ -26,59 +27,52 @@ public OrderController(OrderService orderService) {

// Create order after Stripe success
@PostMapping("/create")
public ResponseEntity<?> createOrder(
@RequestBody List<CheckoutItemDTO> items,
@AuthenticationPrincipal User user
) {
if (user == null)
public ResponseEntity<?> createOrder(@RequestBody List<CheckoutItemDTO> items, @AuthenticationPrincipal User user) {
if (user == null){
return ResponseEntity.status(401).body("Unauthorized");
}

if (user.getRole() != User.Role.CUSTOMER)
if (user.getRole() != User.Role.CUSTOMER) {
return ResponseEntity.status(403).body("Only customers can place orders.");
}

try {
Order saved = orderService.createOrderFromItems(
user,
items,
Order.Status.COMPLETED
);

Order saved = orderService.createOrderFromItems(user, items, Order.Status.COMPLETED);
return ResponseEntity.ok(saved);

} catch (Exception e) {
return ResponseEntity
.badRequest()
.body("Failed to create order: " + e.getMessage());
return ResponseEntity.badRequest().body("Failed to create order: " + e.getMessage());
}
}

// Customer view own orders
@GetMapping("/my")
public ResponseEntity<?> getMyOrders(@AuthenticationPrincipal User user) {
if (user == null)
if (user == null) {
return ResponseEntity.status(401).body("Unauthorized");

}
return ResponseEntity.ok(orderService.getOrdersByUser(user));
}

// Customer or Admin view single order
@GetMapping("/{id}")
public ResponseEntity<?> getOrderById(
@PathVariable Long id,
@AuthenticationPrincipal User user
) {
if (user == null)
public ResponseEntity<?> getOrderById(@PathVariable Long id, @AuthenticationPrincipal User user) {
if (user == null) {
return ResponseEntity.status(401).body("Unauthorized");
}

Optional<Order> optional = orderService.getOrderById(id);

return orderService.getOrderById(id)
.map(order -> {
if (order.getUser().getId().equals(user.getId()) ||
user.getRole() == User.Role.ADMIN)
return ResponseEntity.ok(order);
else
return ResponseEntity.status(403).body("Forbidden");
})
.orElse(ResponseEntity.notFound().build());
if (optional.isPresent()) {
Order order = optional.get();
// User owns order OR is admin
if (order.getUser().getId().equals(user.getId()) || user.getRole() == User.Role.ADMIN) {
return ResponseEntity.ok(order);
} else {
return ResponseEntity.status(403).body("Forbidden");
}
}
// Order does not exist
return ResponseEntity.notFound().build();
}

// Admin — get all orders
Expand All @@ -91,18 +85,13 @@ public ResponseEntity<?> getAllOrders() {
// Admin — update order status
@PatchMapping("/admin/{id}/status")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> updateOrderStatus(
@PathVariable Long id,
@RequestParam String status
) {
public ResponseEntity<?> updateOrderStatus(@PathVariable Long id, @RequestParam String status) {
try {
Order.Status newStatus = Order.Status.valueOf(status.toUpperCase());
Order updated = orderService.updateStatus(id, newStatus);
return ResponseEntity.ok(updated);

} catch (IllegalArgumentException e) {
return ResponseEntity.badRequest().body("Invalid status value.");

} catch (Exception e) {
return ResponseEntity.notFound().build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,73 +28,37 @@ public class PaymentController {
private String cancelUrl;

@PostMapping("/create-checkout-session")
public ResponseEntity<?> createCheckoutSession(
@RequestBody CheckoutRequest request,
@AuthenticationPrincipal User user) {

public ResponseEntity<?> createCheckoutSession(@RequestBody CheckoutRequest request, @AuthenticationPrincipal User user) {
if (user == null) {
return ResponseEntity.status(401).body("Unauthorized");
}

try {
Stripe.apiKey = stripeSecretKey;

if (request.getItems() == null || request.getItems().isEmpty()) {
return ResponseEntity.badRequest().body("Items required");
}

SessionCreateParams.Builder builder = SessionCreateParams.builder()
.setMode(SessionCreateParams.Mode.PAYMENT)
.setSuccessUrl(successUrl)
.setCancelUrl(cancelUrl);

SessionCreateParams.Builder builder = SessionCreateParams.builder().setMode(SessionCreateParams.Mode.PAYMENT).setSuccessUrl(successUrl).setCancelUrl(cancelUrl);
for (CheckoutItemDTO item : request.getItems()) {

if (item.getPrice() == null) {
return ResponseEntity.badRequest()
.body("Invalid price for productId=" + item.getProductId());
return ResponseEntity.badRequest().body("Invalid price for productId=" + item.getProductId());
}

if (item.getQuantity() <= 0) {
return ResponseEntity.badRequest()
.body("Invalid quantity for productId=" + item.getProductId());
return ResponseEntity.badRequest().body("Invalid quantity for productId=" + item.getProductId());
}
long unitAmountCents = item.getPrice().multiply(new BigDecimal("100")).longValue();

long unitAmountCents = item.getPrice()
.multiply(new BigDecimal("100"))
.longValue();

builder.addLineItem(
SessionCreateParams.LineItem.builder()
.setQuantity((long) item.getQuantity())
.setPriceData(
SessionCreateParams.LineItem.PriceData.builder()
.setCurrency("usd")
.setUnitAmount(unitAmountCents)
.setProductData(
SessionCreateParams.LineItem.PriceData.ProductData.builder()
.setName(item.getName())
.build()
)
.build()
)
.build()
);
builder.addLineItem(SessionCreateParams.LineItem.builder().setQuantity((long) item.getQuantity()).setPriceData(
SessionCreateParams.LineItem.PriceData.builder().setCurrency("usd").setUnitAmount(unitAmountCents).setProductData(
SessionCreateParams.LineItem.PriceData.ProductData.builder().setName(item.getName()).build()).build()).build());
}

Session session = Session.create(builder.build());

return ResponseEntity.ok(
Map.of(
"url", session.getUrl(),
"sessionID", session.getId()
)
);

Map.of("url", session.getUrl(),"sessionID", session.getId()));
} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.internalServerError()
.body("Stripe error: " + e.getMessage());
return ResponseEntity.internalServerError().body("Stripe error: " + e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ public ResponseEntity<?> getProducts(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "100") int size,
@RequestParam(defaultValue = "id") String sortBy,
@RequestParam(defaultValue = "asc") String sortDir
) {
@RequestParam(defaultValue = "asc") String sortDir) {
Page<Product> products = productService.getProducts(category, search, minPrice, maxPrice, inStock, page, size, sortBy, sortDir);
return ResponseEntity.ok(products);
}
Expand All @@ -71,6 +70,25 @@ public ResponseEntity<List<Product>> getByCategory(@PathVariable String category
return ResponseEntity.ok(productService.getByCategory(category));
}

// Recommendations
// Top-rated products
@GetMapping("/recommendations/top-rated")
@PreAuthorize("permitAll()")
public ResponseEntity<List<Product>> getTopRatedProducts(@RequestParam(defaultValue = "50") int n) {
return ResponseEntity.ok(productService.getTopRatedProducts(n));
}

// Personalized-based: user's order history
@GetMapping("/recommendations/personal")
@PreAuthorize("hasRole('CUSTOMER') or hasRole('ADMIN')")
public ResponseEntity<List<Product>> getPersonalRecommendations(@AuthenticationPrincipal User currentUser, @RequestParam(defaultValue = "50") int n ) {
if (currentUser == null) {
// Fallback to top rated if somehow no principal
return ResponseEntity.ok(productService.getTopRatedProducts(n));
}
return ResponseEntity.ok(productService.getRecommendationsForUser(currentUser.getId(), n));
}

// Update product (Admin only)
@PreAuthorize("hasRole('ADMIN')")
@PutMapping("/{id}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,10 @@ public List<ProductReview> getReviews(@PathVariable Long productId) {
}

@PostMapping("/{productId}")
public ProductReview addReview(
@RequestHeader("Authorization") String token,
@PathVariable Long productId,
@RequestBody ReviewRequest req) {

public ProductReview addReview(@RequestHeader("Authorization") String token, @PathVariable Long productId, @RequestBody ReviewRequest req) {
User user = getUser(token);

return reviewService.addReview(productId, req.rating, req.comment, user);
}

public static class ReviewRequest {
public int rating;
public String comment;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,8 @@ public UserController(UserService userService, PasswordEncoder passwordEncoder)
public ResponseEntity<?> register(@RequestBody User user) {
try {
if (userService.findByEmail(user.getEmail()) != null) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("Email is already in use.");
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Email is already in use.");
}

if (user.getRole() == null) {
user.setRole(User.Role.CUSTOMER);
}
Expand All @@ -44,8 +42,7 @@ public ResponseEntity<?> register(@RequestBody User user) {

} catch (Exception e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("An error occurred during registration");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An error occurred during registration");
}
}

Expand Down Expand Up @@ -73,10 +70,7 @@ public ResponseEntity<?> getCurrentUser(@AuthenticationPrincipal User currentUse
// UPDATE profile for Customer and Admin
@PutMapping("/me")
@PreAuthorize("hasAnyRole('CUSTOMER', 'ADMIN')")
public ResponseEntity<?> updateProfile(
@AuthenticationPrincipal User currentUser,
@RequestBody User updatedUser) {

public ResponseEntity<?> updateProfile(@AuthenticationPrincipal User currentUser, @RequestBody User updatedUser) {
if (currentUser == null) {
return ResponseEntity.status(401).body("Unauthorized");
}
Expand Down
Loading