diff --git a/pom.xml b/pom.xml index fc5bfeac..e4c801a0 100644 --- a/pom.xml +++ b/pom.xml @@ -52,9 +52,9 @@ - mysql - mysql-connector-java - 8.0.33 + com.mysql + mysql-connector-j + 9.1.0 runtime @@ -67,6 +67,11 @@ spring-security-test test + + com.h2database + h2 + test + @@ -80,8 +85,8 @@ maven-compiler-plugin 3.8.0 - 1.8 - 1.8 + 17 + 17 diff --git a/src/main/java/com/example/bankapp/config/SecurityConfig.java b/src/main/java/com/example/bankapp/config/SecurityConfig.java index 4dbd1572..0182ede5 100644 --- a/src/main/java/com/example/bankapp/config/SecurityConfig.java +++ b/src/main/java/com/example/bankapp/config/SecurityConfig.java @@ -27,7 +27,6 @@ public static PasswordEncoder passwordEncoder() { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http - .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(authz -> authz .requestMatchers("/register").permitAll() .anyRequest().authenticated() @@ -41,12 +40,14 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .logout(logout -> logout .invalidateHttpSession(true) .clearAuthentication(true) - .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) + .logoutRequestMatcher(new AntPathRequestMatcher("/logout", "POST")) .logoutSuccessUrl("/login?logout") .permitAll() ) .headers(headers -> headers .frameOptions(frameOptions -> frameOptions.sameOrigin()) + .contentTypeOptions(contentTypeOptions -> {}) + .httpStrictTransportSecurity(hsts -> hsts.includeSubDomains(true).maxAgeInSeconds(31536000)) ); return http.build(); diff --git a/src/main/java/com/example/bankapp/controller/BankController.java b/src/main/java/com/example/bankapp/controller/BankController.java index 19fcded7..62724436 100644 --- a/src/main/java/com/example/bankapp/controller/BankController.java +++ b/src/main/java/com/example/bankapp/controller/BankController.java @@ -48,10 +48,18 @@ public String login() { } @PostMapping("/deposit") - public String deposit(@RequestParam BigDecimal amount) { + public String deposit(@RequestParam BigDecimal amount, Model model) { String username = SecurityContextHolder.getContext().getAuthentication().getName(); Account account = accountService.findAccountByUsername(username); - accountService.deposit(account, amount); + + try { + accountService.deposit(account, amount); + } catch (RuntimeException e) { + model.addAttribute("error", e.getMessage()); + model.addAttribute("account", account); + return "dashboard"; + } + return "redirect:/dashboard"; } diff --git a/src/main/java/com/example/bankapp/service/AccountService.java b/src/main/java/com/example/bankapp/service/AccountService.java index 5d7d90ec..34220e8f 100644 --- a/src/main/java/com/example/bankapp/service/AccountService.java +++ b/src/main/java/com/example/bankapp/service/AccountService.java @@ -12,6 +12,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -36,19 +37,30 @@ public Account findAccountByUsername(String username) { } public Account registerAccount(String username, String password) { + if (username == null || username.trim().isEmpty() || username.trim().length() < 3) { + throw new RuntimeException("Username must be at least 3 characters"); + } + username = username.trim(); + if (password == null || password.length() < 8) { + throw new RuntimeException("Password must be at least 8 characters"); + } if (accountRepository.findByUsername(username).isPresent()) { - throw new RuntimeException("Username already exists"); + throw new RuntimeException("Registration failed. Please try a different username."); } Account account = new Account(); account.setUsername(username); - account.setPassword(passwordEncoder.encode(password)); // Encrypt password - account.setBalance(BigDecimal.ZERO); // Initial balance set to 0 + account.setPassword(passwordEncoder.encode(password)); + account.setBalance(BigDecimal.ZERO); return accountRepository.save(account); } + @Transactional public void deposit(Account account, BigDecimal amount) { + if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) { + throw new RuntimeException("Amount must be positive"); + } account.setBalance(account.getBalance().add(amount)); accountRepository.save(account); @@ -61,7 +73,11 @@ public void deposit(Account account, BigDecimal amount) { transactionRepository.save(transaction); } + @Transactional public void withdraw(Account account, BigDecimal amount) { + if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) { + throw new RuntimeException("Amount must be positive"); + } if (account.getBalance().compareTo(amount) < 0) { throw new RuntimeException("Insufficient funds"); } @@ -100,7 +116,11 @@ public Collection extends GrantedAuthority> authorities() { return Arrays.asList(new SimpleGrantedAuthority("USER")); } + @Transactional public void transferAmount(Account fromAccount, String toUsername, BigDecimal amount) { + if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) { + throw new RuntimeException("Amount must be positive"); + } if (fromAccount.getBalance().compareTo(amount) < 0) { throw new RuntimeException("Insufficient funds"); } diff --git a/src/main/resources/templates/dashboard.html b/src/main/resources/templates/dashboard.html index 23a0cc7f..d039ab61 100644 --- a/src/main/resources/templates/dashboard.html +++ b/src/main/resources/templates/dashboard.html @@ -117,7 +117,11 @@ Dashboard Transactions - Logout + + + Logout + + @@ -141,7 +145,7 @@ Account Details Deposit - + Amount: @@ -157,7 +161,7 @@ Account Details Withdraw - + Amount: @@ -173,7 +177,7 @@ Account Details Transfer Money - + Recipient Username: diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html index 7b40190d..412a68eb 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -105,7 +105,7 @@ Login - + Username: diff --git a/src/main/resources/templates/register.html b/src/main/resources/templates/register.html index e410b74e..b5041caf 100644 --- a/src/main/resources/templates/register.html +++ b/src/main/resources/templates/register.html @@ -105,7 +105,7 @@ Register a New Account - + Username: @@ -119,7 +119,7 @@ Register a New Account Already have an account? Login here - User already present. + diff --git a/src/main/resources/templates/transactions.html b/src/main/resources/templates/transactions.html index 307bc5de..e6291b3f 100644 --- a/src/main/resources/templates/transactions.html +++ b/src/main/resources/templates/transactions.html @@ -96,7 +96,11 @@ Dashboard Transactions - Logout + + + Logout + + diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 00000000..550f3d4d --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,6 @@ +spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.show-sql=true
Already have an account? Login here