From d539ae78540683679bff4914a6083fb32092f047 Mon Sep 17 00:00:00 2001 From: Celestino Bellone Date: Fri, 6 Sep 2019 21:01:14 +0200 Subject: [PATCH] #742 add ticket validity check for badge scan --- .../java/alfio/manager/CheckInManager.java | 31 ++++++++++++++----- .../repository/TicketCategoryRepository.java | 2 -- .../ReservationFlowIntegrationTest.java | 8 +++++ 3 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/main/java/alfio/manager/CheckInManager.java b/src/main/java/alfio/manager/CheckInManager.java index c665da0393..350a847b9d 100644 --- a/src/main/java/alfio/manager/CheckInManager.java +++ b/src/main/java/alfio/manager/CheckInManager.java @@ -50,6 +50,7 @@ import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; +import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.*; @@ -213,9 +214,19 @@ private TicketAndCheckInResult extractStatus(Optional maybeEvent, Optiona } Ticket ticket = maybeTicket.get(); + if(ticket.getCategoryId() == null) { + return new TicketAndCheckInResult(new TicketWithCategory(ticket, null), new DefaultCheckInResult(INVALID_TICKET_STATE, "Invalid ticket state")); + } + + TicketCategory tc = ticketCategoryRepository.getById(ticket.getCategoryId()); + Event event = maybeEvent.get(); if(ticketCode.filter(StringUtils::isNotBlank).isEmpty()) { - if(ticket.isCheckedIn() && ticketCategoryRepository.getCheckInStrategy(ticket.getCategoryId()) == TicketCategory.TicketCheckInStrategy.ONCE_PER_DAY) { + if(ticket.isCheckedIn() && tc.getTicketCheckInStrategy() == TicketCategory.TicketCheckInStrategy.ONCE_PER_DAY) { + if(!isBadgeValidNow(tc, event)) { + // if the badge is not currently valid, we give an error + return new TicketAndCheckInResult(new TicketWithCategory(ticket, null), new DefaultCheckInResult(INVALID_TICKET_CATEGORY_CHECK_IN_DATE, "Not allowed to check in at this time.")); + } var ticketsReservationId = ticket.getTicketsReservationId(); int previousScan = auditingRepository.countAuditsOfTypesInTheSameDay(ticketsReservationId, Set.of(CHECK_IN.name(), MANUAL_CHECK_IN.name(), BADGE_SCAN.name()), ZonedDateTime.now(event.getZoneId())); if(previousScan > 0) { @@ -228,12 +239,6 @@ private TicketAndCheckInResult extractStatus(Optional maybeEvent, Optiona String code = ticketCode.get(); - if(ticket.getCategoryId() == null) { - return new TicketAndCheckInResult(new TicketWithCategory(ticket, null), new DefaultCheckInResult(INVALID_TICKET_STATE, "Invalid ticket state")); - } - - TicketCategory tc = ticketCategoryRepository.getById(ticket.getCategoryId()); - ZonedDateTime now = ZonedDateTime.now(event.getZoneId()); if(!tc.hasValidCheckIn(now, event.getZoneId())) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy - hh:mm"); @@ -266,6 +271,18 @@ private TicketAndCheckInResult extractStatus(Optional maybeEvent, Optiona return new TicketAndCheckInResult(new TicketWithCategory(ticket, tc), new DefaultCheckInResult(OK_READY_TO_BE_CHECKED_IN, "Ready to be checked in")); } + private static boolean isBadgeValidNow(TicketCategory tc, Event event) { + var zoneId = event.getZoneId(); + var now = ZonedDateTime.now(zoneId); + return now.isAfter(toZoneIdIfNotNull(tc.getValidCheckInFrom(), zoneId).orElse(event.getBegin())) + && now.isAfter(toZoneIdIfNotNull(tc.getTicketValidityStart(), zoneId).orElse(event.getBegin())) + && now.isBefore(toZoneIdIfNotNull(tc.getTicketValidityEnd(), zoneId).orElse(event.getEnd())); + } + + private static Optional toZoneIdIfNotNull(ZonedDateTime in, ZoneId zoneId) { + return Optional.ofNullable(in).map(d -> d.withZoneSameInstant(zoneId)); + } + private static Pair getCypher(String key) { try { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); diff --git a/src/main/java/alfio/repository/TicketCategoryRepository.java b/src/main/java/alfio/repository/TicketCategoryRepository.java index 58cd64cda7..b3f1687457 100644 --- a/src/main/java/alfio/repository/TicketCategoryRepository.java +++ b/src/main/java/alfio/repository/TicketCategoryRepository.java @@ -133,6 +133,4 @@ default Map findStatisticsForEventIdByCate @Query("select access_restricted from ticket_category where id = :id") Boolean isAccessRestricted(@Bind("id") Integer hiddenCategoryId); - @Query("select ticket_checkin_strategy from ticket_category where id = :id") - TicketCategory.TicketCheckInStrategy getCheckInStrategy(@Bind("id") int categoryId); } diff --git a/src/test/java/alfio/controller/ReservationFlowIntegrationTest.java b/src/test/java/alfio/controller/ReservationFlowIntegrationTest.java index a5d5dbdb9d..d596f3627a 100644 --- a/src/test/java/alfio/controller/ReservationFlowIntegrationTest.java +++ b/src/test/java/alfio/controller/ReservationFlowIntegrationTest.java @@ -527,6 +527,14 @@ updateTicketOwnerForm, new BeanPropertyBindingResult(updateTicketOwnerForm, "upd MonetaryUtil.unitToCents(category.getPrice()), category.getCode(), category.getValidCheckInFrom(), category.getValidCheckInTo(), category.getTicketValidityStart(), category.getTicketValidityEnd(), TicketCategory.TicketCheckInStrategy.ONCE_PER_DAY ); + ticketAndcheckInResult = checkInApiController.checkIn(event.getId(), ticketIdentifier, badgeScan, new TestingAuthenticationToken("ciccio", "ciccio")); + // the event start date is in one week, so we expect an error here + assertEquals(CheckInStatus.INVALID_TICKET_CATEGORY_CHECK_IN_DATE, ticketAndcheckInResult.getResult().getStatus()); + + eventRepository.updateHeader(event.getId(), event.getDisplayName(), event.getWebsiteUrl(), event.getExternalUrl(), event.getTermsAndConditionsUrl(), event.getPrivacyPolicyUrl(), event.getImageUrl(), + event.getFileBlobId(), event.getLocation(), event.getLatitude(), event.getLongitude(), ZonedDateTime.now(event.getZoneId()).minusSeconds(1), event.getEnd(), event.getTimeZone(), + event.getOrganizationId(), event.getLocales()); + ticketAndcheckInResult = checkInApiController.checkIn(event.getId(), ticketIdentifier, badgeScan, new TestingAuthenticationToken("ciccio", "ciccio")); // we have already scanned the ticket today, so we expect to receive a warning assertEquals(CheckInStatus.BADGE_SCAN_ALREADY_DONE, ticketAndcheckInResult.getResult().getStatus());