From 9f0fbb02e4493b6995315f34ed243ed7129e0aaf Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Mon, 10 Mar 2025 16:27:11 +0530 Subject: [PATCH 01/27] Beneficiary consent --- .../java/com/iemr/common/dto/identity/CommonIdentityDTO.java | 1 + .../com/iemr/common/model/beneficiary/BeneficiaryModel.java | 3 +++ .../service/beneficiary/RegisterBenificiaryServiceImpl.java | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java b/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java index 431a267a..846e5c51 100644 --- a/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java +++ b/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java @@ -59,6 +59,7 @@ public class CommonIdentityDTO { private Integer educationId; private String education; private Boolean emergencyRegistration = false; + private Boolean isConsent; private Integer healthCareWorkerId; private String healthCareWorker; private String fatherName; diff --git a/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java b/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java index aee6b8f7..696da9b1 100644 --- a/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java +++ b/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java @@ -77,6 +77,9 @@ public class BeneficiaryModel implements Comparable { // private List outboundCallRequests; // private List beneficiaryCalls; // private List feedbacks; + @Expose + private Boolean isConsent=false; + @Expose private String beneficiaryID; @Expose diff --git a/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java b/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java index 1d829d17..8af08922 100644 --- a/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java +++ b/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java @@ -163,13 +163,14 @@ private int updateDemographics(BeneficiaryDemographicsModel i_BenDemographics) { @Override public String save(BeneficiaryModel beneficiaryModel, HttpServletRequest servletRequest) throws Exception { - // logger.info("benificiaryDetails: " + beneficiaryModel); + logger.info("benificiaryDetails: " + beneficiaryModel); CommonIdentityDTO identityDTO = identityMapper.beneficiaryModelCommonIdentityDTO(beneficiaryModel); setSaveDemographicDetails(identityDTO,beneficiaryModel); // identityDTO.setOtherFields(beneficiaryModel.getOtherFields()); identityDTO.setFaceEmbedding(beneficiaryModel.getFaceEmbedding()); identityDTO.setEmergencyRegistration(beneficiaryModel.isEmergencyRegistration()); + identityDTO.setIsConsent(beneficiaryModel.getIsConsent()); identityDTO .setBenFamilyDTOs(identityMapper.benPhoneMapListToBenFamilyDTOList(beneficiaryModel.getBenPhoneMaps())); String request = new Gson().toJson(identityDTO); From a94ad60568d0069a2dcc7b00ede255aeffd2cfee Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Mon, 10 Mar 2025 17:31:49 +0530 Subject: [PATCH 02/27] Beneficiary consent --- .../java/com/iemr/common/dto/identity/CommonIdentityDTO.java | 2 ++ .../com/iemr/common/model/beneficiary/BeneficiaryModel.java | 3 +++ .../service/beneficiary/RegisterBenificiaryServiceImpl.java | 3 ++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java b/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java index 431a267a..8e364eb3 100644 --- a/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java +++ b/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java @@ -54,6 +54,8 @@ public class CommonIdentityDTO { private Integer beneficiaryRegId; private Integer communityId; private String community; + private Boolean isConsent=false; + private Timestamp dob; private Integer ageAtMarriage; private Integer educationId; diff --git a/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java b/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java index aee6b8f7..209472ef 100644 --- a/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java +++ b/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java @@ -87,6 +87,9 @@ public class BeneficiaryModel implements Comparable { private TitleModel m_title; @Expose private String firstName; + @Expose + private Boolean isConsent=false; + @Expose private String middleName; @Expose diff --git a/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java b/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java index 1d829d17..4ab722e7 100644 --- a/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java +++ b/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java @@ -163,11 +163,12 @@ private int updateDemographics(BeneficiaryDemographicsModel i_BenDemographics) { @Override public String save(BeneficiaryModel beneficiaryModel, HttpServletRequest servletRequest) throws Exception { - // logger.info("benificiaryDetails: " + beneficiaryModel); + logger.info("benificiaryDetails: " + beneficiaryModel); CommonIdentityDTO identityDTO = identityMapper.beneficiaryModelCommonIdentityDTO(beneficiaryModel); setSaveDemographicDetails(identityDTO,beneficiaryModel); // identityDTO.setOtherFields(beneficiaryModel.getOtherFields()); + identityDTO.setIsConsent(beneficiaryModel.getIsConsent()); identityDTO.setFaceEmbedding(beneficiaryModel.getFaceEmbedding()); identityDTO.setEmergencyRegistration(beneficiaryModel.isEmergencyRegistration()); identityDTO From 01abcbda8003b76986644c63d928baa0a0974efe Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 10 Apr 2025 11:05:36 +0530 Subject: [PATCH 03/27] Beneficiary consent --- .../java/com/iemr/common/controller/otp/OTPGateway.java | 9 +++++++-- .../iemr/common/model/beneficiary/BeneficiaryModel.java | 1 + .../beneficiary/RegisterBenificiaryServiceImpl.java | 3 ++- .../com/iemr/common/utils/JwtUserIdValidationFilter.java | 1 + 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/iemr/common/controller/otp/OTPGateway.java b/src/main/java/com/iemr/common/controller/otp/OTPGateway.java index 42371a88..f74caa63 100644 --- a/src/main/java/com/iemr/common/controller/otp/OTPGateway.java +++ b/src/main/java/com/iemr/common/controller/otp/OTPGateway.java @@ -55,6 +55,7 @@ public class OTPGateway { @Operation(summary = "Send OTP") @RequestMapping(value = "/sendOTP", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, headers = "Authorization") public String sendOTP(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody String requestOBJ) { + logger.info(requestOBJ.toString()); OutputResponse response = new OutputResponse(); @@ -62,7 +63,8 @@ public String sendOTP(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody Stri OTPRequestParsor obj = InputMapper.gson().fromJson(requestOBJ, OTPRequestParsor.class); String success = otpHandler.sendOTP(obj); - if (success.equalsIgnoreCase("success")) + logger.info(success.toString()); + if (success.contains("otp")) response.setResponse(success); else response.setError(5000, "failure"); @@ -102,6 +104,7 @@ public String validateOTP( @Operation(summary = "Resend OTP") @RequestMapping(value = "/resendOTP", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, headers = "Authorization") public String resendOTP(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody String requestOBJ) { + logger.info(requestOBJ.toString()); OutputResponse response = new OutputResponse(); @@ -109,7 +112,9 @@ public String resendOTP(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody St OTPRequestParsor obj = InputMapper.gson().fromJson(requestOBJ, OTPRequestParsor.class); String success = otpHandler.resendOTP(obj); - if (success.equalsIgnoreCase("success")) + logger.info(success.toString()); + + if (success.contains("otp")) response.setResponse(success); else response.setError(5000, "failure"); diff --git a/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java b/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java index 696da9b1..a437ec20 100644 --- a/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java +++ b/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java @@ -80,6 +80,7 @@ public class BeneficiaryModel implements Comparable { @Expose private Boolean isConsent=false; + @Expose private String beneficiaryID; @Expose diff --git a/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java b/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java index 8af08922..0b52ce26 100644 --- a/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java +++ b/src/main/java/com/iemr/common/service/beneficiary/RegisterBenificiaryServiceImpl.java @@ -37,7 +37,6 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; -import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import com.iemr.common.data.beneficiary.Beneficiary; import com.iemr.common.data.mctshistory.MctsOutboundCallDetail; @@ -77,6 +76,8 @@ public class RegisterBenificiaryServiceImpl implements RegisterBenificiaryServic @Autowired Validator validator; + + @Autowired OutboundHistoryRepository outboundHistoryRepository; diff --git a/src/main/java/com/iemr/common/utils/JwtUserIdValidationFilter.java b/src/main/java/com/iemr/common/utils/JwtUserIdValidationFilter.java index 0c12c3a6..5341e678 100644 --- a/src/main/java/com/iemr/common/utils/JwtUserIdValidationFilter.java +++ b/src/main/java/com/iemr/common/utils/JwtUserIdValidationFilter.java @@ -35,6 +35,7 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo String contextPath = request.getContextPath(); logger.info("JwtUserIdValidationFilter invoked for path: " + path); + // Log cookies for debugging Cookie[] cookies = request.getCookies(); if (cookies != null) { From 0f0113c8a93d804f59964d93f61d0960a41a6c1b Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 10 Apr 2025 11:06:32 +0530 Subject: [PATCH 04/27] Beneficiary consent --- .../utils/http/HTTPRequestInterceptor.java | 260 +++++++++--------- 1 file changed, 131 insertions(+), 129 deletions(-) diff --git a/src/main/java/com/iemr/common/utils/http/HTTPRequestInterceptor.java b/src/main/java/com/iemr/common/utils/http/HTTPRequestInterceptor.java index a31b2a2b..bfa07031 100644 --- a/src/main/java/com/iemr/common/utils/http/HTTPRequestInterceptor.java +++ b/src/main/java/com/iemr/common/utils/http/HTTPRequestInterceptor.java @@ -1,24 +1,24 @@ /* -* AMRIT – Accessible Medical Records via Integrated Technology -* Integrated EHR (Electronic Health Records) Solution -* -* Copyright (C) "Piramal Swasthya Management and Research Institute" -* -* This file is part of AMRIT. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see https://www.gnu.org/licenses/. -*/ + * AMRIT – Accessible Medical Records via Integrated Technology + * Integrated EHR (Electronic Health Records) Solution + * + * Copyright (C) "Piramal Swasthya Management and Research Institute" + * + * This file is part of AMRIT. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ package com.iemr.common.utils.http; @@ -38,125 +38,127 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; + @Configuration @Component public class HTTPRequestInterceptor implements HandlerInterceptor { - private Validator validator; + private Validator validator; - Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); + Logger logger = LoggerFactory.getLogger(this.getClass().getSimpleName()); - @Autowired - public void setValidator(Validator validator) { - this.validator = validator; - } + @Autowired + public void setValidator(Validator validator) { + this.validator = validator; + } - private SessionObject sessionObject; + private SessionObject sessionObject; - @Autowired - public void setSessionObject(SessionObject sessionObject) { - this.sessionObject = sessionObject; - } + @Autowired + public void setSessionObject(SessionObject sessionObject) { + this.sessionObject = sessionObject; + } - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception { - boolean status = true; - logger.info("In info preHandle we are Intercepting the Request"); - logger.debug("In preHandle we are Intercepting the Request"); - // String authorization = request.getHeader("Authorization"); - String authorization = null; - String preAuth = request.getHeader("Authorization"); - if(null != preAuth && preAuth.contains("Bearer ")) - authorization=preAuth.replace("Bearer ", ""); - else - authorization = preAuth; - logger.debug("RequestURI::" + request.getRequestURI() + " || Authorization ::" + authorization - + " || method :: " + request.getMethod()); - if (!request.getMethod().equalsIgnoreCase("OPTIONS")) { - try { - String[] requestURIParts = request.getRequestURI().split("/"); - String requestAPI = requestURIParts[requestURIParts.length - 1]; - switch (requestAPI) { - case "userAuthenticate": - case "superUserAuthenticate": - case "userAuthenticateNew": - case "userAuthenticateV1": - case "forgetPassword": - case "setForgetPassword": - case "changePassword": - case "saveUserSecurityQuesAns": - case "doAgentLogout": - case "userLogout": - case "swagger-ui.html": - case "index.html": - case "index.css": - case "swagger-initializer.js": - case "swagger-config": - case "swagger-ui-bundle.js": - case "swagger-ui.css": - case "ui": - case "swagger-ui-standalone-preset.js": - case "favicon-32x32.png": - case "favicon-16x16.png": - case "swagger-resources": - case "api-docs": - case "updateBenCallIdsInPhoneBlock": - case "userAuthenticateByEncryption": + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception { + boolean status = true; + logger.info("In info preHandle we are Intercepting the Request"); + logger.debug("In preHandle we are Intercepting the Request"); + // String authorization = request.getHeader("Authorization"); + String authorization = null; + String preAuth = request.getHeader("Authorization"); + if (null != preAuth && preAuth.contains("Bearer ")) + authorization = preAuth.replace("Bearer ", ""); + else + authorization = preAuth; + logger.debug("RequestURI::" + request.getRequestURI() + " || Authorization ::" + authorization + + " || method :: " + request.getMethod()); + if (!request.getMethod().equalsIgnoreCase("OPTIONS")) { + try { + String[] requestURIParts = request.getRequestURI().split("/"); + String requestAPI = requestURIParts[requestURIParts.length - 1]; - case "sendOTP": - case "validateOTP": - case "resendOTP": - case "validateSecurityQuestionAndAnswer": - case "logOutUserFromConcurrentSession": + switch (requestAPI) { + case "create": + case "userAuthenticate": + case "superUserAuthenticate": + case "userAuthenticateNew": + case "userAuthenticateV1": + case "forgetPassword": + case "setForgetPassword": + case "changePassword": + case "saveUserSecurityQuesAns": + case "doAgentLogout": + case "userLogout": + case "swagger-ui.html": + case "index.html": + case "index.css": + case "swagger-initializer.js": + case "swagger-config": + case "swagger-ui-bundle.js": + case "swagger-ui.css": + case "ui": + case "swagger-ui-standalone-preset.js": + case "favicon-32x32.png": + case "favicon-16x16.png": + case "swagger-resources": + case "api-docs": + case "updateBenCallIdsInPhoneBlock": + case "userAuthenticateByEncryption": + case "sendOTP": + case "validateOTP": + case "resendOTP": + case "validateSecurityQuestionAndAnswer": + case "logOutUserFromConcurrentSession": - break; - case "error": - status = false; - break; - default: - String remoteAddress = request.getHeader("X-FORWARDED-FOR"); - if (remoteAddress == null || remoteAddress.trim().length() == 0) { - remoteAddress = request.getRemoteAddr(); - } - validator.checkKeyExists(authorization, remoteAddress); - break; - } - } catch (Exception e) { - OutputResponse output = new OutputResponse(); - output.setError(e); - response.getOutputStream().print(output.toString()); - response.setContentType(MediaType.APPLICATION_JSON); - response.setContentLength(output.toString().length()); - response.setHeader("Access-Control-Allow-Origin", "*"); - status = false; - } - } - return status; - } + break; + case "error": + status = false; + break; + default: + String remoteAddress = request.getHeader("X-FORWARDED-FOR"); + if (remoteAddress == null || remoteAddress.trim().length() == 0) { + remoteAddress = request.getRemoteAddr(); + } + validator.checkKeyExists(authorization, remoteAddress); + break; + } + } catch (Exception e) { + OutputResponse output = new OutputResponse(); + output.setError(e); + response.getOutputStream().print(output.toString()); + response.setContentType(MediaType.APPLICATION_JSON); + response.setContentLength(output.toString().length()); + response.setHeader("Access-Control-Allow-Origin", "*"); + status = false; + } + } + return status; + } - @Override - public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView model) - throws Exception { - try { - logger.debug("In postHandle we are Intercepting the Request"); - // String authorization = request.getHeader("Authorization"); - String authorization = null; - String postAuth = request.getHeader("Authorization"); - if(null != postAuth && postAuth.contains("Bearer ")) - authorization=postAuth.replace("Bearer ", ""); - else - authorization = postAuth; - logger.debug("RequestURI::" + request.getRequestURI() + " || Authorization ::" + authorization); - if (authorization != null) { - sessionObject.updateSessionObject(authorization, sessionObject.getSessionObject(authorization)); - } - } catch (Exception e) { - logger.debug("postHandle failed with error " + e.getMessage()); - } - } + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object, ModelAndView model) + throws Exception { +// try { +// logger.debug("In postHandle we are Intercepting the Request"); +// // String authorization = request.getHeader("Authorization"); +// String authorization = null; +// String postAuth = request.getHeader("Authorization"); +// if (null != postAuth && postAuth.contains("Bearer ")) +// authorization = postAuth.replace("Bearer ", ""); +// else +// authorization = postAuth; +// logger.debug("RequestURI::" + request.getRequestURI() + " || Authorization ::" + authorization); +// if (authorization != null) { +// sessionObject.updateSessionObject(authorization, sessionObject.getSessionObject(authorization)); +// } +// } catch (Exception e) { +// logger.debug("postHandle failed with error " + e.getMessage()); +// } + } - @Override - public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception arg3) - throws Exception { - logger.debug("In afterCompletion Request Completed"); - } + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object, Exception arg3) + throws Exception { + logger.debug("In afterCompletion Request Completed"); + } } \ No newline at end of file From a5b595ed10a52d3a50468eff4c0c2b1568b18646 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 10 Apr 2025 11:24:30 +0530 Subject: [PATCH 05/27] Beneficiary consent --- .../iemr/common/service/notification/NotificationService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/iemr/common/service/notification/NotificationService.java b/src/main/java/com/iemr/common/service/notification/NotificationService.java index a3c85387..6fa8ee8d 100644 --- a/src/main/java/com/iemr/common/service/notification/NotificationService.java +++ b/src/main/java/com/iemr/common/service/notification/NotificationService.java @@ -55,4 +55,5 @@ String createEmergencyContacts(String request) String updateEmergencyContacts(String request) throws JSONException, NoSuchAlgorithmException, IOException, IEMRException, Exception; + } From a363c332a051a958a4f2e739b6b993a30b11509f Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 10 Apr 2025 11:25:20 +0530 Subject: [PATCH 06/27] Beneficiary consent --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index f29e4dca..0e81958f 100644 --- a/pom.xml +++ b/pom.xml @@ -165,7 +165,6 @@ hibernate-jpa-2.0-api 1.0.1.Final - org.springframework.boot spring-boot-starter-cache @@ -497,7 +496,7 @@ - commonapi-v3.0.0 + commonapi-v1.0 org.apache.maven.plugins From 72715a79bbd00227e01ffec736c6c32a609e46de Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Fri, 11 Apr 2025 14:21:06 +0530 Subject: [PATCH 07/27] firebase setup --- pom.xml | 8 +++- .../com/iemr/common/CommonApplication.java | 20 ++++++++++ .../FirebaseNotificationController.java | 25 +++++++++++++ .../notification/NotificationMessage.java | 14 +++++++ .../FirebaseNotificationService.java | 37 +++++++++++++++++++ 5 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java create mode 100644 src/main/java/com/iemr/common/model/notification/NotificationMessage.java create mode 100644 src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java diff --git a/pom.xml b/pom.xml index db199065..8e41c424 100644 --- a/pom.xml +++ b/pom.xml @@ -107,6 +107,12 @@ + + + com.google.firebase + firebase-admin + 9.4.3 + org.springframework.boot spring-boot-starter-data-jpa @@ -497,7 +503,7 @@ - commonapi-v3.0.0 + commonapi-v1.0 org.apache.maven.plugins diff --git a/src/main/java/com/iemr/common/CommonApplication.java b/src/main/java/com/iemr/common/CommonApplication.java index 83078018..cd140056 100644 --- a/src/main/java/com/iemr/common/CommonApplication.java +++ b/src/main/java/com/iemr/common/CommonApplication.java @@ -21,11 +21,16 @@ */ package com.iemr.common; +import com.google.auth.oauth2.GoogleCredentials; +import com.google.firebase.FirebaseApp; +import com.google.firebase.FirebaseOptions; +import com.google.firebase.messaging.FirebaseMessaging; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.context.annotation.Bean; +import org.springframework.core.io.ClassPathResource; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; @@ -36,6 +41,8 @@ import com.iemr.common.data.users.User; import com.iemr.common.utils.IEMRApplBeans; +import java.io.IOException; + @SpringBootApplication @EnableScheduling public class CommonApplication extends SpringBootServletInitializer { @@ -73,4 +80,17 @@ public RedisTemplate redisTemplate(RedisConnectionFactory factor return template; } + @Bean + FirebaseMessaging firebaseMessaging() throws IOException { + GoogleCredentials googleCredentials = GoogleCredentials.fromStream( + new ClassPathResource("Place your admin json").getInputStream() + + ); + FirebaseOptions firebaseOptions = FirebaseOptions.builder().setCredentials(googleCredentials).build(); + FirebaseApp firebaseApp = FirebaseApp.initializeApp(firebaseOptions); + return FirebaseMessaging.getInstance(firebaseApp); + + + } + } diff --git a/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java b/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java new file mode 100644 index 00000000..22f438ca --- /dev/null +++ b/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java @@ -0,0 +1,25 @@ +package com.iemr.common.controller.firebaseNotification; + +import com.iemr.common.model.notification.NotificationMessage; +import com.iemr.common.service.firebaseNotification.FirebaseNotificationService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping(value= "/firebaseNotification") +public class FirebaseNotificationController { + final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); + + @Autowired + FirebaseNotificationService firebaseNotificationService; + + @CrossOrigin + @RequestMapping(value = "sendNotification",method = RequestMethod.POST) + public String sendNotificationByToken(@RequestBody NotificationMessage notificationMessage){ + return firebaseNotificationService.sendNotification(notificationMessage); + } + + +} diff --git a/src/main/java/com/iemr/common/model/notification/NotificationMessage.java b/src/main/java/com/iemr/common/model/notification/NotificationMessage.java new file mode 100644 index 00000000..2838eca3 --- /dev/null +++ b/src/main/java/com/iemr/common/model/notification/NotificationMessage.java @@ -0,0 +1,14 @@ +package com.iemr.common.model.notification; + +import lombok.Data; + +import java.util.Map; + +@Data +public class NotificationMessage { + private String appType; + private String topic; + private String title; + private String body; + private Map data; +} diff --git a/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java b/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java new file mode 100644 index 00000000..642bd6fa --- /dev/null +++ b/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java @@ -0,0 +1,37 @@ +package com.iemr.common.service.firebaseNotification; + +import com.google.firebase.FirebaseException; +import com.google.firebase.messaging.FirebaseMessaging; +import com.google.firebase.messaging.Message; +import com.google.firebase.messaging.Notification; +import com.iemr.common.model.notification.NotificationMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class FirebaseNotificationService { + final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); + + @Autowired + FirebaseMessaging firebaseMessaging; + + public String sendNotification(NotificationMessage notificationMessage) { + + Notification notification = Notification.builder().setTitle(notificationMessage.getTitle()).setBody(notificationMessage.getBody()).build(); + + Message message = Message.builder().setTopic(notificationMessage.getTopic()).setNotification(notification).putAllData(notificationMessage.getData()).build(); + + + try { + String response = FirebaseMessaging.getInstance().send(message); + + return response; + } catch (FirebaseException e) { + return "Error sending notification"; + + } + } + +} From 121928c71ac4635d34de301c9c152bd135b2f19a Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Fri, 11 Apr 2025 15:23:54 +0530 Subject: [PATCH 08/27] firebase setup --- src/main/java/com/iemr/common/CommonApplication.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/iemr/common/CommonApplication.java b/src/main/java/com/iemr/common/CommonApplication.java index cd140056..7b709768 100644 --- a/src/main/java/com/iemr/common/CommonApplication.java +++ b/src/main/java/com/iemr/common/CommonApplication.java @@ -94,3 +94,4 @@ FirebaseMessaging firebaseMessaging() throws IOException { } } + From 396359d637bbd4f7f1ae528c2ff942b0ac1a9185 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Fri, 11 Apr 2025 16:15:05 +0530 Subject: [PATCH 09/27] firebase setup --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8e41c424..454fd02a 100644 --- a/pom.xml +++ b/pom.xml @@ -503,7 +503,7 @@ - commonapi-v1.0 + commonapi-v3.0.0 org.apache.maven.plugins From 0e24515a15014282ad7aade9ff1d9e1151ed9ca2 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Fri, 11 Apr 2025 18:32:07 +0530 Subject: [PATCH 10/27] firebase setup --- .../firebaseNotification/FirebaseNotificationController.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java b/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java index 22f438ca..18601d22 100644 --- a/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java +++ b/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java @@ -8,14 +8,13 @@ import org.springframework.web.bind.annotation.*; @RestController -@RequestMapping(value= "/firebaseNotification") +@RequestMapping(value= "/firebaseNotification",headers = "Authorization") public class FirebaseNotificationController { final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); @Autowired FirebaseNotificationService firebaseNotificationService; - @CrossOrigin @RequestMapping(value = "sendNotification",method = RequestMethod.POST) public String sendNotificationByToken(@RequestBody NotificationMessage notificationMessage){ return firebaseNotificationService.sendNotification(notificationMessage); From 70a425605d87cddacc876a361a307ceb86d5e3ec Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Mon, 14 Apr 2025 14:48:33 +0530 Subject: [PATCH 11/27] firebase setup --- .../com/iemr/common/CommonApplication.java | 12 ---- .../firebase/FirebaseMessagingConfig.java | 57 +++++++++++++++++++ 2 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/iemr/common/config/firebase/FirebaseMessagingConfig.java diff --git a/src/main/java/com/iemr/common/CommonApplication.java b/src/main/java/com/iemr/common/CommonApplication.java index 7b709768..ea0adb97 100644 --- a/src/main/java/com/iemr/common/CommonApplication.java +++ b/src/main/java/com/iemr/common/CommonApplication.java @@ -80,18 +80,6 @@ public RedisTemplate redisTemplate(RedisConnectionFactory factor return template; } - @Bean - FirebaseMessaging firebaseMessaging() throws IOException { - GoogleCredentials googleCredentials = GoogleCredentials.fromStream( - new ClassPathResource("Place your admin json").getInputStream() - - ); - FirebaseOptions firebaseOptions = FirebaseOptions.builder().setCredentials(googleCredentials).build(); - FirebaseApp firebaseApp = FirebaseApp.initializeApp(firebaseOptions); - return FirebaseMessaging.getInstance(firebaseApp); - - - } } diff --git a/src/main/java/com/iemr/common/config/firebase/FirebaseMessagingConfig.java b/src/main/java/com/iemr/common/config/firebase/FirebaseMessagingConfig.java new file mode 100644 index 00000000..438ca4f9 --- /dev/null +++ b/src/main/java/com/iemr/common/config/firebase/FirebaseMessagingConfig.java @@ -0,0 +1,57 @@ +package com.iemr.common.config.firebase; + +import com.google.auth.oauth2.GoogleCredentials; +import com.google.firebase.FirebaseApp; +import com.google.firebase.FirebaseOptions; +import com.google.firebase.messaging.FirebaseMessaging; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Base64; + +@Configuration +public class FirebaseMessagingConfig { + + @Value("${firebase.enabled:false}") + private boolean firebaseEnabled; + + @Value("${firebase.credential-file:}") + private String firebaseCredentialFile; + + @Value("${firebase.credential-base64:}") + private String firebaseCredentialBase64; + + @Bean + public FirebaseMessaging firebaseMessaging() throws IOException { + if (!firebaseEnabled) { + throw new IllegalStateException("Firebase is disabled"); + } + + GoogleCredentials credentials; + + if (!firebaseCredentialBase64.isBlank()) { + byte[] decoded = Base64.getDecoder().decode(firebaseCredentialBase64); + credentials = GoogleCredentials.fromStream(new ByteArrayInputStream(decoded)); + } else if (!firebaseCredentialFile.isBlank()) { + credentials = GoogleCredentials.fromStream( + new ClassPathResource(firebaseCredentialFile).getInputStream() + ); + } else { + throw new IllegalStateException("No Firebase credentials provided"); + } + + FirebaseOptions options = FirebaseOptions.builder() + .setCredentials(credentials) + .build(); + + FirebaseApp firebaseApp = FirebaseApp.getApps().isEmpty() + ? FirebaseApp.initializeApp(options) + : FirebaseApp.getInstance(); + + return FirebaseMessaging.getInstance(firebaseApp); + } +} From 8df1a0fb68d596676c6c4772fe2a44bf317ea9bf Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 17 Apr 2025 14:22:00 +0530 Subject: [PATCH 12/27] firebase setup --- src/main/environment/common_ci.properties | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/environment/common_ci.properties b/src/main/environment/common_ci.properties index 1f82e9ea..0e498ac8 100644 --- a/src/main/environment/common_ci.properties +++ b/src/main/environment/common_ci.properties @@ -34,6 +34,13 @@ send-message-url=@env.SMS_MESSAGE_URL@ start-sms-scheduler=false cron-scheduler-sms=0 0/1 * * * ? * +// Firebase Configuration +firebase.enabled= @env.FIREBASE_ENABLE@ +# if using file +firebase.credential-file=@env.FIREBASE_CREDENTIAL@ +# for CI/CD +credential-base64 =@env.CREDENTIAL_BASE^$@ + #### Email Configuration send-email=@env.SEND_EMAIL@ spring.mail.host=@env.MAIL_HOST@ From 7222cbd725898cd680365d3ed1d1b676e34e8760 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 17 Apr 2025 14:25:40 +0530 Subject: [PATCH 13/27] Firebase Configuration in ci --- src/main/environment/common_ci.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/environment/common_ci.properties b/src/main/environment/common_ci.properties index 0e498ac8..478cd4e4 100644 --- a/src/main/environment/common_ci.properties +++ b/src/main/environment/common_ci.properties @@ -34,8 +34,8 @@ send-message-url=@env.SMS_MESSAGE_URL@ start-sms-scheduler=false cron-scheduler-sms=0 0/1 * * * ? * -// Firebase Configuration -firebase.enabled= @env.FIREBASE_ENABLE@ ++ # Firebase Configuration +firebase.enabled=@env.FIREBASE_ENABLE@ # if using file firebase.credential-file=@env.FIREBASE_CREDENTIAL@ # for CI/CD From ede033903ea402a6e3c1c918d66219985a7e80bd Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 17 Apr 2025 14:27:01 +0530 Subject: [PATCH 14/27] Firebase Configuration in ci --- src/main/environment/common_ci.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/environment/common_ci.properties b/src/main/environment/common_ci.properties index 478cd4e4..a9a8426f 100644 --- a/src/main/environment/common_ci.properties +++ b/src/main/environment/common_ci.properties @@ -34,12 +34,12 @@ send-message-url=@env.SMS_MESSAGE_URL@ start-sms-scheduler=false cron-scheduler-sms=0 0/1 * * * ? * -+ # Firebase Configuration +# Firebase Configuration firebase.enabled=@env.FIREBASE_ENABLE@ # if using file firebase.credential-file=@env.FIREBASE_CREDENTIAL@ # for CI/CD -credential-base64 =@env.CREDENTIAL_BASE^$@ +firebase.credential-base64=@env.CREDENTIAL_BASE64@ #### Email Configuration send-email=@env.SEND_EMAIL@ From e3a177e65d022e461a47d379075c712f30947f4f Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Fri, 2 May 2025 12:44:26 +0530 Subject: [PATCH 15/27] firebase notification setup --- .../com/iemr/common/model/notification/NotificationMessage.java | 1 + .../firebaseNotification/FirebaseNotificationService.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/iemr/common/model/notification/NotificationMessage.java b/src/main/java/com/iemr/common/model/notification/NotificationMessage.java index 2838eca3..eed0c171 100644 --- a/src/main/java/com/iemr/common/model/notification/NotificationMessage.java +++ b/src/main/java/com/iemr/common/model/notification/NotificationMessage.java @@ -7,6 +7,7 @@ @Data public class NotificationMessage { private String appType; + private String token; private String topic; private String title; private String body; diff --git a/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java b/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java index 642bd6fa..e41ca94f 100644 --- a/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java +++ b/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java @@ -21,7 +21,7 @@ public String sendNotification(NotificationMessage notificationMessage) { Notification notification = Notification.builder().setTitle(notificationMessage.getTitle()).setBody(notificationMessage.getBody()).build(); - Message message = Message.builder().setTopic(notificationMessage.getTopic()).setNotification(notification).putAllData(notificationMessage.getData()).build(); + Message message = Message.builder().setToken(notificationMessage.getToken()).setNotification(notification).putAllData(notificationMessage.getData()).build(); try { From ea4747026f7f3e7db919e31c9ba2ea695915eff9 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Fri, 13 Jun 2025 15:07:53 +0530 Subject: [PATCH 16/27] Beneficiary consent --- .../BeneficiaryConsentController.java | 100 +++++++++ .../BeneficiaryConsentRequest.java | 12 + .../BeneficiaryOTPHandler.java | 14 ++ .../BeneficiaryOTPHandlerImpl.java | 207 ++++++++++++++++++ 4 files changed, 333 insertions(+) create mode 100644 src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java create mode 100644 src/main/java/com/iemr/common/data/beneficiaryConsent/BeneficiaryConsentRequest.java create mode 100644 src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandler.java create mode 100644 src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java diff --git a/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java b/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java new file mode 100644 index 00000000..60c7bdee --- /dev/null +++ b/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java @@ -0,0 +1,100 @@ +package com.iemr.common.controller.beneficiaryConsent; + +import com.iemr.common.data.beneficiaryConsent.BeneficiaryConsentRequest; +import com.iemr.common.data.otp.OTPRequestParsor; +import com.iemr.common.service.beneficiaryOTPHandler.BeneficiaryOTPHandler; +import com.iemr.common.service.otp.OTPHandler; +import com.iemr.common.utils.mapper.InputMapper; +import com.iemr.common.utils.response.OutputResponse; +import io.lettuce.core.dynamic.annotation.Param; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.ws.rs.core.MediaType; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +public class BeneficiaryConsentController { + final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); + + @Autowired + private BeneficiaryOTPHandler beneficiaryOTPHandler; + + @Operation(summary = "Send Consent") + @RequestMapping(value = "/sendConsent", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, headers = "Authorization") + public String sendConsent(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody String requestOBJ) { + logger.info(requestOBJ.toString()); + + OutputResponse response = new OutputResponse(); + + try { + BeneficiaryConsentRequest obj = InputMapper.gson().fromJson(requestOBJ, BeneficiaryConsentRequest.class); + + String success = beneficiaryOTPHandler.sendOTP(obj); // method name unchanged if internal logic still uses 'OTP' + logger.info(success.toString()); + if (success.contains("otp")) + response.setResponse(success); + else + response.setError(500, "failure"); + + } catch (Exception e) { + logger.error("error in sending Consent : " + e); + response.setError(500, "error : " + e); + } + return response.toString(); + } + + @Operation(summary = "Validate Consent") + @RequestMapping(value = "/validateConsent", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, headers = "Authorization") + public String validateConsent(@Param(value = "{\"mobNo\":\"String\",\"otp\":\"Integer\"}") @RequestBody String requestOBJ) { + + OutputResponse response = new OutputResponse(); + + try { + OTPRequestParsor obj = InputMapper.gson().fromJson(requestOBJ, OTPRequestParsor.class); + + JSONObject responseOBJ = beneficiaryOTPHandler.validateOTP(obj); + if (responseOBJ != null) + response.setResponse(responseOBJ.toString()); + else + response.setError(500, "failure"); + + } catch (Exception e) { + logger.error("error in validating Consent : " + e); + response.setError(500, "error : " + e); + } + return response.toString(); + } + + @Operation(summary = "Resend Consent") + @RequestMapping(value = "/resendConsent", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, headers = "Authorization") + public String resendConsent(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody String requestOBJ) { + logger.info(requestOBJ.toString()); + + OutputResponse response = new OutputResponse(); + + try { + OTPRequestParsor obj = InputMapper.gson().fromJson(requestOBJ, OTPRequestParsor.class); + + String success = beneficiaryOTPHandler.resendOTP(obj); + logger.info(success.toString()); + + if (success.contains("otp")) + response.setResponse(success); + else + response.setError(500, "failure"); + + } catch (Exception e) { + logger.error("error in re-sending Consent : " + e); + response.setError(500, "error : " + e); + } + return response.toString(); + } + + +} + + diff --git a/src/main/java/com/iemr/common/data/beneficiaryConsent/BeneficiaryConsentRequest.java b/src/main/java/com/iemr/common/data/beneficiaryConsent/BeneficiaryConsentRequest.java new file mode 100644 index 00000000..ac629a3c --- /dev/null +++ b/src/main/java/com/iemr/common/data/beneficiaryConsent/BeneficiaryConsentRequest.java @@ -0,0 +1,12 @@ +package com.iemr.common.data.beneficiaryConsent; + +import lombok.Data; + +@Data +public class BeneficiaryConsentRequest { + private String mobNo; + private int otp; + private String userName; + private String designation; + +} diff --git a/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandler.java b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandler.java new file mode 100644 index 00000000..234640a8 --- /dev/null +++ b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandler.java @@ -0,0 +1,14 @@ +package com.iemr.common.service.beneficiaryOTPHandler; + +import com.iemr.common.data.beneficiaryConsent.BeneficiaryConsentRequest; +import com.iemr.common.data.otp.OTPRequestParsor; +import org.json.JSONObject; + +public interface BeneficiaryOTPHandler { + public String sendOTP(BeneficiaryConsentRequest obj) throws Exception; + + public JSONObject validateOTP(BeneficiaryConsentRequest obj) throws Exception; + + public String resendOTP(BeneficiaryConsentRequest obj) throws Exception; + +} diff --git a/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java new file mode 100644 index 00000000..9fa73005 --- /dev/null +++ b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java @@ -0,0 +1,207 @@ +/* + * AMRIT – Accessible Medical Records via Integrated Technology + * Integrated EHR (Electronic Health Records) Solution + * + * Copyright (C) "Piramal Swasthya Management and Research Institute" + * + * This file is part of AMRIT. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ +package com.iemr.common.service.beneficiaryOTPHandler; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.primitives.Ints; +import com.iemr.common.data.beneficiaryConsent.BeneficiaryConsentRequest; +import com.iemr.common.data.otp.OTPRequestParsor; +import com.iemr.common.data.sms.SMSTemplate; +import com.iemr.common.data.sms.SMSType; +import com.iemr.common.repository.sms.SMSTemplateRepository; +import com.iemr.common.repository.sms.SMSTypeRepository; +import com.iemr.common.service.otp.OTPHandler; +import com.iemr.common.service.users.IEMRAdminUserServiceImpl; +import com.iemr.common.utils.config.ConfigProperties; +import com.iemr.common.utils.http.HttpUtils; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.security.MessageDigest; +import java.security.SecureRandom; +import java.util.*; +import java.util.concurrent.TimeUnit; + +@Service +public class BeneficiaryOTPHandlerImpl implements BeneficiaryOTPHandler { + + @Autowired + HttpUtils httpUtils; + @Autowired + private IEMRAdminUserServiceImpl iEMRAdminUserServiceImpl; + + final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); + @Autowired + SMSTemplateRepository smsTemplateRepository; + private LoadingCache otpCache; + + @Autowired + SMSTypeRepository smsTypeRepository; + + private static final Integer EXPIRE_MIN = 5; + private static final String SMS_GATEWAY_URL = ConfigProperties.getPropertyByName("sms-gateway-url"); + + // Constructor for new object creation + public BeneficiaryOTPHandlerImpl() { + otpCache = CacheBuilder.newBuilder().expireAfterWrite(EXPIRE_MIN, TimeUnit.MINUTES) + .build(new CacheLoader() { + public String load(String key) { + return "0"; + } + }); + } + + /*** + * @param obj + * @return success if OTP sent successfully + */ + @Override + public String sendOTP(BeneficiaryConsentRequest obj) throws Exception { + int otp = generateOTP(obj.getMobNo()); + sendSMS(otp, obj); + return "success"; + } + + /*** + * @param obj + * @return OTP verification success or failure + * + */ + @Override + public JSONObject validateOTP(BeneficiaryConsentRequest obj) throws Exception { + String cachedOTP = otpCache.get(obj.getMobNo()); + String inputOTPEncrypted = getEncryptedOTP(obj.getOtp()); + + if (cachedOTP.equalsIgnoreCase(inputOTPEncrypted)) { + JSONObject responseObj = new JSONObject(); + responseObj.put("userName", obj.getMobNo()); + responseObj.put("userID", obj.getMobNo()); + + JSONObject responseOBJ = iEMRAdminUserServiceImpl.generateKeyPostOTPValidation(responseObj); + + return responseOBJ; + } else { + throw new Exception("Please enter valid OTP"); + } + + } + + /*** + * @param obj + * @return success if OTP re-sent successfully + */ + @Override + public String resendOTP(BeneficiaryConsentRequest obj) throws Exception { + int otp = generateOTP(obj.getMobNo()); + sendSMS(otp, obj); + return "success"; + } + + // generate 6 digit random no # + public int generateOTP(String authKey) throws Exception { + String generatedPassword = null; + Random random = SecureRandom.getInstanceStrong(); + int otp = 100000 + random.nextInt(900000); + + generatedPassword = getEncryptedOTP(otp); + + if (otpCache != null) + otpCache.put(authKey, generatedPassword); + else { + BeneficiaryOTPHandlerImpl obj = new BeneficiaryOTPHandlerImpl(); + obj.otpCache.put(authKey, generatedPassword); + } + return otp; + } + + // SHA-256 encoding logic implemented + private String getEncryptedOTP(int otp) throws Exception { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + byte[] bytes = md.digest(Ints.toByteArray(otp)); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < bytes.length; i++) { + sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1)); + } + + return sb.toString(); + } + + // send SMS to beneficiary + + + public String sendSMS(int otp, BeneficiaryConsentRequest obj) { + + final RestTemplate restTemplate = new RestTemplate(); + String sendSMSURL = ConfigProperties.getPropertyByName("send-message-url"); + + String sendSMSAPI = BeneficiaryOTPHandlerImpl.SMS_GATEWAY_URL + "/" + sendSMSURL; + + + try { + + +// String message = "Dear Citizen, your OTP for login is " +otp+". Use it within 15 minutes. Do not share this code. Regards PSMRIAM."; + String message = "Hello! Your OTP for providing consent for registration on AMRIT is " + otp + ". This OTP is valid for 10 minutes. Kindly share it only with " + obj.getUserName() + " " + obj.getDesignation() + " to complete the process. PSMRI"; + + // Build payload + Map payload = new HashMap<>(); + payload.put("customerId", ConfigProperties.getPropertyByName("sms-username")); + payload.put("destinationAddress", obj.getMobNo()); + payload.put("message", message); + payload.put("sourceAddress", ConfigProperties.getPropertyByName("source-address")); + payload.put("messageType", "SERVICE_IMPLICIT"); + payload.put("dltTemplateId", ConfigProperties.getPropertyByName("dltTemplateId")); + payload.put("entityId",ConfigProperties.getPropertyByName("entityId") ); + payload.put("otp", true); + // Set headers + HttpHeaders headers = new HttpHeaders(); + String auth = ConfigProperties.getPropertyByName("sms-username") + ":" + ConfigProperties.getPropertyByName("sms-password"); + headers.add("Authorization", + "Basic " + Base64.getEncoder().encodeToString(auth.getBytes())); + + headers.setContentType(MediaType.APPLICATION_JSON); + + HttpEntity> request = new HttpEntity<>(payload, headers); + + // Call API + ResponseEntity response = restTemplate.postForEntity(sendSMSAPI, request, String.class); + + // Return response + return response.getBody(); + + } catch (Exception e) { + e.printStackTrace(); + return "Error sending SMS: " + e.getMessage(); + } + } + +} From bab8d0a365a92dee755316b0ebec77ee4dc00416 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 19 Jun 2025 13:03:00 +0530 Subject: [PATCH 17/27] Firebase update userToken --- .../FirebaseNotificationController.java | 13 +++++ .../common/data/userToken/UserTokenData.java | 22 ++++++++ .../notification/NotificationMessage.java | 1 - .../common/model/notification/UserToken.java | 9 ++++ .../FirebaseNotificationService.java | 53 +++++++++++++++++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/iemr/common/data/userToken/UserTokenData.java create mode 100644 src/main/java/com/iemr/common/model/notification/UserToken.java diff --git a/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java b/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java index 18601d22..3e39fe21 100644 --- a/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java +++ b/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java @@ -1,7 +1,9 @@ package com.iemr.common.controller.firebaseNotification; import com.iemr.common.model.notification.NotificationMessage; +import com.iemr.common.model.notification.UserToken; import com.iemr.common.service.firebaseNotification.FirebaseNotificationService; +import com.iemr.common.utils.exception.IEMRException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -20,5 +22,16 @@ public String sendNotificationByToken(@RequestBody NotificationMessage notificat return firebaseNotificationService.sendNotification(notificationMessage); } + @RequestMapping(value = "updateToken",method = RequestMethod.POST) + public String updateToken(@RequestBody UserToken userToken){ + return firebaseNotificationService.updateToken(userToken); + } + + @RequestMapping(value = "getToken",method = RequestMethod.GET,headers = "Authorization") + public String getUserToken() throws IEMRException { + + return firebaseNotificationService.getUserToken(); + } + } diff --git a/src/main/java/com/iemr/common/data/userToken/UserTokenData.java b/src/main/java/com/iemr/common/data/userToken/UserTokenData.java new file mode 100644 index 00000000..f27d74e4 --- /dev/null +++ b/src/main/java/com/iemr/common/data/userToken/UserTokenData.java @@ -0,0 +1,22 @@ +package com.iemr.common.data.userToken; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Data; + +import java.sql.Timestamp; + +@Entity +@Table(name = "user_tokens", schema = "db_iemr") +@Data +public class UserTokenData { + @Id + @Column(name = "user_id") + Integer userId; + @Column(name = "token") + String token; + @Column(name = "updated_at") + Timestamp updatedAt; +} diff --git a/src/main/java/com/iemr/common/model/notification/NotificationMessage.java b/src/main/java/com/iemr/common/model/notification/NotificationMessage.java index eed0c171..c81f68c4 100644 --- a/src/main/java/com/iemr/common/model/notification/NotificationMessage.java +++ b/src/main/java/com/iemr/common/model/notification/NotificationMessage.java @@ -8,7 +8,6 @@ public class NotificationMessage { private String appType; private String token; - private String topic; private String title; private String body; private Map data; diff --git a/src/main/java/com/iemr/common/model/notification/UserToken.java b/src/main/java/com/iemr/common/model/notification/UserToken.java new file mode 100644 index 00000000..d68d6c5e --- /dev/null +++ b/src/main/java/com/iemr/common/model/notification/UserToken.java @@ -0,0 +1,9 @@ +package com.iemr.common.model.notification; + +import lombok.Data; + +@Data +public class UserToken { + Integer userId; + String token; +} diff --git a/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java b/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java index e41ca94f..0fe37b5a 100644 --- a/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java +++ b/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java @@ -4,11 +4,23 @@ import com.google.firebase.messaging.FirebaseMessaging; import com.google.firebase.messaging.Message; import com.google.firebase.messaging.Notification; +import com.iemr.common.data.userToken.UserTokenData; import com.iemr.common.model.notification.NotificationMessage; +import com.iemr.common.model.notification.UserToken; +import com.iemr.common.repo.userToken.UserTokenRepo; +import com.iemr.common.utils.CookieUtil; +import com.iemr.common.utils.JwtUtil; +import com.iemr.common.utils.exception.IEMRException; +import jakarta.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.sql.Timestamp; +import java.util.Optional; @Service public class FirebaseNotificationService { @@ -17,6 +29,16 @@ public class FirebaseNotificationService { @Autowired FirebaseMessaging firebaseMessaging; + @Autowired + private UserTokenRepo userTokenRepo; + + @Autowired + private CookieUtil cookieUtil; + + @Autowired + private JwtUtil jwtUtil; + + public String sendNotification(NotificationMessage notificationMessage) { Notification notification = Notification.builder().setTitle(notificationMessage.getTitle()).setBody(notificationMessage.getBody()).build(); @@ -34,4 +56,35 @@ public String sendNotification(NotificationMessage notificationMessage) { } } + public String updateToken(UserToken userToken) { + Optional existingTokenData = userTokenRepo.findById(userToken.getUserId()); + + UserTokenData userTokenData; + + if (existingTokenData.isPresent()) { + // User token exist karta hai => update karna hai + userTokenData = existingTokenData.get(); + userTokenData.setToken(userToken.getToken()); + userTokenData.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + } else { + // User token nahi mila => naya insert karna hai + userTokenData = new UserTokenData(); + userTokenData.setUserId(userToken.getUserId()); + userTokenData.setToken(userToken.getToken()); + userTokenData.setUpdatedAt(new Timestamp(System.currentTimeMillis())); + } + + userTokenRepo.save(userTokenData); + return "Save Successfully"; + } + + public String getUserToken() throws IEMRException { + HttpServletRequest requestHeader = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) + .getRequest(); + String jwtTokenFromCookie = cookieUtil.getJwtTokenFromCookie(requestHeader); + return userTokenRepo.findById(Integer.parseInt(jwtUtil.extractUserId(jwtTokenFromCookie))) // because your userId is Long in DB + .map(UserTokenData::getToken) // mil gaya to token nikalo + .orElse(null); // nah + } + } From 8f8cc6f0d62a1099eb1efe7e75ee334f099095a3 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 19 Jun 2025 13:04:41 +0530 Subject: [PATCH 18/27] Firebase update userToken --- .../FirebaseNotificationController.java | 24 ++++++++++++++ .../common/data/userToken/UserTokenData.java | 24 ++++++++++++++ .../notification/NotificationMessage.java | 24 ++++++++++++++ .../common/model/notification/UserToken.java | 24 ++++++++++++++ .../common/repo/userToken/UserTokenRepo.java | 31 +++++++++++++++++++ .../FirebaseNotificationService.java | 24 ++++++++++++++ 6 files changed, 151 insertions(+) create mode 100644 src/main/java/com/iemr/common/repo/userToken/UserTokenRepo.java diff --git a/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java b/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java index 3e39fe21..89fb01a9 100644 --- a/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java +++ b/src/main/java/com/iemr/common/controller/firebaseNotification/FirebaseNotificationController.java @@ -1,3 +1,27 @@ +/* +* AMRIT – Accessible Medical Records via Integrated Technology +* Integrated EHR (Electronic Health Records) Solution +* +* Copyright (C) "Piramal Swasthya Management and Research Institute" +* +* This file is part of AMRIT. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +* +/* +* AMRIT – Accessible Medical Records via Integrated Technology +*/ package com.iemr.common.controller.firebaseNotification; import com.iemr.common.model.notification.NotificationMessage; diff --git a/src/main/java/com/iemr/common/data/userToken/UserTokenData.java b/src/main/java/com/iemr/common/data/userToken/UserTokenData.java index f27d74e4..0646972e 100644 --- a/src/main/java/com/iemr/common/data/userToken/UserTokenData.java +++ b/src/main/java/com/iemr/common/data/userToken/UserTokenData.java @@ -1,3 +1,27 @@ +/* +* AMRIT – Accessible Medical Records via Integrated Technology +* Integrated EHR (Electronic Health Records) Solution +* +* Copyright (C) "Piramal Swasthya Management and Research Institute" +* +* This file is part of AMRIT. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +* +/* +* AMRIT – Accessible Medical Records via Integrated Technology +*/ package com.iemr.common.data.userToken; import jakarta.persistence.Column; diff --git a/src/main/java/com/iemr/common/model/notification/NotificationMessage.java b/src/main/java/com/iemr/common/model/notification/NotificationMessage.java index c81f68c4..58343034 100644 --- a/src/main/java/com/iemr/common/model/notification/NotificationMessage.java +++ b/src/main/java/com/iemr/common/model/notification/NotificationMessage.java @@ -1,3 +1,27 @@ +/* +* AMRIT – Accessible Medical Records via Integrated Technology +* Integrated EHR (Electronic Health Records) Solution +* +* Copyright (C) "Piramal Swasthya Management and Research Institute" +* +* This file is part of AMRIT. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +* +/* +* AMRIT – Accessible Medical Records via Integrated Technology +*/ package com.iemr.common.model.notification; import lombok.Data; diff --git a/src/main/java/com/iemr/common/model/notification/UserToken.java b/src/main/java/com/iemr/common/model/notification/UserToken.java index d68d6c5e..3ea36588 100644 --- a/src/main/java/com/iemr/common/model/notification/UserToken.java +++ b/src/main/java/com/iemr/common/model/notification/UserToken.java @@ -1,3 +1,27 @@ +/* +* AMRIT – Accessible Medical Records via Integrated Technology +* Integrated EHR (Electronic Health Records) Solution +* +* Copyright (C) "Piramal Swasthya Management and Research Institute" +* +* This file is part of AMRIT. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +* +/* +* AMRIT – Accessible Medical Records via Integrated Technology +*/ package com.iemr.common.model.notification; import lombok.Data; diff --git a/src/main/java/com/iemr/common/repo/userToken/UserTokenRepo.java b/src/main/java/com/iemr/common/repo/userToken/UserTokenRepo.java new file mode 100644 index 00000000..817f26f0 --- /dev/null +++ b/src/main/java/com/iemr/common/repo/userToken/UserTokenRepo.java @@ -0,0 +1,31 @@ +/* +* AMRIT – Accessible Medical Records via Integrated Technology +* Integrated EHR (Electronic Health Records) Solution +* +* Copyright (C) "Piramal Swasthya Management and Research Institute" +* +* This file is part of AMRIT. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +* +/* +* AMRIT – Accessible Medical Records via Integrated Technology +*/ +package com.iemr.common.repo.userToken; + +import com.iemr.common.data.userToken.UserTokenData; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserTokenRepo extends JpaRepository { +} diff --git a/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java b/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java index 0fe37b5a..7705fb9e 100644 --- a/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java +++ b/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java @@ -1,3 +1,27 @@ +/* +* AMRIT – Accessible Medical Records via Integrated Technology +* Integrated EHR (Electronic Health Records) Solution +* +* Copyright (C) "Piramal Swasthya Management and Research Institute" +* +* This file is part of AMRIT. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see https://www.gnu.org/licenses/. +* +/* +* AMRIT – Accessible Medical Records via Integrated Technology +*/ package com.iemr.common.service.firebaseNotification; import com.google.firebase.FirebaseException; From f6ca2b92ec6ef6f92a67747eeb7aa5e1bdd09c71 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 19 Jun 2025 18:33:51 +0530 Subject: [PATCH 19/27] Add firebase variables in common_docker.properties --- src/main/environment/common_docker.properties | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/environment/common_docker.properties b/src/main/environment/common_docker.properties index 56e2a2fe..ff2cde29 100644 --- a/src/main/environment/common_docker.properties +++ b/src/main/environment/common_docker.properties @@ -178,4 +178,11 @@ captcha.secret-key=${CAPTCHA_SECRET_KEY} captcha.verify-url=${CAPTCHA_VERIFY_URL} captcha.enable-captcha=${ENABLE_CAPTCHA} -cors.allowed-origins=${CORS_ALLOWED_ORIGINS} \ No newline at end of file +cors.allowed-origins=${CORS_ALLOWED_ORIGINS} + +# Firebase Configuration +firebase.enabled=@env.FIREBASE_ENABLE@ +# if using file +firebase.credential-file=@env.FIREBASE_CREDENTIAL@ +# for CI/CD +firebase.credential-base64=@env.CREDENTIAL_BASE64@ \ No newline at end of file From 825c2c2697c1ac5438a844517f5b25c19c6f49b7 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Thu, 19 Jun 2025 20:06:02 +0530 Subject: [PATCH 20/27] Add firebase variables in common_docker.properties --- .../firebaseNotification/FirebaseNotificationService.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java b/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java index 7705fb9e..ea0cc005 100644 --- a/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java +++ b/src/main/java/com/iemr/common/service/firebaseNotification/FirebaseNotificationService.java @@ -86,12 +86,10 @@ public String updateToken(UserToken userToken) { UserTokenData userTokenData; if (existingTokenData.isPresent()) { - // User token exist karta hai => update karna hai userTokenData = existingTokenData.get(); userTokenData.setToken(userToken.getToken()); userTokenData.setUpdatedAt(new Timestamp(System.currentTimeMillis())); } else { - // User token nahi mila => naya insert karna hai userTokenData = new UserTokenData(); userTokenData.setUserId(userToken.getUserId()); userTokenData.setToken(userToken.getToken()); @@ -107,8 +105,8 @@ public String getUserToken() throws IEMRException { .getRequest(); String jwtTokenFromCookie = cookieUtil.getJwtTokenFromCookie(requestHeader); return userTokenRepo.findById(Integer.parseInt(jwtUtil.extractUserId(jwtTokenFromCookie))) // because your userId is Long in DB - .map(UserTokenData::getToken) // mil gaya to token nikalo - .orElse(null); // nah + .map(UserTokenData::getToken) + .orElse(null); // } } From 02c5a8921247246cb1708b8f0d40e2f059c91547 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Fri, 20 Jun 2025 10:43:43 +0530 Subject: [PATCH 21/27] update firebase variables in common_docker.properties --- .../java/com/iemr/common/utils/JwtUtil.java | 238 +++++++----------- 1 file changed, 90 insertions(+), 148 deletions(-) diff --git a/src/main/java/com/iemr/common/utils/JwtUtil.java b/src/main/java/com/iemr/common/utils/JwtUtil.java index dc29018c..0ea70bda 100644 --- a/src/main/java/com/iemr/common/utils/JwtUtil.java +++ b/src/main/java/com/iemr/common/utils/JwtUtil.java @@ -1,164 +1,106 @@ package com.iemr.common.utils; -import io.jsonwebtoken.*; -import io.jsonwebtoken.security.Keys; +import java.util.Date; +import java.util.UUID; +import java.util.function.Function; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.UnsupportedJwtException; +import io.jsonwebtoken.security.Keys; +import io.jsonwebtoken.security.SignatureException; + import javax.crypto.SecretKey; -import java.util.Date; -import java.util.UUID; -import java.util.function.Function; @Component public class JwtUtil { - @Value("${jwt.secret}") - private String SECRET_KEY; - - @Value("${jwt.access.expiration}") - private long ACCESS_EXPIRATION_TIME; - - @Value("${jwt.refresh.expiration}") - private long REFRESH_EXPIRATION_TIME; - - @Autowired - private TokenDenylist tokenDenylist; - - private SecretKey getSigningKey() { - if (SECRET_KEY == null || SECRET_KEY.isEmpty()) { - throw new IllegalStateException("JWT secret key is not set in application.properties"); - } - return Keys.hmacShaKeyFor(SECRET_KEY.getBytes()); - } - - /** - * Generate an access token. - * - * @param username the username of the user - * @param userId the user ID - * @return the generated JWT access token - */ - public String generateToken(String username, String userId) { - return buildToken(username, userId, "access", ACCESS_EXPIRATION_TIME); - } - - /** - * Generate a refresh token. - * - * @param username the username of the user - * @param userId the user ID - * @return the generated JWT refresh token - */ - public String generateRefreshToken(String username, String userId) { - return buildToken(username, userId, "refresh", REFRESH_EXPIRATION_TIME); - } - - /** - * Build a JWT token with the specified parameters. - * - * @param username the username of the user - * @param userId the user ID - * @param tokenType the type of the token (access or refresh) - * @param expiration the expiration time of the token in milliseconds - * @return the generated JWT token - */ - private String buildToken(String username, String userId, String tokenType, long expiration) { - return Jwts.builder() - .subject(username) - .claim("userId", userId) - .claim("token_type", tokenType) - .id(UUID.randomUUID().toString()) - .issuedAt(new Date()) - .expiration(new Date(System.currentTimeMillis() + expiration)) - .signWith(getSigningKey()) - .compact(); - } - - /** - * Validate the JWT token, checking if it is expired and if it's blacklisted - * @param token the JWT token - * @return Claims if valid, null if invalid (expired or denylisted) - */ - public Claims validateToken(String token) { - try { - Claims claims = Jwts.parser().verifyWith(getSigningKey()).build().parseSignedClaims(token).getPayload(); - String jti = claims.getId(); - - // Check if token is denylisted (only if jti exists) - if (jti != null && tokenDenylist.isTokenDenylisted(jti)) { - return null; - } - - return claims; - } catch (ExpiredJwtException ex) { - - return null; // Token is expired, so return null - } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException ex) { - return null; // Return null for any other JWT-related issue (invalid format, bad signature, etc.) - } - } - - /** - * Extract claims from the token - * @param token the JWT token - * @return all claims from the token - */ - public Claims getAllClaimsFromToken(String token) { - return Jwts.parser() + @Value("${jwt.secret}") + private String SECRET_KEY; + + @Value("${jwt.access.expiration}") + private long ACCESS_EXPIRATION_TIME; + + @Value("${jwt.refresh.expiration}") + private long REFRESH_EXPIRATION_TIME; + + private SecretKey getSigningKey() { + if (SECRET_KEY == null || SECRET_KEY.isEmpty()) { + throw new IllegalStateException("JWT secret key is not set in application.properties"); + } + return Keys.hmacShaKeyFor(SECRET_KEY.getBytes()); + } + + public String generateToken(String username, String userId) { + return buildToken(username, userId, "access", ACCESS_EXPIRATION_TIME); + } + + public String generateRefreshToken(String username, String userId) { + return buildToken(username, userId, "refresh", REFRESH_EXPIRATION_TIME); + } + + private String buildToken(String username, String userId, String tokenType, long expiration) { + return Jwts.builder() + .subject(username) + .claim("userId", userId) + .claim("token_type", tokenType) + .id(UUID.randomUUID().toString()) + .issuedAt(new Date()) + .expiration(new Date(System.currentTimeMillis() + expiration)) + .signWith(getSigningKey()) + .compact(); + } + + public Claims validateToken(String token) { + try { + return Jwts.parser() + .verifyWith(getSigningKey()) + .build() + .parseSignedClaims(token) + .getPayload(); + + } catch (ExpiredJwtException ex) { + // Handle expired token specifically if needed + } catch (UnsupportedJwtException | MalformedJwtException | SignatureException | IllegalArgumentException ex) { + // Log specific error types + } + return null; + } + + public T getClaimFromToken(String token, Function claimsResolver) { + final Claims claims = getAllClaimsFromToken(token); + return claimsResolver.apply(claims); + } + + public Claims getAllClaimsFromToken(String token) { + return Jwts.parser() .verifyWith(getSigningKey()) .build() .parseSignedClaims(token) .getPayload(); + } + + + public long getRefreshTokenExpiration() { + return REFRESH_EXPIRATION_TIME; + } + + // Additional helper methods + public String getJtiFromToken(String token) { + return getAllClaimsFromToken(token).getId(); + } + + public String getUsernameFromToken(String token) { + return getAllClaimsFromToken(token).getSubject(); + } + + public String extractUserId(String token) { + return getAllClaimsFromToken(token).getId(); - } - - /** - * Extract a specific claim from the token using a function - * @param token the JWT token - * @param claimsResolver the function to extract the claim - * @param the type of the claim - * @return the extracted claim - */ - public T getClaimFromToken(String token, Function claimsResolver) { - final Claims claims = getAllClaimsFromToken(token); - return claimsResolver.apply(claims); - } - - /** - * Get the JWT ID (JTI) from the token - * @param token the JWT token - * @return the JWT ID - */ - public String getJtiFromToken(String token) { - return getAllClaimsFromToken(token).getId(); - } - - /** - * Get the username from the token - * @param token the JWT token - * @return the username - */ - public String getUsernameFromToken(String token) { - return getAllClaimsFromToken(token).getSubject(); - } - - /** - * Get the user ID from the token - * @param token the JWT token - * @return the user ID - */ - public String getUserIdFromToken(String token) { - return getAllClaimsFromToken(token).get("userId", String.class); - } - - /** - * Get the expiration time of the refresh token - * @return the expiration time in milliseconds - */ - public long getRefreshTokenExpiration() { - return REFRESH_EXPIRATION_TIME; - } -} + } +} \ No newline at end of file From 6e9d25316441c43445b14c864811efd969d195ac Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Fri, 20 Jun 2025 11:05:35 +0530 Subject: [PATCH 22/27] update firebase variables in common_docker.properties --- src/main/environment/common_docker.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/environment/common_docker.properties b/src/main/environment/common_docker.properties index ff2cde29..999252c0 100644 --- a/src/main/environment/common_docker.properties +++ b/src/main/environment/common_docker.properties @@ -181,8 +181,8 @@ captcha.enable-captcha=${ENABLE_CAPTCHA} cors.allowed-origins=${CORS_ALLOWED_ORIGINS} # Firebase Configuration -firebase.enabled=@env.FIREBASE_ENABLE@ +firebase.enabled= ${FIREBASE_ENABLE} # if using file -firebase.credential-file=@env.FIREBASE_CREDENTIAL@ +firebase.credential-file= ${FIREBASE_CREDENTIAL} # for CI/CD -firebase.credential-base64=@env.CREDENTIAL_BASE64@ \ No newline at end of file +firebase.credential-base64= ${CREDENTIAL_BASE64} \ No newline at end of file From cbe0d55c12b43ff104185c57af10614e6d7d0791 Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Fri, 20 Jun 2025 11:07:04 +0530 Subject: [PATCH 23/27] update firebase variables in common_docker.properties --- src/main/environment/common_docker.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/environment/common_docker.properties b/src/main/environment/common_docker.properties index 999252c0..7fc32ba3 100644 --- a/src/main/environment/common_docker.properties +++ b/src/main/environment/common_docker.properties @@ -181,8 +181,8 @@ captcha.enable-captcha=${ENABLE_CAPTCHA} cors.allowed-origins=${CORS_ALLOWED_ORIGINS} # Firebase Configuration -firebase.enabled= ${FIREBASE_ENABLE} +firebase.enabled=${FIREBASE_ENABLE} # if using file -firebase.credential-file= ${FIREBASE_CREDENTIAL} +firebase.credential-file=${FIREBASE_CREDENTIAL} # for CI/CD -firebase.credential-base64= ${CREDENTIAL_BASE64} \ No newline at end of file +firebase.credential-base64=${CREDENTIAL_BASE64} \ No newline at end of file From 37aadb58a4a9d76ef61a6286add9b37ac008eb5b Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Sat, 21 Jun 2025 11:17:38 +0530 Subject: [PATCH 24/27] fixed code --- .../com/iemr/common/model/beneficiary/BeneficiaryModel.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java b/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java index 8b00263a..a6bd9eca 100644 --- a/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java +++ b/src/main/java/com/iemr/common/model/beneficiary/BeneficiaryModel.java @@ -91,8 +91,7 @@ public class BeneficiaryModel implements Comparable { private TitleModel m_title; @Expose private String firstName; - @Expose - private Boolean isConsent=false; + @Expose private String middleName; From 599ed6e45351d39c8a6c1c766e882f07f896a6ae Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Sat, 21 Jun 2025 11:29:03 +0530 Subject: [PATCH 25/27] fixed code --- .../beneficiaryConsent/BeneficiaryConsentController.java | 4 ++-- .../com/iemr/common/controller/users/IEMRAdminController.java | 2 +- .../java/com/iemr/common/dto/identity/CommonIdentityDTO.java | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java b/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java index 60c7bdee..3b89f63e 100644 --- a/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java +++ b/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java @@ -54,7 +54,7 @@ public String validateConsent(@Param(value = "{\"mobNo\":\"String\",\"otp\":\"In OutputResponse response = new OutputResponse(); try { - OTPRequestParsor obj = InputMapper.gson().fromJson(requestOBJ, OTPRequestParsor.class); + BeneficiaryConsentRequest obj = InputMapper.gson().fromJson(requestOBJ, BeneficiaryConsentRequest.class); JSONObject responseOBJ = beneficiaryOTPHandler.validateOTP(obj); if (responseOBJ != null) @@ -77,7 +77,7 @@ public String resendConsent(@Param(value = "{\"mobNo\":\"String\"}") @RequestBod OutputResponse response = new OutputResponse(); try { - OTPRequestParsor obj = InputMapper.gson().fromJson(requestOBJ, OTPRequestParsor.class); + BeneficiaryConsentRequest obj = InputMapper.gson().fromJson(requestOBJ, BeneficiaryConsentRequest.class); String success = beneficiaryOTPHandler.resendOTP(obj); logger.info(success.toString()); diff --git a/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java b/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java index 81acd8ca..4a1af2a2 100644 --- a/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java +++ b/src/main/java/com/iemr/common/controller/users/IEMRAdminController.java @@ -567,7 +567,7 @@ public String getLoginResponse(HttpServletRequest request) { } // Extract user ID from the JWT token - String userId = jwtUtil.getUserIdFromToken(jwtToken); + String userId = jwtUtil.extractUserId(jwtToken); // Get user details and prepare response User user = iemrAdminUserServiceImpl.getUserById(Long.parseLong(userId)); diff --git a/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java b/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java index c057b58d..8e364eb3 100644 --- a/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java +++ b/src/main/java/com/iemr/common/dto/identity/CommonIdentityDTO.java @@ -61,7 +61,6 @@ public class CommonIdentityDTO { private Integer educationId; private String education; private Boolean emergencyRegistration = false; - private Boolean isConsent; private Integer healthCareWorkerId; private String healthCareWorker; private String fatherName; From 4970f1e2f4a1dd4d370f2401c56cf71a5b731ece Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Mon, 23 Jun 2025 11:57:37 +0530 Subject: [PATCH 26/27] Fixed security hotspot --- .../BeneficiaryConsentController.java | 25 ++++++++++++++++--- .../BeneficiaryOTPHandlerImpl.java | 1 - 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java b/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java index 3b89f63e..e8e55034 100644 --- a/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java +++ b/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java @@ -1,9 +1,28 @@ +/* + * AMRIT – Accessible Medical Records via Integrated Technology + * Integrated EHR (Electronic Health Records) Solution + * + * Copyright (C) "Piramal Swasthya Management and Research Institute" + * + * This file is part of AMRIT. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ package com.iemr.common.controller.beneficiaryConsent; import com.iemr.common.data.beneficiaryConsent.BeneficiaryConsentRequest; -import com.iemr.common.data.otp.OTPRequestParsor; import com.iemr.common.service.beneficiaryOTPHandler.BeneficiaryOTPHandler; -import com.iemr.common.service.otp.OTPHandler; import com.iemr.common.utils.mapper.InputMapper; import com.iemr.common.utils.response.OutputResponse; import io.lettuce.core.dynamic.annotation.Param; @@ -26,7 +45,6 @@ public class BeneficiaryConsentController { @Operation(summary = "Send Consent") @RequestMapping(value = "/sendConsent", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON, headers = "Authorization") public String sendConsent(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody String requestOBJ) { - logger.info(requestOBJ.toString()); OutputResponse response = new OutputResponse(); @@ -41,7 +59,6 @@ public String sendConsent(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody response.setError(500, "failure"); } catch (Exception e) { - logger.error("error in sending Consent : " + e); response.setError(500, "error : " + e); } return response.toString(); diff --git a/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java index 9fa73005..6f791a87 100644 --- a/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java +++ b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java @@ -199,7 +199,6 @@ public String sendSMS(int otp, BeneficiaryConsentRequest obj) { return response.getBody(); } catch (Exception e) { - e.printStackTrace(); return "Error sending SMS: " + e.getMessage(); } } From 41b327b5a29ffdb6d0851f38dc3976ea7de0088e Mon Sep 17 00:00:00 2001 From: Saurav Mishra Date: Mon, 23 Jun 2025 17:41:23 +0530 Subject: [PATCH 27/27] Fixed security hotspot --- .../BeneficiaryConsentController.java | 9 +++--- .../BeneficiaryOTPHandlerImpl.java | 31 ++++++++++--------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java b/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java index e8e55034..e917204c 100644 --- a/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java +++ b/src/main/java/com/iemr/common/controller/beneficiaryConsent/BeneficiaryConsentController.java @@ -35,7 +35,10 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; +@RequestMapping(value = { "/beneficiaryConsent" },headers ="Authorization" ) +@RestController public class BeneficiaryConsentController { final Logger logger = LoggerFactory.getLogger(this.getClass().getName()); @@ -53,10 +56,8 @@ public String sendConsent(@Param(value = "{\"mobNo\":\"String\"}") @RequestBody String success = beneficiaryOTPHandler.sendOTP(obj); // method name unchanged if internal logic still uses 'OTP' logger.info(success.toString()); - if (success.contains("otp")) - response.setResponse(success); - else - response.setError(500, "failure"); + response.setResponse(success); + } catch (Exception e) { response.setError(500, "error : " + e); diff --git a/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java index 6f791a87..17027667 100644 --- a/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java +++ b/src/main/java/com/iemr/common/service/beneficiaryOTPHandler/BeneficiaryOTPHandlerImpl.java @@ -87,8 +87,7 @@ public String load(String key) { @Override public String sendOTP(BeneficiaryConsentRequest obj) throws Exception { int otp = generateOTP(obj.getMobNo()); - sendSMS(otp, obj); - return "success"; + return sendSMS(otp, obj); } /*** @@ -122,8 +121,7 @@ public JSONObject validateOTP(BeneficiaryConsentRequest obj) throws Exception { @Override public String resendOTP(BeneficiaryConsentRequest obj) throws Exception { int otp = generateOTP(obj.getMobNo()); - sendSMS(otp, obj); - return "success"; + return sendSMS(otp, obj); } // generate 6 digit random no # @@ -161,16 +159,17 @@ private String getEncryptedOTP(int otp) throws Exception { public String sendSMS(int otp, BeneficiaryConsentRequest obj) { final RestTemplate restTemplate = new RestTemplate(); - String sendSMSURL = ConfigProperties.getPropertyByName("send-message-url"); - String sendSMSAPI = BeneficiaryOTPHandlerImpl.SMS_GATEWAY_URL + "/" + sendSMSURL; + String dltTemplateId = smsTemplateRepository.findDLTTemplateID(28); + SMSTemplate template = smsTemplateRepository.findBySmsTemplateID(28); + String sendSMSAPI = BeneficiaryOTPHandlerImpl.SMS_GATEWAY_URL; try { - - -// String message = "Dear Citizen, your OTP for login is " +otp+". Use it within 15 minutes. Do not share this code. Regards PSMRIAM."; - String message = "Hello! Your OTP for providing consent for registration on AMRIT is " + otp + ". This OTP is valid for 10 minutes. Kindly share it only with " + obj.getUserName() + " " + obj.getDesignation() + " to complete the process. PSMRI"; + String message = template.getSmsTemplate() + .replace("$$OTP$$",String.valueOf(otp)) + .replace("$$UserName$$", obj.getUserName()) + .replace("$$Designation$$", obj.getDesignation()); // Build payload Map payload = new HashMap<>(); @@ -179,8 +178,8 @@ public String sendSMS(int otp, BeneficiaryConsentRequest obj) { payload.put("message", message); payload.put("sourceAddress", ConfigProperties.getPropertyByName("source-address")); payload.put("messageType", "SERVICE_IMPLICIT"); - payload.put("dltTemplateId", ConfigProperties.getPropertyByName("dltTemplateId")); - payload.put("entityId",ConfigProperties.getPropertyByName("entityId") ); + payload.put("dltTemplateId", dltTemplateId); + payload.put("entityId",ConfigProperties.getPropertyByName("sms-entityid") ); payload.put("otp", true); // Set headers HttpHeaders headers = new HttpHeaders(); @@ -194,9 +193,13 @@ public String sendSMS(int otp, BeneficiaryConsentRequest obj) { // Call API ResponseEntity response = restTemplate.postForEntity(sendSMSAPI, request, String.class); + logger.info("sms-response:"+response.getBody()); + if(response.getStatusCode().value()==200){ + return "OTP sent successfully on register mobile number"; + }else { + return "Fail"; - // Return response - return response.getBody(); + } } catch (Exception e) { return "Error sending SMS: " + e.getMessage();