From 0ab3d3ebe726eb1b0555612084044a1d018f42b1 Mon Sep 17 00:00:00 2001 From: Sylvain Jermini Date: Thu, 13 Jun 2019 15:02:44 +0200 Subject: [PATCH] remove use of eventController in event api v2 controller #588 --- .../api/v2/user/EventApiV2Controller.java | 62 ++++++++++++++----- .../user/ReservationFlowIntegrationTest.java | 6 +- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/main/java/alfio/controller/api/v2/user/EventApiV2Controller.java b/src/main/java/alfio/controller/api/v2/user/EventApiV2Controller.java index abfec4220a..0806253c24 100644 --- a/src/main/java/alfio/controller/api/v2/user/EventApiV2Controller.java +++ b/src/main/java/alfio/controller/api/v2/user/EventApiV2Controller.java @@ -16,7 +16,6 @@ */ package alfio.controller.api.v2.user; -import alfio.controller.EventController; import alfio.controller.api.v2.model.*; import alfio.controller.api.v2.model.AdditionalService; import alfio.controller.api.v2.model.EventWithAdditionalInfo; @@ -43,6 +42,7 @@ import alfio.util.*; import lombok.AllArgsConstructor; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.tuple.Pair; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -50,7 +50,6 @@ import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.ServletWebRequest; -import org.springframework.web.servlet.mvc.support.RedirectAttributes; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -72,7 +71,6 @@ @AllArgsConstructor public class EventApiV2Controller { - private final EventController eventController; private final EventManager eventManager; private final EventRepository eventRepository; private final ConfigurationManager configurationManager; @@ -91,11 +89,9 @@ public class EventApiV2Controller { private final TicketReservationManager ticketReservationManager; private final PromoCodeDiscountRepository promoCodeRepository; private final EventStatisticsManager eventStatisticsManager; - - // + private final RecaptchaService recaptchaService; private final PromoCodeDiscountRepository promoCodeDiscountRepository; private final SpecialPriceRepository specialPriceRepository; - // @GetMapping("events") @@ -395,8 +391,7 @@ public ResponseEntity> reserveTicket(@PathVariable("ev @RequestParam("lang") String lang, @RequestBody ReservationForm reservation, BindingResult bindingResult, - ServletWebRequest request, - RedirectAttributes redirectAttributes) { + ServletWebRequest request) { if(StringUtils.trimToNull(reservation.getPromoCode()) != null) { var codeCheck = applyPromoCodeInRequest(eventName, reservation.getPromoCode(), request.getRequest()); @@ -407,16 +402,44 @@ public ResponseEntity> reserveTicket(@PathVariable("ev }); } - String redirectResult = eventController.reserveTicket(eventName, reservation, bindingResult, request, redirectAttributes, Locale.forLanguageTag(lang)); - if (bindingResult.hasErrors()) { - return new ResponseEntity<>(ValidatedResponse.toResponse(bindingResult, null), getCorsHeaders(), HttpStatus.UNPROCESSABLE_ENTITY); - } else { - String reservationIdentifier = redirectResult - .substring(redirectResult.lastIndexOf("reservation/")+"reservation/".length()) - .replace("/book", ""); - return ResponseEntity.ok(new ValidatedResponse<>(ValidationResult.success(), reservationIdentifier)); - } + Optional>> r = eventRepository.findOptionalByShortName(eventName).map(event -> { + if (isCaptchaInvalid(reservation.getCaptcha(), request.getRequest(), event)) { + bindingResult.reject(ErrorsCode.STEP_2_CAPTCHA_VALIDATION_FAILED); + } + + var reservationIdRes = reservation.validate(bindingResult, ticketReservationManager, additionalServiceRepository, eventManager, event).flatMap(selected -> { + Date expiration = DateUtils.addMinutes(new Date(), ticketReservationManager.getReservationTimeout(event)); + try { + String reservationId = ticketReservationManager.createTicketReservation(event, + selected.getLeft(), selected.getRight(), expiration, + SessionUtil.retrieveSpecialPriceSessionId(request.getRequest()), + SessionUtil.retrievePromotionCodeDiscount(request.getRequest()), + Locale.forLanguageTag(lang), false); + return Optional.of(reservationId); + } catch (TicketReservationManager.NotEnoughTicketsException nete) { + bindingResult.reject(ErrorsCode.STEP_1_NOT_ENOUGH_TICKETS); + } catch (TicketReservationManager.MissingSpecialPriceTokenException missing) { + bindingResult.reject(ErrorsCode.STEP_1_ACCESS_RESTRICTED); + } catch (TicketReservationManager.InvalidSpecialPriceTokenException invalid) { + bindingResult.reject(ErrorsCode.STEP_1_CODE_NOT_FOUND); + SessionUtil.cleanupSession(request.getRequest()); + } catch (TicketReservationManager.TooManyTicketsForDiscountCodeException tooMany) { + bindingResult.reject(ErrorsCode.STEP_2_DISCOUNT_CODE_USAGE_EXCEEDED); + } + + return Optional.empty(); + }); + + if (bindingResult.hasErrors()) { + return new ResponseEntity<>(ValidatedResponse.toResponse(bindingResult, null), getCorsHeaders(), HttpStatus.UNPROCESSABLE_ENTITY); + } else { + var reservationIdentifier = reservationIdRes.orElseThrow(IllegalStateException::new); + return ResponseEntity.ok(new ValidatedResponse<>(ValidationResult.success(), reservationIdentifier)); + } + }); + + return r.orElseGet(() -> ResponseEntity.notFound().build()); } @GetMapping(value = "event/{eventName}/validate-code") @@ -524,4 +547,9 @@ private static HttpHeaders getCorsHeaders() { headers.add("Access-Control-Allow-Origin", "*"); return headers; } + + private boolean isCaptchaInvalid(String recaptchaResponse, HttpServletRequest request, EventAndOrganizationId event) { + return configurationManager.isRecaptchaForTicketSelectionEnabled(event) + && !recaptchaService.checkRecaptcha(recaptchaResponse, request); + } } diff --git a/src/test/java/alfio/controller/api/v2/user/ReservationFlowIntegrationTest.java b/src/test/java/alfio/controller/api/v2/user/ReservationFlowIntegrationTest.java index 542a0e2e08..1a4863931b 100644 --- a/src/test/java/alfio/controller/api/v2/user/ReservationFlowIntegrationTest.java +++ b/src/test/java/alfio/controller/api/v2/user/ReservationFlowIntegrationTest.java @@ -426,7 +426,7 @@ public void reservationFlowTest() throws Exception { //validation error: select at least one { var form = new ReservationForm(); - var res = eventApiV2Controller.reserveTicket(event.getShortName(), "en", form, new BeanPropertyBindingResult(form, "reservation"), new ServletWebRequest(new MockHttpServletRequest(), new MockHttpServletResponse()), new RedirectAttributesModelMap()); + var res = eventApiV2Controller.reserveTicket(event.getShortName(), "en", form, new BeanPropertyBindingResult(form, "reservation"), new ServletWebRequest(new MockHttpServletRequest(), new MockHttpServletResponse())); assertEquals(HttpStatus.UNPROCESSABLE_ENTITY, res.getStatusCode()); var resBody = res.getBody(); assertFalse(resBody.isSuccess()); @@ -440,7 +440,7 @@ public void reservationFlowTest() throws Exception { ticketReservation.setAmount(1); ticketReservation.setTicketCategoryId(eventApiV2Controller.getTicketCategories(event.getShortName(), null, new MockHttpServletRequest()).getBody().getTicketCategories().get(0).getId()); form.setReservation(Collections.singletonList(ticketReservation)); - var res = eventApiV2Controller.reserveTicket(event.getShortName(), "en", form, new BeanPropertyBindingResult(form, "reservation"), new ServletWebRequest(new MockHttpServletRequest(), new MockHttpServletResponse()), new RedirectAttributesModelMap()); + var res = eventApiV2Controller.reserveTicket(event.getShortName(), "en", form, new BeanPropertyBindingResult(form, "reservation"), new ServletWebRequest(new MockHttpServletRequest(), new MockHttpServletResponse())); assertEquals(HttpStatus.OK, res.getStatusCode()); var resBody = res.getBody(); assertTrue(resBody.isSuccess()); @@ -463,7 +463,7 @@ public void reservationFlowTest() throws Exception { ticketReservation.setAmount(1); ticketReservation.setTicketCategoryId(eventApiV2Controller.getTicketCategories(event.getShortName(), null, new MockHttpServletRequest()).getBody().getTicketCategories().get(0).getId()); form.setReservation(Collections.singletonList(ticketReservation)); - var res = eventApiV2Controller.reserveTicket(event.getShortName(), "en", form, new BeanPropertyBindingResult(form, "reservation"), new ServletWebRequest(new MockHttpServletRequest(), new MockHttpServletResponse()), new RedirectAttributesModelMap()); + var res = eventApiV2Controller.reserveTicket(event.getShortName(), "en", form, new BeanPropertyBindingResult(form, "reservation"), new ServletWebRequest(new MockHttpServletRequest(), new MockHttpServletResponse())); assertEquals(HttpStatus.OK, res.getStatusCode()); var resBody = res.getBody(); assertTrue(resBody.isSuccess());