added customer backend module

added auth module
added customerId to Account aggregate
This commit is contained in:
dartpopikyardo
2016-02-02 19:16:29 +03:00
parent 1ab8832fc8
commit 85f8826741
20 changed files with 527 additions and 7 deletions

View File

@@ -13,10 +13,11 @@ import java.util.List;
public class Account extends ReflectiveMutableCommandProcessingAggregate<Account, AccountCommand> {
private String customerId;
private BigDecimal balance;
public List<Event> process(OpenAccountCommand cmd) {
return EventUtil.events(new AccountOpenedEvent(cmd.getInitialBalance()));
return EventUtil.events(new AccountOpenedEvent(cmd.getCustomerId(), cmd.getInitialBalance()));
}
public List<Event> process(DebitAccountCommand cmd) {
@@ -31,6 +32,7 @@ public class Account extends ReflectiveMutableCommandProcessingAggregate<Account
}
public void apply(AccountOpenedEvent event) {
customerId = event.getCustomerId();
balance = event.getInitialBalance();
}
@@ -48,6 +50,10 @@ public class Account extends ReflectiveMutableCommandProcessingAggregate<Account
public BigDecimal getBalance() {
return balance;
}
public String getCustomerId() {
return customerId;
}
}

View File

@@ -14,8 +14,8 @@ public class AccountService {
this.accountRepository = accountRepository;
}
public rx.Observable<EntityWithIdAndVersion<Account>> openAccount(BigDecimal initialBalance) {
return accountRepository.save(new OpenAccountCommand(initialBalance));
public rx.Observable<EntityWithIdAndVersion<Account>> openAccount(String customerId, BigDecimal initialBalance) {
return accountRepository.save(new OpenAccountCommand(customerId, initialBalance));
}
}

View File

@@ -5,13 +5,18 @@ import java.math.BigDecimal;
public class OpenAccountCommand implements AccountCommand {
private String customerId;
private BigDecimal initialBalance;
public OpenAccountCommand(BigDecimal initialBalance) {
public OpenAccountCommand(String customerId, BigDecimal initialBalance) {
this.initialBalance = initialBalance;
}
public BigDecimal getInitialBalance() {
return initialBalance;
}
public String getCustomerId() {
return customerId;
}
}

View File

@@ -14,14 +14,16 @@ public class AccountTest {
@Test
public void testSomething() {
Account account = new Account();
String customerId = "00000000-00000000";
BigDecimal initialBalance = new BigDecimal(512);
List<Event> events = CommandProcessingAggregates.processToList(account, (AccountCommand)new OpenAccountCommand(initialBalance));
List<Event> events = CommandProcessingAggregates.processToList(account, (AccountCommand)new OpenAccountCommand(customerId, initialBalance));
Assert.assertEquals(1, events.size());
Assert.assertEquals(AccountOpenedEvent.class, events.get(0).getClass());
account.applyEvent(events.get(0));
Assert.assertEquals(customerId, account.getCustomerId());
Assert.assertEquals(initialBalance, account.getBalance());
}
}

View File

@@ -0,0 +1,11 @@
apply plugin: 'java'
dependencies {
compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
compile "org.springframework.security:spring-security-config:4.0.2.RELEASE"
compile "org.springframework.security:spring-security-web:4.0.2.RELEASE"
testCompile "junit:junit:4.11"
}

View File

@@ -0,0 +1,72 @@
package net.chrisrichardson.eventstore.javaexamples.banking.commonauth;
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.filter.StatelessAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.token.KeyBasedPersistenceTokenService;
import org.springframework.security.core.token.TokenService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import java.security.SecureRandom;
/**
* Created by popikyardo on 21.09.15.
*/
@Configuration
@ComponentScan
@EnableWebSecurity
@EnableConfigurationProperties({AuthProperties.class})
public class AuthConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private AuthProperties securityProperties;
@Autowired
private TokenAuthenticationService tokenAuthenticationService;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.formLogin().loginPage("/index.html").and()
.authorizeRequests()
.antMatchers("/health").permitAll()
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/v2/api-docs").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/styles/**").permitAll()
.antMatchers("/views/**").permitAll()
.antMatchers(HttpMethod.POST, "/authenticate").permitAll()
.anyRequest().authenticated().and()
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public TokenService tokenService() {
KeyBasedPersistenceTokenService res = new KeyBasedPersistenceTokenService();
res.setSecureRandom(new SecureRandom());
res.setServerSecret(securityProperties.getServerSecret());
res.setServerInteger(securityProperties.getServerInteger());
return res;
}
}

