Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge whitelist to master #496

Merged
merged 5 commits into from
Jul 31, 2018
Merged
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
14 changes: 4 additions & 10 deletions src/main/java/alfio/controller/ReservationController.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,10 @@ public String showBookingPage(@PathVariable("eventName") String eventName,
List<Ticket> ticketsInReservation = ticketReservationManager.findTicketsInReservation(reservationId);

model.addAttribute("postponeAssignment", false)
.addAttribute("showPostpone", !forceAssignment && ticketsInReservation.size() > 1);
.addAttribute("showPostpone", !forceAssignment && ticketsInReservation.size() > 1 && ticketReservationManager.containsCategoriesLinkedToGroups(reservationId, event.getId()));


try {
model.addAttribute("delayForOfflinePayment", Math.max(1, TicketReservationManager.getOfflinePaymentWaitingPeriod(event, configurationManager)));
} catch (TicketReservationManager.OfflinePaymentException e) {
if(event.getAllowedPaymentProxies().contains(PaymentProxy.OFFLINE)) {
log.error("Already started event {} has been found with OFFLINE payment enabled" , event.getDisplayName() , e);
}
model.addAttribute("delayForOfflinePayment", 0);
}
addDelayForOffline(model, event);

OrderSummary orderSummary = ticketReservationManager.orderSummaryForReservationId(reservationId, event, locale);

Expand Down Expand Up @@ -250,7 +243,8 @@ public String validateToOverview(@PathVariable("eventName") String eventName, @P
final TotalPrice reservationCost = ticketReservationManager.totalReservationCostWithVAT(reservationId);
Configuration.ConfigurationPathKey forceAssignmentKey = Configuration.from(event.getOrganizationId(), event.getId(), ConfigurationKeys.FORCE_TICKET_OWNER_ASSIGNMENT_AT_RESERVATION);
boolean forceAssignment = configurationManager.getBooleanConfigValue(forceAssignmentKey, false);
if(forceAssignment) {

if(forceAssignment || ticketReservationManager.containsCategoriesLinkedToGroups(reservationId, event.getId())) {
contactAndTicketsForm.setPostponeAssignment(false);
}

Expand Down
184 changes: 184 additions & 0 deletions src/main/java/alfio/controller/api/admin/GroupApiController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/**
* This file is part of alf.io.
*
* alf.io is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* alf.io is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with alf.io. If not, see <http://www.gnu.org/licenses/>.
*/
package alfio.controller.api.admin;

import alfio.manager.EventManager;
import alfio.manager.GroupManager;
import alfio.manager.user.UserManager;
import alfio.model.group.Group;
import alfio.model.group.LinkedGroup;
import alfio.model.modification.GroupModification;
import alfio.model.modification.LinkedGroupModification;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static alfio.util.OptionalWrapper.optionally;

@RestController
@RequestMapping("/admin/api/group")
@RequiredArgsConstructor
public class GroupApiController {

private final GroupManager groupManager;
private final UserManager userManager;
private final EventManager eventManager;

@GetMapping("/for/{organizationId}")
public ResponseEntity<List<Group>> loadAllGroupsForOrganization(@PathVariable("organizationId") int organizationId, Principal principal) {
if(notOwner(principal.getName(), organizationId)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
return ResponseEntity.ok(groupManager.getAllForOrganization(organizationId));
}

@GetMapping("/for/{organizationId}/detail/{listId}")
public ResponseEntity<GroupModification> loadDetail(@PathVariable("organizationId") int organizationId, @PathVariable("listId") int listId, Principal principal) {
if(notOwner(principal.getName(), organizationId)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
return groupManager.loadComplete(listId).map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}

@PostMapping("/for/{organizationId}/update/{groupId}")
public ResponseEntity<GroupModification> updateGroup(@PathVariable("organizationId") int organizationId,
@PathVariable("groupId") int listId,
@RequestBody GroupModification modification,
Principal principal) {
if(notOwner(principal.getName(), organizationId)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
return groupManager.update(listId, modification).map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}

@PostMapping("/for/{organizationId}/new")
public ResponseEntity<Integer> createNew(@PathVariable("organizationId") int organizationId, @RequestBody GroupModification request, Principal principal) {
if(notOwner(principal.getName(), organizationId)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
if(request.getOrganizationId() != organizationId) {
return ResponseEntity.badRequest().build();
}
return ResponseEntity.ok(groupManager.createNew(request));
}

@GetMapping("/for/event/{eventName}/all")
public ResponseEntity<List<LinkedGroup>> findLinked(@PathVariable("eventName") String eventName,
Principal principal) {
return eventManager.getOptionalByName(eventName, principal.getName())
.map(event -> ResponseEntity.ok(groupManager.getLinksForEvent(event.getId())))
.orElseGet(() -> ResponseEntity.notFound().build());
}

@GetMapping("/for/event/{eventName}")
public ResponseEntity<LinkedGroup> findActiveGroup(@PathVariable("eventName") String eventName,
Principal principal) {
return eventManager.getOptionalByName(eventName, principal.getName())
.map(event -> {
Optional<LinkedGroup> configuration = groupManager.getLinksForEvent(event.getId()).stream()
.filter(c -> c.getTicketCategoryId() == null)
.findFirst();
return configuration.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.noContent().build());
})
.orElseGet(() -> ResponseEntity.notFound().build());
}

@GetMapping("/for/event/{eventName}/category/{categoryId}")
public ResponseEntity<LinkedGroup> findActiveGroup(@PathVariable("eventName") String eventName,
@PathVariable("categoryId") int categoryId,
Principal principal) {
return eventManager.getOptionalByName(eventName, principal.getName())
.map(event -> {
Optional<LinkedGroup> configuration = groupManager.findLinks(event.getId(), categoryId)
.stream()
.filter(c -> c.getTicketCategoryId() != null && c.getTicketCategoryId() == categoryId)
.findFirst();
return configuration.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.noContent().build());
})
.orElseGet(() -> ResponseEntity.notFound().build());
}

@PostMapping("/{groupId}/link")
public ResponseEntity<Integer> linkGroup(@PathVariable("groupId") int groupId, @RequestBody LinkedGroupModification body, Principal principal) {
if(body == null || groupId != body.getGroupId()) {
return ResponseEntity.badRequest().build();
}

return optionally(() -> eventManager.getSingleEventById(body.getEventId(), principal.getName()))
.map(event -> {
Optional<LinkedGroup> existing = groupManager.getLinksForEvent(event.getId())
.stream()
.filter(c -> Objects.equals(body.getTicketCategoryId(), c.getTicketCategoryId()))
.findFirst();
LinkedGroup link;
if(existing.isPresent()) {
link = groupManager.updateLink(existing.get().getId(), body);
} else {
link = groupManager.createLink(groupId, event.getId(), body);
}
return ResponseEntity.ok(link.getId());
})
.orElseGet(() -> ResponseEntity.notFound().build());
}

@DeleteMapping("/for/{organizationId}/link/{configurationId}")
public ResponseEntity<String> unlinkGroup(@PathVariable("organizationId") int organizationId, @PathVariable("configurationId") int configurationId, Principal principal) {
if(optionally(() -> userManager.findUserByUsername(principal.getName())).filter(u -> userManager.isOwnerOfOrganization(u, organizationId)).isPresent()) {
groupManager.disableLink(configurationId);
return ResponseEntity.ok("OK");
}
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}

@DeleteMapping("/for/{organizationId}/id/{groupId}/member/{memberId}")
public ResponseEntity<Boolean> deactivateMember(@PathVariable("groupId") int groupId,
@PathVariable("memberId") int memberId,
@PathVariable("organizationId") int organizationId,
Principal principal) {
if(notOwner(principal.getName(), organizationId) || !groupManager.findById(groupId, organizationId).isPresent()) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}

return ResponseEntity.ok(groupManager.deactivateMembers(Collections.singletonList(memberId), groupId));

}

@DeleteMapping("/for/{organizationId}/id/{groupId}")
public ResponseEntity<Boolean> deactivateGroup(@PathVariable("groupId") int groupId,
@PathVariable("organizationId") int organizationId,
Principal principal) {
if(notOwner(principal.getName(), organizationId) || !groupManager.findById(groupId, organizationId).isPresent()) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}

return ResponseEntity.ok(groupManager.deactivateGroup(groupId));
}

private boolean notOwner(String username, int organizationId) {
return !optionally(() -> userManager.findUserByUsername(username))
.filter(user -> userManager.isOwnerOfOrganization(user, organizationId))
.isPresent();
}

}
11 changes: 11 additions & 0 deletions src/main/java/alfio/controller/api/support/TicketHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import alfio.manager.EuVatChecker;
import alfio.manager.EuVatChecker.SameCountryValidator;
import alfio.manager.FileUploadManager;
import alfio.manager.GroupManager;
import alfio.manager.TicketReservationManager;
import alfio.manager.support.PartialTicketTextGenerator;
import alfio.model.*;
Expand All @@ -35,6 +36,7 @@
import alfio.util.LocaleUtil;
import alfio.util.TemplateManager;
import alfio.util.Validator;
import alfio.util.Validator.AdvancedTicketAssignmentValidator;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
Expand Down Expand Up @@ -67,6 +69,7 @@ public class TicketHelper {
private final TicketFieldRepository ticketFieldRepository;
private final AdditionalServiceItemRepository additionalServiceItemRepository;
private final EuVatChecker vatChecker;
private final GroupManager groupManager;


public List<TicketFieldConfigurationDescriptionAndValue> findTicketFieldConfigurationAndValue(Ticket ticket) {
Expand Down Expand Up @@ -110,7 +113,12 @@ private Triple<ValidationResult, Event, Ticket> assignTicket(UpdateTicketOwnerFo

final TicketReservation ticketReservation = result.getMiddle();
List<TicketFieldConfiguration> fieldConf = ticketFieldRepository.findAdditionalFieldsForEvent(event.getId());
AdvancedTicketAssignmentValidator advancedValidator = new AdvancedTicketAssignmentValidator(new SameCountryValidator(vatChecker, event.getOrganizationId(), event.getId(), ticketReservation.getId()),
new GroupManager.WhitelistValidator(event.getId(), groupManager));

Validator.AdvancedValidationContext context = new Validator.AdvancedValidationContext(updateTicketOwner, fieldConf, t.getCategoryId(), t.getUuid(), formPrefix);
ValidationResult validationResult = Validator.validateTicketAssignment(updateTicketOwner, fieldConf, bindingResult, event, formPrefix, new SameCountryValidator(vatChecker, event.getOrganizationId(), event.getId(), ticketReservation.getId()))
.or(Validator.performAdvancedValidation(advancedValidator, context, bindingResult.orElse(null)))
.ifSuccess(() -> updateTicketOwner(updateTicketOwner, request, t, event, ticketReservation, userDetails));
return Triple.of(validationResult, event, ticketRepository.findByUUID(t.getUuid()));
}
Expand Down Expand Up @@ -213,6 +221,9 @@ private void updateTicketOwner(UpdateTicketOwnerForm updateTicketOwner, HttpServ
getConfirmationTextBuilder(request, event, ticketReservation, t, category),
getOwnerChangeTextBuilder(request, t, event),
userDetails);
if(t.hasBeenSold() && !groupManager.findLinks(event.getId(), t.getCategoryId()).isEmpty()) {
ticketRepository.forbidReassignment(Collections.singletonList(t.getId()));
}
}

private PartialTicketTextGenerator getOwnerChangeTextBuilder(HttpServletRequest request, Ticket t, Event event) {
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/alfio/controller/form/ContactAndTicketsForm.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
package alfio.controller.form;

import alfio.manager.EuVatChecker;
import alfio.model.*;
import alfio.model.Event;
import alfio.model.TicketFieldConfiguration;
import alfio.model.TicketReservation;
import alfio.model.TicketReservationAdditionalInfo;
import alfio.model.result.ValidationResult;
import alfio.util.ErrorsCode;
import alfio.util.Validator;
Expand All @@ -27,7 +30,10 @@
import org.springframework.validation.ValidationUtils;

import java.io.Serializable;
import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static alfio.util.ErrorsCode.STEP_2_INVALID_VAT;
Expand Down Expand Up @@ -121,8 +127,6 @@ public void validate(BindingResult bindingResult, Event event, List<TicketFieldC
ValidationUtils.rejectIfEmptyOrWhitespace(bindingResult, "vatNr", "error.emptyField");
}

//TODO: here add vat nr validation!
//
}

if (email != null && !email.contains("@") && !bindingResult.hasFieldErrors("email")) {
Expand Down
Loading