Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
Expand All @@ -67,6 +67,11 @@
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand All @@ -80,8 +85,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/com/example/bankapp/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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();
Expand Down
12 changes: 10 additions & 2 deletions src/main/java/com/example/bankapp/controller/BankController.java
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}

Expand Down
26 changes: 23 additions & 3 deletions src/main/java/com/example/bankapp/service/AccountService.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
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");
}
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
account.setBalance(account.getBalance().add(amount));
accountRepository.save(account);

Expand All @@ -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");
}
Expand Down Expand Up @@ -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");
}
Expand Down
12 changes: 8 additions & 4 deletions src/main/resources/templates/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,11 @@
<ul class="navbar-nav ml-auto">
<li class="nav-item"><a class="nav-link" href="/dashboard">Dashboard</a></li>
<li class="nav-item"><a class="nav-link" href="/transactions">Transactions</a></li>
<li class="nav-item"><a class="nav-link" href="/logout">Logout</a></li>
<li class="nav-item">
<form method="post" th:action="@{/logout}" style="display:inline;">
<button type="submit" class="nav-link btn btn-link" style="color:#ffffff !important;cursor:pointer;">Logout</button>
</form>
</li>
</ul>
</nav>

Expand All @@ -141,7 +145,7 @@ <h4>Account Details</h4>
Deposit
</button>
<div class="collapse mt-3" id="depositForm">
<form method="post" action="/deposit" class="form-container">
<form method="post" th:action="@{/deposit}" class="form-container">
<div class="form-group">
<label>Amount:</label>
<input type="number" class="form-control" name="amount" required />
Expand All @@ -157,7 +161,7 @@ <h4>Account Details</h4>
Withdraw
</button>
<div class="collapse mt-3" id="withdrawForm">
<form method="post" action="/withdraw" class="form-container">
<form method="post" th:action="@{/withdraw}" class="form-container">
<div class="form-group">
<label>Amount:</label>
<input type="number" class="form-control" name="amount" required />
Expand All @@ -173,7 +177,7 @@ <h4>Account Details</h4>
Transfer Money
</button>
<div class="collapse mt-3" id="transferForm">
<form method="post" action="/transfer" class="form-container">
<form method="post" th:action="@{/transfer}" class="form-container">
<div class="form-group">
<label>Recipient Username:</label>
<input type="text" class="form-control" name="toUsername" required />
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/templates/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@

<div class="container">
<h2 class="text-left">Login</h2>
<form method="post" action="/login">
<form method="post" th:action="@{/login}">
<div class="form-group">
<label>Username:</label>
<input type="text" class="form-control" name="username" required />
Expand Down
4 changes: 2 additions & 2 deletions src/main/resources/templates/register.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@

<div class="container">
<h2 class="text-left">Register a New Account</h2>
<form method="post" action="/register">
<form method="post" th:action="@{/register}">
<div class="form-group">
<label>Username:</label>
<input type="text" class="form-control" name="username" required />
Expand All @@ -119,7 +119,7 @@ <h2 class="text-left">Register a New Account</h2>
<p class="mt-3">Already have an account? <a href="/login" class="custom-link">Login here</a></p>

<div th:if="${error}" class="alert alert-danger mt-3 text-center">
User already present.
<span th:text="${error}"></span>
</div>
</div>

Expand Down
6 changes: 5 additions & 1 deletion src/main/resources/templates/transactions.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,11 @@
<ul class="navbar-nav ml-auto">
<li class="nav-item"><a class="nav-link" href="/dashboard">Dashboard</a></li>
<li class="nav-item"><a class="nav-link" href="/transactions">Transactions</a></li>
<li class="nav-item"><a class="nav-link" href="/logout">Logout</a></li>
<li class="nav-item">
<form method="post" th:action="@{/logout}" style="display:inline;">
<button type="submit" class="nav-link btn btn-link" style="color:#ffffff !important;cursor:pointer;">Logout</button>
</form>
</li>
</ul>
</nav>

Expand Down
6 changes: 6 additions & 0 deletions src/test/resources/application.properties
Original file line number Diff line number Diff line change
@@ -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