diff --git a/pom.xml b/pom.xml
index 1e6d394a..b443ec18 100644
--- a/pom.xml
+++ b/pom.xml
@@ -212,6 +212,13 @@
8.0.5
+
+ io.springfox
+ springfox-boot-starter
+ 3.0.0
+
+
+
diff --git a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
index c21cceaf..49a49126 100644
--- a/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
+++ b/src/main/java/net/gepafin/tendermanagement/constants/GepafinConstant.java
@@ -225,6 +225,11 @@ public class GepafinConstant {
public static final String DD_MM_YYYY = "dd/MM/yyyy";
public static final String DASHBOARD_WIDGET_FETCHED_SUCCESSFULLY="dashboard.widget.fetched.successfully";
+ public static final Integer DEFAULT_PAGE_LIMIT = 1000;
+ public static final Integer DEFAULT_PAGE = 1;
+ public static final String ATTEMPT_DATE = "attemptDate";
+ public static final String LOGIN_ATTEMPTED_CREATED_SUCCESSFULLY="login_attempt_successfully_created";
+ public static final String GET_LOGIN_ATTEMPT_MSG="get_login_attempt_se_msg";
}
diff --git a/src/main/java/net/gepafin/tendermanagement/dao/LoginAttemptDao.java b/src/main/java/net/gepafin/tendermanagement/dao/LoginAttemptDao.java
new file mode 100644
index 00000000..509d4843
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/dao/LoginAttemptDao.java
@@ -0,0 +1,57 @@
+package net.gepafin.tendermanagement.dao;
+
+import net.gepafin.tendermanagement.config.Translator;
+import net.gepafin.tendermanagement.constants.GepafinConstant;
+import net.gepafin.tendermanagement.entities.LoginAttemptEntity;
+import net.gepafin.tendermanagement.model.response.LoginAttemptPageableResponseBean;
+import net.gepafin.tendermanagement.repositories.LoginAttemptRepository;
+import net.gepafin.tendermanagement.util.DateTimeUtil;
+import net.gepafin.tendermanagement.web.rest.api.errors.Status;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+public class LoginAttemptDao {
+
+ @Autowired
+ LoginAttemptRepository loginAttemptRepository;
+
+ public void createLoginAttempt(LoginAttemptEntity loginAttemptEntity) {
+ loginAttemptEntity.setAttemptDate(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
+
+ loginAttemptRepository.save(loginAttemptEntity);
+ }
+
+ public LoginAttemptPageableResponseBean> getLoginAttemptsList(Integer pageNo, Integer pageLimit) {
+ if (pageLimit == null || pageLimit <= 0) {
+ pageLimit = GepafinConstant.DEFAULT_PAGE_LIMIT;
+ }
+
+ if (pageNo == null || pageNo <= 0) {
+ pageNo = GepafinConstant.DEFAULT_PAGE;
+ }
+
+ Page page = loginAttemptRepository.findAll(PageRequest.of(pageNo - 1, pageLimit, Sort.by(GepafinConstant.ATTEMPT_DATE).descending()));
+ List list = new ArrayList<>();
+ for (LoginAttemptEntity loginAttemptEntity : page.getContent()) {
+ list.add(loginAttemptEntity);
+ }
+
+ LoginAttemptPageableResponseBean> pageableResponseBean = new LoginAttemptPageableResponseBean<>();
+ pageableResponseBean.setBody(list);
+ pageableResponseBean.setCurrentPage(page.getNumber() + 1);
+ pageableResponseBean.setTotalPages(page.getTotalPages());
+ pageableResponseBean.setTotalRecords(page.getTotalElements());
+ pageableResponseBean.setPageSize(page.getSize());
+ pageableResponseBean.setStatus(Status.SUCCESS);
+ pageableResponseBean.setMessage(Translator.toLocale(GepafinConstant.GET_LOGIN_ATTEMPT_MSG));
+ return pageableResponseBean;
+ }
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java
index 84440b5f..a796114a 100644
--- a/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java
+++ b/src/main/java/net/gepafin/tendermanagement/dao/UserDao.java
@@ -257,9 +257,9 @@ public class UserDao {
log.info("User deleted with ID: {}", id);
}
- public JWTToken login(LoginReq loginReq) {
+ public JWTToken login(LoginReq loginReq,HttpServletRequest request) {
log.info("User login attempt for email: {}", loginReq.getEmail());
- JWTToken jwtToken = authService.login(loginReq);
+ JWTToken jwtToken = authService.login(loginReq,request);
log.info("Login successful for email: {}", loginReq.getEmail());
return jwtToken;
}
@@ -354,4 +354,5 @@ public class UserDao {
return authService.validateNewUserToken(token);
}
+
}
diff --git a/src/main/java/net/gepafin/tendermanagement/entities/LoginAttemptEntity.java b/src/main/java/net/gepafin/tendermanagement/entities/LoginAttemptEntity.java
new file mode 100644
index 00000000..11fe1a99
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/entities/LoginAttemptEntity.java
@@ -0,0 +1,44 @@
+package net.gepafin.tendermanagement.entities;
+
+import jakarta.persistence.*;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.time.LocalDateTime;
+
+@Entity
+@Table(name = "LOGIN_ATTEMPT")
+@Getter
+@Setter
+public class LoginAttemptEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ @Column(name = "ID", unique = true)
+ private Long id;
+
+ @Column(name = "USERNAME")
+ private String username;
+
+ @Column(name = "USER_ID")
+ private Long userId;
+
+ @Column(name = "ATTEMPT_DATE", nullable = false)
+ private LocalDateTime attemptDate;
+
+ @Column(name = "IP_ADDRESS", length = 100)
+ private String ipAddress;
+
+ @Column(name = "USER_AGENT")
+ private String userAgent;
+
+ @Column(name = "RESULT", length = 100, nullable = false)
+ private String result;
+
+ @Column(name = "ERROR_MSG")
+ private String errorMsg;
+
+ @Column(name = "ATTEMPT_TYPE", length = 100, nullable = false)
+ private String type;
+
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/enums/LoginAttemptResultEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/LoginAttemptResultEnum.java
new file mode 100644
index 00000000..bd039eb5
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/enums/LoginAttemptResultEnum.java
@@ -0,0 +1,25 @@
+package net.gepafin.tendermanagement.enums;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+public enum LoginAttemptResultEnum {
+
+ SUCCESS("SUCCESS"),
+ FAILED("FAILED");
+
+ private String value;
+
+ LoginAttemptResultEnum(String value) {
+ this.value = value;
+ }
+
+ @JsonValue
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/gepafin/tendermanagement/enums/LoginAttemptTypeEnum.java b/src/main/java/net/gepafin/tendermanagement/enums/LoginAttemptTypeEnum.java
new file mode 100644
index 00000000..dc597e13
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/enums/LoginAttemptTypeEnum.java
@@ -0,0 +1,25 @@
+package net.gepafin.tendermanagement.enums;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+public enum LoginAttemptTypeEnum {
+
+ LOGIN("LOGIN"),
+ SWITCH("SWITCH");
+
+ private String value;
+
+ LoginAttemptTypeEnum(String value) {
+ this.value = value;
+ }
+
+ @JsonValue
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/gepafin/tendermanagement/model/request/LoginAttemptReq.java b/src/main/java/net/gepafin/tendermanagement/model/request/LoginAttemptReq.java
new file mode 100644
index 00000000..f7a48ad3
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/model/request/LoginAttemptReq.java
@@ -0,0 +1,18 @@
+package net.gepafin.tendermanagement.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+
+@Getter
+@Setter
+public class LoginAttemptReq {
+
+ private String userName;
+
+ @NotNull
+ private Long userId;
+}
+
diff --git a/src/main/java/net/gepafin/tendermanagement/model/response/LoginAttemptPageableResponseBean.java b/src/main/java/net/gepafin/tendermanagement/model/response/LoginAttemptPageableResponseBean.java
new file mode 100644
index 00000000..d28d1fd2
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/model/response/LoginAttemptPageableResponseBean.java
@@ -0,0 +1,38 @@
+package net.gepafin.tendermanagement.model.response;
+
+import lombok.Getter;
+import lombok.Setter;
+import net.gepafin.tendermanagement.web.rest.api.errors.Status;
+
+import java.io.Serializable;
+
+@Getter
+@Setter
+public class LoginAttemptPageableResponseBean implements Serializable {
+
+ private transient T body;
+
+ private Long totalRecords;
+
+ private int currentPage;
+
+ private int totalPages;
+
+ private int pageSize;
+
+ private Status status;
+
+ private String message;
+
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/net/gepafin/tendermanagement/repositories/LoginAttemptRepository.java b/src/main/java/net/gepafin/tendermanagement/repositories/LoginAttemptRepository.java
new file mode 100644
index 00000000..257b8ed8
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/repositories/LoginAttemptRepository.java
@@ -0,0 +1,9 @@
+package net.gepafin.tendermanagement.repositories;
+
+import net.gepafin.tendermanagement.entities.LoginAttemptEntity;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface LoginAttemptRepository extends JpaRepository {
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/service/LoginAttemptService.java b/src/main/java/net/gepafin/tendermanagement/service/LoginAttemptService.java
new file mode 100644
index 00000000..3e4ed31a
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/service/LoginAttemptService.java
@@ -0,0 +1,15 @@
+package net.gepafin.tendermanagement.service;
+
+import jakarta.servlet.http.HttpServletRequest;
+import net.gepafin.tendermanagement.entities.LoginAttemptEntity;
+import net.gepafin.tendermanagement.model.request.LoginAttemptReq;
+import net.gepafin.tendermanagement.model.response.LoginAttemptPageableResponseBean;
+
+import java.util.List;
+
+public interface LoginAttemptService {
+
+ LoginAttemptPageableResponseBean> getLoginAttemptsList(Integer pageNo, Integer pageLimit);
+
+ void createLoginAttempt(LoginAttemptReq loginAttemptReq, HttpServletRequest request);
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/service/UserService.java b/src/main/java/net/gepafin/tendermanagement/service/UserService.java
index 47116eed..b9fc2072 100644
--- a/src/main/java/net/gepafin/tendermanagement/service/UserService.java
+++ b/src/main/java/net/gepafin/tendermanagement/service/UserService.java
@@ -21,7 +21,7 @@ public interface UserService {
void deleteUser(Long userId);
- JWTToken login(LoginReq loginReq);
+ JWTToken login(LoginReq loginReq,HttpServletRequest request);
UserEntity validateUser(Long userId);
@@ -41,4 +41,7 @@ public interface UserService {
UserSamlResponse validateNewUserToken(HttpServletRequest request, String token);
UserEntity getUserByBeneficiaryId(Long beneficiaryId);
+
+ public UserEntity getUserEntityById(Long userId);
+
}
diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java
index 4153c2f2..1cb87645 100644
--- a/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java
+++ b/src/main/java/net/gepafin/tendermanagement/service/impl/AuthenticationService.java
@@ -6,9 +6,13 @@ import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.config.jwt.TokenProvider;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.dao.CompanyDao;
+import net.gepafin.tendermanagement.dao.LoginAttemptDao;
import net.gepafin.tendermanagement.dao.RoleDao;
+import net.gepafin.tendermanagement.entities.LoginAttemptEntity;
import net.gepafin.tendermanagement.entities.SamlResponseEntity;
import net.gepafin.tendermanagement.entities.UserEntity;
+import net.gepafin.tendermanagement.enums.LoginAttemptResultEnum;
+import net.gepafin.tendermanagement.enums.LoginAttemptTypeEnum;
import net.gepafin.tendermanagement.enums.UserStatusEnum;
import net.gepafin.tendermanagement.model.request.LoginReq;
import net.gepafin.tendermanagement.model.response.CompanyResponse;
@@ -57,29 +61,61 @@ public class AuthenticationService {
@Autowired
private SamlResponseRepository samlResponseLogRepository;
+ @Autowired
+ private LoginAttemptDao loginAttemptDao;
+
@Autowired
public AuthenticationService(TokenProvider tokenProvider, AuthenticationManager authenticationManager) {
this.tokenProvider = tokenProvider;
this.authenticationManager = authenticationManager;
}
- public JWTToken login(LoginReq loginReq) {
- log.info("Attempting login for email: {}", loginReq.getEmail());
- UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
- loginReq.getEmail(), loginReq.getPassword());
- Authentication authentication = this.authenticationManager.authenticate(authenticationToken);
- SecurityContextHolder.getContext().setAuthentication(authentication);
- log.info("Authentication successful for email: {}", loginReq.getEmail());
- UserEntity user = userRepository.findByEmailIgnoreCase(loginReq.getEmail())
- .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,
- Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)));
- if (Boolean.FALSE.equals(UserStatusEnum.ACTIVE.getValue().equals(user.getStatus()))) {
- throw new ResourceNotFoundException(Status.NOT_FOUND,
- Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG));
+ public JWTToken login(LoginReq loginReq,HttpServletRequest request) {
+ UserEntity user=null;
+ try {
+ LoginAttemptEntity loginAttemptEntity = prepareLoginAttemptEntity(loginReq, request);
+ log.info("Attempting login for email: {}", loginReq.getEmail());
+ UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
+ loginReq.getEmail(), loginReq.getPassword());
+ Authentication authentication = this.authenticationManager.authenticate(authenticationToken);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ log.info("Authentication successful for email: {}", loginReq.getEmail());
+ user = userRepository.findByEmailIgnoreCase(loginReq.getEmail())
+ .orElseThrow(() -> new ResourceNotFoundException(Status.NOT_FOUND,
+ Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG)));
+ loginAttemptEntity.setUserId(user.getId());
+ if (Boolean.FALSE.equals(UserStatusEnum.ACTIVE.getValue().equals(user.getStatus()))) {
+ throw new ResourceNotFoundException(Status.NOT_FOUND,
+ Translator.toLocale(GepafinConstant.USER_NOT_FOUND_MSG));
+ }
+ createSuccessLoginAttempt(loginAttemptEntity);
+ } catch (Exception e) {
+
+
}
return getJWTTokenBean(user, loginReq.getRememberMe());
}
-
+
+ private LoginAttemptEntity prepareLoginAttemptEntity(LoginReq loginUserReq, HttpServletRequest request) {
+ String ipAddress = Utils.getClientIpAddress(request);
+ String userAgent = request.getHeader("user-agent");
+ LoginAttemptEntity loginAttemptEntity = new LoginAttemptEntity();
+ loginAttemptEntity.setType(LoginAttemptTypeEnum.LOGIN.getValue());
+ loginAttemptEntity.setUsername(loginUserReq.getEmail());
+ loginAttemptEntity.setIpAddress(ipAddress);
+ loginAttemptEntity.setUserAgent(userAgent);
+ return loginAttemptEntity;
+ }
+
+ private void createSuccessLoginAttempt(LoginAttemptEntity loginAttemptEntity) {
+ loginAttemptEntity.setResult(LoginAttemptResultEnum.SUCCESS.getValue());
+ loginAttemptDao.createLoginAttempt(loginAttemptEntity);
+ }
+ private void createFailedLoginAttempt(LoginAttemptEntity loginAttemptEntity, String errorMsg) {
+ loginAttemptEntity.setResult(LoginAttemptResultEnum.FAILED.getValue());
+ loginAttemptEntity.setErrorMsg(errorMsg);
+ loginAttemptDao.createLoginAttempt(loginAttemptEntity);
+ }
public JWTToken getJWTTokenBean(UserEntity user, Boolean rememberMe) {
user.setLastLogin(DateTimeUtil.DateServerToUTC(LocalDateTime.now()));
userRepository.save(user);
diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/LoginAttemptServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/LoginAttemptServiceImpl.java
new file mode 100644
index 00000000..1519273f
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/service/impl/LoginAttemptServiceImpl.java
@@ -0,0 +1,40 @@
+package net.gepafin.tendermanagement.service.impl;
+
+import jakarta.servlet.http.HttpServletRequest;
+import net.gepafin.tendermanagement.dao.LoginAttemptDao;
+import net.gepafin.tendermanagement.entities.LoginAttemptEntity;
+import net.gepafin.tendermanagement.enums.LoginAttemptResultEnum;
+import net.gepafin.tendermanagement.enums.LoginAttemptTypeEnum;
+import net.gepafin.tendermanagement.model.request.LoginAttemptReq;
+import net.gepafin.tendermanagement.model.response.LoginAttemptPageableResponseBean;
+import net.gepafin.tendermanagement.service.LoginAttemptService;
+import net.gepafin.tendermanagement.util.Utils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class LoginAttemptServiceImpl implements LoginAttemptService {
+
+ @Autowired
+ LoginAttemptDao loginAttemptDao;
+
+ @Override
+ public LoginAttemptPageableResponseBean> getLoginAttemptsList(Integer pageNo, Integer pageLimit) {
+ return loginAttemptDao.getLoginAttemptsList(pageNo, pageLimit);
+ }
+
+ @Override
+ public void createLoginAttempt(LoginAttemptReq loginAttemptReq, HttpServletRequest request) {
+ String ipAddress = Utils.getClientIpAddress(request);
+ String userAgent = request.getHeader("user-agent");
+ LoginAttemptEntity loginAttemptEntity = new LoginAttemptEntity();
+ loginAttemptEntity.setType(LoginAttemptTypeEnum.SWITCH.getValue());
+ loginAttemptEntity.setIpAddress(ipAddress);
+ loginAttemptEntity.setUserAgent(userAgent);
+ loginAttemptEntity.setUsername(loginAttemptReq.getUserName());
+ loginAttemptEntity.setResult(LoginAttemptResultEnum.SUCCESS.getValue());
+ loginAttemptDao.createLoginAttempt(loginAttemptEntity);
+ }
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java
index fbfdbc0b..63c0f88e 100644
--- a/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java
+++ b/src/main/java/net/gepafin/tendermanagement/service/impl/UserServiceImpl.java
@@ -66,8 +66,8 @@ public class UserServiceImpl implements UserService {
}
@Override
- public JWTToken login(LoginReq loginReq) {
- return userDao.login(loginReq);
+ public JWTToken login(LoginReq loginReq,HttpServletRequest request) {
+ return userDao.login(loginReq,request);
}
@@ -119,4 +119,9 @@ public class UserServiceImpl implements UserService {
public UserEntity getUserByBeneficiaryId(Long beneficiaryId) {
return userDao.getUserByBeneficiaryId(beneficiaryId);
}
+ @Override
+ public UserEntity getUserEntityById(Long userId) {
+ // Calling DAO Function
+ return userDao.validateUser(userId);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/net/gepafin/tendermanagement/util/Utils.java b/src/main/java/net/gepafin/tendermanagement/util/Utils.java
index d7da174b..767872ce 100644
--- a/src/main/java/net/gepafin/tendermanagement/util/Utils.java
+++ b/src/main/java/net/gepafin/tendermanagement/util/Utils.java
@@ -4,15 +4,13 @@ import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
-import java.util.Base64;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -302,5 +300,12 @@ public class Utils {
private static String replaceNull(String text, String target, String replacement) {
return text.replace(target, replacement != null ? replacement : "");
}
+ public static String getClientIpAddress(HttpServletRequest request) {
+ String header = request.getHeader("X-Forwarded-For");
+ if (org.apache.commons.lang3.StringUtils.isBlank(header)) {
+ return request.getRemoteAddr();
+ }
+ return new StringTokenizer(header, ",").nextToken().trim();
+ }
}
diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/LoginAttemptApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/LoginAttemptApi.java
new file mode 100644
index 00000000..379a1d05
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/LoginAttemptApi.java
@@ -0,0 +1,60 @@
+package net.gepafin.tendermanagement.web.rest.api;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.ExampleObject;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.validation.Valid;
+import io.swagger.annotations.ApiParam;
+import net.gepafin.tendermanagement.entities.LoginAttemptEntity;
+import net.gepafin.tendermanagement.model.request.LoginAttemptReq;
+import net.gepafin.tendermanagement.model.response.LoginAttemptPageableResponseBean;
+import net.gepafin.tendermanagement.model.util.Response;
+import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.context.request.NativeWebRequest;
+
+import java.util.List;
+import java.util.Optional;
+
+@Validated
+public interface LoginAttemptApi {
+
+ default Optional getRequest() {
+ return Optional.empty();
+ }
+
+ @Operation(summary = "Api to get list of login attempts", responses = {
+ @ApiResponse(responseCode = "200", description = "OK"),
+ @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
+ @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
+ @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
+ @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
+ @GetMapping(value = "/login-attempt", produces = {"application/json"})
+ @PreAuthorize("hasRole('ROLE_SUPER_ADMIN')")
+ default ResponseEntity>> getLoginAttemptsList(
+ @ApiParam(value = "page number") @RequestParam(name = "pageNo", required = false) Integer pageNo,
+ @ApiParam(value = "page limit") @RequestParam(name = "pageLimit", required = false) Integer pageLimit) {
+ return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+ }
+
+ @Operation(summary = "Api to create a login attempt", responses = {
+ @ApiResponse(responseCode = "201", description = "Created"),
+ @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
+ @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE)})),
+ @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
+ @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE)}))})
+ @PostMapping(value = "/login-attempt", consumes = {"application/json"})
+ default ResponseEntity> createLoginAttempt(@ApiParam(value = "login attempt request", required = true) @Valid @RequestBody LoginAttemptReq loginAttemptReq, HttpServletRequest request) {
+ return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
+ }
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/PdfApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/PdfApi.java
deleted file mode 100644
index a8f7ea48..00000000
--- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/PdfApi.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package net.gepafin.tendermanagement.web.rest.api;
-
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.ExampleObject;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import jakarta.servlet.http.HttpServletRequest;
-import net.gepafin.tendermanagement.web.rest.api.errors.ErrorConstants;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-
-@Validated
-public interface PdfApi {
-
- @Operation(summary = "API to generate PDF for an application",
- responses = {
- @ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/pdf")),
- @ApiResponse(responseCode = "404", description = "Not Found", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
- @ExampleObject(value = ErrorConstants.NOTFOUND_ERROR_EXAMPLE) })),
- @ApiResponse(responseCode = "401", description = "Unauthorized", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
- @ExampleObject(value = ErrorConstants.UNAUTHORIZED_ERROR_EXAMPLE) })),
- @ApiResponse(responseCode = "400", description = "Bad Request", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, examples = {
- @ExampleObject(value = ErrorConstants.BADREQUEST_ERROR_EXAMPLE) }))
- })
- @PostMapping(value = "/{applicationId}/generate-pdf",
- produces = { "application/pdf" })
- public ResponseEntity generateApplicationPdf(
- HttpServletRequest request,
- @Parameter(description = "The application id", required = true)
- @PathVariable(value = "applicationId", required = true) Long applicationId);
-}
diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java
index 6bb6a388..32f34963 100644
--- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java
+++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/UserApi.java
@@ -104,7 +104,7 @@ public interface UserApi {
@RequestMapping(value = "/login",
produces = {"application/json"},
method = RequestMethod.POST)
- ResponseEntity> login(
+ ResponseEntity> login(HttpServletRequest request,
@Parameter(description = "Login request object", required = true) @Valid @RequestBody LoginReq loginReq);
@Operation(summary = "Api to initiate password reset request",
responses = {
diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/LoginAttemptApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/LoginAttemptApiController.java
new file mode 100644
index 00000000..ed3a048b
--- /dev/null
+++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/LoginAttemptApiController.java
@@ -0,0 +1,56 @@
+package net.gepafin.tendermanagement.web.rest.api.impl;
+
+import jakarta.servlet.http.HttpServletRequest;
+import net.gepafin.tendermanagement.config.Translator;
+import net.gepafin.tendermanagement.constants.GepafinConstant;
+import net.gepafin.tendermanagement.entities.LoginAttemptEntity;
+import net.gepafin.tendermanagement.entities.UserEntity;
+import net.gepafin.tendermanagement.model.request.LoginAttemptReq;
+import net.gepafin.tendermanagement.model.response.LoginAttemptPageableResponseBean;
+import net.gepafin.tendermanagement.model.util.Response;
+import net.gepafin.tendermanagement.service.LoginAttemptService;
+import net.gepafin.tendermanagement.service.UserService;
+import net.gepafin.tendermanagement.util.Validator;
+import net.gepafin.tendermanagement.web.rest.api.LoginAttemptApi;
+import net.gepafin.tendermanagement.web.rest.api.errors.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("${openapi.gepafin.base-path:/v1/loginAttempt}")
+public class LoginAttemptApiController implements LoginAttemptApi {
+
+ public final Logger log = LoggerFactory.getLogger(LoginAttemptApiController.class);
+ @Autowired
+ Validator validator;
+
+ @Autowired
+ private LoginAttemptService loginAttemptService;
+
+ @Autowired
+ private UserService userService;
+
+ @Override
+ public ResponseEntity>> getLoginAttemptsList(Integer pageNo, Integer pageLimit) {
+ LoginAttemptPageableResponseBean> response = loginAttemptService.getLoginAttemptsList(pageNo, pageLimit);
+ return ResponseEntity.status(HttpStatus.OK).body(response);
+ }
+
+ @Override
+ public ResponseEntity> createLoginAttempt(LoginAttemptReq loginAttemptReq, HttpServletRequest request) {
+ Map userInfo = validator.getUserInfoFromToken(request);
+ String userIdString = (String) userInfo.get("userId");
+ UserEntity currentUser = userService.getUserEntityById(Long.parseLong(userIdString));
+ loginAttemptReq.setUserName(currentUser.getEmail());
+ loginAttemptService.createLoginAttempt(loginAttemptReq, request);
+ return ResponseEntity.status(HttpStatus.CREATED).body(new Response(null, Status.SUCCESS, Translator.toLocale(GepafinConstant.LOGIN_ATTEMPTED_CREATED_SUCCESSFULLY)));
+ }
+}
diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/PdfController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/PdfController.java
deleted file mode 100644
index f14451ed..00000000
--- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/PdfController.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package net.gepafin.tendermanagement.web.rest.api.impl;
-
-import com.itextpdf.text.*;
-import com.itextpdf.text.pdf.*;
-import jakarta.servlet.http.HttpServletRequest;
-import net.gepafin.tendermanagement.dao.RoundedCorners;
-import net.gepafin.tendermanagement.service.PdfService;
-import net.gepafin.tendermanagement.web.rest.api.PdfApi;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-
-@RestController
-public class PdfController implements PdfApi {
-
- @Autowired
- private PdfService pdfService;
-
- @Override
- public ResponseEntity generateApplicationPdf(HttpServletRequest request, Long applicationId) {
- byte[] pdfBytes =pdfService.generatePdf(request,applicationId);
-
- // Prepare headers for downloading the PDF
- HttpHeaders headers = new HttpHeaders();
- headers.add("Content-Disposition", "attachment; filename=bando-preview.pdf");
-
- // Return the PDF as a response
- return ResponseEntity.ok()
- .headers(headers)
- .contentType(MediaType.APPLICATION_PDF)
- .body(pdfBytes);
- }
-}
-
diff --git a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java
index 4ffd3e87..c6c57b0d 100644
--- a/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java
+++ b/src/main/java/net/gepafin/tendermanagement/web/rest/api/impl/UserApiController.java
@@ -70,10 +70,10 @@ public class UserApiController implements UserApi {
}
@Override
- public ResponseEntity> login(
+ public ResponseEntity> login(HttpServletRequest request,
@Valid @RequestBody LoginReq loginReq) {
log.info("User login attempt ");
- JWTToken jwtToken = userService.login(loginReq);
+ JWTToken jwtToken = userService.login(loginReq,request);
return ResponseEntity.ok(new Response<>(jwtToken, Status.SUCCESS, Translator.toLocale(GepafinConstant.LOGIN_SUCCESS_MSG)));
}
@Override
diff --git a/src/main/resources/db/changelog/db.changelog-1.0.0.xml b/src/main/resources/db/changelog/db.changelog-1.0.0.xml
index 03f3d5db..eceb9426 100644
--- a/src/main/resources/db/changelog/db.changelog-1.0.0.xml
+++ b/src/main/resources/db/changelog/db.changelog-1.0.0.xml
@@ -1052,4 +1052,35 @@
path="db/dump/update_system_email_template_of_application_submission.sql" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/message_en.properties b/src/main/resources/message_en.properties
index 31a22928..2e384261 100644
--- a/src/main/resources/message_en.properties
+++ b/src/main/resources/message_en.properties
@@ -248,5 +248,7 @@ application.signed.document.not.found=Signed document for the application not fo
delete.signed.document.file.success=Signed document deleted successfully.
dashboard.widget.fetched.successfully=Dasboard widget fetched sucessfully.
+login_attempt_successfully_created = Login attempt successfully created.
+get_login_attempt_se_msg=Login attempts fetched successfully.
diff --git a/src/main/resources/message_it.properties b/src/main/resources/message_it.properties
index 74b6e2b7..022c23db 100644
--- a/src/main/resources/message_it.properties
+++ b/src/main/resources/message_it.properties
@@ -244,4 +244,6 @@ application.signed.document.not.found=Documento firmato per l'applicazione non t
delete.signed.document.file.success=Documento firmato eliminato con successo.
dashboard.widget.fetched.successfully=Widget dashboard recuperato correttamente.
+login_attempt_successfully_created= Tentativo di login creato con successo.
+get_login_attempt_se_msg=Lista dei tentativi di accesso recuperata correttamente.