diff --git a/.idea/FullStack.MicroWebApplication-Server.iml b/.idea/FullStack.MicroWebApplication-Server.iml index 0ce23ba40..eb02fb50d 100644 --- a/.idea/FullStack.MicroWebApplication-Server.iml +++ b/.idea/FullStack.MicroWebApplication-Server.iml @@ -15,6 +15,7 @@ + @@ -35,6 +36,8 @@ + + diff --git a/src/main/java/runner/controllers/AccountController.java b/src/main/java/runner/controllers/AccountController.java index 77796ac5f..366b37cea 100644 --- a/src/main/java/runner/controllers/AccountController.java +++ b/src/main/java/runner/controllers/AccountController.java @@ -1,4 +1,5 @@ package runner.controllers; +import com.fasterxml.jackson.annotation.JsonView; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -8,8 +9,11 @@ import runner.entities.Transaction; import runner.services.AccountServices; import runner.services.CustomerServices; +import runner.views.Views; + import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; @RequestMapping("/myaccount") @RestController @@ -18,8 +22,6 @@ public class AccountController { @Autowired private AccountServices accountServices; - @Autowired - private CustomerServices customerServices; /** * This controller is used only for JWT testing purposes * */ @@ -29,16 +31,17 @@ public String testJWT() { } //get accounts for the authenticated user only, THIS is the homepage once user has logged in + @JsonView(Views.AllAccounts.class) @GetMapping public ResponseEntity> readAllAccount() { String currentPrincipalName = SecurityContextHolder.getContext().getAuthentication().getName(); - return new ResponseEntity<>(customerServices.getAllAccounts(currentPrincipalName), HttpStatus.OK); + return new ResponseEntity<>(accountServices.getAllAccounts(currentPrincipalName), HttpStatus.OK); } - //REMOVE if not needed - @GetMapping(value = "/{id}") - public ResponseEntity readAccount(@PathVariable Long id) throws Exception { - return new ResponseEntity<>(accountServices.readAccount(id), HttpStatus.OK); + @JsonView(Views.AccountSpecific.class) + @GetMapping(value = "/{accountEncryptedUrl}") + public ResponseEntity readAccountById(@PathVariable String accountEncryptedUrl){ + return new ResponseEntity<>(accountServices.findAccountByEncryptedUrl(accountEncryptedUrl), HttpStatus.OK); } //REMOVE if not needed @@ -53,10 +56,10 @@ public ResponseEntity> update(@RequestBody Account account, @P return new ResponseEntity<>(accountServices.updateAccount(id,account), HttpStatus.OK); } - //This needs to be rewritten with "encryptedUrl/delete" - @DeleteMapping(value = "/delete/{id}") - public ResponseEntity deleteById(@PathVariable Long id) throws Exception { - return new ResponseEntity<>(accountServices.removeAccount(id), HttpStatus.OK); + //This needs to be rewritten with "encryptedUrl/delete", need to doublecheck if deleting account deletes User due to cascade.ALL + @DeleteMapping(value = "/{encryptedUrl}/delete") + public ResponseEntity deleteById(@PathVariable String encryptedUrl){ + return new ResponseEntity<>(accountServices.removeAccount(encryptedUrl), HttpStatus.OK); } @PutMapping(value = "/{encryptedUrl}/deposit") diff --git a/src/main/java/runner/controllers/CustomerController.java b/src/main/java/runner/controllers/CustomerController.java index 116b24780..9a0d9ac86 100644 --- a/src/main/java/runner/controllers/CustomerController.java +++ b/src/main/java/runner/controllers/CustomerController.java @@ -1,4 +1,5 @@ package runner.controllers; +import com.fasterxml.jackson.annotation.JsonView; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -9,6 +10,7 @@ import runner.entities.Address; import runner.entities.Customer; import runner.services.CustomerServices; +import runner.views.Views; import java.net.URI; @@ -23,9 +25,9 @@ public class CustomerController { private final static Logger logger = Logger.getLogger(CustomerController.class.getName()); - + @JsonView(Views.Profile.class) @GetMapping - public ResponseEntity readById() { + public ResponseEntity getCustomer() { String currentPrincipalName = SecurityContextHolder.getContext().getAuthentication().getName(); Customer customer =customerServices.readCustomerByLogin(currentPrincipalName); if( customer == null) @@ -62,6 +64,7 @@ public ResponseEntity update(@RequestBody Customer customer) throws Ex return new ResponseEntity<>(customerServices.updateCustomer(id,customer), HttpStatus.OK); } + @JsonView(Views.PhoneNumber.class) @PutMapping(value = "/update/phone") public ResponseEntity updatePhone(@RequestBody String phoneNumber) throws Exception { String currentPrincipalName = SecurityContextHolder.getContext().getAuthentication().getName(); @@ -77,6 +80,7 @@ else if(response == 1 ) } + @JsonView(Views.Email.class) @PutMapping(value = "/update/email") public ResponseEntity updateEmail(@RequestBody String email) throws Exception { String currentPrincipalName = SecurityContextHolder.getContext().getAuthentication().getName(); @@ -92,6 +96,7 @@ else if(response == 1 ) } + @JsonView(Views.Address.class) @PutMapping(value = "/update/address") public ResponseEntity updateEmail(@RequestBody Address address) throws Exception { String currentPrincipalName = SecurityContextHolder.getContext().getAuthentication().getName(); @@ -103,6 +108,7 @@ public ResponseEntity updateEmail(@RequestBody Address address) throws Except else return new ResponseEntity<>(customerServices.readCustomer(id), HttpStatus.OK); } + @DeleteMapping(value = "/delete") public ResponseEntity deleteById() { String currentPrincipalName = SecurityContextHolder.getContext().getAuthentication().getName(); @@ -117,14 +123,4 @@ else if(flag==2) return new ResponseEntity<>("No accounts/user found", HttpStatus.NOT_FOUND); } - @GetMapping(value = "/accounts") - public ResponseEntity getAllAccounts(){ - String currentPrincipalName = SecurityContextHolder.getContext().getAuthentication().getName(); - Customer customerReturned =customerServices.readCustomerByLogin(currentPrincipalName); - Long id = customerReturned.getId(); - if(customerServices.getAllAccounts(id) == null) - return new ResponseEntity<>("Customer not found", HttpStatus.NOT_FOUND); - else - return new ResponseEntity<>(customerServices.getAllAccounts(id), HttpStatus.OK); - } } \ No newline at end of file diff --git a/src/main/java/runner/controllers/TestHomePageDeleteLater.java b/src/main/java/runner/controllers/TestHomePageDeleteLater.java index 5271ff99f..d551e6358 100644 --- a/src/main/java/runner/controllers/TestHomePageDeleteLater.java +++ b/src/main/java/runner/controllers/TestHomePageDeleteLater.java @@ -13,7 +13,6 @@ import java.util.Set; import java.util.stream.Collectors; -//@RequestMapping(value = "/myaccount") @RestController public class TestHomePageDeleteLater { @Autowired @@ -37,13 +36,15 @@ public ResponseEntity> readAllAccount(){ return new ResponseEntity<>(customerServices.getAllAccounts(currentPrincipalName), HttpStatus.OK); }*/ - @GetMapping(value = "/{accountEncryptedUrl}") + + //get account for specific encrypted URL: THIS METHOD HAS BEEN MOVED TO ACCOUNTCONTROLLER +/* @GetMapping(value = "/{accountEncryptedUrl}") public ResponseEntity readAccountById(@PathVariable String accountEncryptedUrl) throws Exception { String currentPrincipalName = SecurityContextHolder.getContext().getAuthentication().getName(); - Long accountId = customerServices.getAllAccounts(currentPrincipalName).stream() + Long accountId = accountServices.getAllAccounts(currentPrincipalName).stream() .filter(a->a.getEncryptedUrl().equals(accountEncryptedUrl)) .collect(Collectors.toList()).get(0).getId(); return new ResponseEntity<>(accountServices.readAccount(accountId), HttpStatus.OK); - } + }*/ } \ No newline at end of file diff --git a/src/main/java/runner/entities/Account.java b/src/main/java/runner/entities/Account.java index 6f921ce2a..33109dc97 100644 --- a/src/main/java/runner/entities/Account.java +++ b/src/main/java/runner/entities/Account.java @@ -1,7 +1,10 @@ package runner.entities; import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonView; import runner.enums.AccountType; +import runner.views.Views; + import javax.persistence.*; import java.time.LocalDate; @@ -15,15 +18,30 @@ public class Account { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; + + @JsonView(Views.AccountNumber.class) private String accountNumber; + + @JsonView(Views.AccountDetails.class) private String routingNumber; + + @JsonView(Views.AccountType.class) @Enumerated(EnumType.STRING) private AccountType accountType; //enum + + @JsonView(Views.AccountActions.class) private Double balance; + + @JsonView(Views.AccountDetails.class) private LocalDate dateOfOpening; + + @JsonView(Views.AccountDetails.class) private Double interestRate; + + @JsonView(Views.AllAccounts.class) //delete this later in production private String encryptedUrl; + @JsonView(Views.AccountSpecific.class) @ManyToMany(cascade = CascadeType.ALL) @JoinTable( name = "account_transaction", diff --git a/src/main/java/runner/entities/Customer.java b/src/main/java/runner/entities/Customer.java index edafbc743..210c1de26 100644 --- a/src/main/java/runner/entities/Customer.java +++ b/src/main/java/runner/entities/Customer.java @@ -1,6 +1,9 @@ package runner.entities; import com.fasterxml.jackson.annotation.JsonBackReference; +import com.fasterxml.jackson.annotation.JsonView; +import runner.views.Views; + import javax.persistence.*; import java.time.LocalDate; import java.util.Set; @@ -12,20 +15,31 @@ public class Customer { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; + @Column(nullable = false) private String firstName; + + @JsonView(Views.Profile.class) private String middleName; + @Column(nullable = false) private String lastName; + @Column(nullable = false) private LocalDate dateOfBirth; + @Column(nullable = false) private String socialSecurity; + @Column(nullable = false) + @JsonView(Views.Email.class) private String email; + + @JsonView(Views.PhoneNumber.class) @Column(nullable = false) private String phoneNumber; + @JsonView(Views.Address.class) @OneToOne(cascade = ALL, fetch = FetchType.EAGER) private Address address; @JsonBackReference(value = "login") diff --git a/src/main/java/runner/entities/Login.java b/src/main/java/runner/entities/Login.java index 7d946331b..a357121a2 100644 --- a/src/main/java/runner/entities/Login.java +++ b/src/main/java/runner/entities/Login.java @@ -2,9 +2,11 @@ import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonView; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; +import runner.views.Views; import javax.persistence.*; import java.util.Collection; @@ -15,8 +17,11 @@ public class Login implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; + + @JsonView(Views.Profile.class) @Column(nullable = false) private String username; + @Column(nullable = false) private String password; diff --git a/src/main/java/runner/repositories/AccountRepo.java b/src/main/java/runner/repositories/AccountRepo.java index 6d8ef36f5..161876ccf 100644 --- a/src/main/java/runner/repositories/AccountRepo.java +++ b/src/main/java/runner/repositories/AccountRepo.java @@ -1,9 +1,13 @@ package runner.repositories; +import org.springframework.data.jpa.repository.Query; import runner.entities.Account; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Set; + @Repository public interface AccountRepo extends CrudRepository { @@ -11,5 +15,6 @@ public interface AccountRepo extends CrudRepository { Account findAccountById(Long Id); Account findAccountByEncryptedUrl(String encryptedUrl); Account findAccountByAccountNumber(String accountNumber); - + Set findAccountsByCustomer_LoginUsername (String login); + Account deleteAccountByEncryptedUrl(String encryptedUrl); } diff --git a/src/main/java/runner/security/config/WebSecurityConfig.java b/src/main/java/runner/security/config/WebSecurityConfig.java index 4feb95040..40d8b552f 100644 --- a/src/main/java/runner/security/config/WebSecurityConfig.java +++ b/src/main/java/runner/security/config/WebSecurityConfig.java @@ -29,8 +29,8 @@ import java.util.ArrayList; import java.util.List; -@Configuration //allows Spring to find and automatically apply the class to the global Web Security. -@EnableWebSecurity +@Configuration +@EnableWebSecurity //allows Spring to find and automatically apply the class to the global Web Security. public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired diff --git a/src/main/java/runner/security/controllers/AuthenticationController.java b/src/main/java/runner/security/controllers/AuthenticationController.java index 5e0a8f342..ae6a4f31d 100644 --- a/src/main/java/runner/security/controllers/AuthenticationController.java +++ b/src/main/java/runner/security/controllers/AuthenticationController.java @@ -14,6 +14,7 @@ import runner.entities.Login; import runner.security.models.AuthenticationResponse; import runner.security.utilities.JwtUtil; +import runner.services.AccountServices; import runner.services.CustomerServices; import runner.services.LoginServices; @@ -29,7 +30,7 @@ public class AuthenticationController { @Autowired private LoginServices loginServices; @Autowired - private CustomerServices customerServices; + private AccountServices accountServices; //jwt authentication @PostMapping(value = "/authenticate") @@ -51,7 +52,7 @@ public ResponseEntity generateAuthenticationToken(@RequestBody Login login) t //adding the random URL to the accounts public void addRandomUrlToAccounts(Login login){ - Set accountSet = customerServices.getAllAccounts(login.getUsername()); + Set accountSet = accountServices.getAllAccounts(login.getUsername()); accountSet.stream().forEach(a->a.setEncryptedUrl(generateRandomUrl())); } diff --git a/src/main/java/runner/services/AccountServices.java b/src/main/java/runner/services/AccountServices.java index ab4d1d196..fc870471b 100644 --- a/src/main/java/runner/services/AccountServices.java +++ b/src/main/java/runner/services/AccountServices.java @@ -18,6 +18,10 @@ public class AccountServices { @Autowired private TransactionServices transactionServices; + public Set getAllAccounts(String username){ + return accountRepo.findAccountsByCustomer_LoginUsername(username); + } + public Account createAccount(Account account) { loggerService.log(Level.INFO, "The customer's new account is being saved"); return accountRepo.save(account); @@ -51,6 +55,14 @@ public Boolean removeAccount(Long id) throws Exception{ } } + public Boolean removeAccount(String encryptedUrl){ + if(accountRepo.findAccountByEncryptedUrl(encryptedUrl).getBalance()==0) { + accountRepo.deleteAccountByEncryptedUrl(encryptedUrl); + return true; + } + return false; + } + public Optional updateAccount(Long id, Account account) throws Exception{ loggerService.log(Level.INFO, "Attempting to update customer's account # " + id); if (accountRepo.existsById(id) == true) { diff --git a/src/main/java/runner/services/CustomerServices.java b/src/main/java/runner/services/CustomerServices.java index 68b332a4a..08746c4b9 100644 --- a/src/main/java/runner/services/CustomerServices.java +++ b/src/main/java/runner/services/CustomerServices.java @@ -29,9 +29,6 @@ public CustomerServices(CustomerRepo customerRepo) { this.customerRepo = customerRepo; } - @Autowired - private LoginRepo loginRepo; - @Autowired private BCryptPasswordEncoder bCryptPasswordEncoder; @@ -185,6 +182,7 @@ public Customer updateCustomerAddress(Long id, Address address) { return null; } + //Delete if not needed public Set getAllAccounts(Long id) { loggerService.log(Level.INFO, "Finding the customer to get all accounts"); Customer customer = customerRepo.findCustomerById(id); @@ -196,7 +194,8 @@ public Set getAllAccounts(Long id) { return null; } - public Set getAllAccounts(String username) { + //superceded by Set findAccountsByCustomer_LoginUsername (String login) in AccountRepo +/* public Set getAllAccounts(String username) { loggerService.log(Level.INFO, "Finding the customer to get all accounts"); Login login = loginRepo.findLoginByUsername(username); Customer customer = customerRepo.findCustomerById(login.getId()); @@ -206,7 +205,7 @@ public Set getAllAccounts(String username) { return customer.getAccounts(); } return null; - } + }*/ //generate 35-40 random characters public String generateRandomUrl() { diff --git a/src/main/java/runner/views/Views.java b/src/main/java/runner/views/Views.java new file mode 100644 index 000000000..37c1ff241 --- /dev/null +++ b/src/main/java/runner/views/Views.java @@ -0,0 +1,49 @@ +package runner.views; + +public class Views { + + public static interface AccountNumber{ + + } + + public static interface AccountType{ + + } + + public static class AllAccounts implements AccountNumber, AccountType{ + /* + payload: multiple accounts: account number, account balance, account type + */ + } + + public static interface AccountActions{ + /* + payload: account balance + */ + } + + public static class AccountDetails implements AccountNumber, AccountType, AccountActions{ + /* + payload: account balance, interest rate, date of creation, account number, routing number, account type + */ + } + + public static class AccountSpecific implements AccountActions{ + /* + payload: account balance, transactions + */ + } + + public static interface Email{ + } + + public static interface PhoneNumber{ + } + + public static interface Address{ + } + + public static class Profile implements Email, PhoneNumber, Address { + } + +} diff --git a/src/test/java/runner/security/JwtTest.java b/src/test/java/runner/security/JwtTest.java index 6fb4374c9..772c25f33 100644 --- a/src/test/java/runner/security/JwtTest.java +++ b/src/test/java/runner/security/JwtTest.java @@ -38,17 +38,17 @@ public class JwtTest { @Autowired private JwtUtil jwtUtil; -// @Test -// public void notAuthenticatedTest() throws Exception { -// mockMvc.perform(MockMvcRequestBuilders.get("/account/test")).andExpect(status().isForbidden()); -// } + @Test + public void notAuthenticatedTest() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get("/account/test")).andExpect(status().isForbidden()); + } -// @Test -// public void shouldGenerateToken() throws Exception{ -// UserDetails user = new User("username","password", new ArrayList<>()); -// String token = jwtUtil.generateToken(user); -// mockMvc.perform(MockMvcRequestBuilders.get("/account/test") -// .header("Authorization", token)) -// .andExpect(status().isOk()); -// } + @Test + public void shouldGenerateToken() throws Exception{ + UserDetails user = new User("username","password", new ArrayList<>()); + String token = jwtUtil.generateToken(user); + mockMvc.perform(MockMvcRequestBuilders.get("/account/test") + .header("Authorization", token)) + .andExpect(status().isOk()); + } } diff --git a/target/classes/runner/controllers/AccountController.class b/target/classes/runner/controllers/AccountController.class index 5261ee3c8..f4834b0a4 100644 Binary files a/target/classes/runner/controllers/AccountController.class and b/target/classes/runner/controllers/AccountController.class differ diff --git a/target/classes/runner/controllers/TestHomePageDeleteLater.class b/target/classes/runner/controllers/TestHomePageDeleteLater.class index ccfbc0a8b..28b1b04ca 100644 Binary files a/target/classes/runner/controllers/TestHomePageDeleteLater.class and b/target/classes/runner/controllers/TestHomePageDeleteLater.class differ diff --git a/target/classes/runner/entities/Account.class b/target/classes/runner/entities/Account.class index 3b1d8ea93..a39ff086a 100644 Binary files a/target/classes/runner/entities/Account.class and b/target/classes/runner/entities/Account.class differ diff --git a/target/classes/runner/repositories/AccountRepo.class b/target/classes/runner/repositories/AccountRepo.class index db5293922..076181a9c 100644 Binary files a/target/classes/runner/repositories/AccountRepo.class and b/target/classes/runner/repositories/AccountRepo.class differ diff --git a/target/classes/runner/security/controllers/AuthenticationController.class b/target/classes/runner/security/controllers/AuthenticationController.class index 17a083405..fc210b051 100644 Binary files a/target/classes/runner/security/controllers/AuthenticationController.class and b/target/classes/runner/security/controllers/AuthenticationController.class differ diff --git a/target/classes/runner/services/AccountServices.class b/target/classes/runner/services/AccountServices.class index 61c9b02dd..8548a25a6 100644 Binary files a/target/classes/runner/services/AccountServices.class and b/target/classes/runner/services/AccountServices.class differ diff --git a/target/classes/runner/services/CustomerServices.class b/target/classes/runner/services/CustomerServices.class index a97169b17..6e8749ec7 100644 Binary files a/target/classes/runner/services/CustomerServices.class and b/target/classes/runner/services/CustomerServices.class differ diff --git a/target/classes/runner/views/Views$AccountActions.class b/target/classes/runner/views/Views$AccountActions.class new file mode 100644 index 000000000..9eea03fa7 Binary files /dev/null and b/target/classes/runner/views/Views$AccountActions.class differ diff --git a/target/classes/runner/views/Views$AccountDetails.class b/target/classes/runner/views/Views$AccountDetails.class new file mode 100644 index 000000000..c6649830b Binary files /dev/null and b/target/classes/runner/views/Views$AccountDetails.class differ diff --git a/target/classes/runner/views/Views$AccountNumber.class b/target/classes/runner/views/Views$AccountNumber.class new file mode 100644 index 000000000..e1a6befdc Binary files /dev/null and b/target/classes/runner/views/Views$AccountNumber.class differ diff --git a/target/classes/runner/views/Views$AccountSpecific.class b/target/classes/runner/views/Views$AccountSpecific.class new file mode 100644 index 000000000..49768f12f Binary files /dev/null and b/target/classes/runner/views/Views$AccountSpecific.class differ diff --git a/target/classes/runner/views/Views$AccountType.class b/target/classes/runner/views/Views$AccountType.class new file mode 100644 index 000000000..bec16886c Binary files /dev/null and b/target/classes/runner/views/Views$AccountType.class differ diff --git a/target/classes/runner/views/Views$Address.class b/target/classes/runner/views/Views$Address.class new file mode 100644 index 000000000..3e3d188de Binary files /dev/null and b/target/classes/runner/views/Views$Address.class differ diff --git a/target/classes/runner/views/Views$AllAccounts.class b/target/classes/runner/views/Views$AllAccounts.class new file mode 100644 index 000000000..b84c53035 Binary files /dev/null and b/target/classes/runner/views/Views$AllAccounts.class differ diff --git a/target/classes/runner/views/Views$Email.class b/target/classes/runner/views/Views$Email.class new file mode 100644 index 000000000..7a871efc1 Binary files /dev/null and b/target/classes/runner/views/Views$Email.class differ diff --git a/target/classes/runner/views/Views$PhoneNumber.class b/target/classes/runner/views/Views$PhoneNumber.class new file mode 100644 index 000000000..660f91a58 Binary files /dev/null and b/target/classes/runner/views/Views$PhoneNumber.class differ diff --git a/target/classes/runner/views/Views$Profile.class b/target/classes/runner/views/Views$Profile.class new file mode 100644 index 000000000..cd29d30cb Binary files /dev/null and b/target/classes/runner/views/Views$Profile.class differ diff --git a/target/classes/runner/views/Views.class b/target/classes/runner/views/Views.class new file mode 100644 index 000000000..746a9ede2 Binary files /dev/null and b/target/classes/runner/views/Views.class differ diff --git a/target/test-classes/runner/security/JwtTest.class b/target/test-classes/runner/security/JwtTest.class index 1690f3464..655c9a87c 100644 Binary files a/target/test-classes/runner/security/JwtTest.class and b/target/test-classes/runner/security/JwtTest.class differ