Merge branch 'bug5510' into bug5666

# Conflicts:
#	java/com.sap.sse.security/src/com/sap/sse/security/impl/SecurityServiceImpl.java
This commit is contained in:
Udo Wessels
2022-03-16 16:56:08 +01:00
19 changed files with 149 additions and 52 deletions
@@ -45,7 +45,6 @@ public class SailingSubscriptionPlan extends SubscriptionPlan {
Stream.of(new SubscriptionPrice(YEARLY_PLAN_ITEMPRICE_ID, YEARLY_PLAN_PRICE, USD_CURRENCY_CODE,
PaymentInterval.YEAR)).collect(Collectors.toSet()),
new SubscriptionPlanRole(PremiumRole.getRoleId()));
public static final SubscriptionPlan WEEKLY = new SailingSubscriptionPlan(WEEKLY_PLAN_ID,
Stream.of(new SubscriptionPrice(WEEKLY_PLAN_ITEMPRICE_ID, WEEKLY_PLAN_PRICE, USD_CURRENCY_CODE,
PaymentInterval.WEEK)).collect(Collectors.toSet()),
@@ -68,7 +68,16 @@ public class SubscriptionViewImpl extends Composite implements SubscriptionView
public void onOpenCheckoutError(final String error) {
Notification.notify(error, NotificationType.ERROR);
}
@Override
public void onFinishedPayment(final String message) {
Notification.notify(message, NotificationType.SUCCESS);
}
@Override
public void onUnfinishedPayment(final String message) {
Notification.notify(message, NotificationType.WARNING);
}
@Override
public void resetSubscriptions() {
container.resetSubscriptions();
@@ -6,6 +6,7 @@ import com.sap.sailing.gwt.home.shared.places.subscription.SubscriptionPlace;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.dialog.ConfirmationDialog;
import com.sap.sse.security.shared.subscription.InvalidSubscriptionProviderException;
import com.sap.sse.security.ui.authentication.WithUserService;
import com.sap.sse.security.ui.client.UserService;
@@ -51,27 +52,34 @@ public class UserSubscriptionsPresenter<C extends WithUserService & WithSecurity
@Override
public void cancelSubscription(final String planId, final String providerName) {
try {
final SubscriptionWriteServiceAsync<?, ?, ?> service = factory.getWriteAsyncServiceByProvider(providerName);
service.cancelSubscription(planId, new AsyncCallback<Boolean>() {
@Override
public void onSuccess(final Boolean result) {
if (!result) {
showError(StringMessages.INSTANCE.failedCancelSubscription());
} else {
userService.updateUser(true);
fetchSubscription();
}
}
ConfirmationDialog.create(StringMessages.INSTANCE.confirmCancelSubscriptionTitle(),
StringMessages.INSTANCE.confirmCancelSubscriptionText(), StringMessages.INSTANCE.confirm(),
StringMessages.INSTANCE.cancel(), (cancel) -> {
if (cancel) {
try {
final SubscriptionWriteServiceAsync<?, ?, ?> service = factory
.getWriteAsyncServiceByProvider(providerName);
service.cancelSubscription(planId, new AsyncCallback<Boolean>() {
@Override
public void onSuccess(final Boolean result) {
if (!result) {
showError(StringMessages.INSTANCE.failedCancelSubscription());
} else {
userService.updateUser(true);
fetchSubscription();
}
}
@Override
public void onFailure(final Throwable caught) {
showError(StringMessages.INSTANCE.errorCancelSubscription(caught.getMessage()));
}
});
} catch (final InvalidSubscriptionProviderException e) {
onInvalidSubscriptionProviderError(e);
}
@Override
public void onFailure(final Throwable caught) {
showError(StringMessages.INSTANCE.errorCancelSubscription(caught.getMessage()));
}
});
} catch (final InvalidSubscriptionProviderException e) {
onInvalidSubscriptionProviderError(e);
}
}
}).center();
}
private void fetchSubscription() {
@@ -2394,4 +2394,6 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String timePointOfLastFix();
String copyMarkDeviceMappings();
String errorLoadingPolarDataForBoatClass(String boatClass, String message);
String confirmCancelSubscriptionTitle();
String confirmCancelSubscriptionText();
}
@@ -2432,4 +2432,6 @@ filterYellowBrickConfigurations=Filter YellowBrick Configuration
yellowBrickEvents=YellowBrick Events
timePointOfLastFix=Time point of last fix
copyMarkDeviceMappings=Copy mark device mappings?
errorLoadingPolarDataForBoatClass=Error loading polar data for boat class {0}: {1}
errorLoadingPolarDataForBoatClass=Error loading polar data for boat class {0}: {1}
confirmCancelSubscriptionTitle=Cancel Subscription
confirmCancelSubscriptionText=Do you really want to cancel your subscription?\n You will loose your aquired premium privileges at the end of the current term.
@@ -2442,4 +2442,6 @@ filterYellowBrickConfigurations=YellowBrick-Konfigurationen filtern
yellowBrickEvents=YellowBrick Events
timePointOfLastFix=Zeitpunkt der letzten Position
copyMarkDeviceMappings=Gerätezuordnungen für Bahnmarken übernehmen?
errorLoadingPolarDataForBoatClass=Fehler beim Laden der Polardaten zu Bootsklasse {0}: {1}
errorLoadingPolarDataForBoatClass=Fehler beim Laden der Polardaten zu Bootsklasse {0}: {1}
confirmCancelSubscriptionTitle=Abonemment Kündigen.
confirmCancelSubscriptionText=Möchten Sie ihr Abonemment wirklich kündigen?\n Sie werden ihre Premium Privilegien am Ende der aktuellen Periode verlieren.
@@ -4,6 +4,9 @@ import java.io.Serializable;
import java.util.Arrays;
import java.util.Set;
import com.sap.sse.security.shared.impl.Role;
import com.sap.sse.security.shared.impl.User;
/**
* Payment subscription plans. A subscription plan has a name, a {@link String}-based ID, and a set of
* {@link SubscriptionPlanRole roles} it grants to a subscribing user. These roles can specify how they are to be
@@ -40,6 +43,24 @@ public abstract class SubscriptionPlan implements Serializable{
return roles;
}
public boolean isUserInPossessionOfRoles(User user) {
boolean foundAll = true;
for (SubscriptionPlanRole planRole : getRoles()) {
boolean found = false;
for (Role userRole : user.getRoles()) {
if (userRole.getRoleDefinition().getId().equals(planRole.getRoleId())) {
found = true;
break;
}
}
if (!found) {
foundAll = false;
break;
}
}
return foundAll;
}
@Override
public int hashCode() {
final int prime = 31;
@@ -213,4 +213,7 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages {
String streamletsOverlayFeature();
String subscriptionSuggestionTitle();
String takeMeToSubscriptions();
String errorPollingCheckoutResults();
String paymentUnfinished();
String paymentFinished();
}
@@ -219,4 +219,7 @@ pleaseSubscribeToUseSpecific=You do not have permission to use the feature "{0}"
notLoggedIn=You have to register or log in first!
streamletsOverlayFeature=streamlet overlay
subscriptionSuggestionTitle=Lacking Permission
takeMeToSubscriptions=Go to subscription plans
takeMeToSubscriptions=Go to subscription planserrorPollingCheckoutResults
errorPollingCheckoutResults=Could not retrieve payment status.
paymentUnfinished=Waiting for payment to process.
paymentFinished=Payment successful. Premium roles have been granted.
@@ -216,4 +216,7 @@ pleaseSubscribeToUse=Erlaubnis verweigert! Möchten sie ein Abonement abschließ
pleaseSubscribeToUseSpecific=Sie sind nicht berechtigt, die Funktion "{0}" zu verwenden! Möchten sie ein Abonement abschließen?
notLoggedIn=Sie müssen sich erst registrieren bzw. anmelden!
subscriptionSuggestionTitle=Fehlende Befugnis
takeMeToSubscriptions=Zur Abbonementübersicht
takeMeToSubscriptions=Zur Abbonementübersicht
errorPollingCheckoutResults=Der Zahlungsstatus konnte nicht abgerufen werden.
paymentUnfinished=Warte auf Zahlungsbestätigung.
paymentFinished=Zahlung erfolgreich. Premium Rolle verliehen.
@@ -18,4 +18,21 @@ public interface SubscribeView {
* the {@link String error text} to show
*/
public void onOpenCheckoutError(String error);
/**
* Called if payment has not yet finished.
*
* @param error
* the {@link String error text} to show
*/
void onUnfinishedPayment(String message);
/**
* Called if payment has finished (or Trial has begun)
* and the User has aquired the roles.
*
* @param error
* the {@link String error text} to show
*/
void onFinishedPayment(String message);
}
@@ -34,4 +34,6 @@ public interface SubscriptionService<C, P> extends RemoteService {
SubscriptionPlanDTO getSubscriptionPlanById(String planId);
boolean isUserInPossessionOfRoles(String planId) throws UserManagementException;
}
@@ -19,4 +19,6 @@ public interface SubscriptionServiceAsync<C, P> {
public void getUnlockingSubscriptionplans(WildcardPermission permission, AsyncCallback<ArrayList<String>> callback);
public void getSubscriptionPlanById(String planId, AsyncCallback<SubscriptionPlanDTO> callback);
void isUserInPossessionOfRoles(String planId, AsyncCallback<Boolean> callback);
}
@@ -6,5 +6,4 @@ import com.sap.sse.security.ui.shared.subscription.chargebee.PrepareCheckoutDTO;
public interface ChargebeeSubscriptionServiceAsync
extends SubscriptionServiceAsync<ChargebeeConfigurationDTO, PrepareCheckoutDTO> {
}
@@ -1,5 +1,8 @@
package com.sap.sse.security.ui.client.subscription.chargebee;
import java.util.concurrent.atomic.AtomicBoolean;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.sap.sse.security.ui.client.i18n.StringMessages;
import com.sap.sse.security.ui.client.subscription.SubscribeView;
@@ -32,7 +35,7 @@ public class ChargebeeSubscriptionViewPresenter implements SubscriptionViewPrese
new CheckoutOption.SuccessCallback() {
@Override
public void call(final String hostedPageId) {
requestFinishingPlanUpdating(hostedPageId, view, fireUserUpdateEvent);
requestFinishingPlanUpdating(hostedPageId, view, fireUserUpdateEvent, planId);
}
}, new CheckoutOption.ErrorCallback() {
@Override
@@ -58,13 +61,14 @@ public class ChargebeeSubscriptionViewPresenter implements SubscriptionViewPrese
}
private void requestFinishingPlanUpdating(final String hostedPageId, final SubscribeView view,
final Runnable fireUserUpdateEvent) {
final Runnable fireUserUpdateEvent, String planId) {
final FinishCheckoutDTO data = new FinishCheckoutDTO();
data.setHostedPageId(hostedPageId);
writeService.finishCheckout(data, new AsyncCallback<SubscriptionListDTO>() {
@Override
public void onSuccess(final SubscriptionListDTO result) {
fireUserUpdateEvent.run();
longpoll(fireUserUpdateEvent);
Chargebee.getInstance().closeAll();
}
@@ -73,6 +77,36 @@ public class ChargebeeSubscriptionViewPresenter implements SubscriptionViewPrese
Chargebee.getInstance().closeAll();
view.onOpenCheckoutError(StringMessages.INSTANCE.errorSaveSubscription(caught.getMessage()));
}
private void longpoll(final Runnable fireUserUpdateEvent) {
final AtomicBoolean updateProcessed = new AtomicBoolean(false);
new Timer() {
private int counter = 0;
@Override
public void run() {
if (counter == 10 || updateProcessed.get()) {
this.cancel();
}
service.isUserInPossessionOfRoles(planId, new AsyncCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
if(result) {
updateProcessed.set(true);
fireUserUpdateEvent.run();
view.onFinishedPayment(StringMessages.INSTANCE.paymentFinished());
}else {
view.onUnfinishedPayment(StringMessages.INSTANCE.paymentUnfinished());
}
}
@Override
public void onFailure(Throwable caught) {
view.onOpenCheckoutError(StringMessages.INSTANCE.errorPollingCheckoutResults());
}
});
counter++;
}
}.scheduleRepeating(4000);
}
});
}
@@ -97,6 +97,13 @@ public abstract class SubscriptionServiceImpl<C, P> extends RemoteServiceServlet
});
return result;
}
@Override
public boolean isUserInPossessionOfRoles(String priceId) throws UserManagementException {
final User currentUser = getCurrentUser();
final SubscriptionPlan plan = getSecurityService().getSubscriptionPlanByItemPriceId(priceId);
return plan.isUserInPossessionOfRoles(currentUser);
}
private CompletableFuture<SecurityService> initSecurityService() {
final FullyInitializedReplicableTracker<SecurityService> tracker = FullyInitializedReplicableTracker
@@ -214,4 +221,6 @@ public abstract class SubscriptionServiceImpl<C, P> extends RemoteServiceServlet
}
protected abstract String getProviderName();
}
@@ -136,5 +136,4 @@ public class ChargebeeSubscriptionServiceImpl extends
final SubscriptionPlan subscriptionPlanById = getSecurityService().getSubscriptionPlanById(planId);
return subscriptionPlanById == null ? null : convertToDto(subscriptionPlanById);
}
}
@@ -76,6 +76,9 @@ public class ChargebeeSubscriptionWriteServiceImpl extends ChargebeeSubscription
break;
}
}
if (plan == null) {
throw new IllegalArgumentException("No such Subscriptionplan");
}
final String paymentStatus = ChargebeeSubscription.determinePaymentStatus(transactionType, transactionStatus, invoiceStatus);
final Subscription subscription = new ChargebeeSubscription(contentSubscription.id(), plan.getId(),
customerId, trialStart == null ? Subscription.emptyTime() : TimePoint.of(trialStart),
@@ -2893,33 +2893,13 @@ implements ReplicableSecurityService, ClearStateTestSupport {
if (newSubscription.isActiveSubscription() != currentSubscription.isActiveSubscription()) {
result = true;
} else {
result = checkIfRolesDiffer(user, newSubscription);
final SubscriptionPlan subscriptionPlanById = getSubscriptionPlanById(newSubscription.getPlanId());
result = !subscriptionPlanById.isUserInPossessionOfRoles(user);
}
}
return result;
}
private boolean checkIfRolesDiffer(User user, Subscription newSubscription) {
final boolean result;
final SubscriptionPlan subscriptionPlanById = getSubscriptionPlanById(newSubscription.getPlanId());
boolean foundAll = true;
for (SubscriptionPlanRole planRole : subscriptionPlanById.getRoles()) {
boolean found = false;
for (Role userRole : user.getRoles()) {
if (userRole.getRoleDefinition().getId().equals(planRole.getRoleId())) {
found = true;
break;
}
}
if (!found) {
foundAll = false;
break;
}
}
result = !foundAll;
return result;
}
@Override
public void addPermissionChangeListener(WildcardPermission permission, PermissionChangeListener listener) {
permissionChangeListeners.addPermissionChangeListener(permission, listener);