Skip to content
Closed
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
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -48,6 +49,7 @@

@RestController
@RequestMapping(value = "/dataTemplate", headers = "Authorization")
@PreAuthorize("hasRole('SUPERVISOR')")
public class DataTemplateController {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
Expand All @@ -41,6 +42,7 @@
import io.swagger.v3.oas.annotations.responses.ApiResponses;

@RestController
@PreAuthorize("hasRole('SUPERVISOR')")
public class DataUploadController {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -41,7 +42,7 @@
import io.swagger.v3.oas.annotations.responses.ApiResponses;

@RestController
@RequestMapping(value = "/agent", headers = "Authorization")
@PreAuthorize("hasRole('SUPERVISOR') || hasRole('QUALITY_SUPERVISOR') || hasRole('QUALITY_AUDITOR')")
public class CallStatisticsController {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -48,6 +49,7 @@

@RestController
@RequestMapping(value = "/outbound-worklist", headers = "Authorization")
@PreAuthorize("hasRole('ANM') || hasRole('MO') || hasRole('ASSOCIATE')")
public class OutBoundWorklistController {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -44,6 +45,7 @@

@RestController
@RequestMapping(value = "/charts", headers = "Authorization")
@PreAuthorize("hasRole('SUPERVISOR') || hasRole('QUALITY_SUPERVISOR') || hasRole('QUALITY_AUDITOR')")
public class ChartsController {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -47,6 +48,7 @@

@RestController
@RequestMapping(value = "/gradeConfiguration", headers = "Authorization")
@PreAuthorize("hasRole('QUALITY_SUPERVISOR')")
public class GradeConfigurationController {

@Autowired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand Down Expand Up @@ -55,6 +55,7 @@

@RestController
@RequestMapping(value = "/qualityAudit", headers = "Authorization")
@PreAuthorize("hasRole('QUALITY_AUDITOR')")
public class QualityAuditController {
@Autowired
private QualityAuditImpl qualityAuditImpl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -48,6 +49,7 @@

@RestController
@RequestMapping(value = "/questionnaireConfiguration", headers = "Authorization")
@PreAuthorize("hasRole('QUALITY_SUPERVISOR') || hasRole('QUALITY_AUDITOR')")
public class QualityAuditQuestionConfigurationController {
@Autowired
private QualityAuditQuestionConfigurationImpl qualityAuditQuestionConfigurationImpl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -47,6 +48,7 @@

@RestController
@RequestMapping(value = "/sectionConfiguration", headers = "Authorization")
@PreAuthorize("hasRole('QUALITY_SUPERVISOR') || hasRole('QUALITY_AUDITOR')")
public class QualityAuditSectionConfigurationController {
@Autowired
private QualityAuditSectionConfigurationImpl qualityAuditSectionConfigurationImpl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -47,6 +48,7 @@

@RestController
@RequestMapping(value = "/sampleSelectionConfiguration", headers = "Authorization")
@PreAuthorize("hasRole('QUALITY_SUPERVISOR') || hasRole('QUALITY_AUDITOR')")
public class SampleSelectionConfigurationController {
@Autowired
private SampleSelectionConfigurationImpl sampleSelectionConfigurationImpl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand Down Expand Up @@ -56,6 +57,7 @@

@RestController
@RequestMapping(value = "/Questionnaire", headers = "Authorization")
@PreAuthorize("hasRole('SUPERVISOR')")
public class EcdQuestionareController {

@Autowired
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/com/iemr/ecd/repository/masters/RoleRepo.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@

import java.util.List;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import com.iemr.ecd.dao.masters.Role;
Expand All @@ -32,5 +34,6 @@
public interface RoleRepo extends CrudRepository<Role, Integer> {

List<Role> findByPsmIdAndDeleted(Integer psmId, Boolean deleted);

@Query(nativeQuery = true,value = "select rolename from m_role where roleid in (select roleid from m_userservicerolemapping where userid=:userID)")
List<String> getRoleNamebyUserId(@Param("userID") Long userID);
}
15 changes: 15 additions & 0 deletions src/main/java/com/iemr/ecd/service/masters/MasterServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,21 @@ public List<Frequency> getFrequency() {
public List<V_GetUserlangmapping> getLanguageByUserId(Integer userId) throws ECDException {
return v_GetUserlangmappingRepo.findByUserId(userId);
}

public List<String> getUserRoles(Long userId) {
if (null == userId || userId <= 0) {
throw new IllegalArgumentException("Invalid User ID : " + userId);
}
try {
List<String> role = roleRepo.getRoleNamebyUserId(userId);
if (null == role || role.isEmpty()) {
throw new ECDException("No role found for userId : " + userId);
}
return role;
} catch (Exception e) {
throw new ECDException("Failed to retrieverole for usedId : " + userId + " error : " + e.getMessage());
}
}


//gender master
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.iemr.ecd.utils.advice.exception_handler;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.Map;

@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {

private static final ObjectMapper mapper = new ObjectMapper();
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException {
response.setStatus(HttpServletResponse.SC_FORBIDDEN); // 403
response.setContentType("application/json");
Map<String, String> errorResponse = Map.of("error" , "Forbidden",
"message","Access denied");
response.getWriter().write(mapper.writeValueAsString(errorResponse));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.iemr.ecd.utils.advice.exception_handler;

import java.io.IOException;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401
response.setContentType("application/json");
response.getWriter().write("{\"error\": \"Unauthorized\", \"message\": \"" + authException.getMessage() + "\"}");
}
}
2 changes: 1 addition & 1 deletion src/main/java/com/iemr/ecd/utils/mapper/JwtUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
return claims != null ? claimsResolver.apply(claims) : null;
}

private Claims extractAllClaims(String token) {
public Claims extractAllClaims(String token) {
return Jwts.parser()
.verifyWith(getSigningKey())
.build()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.iemr.ecd.utils.mapper;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import com.iemr.ecd.service.masters.MasterServiceImpl;
import com.iemr.ecd.utils.constants.Constants;
import com.iemr.ecd.utils.redis.RedisStorage;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.io.IOException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Component
public class RoleAuthenticationFilter extends OncePerRequestFilter {
Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName());

@Autowired
private JwtUtil jwtUtil;

@Autowired
private RedisStorage redisService;

@Autowired
private MasterServiceImpl userService;

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException, java.io.IOException {
List<String> authRoles = null;
try {
String jwtFromCookie = CookieUtil.getJwtTokenFromCookie(request);
String jwtFromHeader = request.getHeader(Constants.JWT_TOKEN);

String jwtToken = jwtFromCookie != null ? jwtFromCookie : jwtFromHeader;
if(null == jwtToken || jwtToken.trim().isEmpty()) {
filterChain.doFilter(request, response);
return;
}
Claims extractAllClaims = jwtUtil.extractAllClaims(jwtToken);
if(null == extractAllClaims) {
filterChain.doFilter(request, response);
return;
}
Object userIdObj = extractAllClaims.get("userId");
String userId = userIdObj != null ? userIdObj.toString() : null;
if (null == userId || userId.trim().isEmpty()) {
filterChain.doFilter(request, response);
return;
}
Long userIdLong;
try {
userIdLong=Long.valueOf(userId);
}catch (NumberFormatException ex) {
logger.warn("Invalid userId format: {}",userId);
filterChain.doFilter(request, response);
return;
}
authRoles = redisService.getUserRoleFromCache(userIdLong);
if (authRoles == null || authRoles.isEmpty()) {
List<String> roles = userService.getUserRoles(Long.valueOf(userId)); // assuming this returns multiple roles
authRoles = roles.stream()
.filter(Objects::nonNull)
.map(String::trim)
.map(role -> "ROLE_" + role.toUpperCase().replace(" ", "_"))
.collect(Collectors.toList());
redisService.cacheUserRoles(Long.valueOf(userId), authRoles);
}

List<GrantedAuthority> authorities = authRoles.stream()
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());

UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userId, null, authorities);
SecurityContextHolder.getContext().setAuthentication(auth);
} catch (Exception e) {
logger.error("Authentication filter error for request {}: {}", request.getRequestURI(), e.getMessage());
SecurityContextHolder.clearContext();
} finally {
filterChain.doFilter(request, response);
}

}
}
Loading
Loading