Skip to content

Commit

Permalink
#86 - first version of REST APIs (view list and detail, register scan)
Browse files Browse the repository at this point in the history
  • Loading branch information
cbellone committed Oct 31, 2015
1 parent 3e3ae40 commit bd9d8d2
Show file tree
Hide file tree
Showing 17 changed files with 701 additions and 7 deletions.
6 changes: 5 additions & 1 deletion src/main/java/alfio/config/WebSecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class WebSecurityConfig {
private static final String ADMIN = "ADMIN";
private static final String OWNER = "OWNER";
private static final String OPERATOR = "OPERATOR";
private static final String SPONSOR = "SPONSOR";



Expand Down Expand Up @@ -83,7 +84,9 @@ protected void configure(HttpSecurity http) throws Exception {
.authorizeRequests()
.antMatchers(ADMIN_API + "/check-in/**").hasRole(OPERATOR)
.antMatchers(HttpMethod.GET, ADMIN_API + "/events/**").hasRole(OPERATOR)
.antMatchers("/**").denyAll()
.antMatchers(ADMIN_API + "/**").denyAll()
.antMatchers(HttpMethod.POST, "/api/attendees/sponsor-scan").hasRole(SPONSOR)
.antMatchers("/**").authenticated()
.and().httpBasic();
}
}
Expand Down Expand Up @@ -129,6 +132,7 @@ protected void configure(HttpSecurity http) throws Exception {
.antMatchers(ADMIN_API + "/**").hasAnyRole(ADMIN, OWNER)
.antMatchers("/admin/**/export/**").hasAnyRole(ADMIN, OWNER)
.antMatchers("/admin/**").hasAnyRole(ADMIN, OWNER, OPERATOR)
.antMatchers("/api/attendees/sponsor-scan").denyAll()
.antMatchers("/**").permitAll()
.and()
.formLogin()
Expand Down
59 changes: 59 additions & 0 deletions src/main/java/alfio/controller/api/AttendeeApiController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/**
* 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;

import alfio.manager.AttendeeManager;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.ZonedDateTime;

@RestController
@RequestMapping("/api/attendees")
@Log4j2
public class AttendeeApiController {

private final AttendeeManager attendeeManager;

@Autowired
public AttendeeApiController(AttendeeManager attendeeManager) {
this.attendeeManager = attendeeManager;
}

@ExceptionHandler({DataIntegrityViolationException.class, IllegalArgumentException.class})
public ResponseEntity<String> handleDataIntegrityException(Exception e) {
log.warn("bad input detected", e);
return new ResponseEntity<>("the requested resource already exists", HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleGenericException(RuntimeException e) {
log.error("unexpected exception", e);
return new ResponseEntity<>("unexpected error", HttpStatus.INTERNAL_SERVER_ERROR);
}


@RequestMapping(value = "/sponsor-scan", method = RequestMethod.POST)
public ResponseEntity<ZonedDateTime> scanBadge(@RequestParam("eventId") int eventId, @RequestParam("ticketIdentifier") String ticketIdentifier) {
return attendeeManager.registerSponsorScan(eventId, ticketIdentifier).map(z -> new ResponseEntity<>(z, HttpStatus.CONFLICT)).orElseGet(() -> new ResponseEntity<>(HttpStatus.OK));
}

}
114 changes: 114 additions & 0 deletions src/main/java/alfio/controller/api/EventPublicApiController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* 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;

import alfio.controller.api.support.DescriptionsLoader;
import alfio.controller.api.support.EventListItem;
import alfio.controller.api.support.PublicCategory;
import alfio.controller.api.support.PublicEvent;
import alfio.manager.EventManager;
import alfio.manager.TicketReservationManager;
import alfio.manager.system.ConfigurationManager;
import alfio.model.Event;
import alfio.model.TicketCategory;
import alfio.model.system.Configuration;
import alfio.model.system.ConfigurationKeys;
import alfio.repository.EventDescriptionRepository;
import alfio.repository.EventRepository;
import alfio.repository.TicketCategoryDescriptionRepository;
import alfio.repository.TicketCategoryRepository;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api")
@Log4j2
public class EventPublicApiController {

private final EventManager eventManager;
private final EventRepository eventRepository;
private final TicketCategoryRepository ticketCategoryRepository;
private final TicketReservationManager ticketReservationManager;
private final ConfigurationManager configurationManager;
private final DescriptionsLoader descriptionsLoader;

@Autowired
public EventPublicApiController(EventManager eventManager,
EventRepository eventRepository,
TicketCategoryRepository ticketCategoryRepository,
TicketReservationManager ticketReservationManager,
ConfigurationManager configurationManager,
DescriptionsLoader descriptionsLoader) {
this.eventManager = eventManager;
this.eventRepository = eventRepository;
this.ticketCategoryRepository = ticketCategoryRepository;
this.ticketReservationManager = ticketReservationManager;
this.configurationManager = configurationManager;
this.descriptionsLoader = descriptionsLoader;
}

@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleGenericException(RuntimeException e) {
log.error("unexpected exception", e);
return new ResponseEntity<>("unexpected error", HttpStatus.INTERNAL_SERVER_ERROR);
}

@RequestMapping("/events")
public ResponseEntity<List<EventListItem>> getEvents(HttpServletRequest request) {
List<EventListItem> events = eventManager.getActiveEvents().stream()
.map(e -> new EventListItem(e, request.getContextPath(), descriptionsLoader.eventDescriptions()))
.collect(Collectors.toList());
return new ResponseEntity<>(events, getCorsHeaders(), HttpStatus.OK);
}

@RequestMapping("/events/{shortName}")
public ResponseEntity<PublicEvent> getEvent(@PathVariable("shortName") String shortName, HttpServletRequest request) {
return eventRepository.findOptionalByShortName(shortName)
.map(e -> {
List<PublicCategory> categories = ticketCategoryRepository.findAllTicketCategories(e.getId()).stream()
.map(c -> buildPublicCategory(c, e))
.collect(Collectors.toList());
return new ResponseEntity<>(new PublicEvent(e, request.getContextPath(), descriptionsLoader.eventDescriptions(), categories), getCorsHeaders(), HttpStatus.OK);
})
.orElseGet(() -> new ResponseEntity<>(getCorsHeaders(), HttpStatus.NOT_FOUND));
}

private static HttpHeaders getCorsHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.add("Access-Control-Allow-Origin", "*");
return headers;
}

private PublicCategory buildPublicCategory(TicketCategory c, Event e) {
return new PublicCategory(c, e,
ticketReservationManager.countAvailableTickets(e, c),
configurationManager.getIntConfigValue(Configuration.from(e.getOrganizationId(), e.getId(), c.getId(), ConfigurationKeys.MAX_AMOUNT_OF_TICKETS_BY_RESERVATION), 5),
descriptionsLoader.ticketCategoryDescriptions());
}

}
24 changes: 24 additions & 0 deletions src/main/java/alfio/controller/api/support/DataLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* 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.support;

import java.util.List;

@FunctionalInterface
public interface DataLoader<I,O> {
List<O> load(I input);
}
48 changes: 48 additions & 0 deletions src/main/java/alfio/controller/api/support/DescriptionsLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* 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.support;

import alfio.model.Event;
import alfio.model.EventDescription;
import alfio.model.TicketCategory;
import alfio.model.TicketCategoryDescription;
import alfio.repository.EventDescriptionRepository;
import alfio.repository.TicketCategoryDescriptionRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


@Component
public class DescriptionsLoader {

private final EventDescriptionRepository eventDescriptionRepository;
private final TicketCategoryDescriptionRepository categoryDescriptionRepository;

@Autowired
public DescriptionsLoader(EventDescriptionRepository eventDescriptionRepository, TicketCategoryDescriptionRepository categoryDescriptionRepository) {
this.eventDescriptionRepository = eventDescriptionRepository;
this.categoryDescriptionRepository = categoryDescriptionRepository;
}

public DataLoader<Event, EventDescription> eventDescriptions() {
return e -> eventDescriptionRepository.findByEventId(e.getId());
}

public DataLoader<TicketCategory, TicketCategoryDescription> ticketCategoryDescriptions() {
return c -> categoryDescriptionRepository.findByTicketCategoryId(c.getId());
}
}
82 changes: 82 additions & 0 deletions src/main/java/alfio/controller/api/support/EventListItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* 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.support;

import alfio.model.Event;
import alfio.model.EventDescription;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.stream.Collectors;

public class EventListItem {

protected final Event event;
protected final String requestContextPath;
protected final List<EventDescription> eventDescriptions;

public EventListItem(Event event, String requestContextPath, DataLoader<Event, EventDescription> eventDescriptionsLoader) {
this.event = event;
this.requestContextPath = requestContextPath;
this.eventDescriptions = eventDescriptionsLoader.load(event);
}

public String getImageUrl() {
return event.getFileBlobIdIsPresent() ? requestContextPath + "/file/" + event.getFileBlobId() : event.getImageUrl();
}

public String getUrl() {
return event.isInternal() ? requestContextPath + "/events/" + event.getShortName() : event.getExternalUrl();
}

public boolean isExternal() {
return !event.isInternal();
}

public String getName() {
return event.getDisplayName();
}

public List<PublicEventDescription> getDescriptions() {
return eventDescriptions.stream().map(PublicEventDescription::fromEventDescription).collect(Collectors.toList());
}

public boolean isSameDay() {
return event.getSameDay();
}

public ZonedDateTime getBegin() {
return event.getBegin();
}

public ZonedDateTime getEnd() {
return event.getEnd();
}

public String getLocation() {
return event.getLocation();
}

public String getLatitude() {
return event.getLatitude();
}

public String getLongitude() {
return event.getLongitude();
}

}
Loading

0 comments on commit bd9d8d2

Please sign in to comment.