View File

@@ -0,0 +1,28 @@
package net.chrisrichardson.eventstore.javaexamples.banking.commonauth;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Created by popikyardo on 21.09.15.
*/
@ConfigurationProperties(locations = "classpath:auth.properties", ignoreUnknownFields = false, prefix = "auth")
public class AuthProperties {
private String serverSecret;
private Integer serverInteger;
public String getServerSecret() {
return serverSecret;
}
public void setServerSecret(String serverSecret) {
this.serverSecret = serverSecret;
}
public Integer getServerInteger() {
return serverInteger;
}
public void setServerInteger(Integer serverInteger) {
this.serverInteger = serverInteger;
}
}

View File

@@ -0,0 +1,43 @@
package net.chrisrichardson.eventstore.javaexamples.banking.commonauth;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model.User;
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model.UserAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.token.Token;
import org.springframework.security.core.token.TokenService;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* Created by popikyardo on 23.09.15.
*/
@Service
public class TokenAuthenticationService {
@Autowired
private TokenService tokenService;
private static final String AUTH_HEADER_NAME = "x-access-token";
private static final long DAY = 1000 * 60 * 60 * 24;
private ObjectMapper mapper = new ObjectMapper();
public Authentication getAuthentication(HttpServletRequest request) throws IOException {
final String tokenString = request.getHeader(AUTH_HEADER_NAME);
if (tokenString != null) {
Token token = tokenService.verifyToken(tokenString);
final User user = mapper.readValue(token.getExtendedInformation(), User.class);
if (user != null && (System.currentTimeMillis() - token.getKeyCreationTime()) < DAY) {
return new UserAuthentication(user);
}
}
return null;
}
}

View File

@@ -0,0 +1,32 @@
package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.filter;
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.TokenAuthenticationService;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* Created by popikyardo on 23.09.15.
*/
public class StatelessAuthenticationFilter extends GenericFilterBean {
private final TokenAuthenticationService tokenAuthenticationService;
public StatelessAuthenticationFilter(TokenAuthenticationService taService) {
this.tokenAuthenticationService = taService;
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
SecurityContextHolder.getContext().setAuthentication(
tokenAuthenticationService.getAuthentication((HttpServletRequest) req));
chain.doFilter(req, res);
}
}

View File

