diff --git a/schedule/schedule-appengine/src/main/client/jasify/booking-via-jasify/booking-via-jasify.js b/schedule/schedule-appengine/src/main/client/jasify/booking-via-jasify/booking-via-jasify.js index 10eb8291..1be21183 100644 --- a/schedule/schedule-appengine/src/main/client/jasify/booking-via-jasify/booking-via-jasify.js +++ b/schedule/schedule-appengine/src/main/client/jasify/booking-via-jasify/booking-via-jasify.js @@ -120,7 +120,7 @@ } function confirmClearPackageSelection() { - var translation = $translate('CLEAR_PACKAGE_SELECTION_PROMPT'); + var translation = $translate('CLEAR_ACTIVITY_PACKAGE_SELECTION_PROMPT'); jasDialogs.ruSure(translation, function () { $rootScope.$apply(function () { vm.activityPackageSelection = {}; diff --git a/schedule/schedule-appengine/src/main/client/jasify/booking-via-jasify/checkout.selection.html b/schedule/schedule-appengine/src/main/client/jasify/booking-via-jasify/checkout.selection.html index 635fc055..6d5d5248 100644 --- a/schedule/schedule-appengine/src/main/client/jasify/booking-via-jasify/checkout.selection.html +++ b/schedule/schedule-appengine/src/main/client/jasify/booking-via-jasify/checkout.selection.html @@ -37,7 +37,7 @@

{{ 'NO_ITEMS_SELECTED' | translate }}

{{ 'SELECTED_ACTIVITY_PACKAGES' | translate }}

diff --git a/schedule/schedule-appengine/src/main/i18n/locale-en.json b/schedule/schedule-appengine/src/main/i18n/locale-en.json index 4c36ac30..21061847 100644 --- a/schedule/schedule-appengine/src/main/i18n/locale-en.json +++ b/schedule/schedule-appengine/src/main/i18n/locale-en.json @@ -41,6 +41,10 @@ "CHECKOUT_ERROR": "System was unable to determine the result of your checkout operation", "CHECKOUT_NOT_COMPLETE_RETRY_SELECTION": "You did not finish your checkout. You can change your selections and try again", "CHECKOUT_PAYMENT_NOT_COMPLETE_RETRY_SELECTION": "You did not complete your payment. You can change your selections and try again", + "CLEAR_ACTIVITY_PACKAGE_SELECTION": "Clear Package selection", + "CLEAR_ACTIVITY_PACKAGE_SELECTION_PROMPT": "Do you want to remove all Activity Packages?", + "CLEAR_ACTIVITY_SELECTION": "Clear Activity selection", + "CLEAR_ACTIVITY_SELECTION_PROMPT": "Do you want to remove all Activities?", "CLICK_TO_DESELECT": "Click to deselect", "CLICK_TO_SELECT": "Click to select", "COLOUR": "Colour", @@ -125,10 +129,6 @@ "PROCEED_TO_BOOKING_VIA_JASIFY": "Booking is done via Jasify. A new window will be opened where you will be able to Sign In or Create an account and proceed to your checkout", "PROFILE_SETTINGS": "Profile Settings", "REMOVE": "Remove", - "CLEAR_PACKAGE_SELECTION": "Clear Package Selection", - "CLEAR_PACKAGE_SELECTION_PROMPT": "Do you want to remove all Packages?", - "CLEAR_ACTIVITY_SELECTION": "Clear Activity Selection", - "CLEAR_ACTIVITY_SELECTION_PROMPT": "Do you want to remove all Activities?", "REMOVE_ACTIVITY": "Do you want to remove this Activity?", "REMOVE_ACTIVITY_PACKAGE": "Do you want to remove this Activity Package?", "REPEAT_DAILY": "Repeat daily", diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/SchemaMigration.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/SchemaMigration.java index 5ac34eca..097d020f 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/SchemaMigration.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/SchemaMigration.java @@ -191,7 +191,9 @@ void initializeDevSystem() { UserServiceFactory.getUserService().create(admin, "admin"); } catch (UsernameExistsException | EmailExistsException e) { // Don't really care + log.warn(e.getMessage()); } + if (EnvironmentUtil.isContinuousIntegrationEnvironment()) { log.warn("CONTINUOUS INTEGRATION: Creating test values for OAuth2ProviderConfig"); for (OAuth2ProviderEnum provider : OAuth2ProviderEnum.values()) { diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/AccountUtil.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/AccountUtil.java index 932664ac..a58c8a21 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/AccountUtil.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/AccountUtil.java @@ -7,6 +7,8 @@ import com.jasify.schedule.appengine.meta.balance.UserAccountMeta; import com.jasify.schedule.appengine.meta.common.OrganizationMeta; import com.jasify.schedule.appengine.meta.users.UserMeta; +import com.jasify.schedule.appengine.model.ModelOperation; +import com.jasify.schedule.appengine.model.TransactionOperator; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,8 +28,8 @@ public final class AccountUtil { public static final String PROFIT_AND_LOSS_ACCOUNT = "P&L"; public static final String USER_ACCOUNT_PREFIX = "u"; public static final String ORGANIZATION_ACCOUNT_PREFIX = "o"; - private static final Logger log = LoggerFactory.getLogger(AccountUtil.class); public static final String DEFAULT_CURRENCY = "CHF"; + private static final Logger log = LoggerFactory.getLogger(AccountUtil.class); private AccountUtil() { } @@ -41,25 +43,21 @@ public static Key profitAndLossAccountKey() { } public static Account profitAndLossAccount() { - com.google.appengine.api.datastore.Transaction tx = Datastore.beginTransaction(); - try { - Key id = profitAndLossAccountKey(); - Account account = Datastore.getOrNull(AccountMeta.get(), id); - if (account == null) { - account = new Account(id); - account.setCurrency(DEFAULT_CURRENCY); - log.info("Created P&L account:{}", account); - Datastore.put(tx, account); + return TransactionOperator.executeNoEx(new ModelOperation() { + @Override + public Account execute(com.google.appengine.api.datastore.Transaction tx) { + Key id = profitAndLossAccountKey(); + Account account = Datastore.getOrNull(AccountMeta.get(), id); + if (account == null) { + account = new Account(id); + account.setCurrency(DEFAULT_CURRENCY); + log.info("Created P&L account:{}", account); + Datastore.put(tx, account); + tx.commit(); + } + return account; } - - tx.commit(); - return account; - } finally { - - if (tx.isActive()) - tx.rollback(); - - } + }); } /** @@ -122,28 +120,21 @@ public static Key memberAccountIdMustExist(Key memberId) { return memberAccountMustExist(memberId).getId(); } - public static Account memberAccountMustExist(Key memberId) { - Key memberAccountId = AccountUtil.memberIdToAccountId(memberId); - com.google.appengine.api.datastore.Transaction tx = Datastore.beginTransaction(); - Account account; - try { - - account = Datastore.getOrNull(AccountMeta.get(), memberAccountId); - if (account == null) { - account = AccountUtil.newMemberAccount(memberId); - log.info("Created member account:{} for member:{}", memberAccountId, memberId); - Datastore.put(tx, account); + public static Account memberAccountMustExist(final Key memberId) { + final Key memberAccountId = AccountUtil.memberIdToAccountId(memberId); + + return TransactionOperator.executeNoEx(new ModelOperation() { + @Override + public Account execute(com.google.appengine.api.datastore.Transaction tx) { + Account account = Datastore.getOrNull(AccountMeta.get(), memberAccountId); + if (account == null) { + account = AccountUtil.newMemberAccount(memberId); + log.info("Created member account:{} for member:{}", memberAccountId, memberId); + Datastore.put(tx, account); + tx.commit(); + } + return account; } - - tx.commit(); - - } finally { - - if (tx.isActive()) - tx.rollback(); - - } - - return account; + }); } } diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/DefaultBalanceService.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/DefaultBalanceService.java index 3b6e30cb..5b0513b2 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/DefaultBalanceService.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/DefaultBalanceService.java @@ -1,5 +1,6 @@ package com.jasify.schedule.appengine.model.balance; +import com.google.api.client.repackaged.com.google.common.base.Throwables; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.taskqueue.Queue; import com.google.appengine.api.taskqueue.QueueFactory; @@ -93,7 +94,6 @@ public void subscription(Subscription subscription) throws EntityNotFoundExcepti } private void subscription(Subscription subscription, Account payer, Account beneficiary, boolean unpaid) throws EntityNotFoundException { - //TODO: Validate balance is there before we start. linkToTransfer(subscription); @@ -133,7 +133,6 @@ public void activityPackageExecution(Key activityPackageExecutionId) throws Enti } private void activityPackageExecution(ActivityPackageExecution execution, Account payer, Account beneficiary, boolean unpaid) throws EntityNotFoundException { - //TODO: Validate balance is there before we start. linkToTransfer(execution); @@ -186,20 +185,20 @@ public void applyTransfer(Transfer transfer) { * @param hasTransfer that is to be credited to the user * @return the newly allocated or restored transferId */ - private Key linkToTransfer(HasTransfer hasTransfer) { + private Key linkToTransfer(final HasTransfer hasTransfer) { Key transferId = hasTransfer.getTransferRef().getKey(); if (transferId == null) { transferId = Datastore.allocateId(transferMeta); hasTransfer.getTransferRef().setKey(transferId); - com.google.appengine.api.datastore.Transaction tx = Datastore.beginTransaction(); - try { - Datastore.put(tx, hasTransfer); - tx.commit(); - } finally { - if (tx.isActive()) - tx.rollback(); - } + TransactionOperator.executeNoEx(new ModelOperation() { + @Override + public Void execute(com.google.appengine.api.datastore.Transaction tx) { + Datastore.put(tx, hasTransfer); + tx.commit(); + return null; + } + }); } else { log.warn("{} was already linked to transfer, HasTransfer.Id={}, Transfer.Id={}", hasTransfer.getClass().getName(), hasTransfer.getId(), transferId); } @@ -212,141 +211,136 @@ private Key linkToTransfer(HasTransfer hasTransfer) { * @param executedPayment the needs to be transfered * @return the created or restored transfer */ - private Transfer createPaymentTransfer(Payment executedPayment) { + private Transfer createPaymentTransfer(final Payment executedPayment) { Preconditions.checkNotNull(executedPayment.getTransferRef().getKey()); Key userKey = Preconditions.checkNotNull(executedPayment.getUserRef().getKey()); - Transfer transfer; + final Key userAccountKey = AccountUtil.memberAccountIdMustExist(userKey); - Key userAccountKey = AccountUtil.memberAccountIdMustExist(userKey); - - com.google.appengine.api.datastore.Transaction tx = Datastore.beginTransaction(); - try { - transfer = Datastore.getOrNull(tx, transferMeta, executedPayment.getTransferRef().getKey()); - if (transfer == null) { - Double amount = executedPayment.getAmount(); - Double fee = executedPayment.getFee(); - if (fee == null) { - fee = 0d; - } - - amount -= fee; + return TransactionOperator.executeNoEx(new ModelOperation() { + @Override + public Transfer execute(com.google.appengine.api.datastore.Transaction tx) { + Transfer transfer = Datastore.getOrNull(tx, transferMeta, executedPayment.getTransferRef().getKey()); + if (transfer == null) { + Double amount = executedPayment.getAmount(); + Double fee = executedPayment.getFee(); + if (fee == null) { + fee = 0d; + } - transfer = new Transfer(); - transfer.setId(executedPayment.getTransferRef().getKey()); - transfer.setAmount(amount); - transfer.setCurrency(executedPayment.getCurrency()); - transfer.setDescription(executedPayment.describe()); - // Datastore does not allow String properties to exceed 500 characters. Do some magic. - if (transfer.getDescription().length() > 500) { - transfer.setDescription(transfer.getDescription().substring(0, 490) + " ..."); - } - transfer.setReference(executedPayment.reference()); - transfer.getPayerLegRef().setKey(Datastore.allocateId(custodialAccountKey, transactionMeta)); - transfer.getBeneficiaryLegRef().setKey(Datastore.allocateId(userAccountKey, transactionMeta)); + amount -= fee; - executedPayment.onCreateTransfer(transfer); + transfer = new Transfer(); + transfer.setId(executedPayment.getTransferRef().getKey()); + transfer.setAmount(amount); + transfer.setCurrency(executedPayment.getCurrency()); + transfer.setDescription(executedPayment.describe()); + // Datastore does not allow String properties to exceed 500 characters. Do some magic. + if (transfer.getDescription().length() > 500) { + transfer.setDescription(transfer.getDescription().substring(0, 490) + " ..."); + } + transfer.setReference(executedPayment.reference()); + transfer.getPayerLegRef().setKey(Datastore.allocateId(custodialAccountKey, transactionMeta)); + transfer.getBeneficiaryLegRef().setKey(Datastore.allocateId(userAccountKey, transactionMeta)); - Datastore.put(tx, transfer); + executedPayment.onCreateTransfer(transfer); - } else { - log.warn("Transfer already existed, Transfer.Id={}", executedPayment.getTransferRef().getKey()); + Datastore.put(tx, transfer); + } else { + log.warn("Transfer already existed, Transfer.Id={}", executedPayment.getTransferRef().getKey()); + } + tx.commit(); + return transfer; } - tx.commit(); - } finally { - if (tx.isActive()) - tx.rollback(); - } - return transfer; + }); } - private Transfer createActivityPackageExecutionTransfer(ActivityPackageExecution execution, Account payer, Account beneficiary, boolean unpaid) throws EntityNotFoundException { - Transfer transfer; - com.google.appengine.api.datastore.Transaction tx = Datastore.beginTransaction(); + private Transfer createActivityPackageExecutionTransfer(final ActivityPackageExecution execution, final Account payer, final Account beneficiary, final boolean unpaid) throws EntityNotFoundException { try { - transfer = Datastore.getOrNull(tx, transferMeta, execution.getTransferRef().getKey()); - if (transfer == null) { - ActivityPackage activityPackage = activityPackageDao.get(execution.getActivityPackageRef().getKey()); - Double amount = activityPackage.getPrice(); - transfer = new Transfer(); - transfer.setId(execution.getTransferRef().getKey()); - transfer.setAmount(amount); - if (unpaid) { //cash payments are marked as unpaid - transfer.setUnpaid(amount); + return TransactionOperator.execute(new ModelOperation() { + @Override + public Transfer execute(com.google.appengine.api.datastore.Transaction tx) throws EntityNotFoundException { + Transfer transfer = Datastore.getOrNull(tx, transferMeta, execution.getTransferRef().getKey()); + if (transfer == null) { + ActivityPackage activityPackage = activityPackageDao.get(execution.getActivityPackageRef().getKey()); + Double amount = activityPackage.getPrice(); + transfer = new Transfer(); + transfer.setId(execution.getTransferRef().getKey()); + transfer.setAmount(amount); + if (unpaid) { //cash payments are marked as unpaid + transfer.setUnpaid(amount); + } + transfer.setCurrency(activityPackage.getCurrency()); + transfer.setDescription(FormatUtil.toString(activityPackage)); + transfer.setReference(Objects.toString(execution.getId())); + transfer.getPayerLegRef().setKey(Datastore.allocateId(payer.getId(), transactionMeta)); + transfer.getBeneficiaryLegRef().setKey(Datastore.allocateId(beneficiary.getId(), transactionMeta)); + + Datastore.put(tx, transfer); + } else { + log.warn("Transfer already existed, Transfer.Id={}", execution.getTransferRef().getKey()); + } + tx.commit(); + return transfer; } - transfer.setCurrency(activityPackage.getCurrency()); - transfer.setDescription(FormatUtil.toString(activityPackage)); - transfer.setReference(Objects.toString(execution.getId())); - transfer.getPayerLegRef().setKey(Datastore.allocateId(payer.getId(), transactionMeta)); - transfer.getBeneficiaryLegRef().setKey(Datastore.allocateId(beneficiary.getId(), transactionMeta)); - - Datastore.put(tx, transfer); - - } else { - log.warn("Transfer already existed, Transfer.Id={}", execution.getTransferRef().getKey()); - } - tx.commit(); - } finally { - if (tx.isActive()) - tx.rollback(); + }); + } catch (ModelException e) { + throw Throwables.propagate(e); } - return transfer; } - private Transfer createSubscriptionTransfer(Subscription subscription, Account payer, Account beneficiary, boolean unpaid) throws EntityNotFoundException { - Transfer transfer; - com.google.appengine.api.datastore.Transaction tx = Datastore.beginTransaction(); + private Transfer createSubscriptionTransfer(final Subscription subscription, final Account payer, final Account beneficiary, final boolean unpaid) throws EntityNotFoundException { try { - transfer = Datastore.getOrNull(tx, transferMeta, subscription.getTransferRef().getKey()); - if (transfer == null) { - Activity activity = activityDao.get(subscription.getActivityRef().getKey()); - Double amount = activity.getPrice(); - transfer = new Transfer(); - transfer.setId(subscription.getTransferRef().getKey()); - transfer.setAmount(amount); - if (unpaid) { //cash payments are marked as unpaid - transfer.setUnpaid(amount); + return TransactionOperator.execute(new ModelOperation() { + @Override + public Transfer execute(com.google.appengine.api.datastore.Transaction tx) throws EntityNotFoundException { + Transfer transfer = Datastore.getOrNull(tx, transferMeta, subscription.getTransferRef().getKey()); + if (transfer == null) { + Activity activity = activityDao.get(subscription.getActivityRef().getKey()); + Double amount = activity.getPrice(); + transfer = new Transfer(); + transfer.setId(subscription.getTransferRef().getKey()); + transfer.setAmount(amount); + if (unpaid) { //cash payments are marked as unpaid + transfer.setUnpaid(amount); + } + transfer.setCurrency(activity.getCurrency()); + transfer.setDescription(FormatUtil.toString(activity)); + transfer.setReference(Objects.toString(subscription.getId())); + transfer.getPayerLegRef().setKey(Datastore.allocateId(payer.getId(), transactionMeta)); + transfer.getBeneficiaryLegRef().setKey(Datastore.allocateId(beneficiary.getId(), transactionMeta)); + + Datastore.put(tx, transfer); + tx.commit(); + } else { + log.warn("Transfer already existed, Transfer.Id={}", subscription.getTransferRef().getKey()); + } + return transfer; } - transfer.setCurrency(activity.getCurrency()); - transfer.setDescription(FormatUtil.toString(activity)); - transfer.setReference(Objects.toString(subscription.getId())); - transfer.getPayerLegRef().setKey(Datastore.allocateId(payer.getId(), transactionMeta)); - transfer.getBeneficiaryLegRef().setKey(Datastore.allocateId(beneficiary.getId(), transactionMeta)); - - Datastore.put(tx, transfer); - - } else { - log.warn("Transfer already existed, Transfer.Id={}", subscription.getTransferRef().getKey()); - } - tx.commit(); - } finally { - if (tx.isActive()) - tx.rollback(); + }); + } catch (ModelException e) { + throw Throwables.propagate(e); } - return transfer; } @Override - public Transfer createTransfer(Double amount, String currency, String description, String reference, Account payerAccount, Account beneficiaryAccount) { - com.google.appengine.api.datastore.Transaction tx = Datastore.beginTransaction(); - try { - Transfer transfer = new Transfer(); - transfer.setId(Datastore.allocateId(transferMeta)); - transfer.setAmount(amount); - transfer.setCurrency(currency); - transfer.setDescription(description); - transfer.setReference(reference); - transfer.getPayerLegRef().setKey(Datastore.allocateId(payerAccount.getId(), transactionMeta)); - transfer.getBeneficiaryLegRef().setKey(Datastore.allocateId(beneficiaryAccount.getId(), transactionMeta)); - - Datastore.put(tx, transfer); - tx.commit(); - - return transfer; - } finally { - if (tx.isActive()) - tx.rollback(); - } + public Transfer createTransfer(final Double amount, final String currency, final String description, final String reference, final Account payerAccount, final Account beneficiaryAccount) { + return TransactionOperator.executeNoEx(new ModelOperation() { + @Override + public Transfer execute(com.google.appengine.api.datastore.Transaction tx) { + Transfer transfer = new Transfer(); + transfer.setId(Datastore.allocateId(transferMeta)); + transfer.setAmount(amount); + transfer.setCurrency(currency); + transfer.setDescription(description); + transfer.setReference(reference); + transfer.getPayerLegRef().setKey(Datastore.allocateId(payerAccount.getId(), transactionMeta)); + transfer.getBeneficiaryLegRef().setKey(Datastore.allocateId(beneficiaryAccount.getId(), transactionMeta)); + Datastore.put(tx, transfer); + tx.commit(); + return transfer; + } + }); } private void applyTransferTransaction(final Transfer transfer, final boolean debit) throws ModelException { @@ -356,9 +350,9 @@ private void applyTransferTransaction(final Transfer transfer, final boolean deb Preconditions.checkNotNull(legRef.getKey(), desc); Preconditions.checkNotNull(legRef.getKey().getParent(), desc + ".parent"); - TransactionOperator.execute(new ModelOperation() { + TransactionOperator.execute(new ModelOperation() { @Override - public Void execute(com.google.appengine.api.datastore.Transaction tx) throws ModelException { + public Void execute(com.google.appengine.api.datastore.Transaction tx) { Transaction transaction = Datastore.getOrNull(tx, transactionMeta, legRef.getKey()); if (transaction == null) { transaction = new Transaction(transfer, debit); diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/task/ApplySubscriptionCharges.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/task/ApplySubscriptionCharges.java index 47a0bab6..15f3a405 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/task/ApplySubscriptionCharges.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/balance/task/ApplySubscriptionCharges.java @@ -36,7 +36,8 @@ public void run() { But, right now, we only have the "BETA" plan... So as a proof of concept, we charge 0 CHF on every subscription */ - log.info("Applying subscription fess for subscription={}", subscriptionId); + + log.info("Applying subscription fees for subscription={}", subscriptionId); Subscription subscription = Datastore.get(SubscriptionMeta.get(), subscriptionId); Transfer transfer = subscription.getTransferRef().getModel(); Transaction beneficiaryTransaction = transfer.getBeneficiaryLegRef().getModel(); diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/DefaultPaymentService.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/DefaultPaymentService.java index d2bb0f9e..4a3cf34c 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/DefaultPaymentService.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/DefaultPaymentService.java @@ -1,6 +1,7 @@ package com.jasify.schedule.appengine.model.payment; import com.google.api.client.http.GenericUrl; +import com.google.api.client.repackaged.com.google.common.base.Throwables; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.Transaction; import com.google.appengine.api.taskqueue.Queue; @@ -10,6 +11,9 @@ import com.jasify.schedule.appengine.meta.payment.PaymentMeta; import com.jasify.schedule.appengine.meta.users.UserMeta; import com.jasify.schedule.appengine.model.EntityNotFoundException; +import com.jasify.schedule.appengine.model.ModelException; +import com.jasify.schedule.appengine.model.ModelOperation; +import com.jasify.schedule.appengine.model.TransactionOperator; import com.jasify.schedule.appengine.model.application.ApplicationData; import com.jasify.schedule.appengine.model.payment.task.CancelPaymentTask; import com.jasify.schedule.appengine.model.payment.workflow.PaymentWorkflow; @@ -105,96 +109,110 @@ private void queueCancelTask(Transaction tx, Key paymentId) { } @Override - public void createPayment(PaymentProvider provider, T payment, GenericUrl baseUrl) throws EntityNotFoundException, PaymentException { + public void createPayment(final PaymentProvider provider, final T payment, final GenericUrl baseUrl) throws EntityNotFoundException, PaymentException { Preconditions.checkNotNull(payment.getId(), "PaymentService.newPayment first"); Preconditions.checkNotNull(provider); - Transaction tx = Datastore.beginTransaction(); - try { - Payment dbPayment = Datastore.getOrNull(tx, paymentMeta, payment.getId()); - if (dbPayment == null) { - throw new EntityNotFoundException("Payment id=" + payment.getId()); - } - if (dbPayment.getState() != PaymentStateEnum.New) { - throw new PaymentException("Payment.State: " + dbPayment.getState() + " (expected New)"); - } - provider.createPayment(payment, baseUrl); - Datastore.put(tx, payment); - queueCancelTask(tx, dbPayment.getId()); - - tx.commit(); - } finally { - if (tx.isActive()) { - tx.rollback(); - } + try { + TransactionOperator.execute(new ModelOperation() { + @Override + public Void execute(Transaction tx) throws EntityNotFoundException, PaymentException { + Payment dbPayment = Datastore.getOrNull(tx, paymentMeta, payment.getId()); + if (dbPayment == null) { + throw new EntityNotFoundException("Payment id=" + payment.getId()); + } + if (dbPayment.getState() != PaymentStateEnum.New) { + throw new PaymentException("Payment.State: " + dbPayment.getState() + " (expected New)"); + } + provider.createPayment(payment, baseUrl); + Datastore.put(tx, payment); + + queueCancelTask(tx, dbPayment.getId()); + tx.commit(); + return null; + } + }); + } catch (EntityNotFoundException | PaymentException e) { + throw e; + } catch (ModelException e) { + throw Throwables.propagate(e); } - transitionWorkflowList(payment); } @Override - public void executePayment(PaymentProvider provider, T payment) throws EntityNotFoundException, PaymentException { + public void executePayment(final PaymentProvider provider, final T payment) throws EntityNotFoundException, PaymentException { Preconditions.checkNotNull(provider); Preconditions.checkNotNull(payment.getId()); - Transaction tx = Datastore.beginTransaction(); - try { - Payment dbPayment = Datastore.getOrNull(tx, paymentMeta, payment.getId()); - - if (dbPayment == null) { - throw new EntityNotFoundException("Payment id=" + payment.getId()); - } - - if (dbPayment.getState() != PaymentStateEnum.Created) { - throw new PaymentException("Payment.State: " + dbPayment.getState() + " (expected Created)"); - } - provider.executePayment(payment); - Datastore.put(tx, payment); - tx.commit(); - } finally { - if (tx.isActive()) { - tx.rollback(); - } + try { + TransactionOperator.execute(new ModelOperation() { + @Override + public Void execute(Transaction tx) throws EntityNotFoundException, PaymentException { + Payment dbPayment = Datastore.getOrNull(tx, paymentMeta, payment.getId()); + + if (dbPayment == null) { + throw new EntityNotFoundException("Payment id=" + payment.getId()); + } + + if (dbPayment.getState() != PaymentStateEnum.Created) { + throw new PaymentException("Payment.State: " + dbPayment.getState() + " (expected Created)"); + } + + provider.executePayment(payment); + Datastore.put(tx, payment); + tx.commit(); + return null; + } + }); + } catch (EntityNotFoundException | PaymentException e) { + throw e; + } catch (ModelException e) { + throw Throwables.propagate(e); } transitionWorkflowList(payment); } @Override - public void cancelPayment(T payment) throws EntityNotFoundException, PaymentException { + public void cancelPayment(final T payment) throws EntityNotFoundException, PaymentException { Preconditions.checkNotNull(payment.getId()); - Transaction tx = Datastore.beginTransaction(); try { - Payment dbPayment = Datastore.getOrNull(tx, paymentMeta, payment.getId()); - - if (dbPayment == null) { - throw new EntityNotFoundException("Payment id=" + payment.getId()); - } - - if (dbPayment.getState() == PaymentStateEnum.Canceled) { - log.warn("Cancelling a canceled payment", new Throwable()); // How did this happen - return; - } - - if (dbPayment.getState() != null && dbPayment.getState().isFinal()) { - throw new IllegalStateException("Payment[" + dbPayment.getId() + "] is already in a final state: " + dbPayment.getState()); - } - dbPayment.setState(PaymentStateEnum.Canceled); - Datastore.put(tx, dbPayment); - tx.commit(); + TransactionOperator.execute(new ModelOperation() { + @Override + public Void execute(Transaction tx) throws EntityNotFoundException { + Payment dbPayment = Datastore.getOrNull(tx, paymentMeta, payment.getId()); + + if (dbPayment == null) { + throw new EntityNotFoundException("Payment id=" + payment.getId()); + } + + if (dbPayment.getState() == PaymentStateEnum.Canceled) { + log.warn("Cancelling a canceled payment", new Throwable()); // How did this happen + return null; + } + + if (dbPayment.getState() != null && dbPayment.getState().isFinal()) { + throw new IllegalStateException("Payment[" + dbPayment.getId() + "] is already in a final state: " + dbPayment.getState()); + } + dbPayment.setState(PaymentStateEnum.Canceled); + Datastore.put(tx, dbPayment); + tx.commit(); /* Must also update the payment object. It is forwarded to transitionWorkflowList call and our current model always reflects the current state in the passed in object */ - payment.setState(PaymentStateEnum.Canceled); - log.info("Payment canceled id={}", dbPayment.getId()); - } finally { - if (tx.isActive()) { - tx.rollback(); - } + payment.setState(PaymentStateEnum.Canceled); + log.info("Payment canceled id={}", dbPayment.getId()); + return null; + } + }); + } catch (EntityNotFoundException e) { + throw e; + } catch (ModelException e) { + throw Throwables.propagate(e); } - transitionWorkflowList(payment); } diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/task/CancelPaymentTask.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/task/CancelPaymentTask.java index 48851c43..789a2a31 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/task/CancelPaymentTask.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/task/CancelPaymentTask.java @@ -55,7 +55,7 @@ private boolean executePayment(Payment payment) { return true; } } - } catch (PaymentException | EntityNotFoundException e) { + } catch (EntityNotFoundException | PaymentException e) { log.error("Failed to complete payment", e); } return false; diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ActivityPackagePaymentWorkflow.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ActivityPackagePaymentWorkflow.java index 0217fb8c..8ff8a03a 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ActivityPackagePaymentWorkflow.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ActivityPackagePaymentWorkflow.java @@ -3,6 +3,7 @@ import com.google.appengine.api.datastore.Key; import com.jasify.schedule.appengine.dao.common.ActivityPackageExecutionDao; import com.jasify.schedule.appengine.model.EntityNotFoundException; +import com.jasify.schedule.appengine.model.ModelException; import com.jasify.schedule.appengine.model.OperationException; import com.jasify.schedule.appengine.model.UniqueConstraintException; import com.jasify.schedule.appengine.model.activity.ActivityPackageExecution; @@ -91,7 +92,7 @@ public void onCompleted() throws PaymentWorkflowException { } else { BalanceServiceFactory.getBalanceService().activityPackageExecution(activityPackageExecutionId); } - } catch (EntityNotFoundException e) { + } catch (ModelException e) { throw new PaymentWorkflowException(e); } } diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ActivityPaymentWorkflow.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ActivityPaymentWorkflow.java index acac1c40..efa15865 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ActivityPaymentWorkflow.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ActivityPaymentWorkflow.java @@ -3,8 +3,8 @@ import com.google.appengine.api.datastore.Key; import com.jasify.schedule.appengine.dao.common.ActivityDao; import com.jasify.schedule.appengine.model.EntityNotFoundException; +import com.jasify.schedule.appengine.model.ModelException; import com.jasify.schedule.appengine.model.OperationException; -import com.jasify.schedule.appengine.model.UniqueConstraintException; import com.jasify.schedule.appengine.model.activity.Activity; import com.jasify.schedule.appengine.model.activity.ActivityService; import com.jasify.schedule.appengine.model.activity.ActivityServiceFactory; @@ -79,18 +79,14 @@ public void onCanceled() throws PaymentWorkflowException { public void onCompleted() throws PaymentWorkflowException { if (subscriptionId != null) { Payment payment = getPaymentRef().getModel(); - if (payment.getType() == PaymentTypeEnum.Cash) { - try { + try { + if (payment.getType() == PaymentTypeEnum.Cash) { BalanceServiceFactory.getBalanceService().unpaidSubscription(subscriptionId); - } catch (EntityNotFoundException e) { - throw new PaymentWorkflowException(e); - } - } else { - try { + } else { BalanceServiceFactory.getBalanceService().subscription(subscriptionId); - } catch (EntityNotFoundException e) { - throw new PaymentWorkflowException(e); } + } catch (ModelException e) { + throw new PaymentWorkflowException(e); } } } diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ShoppingCartPaymentWorkflow.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ShoppingCartPaymentWorkflow.java index b9716506..f87fd6ae 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ShoppingCartPaymentWorkflow.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/payment/workflow/ShoppingCartPaymentWorkflow.java @@ -158,7 +158,13 @@ private void notifyPublisher(List subscriptions, List orgSubscriptions = subscriptionMap.containsKey(organization.getId()) ? subscriptionMap.get(organization.getId()) : Collections.emptyList(); Collection orgExecutions = executionMap.containsKey(organization.getId()) ? executionMap.get(organization.getId()) : Collections.emptyList(); diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/users/DefaultUserService.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/users/DefaultUserService.java index def7d4bb..9bbff344 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/users/DefaultUserService.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/users/DefaultUserService.java @@ -1,19 +1,16 @@ package com.jasify.schedule.appengine.model.users; +import com.google.api.client.repackaged.com.google.common.base.Throwables; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.datastore.Query; import com.google.appengine.api.datastore.ShortBlob; -import com.google.appengine.api.datastore.Transaction; import com.google.common.base.Preconditions; import com.jasify.schedule.appengine.mail.MailParser; import com.jasify.schedule.appengine.mail.MailServiceFactory; import com.jasify.schedule.appengine.meta.users.PasswordRecoveryMeta; import com.jasify.schedule.appengine.meta.users.UserLoginMeta; import com.jasify.schedule.appengine.meta.users.UserMeta; -import com.jasify.schedule.appengine.model.EntityNotFoundException; -import com.jasify.schedule.appengine.model.FieldValueException; -import com.jasify.schedule.appengine.model.UniqueConstraint; -import com.jasify.schedule.appengine.model.UniqueConstraintException; +import com.jasify.schedule.appengine.model.*; import com.jasify.schedule.appengine.util.DigestUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -65,7 +62,7 @@ public User newUser() { } @Override - public User create(User user, String password) throws UsernameExistsException, EmailExistsException { + public User create(final User user, String password) throws EmailExistsException, UsernameExistsException { user.setName(StringUtils.lowerCase(Preconditions.checkNotNull(StringUtils.trimToNull(user.getName()), "User.Name cannot be null"))); user.setEmail(StringUtils.lowerCase(StringUtils.trimToNull(user.getEmail()))); user.setPassword(new ShortBlob(DigestUtil.encrypt(password))); @@ -89,11 +86,15 @@ public User create(User user, String password) throws UsernameExistsException, E user.setAdmin(true);//Admin for me... } - user.setId(Datastore.allocateId(userMeta)); - - Transaction tx = Datastore.beginTransaction(); - Datastore.put(tx, user); - tx.commit(); + TransactionOperator.executeNoEx(new ModelOperation() { + @Override + public Void execute(com.google.appengine.api.datastore.Transaction tx) { + user.setId(Datastore.allocateId(userMeta)); + Datastore.put(tx, user); + tx.commit(); + return null; + } + }); notify(user); @@ -101,8 +102,8 @@ public User create(User user, String password) throws UsernameExistsException, E } @Override - public User create(User user, UserLogin login) throws UsernameExistsException, UserLoginExistsException, EmailExistsException { - login = Preconditions.checkNotNull(login, "login cannot be NULL"); + public User create(final User user, final UserLogin login) throws EmailExistsException, UsernameExistsException, UserLoginExistsException { + Preconditions.checkNotNull(login, "login cannot be NULL"); Preconditions.checkNotNull(login.getProvider(), "login.Provider cannot be NULL"); Preconditions.checkNotNull(login.getUserId(), "login.UserId cannot be NULL"); user.setName(StringUtils.lowerCase(Preconditions.checkNotNull(StringUtils.trimToNull(user.getName()), "User.Name cannot be null"))); @@ -132,13 +133,17 @@ public User create(User user, UserLogin login) throws UsernameExistsException, U } } - - Transaction tx = Datastore.beginTransaction(); - user.setId(Datastore.allocateId(userMeta)); - login.setId(Datastore.allocateId(user.getId(), userLoginMeta)); - login.getUserRef().setModel(user); - Datastore.put(tx, user, login); - tx.commit(); + TransactionOperator.executeNoEx(new ModelOperation() { + @Override + public Void execute(com.google.appengine.api.datastore.Transaction tx) { + user.setId(Datastore.allocateId(userMeta)); + login.setId(Datastore.allocateId(user.getId(), userLoginMeta)); + login.getUserRef().setModel(user); + Datastore.put(tx, user, login); + tx.commit(); + return null; + } + }); notify(user); @@ -156,102 +161,132 @@ private void notify(User user) { } @Override - public User save(User user) throws EntityNotFoundException, FieldValueException { + public User save(final User user) throws EntityNotFoundException, FieldValueException { //TODO: permissions? - - Transaction tx = Datastore.beginTransaction(); try { - User db = Datastore.getOrNull(tx, userMeta, user.getId()); - if (db == null) { - throw new EntityNotFoundException(); - } - - //TODO: why did I decide to manually copy these!? Horrible! - - - if (!StringUtils.equals(db.getName(), user.getName())) { - throw new FieldValueException("Cannot change 'name' with save();"); - } - - String email = StringUtils.trimToNull(StringUtils.lowerCase(user.getEmail())); - if (!StringUtils.equals(db.getEmail(), email)) { - if (db.getEmail() != null) uniqueEmail.releaseInCurrentTransaction(db.getEmail()); - try { - if (email != null) uniqueEmail.reserveInCurrentTransaction(email); - } catch (UniqueConstraintException e) { - throw new FieldValueException("Duplicate e-mail: " + email); + TransactionOperator.execute(new ModelOperation() { + @Override + public Void execute(com.google.appengine.api.datastore.Transaction tx) throws EntityNotFoundException, FieldValueException { + User db = Datastore.getOrNull(tx, userMeta, user.getId()); + if (db == null) { + throw new EntityNotFoundException(); + } + + //TODO: why did I decide to manually copy these!? Horrible! + + if (!StringUtils.equals(db.getName(), user.getName())) { + throw new FieldValueException("Cannot change 'name' with save();"); + } + + String email = StringUtils.trimToNull(StringUtils.lowerCase(user.getEmail())); + if (!StringUtils.equals(db.getEmail(), email)) { + if (db.getEmail() != null) uniqueEmail.releaseInCurrentTransaction(db.getEmail()); + try { + if (email != null) uniqueEmail.reserveInCurrentTransaction(email); + } catch (UniqueConstraintException e) { + throw new FieldValueException("Duplicate e-mail: " + email); + } + } + + db.setAbout(user.getAbout()); + db.setEmail(email); + db.setLocale(user.getLocale()); + db.setAdmin(user.isAdmin()); + db.setRealName(user.getRealName()); + + UserDetail model = db.getDetailRef().getModel(); + if (model == null) { + Datastore.put(tx, db); + } else { + Datastore.put(tx, db, model); + } + tx.commit(); + return null; } - } - - db.setAbout(user.getAbout()); - db.setEmail(email); - db.setLocale(user.getLocale()); - db.setAdmin(user.isAdmin()); - db.setRealName(user.getRealName()); - - UserDetail model = db.getDetailRef().getModel(); - if (model == null) { - Datastore.put(tx, db); - } else { - Datastore.put(tx, db, model); - } - tx.commit(); - } finally { - if (tx.isActive()) tx.rollback(); + }); + } catch (EntityNotFoundException | FieldValueException e) { + throw e; + } catch (ModelException e) { + throw Throwables.propagate(e); } return user; } @Override - public User setPassword(User user, String newPassword) throws EntityNotFoundException { - Transaction tx = Datastore.beginTransaction(); - User db = Datastore.getOrNull(tx, userMeta, user.getId()); - if (db == null) { - tx.rollback(); - throw new EntityNotFoundException(); + public User setPassword(final User user, final String newPassword) throws EntityNotFoundException { + try { + return TransactionOperator.execute(new ModelOperation() { + @Override + public User execute(com.google.appengine.api.datastore.Transaction tx) throws EntityNotFoundException { + User db = Datastore.getOrNull(tx, userMeta, user.getId()); + if (db == null) { + throw new EntityNotFoundException(); + } + db.setPassword(new ShortBlob(DigestUtil.encrypt(newPassword))); + Datastore.put(tx, db); + tx.commit(); + return db; + } + }); + } catch (EntityNotFoundException e) { + throw e; + } catch (ModelException e) { + throw Throwables.propagate(e); } - db.setPassword(new ShortBlob(DigestUtil.encrypt(newPassword))); - Datastore.put(tx, db); - tx.commit(); - return db; } @Override - public UserLogin addLogin(User user, UserLogin login) throws EntityNotFoundException, UserLoginExistsException { + public UserLogin addLogin(final User user, final UserLogin login) throws UserLoginExistsException, EntityNotFoundException { try { - uniqueLogin.reserve(login.getUserId(), login.getProvider()); - } catch (UniqueConstraintException e) { - throw new UserLoginExistsException(e.getMessage()); - } - - Transaction tx = Datastore.beginTransaction(); - User db = Datastore.getOrNull(tx, userMeta, user.getId()); - if (db == null) { - tx.rollback(); - uniqueLogin.release(login.getUserId(), login.getProvider()); - throw new EntityNotFoundException(); + return TransactionOperator.execute(new ModelOperation() { + @Override + public UserLogin execute(com.google.appengine.api.datastore.Transaction tx) throws UserLoginExistsException, EntityNotFoundException { + try { + uniqueLogin.reserveInCurrentTransaction(login.getUserId(), login.getProvider()); + } catch (UniqueConstraintException e) { + throw new UserLoginExistsException(e.getMessage()); + } + + User db = Datastore.getOrNull(tx, userMeta, user.getId()); + if (db == null) { + throw new EntityNotFoundException(); + } + login.setId(Datastore.allocateId(db.getId(), UserLogin.class)); + login.getUserRef().setModel(db); + + Datastore.put(tx, db, login); + tx.commit(); + return login; + } + }); + } catch (UserLoginExistsException | EntityNotFoundException e) { + throw e; + } catch (ModelException e) { + throw Throwables.propagate(e); } - login.setId(Datastore.allocateId(db.getId(), UserLogin.class)); - login.getUserRef().setModel(db); - - Datastore.put(tx, db, login); - tx.commit(); - return login; } @Override - public void removeLogin(Key id) throws EntityNotFoundException { - Transaction tx = Datastore.beginTransaction(); - UserLogin dbLogin = Datastore.getOrNull(tx, userLoginMeta, id); - if (dbLogin == null) { - tx.rollback(); - throw new EntityNotFoundException("UserLogin"); + public void removeLogin(final Key id) throws EntityNotFoundException { + try { + TransactionOperator.execute(new ModelOperation() { + @Override + public Void execute(com.google.appengine.api.datastore.Transaction tx) throws EntityNotFoundException { + UserLogin dbLogin = Datastore.getOrNull(tx, userLoginMeta, id); + if (dbLogin == null) { + throw new EntityNotFoundException("UserLogin"); + } + Datastore.delete(tx, dbLogin.getId()); + uniqueLogin.releaseInCurrentTransaction(dbLogin.getUserId(), dbLogin.getProvider()); + tx.commit(); + return null; + } + }); + } catch (EntityNotFoundException e) { + throw e; + } catch (ModelException e) { + throw Throwables.propagate(e); } - Datastore.delete(tx, dbLogin.getId()); - tx.commit(); - - uniqueLogin.release(dbLogin.getUserId(), dbLogin.getProvider()); - } @Override @@ -324,30 +359,33 @@ public User findByEmail(String email) { } @Override - public PasswordRecovery registerPasswordRecovery(String email) throws EntityNotFoundException { - User user = findByEmail(email); + public PasswordRecovery registerPasswordRecovery(final String email) throws EntityNotFoundException { + final User user = findByEmail(email); if (user == null) { throw new EntityNotFoundException(email); } - Key key; - Transaction tx = Datastore.beginTransaction(); - do { - key = Datastore.createKey(passwordRecoveryMeta, new BigInteger(32, random).toString(32)); - if (Datastore.getOrNull(tx, passwordRecoveryMeta, key) != null) { - //You know, random shit can repeat itself... In that case, we generate a new key - key = null; + return TransactionOperator.executeNoEx(new ModelOperation() { + @Override + public PasswordRecovery execute(com.google.appengine.api.datastore.Transaction tx) { + Key key; + do { + key = Datastore.createKey(passwordRecoveryMeta, new BigInteger(32, random).toString(32)); + if (Datastore.getOrNull(tx, passwordRecoveryMeta, key) != null) { + //You know, random shit can repeat itself... In that case, we generate a new key + key = null; + } + } while (key == null); + + PasswordRecovery recovery = new PasswordRecovery(); + recovery.setCode(key); + recovery.getUserRef().setModel(user); + Datastore.put(tx, recovery); + tx.commit(); + log.info("Recovery for email={}, id={} registered", email, user.getId()); + return recovery; } - } while (key == null); - - PasswordRecovery recovery = new PasswordRecovery(); - recovery.setCode(key); - recovery.getUserRef().setModel(user); - Datastore.put(tx, recovery); - tx.commit(); - - log.info("Recovery for email={}, id={} registered", email, user.getId()); - return recovery; + }); } @Override @@ -397,12 +435,10 @@ public User login(String name, String password) throws LoginFailedException { @Override public List list(Query.SortDirection order, int offset, int limit) { return search(offset, limit, order == Query.SortDirection.DESCENDING ? userMeta.id.desc : userMeta.id.asc); - } @Override public List searchByName(final Pattern pattern, Query.SortDirection order, int offset, int limit) { - if (pattern == null) { return search(offset, limit, order == Query.SortDirection.DESCENDING ? userMeta.name.desc : userMeta.name.asc); } @@ -456,7 +492,6 @@ public List searchByName(String startsWith, Query.SortDirection order, int @Override public List searchByEmail(final Pattern pattern, Query.SortDirection order, int offset, int limit) { - if (pattern == null) { return search(offset, limit, order == Query.SortDirection.DESCENDING ? userMeta.email.desc : userMeta.email.asc); } @@ -523,5 +558,4 @@ private List search(int offset, int limit, SortCriterion criteria) { private static final class Singleton { private static final UserService INSTANCE = new DefaultUserService(); } - } diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/users/UserService.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/users/UserService.java index aaed3b85..18da4926 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/users/UserService.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/model/users/UserService.java @@ -39,7 +39,7 @@ public interface UserService { User get(Key id); @Nonnull - public User getUser(Key id) throws EntityNotFoundException; + User getUser(Key id) throws EntityNotFoundException; User findByLogin(String provider, String userId); diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/AuthEndpoint.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/AuthEndpoint.java index 47833265..6c4bd65d 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/AuthEndpoint.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/AuthEndpoint.java @@ -311,6 +311,4 @@ private void notify(PasswordRecovery recovery, String siteUrl) { log.warn("Failed to notify", e); } } - - } diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/BalanceEndpoint.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/BalanceEndpoint.java index 8a465e32..5172f832 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/BalanceEndpoint.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/BalanceEndpoint.java @@ -109,7 +109,6 @@ public JasPaymentResponse createCheckoutPayment(User caller, JasCheckoutPaymentR default: throw new BadRequestException("Unsupported payment type: " + paymentRequest.getType()); } - } private T createPaymentInternal(JasifyEndpointUser jasCaller, PaymentProvider provider, diff --git a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/UserEndpoint.java b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/UserEndpoint.java index 5a74ce97..34d528c2 100644 --- a/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/UserEndpoint.java +++ b/schedule/schedule-appengine/src/main/java/com/jasify/schedule/appengine/spi/UserEndpoint.java @@ -145,12 +145,12 @@ public com.jasify.schedule.appengine.model.users.User addUser(User caller, JasAd user = UserServiceFactory.getUserService().create(request.getUser(), pw); } + if (caller == null) { boolean isOrgMember = organizationDao.isUserMemberOfAnyOrganization(user.getId()); new HttpUserSession(user, isOrgMember).put(servletRequest); //login } return user; - } } diff --git a/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/model/balance/AccountUtilTest.java b/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/model/balance/AccountUtilTest.java index 67909ee5..416172fc 100644 --- a/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/model/balance/AccountUtilTest.java +++ b/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/model/balance/AccountUtilTest.java @@ -50,7 +50,7 @@ public void testProfitAndLossAccountKey() { } @Test - public void testProfitAndLossAccount() { + public void testProfitAndLossAccount() throws Exception { Account account = AccountUtil.profitAndLossAccount(); assertNotNull(account); assertEquals(AccountUtil.profitAndLossAccountKey(), account.getId()); @@ -119,7 +119,7 @@ public void testMemberIdsAreUnique() { } @Test - public void testMemberAccountMustExistUser() { + public void testMemberAccountMustExistUser() throws Exception { Key userId = Datastore.allocateId(UserMeta.get()); assertNull(Datastore.getOrNull(UserAccountMeta.get(), AccountUtil.memberIdToAccountId(userId))); Key accountId = AccountUtil.memberAccountIdMustExist(userId); @@ -130,7 +130,7 @@ public void testMemberAccountMustExistUser() { } @Test - public void testMemberAccountMustExistOrganization() { + public void testMemberAccountMustExistOrganization() throws Exception { Key organizationId = Datastore.allocateId(OrganizationMeta.get()); assertNull(Datastore.getOrNull(UserAccountMeta.get(), AccountUtil.memberIdToAccountId(organizationId))); Key accountId = AccountUtil.memberAccountIdMustExist(organizationId); diff --git a/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/model/balance/BalanceServiceTest.java b/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/model/balance/BalanceServiceTest.java index b6f402ee..1af40c14 100644 --- a/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/model/balance/BalanceServiceTest.java +++ b/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/model/balance/BalanceServiceTest.java @@ -4,7 +4,7 @@ import com.google.appengine.tools.development.testing.LocalServiceTestHelper; import com.google.appengine.tools.development.testing.LocalTaskQueueTestConfig; import com.jasify.schedule.appengine.TestHelper; -import com.jasify.schedule.appengine.model.EntityNotFoundException; +import com.jasify.schedule.appengine.model.ModelException; import com.jasify.schedule.appengine.model.ModelMetadataUtil; import com.jasify.schedule.appengine.model.activity.*; import com.jasify.schedule.appengine.model.common.Organization; @@ -127,7 +127,7 @@ public void testPaymentPayPal() throws Exception { public void testSubscriptionWithSubscriptionId() throws Exception { assertSubscription(new DoSubscription() { @Override - public void subscription(Subscription subscription, Account payer, Account beneficiary) throws EntityNotFoundException { + public void subscription(Subscription subscription, Account payer, Account beneficiary) throws ModelException { balanceService.subscription(subscription.getId()); } }, false); @@ -137,7 +137,7 @@ public void subscription(Subscription subscription, Account payer, Account benef public void testSubscriptionWithSubscription() throws Exception { assertSubscription(new DoSubscription() { @Override - public void subscription(Subscription subscription, Account payer, Account beneficiary) throws EntityNotFoundException { + public void subscription(Subscription subscription, Account payer, Account beneficiary) throws ModelException { balanceService.subscription(subscription); } }, false); @@ -147,7 +147,7 @@ public void subscription(Subscription subscription, Account payer, Account benef public void testUnpaidSubscriptionWithSubscriptionId() throws Exception { assertSubscription(new DoSubscription() { @Override - public void subscription(Subscription subscription, Account payer, Account beneficiary) throws EntityNotFoundException { + public void subscription(Subscription subscription, Account payer, Account beneficiary) throws ModelException { balanceService.unpaidSubscription(subscription.getId()); } }, true); @@ -157,7 +157,7 @@ public void subscription(Subscription subscription, Account payer, Account benef public void testActivityPackageExecutionWithId() throws Exception { assertActivityPackageExecution(new DoActivityPackageExecution() { @Override - public void activityPackageExecution(ActivityPackageExecution execution, Account payer, Account beneficiary) throws EntityNotFoundException { + public void activityPackageExecution(ActivityPackageExecution execution, Account payer, Account beneficiary) throws ModelException { balanceService.activityPackageExecution(execution.getId()); } }, false); @@ -167,7 +167,7 @@ public void activityPackageExecution(ActivityPackageExecution execution, Account public void testActivityPackageExecutionWithModel() throws Exception { assertActivityPackageExecution(new DoActivityPackageExecution() { @Override - public void activityPackageExecution(ActivityPackageExecution execution, Account payer, Account beneficiary) throws EntityNotFoundException { + public void activityPackageExecution(ActivityPackageExecution execution, Account payer, Account beneficiary) throws ModelException { balanceService.activityPackageExecution(execution); } }, false); @@ -177,7 +177,7 @@ public void activityPackageExecution(ActivityPackageExecution execution, Account public void testUnpaidActivityPackageExecutionWithId() throws Exception { assertActivityPackageExecution(new DoActivityPackageExecution() { @Override - public void activityPackageExecution(ActivityPackageExecution execution, Account payer, Account beneficiary) throws EntityNotFoundException { + public void activityPackageExecution(ActivityPackageExecution execution, Account payer, Account beneficiary) throws ModelException { balanceService.unpaidActivityPackageExecution(execution.getId()); } }, true); @@ -447,11 +447,11 @@ public void testListTransactionsMultiple() throws Exception { assertEquals(otherTransactions.get(3).getId(), timed.get(2).getId()); } - private static interface DoSubscription { - void subscription(Subscription subscription, Account payer, Account beneficiary) throws EntityNotFoundException; + private interface DoSubscription { + void subscription(Subscription subscription, Account payer, Account beneficiary) throws ModelException; } - private static interface DoActivityPackageExecution { - void activityPackageExecution(ActivityPackageExecution activityPackageExecution, Account payer, Account beneficiary) throws EntityNotFoundException; + private interface DoActivityPackageExecution { + void activityPackageExecution(ActivityPackageExecution activityPackageExecution, Account payer, Account beneficiary) throws ModelException; } } \ No newline at end of file diff --git a/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/spi/UserEndpointTest.java b/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/spi/UserEndpointTest.java index 2d49af41..5f2cf6e1 100644 --- a/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/spi/UserEndpointTest.java +++ b/schedule/schedule-appengine/src/test/java/com/jasify/schedule/appengine/spi/UserEndpointTest.java @@ -1,6 +1,7 @@ package com.jasify.schedule.appengine.spi; import com.google.api.server.spi.response.ForbiddenException; +import com.google.api.server.spi.response.InternalServerErrorException; import com.google.api.server.spi.response.NotFoundException; import com.google.api.server.spi.response.UnauthorizedException; import com.google.appengine.api.datastore.Key; @@ -11,6 +12,7 @@ import com.jasify.schedule.appengine.http.HttpUserSession; import com.jasify.schedule.appengine.model.EntityNotFoundException; import com.jasify.schedule.appengine.model.FieldValueException; +import com.jasify.schedule.appengine.model.ModelException; import com.jasify.schedule.appengine.model.UserContext; import com.jasify.schedule.appengine.model.users.*; import com.jasify.schedule.appengine.spi.dm.JasAddUserRequest; @@ -233,19 +235,19 @@ public void testGetUserByAdmin() throws NotFoundException, UnauthorizedException } @Test(expected = NotFoundException.class) - public void testUpdateUserNullId() throws NotFoundException, UnauthorizedException, ForbiddenException, FieldValueException { + public void testUpdateUserNullId() throws NotFoundException, UnauthorizedException, ForbiddenException, FieldValueException, InternalServerErrorException { testUserServiceFactory.replay(); endpoint.updateUser(newCaller(1), null, new User()); } @Test(expected = ForbiddenException.class) - public void testUpdateUserNotSameUser() throws NotFoundException, UnauthorizedException, ForbiddenException, FieldValueException { + public void testUpdateUserNotSameUser() throws NotFoundException, UnauthorizedException, ForbiddenException, FieldValueException, InternalServerErrorException { testUserServiceFactory.replay(); endpoint.updateUser(newCaller(1), KeyFactory.createKey("u", 2), new User()); } @Test - public void testUpdateUser() throws NotFoundException, UnauthorizedException, ForbiddenException, FieldValueException, EntityNotFoundException { + public void testUpdateUser() throws NotFoundException, UnauthorizedException, ForbiddenException, ModelException, InternalServerErrorException { User expected = new User(); expect(UserServiceFactory.getUserService().save(expected)).andReturn(expected); testUserServiceFactory.replay(); @@ -254,7 +256,7 @@ public void testUpdateUser() throws NotFoundException, UnauthorizedException, Fo } @Test(expected = NotFoundException.class) - public void testUpdateUserNotFoundException() throws NotFoundException, UnauthorizedException, ForbiddenException, FieldValueException, EntityNotFoundException { + public void testUpdateUserNotFoundException() throws NotFoundException, UnauthorizedException, ForbiddenException, ModelException, InternalServerErrorException { User user = new User(); UserServiceFactory.getUserService().save(user); expectLastCall().andThrow(new EntityNotFoundException());