Skip to content

Commit

Permalink
Embedded customization (#1144)
Browse files Browse the repository at this point in the history
* add EmbeddingConfiguration

* support EmbeddingConfiguration + add metadata to reservation
  • Loading branch information
cbellone committed Dec 3, 2022
1 parent 90ff725 commit 586cf79
Show file tree
Hide file tree
Showing 20 changed files with 204 additions and 19 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Expand Up @@ -8,4 +8,4 @@ targetCompatibility=11
systemProp.jdk.tls.client.protocols="TLSv1,TLSv1.1,TLSv1.2"

# https://jitpack.io/#alfio-event/alf.io-public-frontend -> go to commit tab, set the version
alfioPublicFrontendVersion=b34d95ac2b
alfioPublicFrontendVersion=3e3376d14b
Expand Up @@ -19,13 +19,15 @@
import alfio.manager.EventManager;
import alfio.manager.PromoCodeRequestManager;
import alfio.manager.TicketReservationManager;
import alfio.model.ReservationMetadata;
import alfio.model.api.v1.admin.ReservationCreationRequest;
import alfio.model.result.ErrorCode;
import alfio.util.ReservationUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.web.bind.annotation.*;

Expand Down Expand Up @@ -55,6 +57,7 @@ public ReservationApiV1Controller(TicketReservationManager ticketReservationMana
}

@PostMapping("/{slug}/reservation")
@Transactional
public ResponseEntity<CreationResponse> createReservation(@PathVariable("slug") String eventSlug,
@RequestBody ReservationCreationRequest reservationCreationRequest,
Principal principal) {
Expand All @@ -76,6 +79,9 @@ public ResponseEntity<CreationResponse> createReservation(@PathVariable("slug")
if(user != null) {
ticketReservationManager.setReservationOwner(id, user.getUsername(), user.getEmail(), user.getFirstName(), user.getLastName(), locale.getLanguage());
}
if(reservationCreationRequest.getReservationConfiguration() != null) {
ticketReservationManager.setReservationMetadata(id, new ReservationMetadata(reservationCreationRequest.getReservationConfiguration().isHideContactData()));
}
return ResponseEntity.ok(CreationResponse.success(id, ticketReservationManager.reservationUrlForExternalClients(id, event, locale.getLanguage(), user != null)));
})
.orElseGet(() -> ResponseEntity.badRequest().build());
Expand Down
Expand Up @@ -33,6 +33,9 @@ public interface ApiPurchaseContext {

OfflinePaymentConfiguration getOfflinePaymentConfiguration();
EventWithAdditionalInfo.CaptchaConfiguration getCaptchaConfiguration();

EmbeddingConfiguration getEmbeddingConfiguration();

boolean isVatIncluded();
boolean isFree();
String getCurrency();
Expand Down
@@ -0,0 +1,35 @@
/**
* 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.v2.model;

import java.util.Objects;

public class EmbeddingConfiguration {
private final String notificationOrigin;

public EmbeddingConfiguration(String notificationOrigin) {
this.notificationOrigin = Objects.requireNonNullElse(notificationOrigin, "");
}

public boolean isEnabled() {
return notificationOrigin != null && !notificationOrigin.isBlank();
}

public String getNotificationOrigin() {
return notificationOrigin;
}
}
Expand Up @@ -66,6 +66,8 @@ public class EventWithAdditionalInfo implements DateValidity, ApiPurchaseContext

private final OfflinePaymentConfiguration offlinePaymentConfiguration;

private final EmbeddingConfiguration embeddingConfiguration;

private final Map<String, Map<String, String>> i18nOverride;

private final Integer availableTicketsCount;
Expand Down Expand Up @@ -243,6 +245,11 @@ public OfflinePaymentConfiguration getOfflinePaymentConfiguration() {
return offlinePaymentConfiguration;
}

@Override
public EmbeddingConfiguration getEmbeddingConfiguration() {
return embeddingConfiguration;
}

@AllArgsConstructor
@Getter
public static class CaptchaConfiguration {
Expand Down
Expand Up @@ -19,6 +19,7 @@
import alfio.controller.api.support.BookingInfoTicket;
import alfio.model.BillingDetails;
import alfio.model.OrderSummary;
import alfio.model.ReservationMetadata;
import alfio.model.SummaryRow.SummaryType;
import alfio.model.TicketCategory;
import alfio.model.TicketReservation.TicketReservationStatus;
Expand Down Expand Up @@ -78,6 +79,8 @@ public class ReservationInfo {

private final List<SubscriptionInfo> subscriptionInfos;

private final ReservationMetadata metadata;


@AllArgsConstructor
@Getter
Expand Down
Expand Up @@ -33,6 +33,7 @@ public class SubscriptionDescriptorWithAdditionalInfo implements ApiPurchaseCont
private final InvoicingConfiguration invoicingConfiguration;
private final AnalyticsConfiguration analyticsConfiguration;
private final EventWithAdditionalInfo.CaptchaConfiguration captchaConfiguration;
private final EmbeddingConfiguration embeddingConfiguration;

//payment related information
private final String bankAccount;
Expand Down Expand Up @@ -193,6 +194,11 @@ public OfflinePaymentConfiguration getOfflinePaymentConfiguration() {
return null;
}

@Override
public EmbeddingConfiguration getEmbeddingConfiguration() {
return embeddingConfiguration;
}

@Override
public boolean isCanApplySubscriptions() {
return false;//cannot buy a subscription with another subscription
Expand Down
Expand Up @@ -160,9 +160,6 @@ public ResponseEntity<ReservationInfo> getReservationInfo(@PathVariable("reserva
var additionalInfo = ticketReservationRepository.getAdditionalInfo(reservationId);

var shortReservationId = ticketReservationManager.getShortReservationID(purchaseContext, reservation);
var italianInvoicing = additionalInfo.getInvoicingAdditionalInfo().getItalianEInvoicing() == null ?
new TicketReservationInvoicingAdditionalInfo.ItalianEInvoicing(null, null, null, null, false) :
additionalInfo.getInvoicingAdditionalInfo().getItalianEInvoicing();
//


Expand Down Expand Up @@ -211,7 +208,8 @@ public ResponseEntity<ReservationInfo> getReservationInfo(@PathVariable("reserva
//
containsCategoriesLinkedToGroups,
getActivePaymentMethods(purchaseContext, ticketsByCategory.keySet(), orderSummary, reservationId),
subscriptionInfos
subscriptionInfos,
ticketReservationRepository.getMetadata(reservationId)
));
}));

Expand Down
Expand Up @@ -47,15 +47,15 @@
import java.util.stream.Collectors;

import static alfio.model.PriceContainer.VatStatus.isVatIncluded;
import static alfio.model.system.ConfigurationKeys.BANK_ACCOUNT_NR;
import static alfio.model.system.ConfigurationKeys.BANK_ACCOUNT_OWNER;
import static alfio.model.system.ConfigurationKeys.*;
import static java.util.stream.Collectors.toList;

@RestController
@RequestMapping("/api/v2/public/")
@AllArgsConstructor
public class SubscriptionsApiController {

private static final String DATE_FORMAT_KEY = "common.event.date-format";
private final SubscriptionManager subscriptionManager;
private final I18nManager i18nManager;
private final TicketReservationManager reservationManager;
Expand All @@ -67,8 +67,6 @@ public class SubscriptionsApiController {

@GetMapping("subscriptions")
public ResponseEntity<List<BasicSubscriptionDescriptorInfo>> listSubscriptions(SearchOptions searchOptions) {
var contentLanguages = i18nManager.getAvailableLanguages();

var now = ZonedDateTime.now(ClockProvider.clock());
var activeSubscriptions = subscriptionManager.getActivePublicSubscriptionsDescriptor(now, searchOptions)
.stream()
Expand Down Expand Up @@ -100,10 +98,10 @@ private static BasicSubscriptionDescriptorInfo subscriptionDescriptorMapper(Subs
currencyDescriptor,
s.getVat(),
isVatIncluded(s.getVatStatus()),
Formatters.getFormattedDate(s, s.getOnSaleFrom(), "common.event.date-format", messageSource),
Formatters.getFormattedDate(s, s.getOnSaleTo(), "common.event.date-format", messageSource),
Formatters.getFormattedDate(s, s.getValidityFrom(), "common.event.date-format", messageSource),
Formatters.getFormattedDate(s, s.getValidityTo(), "common.event.date-format", messageSource),
Formatters.getFormattedDate(s, s.getOnSaleFrom(), DATE_FORMAT_KEY, messageSource),
Formatters.getFormattedDate(s, s.getOnSaleTo(), DATE_FORMAT_KEY, messageSource),
Formatters.getFormattedDate(s, s.getValidityFrom(), DATE_FORMAT_KEY, messageSource),
Formatters.getFormattedDate(s, s.getValidityTo(), DATE_FORMAT_KEY, messageSource),
s.getContentLanguages().stream().map(cl -> new Language(cl.getLocale().getLanguage(), cl.getDisplayLanguage())).collect(toList())
);
}
Expand Down Expand Up @@ -133,16 +131,17 @@ public ResponseEntity<SubscriptionDescriptorWithAdditionalInfo> getSubscriptionI
invoicingInfo,
analyticsConf,
captchaConf,
new EmbeddingConfiguration(configurationsValues.get(EMBED_POST_MESSAGE_ORIGIN).getValueOrNull()),
bankAccount,
bankAccountOwner,
orgContact.getEmail(),
orgContact.getName(),
DatesWithTimeZoneOffset.fromDates(s.getOnSaleFrom(), s.getOnSaleTo()),
Formatters.getFormattedDate(s, s.getOnSaleFrom(), "common.event.date-format", messageSource),
Formatters.getFormattedDate(s, s.getOnSaleTo(), "common.event.date-format", messageSource),
Formatters.getFormattedDate(s, s.getOnSaleFrom(), DATE_FORMAT_KEY, messageSource),
Formatters.getFormattedDate(s, s.getOnSaleTo(), DATE_FORMAT_KEY, messageSource),
s.getZoneId().toString(),
Formatters.getFormattedDate(s, s.getValidityFrom(), "common.event.date-format", messageSource),
Formatters.getFormattedDate(s, s.getValidityTo(), "common.event.date-format", messageSource),
Formatters.getFormattedDate(s, s.getValidityFrom(), DATE_FORMAT_KEY, messageSource),
Formatters.getFormattedDate(s, s.getValidityTo(), DATE_FORMAT_KEY, messageSource),
available);
})
.map(ResponseEntity::ok)
Expand Down
Expand Up @@ -17,6 +17,7 @@
package alfio.controller.api.v2.user.support;

import alfio.controller.api.v2.model.AnalyticsConfiguration;
import alfio.controller.api.v2.model.EmbeddingConfiguration;
import alfio.controller.api.v2.model.EventWithAdditionalInfo;
import alfio.controller.api.v2.model.OfflinePaymentConfiguration;
import alfio.controller.support.Formatters;
Expand Down Expand Up @@ -116,6 +117,7 @@ public Optional<EventWithAdditionalInfo> loadEventInfo(String eventName, HttpSes
formattedDates.beginDate, formattedDates.beginTime,
formattedDates.endDate, formattedDates.endTime,
invoicingConf, captchaConf, assignmentConf, promoConf, analyticsConf, offlinePaymentConfiguration,
new EmbeddingConfiguration(configurationsValues.get(EMBED_POST_MESSAGE_ORIGIN).getValueOrNull()),
MessageSourceManager.convertPlaceholdersForEachLanguage(i18nOverride), availableTicketsCount, customCss, hasLinkedSubscription);
});
}
Expand Down
Expand Up @@ -68,7 +68,8 @@ public static Map<ConfigurationKeys, ConfigurationManager.MaybeConfiguration> co
ENABLE_REVERSE_CHARGE_ONLINE,

DISPLAY_TICKETS_LEFT_INDICATOR,
EVENT_CUSTOM_CSS
EVENT_CUSTOM_CSS,
EMBED_POST_MESSAGE_ORIGIN
), purchaseContext.getConfigurationLevel());
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/alfio/manager/TicketReservationManager.java
Expand Up @@ -2464,6 +2464,10 @@ public void setReservationOwner(String reservationId,
);
}

public void setReservationMetadata(String reservationId, ReservationMetadata metadata) {
Validate.isTrue(ticketReservationRepository.setMetadata(reservationId, metadata) == 1, "Error while updating metadata");
}

static String buildCompleteBillingAddress(CustomerName customerName,
String billingAddressCompany,
String billingAddressLine1,
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/alfio/model/ReservationMetadata.java
@@ -0,0 +1,33 @@
/**
* 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.model;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class ReservationMetadata {
private final boolean hideContactData;

@JsonCreator
public ReservationMetadata(@JsonProperty("hideContactData") Boolean hideContactData) {
this.hideContactData = Boolean.TRUE.equals(hideContactData);
}

public boolean isHideContactData() {
return hideContactData;
}
}
@@ -0,0 +1,33 @@
/**
* 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.model.api.v1.admin;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class ReservationConfiguration {
private final boolean hideContactData;

@JsonCreator
public ReservationConfiguration(@JsonProperty("hideContactData") boolean hideContactData) {
this.hideContactData = hideContactData;
}

public boolean isHideContactData() {
return hideContactData;
}
}
Expand Up @@ -28,18 +28,21 @@ public class ReservationCreationRequest implements ReservationCreate {

private final List<TicketReservationModification> tickets;
private final List<AdditionalServiceReservationModification> additionalServices;
private final ReservationConfiguration reservationConfiguration;
private final ReservationUser user;
private final String promoCode;
private final String language;

@JsonCreator
public ReservationCreationRequest(@JsonProperty("tickets") List<TicketReservationModification> tickets,
@JsonProperty("additionalServices") List<AdditionalServiceReservationModification> additionalServices,
@JsonProperty("configuration") ReservationConfiguration reservationConfiguration,
@JsonProperty("user") ReservationUser user,
@JsonProperty("promoCode") String promoCode,
@JsonProperty("language") String language) {
this.tickets = tickets;
this.additionalServices = additionalServices;
this.reservationConfiguration = reservationConfiguration;
this.user = user;
this.promoCode = promoCode;
this.language = language;
Expand Down Expand Up @@ -73,4 +76,8 @@ public String getLanguage() {
public ReservationUser getUser() {
return user;
}

public ReservationConfiguration getReservationConfiguration() {
return reservationConfiguration;
}
}
4 changes: 3 additions & 1 deletion src/main/java/alfio/model/system/ConfigurationKeys.java
Expand Up @@ -254,7 +254,8 @@ public enum ConfigurationKeys {
SECURITY_CSP_REPORT_ENABLED("Enable Content-Security-Policy reporting (default: false)", false, SettingCategory.GENERAL, ComponentType.BOOLEAN, false, EnumSet.of(SYSTEM), BooleanUtils.FALSE),
SECURITY_CSP_REPORT_URI("Define Content-Security-Policy reporting URI (default: /report-csp-violation)", false, SettingCategory.GENERAL, ComponentType.TEXT, false, EnumSet.of(SYSTEM)),

EMBED_ALLOWED_ORIGINS("Allowed origins for embedding the reservation process in an iFrame. Separate different origins with a newline", false, SettingCategory.GENERAL, ComponentType.TEXTAREA, false, EnumSet.of(SYSTEM, ORGANIZATION, EVENT)),
EMBED_ALLOWED_ORIGINS("Allowed origins. Separate different origins with a newline", false, SettingCategory.RESERVATION_EMBED, ComponentType.TEXTAREA, false, EnumSet.of(SYSTEM)),
EMBED_POST_MESSAGE_ORIGIN("URI to notify container (via PostMessage API) for Reservation success / cancel", false, SettingCategory.RESERVATION_EMBED, ComponentType.TEXT, false, EnumSet.of(SYSTEM)),

//
TRANSLATION_OVERRIDE("Translation override (json)", false, SettingCategory.TRANSLATIONS, ComponentType.TEXTAREA, false, EnumSet.of(SYSTEM, ORGANIZATION, EVENT)),
Expand All @@ -274,6 +275,7 @@ public enum ConfigurationKeys {
public enum SettingCategory {
GENERAL("General settings"),
RESERVATION_UI("Reservation Process UI"),
RESERVATION_EMBED("Embedding reservation process"),
PAYMENT("Payment"),
PAYMENT_STRIPE("Stripe.com settings"),
PAYMENT_SAFERPAY("Saferpay settings"),
Expand Down

0 comments on commit 586cf79

Please sign in to comment.