diff --git a/retail-managment-system/rms-api/pom.xml b/retail-managment-system/rms-api/pom.xml
index c1a51307..1375d5d4 100644
--- a/retail-managment-system/rms-api/pom.xml
+++ b/retail-managment-system/rms-api/pom.xml
@@ -119,6 +119,38 @@
+
+
+
+ io.jsonwebtoken
+ jjwt-api
+ 0.11.5
+
+
+ io.jsonwebtoken
+ jjwt-impl
+ 0.11.5
+ runtime
+
+
+ io.jsonwebtoken
+ jjwt-jackson
+ 0.11.5
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+
+ org.passay
+ passay
+ 1.3.1
+
+
+
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/config/GlobalCorsConfiguration.java b/retail-managment-system/rms-api/src/main/java/com/rms/config/GlobalCorsConfiguration.java
deleted file mode 100644
index f20d7c7c..00000000
--- a/retail-managment-system/rms-api/src/main/java/com/rms/config/GlobalCorsConfiguration.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.rms.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.config.annotation.CorsRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
-
-@Configuration
-public class GlobalCorsConfiguration {
-
- public GlobalCorsConfiguration() {
- super();
- }
-
- /**
- * Bean to define global CORS.
- *
- * @return
- */
- @Bean
- public WebMvcConfigurer corsConfigurer() {
- return new WebMvcConfigurerAdapter() {
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**").allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
- }
- };
- }
-}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/config/WebSecurityConfig.java b/retail-managment-system/rms-api/src/main/java/com/rms/config/WebSecurityConfig.java
index a953d901..75de6d8a 100644
--- a/retail-managment-system/rms-api/src/main/java/com/rms/config/WebSecurityConfig.java
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/config/WebSecurityConfig.java
@@ -1,36 +1,93 @@
-//package com.rms.config;
-//
-//import org.springframework.context.annotation.Bean;
-//import org.springframework.context.annotation.Configuration;
-//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.web.cors.CorsConfiguration;
-//import org.springframework.web.cors.CorsConfigurationSource;
-//import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
-//
-//@Configuration
-//@EnableWebSecurity
-//public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
-//
-// protected void configure(HttpSecurity http) throws Exception {
-// http.cors().configurationSource(corsConfigurationSource()).and().csrf().disable();
-// }
-//
-// @Bean
-// public CorsConfigurationSource corsConfigurationSource() {
-// UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
-// CorsConfiguration config = new CorsConfiguration();
-// config.setAllowCredentials(true);
-// config.addAllowedOrigin("*");
-// config.addAllowedHeader("Authorization");
-// config.addAllowedHeader("Content-Type");
-// config.addAllowedHeader("x-auth-token");
-// config.addAllowedHeader("If-None-Match");
-// config.addAllowedHeader("If-Match");
-// config.addExposedHeader("ETag");
-// config.addAllowedMethod("*");
-// source.registerCorsConfiguration("/**", config);
-// return source;
-// }
-//}
+package com.rms.config;
+import com.rms.security.CustomUserDetailsService;
+import com.rms.security.RestAuthenticationEntryPoint;
+import com.rms.security.TokenAuthenticationFilter;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+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.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+@RequiredArgsConstructor
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ private final CustomUserDetailsService customUserDetailsService;
+
+ private final RestAuthenticationEntryPoint restAuthenticationEntryPoint;
+
+
+
+
+ @Override
+ public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
+ authenticationManagerBuilder.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
+ }
+
+ @Bean
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+
+ @Bean
+ public TokenAuthenticationFilter authenticationJwtTokenFilter() {
+ return new TokenAuthenticationFilter();
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+
+ http.cors().configurationSource(corsConfigurationSource()).and().csrf().disable().exceptionHandling()
+ .authenticationEntryPoint(restAuthenticationEntryPoint);
+ http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
+ http.authorizeRequests().antMatchers("/auth/**").permitAll();
+ http.authorizeRequests().antMatchers("/customer/**","/installment/**",
+ "/investor/**","/employee/**","/profits/**"
+ ,"/role/**","/store/**","/supplier/**",
+ "/transaction/**","/user/**","/user-role/**").hasRole("ADMIN");
+ //for swagger
+ http.authorizeRequests().antMatchers("/v3/api-docs/*", "/v3/api-docs", "/swagger-ui.html", "/swagger-ui/*").permitAll();
+ http.authorizeRequests().anyRequest().authenticated();
+ http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
+ }
+
+ @Override
+ public void configure(WebSecurity web) throws Exception {
+
+ }
+
+
+ @Bean
+ CorsConfigurationSource corsConfigurationSource() {
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ CorsConfiguration corsConfiguration = new CorsConfiguration().applyPermitDefaultValues();
+ corsConfiguration.addAllowedMethod(HttpMethod.PUT);
+ corsConfiguration.addAllowedMethod(HttpMethod.DELETE);
+ corsConfiguration.addAllowedMethod(HttpMethod.OPTIONS);
+ corsConfiguration.addAllowedMethod(HttpMethod.PATCH);
+ source.registerCorsConfiguration("/**", corsConfiguration);
+ return source;
+ }
+}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/repository/UserRepository.java b/retail-managment-system/rms-api/src/main/java/com/rms/repository/UserRepository.java
index 6ec9c6b0..94c1dc22 100644
--- a/retail-managment-system/rms-api/src/main/java/com/rms/repository/UserRepository.java
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/repository/UserRepository.java
@@ -1,6 +1,8 @@
package com.rms.repository;
import com.rms.domain.security.User;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
@@ -10,6 +12,17 @@
@Repository
public interface UserRepository extends JpaRepository {
+
+
+ @Query(value = "SELECT u FROM User u LEFT JOIN FETCH u.employee WHERE u.id= :id")
+ Optional findById(@Param("id") Integer id);
+
@Query("select u from User u where u.userName = :userName")
Optional findByUserName(@Param("userName") String userName);
+
+
+ @Query(value = "Select u.userName FROM User u WHERE u.userName= :username ")
+ Optional checkUsername(@Param("username") String username);
+
+
}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/repository/UserRoleRepository.java b/retail-managment-system/rms-api/src/main/java/com/rms/repository/UserRoleRepository.java
index 19024f3d..99e231c5 100644
--- a/retail-managment-system/rms-api/src/main/java/com/rms/repository/UserRoleRepository.java
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/repository/UserRoleRepository.java
@@ -1,5 +1,6 @@
package com.rms.repository;
+import com.rms.domain.security.Role;
import com.rms.domain.security.UserRole;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@@ -7,6 +8,8 @@
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
+
+import java.util.List;
import java.util.Optional;
@Repository
@@ -16,6 +19,8 @@ public interface UserRoleRepository extends JpaRepository {
Optional findRoleIdByUserIdAndRoleId(@Param("userId") Integer userId, @Param("roleId") Integer roleId);
+ @Query(value = "SELECT ur.role FROM UserRole ur WHERE ur.user.userName= :username")
+ List findByUserName(@Param("username") String username);
@Query(value = "SELECT ur FROM UserRole ur JOIN FETCH ur.role WHERE ur.user.id= :userId",
countQuery = "SELECT COUNT(ur) FROM UserRole ur WHERE ur.user.id= :userId")
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/rest/handler/UserHandler.java b/retail-managment-system/rms-api/src/main/java/com/rms/rest/handler/UserHandler.java
index 747e9167..980c87af 100644
--- a/retail-managment-system/rms-api/src/main/java/com/rms/rest/handler/UserHandler.java
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/rest/handler/UserHandler.java
@@ -1,13 +1,17 @@
package com.rms.rest.handler;
import com.rms.domain.core.Employee;
+import com.rms.domain.security.Role;
import com.rms.domain.security.User;
+import com.rms.domain.security.UserRole;
import com.rms.rest.dto.UserDto;
import com.rms.rest.dto.common.PaginatedResultDto;
import com.rms.rest.exception.*;
import com.rms.rest.modelmapper.UserMapper;
import com.rms.rest.modelmapper.common.PaginationMapper;
import com.rms.service.EmployeeService;
+import com.rms.service.RoleService;
+import com.rms.service.UserRoleService;
import com.rms.service.UserService;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Page;
@@ -26,11 +30,8 @@ public class UserHandler {
private UserMapper mapper ;
private EmployeeService employeeService ;
private PaginationMapper paginationMapper ;
-
-
-
-
-
+ private UserRoleService userRoleService;
+ private RoleService roleService;
public ResponseEntity> getAll (Integer page , Integer size)
{
@@ -52,21 +53,22 @@ public ResponseEntity> getById (Integer id)
public ResponseEntity> save(UserDto dto)
{
- Optional existedUsername = userService.findUserName(dto.getUserName());
- existedUsername.ifPresent(e -> {
- throw new ResourceAlreadyExistsException(User.class.getSimpleName(), "User Name " ,
- dto.getUserName(), ErrorCodes.DUPLICATE_RESOURCE.getCode());
- });
- User user =mapper.toEntity(dto);
- userService.save(user);
- UserDto userDto = mapper.toDto(user);
- return ResponseEntity.created(URI.create("/user/" + userDto.getId())).body(userDto);
+ Optional existedUsername= userService.findUsername(dto.getUserName());
+ if (existedUsername.isPresent()){
+ throw new ResourceAlreadyExistsException(User.class.getSimpleName(),
+ "username", dto.getUserName(), ErrorCodes.DUPLICATE_RESOURCE.getCode());
+ }
+
+ User user = mapper.toEntity(dto);
+ userService.save(user);
+ UserDto usersDto=mapper.toDto(user);
+ return ResponseEntity.created(URI.create("/user/" + usersDto.getId())).body(usersDto);
}
public ResponseEntity> update (Integer id , UserDto userDto)
{
User existedUser= userService.getById(id).orElseThrow(
()-> new ResourceNotFoundException(User.class.getSimpleName() , id));
- Optional existedUsername = userService.findUserName(userDto.getUserName());
+ Optional existedUsername = userService.getByUserName(userDto.getUserName());
if (existedUsername.isPresent() && !existedUsername.get().getId().equals(id)) {
throw new ResourceAlreadyExistsException(User.class.getSimpleName(), "Username", userDto.getUserName(), ErrorCodes.DUPLICATE_RESOURCE.getCode());
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/security/AuthController.java b/retail-managment-system/rms-api/src/main/java/com/rms/security/AuthController.java
new file mode 100644
index 00000000..021d001b
--- /dev/null
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/security/AuthController.java
@@ -0,0 +1,40 @@
+package com.rms.security;
+
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.AllArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.annotation.AuthenticationPrincipal;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+@RestController
+@RequestMapping("/auth")
+@AllArgsConstructor
+@Tag(name = "Authentication", description = "REST API for Authentication")
+@Log4j2
+public class AuthController {
+
+ private AuthHandler authHandler;
+
+ @PostMapping(value = "/login")
+ public ResponseEntity> login(@Valid @RequestBody LoginRequestDto loginRequest) {
+ //TODO:add encryption/decryption
+ return authHandler.login(loginRequest);
+ }
+
+
+ @PostMapping(value = "/refresh")
+ public ResponseEntity> refreshToken(@RequestBody RefreshTokenRequestDto refreshToken) {
+ return authHandler.refresh(refreshToken);
+ }
+
+ @GetMapping(value = "/user-info")
+ @PreAuthorize("isAuthenticated()")
+ public ResponseEntity> getUserInfo(@AuthenticationPrincipal UserDetails userDetails) {
+ return authHandler.getUserInfo(userDetails);
+ }
+}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/security/AuthHandler.java b/retail-managment-system/rms-api/src/main/java/com/rms/security/AuthHandler.java
new file mode 100644
index 00000000..67b0ae8c
--- /dev/null
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/security/AuthHandler.java
@@ -0,0 +1,72 @@
+package com.rms.security;
+import com.rms.rest.handler.UserHandler;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+
+import java.util.Set;
+
+@Component
+@RequiredArgsConstructor
+@Log4j2
+public class AuthHandler {
+
+ private final AuthenticationManager authenticationManager;
+
+ private final TokenProvider tokenProvider;
+ @Value("${app.jwt.token.expiration-in-ms}")
+ private Long tokenExpirationMillis;
+
+ @Value("${app.jwt.refresh.expiration-in-ms}")
+ private Long refreshTokenExpirationMillis;
+
+
+ @Autowired
+ private UserHandler userHandler;
+
+
+
+ public ResponseEntity> login(LoginRequestDto loginRequest) {
+ log.info("start login for user {}", loginRequest.getUsername());
+ Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ HttpHeaders responseHeaders = new HttpHeaders();
+ String accessToken = tokenProvider.generateAccessToken(loginRequest.getUsername());
+ String refreshToken = tokenProvider.generateRefreshToken(loginRequest.getUsername());
+ return ResponseEntity.ok().body(new LoginResponseDto(accessToken, refreshToken));
+ }
+
+
+ public ResponseEntity> refresh(RefreshTokenRequestDto dto) {
+ Boolean refreshTokenValid = tokenProvider.validateToken(dto.getRefreshToken());
+ if (!refreshTokenValid) {
+ return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
+ }
+
+ String currentUsername = tokenProvider.getUsernameFromToken(dto.getRefreshToken());
+
+ String newAccessToken = tokenProvider.generateAccessToken(currentUsername);
+ HttpHeaders responseHeaders = new HttpHeaders();
+
+ return ResponseEntity.ok().body(new LoginResponseDto(newAccessToken, dto.getRefreshToken()));
+ }
+
+
+ public ResponseEntity> getUserInfo(UserDetails userDetails) {
+ UserDto userDto = UserDto.builder().username(userDetails.getUsername()).authorities((Set) userDetails.getAuthorities()).build();
+
+ return ResponseEntity.ok(userDto);
+ }
+
+}
\ No newline at end of file
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/security/CustomUserDetailsService.java b/retail-managment-system/rms-api/src/main/java/com/rms/security/CustomUserDetailsService.java
new file mode 100644
index 00000000..296411a8
--- /dev/null
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/security/CustomUserDetailsService.java
@@ -0,0 +1,51 @@
+package com.rms.security;
+import com.rms.domain.security.Role;
+import com.rms.domain.security.User;
+import com.rms.repository.UserRepository;
+import com.rms.service.UserRoleService;
+import lombok.AllArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@AllArgsConstructor
+@Log4j2
+public class CustomUserDetailsService implements UserDetailsService {
+
+ private UserRepository userRepository;
+ private UserRoleService userRoleService;
+
+
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ User user = userRepository.findByUserName(username).orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
+ List roles= userRoleService.getRoleByUsername(username);
+ if (roles.isEmpty()){
+ return org.springframework.security.core.userdetails.User
+ .withUsername(username)
+ .password(user.getPassword())
+ .disabled(true)
+ .build();
+ }
+ List authorities = roles.stream()
+ .map(role -> new SimpleGrantedAuthority(role.getCode()))
+ .collect(Collectors.toList());
+ return org.springframework.security.core.userdetails.User
+ .withUsername(username)
+ .password(user.getPassword())
+ .authorities(authorities)
+ .accountExpired(false)
+ .accountLocked(false)
+ .credentialsExpired(false)
+ .disabled(false)
+ .build();
+ }
+}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/security/LoginRequestDto.java b/retail-managment-system/rms-api/src/main/java/com/rms/security/LoginRequestDto.java
new file mode 100644
index 00000000..d6e78da7
--- /dev/null
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/security/LoginRequestDto.java
@@ -0,0 +1,19 @@
+package com.rms.security;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+
+@Data
+public class LoginRequestDto {
+
+ @NotBlank(message = "username is mandatory")
+ @Size(max = 100, message = "username's max length allowed is 100 characters")
+ private String username;
+
+ @NotBlank(message = "password is mandatory")
+ @Size(max = 100, message = "password's max length allowed is 100 characters")
+ private String password;
+
+}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/security/LoginResponseDto.java b/retail-managment-system/rms-api/src/main/java/com/rms/security/LoginResponseDto.java
new file mode 100644
index 00000000..29ad84ac
--- /dev/null
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/security/LoginResponseDto.java
@@ -0,0 +1,17 @@
+package com.rms.security;
+
+import lombok.Data;
+
+@Data
+public class LoginResponseDto {
+ private String accessToken;
+ private String refreshToken;
+
+ public LoginResponseDto(String accessToken, String refreshToken) {
+ this.accessToken = accessToken;
+ this.refreshToken = refreshToken;
+ }
+
+ public LoginResponseDto() {
+ }
+}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/security/RefreshTokenRequestDto.java b/retail-managment-system/rms-api/src/main/java/com/rms/security/RefreshTokenRequestDto.java
new file mode 100644
index 00000000..ce3c14fa
--- /dev/null
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/security/RefreshTokenRequestDto.java
@@ -0,0 +1,8 @@
+package com.rms.security;
+
+import lombok.Data;
+
+@Data
+public class RefreshTokenRequestDto {
+ private String refreshToken;
+}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/security/RestAuthenticationEntryPoint.java b/retail-managment-system/rms-api/src/main/java/com/rms/security/RestAuthenticationEntryPoint.java
new file mode 100644
index 00000000..cfca1c0b
--- /dev/null
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/security/RestAuthenticationEntryPoint.java
@@ -0,0 +1,27 @@
+package com.rms.security;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+@Component
+public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
+ private static final Logger logger = LoggerFactory.getLogger(RestAuthenticationEntryPoint.class);
+
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response,
+ AuthenticationException authException) throws IOException, ServletException {
+ logger.error("Unauthorized error: {}", authException.getMessage());
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized :D :D :D ");
+ }
+
+}
+
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/security/TokenAuthenticationFilter.java b/retail-managment-system/rms-api/src/main/java/com/rms/security/TokenAuthenticationFilter.java
new file mode 100644
index 00000000..55594857
--- /dev/null
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/security/TokenAuthenticationFilter.java
@@ -0,0 +1,54 @@
+package com.rms.security;
+import lombok.AllArgsConstructor;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+@AllArgsConstructor
+@Log4j2
+public class TokenAuthenticationFilter extends OncePerRequestFilter {
+ @Autowired
+ private TokenProvider tokenProvider;
+ @Autowired
+ private UserDetailsService customUserDetailsService;
+ public TokenAuthenticationFilter() {
+ }
+ @Override
+ protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
+ try {
+ String jwt = getJwtFromRequest(httpServletRequest);
+ if (tokenProvider.validateToken(jwt)) {
+ String username = tokenProvider.getUsernameFromToken(jwt);
+ UserDetails userDetails = customUserDetailsService.loadUserByUsername(username);
+ UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
+ authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ filterChain.doFilter(httpServletRequest, httpServletResponse);
+ }
+
+ private String getJwtFromRequest(HttpServletRequest request) {
+ String bearerToken = request.getHeader("Authorization");
+ if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
+ String accessToken = bearerToken.substring(7);
+ if (accessToken == null) return null;
+ return accessToken;
+ }
+ return null;
+ }
+
+}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/security/TokenProvider.java b/retail-managment-system/rms-api/src/main/java/com/rms/security/TokenProvider.java
new file mode 100644
index 00000000..d585a97f
--- /dev/null
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/security/TokenProvider.java
@@ -0,0 +1,80 @@
+package com.rms.security;
+
+
+import io.jsonwebtoken.*;
+import io.jsonwebtoken.security.Keys;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import java.security.Key;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Date;
+
+@Component
+public class TokenProvider {
+
+ private final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
+ @Value("${app.jwt.token.expiration-in-ms}")
+ private Long tokenExpirationMillis;
+ @Value("${app.jwt.refresh.expiration-in-ms}")
+ private Long refreshTokenExpirationMillis;
+
+ public String generateAccessToken(String subject) {
+ Date now = new Date();
+ Long duration = now.getTime() + tokenExpirationMillis;
+ Date expiryDate = new Date(duration);
+
+ String token = Jwts.builder()
+ .setSubject(subject)
+ .setIssuedAt(now)
+ .setExpiration(expiryDate)
+ .signWith(key)
+ .compact();
+ return token;
+ }
+
+ public String generateRefreshToken(String subject) {
+ Date now = new Date();
+ Long duration = now.getTime() + refreshTokenExpirationMillis;
+ Date expiryDate = new Date(duration);
+ String token = Jwts.builder()
+ .setSubject(subject)
+ .setIssuedAt(now)
+ .setExpiration(expiryDate)
+ .signWith(key)
+ .compact();
+ return token;
+ }
+
+ public String getUsernameFromToken(String token) {
+ Claims claims = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
+ return claims.getSubject();
+ }
+
+ public LocalDateTime getExpiryDateFromToken(String token) {
+ Claims claims = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token).getBody();
+ return LocalDateTime.ofInstant(claims.getExpiration().toInstant(), ZoneId.systemDefault());
+ }
+
+ public boolean validateToken(String token) {
+ try {
+ if (!StringUtils.hasText(token))
+ return false;
+ Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
+ return true;
+ } catch (SignatureException ex) {
+ ex.printStackTrace();
+ } catch (MalformedJwtException ex) {
+ ex.printStackTrace();
+ } catch (ExpiredJwtException ex) {
+ ex.printStackTrace();
+ } catch (UnsupportedJwtException ex) {
+ ex.printStackTrace();
+ } catch (IllegalArgumentException ex) {
+ ex.printStackTrace();
+ }
+ return false;
+ }
+}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/security/UserDto.java b/retail-managment-system/rms-api/src/main/java/com/rms/security/UserDto.java
new file mode 100644
index 00000000..e61f53ad
--- /dev/null
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/security/UserDto.java
@@ -0,0 +1,17 @@
+package com.rms.security;
+
+import lombok.Builder;
+import lombok.Getter;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.Set;
+
+
+@Builder
+@Getter
+public class UserDto {
+
+ private String username;
+ private Set authorities;
+
+}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/service/UserRoleService.java b/retail-managment-system/rms-api/src/main/java/com/rms/service/UserRoleService.java
index cd3ce455..83f7748e 100644
--- a/retail-managment-system/rms-api/src/main/java/com/rms/service/UserRoleService.java
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/service/UserRoleService.java
@@ -7,6 +7,8 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
+
+import java.util.List;
import java.util.Optional;
@Service
@@ -37,5 +39,8 @@ public Optional getRoleIdByUserIdAndRoleId(Integer userId,Integer roleI
public Page getByUserId(Integer userId ,Integer page , Integer size){
return userRoleRepository.findUserRoleByUserId(userId , PageRequest.of(page,size));
}
+ public List getRoleByUsername(String username){
+ return userRoleRepository.findByUserName(username);
+ }
}
diff --git a/retail-managment-system/rms-api/src/main/java/com/rms/service/UserService.java b/retail-managment-system/rms-api/src/main/java/com/rms/service/UserService.java
index 273d925a..9671c017 100644
--- a/retail-managment-system/rms-api/src/main/java/com/rms/service/UserService.java
+++ b/retail-managment-system/rms-api/src/main/java/com/rms/service/UserService.java
@@ -3,8 +3,10 @@
import com.rms.domain.security.User;
import com.rms.repository.UserRepository;
import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
+import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Optional;
@@ -12,30 +14,44 @@
@Service
@AllArgsConstructor
public class UserService {
+ private UserRepository userRepository;
- private UserRepository userRepository ;
+ @Autowired
+ private PasswordEncoder passwordEncoder;
- public Page getAll(Integer page , Integer size)
- {
- return userRepository.findAll(PageRequest.of(page,size));
+ public Page getAll(Integer page, Integer size) {
+ return userRepository.findAll(PageRequest.of(page, size));
}
- public Optional getById(int id)
- {
- return userRepository.findById(id);
+ public User save(User user) {
+ user.setPassword(passwordEncoder.encode(user.getPassword()));
+ return userRepository.save(user);
}
- public User save (User user)
- {
- return userRepository.save(user);
+ public Optional getById(Integer id) {
+ return userRepository.findById(id);
}
- public Optional findUserName(String userName) {
- return userRepository.findByUserName(userName);
+ public void update(User user) {
+ user.setPassword(passwordEncoder.encode(user.getPassword()));
+ userRepository.save(user);
}
- public void delete(User user)
- {
+ public void delete(User user) {
userRepository.delete(user);
}
+
+
+ public Optional findUsername(String username) {
+ return userRepository.checkUsername(username);
+ }
+
+ public Optional getByUserName(String username) {
+ return userRepository.findByUserName(username);
+ }
+
+
+
+
+
}
diff --git a/retail-managment-system/rms-api/src/main/resources/application.yml b/retail-managment-system/rms-api/src/main/resources/application.yml
index 5efb1cd9..f0e4e2ff 100644
--- a/retail-managment-system/rms-api/src/main/resources/application.yml
+++ b/retail-managment-system/rms-api/src/main/resources/application.yml
@@ -24,7 +24,7 @@ spring:
ddl-auto: none
properties:
- hibernate:
+ 9+hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
# default_schema: rms_core
show-sql: true
@@ -45,4 +45,15 @@ spring:
default-schema: public
-
+logging:
+ level:
+ org:
+ hibernate:
+ SQL: INFO
+ type: INFO
+app:
+ jwt:
+ token:
+ expiration-in-ms: 86400000
+ refresh:
+ expiration-in-ms: 108000000
\ No newline at end of file