Skip to content

Commit

Permalink
Send Email Notification on Login (#12)
Browse files Browse the repository at this point in the history
* Untrack changes in `target/` directory

* Update Maven and refactor some code

* Refactored code and fixed naming convention mistakes

* Added UserControllerTests

* Clean up README file

* Add DashboardControllerTests

* Renamed `JwtUserDetailsService`, and other small changes

* Refactor: add `TestUtil`, rename `OtpService` and `OtpServiceImpl`, and enhance exception handling

* Add AccountControllerTests

* Test fund transfer to the same account

* Untrack changes in `target/` directory

* Update Maven and refactor some code

* Refactored code and fixed naming convention mistakes

* Added UserControllerTests

* Clean up README file

* Add DashboardControllerTests

* Renamed `JwtUserDetailsService`, and other small changes

* Refactor: add `TestUtil`, rename `OtpService` and `OtpServiceImpl`, and enhance exception handling

* Add AccountControllerTests

* Test fund transfer to the same account

* Fix `accountService.createPin` and `accountService.updatePin`

* Feature: Add country code

* Replaced 'country' with 'countryCode' and added new test cases

* test update user without authentication

* Add Token Service

* Add logs to `TokenServiceImpl`

* Add `GeolocationService`

* Feature: Send Email Notification on Login

* Rename `UserResponse` attribute `country` to `countryCode`

* Fix some issues
  • Loading branch information
AmrElsayyad authored Jun 22, 2024
1 parent fa4b629 commit a2cc26e
Show file tree
Hide file tree
Showing 33 changed files with 1,557 additions and 697 deletions.
264 changes: 130 additions & 134 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.webapp</groupId>
<artifactId>bankingportal</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>bankingportal</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.webapp</groupId>
<artifactId>bankingportal</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>bankingportal</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.googlecode.libphonenumber</groupId>
<artifactId>libphonenumber</artifactId>
<version>8.13.38</version>
</dependency>


<dependency>
<groupId>com.github.javafaker</groupId>
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
</dependency>


<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
Expand All @@ -42,123 +38,123 @@
<artifactId>mapstruct</artifactId>
<version>1.6.0.Beta2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.0.2</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- JSON serialization -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- JSON serialization -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.15.0</version> <!-- Use the latest version available -->
<configuration>
<rulesets>
<ruleset>/rulesets/java/braces.xml</ruleset>
<ruleset>/rulesets/java/naming.xml</ruleset>
<ruleset>/usr/pmd/rulesets/strings.xml</ruleset>
<ruleset>http://localhost/design.xml</ruleset>
</rulesets>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.15.0</version> <!-- Use the latest version available -->
<configuration>
<rulesets>
<ruleset>/rulesets/java/braces.xml</ruleset>
<ruleset>/rulesets/java/naming.xml</ruleset>
<ruleset>/usr/pmd/rulesets/strings.xml</ruleset>
<ruleset>http://localhost/design.xml</ruleset>
</rulesets>

</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>pmd</goal>
<goal>cpd-check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</configuration>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>pmd</goal>
<goal>cpd-check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>


</project>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,38 @@

import com.webapp.bankingportal.security.JwtAuthenticationEntryPoint;
import com.webapp.bankingportal.security.JwtAuthenticationFilter;
import com.webapp.bankingportal.service.JwtUserDetailsService;
import com.webapp.bankingportal.service.TokenService;

import jakarta.servlet.http.HttpServletResponse;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class WebSecurityConfig {

private static final String[] PUBLIC_URLS = {
"/api/users/register",
"/api/users/login",
"/api/users/generate-otp",
"/api/users/verify-otp",
"swagger-ui.html",
"/v3/api-docs/**",
"/swagger-ui/**",
"/actuator/**"
};

@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

@Autowired
private JwtUserDetailsService jwtUserDetailsService;
private JwtAuthenticationFilter jwtAuthenticationFilter;

@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
private TokenService tokenService;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
auth.userDetailsService(tokenService).passwordEncoder(passwordEncoder());
}

@Bean
Expand All @@ -45,29 +58,32 @@ public PasswordEncoder passwordEncoder() {
}

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration)
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration)
throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable()).authorizeHttpRequests(requests -> requests
.requestMatchers("/api/users/register").permitAll()
.requestMatchers("/api/users/login").permitAll()
.requestMatchers("/api/users/generate-otp").permitAll()
.requestMatchers("/api/users/verify-otp").permitAll()
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.requestMatchers("swagger-ui.html").permitAll()
.requestMatchers("/v3/api-docs/**").permitAll()
.requestMatchers("/swagger-ui/**").permitAll()
.requestMatchers("/actuator/**").permitAll()
.anyRequest().authenticated()).exceptionHandling(handling -> handling
.authenticationEntryPoint(jwtAuthenticationEntryPoint))
.sessionManagement(management -> management
.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(requests -> requests
.requestMatchers(PUBLIC_URLS).permitAll()
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.anyRequest().authenticated())
.exceptionHandling(handling -> {
handling.authenticationEntryPoint(jwtAuthenticationEntryPoint);
})
.sessionManagement(management -> {
management.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
})
.logout(logout -> logout
.logoutSuccessHandler((request, response, authentication) -> {
response.setStatus(HttpServletResponse.SC_OK);
}));

http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http.addFilterBefore(jwtAuthenticationFilter,
UsernamePasswordAuthenticationFilter.class);

return http.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public ResponseEntity<?> fundTransfer(@RequestBody FundTransferRequest fundTrans
if (LoggedinUser.getAccountNumber()
.equals(fundTransferRequest.getTargetAccountNumber())) {
return new ResponseEntity<>(
"Source and target account cannot be same",
"Source and target account cannot be the same",
HttpStatus.BAD_REQUEST);
}

Expand Down
Loading

0 comments on commit a2cc26e

Please sign in to comment.