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
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ public String superUserAuthenticate(
response.setResponse(responseObj.toString());
} catch (Exception e) {
logger.error("userAuthenticate failed with error " + e.getMessage(), e);
response.setError(5000, "Authentication failed. Please try again later."); // Generic fallback
response.setError(e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Security concern: Direct exception propagation may leak sensitive information.

Propagating raw exceptions directly to the response could expose internal system details, stack traces, or database information that attackers could exploit. This contradicts the PR's objective of preventing information leakage.

Consider maintaining generic error messages for client responses while logging detailed exceptions server-side:

} catch (Exception e) {
    logger.error("userAuthenticate failed with error " + e.getMessage(), e);
-    response.setError(e);
+    response.setError(5000, "Authentication failed. Please try again.");
}

Also applies to: 648-648, 737-737, 755-755, 1061-1061, 1079-1079, 1163-1163

πŸ€– Prompt for AI Agents
In src/main/java/com/iemr/common/controller/users/IEMRAdminController.java at
line 522 and similarly at lines 648, 737, 755, 1061, 1079, and 1163, avoid
setting raw exceptions directly in the response to prevent leaking sensitive
internal details. Instead, log the full exception details on the server side for
debugging, and set a generic, non-sensitive error message in the response object
to safely inform the client of an error without exposing system internals.

}
logger.info("userAuthenticate response " + response.toString());
return response.toString();
Expand Down Expand Up @@ -620,10 +620,10 @@ public String forgetPassword(

if (mUsers == null || mUsers.size() <= 0) {
logger.error("User not found");
throw new IEMRException("Request failed, please try again later");
throw new IEMRException("If the username is registered, you will be asked a security question");
} else if (mUsers.size() > 1) {
logger.error("More than 1 user found");
throw new IEMRException("Request failed. Please retry again");
throw new IEMRException("If the username is registered, you will be asked a security question");

} else if (mUsers.size() == 1) {
List<Map<String, String>> quesAnsList = new ArrayList<>();
Expand All @@ -645,7 +645,7 @@ public String forgetPassword(
}
} catch (Exception e) {
logger.error("forgetPassword failed with error " + e.getMessage(), e);
response.setError(5000, "ForgetPassword failed.");
response.setError(e);
}
logger.info("forgetPassword response " + response.toString());
return response.toString();
Expand Down Expand Up @@ -734,7 +734,7 @@ public String changePassword(
response.setResponse(changeReqResult);
} catch (Exception e) {
logger.error("changePassword failed with error " + e.getMessage(), e);
response.setError(5000, "Password change failed. Please try again later.");
response.setError(e);
}
logger.info("changePassword response " + response.toString());
return response.toString();
Expand All @@ -752,7 +752,7 @@ public String saveUserSecurityQuesAns(
response.setResponse(responseData);
} catch (Exception e) {
logger.error("saveUserSecurityQuesAns failed with error " + e.getMessage(), e);
response.setError(5000, "Failed to save security questions. Please try again later.");
response.setError(e);
}
logger.info("saveUserSecurityQuesAns response " + response.toString());
return response.toString();
Expand Down Expand Up @@ -1058,7 +1058,7 @@ public String userAuthenticateByEncryption(
response.setResponse(responseObj.toString());
} catch (Exception e) {
logger.error("userAuthenticateByEncryption failed with error " + e.getMessage(), e);
response.setError(5000, "Request failed. Please try again.");
response.setError(e);
}
logger.info("userAuthenticateByEncryption response " + response.toString());
return response.toString();
Expand All @@ -1076,7 +1076,7 @@ public String getrolewrapuptime(@PathVariable("roleID") Integer roleID) {
}
response.setResponse(test.toString());
} catch (Exception e) {
response.setError(5000, "Request failed. Please try again.");
response.setError(e);
}
return response.toString();
}
Expand Down Expand Up @@ -1104,7 +1104,7 @@ public String validateSecurityQuestionAndAnswer(
throw new IEMRException("Invalid Request");
} catch (Exception e) {
logger.error("validateSecurityQuestionAndAnswer failed: {}", e.toString());
response.setError(5000, "Request failed. Please try again.");
response.setError(5000, e.getMessage());
}
logger.info("validateSecurityQuestionAndAnswer API response" + response.toString());
return response.toString();
Expand Down Expand Up @@ -1160,7 +1160,7 @@ public String userAuthenticateBhavya(
response.setResponse(responseObj.toString());
} catch (Exception e) {
logger.error("userAuthenticate failed with error " + e.getMessage(), e);
response.setError(5000, "Authentication failed. Please try again.");
response.setError(e);
}
logger.info("userAuthenticate response " + response.toString());
return response.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ public class KMFileManager {
@Transient
@Expose
private Integer categoryID;
@Transient

@Column(name = "SubCategoryID")
@Expose
private Integer subCategoryID;
@Transient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ public class GrievanceWorklistDTO implements Serializable {
private String age;
private Boolean retryNeeded;
private Integer callCounter;
private Timestamp lastCall;
private Timestamp lastCall;
private Boolean beneficiaryConsent;

public GrievanceWorklistDTO(String complaintID,Long grievanceId, String subjectOfComplaint, String complaint,
Long beneficiaryRegID, Integer providerServiceMapID,String primaryNumber,String severety,String state,
Integer userId, Boolean deleted, String createdBy, Timestamp createdDate, Timestamp lastModDate,
Boolean isCompleted,String firstName, String lastName, String gender, String district, Long beneficiaryID, String age,
Boolean retryNeeded, Integer callCounter, Timestamp lastCall) {
Boolean retryNeeded, Integer callCounter, Timestamp lastCall, Boolean beneficiaryConsent) {
super();
this.complaintID = complaintID;
this.grievanceId = grievanceId;
Expand All @@ -71,6 +72,7 @@ public GrievanceWorklistDTO(String complaintID,Long grievanceId, String subjectO
this.retryNeeded = retryNeeded;
this.callCounter = callCounter;
this.lastCall = lastCall;
this.beneficiaryConsent = beneficiaryConsent;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,9 @@ ArrayList<KMFileManager> getKMFileLists(@Param("providerServiceMapID") Integer p
@Query("select kmFileManager.fileName, kmFileManager.fileExtension from KMFileManager kmFileManager "
+ "where kmFileManager.fileUID = :fileUID")
List<Object[]> getFileNameByUID(@Param("fileUID") String fileUID);


@Query("SELECT km FROM KMFileManager km WHERE km.subCategoryID = :subCategoryID AND km.deleted = false")
List<KMFileManager> getFilesBySubCategoryID(@Param("subCategoryID") Integer subCategoryID);

}
Original file line number Diff line number Diff line change
Expand Up @@ -579,41 +579,48 @@ public String completeGrievanceCall(String request) throws Exception {

// Logic for reattempt based on call group type and call type
boolean isRetryNeeded = grievanceCallStatus.getRetryNeeded();
if ((null != grievanceCallStatus.getComplaintResolution()
&& grievanceCallStatus.getComplaintResolution().equalsIgnoreCase("Resolved")) || (callGroupType.equalsIgnoreCase("Valid") && (callType.equalsIgnoreCase("Valid") || callType.equals("Test Call")))) {
boolean isResolved = grievanceCallStatus.getComplaintResolution() != null
&& grievanceCallStatus.getComplaintResolution().equalsIgnoreCase("Resolved");
boolean isValidGroup = callGroupType.equalsIgnoreCase("Valid")
&& (callType.equalsIgnoreCase("Valid") || callType.equals("Test Call"));
boolean isInvalidGroup = callGroupType.equalsIgnoreCase("Invalid")
&& (callType.equalsIgnoreCase("Wrong Number") || callType.equalsIgnoreCase("Invalid Call"));

if (isResolved) {
// 1) Any resolved call β†’ complete, no retry
isRetryNeeded = false;
updateCount = grievanceDataRepo.updateCompletedStatusInCall(true, false, complaintID, userID, beneficiaryRegID);
}
else if (callGroupType.equalsIgnoreCase("Invalid") && (callType.equalsIgnoreCase("Wrong Number") || callType.equalsIgnoreCase("Invalid Call"))) {

} else if (isValidGroup) {
// 2) Valid but not resolved β†’ leave open, retry allowed
isRetryNeeded = true;
updateCount = grievanceDataRepo.updateCompletedStatusInCall(false, true, complaintID, userID, beneficiaryRegID);

} else if (isInvalidGroup) {
// 3) Invalid calls β†’ complete, no retry
isRetryNeeded = false;
updateCount = grievanceDataRepo.updateCompletedStatusInCall(true, isRetryNeeded, complaintID, userID,
beneficiaryRegID);
}else {
updateCount = grievanceDataRepo.updateCompletedStatusInCall(true, false, complaintID, userID, beneficiaryRegID);

} else {
// 4) All other cases (e.g. unreachable) β†’ leave open, retry allowed
isRetryNeeded = true;
updateCount = grievanceDataRepo.updateCompletedStatusInCall(false, isRetryNeeded, complaintID,
userID, beneficiaryRegID);
updateCount = grievanceDataRepo.updateCompletedStatusInCall(false, true, complaintID, userID, beneficiaryRegID);
}
// Check if max attempts (3) are reached

//Call counter update
if (isRetryNeeded && grievanceCallStatus.getCallCounter() < grievanceAllocationRetryConfiguration) {
grievanceCallStatus.setCallCounter(grievanceCallStatus.getCallCounter() + 1);
updateCallCounter = grievanceDataRepo.updateCallCounter(grievanceCallStatus.getCallCounter(),
isRetryNeeded, grievanceCallRequest.getComplaintID(),
grievanceCallRequest.getBeneficiaryRegID(),
grievanceCallRequest.getUserID());
if (updateCallCounter > 0)
response = "Successfully closing call";
else {
response = "failure in closing call";
}
} else if (grievanceCallStatus.getCallCounter() == grievanceAllocationRetryConfiguration) {
// Max attempts reached, no further reattempt
updateCallCounter = grievanceDataRepo.updateCallCounter(
grievanceCallStatus.getCallCounter(), true, complaintID, beneficiaryRegID, userID);
response = (updateCallCounter > 0) ? "Successfully closing call" : "failure in closing call";

} else if (grievanceCallStatus.getCallCounter() >= grievanceAllocationRetryConfiguration) {
// Max attempts reached β†’ treated as β€œcomplete”
isRetryNeeded = false;
// isCompleted = true;
updateCount = grievanceDataRepo.updateCompletedStatusInCall(isCompleted, isRetryNeeded, complaintID,
userID, beneficiaryRegID);
response = "max_attempts_reached"; // Indicate that max attempts are reached
updateCount = grievanceDataRepo.updateCompletedStatusInCall(true, false, complaintID, userID, beneficiaryRegID);
response = "max_attempts_reached";

}else if(updateCount > 0) {
} else if (updateCount > 0) {
response = "Successfully closing call";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ public List<GrievanceWorklistDTO> getFormattedGrievanceData(String request) thro

// Loop through the worklist data and format the response
for (Object[] row : worklistData) {
if (row == null || row.length < 22)
if (row == null || row.length < 24)
{
logger.warn("invalid row data received");
continue;
Expand Down Expand Up @@ -334,7 +334,8 @@ public List<GrievanceWorklistDTO> getFormattedGrievanceData(String request) thro
ageFormatted,
(Boolean) row[21], // retryNeeded
(Integer) row[22], // callCounter
(Timestamp) row[13] //lastCall
(Timestamp) row[13], // lastCall
(Boolean) row[23] //beneficiaryConsent
Comment on lines +337 to +338
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’‘ Verification agent

🧩 Analysis chain

Verify lastCall field assignment.

The lastCall field is being assigned row[13] which is the same as lastModDate. This seems incorrect - lastCall should likely be assigned a separate timestamp field from the database query result.


🏁 Script executed:

#!/bin/bash
# Description: Check the database query or stored procedure that populates the worklistData to understand the correct field mapping
# Expected: Find the query definition to verify what row[13] actually represents and if there's a separate lastCall field

# Search for the stored procedure or query definition that provides worklistData
rg -A 10 -B 5 "getGrievanceWorklistData|grievance.*worklist.*data" --type java

# Look for any SQL queries or native queries that might show the field order
ast-grep --pattern 'nativeQuery = $_'

Length of output: 3892


To verify the field ordering, let’s pull in the full mapping block around those row[...] assignments:


🏁 Script executed:

#!/bin/bash
# Extract the array-to-DTO mapping in GrievanceHandlingServiceImpl
sed -n '300,380p' src/main/java/com/iemr/common/service/grievance/GrievanceHandlingServiceImpl.java

Length of output: 4023


Fix incorrect lastCall mapping in GrievanceWorklistDTO constructor

The lastCall field is currently pulling from row[13] (which is already used for lastModDate), so it’s wrong. You’ll need to update it to the correct index from your stored-procedure result set and shift the beneficiaryConsent index accordingly.

β€’ File: src/main/java/com/iemr/common/service/grievance/GrievanceHandlingServiceImpl.java
β€’ Around lines 337–338 in the new GrievanceWorklistDTO(…) mapping

Suggested diff (adjust indices to match your procedure’s column order):

-               (Timestamp) row[13], // lastCall
-               (Boolean)   row[23]  // beneficiaryConsent
+               (Timestamp) row[23], // lastCall
+               (Boolean)   row[24]  // beneficiaryConsent

Please verify the actual column positions in Pr_Grievanceworklist and update the indices accordingly to prevent data mix-ups.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(Timestamp) row[13], // lastCall
(Boolean) row[23] //beneficiaryConsent
(Timestamp) row[23], // lastCall
(Boolean) row[24] // beneficiaryConsent
πŸ€– Prompt for AI Agents
In
src/main/java/com/iemr/common/service/grievance/GrievanceHandlingServiceImpl.java
around lines 337 to 338, the lastCall field is incorrectly mapped from row[13],
which is already used for lastModDate. Review the stored procedure
Pr_Grievanceworklist to identify the correct column index for lastCall, update
the mapping to use that correct index, and adjust the beneficiaryConsent index
accordingly to maintain correct data alignment.


);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ public String addKMFile(String request) throws IOException, NoSuchAlgorithmExcep
return kmFileManagers.toString();
}


private ArrayList<KMFileManager> addKMFile(Iterable<KMFileManager> kmFileManagers)
throws IOException, NoSuchAlgorithmException {
ArrayList<KMFileManager> savedFileManagers = new ArrayList<KMFileManager>();
Expand Down Expand Up @@ -175,6 +176,9 @@ private ArrayList<KMFileManager> addKMFile(Iterable<KMFileManager> kmFileManager
if (uuid != null) {
kmFileManager.setKmUploadStatus(KM_UPLOADSTATUS_COMPLETED);
kmFileManager.setFileUID(uuid);

kmFileManager.setSubCategoryID(kmFileManager.getSubCategoryID());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

Remove redundant assignment.

The line kmFileManager.setSubCategoryID(kmFileManager.getSubCategoryID()); is redundant as it sets a field to its own current value, serving no functional purpose.

-		kmFileManager.setSubCategoryID(kmFileManager.getSubCategoryID());
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
kmFileManager.setSubCategoryID(kmFileManager.getSubCategoryID());
πŸ€– Prompt for AI Agents
In
src/main/java/com/iemr/common/service/kmfilemanager/KMFileManagerServiceImpl.java
at line 180, remove the redundant assignment where kmFileManager sets its
SubCategoryID to its current value, as this line has no functional effect and
can be safely deleted.


savedFileManagers.add(kmFileManagerRepository.save(kmFileManager));
if (kmFileManager.getSubCategoryID() != null) {
updateSubcategoryFilePath(kmFileManager);
Expand All @@ -197,6 +201,7 @@ private ArrayList<KMFileManager> addKMFile(Iterable<KMFileManager> kmFileManager
return savedFileManagers;
}


private void updateSubcategoryFilePath(KMFileManager kmFileManager) {
subCategoryRepository.updateFilePath(kmFileManager.getSubCategoryID(), kmFileManager.getFileUID());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import com.iemr.common.utils.exception.IEMRException;
import com.iemr.common.utils.mapper.InputMapper;
import com.iemr.common.data.common.DocFileManager;
import com.iemr.common.data.kmfilemanager.KMFileManager;

@Service
@PropertySource("classpath:/application.properties")
Expand Down Expand Up @@ -133,29 +134,45 @@ public Iterable<CategoryDetails> getCategories() {
return categoriesList;
}


//newChange
@Override
public Iterable<SubCategoryDetails> getSubCategories(String request) throws IEMRException, JsonMappingException, JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
SubCategoryDetails subCategoryDetails = objectMapper.readValue(request, SubCategoryDetails.class);
List<SubCategoryDetails> subCategoriesList = new ArrayList<SubCategoryDetails>();
ArrayList<Object[]> lists = subCategoryRepository.findByCategoryID(subCategoryDetails.getCategoryID());
for (Object[] objects : lists) {
if (objects != null && objects.length > 1) {
String SubCatFilePath = (String) objects[2];
String fileUIDAsURI = null;
String fileNameWithExtension = null;
if(SubCatFilePath!=null) {
fileUIDAsURI=getFilePath(SubCatFilePath);
List<Object[]> fileNameList = kmFileManagerRepository.getFileNameByUID(SubCatFilePath);
Object[] fileobjects = fileNameList.get(0);
fileNameWithExtension= (String)fileobjects[0]+ (String) fileobjects[1];
}
subCategoriesList.add(new SubCategoryDetails((Integer) objects[0], (String) objects[1], SubCatFilePath, fileUIDAsURI, fileNameWithExtension));
}
}
return subCategoriesList;
ObjectMapper objectMapper = new ObjectMapper();
SubCategoryDetails subCategoryDetails = objectMapper.readValue(request, SubCategoryDetails.class);
List<SubCategoryDetails> subCategoriesList = new ArrayList<>();
ArrayList<Object[]> lists = subCategoryRepository.findByCategoryID(subCategoryDetails.getCategoryID());

for (Object[] objects : lists) {
if (objects != null && objects.length > 1) {
Integer subCatId = (Integer) objects[0];
String subCatName = (String) objects[1];

// Fetch all files under this subcategory from KMFileManager
List<KMFileManager> files = kmFileManagerRepository.getFilesBySubCategoryID(subCatId);
ArrayList<KMFileManager> fileList = new ArrayList<>(files);

String fileURL = null;
String fileNameWithExtension = null;

if (!fileList.isEmpty()) {
KMFileManager firstFile = fileList.get(0); // Just for representative file URL and name
fileURL = getFilePath(firstFile.getFileUID());
fileNameWithExtension = firstFile.getFileName() + firstFile.getFileExtension();
}

SubCategoryDetails subCategory = new SubCategoryDetails(subCatId, subCatName);
subCategory.setFileManger(fileList); // Attach all files here
subCategory.setFileURL(fileURL); // Representative file URL
subCategory.setFileNameWithExtension(fileNameWithExtension); // Representative file name+ext

subCategoriesList.add(subCategory);
}
}
return subCategoriesList;
}


private String getFilePath(String fileUID)
{
String fileUIDAsURI = null;
Expand Down
Loading