@@ -0,0 +1,71 @@
package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* Created by popikyardo on 23.09.15.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class User implements UserDetails {
private String email;
public void setUsername(String username) {
this.email = username;
}
@Override
@JsonIgnore
public Collection<? extends GrantedAuthority> getAuthorities() {
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("USER");
Set<GrantedAuthority> res = new HashSet<GrantedAuthority>();
res.add(authority);
return res;
}
@Override
public String getPassword() {
return "";
}
@Override
public String getUsername() {
return this.email;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View File

@@ -0,0 +1,54 @@
package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
/**
* Created by popikyardo on 23.09.15.
*/
public class UserAuthentication implements Authentication {
private final User user;
private boolean authenticated = true;
public UserAuthentication(User user) {
this.user = user;
}
@Override
public String getName() {
return user.getUsername();
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getAuthorities();
}
@Override
public Object getCredentials() {
return user.getPassword();
}
@Override
public User getDetails() {
return user;
}
@Override
public Object getPrincipal() {
return user.getUsername();
}
@Override
public boolean isAuthenticated() {
return authenticated;
}
@Override
public void setAuthenticated(boolean authenticated) {
this.authenticated = authenticated;
}
}

View File

@@ -7,15 +7,21 @@ import java.math.BigDecimal;
public class AccountOpenedEvent implements Event {
private String customerId;
private BigDecimal initialBalance;
private AccountOpenedEvent() {
}
public AccountOpenedEvent(BigDecimal initialBalance) {
public AccountOpenedEvent(String customerId, BigDecimal initialBalance) {
this.customerId = customerId;
this.initialBalance = initialBalance;
}
public String getCustomerId() {
return customerId;
}
public BigDecimal getInitialBalance() {
return initialBalance;
}

View File

@@ -0,0 +1,64 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;
/**
* Created by popikyardo on 02.02.16.
*/
public class Address {
private String street1;
private String street2;
private String city;
private String state;
private int zipCode;
public Address() {
}
public Address(String street1, String street2, String city, String state, int zipCode) {
this.street1 = street1;
this.street2 = street2;
this.city = city;
this.state = state;
this.zipCode = zipCode;
}
public String getStreet1() {
return street1;
}
public void setStreet1(String street1) {
this.street1 = street1;
}
public String getStreet2() {
return street2;
}
public void setStreet2(String street2) {
this.street2 = street2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public int getZipCode() {
return zipCode;
}
public void setZipCode(int zipCode) {
this.zipCode = zipCode;
}
}

View File

@@ -0,0 +1,46 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;
import net.chrisrichardson.eventstore.Event;
/**
* Created by popikyardo on 02.02.16.
*/
public class CustomerCreatedEvent implements Event {
private String socialSecurityNum;
private String phoneNum;
private Address address;
public CustomerCreatedEvent() {
}
public CustomerCreatedEvent(String socialSecurityNum, String phoneNum, Address address) {
this.socialSecurityNum = socialSecurityNum;
this.phoneNum = phoneNum;
this.address = address;
}
public String getSocialSecurityNum() {
return socialSecurityNum;
}
public void setSocialSecurityNum(String socialSecurityNum) {
this.socialSecurityNum = socialSecurityNum;
}
public String getPhoneNum() {
return phoneNum;
}
public void setPhoneNum(String phoneNum) {
this.phoneNum = phoneNum;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}

View File

@@ -0,0 +1,2 @@
@net.chrisrichardson.eventstore.EventEntity(entity="net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.customers.Customer")
package net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers;

View File

@@ -0,0 +1,11 @@
apply plugin: 'java'
dependencies {
compile project(":common-backend")
compile "net.chrisrichardson.eventstore.client:eventstore-java-client_2.10:$eventStoreClientVersion"
testCompile project(":testutil")
testCompile "junit:junit:4.11"
testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
testCompile "net.chrisrichardson.eventstore.client:eventstore-jdbc_2.10:$eventStoreClientVersion"
}

View File

@@ -0,0 +1,31 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.customers;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.Address;
/**
* Created by popikyardo on 02.02.16.
*/
public class CreateCustomerCommand implements CustomerCommand {
private String socialSecurityNum;
private String phoneNum;
private Address address;
public CreateCustomerCommand(String socialSecurityNum, String phoneNum, Address address) {
this.socialSecurityNum = socialSecurityNum;
this.phoneNum = phoneNum;
this.address = address;
}
public String getSocialSecurityNum() {
return socialSecurityNum;
}
public String getPhoneNum() {
return phoneNum;
}
public Address getAddress() {
return address;
}
}

View File

@@ -0,0 +1,29 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.customers;
import net.chrisrichardson.eventstore.Event;
import net.chrisrichardson.eventstore.EventUtil;
import net.chrisrichardson.eventstore.ReflectiveMutableCommandProcessingAggregate;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.Address;
import net.chrisrichardson.eventstore.javaexamples.banking.backend.common.customers.CustomerCreatedEvent;
import java.util.List;
/**
* Created by popikyardo on 02.02.16.
*/
public class Customer extends ReflectiveMutableCommandProcessingAggregate<Customer, CustomerCommand> {
private String socialSecurityNum;
private String phoneNum;
private Address address;
public List<Event> process(CreateCustomerCommand cmd) {
return EventUtil.events(new CustomerCreatedEvent(cmd.getSocialSecurityNum(), cmd.getPhoneNum(), cmd.getAddress()));
}
public void apply(CustomerCreatedEvent event) {
socialSecurityNum = event.getSocialSecurityNum();
phoneNum = event.getPhoneNum();
address = event.getAddress();
}
}

View File

@@ -0,0 +1,6 @@
package net.chrisrichardson.eventstore.javaexamples.banking.backend.commandside.customers;
import net.chrisrichardson.eventstore.Command;
interface CustomerCommand extends Command {
}

View File

@@ -6,6 +6,7 @@ include 'common-backend'
include 'accounts-command-side-backend'
include 'transactions-command-side-backend'
include 'customer-command-side-backend'
include 'accounts-command-side-web'
include 'transactions-command-side-web'
@@ -24,5 +25,5 @@ include 'transactions-command-side-service'
include 'e2e-test'
rootProject.name = 'java-spring-event-sourcing-example'
include 'common-auth'