Merge pull request #36 from dartpopikyardo/wip-customer
UI updates, backend transaction history fixes
This commit is contained in:
@@ -25,7 +25,7 @@ public class AccountsCommandSideServiceIntegrationTest {
|
||||
private int port;
|
||||
|
||||
private String baseUrl(String path) {
|
||||
return "http://localhost:" + port + "/" + path;
|
||||
return "http://localhost:" + port + "/api" + path;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/accounts")
|
||||
@RequestMapping("/api/accounts")
|
||||
public class AccountController {
|
||||
|
||||
private AccountService accountService;
|
||||
|
||||
@@ -35,7 +35,7 @@ public class AccountControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void shouldCreateAccount() throws Exception {
|
||||
mockMvc.perform(post("/accounts")
|
||||
mockMvc.perform(post("/api/accounts")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"customerId\" : \"00000000-00000000\", \"initialBalance\" : 500}")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
@@ -44,7 +44,7 @@ public class AccountControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void shouldRejectBadRequest() throws Exception {
|
||||
mockMvc.perform(post("/accounts")
|
||||
mockMvc.perform(post("/api/accounts")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"initialBalanceXXX\" : 500}")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
public class AccountChangeInfo {
|
||||
|
||||
private String changeId;
|
||||
private String transactionId;
|
||||
private String transactionType;
|
||||
private long amount;
|
||||
private long balanceDelta;
|
||||
|
||||
public AccountChangeInfo(String changeId, String transactionId, String transactionType, long amount, long balanceDelta) {
|
||||
this.changeId = changeId;
|
||||
this.transactionId = transactionId;
|
||||
this.transactionType = transactionType;
|
||||
this.amount = amount;
|
||||
this.balanceDelta = balanceDelta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return EqualsBuilder.reflectionEquals(this, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HashCodeBuilder.reflectionHashCode(this);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountChangeInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by cer on 11/21/14.
|
||||
@@ -18,13 +17,19 @@ public class AccountInfo {
|
||||
private String description;
|
||||
private long balance;
|
||||
private List<AccountChangeInfo> changes;
|
||||
private List<AccountTransactionInfo> transactions;
|
||||
private Map<String, AccountTransactionInfo> transactions;
|
||||
private Map<String, TransferState> transferStates;
|
||||
private String version;
|
||||
private Date date;
|
||||
|
||||
private AccountInfo() {
|
||||
}
|
||||
|
||||
public AccountInfo(String id, String customerId, String title, String description, long balance, List<AccountChangeInfo> changes, List<AccountTransactionInfo> transactions, String version) {
|
||||
public AccountInfo(String id, String customerId, String title, String description, long balance, List<AccountChangeInfo> changes, Map<String, AccountTransactionInfo> transactions, String version) {
|
||||
this(id, customerId, title, description, balance, changes, transactions, version, new Date());
|
||||
}
|
||||
|
||||
public AccountInfo(String id, String customerId, String title, String description, long balance, List<AccountChangeInfo> changes, Map<String, AccountTransactionInfo> transactions, String version, Date date) {
|
||||
|
||||
this.id = id;
|
||||
this.customerId = customerId;
|
||||
@@ -34,6 +39,7 @@ public class AccountInfo {
|
||||
this.changes = changes;
|
||||
this.transactions = transactions;
|
||||
this.version = version;
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
@@ -57,14 +63,26 @@ public class AccountInfo {
|
||||
}
|
||||
|
||||
public List<AccountChangeInfo> getChanges() {
|
||||
return changes;
|
||||
return changes == null ? Collections.EMPTY_LIST : changes;
|
||||
}
|
||||
|
||||
public List<AccountTransactionInfo> getTransactions() {
|
||||
return transactions;
|
||||
return transactions == null ? Collections.EMPTY_LIST : new ArrayList<>(transactions.values());
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public Map<String, TransferState> getTransferStates() {
|
||||
return transferStates;
|
||||
}
|
||||
|
||||
public void setTransferStates(Map<String, TransferState> transferStates) {
|
||||
this.transferStates = transferStates;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts;
|
||||
|
||||
import com.mongodb.WriteResult;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountChangeInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import static net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts.MoneyUtil.toIntegerRepr;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.where;
|
||||
@@ -28,29 +31,33 @@ public class AccountInfoUpdateService {
|
||||
|
||||
public void create(String accountId, String customerId, String title, BigDecimal initialBalance, String description, String version) {
|
||||
try {
|
||||
accountInfoRepository.save(new AccountInfo(
|
||||
accountId,
|
||||
customerId,
|
||||
title,
|
||||
description,
|
||||
toIntegerRepr(initialBalance),
|
||||
Collections.<AccountChangeInfo>emptyList(),
|
||||
Collections.<AccountTransactionInfo>emptyList(),
|
||||
version));
|
||||
AccountChangeInfo ci = new AccountChangeInfo();
|
||||
ci.setAmount(toIntegerRepr(initialBalance));
|
||||
WriteResult x = mongoTemplate.upsert(new Query(where("id").is(accountId).and("version").exists(false)),
|
||||
new Update()
|
||||
.set("customerId", customerId)
|
||||
.set("title", title)
|
||||
.set("description", description)
|
||||
.set("balance", toIntegerRepr(initialBalance))
|
||||
.push("changes", ci)
|
||||
.set("date", new Date())
|
||||
.set("version", version),
|
||||
AccountInfo.class);
|
||||
logger.info("Saved in mongo");
|
||||
|
||||
} catch (DuplicateKeyException t) {
|
||||
logger.warn("When saving ", t);
|
||||
} catch (Throwable t) {
|
||||
logger.error("Error during saving: ");
|
||||
logger.error("Error during saving: ", t);
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void addTransaction(String eventId, String fromAccountId, AccountTransactionInfo ti) {
|
||||
mongoTemplate.updateMulti(new Query(where("id").is(fromAccountId)), /* wrong .and("version").lt(eventId) */
|
||||
public void addTransaction(String accountId, AccountTransactionInfo ti) {
|
||||
mongoTemplate.upsert(new Query(where("id").is(accountId)),
|
||||
new Update().
|
||||
push("transactions", ti).
|
||||
set("version", eventId),
|
||||
set("transactions." + ti.getTransactionId(), ti),
|
||||
AccountInfo.class);
|
||||
}
|
||||
|
||||
@@ -64,5 +71,10 @@ public class AccountInfoUpdateService {
|
||||
AccountInfo.class);
|
||||
}
|
||||
|
||||
|
||||
public void updateTransactionStatus(String accountId, String transactionId, TransferState status) {
|
||||
mongoTemplate.upsert(new Query(where("id").is(accountId)),
|
||||
new Update().
|
||||
set("transferStates." + transactionId, status),
|
||||
AccountInfo.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts;
|
||||
|
||||
import io.eventuate.CompletableFutureUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class AccountQueryService {
|
||||
|
||||
@@ -13,15 +10,17 @@ public class AccountQueryService {
|
||||
this.accountInfoRepository = accountInfoRepository;
|
||||
}
|
||||
|
||||
public CompletableFuture<AccountInfo> findByAccountId(String accountId) {
|
||||
public AccountInfo findByAccountId(String accountId) {
|
||||
AccountInfo account = accountInfoRepository.findOne(accountId);
|
||||
if (account == null)
|
||||
return CompletableFutureUtil.failedFuture(new AccountNotFoundException(accountId));
|
||||
throw new AccountNotFoundException(accountId);
|
||||
else
|
||||
return CompletableFuture.completedFuture(account);
|
||||
if(account.getTransferStates()!=null)
|
||||
account.getTransactions().stream().forEach(ati -> ati.setStatus(account.getTransferStates().get(ati.getTransactionId())));
|
||||
return account;
|
||||
}
|
||||
|
||||
public CompletableFuture<List<AccountInfo>> findByCustomerId(String customerId) {
|
||||
return CompletableFuture.completedFuture(accountInfoRepository.findByCustomerId(customerId));
|
||||
public List<AccountInfo> findByCustomerId(String customerId) {
|
||||
return accountInfoRepository.findByCustomerId(customerId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.ac
|
||||
import io.eventuate.DispatchedEvent;
|
||||
import io.eventuate.EventHandlerMethod;
|
||||
import io.eventuate.EventSubscriber;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountChangedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountCreditedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountDebitedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountOpenedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.*;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.CreditRecordedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.DebitRecordedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.FailedDebitRecordedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.MoneyTransferCreatedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountChangeInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -57,20 +59,36 @@ public class AccountQueryWorkflow {
|
||||
de.getEvent().getDetails().getDate(),
|
||||
de.getEvent().getDetails().getDescription());
|
||||
|
||||
accountInfoUpdateService.addTransaction(eventId, fromAccountId, ti);
|
||||
accountInfoUpdateService.addTransaction(eventId, toAccountId, ti);
|
||||
accountInfoUpdateService.addTransaction(fromAccountId, ti);
|
||||
accountInfoUpdateService.addTransaction(toAccountId, ti);
|
||||
}
|
||||
|
||||
@EventHandlerMethod
|
||||
public void recordDebit(DispatchedEvent<AccountDebitedEvent> de) {
|
||||
String accountId = de.getEntityId();
|
||||
String transactionId = de.getEvent().getTransactionId();
|
||||
|
||||
accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.DEBITED);
|
||||
saveChange(de, -1);
|
||||
}
|
||||
|
||||
@EventHandlerMethod
|
||||
public void recordCredit(DispatchedEvent<AccountCreditedEvent> de) {
|
||||
String accountId = de.getEntityId();
|
||||
String transactionId = de.getEvent().getTransactionId();
|
||||
|
||||
accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.COMPLETED);
|
||||
saveChange(de, +1);
|
||||
}
|
||||
|
||||
@EventHandlerMethod
|
||||
public void recordFailed(DispatchedEvent<AccountDebitFailedDueToInsufficientFundsEvent> de) {
|
||||
String accountId = de.getEntityId();
|
||||
String transactionId = de.getEvent().getTransactionId();
|
||||
|
||||
accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.FAILED_DUE_TO_INSUFFICIENT_FUNDS);
|
||||
}
|
||||
|
||||
public <T extends AccountChangedEvent> void saveChange(DispatchedEvent<T> de, int delta) {
|
||||
String changeId = de.getEventId().asString();
|
||||
String transactionId = de.getEvent().getTransactionId();
|
||||
|
||||
@@ -4,7 +4,9 @@ import io.eventuate.javaclient.spring.jdbc.EventuateJdbcEventStoreConfiguration;
|
||||
import io.eventuate.javaclient.spring.jdbc.IdGenerator;
|
||||
import io.eventuate.javaclient.spring.jdbc.IdGeneratorImpl;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.accounts.AccountCreditedEvent;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountChangeInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -14,11 +16,9 @@ import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
@@ -54,14 +54,14 @@ public class AccountInfoUpdateServiceTest {
|
||||
|
||||
accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version);
|
||||
|
||||
AccountInfo accountInfo = accountQueryService.findByAccountId(accountId).get();
|
||||
AccountInfo accountInfo = accountQueryService.findByAccountId(accountId);
|
||||
|
||||
assertEquals(accountId, accountInfo.getId());
|
||||
assertEquals(customerId, accountInfo.getCustomerId());
|
||||
assertEquals(title, accountInfo.getTitle());
|
||||
assertEquals(description, accountInfo.getDescription());
|
||||
assertEquals(initialBalance.longValue() * 100, accountInfo.getBalance());
|
||||
assertTrue(accountInfo.getChanges().isEmpty());
|
||||
assertEquals(1, accountInfo.getChanges().size());
|
||||
assertTrue(accountInfo.getTransactions().isEmpty());
|
||||
assertEquals(version, accountInfo.getVersion());
|
||||
|
||||
@@ -76,22 +76,74 @@ public class AccountInfoUpdateServiceTest {
|
||||
accountInfoUpdateService.updateBalance(accountId, changeId, 500,
|
||||
change);
|
||||
|
||||
accountInfo = accountQueryService.findByAccountId(accountId).get();
|
||||
accountInfo = accountQueryService.findByAccountId(accountId);
|
||||
assertEquals(initialBalance.add(new BigDecimal(5)).longValue() * 100, accountInfo.getBalance());
|
||||
assertFalse(accountInfo.getChanges().isEmpty());
|
||||
|
||||
assertEquals(change, accountInfo.getChanges().get(0));
|
||||
assertEquals(change, accountInfo.getChanges().get(1));
|
||||
|
||||
String eventId = x.genId().asString();
|
||||
|
||||
AccountTransactionInfo ti = new AccountTransactionInfo(transactionId, accountId, accountId, 5, new Date(), "A transfer");
|
||||
|
||||
accountInfoUpdateService.addTransaction(eventId, accountId, ti);
|
||||
accountInfoUpdateService.addTransaction(accountId, ti);
|
||||
|
||||
accountInfo = accountQueryService.findByAccountId(accountId).get();
|
||||
accountInfo = accountQueryService.findByAccountId(accountId);
|
||||
assertFalse(accountInfo.getTransactions().isEmpty());
|
||||
|
||||
assertEquals(ti, accountInfo.getTransactions().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldHandleDuplicateSaveAccountInfo() throws ExecutionException, InterruptedException {
|
||||
IdGenerator x = new IdGeneratorImpl();
|
||||
String accountId = x.genId().asString();
|
||||
String customerId = x.genId().asString();
|
||||
String version = x.genId().asString();
|
||||
|
||||
String title = "Checking account";
|
||||
BigDecimal initialBalance = new BigDecimal("1345");
|
||||
String description = "Some account";
|
||||
|
||||
accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version);
|
||||
accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUpdateTransactionStatus() {
|
||||
IdGenerator x = new IdGeneratorImpl();
|
||||
String accountId = x.genId().asString();
|
||||
String customerId = x.genId().asString();
|
||||
String version = x.genId().asString();
|
||||
|
||||
String title = "Checking account";
|
||||
BigDecimal initialBalance = new BigDecimal("1345");
|
||||
String description = "Some account";
|
||||
|
||||
accountInfoUpdateService.create(accountId, customerId, title, initialBalance, description, version);
|
||||
|
||||
String transactionId = x.genId().asString();
|
||||
|
||||
AccountTransactionInfo transactionInfo = new AccountTransactionInfo();
|
||||
transactionInfo.setTransactionId(transactionId);
|
||||
transactionInfo.setStatus(TransferState.INITIAL);
|
||||
|
||||
accountInfoUpdateService.addTransaction(accountId, transactionInfo);
|
||||
|
||||
AccountInfo accountInfo = accountQueryService.findByAccountId(accountId);
|
||||
assertEquals(accountId, accountInfo.getId());
|
||||
assertFalse(accountInfo.getTransactions().isEmpty());
|
||||
assertEquals(1, accountInfo.getTransactions().size());
|
||||
|
||||
assertEquals(TransferState.INITIAL, accountInfo.getTransactions().get(0).getStatus());
|
||||
|
||||
accountInfoUpdateService.updateTransactionStatus(accountId, transactionId, TransferState.COMPLETED);
|
||||
|
||||
accountInfo = accountQueryService.findByAccountId(accountId);
|
||||
assertEquals(accountId, accountInfo.getId());
|
||||
assertFalse(accountInfo.getTransactions().isEmpty());
|
||||
assertEquals(1, accountInfo.getTransactions().size());
|
||||
|
||||
assertEquals(TransferState.COMPLETED, accountInfo.getTransactions().get(0).getStatus());
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ public class AccountsQuerySideServiceIntegrationTest {
|
||||
private int port;
|
||||
|
||||
private String baseUrl(String path) {
|
||||
return "http://localhost:" + port + "/" + path;
|
||||
return "http://localhost:" + port + "/api" + path;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -4,18 +4,19 @@ import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.acc
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts.AccountNotFoundException;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.accounts.AccountQueryService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.GetAccountResponse;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class AccountQueryController {
|
||||
|
||||
private AccountQueryService accountInfoQueryService;
|
||||
@@ -26,21 +27,35 @@ public class AccountQueryController {
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/accounts/{accountId}", method = RequestMethod.GET)
|
||||
public CompletableFuture<GetAccountResponse> get(@PathVariable String accountId) {
|
||||
return accountInfoQueryService.findByAccountId(accountId)
|
||||
.thenApply(accountInfo -> new GetAccountResponse(accountInfo.getId(), new BigDecimal(accountInfo.getBalance()), accountInfo.getTitle(), accountInfo.getDescription()));
|
||||
public ResponseEntity<GetAccountResponse> get(@PathVariable String accountId) {
|
||||
AccountInfo accountInfo = accountInfoQueryService.findByAccountId(accountId);
|
||||
return ResponseEntity.ok().body(new GetAccountResponse(accountInfo.getId(), new BigDecimal(accountInfo.getBalance()), accountInfo.getTitle(), accountInfo.getDescription()));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/accounts", method = RequestMethod.GET)
|
||||
public CompletableFuture<List<GetAccountResponse>> getAccountsForCustomer(@RequestParam("customerId") String customerId) {
|
||||
return accountInfoQueryService.findByCustomerId(customerId)
|
||||
.thenApply(accountInfoList -> accountInfoList.stream().map(accountInfo -> new GetAccountResponse(accountInfo.getId(), new BigDecimal(accountInfo.getBalance()), accountInfo.getTitle(), accountInfo.getDescription())).collect(Collectors.toList()));
|
||||
@RequestMapping(value = "/customers/{customerId}/accounts", method = RequestMethod.GET)
|
||||
public ResponseEntity<GetAccountsResponse> getAccountsForCustomer(@PathVariable("customerId") String customerId) {
|
||||
return ResponseEntity.ok().body(
|
||||
new GetAccountsResponse(
|
||||
accountInfoQueryService.findByCustomerId(customerId)
|
||||
.stream()
|
||||
.map(accountInfo -> new GetAccountResponse(
|
||||
accountInfo.getId(),
|
||||
new BigDecimal(accountInfo.getBalance()),
|
||||
accountInfo.getTitle(),
|
||||
accountInfo.getDescription()))
|
||||
.collect(Collectors.toList())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/accounts/{accountId}/history", method = RequestMethod.GET)
|
||||
public CompletableFuture<List<AccountTransactionInfo>> getTransactionsHistory(@PathVariable String accountId) {
|
||||
return accountInfoQueryService.findByAccountId(accountId)
|
||||
.thenApply(AccountInfo::getTransactions);
|
||||
public ResponseEntity<AccountHistoryResponse> getTransactionsHistory(@PathVariable String accountId) {
|
||||
AccountInfo accountInfo = accountInfoQueryService.findByAccountId(accountId);
|
||||
List<AccountHistoryEntry> historyEntries = new ArrayList<>();
|
||||
historyEntries.add(new AccountOpenInfo(accountInfo.getDate(), AccountHistoryEntry.EntryType.account, accountInfo.getChanges().get(0).getAmount()));
|
||||
accountInfo.getTransactions().forEach(historyEntries::add);
|
||||
|
||||
return ResponseEntity.ok().body(new AccountHistoryResponse(historyEntries));
|
||||
}
|
||||
|
||||
@ResponseStatus(value= HttpStatus.NOT_FOUND, reason="account not found")
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.apigateway.ApiGateway
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.apigateway.utils.ContentRequestTransformer;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.apigateway.utils.HeadersRequestTransformer;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.apigateway.utils.URLRequestTransformer;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
@@ -12,9 +13,12 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
|
||||
|
||||
@@ -26,6 +30,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.GET;
|
||||
import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||
@@ -52,13 +57,20 @@ public class GatewayController {
|
||||
.build();
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/**", method = {GET, POST})
|
||||
@RequestMapping(value = "/api/**", method = {GET, POST})
|
||||
@ResponseBody
|
||||
public ResponseEntity<String> proxyRequest(HttpServletRequest request) throws NoSuchRequestHandlingMethodException, IOException, URISyntaxException {
|
||||
HttpUriRequest proxiedRequest = createHttpUriRequest(request);
|
||||
logger.info("request: {}", proxiedRequest);
|
||||
HttpResponse proxiedResponse = httpClient.execute(proxiedRequest);
|
||||
logger.info("Response {}", proxiedResponse.getStatusLine().getStatusCode());
|
||||
return new ResponseEntity<>(read(proxiedResponse.getEntity().getContent()), HttpStatus.valueOf(proxiedResponse.getStatusLine().getStatusCode()));
|
||||
return new ResponseEntity<>(read(proxiedResponse.getEntity().getContent()), processHeaders(proxiedResponse.getAllHeaders()), HttpStatus.valueOf(proxiedResponse.getStatusLine().getStatusCode()));
|
||||
}
|
||||
|
||||
private HttpHeaders processHeaders(Header[] headers) {
|
||||
HttpHeaders result = new HttpHeaders();
|
||||
Stream.of(headers).filter(h -> h.getName().equalsIgnoreCase("Content-Type")).forEach( h -> result.set(h.getName(), h.getValue()));
|
||||
return result;
|
||||
}
|
||||
|
||||
private HttpUriRequest createHttpUriRequest(HttpServletRequest request) throws URISyntaxException, NoSuchRequestHandlingMethodException, IOException {
|
||||
|
||||
@@ -5,18 +5,21 @@ customers.queryside.service.host=localhost
|
||||
transfers.commandside.service.host=localhost
|
||||
|
||||
|
||||
api.gateway.endpoints[0].path=[/]*accounts.*
|
||||
api.gateway.endpoints[0].path=[/]*api/accounts.*
|
||||
api.gateway.endpoints[0].method=GET
|
||||
api.gateway.endpoints[0].location=http://${accounts.queryside.service.host}:8080
|
||||
api.gateway.endpoints[1].path=[/]*accounts.*
|
||||
api.gateway.endpoints[1].method=POST
|
||||
api.gateway.endpoints[1].location=http://${accounts.commandside.service.host}:8080
|
||||
api.gateway.endpoints[2].path=[/]*customers.*
|
||||
api.gateway.endpoints[2].method=GET
|
||||
api.gateway.endpoints[2].location=http://${customers.queryside.service.host}:8080
|
||||
api.gateway.endpoints[3].path=[/]*customers.*
|
||||
api.gateway.endpoints[3].method=POST
|
||||
api.gateway.endpoints[3].location=http://${customers.commandside.service.host}:8080
|
||||
api.gateway.endpoints[4].path=[/]*transfers.*
|
||||
api.gateway.endpoints[1].path=[/]*api/customers.*/accounts
|
||||
api.gateway.endpoints[1].method=GET
|
||||
api.gateway.endpoints[1].location=http://${accounts.queryside.service.host}:8080
|
||||
api.gateway.endpoints[2].path=[/]*api/accounts.*
|
||||
api.gateway.endpoints[2].method=POST
|
||||
api.gateway.endpoints[2].location=http://${accounts.commandside.service.host}:8080
|
||||
api.gateway.endpoints[3].path=[/]*api/customers.*
|
||||
api.gateway.endpoints[3].method=GET
|
||||
api.gateway.endpoints[3].location=http://${customers.queryside.service.host}:8080
|
||||
api.gateway.endpoints[4].path=[/]*api/customers.*
|
||||
api.gateway.endpoints[4].method=POST
|
||||
api.gateway.endpoints[4].location=http://${transfers.commandside.service.host}:8080
|
||||
api.gateway.endpoints[4].location=http://${customers.commandside.service.host}:8080
|
||||
api.gateway.endpoints[5].path=[/]*api/transfers.*
|
||||
api.gateway.endpoints[5].method=POST
|
||||
api.gateway.endpoints[5].location=http://${transfers.commandside.service.host}:8080
|
||||
@@ -6,7 +6,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.a
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.accounts.AccountService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransfer;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransferService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.TransferState;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.TransferDetails;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -6,7 +6,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.a
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.accounts.AccountService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransfer;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.MoneyTransferService;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions.TransferState;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.TransferDetails;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@@ -17,6 +17,7 @@ import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.await;
|
||||
import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.eventually;
|
||||
@@ -55,10 +56,10 @@ public class AccountQuerySideIntegrationTest {
|
||||
updatedTransaction -> Assert.assertEquals(TransferState.COMPLETED, updatedTransaction.getEntity().getState()));
|
||||
|
||||
eventually(
|
||||
() -> accountQueryService.findByAccountId(fromAccount.getEntityId()),
|
||||
() -> CompletableFuture.completedFuture(accountQueryService.findByAccountId(fromAccount.getEntityId())),
|
||||
accountInfo -> Assert.assertEquals(70 * 100, accountInfo.getBalance()));
|
||||
eventually(
|
||||
() -> accountQueryService.findByAccountId(toAccount.getEntityId()),
|
||||
() -> CompletableFuture.completedFuture(accountQueryService.findByAccountId(toAccount.getEntityId())),
|
||||
accountInfo -> Assert.assertEquals(380 * 100, accountInfo.getBalance()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import static org.springframework.web.bind.annotation.RequestMethod.POST;
|
||||
*/
|
||||
@RestController
|
||||
@Validated
|
||||
@RequestMapping("/api")
|
||||
public class AuthController {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -80,7 +80,7 @@ public class AuthConfiguration extends WebSecurityConfigurerAdapter {
|
||||
.authorizeRequests()
|
||||
.antMatchers("/index.html", "/", "/**.js", "/**.css").permitAll()
|
||||
.antMatchers("/swagger-ui.html", "/v2/api-docs").permitAll()
|
||||
.antMatchers(HttpMethod.POST, "/customers", "/login").permitAll()
|
||||
.antMatchers(HttpMethod.POST, "/api/customers", "/api/login").permitAll()
|
||||
.anyRequest().authenticated().and()
|
||||
.addFilterAfter(new StatelessAuthenticationFilter(tokenAuthenticationService), BasicAuthenticationFilter.class);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class AccountChangeInfo {
|
||||
|
||||
private String changeId;
|
||||
private String transactionId;
|
||||
private String transactionType;
|
||||
private long amount;
|
||||
private long balanceDelta;
|
||||
|
||||
public AccountChangeInfo() {
|
||||
}
|
||||
|
||||
public AccountChangeInfo(String changeId, String transactionId, String transactionType, long amount, long balanceDelta) {
|
||||
this(new Date(), changeId, transactionId, transactionType, amount, balanceDelta);
|
||||
}
|
||||
|
||||
public AccountChangeInfo(Date date, String changeId, String transactionId, String transactionType, long amount, long balanceDelta) {
|
||||
this.changeId = changeId;
|
||||
this.transactionId = transactionId;
|
||||
this.transactionType = transactionType;
|
||||
this.amount = amount;
|
||||
this.balanceDelta = balanceDelta;
|
||||
}
|
||||
|
||||
public String getChangeId() {
|
||||
return changeId;
|
||||
}
|
||||
|
||||
public void setChangeId(String changeId) {
|
||||
this.changeId = changeId;
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public void setTransactionId(String transactionId) {
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public String getTransactionType() {
|
||||
return transactionType;
|
||||
}
|
||||
|
||||
public void setTransactionType(String transactionType) {
|
||||
this.transactionType = transactionType;
|
||||
}
|
||||
|
||||
public long getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(long amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public long getBalanceDelta() {
|
||||
return balanceDelta;
|
||||
}
|
||||
|
||||
public void setBalanceDelta(long balanceDelta) {
|
||||
this.balanceDelta = balanceDelta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return EqualsBuilder.reflectionEquals(this, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return HashCodeBuilder.reflectionHashCode(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,
|
||||
include = JsonTypeInfo.As.PROPERTY,
|
||||
property = "entryType")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = AccountTransactionInfo.class, name = "transaction"),
|
||||
@JsonSubTypes.Type(value = AccountOpenInfo.class, name = "account")
|
||||
})
|
||||
public class AccountHistoryEntry {
|
||||
|
||||
protected Date date;
|
||||
protected EntryType entryType;
|
||||
|
||||
public AccountHistoryEntry() {
|
||||
}
|
||||
|
||||
public AccountHistoryEntry(Date date, EntryType entryType) {
|
||||
this.date = date;
|
||||
this.entryType = entryType;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public EntryType getEntryType() {
|
||||
return entryType;
|
||||
}
|
||||
|
||||
public void setEntryType(EntryType entryType) {
|
||||
this.entryType = entryType;
|
||||
}
|
||||
|
||||
public enum EntryType {
|
||||
transaction, account
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
public class AccountHistoryResponse {
|
||||
private List<AccountHistoryEntry> transactionsHistory;
|
||||
|
||||
public AccountHistoryResponse() {
|
||||
}
|
||||
|
||||
public AccountHistoryResponse(List<AccountHistoryEntry> transactionsHistory) {
|
||||
|
||||
this.transactionsHistory = transactionsHistory;
|
||||
}
|
||||
|
||||
public List<AccountHistoryEntry> getTransactionsHistory() {
|
||||
return transactionsHistory;
|
||||
}
|
||||
|
||||
public void setTransactionsHistory(List<AccountHistoryEntry> transactionsHistory) {
|
||||
this.transactionsHistory = transactionsHistory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
public class AccountOpenInfo extends AccountHistoryEntry {
|
||||
|
||||
private long initialBalance;
|
||||
|
||||
public AccountOpenInfo() {
|
||||
}
|
||||
|
||||
public AccountOpenInfo(Date date, EntryType entryType, long initialBalance) {
|
||||
super(date, entryType);
|
||||
this.initialBalance=initialBalance;
|
||||
}
|
||||
|
||||
public long getInitialBalance() {
|
||||
return initialBalance;
|
||||
}
|
||||
|
||||
public void setInitialBalance(long initialBalance) {
|
||||
this.initialBalance = initialBalance;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
import org.apache.commons.lang.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class AccountTransactionInfo {
|
||||
public class AccountTransactionInfo extends AccountHistoryEntry{
|
||||
|
||||
private String transactionId;
|
||||
private String fromAccountId;
|
||||
private String toAccountId;
|
||||
private long amount;
|
||||
private Date date;
|
||||
private String description;
|
||||
private TransferState status = TransferState.INITIAL;
|
||||
|
||||
public AccountTransactionInfo() {
|
||||
}
|
||||
@@ -35,6 +36,7 @@ public class AccountTransactionInfo {
|
||||
this.amount = amount;
|
||||
this.date = date;
|
||||
this.description = description;
|
||||
this.entryType = EntryType.transaction;
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
@@ -69,14 +71,6 @@ public class AccountTransactionInfo {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
@@ -85,6 +79,14 @@ public class AccountTransactionInfo {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public TransferState getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(TransferState status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return EqualsBuilder.reflectionEquals(this, o);
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.accounts;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by popikyardo on 9/1/16.
|
||||
*/
|
||||
public class GetAccountsResponse {
|
||||
private List<GetAccountResponse> accounts;
|
||||
|
||||
public GetAccountsResponse() {
|
||||
}
|
||||
|
||||
public GetAccountsResponse(List<GetAccountResponse> accounts) {
|
||||
this.accounts = accounts;
|
||||
}
|
||||
|
||||
public List<GetAccountResponse> getAccounts() {
|
||||
return accounts;
|
||||
}
|
||||
|
||||
public void setAccounts(List<GetAccountResponse> accounts) {
|
||||
this.accounts = accounts;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.transactions;
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.common.transactions;
|
||||
|
||||
public enum TransferState {
|
||||
NEW, INITIAL, DEBITED, COMPLETED, FAILED_DUE_TO_INSUFFICIENT_FUNDS
|
||||
@@ -4,10 +4,12 @@ import io.eventuate.AggregateRepository;
|
||||
import io.eventuate.EventuateAggregateStore;
|
||||
import io.eventuate.javaclient.spring.EnableEventHandlers;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableEventHandlers
|
||||
@ComponentScan
|
||||
public class CustomerConfiguration {
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -6,7 +6,6 @@ import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.custo
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
@@ -15,7 +14,6 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert
|
||||
@Configuration
|
||||
@Import({CustomersCommandSideWebConfiguration.class, EventuateHttpStompClientConfiguration.class, CommonSwaggerConfiguration.class})
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan
|
||||
public class CustomersCommandSideServiceConfiguration {
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ public class CustomersCommandSideServiceIntegrationTest {
|
||||
private int port;
|
||||
|
||||
private String baseUrl(String path) {
|
||||
return "http://localhost:" + port + "/" + path;
|
||||
return "http://localhost:" + port + "/api" + path;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -15,7 +15,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
* Created by popikyardo on 03.02.16.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/customers")
|
||||
@RequestMapping("/api/customers")
|
||||
public class CustomerController {
|
||||
|
||||
private CustomerService customerService;
|
||||
|
||||
@@ -5,6 +5,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.Quer
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.ToAccountInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -13,36 +14,38 @@ import java.util.Collections;
|
||||
*/
|
||||
public class CustomerInfoUpdateService {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private QuerySideCustomerRepository accountInfoRepository;
|
||||
private QuerySideCustomerRepository querySideCustomerRepository;
|
||||
|
||||
public CustomerInfoUpdateService(QuerySideCustomerRepository accountInfoRepository) {
|
||||
this.accountInfoRepository = accountInfoRepository;
|
||||
}
|
||||
|
||||
public void create(String id, CustomerInfo customerInfo) {
|
||||
try {
|
||||
accountInfoRepository.save(new QuerySideCustomer(id,
|
||||
customerInfo.getName(),
|
||||
customerInfo.getEmail(),
|
||||
customerInfo.getSsn(),
|
||||
customerInfo.getPhoneNumber(),
|
||||
customerInfo.getAddress(),
|
||||
Collections.<String, ToAccountInfo>emptyMap()
|
||||
)
|
||||
);
|
||||
logger.info("Saved in mongo");
|
||||
} catch (Throwable t) {
|
||||
logger.error("Error during saving: ", t);
|
||||
throw new RuntimeException(t);
|
||||
public CustomerInfoUpdateService(QuerySideCustomerRepository querySideCustomerRepository) {
|
||||
this.querySideCustomerRepository = querySideCustomerRepository;
|
||||
}
|
||||
}
|
||||
|
||||
public void addToAccount(String id, ToAccountInfo accountInfo) {
|
||||
QuerySideCustomer customer = accountInfoRepository.findOne(id);
|
||||
customer.getToAccounts().put(accountInfo.getId(), accountInfo);
|
||||
accountInfoRepository.save(customer);
|
||||
}
|
||||
public void create(String id, CustomerInfo customerInfo) {
|
||||
try {
|
||||
querySideCustomerRepository.save(new QuerySideCustomer(id,
|
||||
customerInfo.getName(),
|
||||
customerInfo.getEmail(),
|
||||
customerInfo.getSsn(),
|
||||
customerInfo.getPhoneNumber(),
|
||||
customerInfo.getAddress(),
|
||||
Collections.<String, ToAccountInfo>emptyMap()
|
||||
)
|
||||
);
|
||||
logger.info("Saved in mongo");
|
||||
} catch (DuplicateKeyException t) {
|
||||
logger.warn("When saving ", t);
|
||||
} catch (Throwable t) {
|
||||
logger.error("Error during saving: ", t);
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
public void addToAccount(String id, ToAccountInfo accountInfo) {
|
||||
QuerySideCustomer customer = querySideCustomerRepository.findOne(id);
|
||||
customer.getToAccounts().put(accountInfo.getId(), accountInfo);
|
||||
querySideCustomerRepository.save(customer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.cu
|
||||
|
||||
import io.eventuate.javaclient.spring.EnableEventHandlers;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||
@@ -12,6 +13,7 @@ import org.springframework.data.mongodb.repository.config.EnableMongoRepositorie
|
||||
@Configuration
|
||||
@EnableMongoRepositories
|
||||
@EnableEventHandlers
|
||||
@ComponentScan
|
||||
public class QuerySideCustomerConfiguration {
|
||||
@Bean
|
||||
public CustomerQueryWorkflow customerQueryWorkflow(CustomerInfoUpdateService accountInfoUpdateService) {
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.web;
|
||||
|
||||
import io.eventuate.javaclient.spring.httpstomp.EventuateHttpStompClientConfiguration;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.queryside.customers.QuerySideCustomerConfiguration;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.commonswagger.CommonSwaggerConfiguration;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.web.customers.queryside.CustomersQuerySideWebConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
|
||||
@Configuration
|
||||
@Import({QuerySideCustomerConfiguration.class, EventuateHttpStompClientConfiguration.class, CommonSwaggerConfiguration.class})
|
||||
@Import({CustomersQuerySideWebConfiguration.class, EventuateHttpStompClientConfiguration.class, CommonSwaggerConfiguration.class})
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan
|
||||
public class CustomersQuerySideServiceConfiguration {
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.web;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.*;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse;
|
||||
import net.chrisrichardson.eventstorestore.javaexamples.testutil.CustomersTestUtils;
|
||||
import org.apache.tomcat.jni.Thread;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -13,7 +12,6 @@ import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import rx.Observable;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
@@ -29,7 +27,7 @@ public class CustomersQuerySideServiceIntegrationTest {
|
||||
private int port;
|
||||
|
||||
private String baseUrl(String path) {
|
||||
return "http://localhost:" + port + "/" + path;
|
||||
return "http://localhost:" + port + "/api" + path;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@@ -51,12 +49,6 @@ public class CustomersQuerySideServiceIntegrationTest {
|
||||
final CustomerResponse customerResponse = restTemplate.postForEntity(baseUrl("/customers"), customerInfo, CustomerResponse.class).getBody();
|
||||
final String customerId = customerResponse.getId();
|
||||
|
||||
try {
|
||||
java.lang.Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
customersTestUtils.assertCustomerResponse(customerId, customerInfo);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
* Created by Main on 05.02.2016.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class CustomerQueryController {
|
||||
|
||||
private CustomerQueryService customerQueryService;
|
||||
|
||||
@@ -3,7 +3,7 @@ apigateway:
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- ./api-gateway-service/build/libs:/app
|
||||
command: java -jar /app/api-gateway-service.jar --accounts.commandside.service.host=accountscommandside --transactions.commandside.service.host=transactionscommandside --accounts.queryside.service.host=accountsqueryside --customers.commandside.service.host=customerscommandside --customers.queryside.service.host=customersqueryside
|
||||
command: java -jar /app/api-gateway-service.jar --accounts.commandside.service.host=accountscommandside --transfers.commandside.service.host=transactionscommandside --accounts.queryside.service.host=accountsqueryside --customers.commandside.service.host=customerscommandside --customers.queryside.service.host=customersqueryside
|
||||
ports:
|
||||
- "8080:8080"
|
||||
links:
|
||||
|
||||
@@ -18,7 +18,7 @@ public class EndToEndTest extends AbstractRestAPITest {
|
||||
CustomersTestUtils customersTestUtils = new CustomersTestUtils(restTemplate, baseUrl("/customers/"));
|
||||
|
||||
public String baseUrl(String path) {
|
||||
return "http://" + getenv("SERVICE_HOST", "localhost") + ":" + 8080 + "/" + path;
|
||||
return "http://" + getenv("SERVICE_HOST", "localhost") + ":" + 8080 + "/api" + path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,7 +22,7 @@ dependencies {
|
||||
}
|
||||
|
||||
task copyWebStatic(type: Copy) {
|
||||
from "../../prebuilt-web-client"
|
||||
from "../../js-frontend/build"
|
||||
into "build/resources/main/static"
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ public class BankingAuthTest {
|
||||
}
|
||||
|
||||
private String baseUrl(String path) {
|
||||
return "http://localhost:" + port + "/" + path;
|
||||
return "http://localhost:" + port + "/api" + path;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -32,7 +32,7 @@ public class BankingWebIntegrationTest extends AbstractRestAPITest {
|
||||
|
||||
@Override
|
||||
public String baseUrl(String path) {
|
||||
return "http://localhost:" + port + "/" + path;
|
||||
return "http://localhost:" + port + "/api" + path;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package net.chrisrichardson.eventstorestore.javaexamples.testutil;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.AccountTransactionInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.CreateAccountRequest;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.CreateAccountResponse;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.GetAccountResponse;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.accounts.*;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.QuerySideCustomer;
|
||||
@@ -51,12 +48,6 @@ public abstract class AbstractRestAPITest {
|
||||
Assert.assertNotNull(fromAccountId);
|
||||
Assert.assertNotNull(toAccountId);
|
||||
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
assertAccountBalance(fromAccountId, initialFromAccountBalance);
|
||||
assertAccountBalance(toAccountId, initialToAccountBalance);
|
||||
|
||||
@@ -68,21 +59,21 @@ public abstract class AbstractRestAPITest {
|
||||
assertAccountBalance(toAccountId, finalToAccountBalance);
|
||||
|
||||
eventually(
|
||||
new Producer<AccountTransactionInfo[]>() {
|
||||
new Producer<AccountHistoryResponse>() {
|
||||
@Override
|
||||
public CompletableFuture<AccountTransactionInfo[]> produce() {
|
||||
public CompletableFuture<AccountHistoryResponse> produce() {
|
||||
return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/accounts/" + fromAccountId + "/history"),
|
||||
AccountTransactionInfo[].class));
|
||||
AccountHistoryResponse.class));
|
||||
}
|
||||
},
|
||||
new Verifier<AccountTransactionInfo[]>() {
|
||||
new Verifier<AccountHistoryResponse>() {
|
||||
@Override
|
||||
public void verify(AccountTransactionInfo[] transactionInfos) {
|
||||
Optional<AccountTransactionInfo> first = Arrays.asList(transactionInfos).stream().filter(ti -> ti.getTransactionId().equals(moneyTransfer.getMoneyTransferId())).findFirst();
|
||||
public void verify(AccountHistoryResponse accountHistoryResponse) {
|
||||
Optional<AccountHistoryEntry> first = accountHistoryResponse.getTransactionsHistory().stream().filter( ahe -> ahe.getEntryType() == AccountHistoryEntry.EntryType.transaction && ((AccountTransactionInfo)ahe).getTransactionId().equals(moneyTransfer.getMoneyTransferId())).findFirst();
|
||||
|
||||
assertTrue(first.isPresent());
|
||||
|
||||
AccountTransactionInfo ti = first.get();
|
||||
AccountTransactionInfo ti = (AccountTransactionInfo)first.get();
|
||||
|
||||
assertEquals(fromAccountId, ti.getFromAccountId());
|
||||
assertEquals(toAccountId, ti.getToAccountId());
|
||||
@@ -104,12 +95,6 @@ public abstract class AbstractRestAPITest {
|
||||
Assert.assertNotNull(customerId);
|
||||
assertEquals(customerInfo, customerResponse.getCustomerInfo());
|
||||
|
||||
try {
|
||||
Thread.sleep(10000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
getCustomersTestUtils().assertCustomerResponse(customerId, customerInfo);
|
||||
|
||||
final CreateAccountResponse account = getAuthenticatedRestTemplate().postForEntity(baseUrl("/accounts"),
|
||||
@@ -123,17 +108,17 @@ public abstract class AbstractRestAPITest {
|
||||
assertAccountBalance(accountId, initialFromAccountBalance);
|
||||
|
||||
eventually(
|
||||
new Producer<GetAccountResponse[]>() {
|
||||
new Producer<GetAccountsResponse>() {
|
||||
@Override
|
||||
public CompletableFuture<GetAccountResponse[]> produce() {
|
||||
return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/accounts?customerId=" + customerId),
|
||||
GetAccountResponse[].class));
|
||||
public CompletableFuture<GetAccountsResponse> produce() {
|
||||
return CompletableFuture.completedFuture(getAuthenticatedRestTemplate().getForEntity(baseUrl("/customers/"+customerId+"/accounts"),
|
||||
GetAccountsResponse.class));
|
||||
}
|
||||
},
|
||||
new Verifier<GetAccountResponse[]>() {
|
||||
new Verifier<GetAccountsResponse>() {
|
||||
@Override
|
||||
public void verify(GetAccountResponse[] accountResponses) {
|
||||
assertTrue(Arrays.asList(accountResponses).stream().filter(acc -> acc.getAccountId().equals(accountId)).findFirst().isPresent());
|
||||
public void verify(GetAccountsResponse accountResponses) {
|
||||
assertTrue(accountResponses.getAccounts().stream().filter(acc -> acc.getAccountId().equals(accountId)).findFirst().isPresent());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.chrisrichardson.eventstorestore.javaexamples.testutil;
|
||||
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.utils.BasicAuthUtils;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.utils;
|
||||
package net.chrisrichardson.eventstorestore.javaexamples.testutil;
|
||||
|
||||
import org.apache.tomcat.util.codec.binary.Base64;
|
||||
import org.springframework.http.*;
|
||||
@@ -6,7 +6,6 @@ import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.awaitSuccessfulRequest;
|
||||
import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.eventually;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package net.chrisrichardson.eventstorestore.javaexamples.testutil;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import rx.Observable;
|
||||
import rx.Subscriber;
|
||||
import rx.functions.Action1;
|
||||
@@ -13,7 +11,6 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class TestUtil {
|
||||
|
||||
@@ -25,18 +22,6 @@ public class TestUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T awaitSuccessfulRequest(Supplier<ResponseEntity<T>> func, Func1<T, Boolean> predicate) {
|
||||
try {
|
||||
return Observable.interval(400, TimeUnit.MILLISECONDS)
|
||||
.take(50)
|
||||
.map(x -> func.get())
|
||||
.filter(re -> re.getStatusCode().equals(HttpStatus.OK) && re.getBody() != null && predicate.call(re.getBody()))
|
||||
.toBlocking().first().getBody();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class Tuple2<A, B> {
|
||||
private A first;
|
||||
@@ -52,7 +37,7 @@ public class TestUtil {
|
||||
|
||||
}
|
||||
|
||||
static class Success<T> implements Outcome<T> {
|
||||
static class Success<T> implements Outcome<T> {
|
||||
|
||||
T value;
|
||||
|
||||
@@ -69,51 +54,26 @@ public class TestUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> void eventually(final Producer<T> producer, final Verifier<T> verifier) {
|
||||
final int n = 150;
|
||||
Object possibleException = Observable.timer(0, 200, TimeUnit.MILLISECONDS).flatMap(new Func1<Long, Observable<Outcome<T>>>() {
|
||||
|
||||
@Override
|
||||
public Observable<Outcome<T>> call(Long aLong) {
|
||||
try {
|
||||
return fromCompletableFuture(producer.produce()).map(new Func1<T, Outcome<T>>() {
|
||||
@Override
|
||||
public Outcome<T> call(T t) {
|
||||
return new Success<T>(t);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Outcome<T> value = new Failure<T>(e);
|
||||
return Observable.just(value);
|
||||
}
|
||||
public static <T> void eventually(Producer<T> producer, Verifier<T> predicate) {
|
||||
Throwable laste = null;
|
||||
for (int i = 0; i < 30 ; i++) {
|
||||
try {
|
||||
T x = producer.produce().get(30, TimeUnit.SECONDS);
|
||||
predicate.verify(x);
|
||||
return;
|
||||
} catch (Throwable t) {
|
||||
laste = t;
|
||||
}
|
||||
}).map(new Func1<Outcome<T>, Throwable>() {
|
||||
@Override
|
||||
public Throwable call(Outcome<T> t) {
|
||||
try {
|
||||
if (t instanceof Success) {
|
||||
verifier.verify(((Success<T>) t).value);
|
||||
return null;
|
||||
} else
|
||||
return ((Failure<T>) t).t;
|
||||
} catch (Throwable e) {
|
||||
return e;
|
||||
}
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}).take(n).zipWith(Observable.range(0, n), new Func2<Throwable, Integer, Tuple2<Throwable, Integer>>() {
|
||||
@Override
|
||||
public Tuple2<Throwable, Integer> call(Throwable e, Integer idx) {
|
||||
return new Tuple2<Throwable, Integer>(e, idx);
|
||||
}
|
||||
}).skipWhile(new Func1<Tuple2<Throwable, Integer>, Boolean>() {
|
||||
@Override
|
||||
public Boolean call(Tuple2<Throwable, Integer> tuple2) {
|
||||
return tuple2.first != null && tuple2.second < n - 1;
|
||||
}
|
||||
}).first().toBlocking().getIterator().next().first;
|
||||
|
||||
if (possibleException != null)
|
||||
throw new RuntimeException((Throwable) possibleException);
|
||||
}
|
||||
if (laste != null)
|
||||
throw new RuntimeException("Last exception was", laste);
|
||||
else
|
||||
throw new RuntimeException("predicate never satisfied");
|
||||
}
|
||||
|
||||
private static <T> Observable<T> fromCompletableFuture(CompletableFuture<T> future) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.eventuate.Event;
|
||||
import io.eventuate.EventUtil;
|
||||
import io.eventuate.ReflectiveMutableCommandProcessingAggregate;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.transactions.*;
|
||||
import net.chrisrichardson.eventstore.javaexamples.banking.common.transactions.TransferState;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public class TransactionsCommandSideServiceIntegrationTest {
|
||||
private int port;
|
||||
|
||||
private String baseUrl(String path) {
|
||||
return "http://localhost:" + port + "/" + path;
|
||||
return "http://localhost:" + port + "/api" + path;
|
||||
}
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Date;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/transfers")
|
||||
@RequestMapping("/api/transfers")
|
||||
public class MoneyTransferController {
|
||||
|
||||
private final MoneyTransferService moneyTransferService;
|
||||
|
||||
@@ -36,7 +36,7 @@ public class MoneyTransferControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void shouldCreateAccount() throws Exception {
|
||||
mockMvc.perform(post("/transfers")
|
||||
mockMvc.perform(post("/api/transfers")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"fromAccountId\" : \"fromAccountId\", \"toAccountId\" : \"toAccountId\", \"amount\" : \"500\"}")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
@@ -45,7 +45,7 @@ public class MoneyTransferControllerIntegrationTest {
|
||||
|
||||
@Test
|
||||
public void shouldRejectBadRequest() throws Exception {
|
||||
mockMvc.perform(post("/transfers")
|
||||
mockMvc.perform(post("/api/transfers")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"fromAccountId\" : \"fromAccountIdXXXXXX\"}, {\"toAccountId\" : \"toAccountId\"}, {\"amount\" : \"500\"}")
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -185,11 +185,11 @@ webpackJsonp([0,3],{
|
||||
return store.dispatch((0, _configure.configure)([{
|
||||
default: {
|
||||
//apiUrl: '/',
|
||||
emailSignInPath: '/login',
|
||||
customersPath: '/customers',
|
||||
currentUserPath: '/user',
|
||||
accountsPath: '/accounts',
|
||||
transfersPath: '/transfers'
|
||||
emailSignInPath: '/api/login',
|
||||
customersPath: '/api/customers',
|
||||
currentUserPath: '/api/user',
|
||||
accountsPath: '/api/accounts',
|
||||
transfersPath: '/api/transfers'
|
||||
}
|
||||
}], {
|
||||
cookies: cookies,
|
||||
@@ -1403,6 +1403,9 @@ webpackJsonp([0,3],{
|
||||
var state = arguments.length <= 0 || arguments[0] === undefined ? _extends({}, initialState) : arguments[0];
|
||||
var action = arguments[1];
|
||||
|
||||
if (typeof action.length !== 'undefined') {
|
||||
debugger;
|
||||
}
|
||||
switch (action.type) {
|
||||
case _ACTION_TYPES2.default.ENTITIES.REQUESTED:
|
||||
{
|
||||
@@ -1829,7 +1832,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var _authenticate = __webpack_require__(316);
|
||||
|
||||
var _sessionStorage = __webpack_require__(317);
|
||||
var _sessionStorage = __webpack_require__(318);
|
||||
|
||||
var _clientSettings = __webpack_require__(327);
|
||||
|
||||
@@ -1839,7 +1842,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var _reduxRouter = __webpack_require__(246);
|
||||
|
||||
var _root = __webpack_require__(319);
|
||||
var _root = __webpack_require__(320);
|
||||
|
||||
var _root2 = _interopRequireDefault(_root);
|
||||
|
||||
@@ -1919,35 +1922,32 @@ webpackJsonp([0,3],{
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.authenticateStart = authenticateStart;
|
||||
exports.authenticateComplete = authenticateComplete;
|
||||
exports.authenticateError = authenticateError;
|
||||
exports.authenticateError = exports.authenticateComplete = exports.authenticateStart = undefined;
|
||||
exports.authenticate = authenticate;
|
||||
|
||||
var _ACTION_TYPES = __webpack_require__(295);
|
||||
|
||||
var _ACTION_TYPES2 = _interopRequireDefault(_ACTION_TYPES);
|
||||
|
||||
var _sessionStorage = __webpack_require__(317);
|
||||
var _actions = __webpack_require__(317);
|
||||
|
||||
var _api = __webpack_require__(320);
|
||||
var _sessionStorage = __webpack_require__(318);
|
||||
|
||||
var _entities = __webpack_require__(325);
|
||||
var U = _interopRequireWildcard(_sessionStorage);
|
||||
|
||||
var _api = __webpack_require__(321);
|
||||
|
||||
var _entities = __webpack_require__(326);
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
/**
|
||||
* Created by andrew on 26/02/16.
|
||||
*/
|
||||
function authenticateStart() {
|
||||
return { type: _ACTION_TYPES2.default.AUTH.AUTHENTICATE_START };
|
||||
}
|
||||
function authenticateComplete(user) {
|
||||
return { type: _ACTION_TYPES2.default.AUTH.AUTHENTICATE_COMPLETE, user: user };
|
||||
}
|
||||
function authenticateError(errors) {
|
||||
return { type: _ACTION_TYPES2.default.AUTH.AUTHENTICATE_ERROR, errors: errors };
|
||||
}
|
||||
var authenticateStart = exports.authenticateStart = (0, _actions.makeActionCreator)(_ACTION_TYPES2.default.AUTH.AUTHENTICATE_START); /**
|
||||
* Created by andrew on 26/02/16.
|
||||
*/
|
||||
var authenticateComplete = exports.authenticateComplete = (0, _actions.makeActionCreator)(_ACTION_TYPES2.default.AUTH.AUTHENTICATE_COMPLETE, 'user');
|
||||
var authenticateError = exports.authenticateError = (0, _actions.makeActionCreator)(_ACTION_TYPES2.default.AUTH.AUTHENTICATE_ERROR, 'errors');
|
||||
|
||||
function authenticate(forceReread) {
|
||||
return function (dispatch) {
|
||||
@@ -1956,25 +1956,24 @@ webpackJsonp([0,3],{
|
||||
|
||||
var savedUserPromise = new Promise(function (rs, rj) {
|
||||
|
||||
var currentHeaders = (0, _sessionStorage.retrieveHeaders)();
|
||||
var currentHeaders = U.retrieveHeaders();
|
||||
var accessToken = currentHeaders["access-token"];
|
||||
|
||||
if (!accessToken) {
|
||||
return rj({ reason: 'no token' });
|
||||
}
|
||||
|
||||
var savedUser = (0, _sessionStorage.retrieveUserData)();
|
||||
var savedUser = U.retrieveUserData();
|
||||
|
||||
if (savedUser && !forceReread) {
|
||||
return rs(savedUser);
|
||||
}
|
||||
|
||||
return (0, _api.apiGetCurrentUser)().then(function (userData) {
|
||||
(0, _sessionStorage.persistUserData)(userData);
|
||||
U.persistUserData(userData);
|
||||
dispatch((0, _entities.entityReceived)(userData.id, userData));
|
||||
rs(userData);
|
||||
}, function (err) {
|
||||
debugger;
|
||||
rj(err);
|
||||
});
|
||||
});
|
||||
@@ -2011,6 +2010,43 @@ webpackJsonp([0,3],{
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.makeActionCreator = makeActionCreator;
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
function makeActionCreator(type) {
|
||||
for (var _len = arguments.length, argNames = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
||||
argNames[_key - 1] = arguments[_key];
|
||||
}
|
||||
|
||||
return function () {
|
||||
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
||||
args[_key2] = arguments[_key2];
|
||||
}
|
||||
|
||||
var action = { type: type };
|
||||
argNames.forEach(function (arg, index) {
|
||||
action[argNames[index]] = args[index];
|
||||
});
|
||||
return action;
|
||||
};
|
||||
}
|
||||
|
||||
/* REACT HOT LOADER */ }).call(this); } finally { if (false) { (function () { var foundReactClasses = module.hot.data && module.hot.data.foundReactClasses || false; if (module.exports && module.makeHot) { var makeExportsHot = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/makeExportsHot.js"); if (makeExportsHot(module, require("react"))) { foundReactClasses = true; } var shouldAcceptModule = true && foundReactClasses; if (shouldAcceptModule) { module.hot.accept(function (err) { if (err) { console.error("Cannot not apply hot update to " + "actions.js" + ": " + err.message); } }); } } module.hot.dispose(function (data) { data.makeHot = module.makeHot; data.foundReactClasses = foundReactClasses; }); })(); } }
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ 318:
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
/* REACT HOT LOADER */ if (false) { (function () { var ReactHotAPI = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/node_modules/react-hot-api/modules/index.js"), RootInstanceProvider = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/RootInstanceProvider.js"), ReactMount = require("react/lib/ReactMount"), React = require("react"); module.makeHot = module.hot.data ? module.hot.data.makeHot : ReactHotAPI(function () { return RootInstanceProvider.getRootInstances(ReactMount); }, React); })(); } try { (function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.retrieveUserData = exports.persistUserData = undefined;
|
||||
exports.setCurrentSettings = setCurrentSettings;
|
||||
exports.getCurrentSettings = getCurrentSettings;
|
||||
exports.setCurrentEndpoint = setCurrentEndpoint;
|
||||
@@ -2033,13 +2069,11 @@ webpackJsonp([0,3],{
|
||||
exports.getTransfersUrl = getTransfersUrl;
|
||||
exports.getApiUrl = getApiUrl;
|
||||
exports.getTokenFormat = getTokenFormat;
|
||||
exports.persistUserData = persistUserData;
|
||||
exports.retrieveUserData = retrieveUserData;
|
||||
exports.retrieveHeaders = retrieveHeaders;
|
||||
exports.persistData = persistData;
|
||||
exports.retrieveData = retrieveData;
|
||||
|
||||
var _jsCookie = __webpack_require__(318);
|
||||
var _jsCookie = __webpack_require__(319);
|
||||
|
||||
var _jsCookie2 = _interopRequireDefault(_jsCookie);
|
||||
|
||||
@@ -2047,7 +2081,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var C = _interopRequireWildcard(_constants);
|
||||
|
||||
var _root = __webpack_require__(319);
|
||||
var _root = __webpack_require__(320);
|
||||
|
||||
var _root2 = _interopRequireDefault(_root);
|
||||
|
||||
@@ -2055,31 +2089,39 @@ webpackJsonp([0,3],{
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
//import "babel-polyfill";
|
||||
|
||||
|
||||
// stateful variables that persist throughout session
|
||||
_root2.default.authState = {
|
||||
var authState = {
|
||||
currentSettings: {},
|
||||
currentEndpoint: {},
|
||||
defaultEndpointKey: 'default'
|
||||
}; /**
|
||||
* Created by andrew on 26/02/16.
|
||||
*/
|
||||
|
||||
|
||||
var memoryStorage = {};
|
||||
|
||||
function clean(obj) {
|
||||
Object.keys(obj).forEach(function (k) {
|
||||
delete obj[k];
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
function setCurrentSettings(s) {
|
||||
_root2.default.authState.currentSettings = s;
|
||||
authState.currentSettings = s;
|
||||
}
|
||||
|
||||
function getCurrentSettings() {
|
||||
return _root2.default.authState.currentSettings;
|
||||
return authState.currentSettings;
|
||||
}
|
||||
|
||||
function setCurrentEndpoint(e) {
|
||||
_root2.default.authState.currentEndpoint = e;
|
||||
authState.currentEndpoint = e;
|
||||
}
|
||||
|
||||
function getCurrentEndpoint() {
|
||||
return _root2.default.authState.currentEndpoint;
|
||||
return authState.currentEndpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2108,18 +2150,15 @@ webpackJsonp([0,3],{
|
||||
|
||||
// reset stateful variables
|
||||
function resetConfig() {
|
||||
_root2.default.authState = _root2.default.authState || {};
|
||||
_root2.default.authState.currentSettings = {};
|
||||
_root2.default.authState.currentEndpoint = {};
|
||||
clean(authState);
|
||||
authState.currentSettings = {};
|
||||
authState.currentEndpoint = {};
|
||||
destroySession();
|
||||
}
|
||||
|
||||
function destroySession() {
|
||||
var sessionKeys = [C.SAVED_CREDS_KEY, C.SAVED_CONFIG_KEY, C.SAVED_USER_INFO];
|
||||
|
||||
for (var key in sessionKeys) {
|
||||
key = sessionKeys[key];
|
||||
|
||||
[C.SAVED_CREDS_KEY, C.SAVED_CONFIG_KEY, C.SAVED_USER_INFO].forEach(function (key) {
|
||||
// kill all local storage keys
|
||||
if (_root2.default.localStorage) {
|
||||
_root2.default.localStorage.removeItem(key);
|
||||
@@ -2127,9 +2166,11 @@ webpackJsonp([0,3],{
|
||||
|
||||
// remove from base path in case config is not specified
|
||||
_jsCookie2.default.remove(key, {
|
||||
path: _root2.default.authState.currentSettings.cookiePath || "/"
|
||||
path: authState.currentSettings.cookiePath || "/"
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
clean(memoryStorage);
|
||||
}
|
||||
|
||||
function unescapeQuotes(val) {
|
||||
@@ -2158,7 +2199,7 @@ webpackJsonp([0,3],{
|
||||
//}
|
||||
|
||||
function getEmailSignInUrl() {
|
||||
return "" + getSessionEndpoint().emailSignInPath;
|
||||
return '' + getSessionEndpoint().emailSignInPath;
|
||||
}
|
||||
|
||||
function getEmailSignUpUrl() {
|
||||
@@ -2166,19 +2207,19 @@ webpackJsonp([0,3],{
|
||||
}
|
||||
|
||||
function getCurrentUserUrl() {
|
||||
return "" + getSessionEndpoint().currentUserPath;
|
||||
return '' + getSessionEndpoint().currentUserPath;
|
||||
}
|
||||
|
||||
function getAccountsUrl() {
|
||||
return "" + getSessionEndpoint().accountsPath;
|
||||
return '' + getSessionEndpoint().accountsPath;
|
||||
}
|
||||
|
||||
function getCustomersUrl() {
|
||||
return "" + getSessionEndpoint().customersPath;
|
||||
return '' + getSessionEndpoint().customersPath;
|
||||
}
|
||||
|
||||
function getTransfersUrl() {
|
||||
return "" + getSessionEndpoint().transfersPath;
|
||||
return '' + getSessionEndpoint().transfersPath;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2188,20 +2229,20 @@ webpackJsonp([0,3],{
|
||||
*/
|
||||
function getApiUrl(key) {
|
||||
var configKey = getSessionEndpointKey(key);
|
||||
return _root2.default.authState.currentEndpoint[configKey].apiUrl;
|
||||
return rauthState.currentEndpoint[configKey].apiUrl;
|
||||
}
|
||||
|
||||
function getTokenFormat() {
|
||||
return _root2.default.authState.currentSettings.tokenFormat;
|
||||
return authState.currentSettings.tokenFormat;
|
||||
}
|
||||
|
||||
function persistUserData(user) {
|
||||
persistData(C.SAVED_USER_INFO, user);
|
||||
}
|
||||
var persistUserData = exports.persistUserData = function persistUserData(user) {
|
||||
memoryStorage[C.SAVED_USER_INFO] = user;
|
||||
};
|
||||
|
||||
function retrieveUserData() {
|
||||
return retrieveData(C.SAVED_USER_INFO);
|
||||
}
|
||||
var retrieveUserData = exports.retrieveUserData = function retrieveUserData() {
|
||||
return memoryStorage[C.SAVED_USER_INFO];
|
||||
};
|
||||
|
||||
function retrieveHeaders() {
|
||||
return retrieveData(C.SAVED_CREDS_KEY) || {};
|
||||
@@ -2210,15 +2251,15 @@ webpackJsonp([0,3],{
|
||||
function persistData(key, val) {
|
||||
val = _root2.default.JSON.stringify(val);
|
||||
|
||||
switch (_root2.default.authState.currentSettings.storage) {
|
||||
switch (authState.currentSettings.storage) {
|
||||
case "localStorage":
|
||||
_root2.default.localStorage.setItem(key, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
_jsCookie2.default.set(key, val, {
|
||||
expires: _root2.default.authState.currentSettings.cookieExpiry,
|
||||
path: _root2.default.authState.currentSettings.cookiePath
|
||||
expires: authState.currentSettings.cookieExpiry,
|
||||
path: authState.currentSettings.cookiePath
|
||||
});
|
||||
break;
|
||||
}
|
||||
@@ -2227,7 +2268,7 @@ webpackJsonp([0,3],{
|
||||
function retrieveData(key) {
|
||||
var val = null;
|
||||
|
||||
switch (_root2.default.authState.currentSettings.storage) {
|
||||
switch (authState.currentSettings.storage) {
|
||||
|
||||
case "localStorage":
|
||||
val = _root2.default.localStorage && _root2.default.localStorage.getItem(key);
|
||||
@@ -2253,7 +2294,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ 319:
|
||||
/***/ 320:
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
/* REACT HOT LOADER */ if (false) { (function () { var ReactHotAPI = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/node_modules/react-hot-api/modules/index.js"), RootInstanceProvider = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/RootInstanceProvider.js"), ReactMount = require("react/lib/ReactMount"), React = require("react"); module.makeHot = module.hot.data ? module.hot.data.makeHot : ReactHotAPI(function () { return RootInstanceProvider.getRootInstances(ReactMount); }, React); })(); } try { (function () {
|
||||
@@ -2274,7 +2315,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ 320:
|
||||
/***/ 321:
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
/* REACT HOT LOADER */ if (false) { (function () { var ReactHotAPI = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/node_modules/react-hot-api/modules/index.js"), RootInstanceProvider = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/RootInstanceProvider.js"), ReactMount = require("react/lib/ReactMount"), React = require("react"); module.makeHot = module.hot.data ? module.hot.data.makeHot : ReactHotAPI(function () { return RootInstanceProvider.getRootInstances(ReactMount); }, React); })(); } try { (function () {
|
||||
@@ -2297,17 +2338,17 @@ webpackJsonp([0,3],{
|
||||
exports.apiRetrieveUsers = apiRetrieveUsers;
|
||||
exports.apiRetrieveUser = apiRetrieveUser;
|
||||
|
||||
var _fetch = __webpack_require__(321);
|
||||
var _fetch = __webpack_require__(322);
|
||||
|
||||
var _fetch2 = _interopRequireDefault(_fetch);
|
||||
|
||||
var _sessionStorage = __webpack_require__(317);
|
||||
var _sessionStorage = __webpack_require__(318);
|
||||
|
||||
var _root = __webpack_require__(319);
|
||||
var _root = __webpack_require__(320);
|
||||
|
||||
var _root2 = _interopRequireDefault(_root);
|
||||
|
||||
var _handleFetchResponse = __webpack_require__(324);
|
||||
var _handleFetchResponse = __webpack_require__(325);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
@@ -2419,7 +2460,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
function apiRetrieveAccounts(customerId) {
|
||||
|
||||
return (0, _fetch2.default)((0, _sessionStorage.getAccountsUrl)() + '?' + makeQuery({ customerId: customerId }), {
|
||||
return (0, _fetch2.default)((0, _sessionStorage.getCustomersUrl)() + '/' + customerId + '/accounts', {
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
@@ -2487,7 +2528,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ 321:
|
||||
/***/ 322:
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
/* REACT HOT LOADER */ if (false) { (function () { var ReactHotAPI = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/node_modules/react-hot-api/modules/index.js"), RootInstanceProvider = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/RootInstanceProvider.js"), ReactMount = require("react/lib/ReactMount"), React = require("react"); module.makeHot = module.hot.data ? module.hot.data.makeHot : ReactHotAPI(function () { return RootInstanceProvider.getRootInstances(ReactMount); }, React); })(); } try { (function () {
|
||||
@@ -2519,7 +2560,7 @@ webpackJsonp([0,3],{
|
||||
});
|
||||
};
|
||||
|
||||
var _isomorphicFetch = __webpack_require__(322);
|
||||
var _isomorphicFetch = __webpack_require__(323);
|
||||
|
||||
var _isomorphicFetch2 = _interopRequireDefault(_isomorphicFetch);
|
||||
|
||||
@@ -2527,7 +2568,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var C = _interopRequireWildcard(_constants);
|
||||
|
||||
var _sessionStorage = __webpack_require__(317);
|
||||
var _sessionStorage = __webpack_require__(318);
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||||
|
||||
@@ -2591,7 +2632,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ 324:
|
||||
/***/ 325:
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
/* REACT HOT LOADER */ if (false) { (function () { var ReactHotAPI = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/node_modules/react-hot-api/modules/index.js"), RootInstanceProvider = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/RootInstanceProvider.js"), ReactMount = require("react/lib/ReactMount"), React = require("react"); module.makeHot = module.hot.data ? module.hot.data.makeHot : ReactHotAPI(function () { return RootInstanceProvider.getRootInstances(ReactMount); }, React); })(); } try { (function () {
|
||||
@@ -2649,7 +2690,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ 325:
|
||||
/***/ 326:
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
/* REACT HOT LOADER */ if (false) { (function () { var ReactHotAPI = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/node_modules/react-hot-api/modules/index.js"), RootInstanceProvider = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/RootInstanceProvider.js"), ReactMount = require("react/lib/ReactMount"), React = require("react"); module.makeHot = module.hot.data ? module.hot.data.makeHot : ReactHotAPI(function () { return RootInstanceProvider.getRootInstances(ReactMount); }, React); })(); } try { (function () {
|
||||
@@ -2678,15 +2719,15 @@ webpackJsonp([0,3],{
|
||||
|
||||
var _ACTION_TYPES2 = _interopRequireDefault(_ACTION_TYPES);
|
||||
|
||||
var _actions = __webpack_require__(326);
|
||||
var _actions = __webpack_require__(317);
|
||||
|
||||
var _api = __webpack_require__(320);
|
||||
var _api = __webpack_require__(321);
|
||||
|
||||
var api = _interopRequireWildcard(_api);
|
||||
|
||||
var _authenticate = __webpack_require__(316);
|
||||
|
||||
var _root = __webpack_require__(319);
|
||||
var _root = __webpack_require__(320);
|
||||
|
||||
var _root2 = _interopRequireDefault(_root);
|
||||
|
||||
@@ -2799,7 +2840,7 @@ webpackJsonp([0,3],{
|
||||
return function (dispatch) {
|
||||
//dispatch(accountsListRequested());
|
||||
return api.apiRetrieveAccounts(customerId).then(function (data) {
|
||||
dispatch(accountsListReceived(data));
|
||||
dispatch(accountsListReceived(data.accounts));
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -2933,7 +2974,7 @@ webpackJsonp([0,3],{
|
||||
return function (dispatch) {
|
||||
dispatch(getTransfersRequested(accountId));
|
||||
return api.apiRetrieveTransfers(accountId).then(function (data) {
|
||||
dispatch(getTransfersComplete(accountId, data));
|
||||
dispatch(getTransfersComplete(accountId, data.transactionsHistory));
|
||||
return data;
|
||||
}).catch(function (err) {
|
||||
dispatch(getTransfersError(accountId, err));
|
||||
@@ -2946,42 +2987,6 @@ webpackJsonp([0,3],{
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ 326:
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
/* REACT HOT LOADER */ if (false) { (function () { var ReactHotAPI = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/node_modules/react-hot-api/modules/index.js"), RootInstanceProvider = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/RootInstanceProvider.js"), ReactMount = require("react/lib/ReactMount"), React = require("react"); module.makeHot = module.hot.data ? module.hot.data.makeHot : ReactHotAPI(function () { return RootInstanceProvider.getRootInstances(ReactMount); }, React); })(); } try { (function () {
|
||||
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.makeActionCreator = makeActionCreator;
|
||||
/**
|
||||
* Created by andrew on 15/03/16.
|
||||
*/
|
||||
function makeActionCreator(type) {
|
||||
for (var _len = arguments.length, argNames = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
||||
argNames[_key - 1] = arguments[_key];
|
||||
}
|
||||
|
||||
return function () {
|
||||
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
||||
args[_key2] = arguments[_key2];
|
||||
}
|
||||
|
||||
var action = { type: type };
|
||||
argNames.forEach(function (arg, index) {
|
||||
action[argNames[index]] = args[index];
|
||||
});
|
||||
return action;
|
||||
};
|
||||
}
|
||||
|
||||
/* REACT HOT LOADER */ }).call(this); } finally { if (false) { (function () { var foundReactClasses = module.hot.data && module.hot.data.foundReactClasses || false; if (module.exports && module.makeHot) { var makeExportsHot = require("/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/react-hot-loader/makeExportsHot.js"); if (makeExportsHot(module, require("react"))) { foundReactClasses = true; } var shouldAcceptModule = true && foundReactClasses; if (shouldAcceptModule) { module.hot.accept(function (err) { if (err) { console.error("Cannot not apply hot update to " + "actions.js" + ": " + err.message); } }); } } module.hot.dispose(function (data) { data.makeHot = module.makeHot; data.foundReactClasses = foundReactClasses; }); })(); } }
|
||||
|
||||
/***/ },
|
||||
|
||||
/***/ 327:
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
@@ -3003,11 +3008,11 @@ webpackJsonp([0,3],{
|
||||
|
||||
var C = _interopRequireWildcard(_constants);
|
||||
|
||||
var _root = __webpack_require__(319);
|
||||
var _root = __webpack_require__(320);
|
||||
|
||||
var _root2 = _interopRequireDefault(_root);
|
||||
|
||||
var _fetch = __webpack_require__(321);
|
||||
var _fetch = __webpack_require__(322);
|
||||
|
||||
var _fetch2 = _interopRequireDefault(_fetch);
|
||||
|
||||
@@ -3017,7 +3022,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var _configure = __webpack_require__(314);
|
||||
|
||||
var _sessionStorage = __webpack_require__(317);
|
||||
var _sessionStorage = __webpack_require__(318);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
@@ -3836,15 +3841,15 @@ webpackJsonp([0,3],{
|
||||
exports.signOutComplete = signOutComplete;
|
||||
exports.signOut = signOut;
|
||||
|
||||
var _sessionStorage = __webpack_require__(317);
|
||||
var _sessionStorage = __webpack_require__(318);
|
||||
|
||||
var _entities = __webpack_require__(325);
|
||||
var _entities = __webpack_require__(326);
|
||||
|
||||
var _configure = __webpack_require__(314);
|
||||
|
||||
var _handleFetchResponse = __webpack_require__(324);
|
||||
var _handleFetchResponse = __webpack_require__(325);
|
||||
|
||||
var _fetch = __webpack_require__(321);
|
||||
var _fetch = __webpack_require__(322);
|
||||
|
||||
var _fetch2 = _interopRequireDefault(_fetch);
|
||||
|
||||
@@ -3852,7 +3857,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var _ACTION_TYPES2 = _interopRequireDefault(_ACTION_TYPES);
|
||||
|
||||
var _root = __webpack_require__(319);
|
||||
var _root = __webpack_require__(320);
|
||||
|
||||
var _root2 = _interopRequireDefault(_root);
|
||||
|
||||
@@ -3923,7 +3928,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var _IndexPanel2 = _interopRequireDefault(_IndexPanel);
|
||||
|
||||
var _entities = __webpack_require__(325);
|
||||
var _entities = __webpack_require__(326);
|
||||
|
||||
var A = _interopRequireWildcard(_entities);
|
||||
|
||||
@@ -4476,7 +4481,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var _reactSelect2 = _interopRequireDefault(_reactSelect);
|
||||
|
||||
var _entities = __webpack_require__(325);
|
||||
var _entities = __webpack_require__(326);
|
||||
|
||||
var A = _interopRequireWildcard(_entities);
|
||||
|
||||
@@ -5101,7 +5106,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var _readProp2 = _interopRequireDefault(_readProp);
|
||||
|
||||
var _entities = __webpack_require__(325);
|
||||
var _entities = __webpack_require__(326);
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||||
|
||||
@@ -5619,7 +5624,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var Modals = _interopRequireWildcard(_modals);
|
||||
|
||||
var _entities = __webpack_require__(325);
|
||||
var _entities = __webpack_require__(326);
|
||||
|
||||
var A = _interopRequireWildcard(_entities);
|
||||
|
||||
@@ -6158,32 +6163,83 @@ webpackJsonp([0,3],{
|
||||
}
|
||||
|
||||
var currentAccountId = forAccount;
|
||||
var transfersMarkup = data.length ? data.filter(function (_ref2) {
|
||||
var transfersMarkup = data.length ? data.sort(function (a, b) {
|
||||
return a.date - b.date;
|
||||
}).filter(function (_ref2) {
|
||||
var entryType = _ref2.entryType;
|
||||
var toAccountId = _ref2.toAccountId;
|
||||
var fromAccountId = _ref2.fromAccountId;
|
||||
return fromAccountId === currentAccountId || toAccountId === currentAccountId;
|
||||
}).sort(function (a, b) {
|
||||
return -(a.date - b.date);
|
||||
}).map(function (_ref3) {
|
||||
var amount = _ref3.amount;
|
||||
var fromAccountId = _ref3.fromAccountId;
|
||||
var toAccountId = _ref3.toAccountId;
|
||||
var transactionId = _ref3.transactionId;
|
||||
var _ref3$description = _ref3.description;
|
||||
var description = _ref3$description === undefined ? '' : _ref3$description;
|
||||
var _ref3$date = _ref3.date;
|
||||
var date = _ref3$date === undefined ? null : _ref3$date;
|
||||
var _ref3$status = _ref3.status;
|
||||
var status = _ref3$status === undefined ? '' : _ref3$status;
|
||||
return entryType !== 'transaction' || fromAccountId === currentAccountId || toAccountId === currentAccountId;
|
||||
}).reduce(function (_ref3, v) {
|
||||
var items = _ref3.items;
|
||||
var balance = _ref3.balance;
|
||||
|
||||
if (v.entryType == 'account') {
|
||||
balance = v.initialBalance;
|
||||
} else if (v.entryType == 'transaction') {
|
||||
var isOriginating = v.fromAccountId == currentAccountId;
|
||||
balance += (isOriginating ? -1 : 1) * v.amount;
|
||||
}
|
||||
v.balance = balance;
|
||||
items.push(v);
|
||||
return { items: items, balance: balance };
|
||||
}, {
|
||||
items: [],
|
||||
balance: 0
|
||||
}).items.sort(function (a, b) {
|
||||
return -(a.date - b.date);
|
||||
}).map(function (_ref4) {
|
||||
var entryType = _ref4.entryType;
|
||||
var amount = _ref4.amount;
|
||||
var fromAccountId = _ref4.fromAccountId;
|
||||
var toAccountId = _ref4.toAccountId;
|
||||
var transactionId = _ref4.transactionId;
|
||||
var _ref4$description = _ref4.description;
|
||||
var description = _ref4$description === undefined ? '—' : _ref4$description;
|
||||
var _ref4$date = _ref4.date;
|
||||
var date = _ref4$date === undefined ? null : _ref4$date;
|
||||
var _ref4$status = _ref4.status;
|
||||
var status = _ref4$status === undefined ? '—' : _ref4$status;
|
||||
var balance = _ref4.balance;
|
||||
var _ref4$initialBalance = _ref4.initialBalance;
|
||||
var initialBalance = _ref4$initialBalance === undefined ? null : _ref4$initialBalance;
|
||||
|
||||
|
||||
var transferTimestamp = new Date(date);
|
||||
var timeAgoTitle = transferTimestamp.toLocaleDateString() + ' ' + transferTimestamp.toLocaleTimeString();
|
||||
|
||||
if (entryType == 'account') {
|
||||
return _react2.default.createElement(
|
||||
"tr",
|
||||
null,
|
||||
_react2.default.createElement(
|
||||
"td",
|
||||
null,
|
||||
_react2.default.createElement(_reactTimeago2.default, { date: date, title: timeAgoTitle })
|
||||
),
|
||||
_react2.default.createElement(
|
||||
"td",
|
||||
{ colSpan: "3" },
|
||||
"Account created"
|
||||
),
|
||||
_react2.default.createElement(
|
||||
"td",
|
||||
null,
|
||||
_react2.default.createElement(_Money.Money, { amount: initialBalance })
|
||||
),
|
||||
_react2.default.createElement("td", null),
|
||||
_react2.default.createElement(
|
||||
"td",
|
||||
null,
|
||||
status || '—'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
var isOriginating = fromAccountId == currentAccountId;
|
||||
var directionMarkup = isOriginating ? 'Debit' : 'Credit';
|
||||
var counterAccountMarkup = isOriginating ? _react2.default.createElement(_AccountInfo2.default, { accountId: toAccountId }) : _react2.default.createElement(_AccountInfo2.default, { accountId: fromAccountId });
|
||||
|
||||
var transferTimestamp = new Date(date);
|
||||
var timeAgoTitle = transferTimestamp.toLocaleDateString() + ' ' + transferTimestamp.toLocaleTimeString();
|
||||
|
||||
return _react2.default.createElement(
|
||||
"tr",
|
||||
null,
|
||||
@@ -6207,6 +6263,11 @@ webpackJsonp([0,3],{
|
||||
null,
|
||||
_react2.default.createElement(_Money.Money, { amount: amount })
|
||||
),
|
||||
_react2.default.createElement(
|
||||
"td",
|
||||
null,
|
||||
_react2.default.createElement(_Money.Money, { amount: balance })
|
||||
),
|
||||
_react2.default.createElement(
|
||||
"td",
|
||||
null,
|
||||
@@ -6257,6 +6318,11 @@ webpackJsonp([0,3],{
|
||||
null,
|
||||
"Amount"
|
||||
),
|
||||
_react2.default.createElement(
|
||||
"th",
|
||||
null,
|
||||
"Balance"
|
||||
),
|
||||
_react2.default.createElement(
|
||||
"th",
|
||||
null,
|
||||
@@ -6309,7 +6375,7 @@ webpackJsonp([0,3],{
|
||||
|
||||
var _reactLoader2 = _interopRequireDefault(_reactLoader);
|
||||
|
||||
var _entities = __webpack_require__(325);
|
||||
var _entities = __webpack_require__(326);
|
||||
|
||||
var A = _interopRequireWildcard(_entities);
|
||||
|
||||
@@ -6763,15 +6829,15 @@ webpackJsonp([0,3],{
|
||||
exports.emailSignInError = exports.emailSignInComplete = exports.emailSignInStart = exports.emailSignInFormUpdate = undefined;
|
||||
exports.emailSignIn = emailSignIn;
|
||||
|
||||
var _sessionStorage = __webpack_require__(317);
|
||||
var _sessionStorage = __webpack_require__(318);
|
||||
|
||||
var _entities = __webpack_require__(325);
|
||||
var _entities = __webpack_require__(326);
|
||||
|
||||
var _configure = __webpack_require__(314);
|
||||
|
||||
var _api = __webpack_require__(320);
|
||||
var _api = __webpack_require__(321);
|
||||
|
||||
var _actions = __webpack_require__(326);
|
||||
var _actions = __webpack_require__(317);
|
||||
|
||||
var _ACTION_TYPES = __webpack_require__(295);
|
||||
|
||||
@@ -7227,13 +7293,13 @@ webpackJsonp([0,3],{
|
||||
exports.emailSignUpError = emailSignUpError;
|
||||
exports.emailSignUp = emailSignUp;
|
||||
|
||||
var _sessionStorage = __webpack_require__(317);
|
||||
var _sessionStorage = __webpack_require__(318);
|
||||
|
||||
var _entities = __webpack_require__(325);
|
||||
var _entities = __webpack_require__(326);
|
||||
|
||||
var _configure = __webpack_require__(314);
|
||||
|
||||
var _api = __webpack_require__(320);
|
||||
var _api = __webpack_require__(321);
|
||||
|
||||
var _signIn = __webpack_require__(609);
|
||||
|
||||
@@ -7287,4 +7353,4 @@ webpackJsonp([0,3],{
|
||||
/***/ }
|
||||
|
||||
});
|
||||
//# sourceMappingURL=app.3a9a7c962cfa5ee06c64.js.map
|
||||
//# sourceMappingURL=app.d4bdff82ac1db214898b.js.map
|
||||
1
js-frontend/build/app.d4bdff82ac1db214898b.js.map
Normal file
1
js-frontend/build/app.d4bdff82ac1db214898b.js.map
Normal file
File diff suppressed because one or more lines are too long
@@ -13,7 +13,7 @@
|
||||
|
||||
<!-- Optional theme -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap-theme.min.css"><link href="/style.6d7a32b1405ea1bb2bdf.css" rel="stylesheet"></head>
|
||||
<body><div id="root"></div><script src="/manifest.3614fb531d249ed18cb9.js"></script><script src="/vendor.9bf2d755cba11113a020.js"></script><script src="/style.6d7a32b1405ea1bb2bdf.js"></script><script src="/app.3a9a7c962cfa5ee06c64.js"></script><script>
|
||||
<body><div id="root"></div><script src="/manifest.09cb8f5a05c9cfc35585.js"></script><script src="/vendor.f73c0104cb72cfb2809e.js"></script><script src="/style.6d7a32b1405ea1bb2bdf.js"></script><script src="/app.d4bdff82ac1db214898b.js"></script><script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
@@ -27,5 +27,5 @@
|
||||
|
||||
ga('send', 'pageview');
|
||||
|
||||
</script><!--{"files":{"publicPath":"/","chunks":{"manifest":{"size":0,"entry":"/manifest.3614fb531d249ed18cb9.js","hash":"3614fb531d249ed18cb9","css":[]},"vendor":{"size":1670874,"entry":"/vendor.9bf2d755cba11113a020.js","hash":"9bf2d755cba11113a020","css":[]},"style":{"size":122,"entry":"/style.6d7a32b1405ea1bb2bdf.js","hash":"6d7a32b1405ea1bb2bdf","css":["/style.6d7a32b1405ea1bb2bdf.css"]},"app":{"size":348671,"entry":"/app.3a9a7c962cfa5ee06c64.js","hash":"3a9a7c962cfa5ee06c64","css":[]}},"js":["/manifest.3614fb531d249ed18cb9.js","/vendor.9bf2d755cba11113a020.js","/style.6d7a32b1405ea1bb2bdf.js","/app.3a9a7c962cfa5ee06c64.js"],"css":["/style.6d7a32b1405ea1bb2bdf.css"]},"options":{"template":"/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/html-webpack-plugin/lib/loader.js!/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/public/index.ejs","filename":"index.html","hash":false,"inject":false,"compile":true,"favicon":false,"minify":false,"cache":true,"showErrors":true,"chunks":"all","excludeChunks":[],"title":"Money Transfer App","xhtml":false,"description":"ES Money Transfer App","appMountId":"root","googleAnalytics":{"trackingId":"UA-XXXX-XX","pageViewOnLoad":true},"mobile":true}}--></body>
|
||||
</script><!--{"files":{"publicPath":"/","chunks":{"manifest":{"size":0,"entry":"/manifest.09cb8f5a05c9cfc35585.js","hash":"09cb8f5a05c9cfc35585","css":[]},"vendor":{"size":1670874,"entry":"/vendor.f73c0104cb72cfb2809e.js","hash":"f73c0104cb72cfb2809e","css":[]},"style":{"size":122,"entry":"/style.6d7a32b1405ea1bb2bdf.js","hash":"6d7a32b1405ea1bb2bdf","css":["/style.6d7a32b1405ea1bb2bdf.css"]},"app":{"size":351315,"entry":"/app.d4bdff82ac1db214898b.js","hash":"d4bdff82ac1db214898b","css":[]}},"js":["/manifest.09cb8f5a05c9cfc35585.js","/vendor.f73c0104cb72cfb2809e.js","/style.6d7a32b1405ea1bb2bdf.js","/app.d4bdff82ac1db214898b.js"],"css":["/style.6d7a32b1405ea1bb2bdf.css"]},"options":{"template":"/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/node_modules/html-webpack-plugin/lib/loader.js!/Users/andrew/dev/clients/ES/code/event-sourcing-examples/js-frontend/public/index.ejs","filename":"index.html","hash":false,"inject":false,"compile":true,"favicon":false,"minify":false,"cache":true,"showErrors":true,"chunks":"all","excludeChunks":[],"title":"Money Transfer App","xhtml":false,"description":"ES Money Transfer App","appMountId":"root","googleAnalytics":{"trackingId":"UA-XXXX-XX","pageViewOnLoad":true},"mobile":true}}--></body>
|
||||
</html>
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
/******/ script.charset = 'utf-8';
|
||||
/******/ script.async = true;
|
||||
/******/
|
||||
/******/ script.src = __webpack_require__.p + "" + {"0":"3a9a7c962cfa5ee06c64","1":"6d7a32b1405ea1bb2bdf","2":"9bf2d755cba11113a020"}[chunkId] + ".js";
|
||||
/******/ script.src = __webpack_require__.p + "" + {"0":"d4bdff82ac1db214898b","1":"6d7a32b1405ea1bb2bdf","2":"f73c0104cb72cfb2809e"}[chunkId] + ".js";
|
||||
/******/ head.appendChild(script);
|
||||
/******/ }
|
||||
/******/ };
|
||||
@@ -92,4 +92,4 @@
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([]);
|
||||
//# sourceMappingURL=manifest.3614fb531d249ed18cb9.js.map
|
||||
//# sourceMappingURL=manifest.09cb8f5a05c9cfc35585.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"sources":["webpack:///webpack/bootstrap c67ebd10dee52fe43758?"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,uDAA+C,iFAAiF;AAChI;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA","file":"manifest.3614fb531d249ed18cb9.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, callbacks = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId])\n \t\t\t\tcallbacks.push.apply(callbacks, installedChunks[chunkId]);\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);\n \t\twhile(callbacks.length)\n \t\t\tcallbacks.shift().call(null, __webpack_require__);\n \t\tif(moreModules[0]) {\n \t\t\tinstalledModules[0] = 0;\n \t\t\treturn __webpack_require__(0);\n \t\t}\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// \"0\" means \"already loaded\"\n \t// Array means \"loading\", array contains callbacks\n \tvar installedChunks = {\n \t\t3:0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId, callback) {\n \t\t// \"0\" is the signal for \"already loaded\"\n \t\tif(installedChunks[chunkId] === 0)\n \t\t\treturn callback.call(null, __webpack_require__);\n\n \t\t// an array means \"currently loading\".\n \t\tif(installedChunks[chunkId] !== undefined) {\n \t\t\tinstalledChunks[chunkId].push(callback);\n \t\t} else {\n \t\t\t// start chunk loading\n \t\t\tinstalledChunks[chunkId] = [callback];\n \t\t\tvar head = document.getElementsByTagName('head')[0];\n \t\t\tvar script = document.createElement('script');\n \t\t\tscript.type = 'text/javascript';\n \t\t\tscript.charset = 'utf-8';\n \t\t\tscript.async = true;\n\n \t\t\tscript.src = __webpack_require__.p + \"\" + {\"0\":\"3a9a7c962cfa5ee06c64\",\"1\":\"6d7a32b1405ea1bb2bdf\",\"2\":\"9bf2d755cba11113a020\"}[chunkId] + \".js\";\n \t\t\thead.appendChild(script);\n \t\t}\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap c67ebd10dee52fe43758\n **/"],"sourceRoot":""}
|
||||
{"version":3,"sources":["webpack:///webpack/bootstrap 8ac05bd1ead33e72514a?"],"names":[],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA,gBAAQ,oBAAoB;AAC5B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAI;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,uDAA+C,iFAAiF;AAChI;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA","file":"manifest.09cb8f5a05c9cfc35585.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules) {\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, callbacks = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(installedChunks[chunkId])\n \t\t\t\tcallbacks.push.apply(callbacks, installedChunks[chunkId]);\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules);\n \t\twhile(callbacks.length)\n \t\t\tcallbacks.shift().call(null, __webpack_require__);\n \t\tif(moreModules[0]) {\n \t\t\tinstalledModules[0] = 0;\n \t\t\treturn __webpack_require__(0);\n \t\t}\n \t};\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// \"0\" means \"already loaded\"\n \t// Array means \"loading\", array contains callbacks\n \tvar installedChunks = {\n \t\t3:0\n \t};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId, callback) {\n \t\t// \"0\" is the signal for \"already loaded\"\n \t\tif(installedChunks[chunkId] === 0)\n \t\t\treturn callback.call(null, __webpack_require__);\n\n \t\t// an array means \"currently loading\".\n \t\tif(installedChunks[chunkId] !== undefined) {\n \t\t\tinstalledChunks[chunkId].push(callback);\n \t\t} else {\n \t\t\t// start chunk loading\n \t\t\tinstalledChunks[chunkId] = [callback];\n \t\t\tvar head = document.getElementsByTagName('head')[0];\n \t\t\tvar script = document.createElement('script');\n \t\t\tscript.type = 'text/javascript';\n \t\t\tscript.charset = 'utf-8';\n \t\t\tscript.async = true;\n\n \t\t\tscript.src = __webpack_require__.p + \"\" + {\"0\":\"d4bdff82ac1db214898b\",\"1\":\"6d7a32b1405ea1bb2bdf\",\"2\":\"f73c0104cb72cfb2809e\"}[chunkId] + \".js\";\n \t\t\thead.appendChild(script);\n \t\t}\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/\";\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap 8ac05bd1ead33e72514a\n **/"],"sourceRoot":""}
|
||||
@@ -6,8 +6,8 @@ webpackJsonp([2,3],[
|
||||
__webpack_require__(262);
|
||||
__webpack_require__(621);
|
||||
__webpack_require__(180);
|
||||
__webpack_require__(322);
|
||||
__webpack_require__(318);
|
||||
__webpack_require__(323);
|
||||
__webpack_require__(319);
|
||||
__webpack_require__(622);
|
||||
__webpack_require__(330);
|
||||
__webpack_require__(2);
|
||||
@@ -30146,7 +30146,8 @@ webpackJsonp([2,3],[
|
||||
/* 315 */,
|
||||
/* 316 */,
|
||||
/* 317 */,
|
||||
/* 318 */
|
||||
/* 318 */,
|
||||
/* 319 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
||||
@@ -30297,22 +30298,22 @@ webpackJsonp([2,3],[
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 319 */,
|
||||
/* 320 */,
|
||||
/* 321 */,
|
||||
/* 322 */
|
||||
/* 322 */,
|
||||
/* 323 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
// the whatwg-fetch polyfill installs the fetch() function
|
||||
// on the global object (window or self)
|
||||
//
|
||||
// Return that as the export for use in Webpack, Browserify etc.
|
||||
__webpack_require__(323);
|
||||
__webpack_require__(324);
|
||||
module.exports = self.fetch.bind(self);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 323 */
|
||||
/* 324 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
(function(self) {
|
||||
@@ -30707,7 +30708,6 @@ webpackJsonp([2,3],[
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 324 */,
|
||||
/* 325 */,
|
||||
/* 326 */,
|
||||
/* 327 */,
|
||||
@@ -55902,4 +55902,4 @@ webpackJsonp([2,3],[
|
||||
|
||||
/***/ }
|
||||
]);
|
||||
//# sourceMappingURL=vendor.9bf2d755cba11113a020.js.map
|
||||
//# sourceMappingURL=vendor.f73c0104cb72cfb2809e.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -21,21 +21,24 @@ exports.devServer = function(options) {
|
||||
host: options.host, // Defaults to `localhost`
|
||||
port: options.port, // Defaults to 8080
|
||||
proxy: {
|
||||
'/user*' : {
|
||||
target: 'http://localhost:8080'
|
||||
},
|
||||
'/login' : {
|
||||
target: 'http://localhost:8080'
|
||||
},
|
||||
'/customers*' : {
|
||||
target: 'http://localhost:8080'
|
||||
},
|
||||
'/accounts*' : {
|
||||
target: 'http://localhost:8080'
|
||||
},
|
||||
'/transfers*' : {
|
||||
'/api*' : {
|
||||
target: 'http://localhost:8080'
|
||||
}
|
||||
// '/user*' : {
|
||||
// target: 'http://localhost:8080'
|
||||
// },
|
||||
// '/login' : {
|
||||
// target: 'http://localhost:8080'
|
||||
// },
|
||||
// '/customers*' : {
|
||||
// target: 'http://localhost:8080'
|
||||
// },
|
||||
// '/accounts*' : {
|
||||
// target: 'http://localhost:8080'
|
||||
// },
|
||||
// '/transfers*' : {
|
||||
// target: 'http://localhost:8080'
|
||||
// }
|
||||
}
|
||||
},
|
||||
watchOptions: {
|
||||
|
||||
@@ -15,7 +15,7 @@ import { reduxReactRouter as serverRouter } from "redux-router/server";
|
||||
|
||||
import mainReducer from './reducers';
|
||||
|
||||
import { configure as reduxAuthConfigure } from './actions/configure';
|
||||
import { configure as endpointsConfig } from './actions/configure';
|
||||
import { requireAuthentication } from './components/AuthComponent';
|
||||
import Container from "./components/partials/Container";
|
||||
import MyAccounts from "./views/MyAccounts";
|
||||
@@ -64,15 +64,15 @@ export function initialize({cookies, isServer, currentLocation, userAgent} = {})
|
||||
/**
|
||||
* The React Router 1.0 routes for both the server and the client.
|
||||
*/
|
||||
return store.dispatch(reduxAuthConfigure([
|
||||
return store.dispatch(endpointsConfig([
|
||||
{
|
||||
default: {
|
||||
//apiUrl: '/',
|
||||
emailSignInPath: '/login',
|
||||
customersPath: '/customers',
|
||||
currentUserPath: '/user',
|
||||
accountsPath: '/accounts',
|
||||
transfersPath: '/transfers'
|
||||
emailSignInPath: '/api/login',
|
||||
customersPath: '/api/customers',
|
||||
currentUserPath: '/api/user',
|
||||
accountsPath: '/api/accounts',
|
||||
transfersPath: '/api/transfers'
|
||||
}
|
||||
}
|
||||
], {
|
||||
|
||||
@@ -2,65 +2,41 @@
|
||||
* Created by andrew on 26/02/16.
|
||||
*/
|
||||
import T from '../constants/ACTION_TYPES';
|
||||
import { makeActionCreator } from '../utils/actions';
|
||||
import * as U from '../utils/sessionStorage';
|
||||
|
||||
import {
|
||||
getCurrentSettings,
|
||||
setCurrentSettings,
|
||||
getInitialEndpointKey,
|
||||
setDefaultEndpointKey,
|
||||
setCurrentEndpoint,
|
||||
setCurrentEndpointKey,
|
||||
retrieveData,
|
||||
persistData,
|
||||
destroySession,
|
||||
persistUserData,
|
||||
retrieveUserData,
|
||||
retrieveHeaders
|
||||
} from "../utils/sessionStorage";
|
||||
|
||||
import {
|
||||
apiGetCurrentUser
|
||||
} from '../utils/api';
|
||||
|
||||
import {entityReceived } from './entities';
|
||||
|
||||
export function authenticateStart() {
|
||||
return { type: T.AUTH.AUTHENTICATE_START };
|
||||
}
|
||||
export function authenticateComplete(user) {
|
||||
return { type: T.AUTH.AUTHENTICATE_COMPLETE, user };
|
||||
}
|
||||
export function authenticateError(errors) {
|
||||
return { type: T.AUTH.AUTHENTICATE_ERROR, errors };
|
||||
}
|
||||
import { apiGetCurrentUser } from '../utils/api';
|
||||
import { entityReceived } from './entities';
|
||||
|
||||
export const authenticateStart = makeActionCreator(T.AUTH.AUTHENTICATE_START);
|
||||
export const authenticateComplete = makeActionCreator(T.AUTH.AUTHENTICATE_COMPLETE, 'user');
|
||||
export const authenticateError = makeActionCreator(T.AUTH.AUTHENTICATE_ERROR, 'errors');
|
||||
|
||||
export function authenticate(forceReread) {
|
||||
return dispatch => {
|
||||
return (dispatch) => {
|
||||
|
||||
dispatch(authenticateStart());
|
||||
|
||||
const savedUserPromise = new Promise((rs, rj) => {
|
||||
|
||||
const currentHeaders = retrieveHeaders();
|
||||
const currentHeaders = U.retrieveHeaders();
|
||||
const accessToken = currentHeaders["access-token"];
|
||||
|
||||
if (!accessToken) {
|
||||
return rj({ reason: 'no token'});
|
||||
}
|
||||
|
||||
const savedUser = retrieveUserData();
|
||||
const savedUser = U.retrieveUserData();
|
||||
|
||||
if (savedUser && !forceReread) {
|
||||
return rs(savedUser);
|
||||
}
|
||||
|
||||
return apiGetCurrentUser().then((userData) => {
|
||||
persistUserData(userData);
|
||||
U.persistUserData(userData);
|
||||
dispatch(entityReceived(userData.id, userData));
|
||||
rs(userData);
|
||||
}, (err) => {
|
||||
debugger;
|
||||
rj(err);
|
||||
});
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ export function fetchOwnAccounts(customerId) {
|
||||
//dispatch(accountsListRequested());
|
||||
return api.apiRetrieveAccounts(customerId)
|
||||
.then(data => {
|
||||
dispatch(accountsListReceived(data));
|
||||
dispatch(accountsListReceived(data.accounts));
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -256,7 +256,7 @@ export const getTransfers = (accountId) => {
|
||||
dispatch(getTransfersRequested(accountId));
|
||||
return api.apiRetrieveTransfers(accountId)
|
||||
.then(data => {
|
||||
dispatch(getTransfersComplete(accountId, data));
|
||||
dispatch(getTransfersComplete(accountId, data.transactionsHistory));
|
||||
return data;
|
||||
})
|
||||
.catch(err => {
|
||||
|
||||
@@ -25,36 +25,67 @@ export class TransfersTable extends React.Component {
|
||||
const currentAccountId = forAccount;
|
||||
const transfersMarkup = data.length ?
|
||||
data
|
||||
.filter(({ toAccountId, fromAccountId}) => ((fromAccountId === currentAccountId) || (toAccountId === currentAccountId)))
|
||||
.sort((a, b) => ((a.date - b.date)))
|
||||
.filter(({ entryType, toAccountId, fromAccountId}) => ((entryType !=='transaction') || (fromAccountId === currentAccountId) || (toAccountId === currentAccountId)))
|
||||
.reduce(({
|
||||
items, balance
|
||||
}, v) => {
|
||||
if (v.entryType == 'account') {
|
||||
balance = v.initialBalance;
|
||||
} else if (v.entryType == 'transaction') {
|
||||
const isOriginating = v.fromAccountId == currentAccountId;
|
||||
balance += (isOriginating ? -1 : 1) * v.amount;
|
||||
}
|
||||
v.balance = balance;
|
||||
items.push(v);
|
||||
return { items, balance };
|
||||
}, {
|
||||
items: [],
|
||||
balance: 0
|
||||
}).items
|
||||
.sort((a, b) => (-(a.date - b.date)))
|
||||
.map(({
|
||||
amount,
|
||||
fromAccountId,
|
||||
toAccountId,
|
||||
transactionId,
|
||||
description = '',
|
||||
date = null,
|
||||
status = ''
|
||||
}) => {
|
||||
entryType,
|
||||
amount,
|
||||
fromAccountId,
|
||||
toAccountId,
|
||||
transactionId,
|
||||
description = '—',
|
||||
date = null,
|
||||
status = '—',
|
||||
balance,
|
||||
initialBalance = null
|
||||
}) => {
|
||||
|
||||
const isOriginating = fromAccountId == currentAccountId;
|
||||
const directionMarkup = isOriginating ? 'Debit' : 'Credit';
|
||||
const counterAccountMarkup = isOriginating ?
|
||||
<AccountInfo accountId={ toAccountId } /> :
|
||||
<AccountInfo accountId={ fromAccountId } />;
|
||||
const transferTimestamp = new Date(date);
|
||||
const timeAgoTitle = transferTimestamp.toLocaleDateString() + ' ' + transferTimestamp.toLocaleTimeString();
|
||||
|
||||
const transferTimestamp = new Date(date);
|
||||
const timeAgoTitle = transferTimestamp.toLocaleDateString() + ' ' + transferTimestamp.toLocaleTimeString();
|
||||
if (entryType == 'account') {
|
||||
return (<tr>
|
||||
<td><TimeAgo date={date} title={ timeAgoTitle } /></td>
|
||||
<td colSpan="3">Account created</td>
|
||||
<td><Money amount={ initialBalance } /></td>
|
||||
<td></td>
|
||||
<td>{ status || '—' }</td>
|
||||
</tr>);
|
||||
}
|
||||
|
||||
return (<tr>
|
||||
<td><TimeAgo date={date} title={ timeAgoTitle } /></td>
|
||||
<td>{ directionMarkup }</td>
|
||||
<td>{ counterAccountMarkup }</td>
|
||||
<td><Money amount={ amount } /></td>
|
||||
<td>{ description || '—' }</td>
|
||||
<td>{ status || '—' }</td>
|
||||
</tr>);
|
||||
}) : (<tr>
|
||||
const isOriginating = fromAccountId == currentAccountId;
|
||||
const directionMarkup = isOriginating ? 'Debit' : 'Credit';
|
||||
const counterAccountMarkup = isOriginating ?
|
||||
<AccountInfo accountId={ toAccountId } /> :
|
||||
<AccountInfo accountId={ fromAccountId } />;
|
||||
|
||||
return (<tr>
|
||||
<td><TimeAgo date={date} title={ timeAgoTitle } /></td>
|
||||
<td>{ directionMarkup }</td>
|
||||
<td>{ counterAccountMarkup }</td>
|
||||
<td><Money amount={ amount } /></td>
|
||||
<td><Money amount={ balance } /></td>
|
||||
<td>{ description || '—' }</td>
|
||||
<td>{ status || '—' }</td>
|
||||
</tr>);
|
||||
}) : (<tr>
|
||||
<td colSpan={6}>No transfers for this account just yet.</td>
|
||||
</tr>);
|
||||
|
||||
@@ -66,6 +97,7 @@ export class TransfersTable extends React.Component {
|
||||
<th>Type</th>
|
||||
<th>Other Account</th>
|
||||
<th>Amount</th>
|
||||
<th>Balance</th>
|
||||
<th>Description</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
|
||||
@@ -12,6 +12,9 @@ const nodeInitialState = {
|
||||
};
|
||||
|
||||
export const entities = (state = {...initialState}, action) => {
|
||||
if (typeof action.length !== 'undefined') {
|
||||
debugger;
|
||||
}
|
||||
switch(action.type) {
|
||||
case T.ENTITIES.REQUESTED: {
|
||||
const { id } = action;
|
||||
|
||||
@@ -108,7 +108,7 @@ export function apiMakeTransfer(fromAccountId, {
|
||||
|
||||
export function apiRetrieveAccounts(customerId) {
|
||||
|
||||
return fetch(`${getAccountsUrl()}?${makeQuery({ customerId })}`, {
|
||||
return fetch(`${getCustomersUrl()}/${customerId}/accounts`, {
|
||||
headers: {
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "application/json"
|
||||
|
||||
@@ -1,34 +1,40 @@
|
||||
/**
|
||||
* Created by andrew on 26/02/16.
|
||||
*/
|
||||
import Cookies from "js-cookie";
|
||||
import Cookies from 'js-cookie';
|
||||
import * as C from "./constants";
|
||||
|
||||
import root from './root';
|
||||
//import "babel-polyfill";
|
||||
|
||||
|
||||
// stateful variables that persist throughout session
|
||||
root.authState = {
|
||||
const authState = {
|
||||
currentSettings: {},
|
||||
currentEndpoint: {},
|
||||
defaultEndpointKey: 'default'
|
||||
};
|
||||
|
||||
const memoryStorage = {};
|
||||
|
||||
function clean(obj) {
|
||||
Object.keys(obj).forEach(k => {
|
||||
delete obj[k];
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
export function setCurrentSettings (s) {
|
||||
root.authState.currentSettings = s;
|
||||
authState.currentSettings = s;
|
||||
}
|
||||
|
||||
export function getCurrentSettings () {
|
||||
return root.authState.currentSettings;
|
||||
return authState.currentSettings;
|
||||
}
|
||||
|
||||
export function setCurrentEndpoint (e) {
|
||||
root.authState.currentEndpoint = e;
|
||||
authState.currentEndpoint = e;
|
||||
}
|
||||
|
||||
export function getCurrentEndpoint () {
|
||||
return root.authState.currentEndpoint;
|
||||
return authState.currentEndpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,23 +63,20 @@ export function getDefaultEndpointKey () {
|
||||
|
||||
// reset stateful variables
|
||||
export function resetConfig () {
|
||||
root.authState = root.authState || {};
|
||||
root.authState.currentSettings = {};
|
||||
root.authState.currentEndpoint = {};
|
||||
clean(authState);
|
||||
authState.currentSettings = {};
|
||||
authState.currentEndpoint = {};
|
||||
destroySession();
|
||||
}
|
||||
|
||||
|
||||
export function destroySession () {
|
||||
var sessionKeys = [
|
||||
|
||||
([
|
||||
C.SAVED_CREDS_KEY,
|
||||
C.SAVED_CONFIG_KEY,
|
||||
C.SAVED_USER_INFO
|
||||
];
|
||||
|
||||
for (var key in sessionKeys) {
|
||||
key = sessionKeys[key];
|
||||
|
||||
]).forEach(key => {
|
||||
// kill all local storage keys
|
||||
if (root.localStorage) {
|
||||
root.localStorage.removeItem(key);
|
||||
@@ -81,9 +84,11 @@ export function destroySession () {
|
||||
|
||||
// remove from base path in case config is not specified
|
||||
Cookies.remove(key, {
|
||||
path: root.authState.currentSettings.cookiePath || "/"
|
||||
path: authState.currentSettings.cookiePath || "/"
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
clean(memoryStorage);
|
||||
}
|
||||
|
||||
function unescapeQuotes (val) {
|
||||
@@ -146,19 +151,19 @@ export function getTransfersUrl () {
|
||||
*/
|
||||
export function getApiUrl(key) {
|
||||
let configKey = getSessionEndpointKey(key);
|
||||
return root.authState.currentEndpoint[configKey].apiUrl;
|
||||
return rauthState.currentEndpoint[configKey].apiUrl;
|
||||
}
|
||||
|
||||
export function getTokenFormat() {
|
||||
return root.authState.currentSettings.tokenFormat;
|
||||
return authState.currentSettings.tokenFormat;
|
||||
}
|
||||
|
||||
export function persistUserData(user) {
|
||||
persistData(C.SAVED_USER_INFO, user);
|
||||
}
|
||||
export const persistUserData = (user) => {
|
||||
memoryStorage[C.SAVED_USER_INFO] = user;
|
||||
};
|
||||
|
||||
export function retrieveUserData() {
|
||||
return retrieveData(C.SAVED_USER_INFO);
|
||||
export const retrieveUserData = () =>{
|
||||
return memoryStorage[C.SAVED_USER_INFO];
|
||||
}
|
||||
|
||||
export function retrieveHeaders() {
|
||||
@@ -168,24 +173,24 @@ export function retrieveHeaders() {
|
||||
export function persistData (key, val) {
|
||||
val = root.JSON.stringify(val);
|
||||
|
||||
switch (root.authState.currentSettings.storage) {
|
||||
switch (authState.currentSettings.storage) {
|
||||
case "localStorage":
|
||||
root.localStorage.setItem(key, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
Cookies.set(key, val, {
|
||||
expires: root.authState.currentSettings.cookieExpiry,
|
||||
path: root.authState.currentSettings.cookiePath
|
||||
expires: authState.currentSettings.cookieExpiry,
|
||||
path: authState.currentSettings.cookiePath
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
export function retrieveData (key) {
|
||||
var val = null;
|
||||
let val = null;
|
||||
|
||||
switch (root.authState.currentSettings.storage) {
|
||||
switch (authState.currentSettings.storage) {
|
||||
|
||||
case "localStorage":
|
||||
val = root.localStorage && root.localStorage.getItem(key);
|
||||
@@ -205,4 +210,4 @@ export function retrieveData (key) {
|
||||
// unescape quotes
|
||||
return unescapeQuotes(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user