diff --git a/TODO b/TODO deleted file mode 100644 index c561059..0000000 --- a/TODO +++ /dev/null @@ -1,14 +0,0 @@ -- ajouter la configuration du realm dans la config Docker de Keycloak - -- implémentation des services REST : - - Implem JUnit - -AddressesApiDelegate.java x x -BeefProductionsApiDelegate.java x x -CustomersApiDelegate.java x x -HonneyProductionsApiDelegate.java x -OrdersApiDelegate.java x x -PackageTemplatesApiDelegate.java x x -ProductionsApiDelegate.java x x -SalesApiDelegate.java (x) diff --git a/backend/app/src/main/java/eu/viandeendirect/domains/order/OrderService.java b/backend/app/src/main/java/eu/viandeendirect/domains/order/OrderService.java index de78f73..ddf6c6e 100644 --- a/backend/app/src/main/java/eu/viandeendirect/domains/order/OrderService.java +++ b/backend/app/src/main/java/eu/viandeendirect/domains/order/OrderService.java @@ -4,8 +4,10 @@ import eu.viandeendirect.domains.payment.StripePaymentRepository; import eu.viandeendirect.domains.payment.StripeService; import eu.viandeendirect.domains.user.CustomerRepository; +import eu.viandeendirect.domains.user.CustomerService; import eu.viandeendirect.model.*; import eu.viandeendirect.domains.production.PackageLotRepository; +import eu.viandeendirect.security.AuthenticationService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -43,14 +45,34 @@ public class OrderService implements OrdersApiDelegate { @Autowired private StripePaymentRepository stripePaymentRepository; + @Autowired + private AuthenticationService authenticationService; + @Override public ResponseEntity getOrder(Integer orderId) { Order order = orderRepository.findById(orderId).get(); + checkOrderAccess(order); List items = orderItemRepository.findByOrder(order); order.setItems(items); return new ResponseEntity<>(order, HttpStatus.OK); } + private void checkOrderAccess(Order order) { + Customer customer = authenticationService.getAuthenticatedCustomer(); + if (customer != null) { + if (!order.getCustomer().equals(customer)) { + throw new ResponseStatusException(HttpStatus.FORBIDDEN); + } + return; + } + Producer producer = authenticationService.getAuthenticatedProducer(); + if (producer!= null) { + if (order.getItems().stream().noneMatch(item -> item.getPackageLot().getProduction().getProducer().equals(producer))) { + throw new ResponseStatusException(HttpStatus.FORBIDDEN); + } + } + } + @Override public ResponseEntity createOrder(Order order) { loadCustomer(order); diff --git a/backend/app/src/main/java/eu/viandeendirect/domains/sale/SaleService.java b/backend/app/src/main/java/eu/viandeendirect/domains/sale/SaleService.java index 70509b8..0517c78 100644 --- a/backend/app/src/main/java/eu/viandeendirect/domains/sale/SaleService.java +++ b/backend/app/src/main/java/eu/viandeendirect/domains/sale/SaleService.java @@ -25,6 +25,7 @@ public class SaleService implements SalesApiDelegate { @Autowired private OrderRepository orderRepository; + @Autowired private ProductionRepository productionRepository; diff --git a/frontend/app/src/layouts/customer/CustomerLayout.tsx b/frontend/app/src/layouts/customer/CustomerLayout.tsx index 1c9e70c..16a37df 100644 --- a/frontend/app/src/layouts/customer/CustomerLayout.tsx +++ b/frontend/app/src/layouts/customer/CustomerLayout.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { AppBar, Box, CssBaseline, Toolbar, Typography } from '@mui/material' +import { AppBar, Box, CssBaseline, IconButton, Toolbar, Typography } from '@mui/material' import { useEffect, useState } from 'react' import { useCookies } from 'react-cookie' @@ -15,6 +15,7 @@ import { AuthenticationService } from '../../authentication/AuthenticationServic import CustomerOrderForm from '../../domains/sale/views/CustomerOrderForm.tsx' import CustomerCreationForm from '../../domains/customer/views/CustomerCreationForm.tsx' import Welcome from '../../domains/welcome/Welcome.tsx' +import { Login, Logout } from '@mui/icons-material' export default function CustomerLayout() { @@ -53,7 +54,7 @@ export default function CustomerLayout() { } } - function renderMainContent() { + function displayMainContent() { if(authenticationService.isAuthenticated() && customer && !customer.id) { return setCustomer(newCustomer)}> } else if(cookies.pendingOrder ) { @@ -71,6 +72,20 @@ export default function CustomerLayout() { setMainContent(ORDER_CREATION) } + function displayAuthenticationButton(): React.ReactNode { + if (authenticationService.isAuthenticated()) { + return <> + {authenticationService.getCurrentUserFirstName() } {authenticationService.getCurrentUserLastName()} + + + + + } + return + + + } + return ( @@ -84,9 +99,10 @@ export default function CustomerLayout() { Viande en direct + {displayAuthenticationButton()} - {renderMainContent()} + {displayMainContent()} ) } diff --git a/frontend/app/src/layouts/customer/PaymentLayout.tsx b/frontend/app/src/layouts/customer/PaymentLayout.tsx index ba389eb..1eca2dd 100644 --- a/frontend/app/src/layouts/customer/PaymentLayout.tsx +++ b/frontend/app/src/layouts/customer/PaymentLayout.tsx @@ -9,18 +9,24 @@ import { AppBar, Box, Button, CircularProgress, CssBaseline, Toolbar, Typography import OrderSummary from '../../domains/sale/components/OrderSummary.tsx' import Order from 'viandeendirect_eu/dist/model/Order.js'; +import { AuthenticationService } from '../../authentication/AuthenticationService.ts'; export default function PaymentLayout() { const { keycloak, initialized } = useKeycloak() const apiBuilder = new ApiBuilder() + const authenticationService = new AuthenticationService(keycloak) let { orderId } = useParams() const [order, setOrder] = useState() + const [orderAccessError, setOrderAccessError] = useState(false) + const [forbiddenAccess, setForbiddenAccess] = useState(false) let intervalId = 0 useEffect(() => { - intervalId = setInterval(loadOrder, 1000) + if (initialized) { + intervalId = setInterval(loadOrder, 1000) + } }, [initialized]) function loadOrder() { @@ -29,6 +35,11 @@ export default function PaymentLayout() { api.getOrder(orderId, (error, orderLoaded, response) => { if (error) { console.error(error) + if (response.statusCode === 403) { + setForbiddenAccess(true) + setOrderAccessError(true) + clearInterval(intervalId) + } } else { console.log('api.getOrder called successfully. Returned data: ' + orderLoaded) if (orderLoaded.status !== 'PAYMENT_PENDING') { @@ -58,14 +69,40 @@ export default function PaymentLayout() { + {getContent()} + + + ) + + function getContent() { + if (orderAccessError) { + if (forbiddenAccess) { + return <> + Désolé, vous n'êtes pas autorisé à consulter cette commande + + + } else { + return <> + Oups... une erreur s'est produite lors de l'accès à la commande {orderId} + + + } + } + if (authenticationService.isAuthenticated()) { + return <>
{getPaymentState()} {getOrderSummary()}
- - - ) + + } else { + return <> + Vous devez vous identifier pour voir l'état de votre commande + + + } + } function getPaymentState(){ if (order) {