From 035c27d69c003567c27b739af319de81d200c40c Mon Sep 17 00:00:00 2001
From: KOPPIREDDY DURGA PRASAD
<144464542+DurgaPrasad-54@users.noreply.github.com>
Date: Tue, 20 Jan 2026 23:47:29 +0530
Subject: [PATCH 1/6] docs(readme): add documentation badge (#132)
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index ba44e2c4..3b1a235e 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# AMRIT - Identity Service
-[](https://www.gnu.org/licenses/gpl-3.0) 
+[](https://www.gnu.org/licenses/gpl-3.0) [](https://deepwiki.com/PSMRI/Identity-API)
Identity API is a microservice which is used for the creation and management of beneficaries.
From 29c461c16f4fc3c0cdd83b812d322c0fe197f246 Mon Sep 17 00:00:00 2001
From: KOPPIREDDY DURGA PRASAD
<144464542+DurgaPrasad-54@users.noreply.github.com>
Date: Wed, 11 Feb 2026 19:47:01 +0530
Subject: [PATCH 2/6] Swagger json Automation (#134)
* docs(readme): add documentation badge
* chore(swagger): automate swagger sync to amrit-docs
* chore(swagger): automate swagger sync to amrit-docs
* chore(swagger): update github workflow for swagger json
* fix(swagger): fix the stop api issue in swagger workflow
* fix(swagger): removed the unnecessary initial sleep
---
.github/workflows/swagger-json.yml | 108 ++++++++++++++++++
pom.xml | 5 +
.../common/identity/utils/FilterConfig.java | 2 +
.../resources/application-swagger.properties | 15 +++
4 files changed, 130 insertions(+)
create mode 100644 .github/workflows/swagger-json.yml
create mode 100644 src/main/resources/application-swagger.properties
diff --git a/.github/workflows/swagger-json.yml b/.github/workflows/swagger-json.yml
new file mode 100644
index 00000000..afd552e4
--- /dev/null
+++ b/.github/workflows/swagger-json.yml
@@ -0,0 +1,108 @@
+name: Sync Swagger to AMRIT-Docs
+
+on:
+ push:
+ branches: [ main ]
+ workflow_dispatch:
+
+jobs:
+ swagger-sync:
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+
+ steps:
+ - name: Checkout API repo
+ uses: actions/checkout@v4
+
+ - name: Set up Java 17
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 17
+ cache: maven
+
+ - name: Build API (skip tests)
+ run: mvn -B clean package -DskipTests
+
+ - name: Install jq
+ run: sudo apt-get update && sudo apt-get install -y jq
+
+ - name: Run API in swagger profile
+ run: |
+ nohup java -jar target/identity-api-*.war \
+ --spring.profiles.active=swagger \
+ --server.port=9090 \
+ > app.log 2>&1 &
+ echo $! > api_pid.txt
+
+ - name: Wait for API & fetch Swagger
+ run: |
+ for i in {1..40}; do
+ CODE=$(curl --connect-timeout 2 --max-time 5 -s -o swagger_raw.json -w "%{http_code}" http://localhost:9090/v3/api-docs || true)
+
+ if [ "$CODE" = "200" ]; then
+ jq . swagger_raw.json > identity-api.json || {
+ echo "Swagger JSON invalid"
+ cat swagger_raw.json
+ exit 1
+ }
+
+ if [ "$(jq '.paths | length' identity-api.json)" -eq 0 ]; then
+ echo "Swagger paths empty – failing"
+ exit 1
+ fi
+
+ echo "Swagger generated successfully"
+ exit 0
+ fi
+
+ echo "Waiting for API... ($i)"
+ sleep 4
+ done
+
+ echo "Swagger not generated"
+ cat app.log || true
+ exit 1
+
+ - name: Stop API
+ if: always()
+ run: |
+ # Attempt graceful shutdown by PID
+ if [ -f api_pid.txt ]; then
+ PID=$(cat api_pid.txt)
+ kill -TERM "$PID" 2>/dev/null || true
+ sleep 2
+ kill -9 "$PID" 2>/dev/null || true
+ fi
+ # Fallback: kill whatever is listening on port 9090
+ fuser -k 9090/tcp 2>/dev/null || true
+ sleep 2
+ # Force-kill if still lingering
+ fuser -k -KILL 9090/tcp 2>/dev/null || true
+
+ - name: Checkout AMRIT-Docs
+ uses: actions/checkout@v4
+ with:
+ repository: PSMRI/AMRIT-Docs
+ token: ${{ secrets.DOCS_REPO_TOKEN }}
+ path: amrit-docs
+ fetch-depth: 0
+
+ - name: Copy Swagger JSON
+ run: |
+ mkdir -p amrit-docs/docs/swagger
+ cp identity-api.json amrit-docs/docs/swagger/identity-api.json
+
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v8
+ with:
+ token: ${{ secrets.DOCS_REPO_TOKEN }}
+ path: amrit-docs
+ branch: auto/swagger-update-${{ github.run_id }}-${{ github.run_attempt }}
+ base: main
+ commit-message: "chore(docs): auto-update identity-api swagger"
+ title: "chore(docs): auto-update identity-api swagger"
+ delete-branch: true
+ body: |
+ This PR automatically updates identity-api Swagger JSON
+ from the latest main branch build.
diff --git a/pom.xml b/pom.xml
index 84eb1596..5170d70a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -240,6 +240,11 @@
0.12.6
runtime
+
+ com.h2database
+ h2
+ runtime
+
diff --git a/src/main/java/com/iemr/common/identity/utils/FilterConfig.java b/src/main/java/com/iemr/common/identity/utils/FilterConfig.java
index e13b8b4e..bb05427d 100644
--- a/src/main/java/com/iemr/common/identity/utils/FilterConfig.java
+++ b/src/main/java/com/iemr/common/identity/utils/FilterConfig.java
@@ -5,8 +5,10 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
+import org.springframework.context.annotation.Profile;
@Configuration
+@Profile("!swagger")
public class FilterConfig {
@Value("${cors.allowed-origins}")
private String allowedOrigins;
diff --git a/src/main/resources/application-swagger.properties b/src/main/resources/application-swagger.properties
new file mode 100644
index 00000000..0b6945e7
--- /dev/null
+++ b/src/main/resources/application-swagger.properties
@@ -0,0 +1,15 @@
+spring.datasource.url=jdbc:h2:mem:swaggerdb
+spring.datasource.driver-class-name=org.h2.Driver
+spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
+spring.jpa.hibernate.ddl-auto=create-drop
+
+# Disable Redis if not needed for docs (optional)
+spring.redis.host=localhost
+spring.redis.port=6379
+
+# CORS for Swagger UI
+cors.allowed-origins=${CORS_ALLOWED_ORIGINS:http://localhost:9090,http://localhost:8080}
+
+jwt.secret=${JWT_SECRET_KEY:default-swagger-secret-change-me}
+# Logging
+logging.level.root=INFO
From 7c91575687f880d145e65206f79cc1bceef4b79f Mon Sep 17 00:00:00 2001
From: KOPPIREDDY DURGA PRASAD
<144464542+DurgaPrasad-54@users.noreply.github.com>
Date: Tue, 17 Feb 2026 16:33:38 +0530
Subject: [PATCH 3/6] Add server urls and update swagger workflow (#135)
* docs(readme): add documentation badge
* chore(swagger): automate swagger sync to amrit-docs
* chore(swagger): automate swagger sync to amrit-docs
* chore(swagger): update github workflow for swagger json
* fix(swagger): fix the stop api issue in swagger workflow
* fix(swagger): removed the unnecessary initial sleep
* chore(swagger): add env-driven Dev/UAT/Demo servers and update swagger workflow
---
.github/workflows/swagger-json.yml | 2 +-
.../common/identity/config/SwaggerConfig.java | 28 +++++++++++++------
.../resources/application-swagger.properties | 4 +++
3 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/swagger-json.yml b/.github/workflows/swagger-json.yml
index afd552e4..a4e70068 100644
--- a/.github/workflows/swagger-json.yml
+++ b/.github/workflows/swagger-json.yml
@@ -98,7 +98,7 @@ jobs:
with:
token: ${{ secrets.DOCS_REPO_TOKEN }}
path: amrit-docs
- branch: auto/swagger-update-${{ github.run_id }}-${{ github.run_attempt }}
+ branch: auto/swagger-update-identity-api
base: main
commit-message: "chore(docs): auto-update identity-api swagger"
title: "chore(docs): auto-update identity-api swagger"
diff --git a/src/main/java/com/iemr/common/identity/config/SwaggerConfig.java b/src/main/java/com/iemr/common/identity/config/SwaggerConfig.java
index e016a99d..d945104c 100644
--- a/src/main/java/com/iemr/common/identity/config/SwaggerConfig.java
+++ b/src/main/java/com/iemr/common/identity/config/SwaggerConfig.java
@@ -23,6 +23,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
@@ -32,14 +33,23 @@
@Configuration
-public class SwaggerConfig
-{
- @Bean
- public OpenAPI customOpenAPI() {
- return new OpenAPI().info(new
- Info().title("Identity API").version("version").description("A microservice for the creation and management of beneficiaries."))
- .addSecurityItem(new SecurityRequirement().addList("my security"))
- .components(new Components().addSecuritySchemes("my security",
- new SecurityScheme().name("my security").type(SecurityScheme.Type.HTTP).scheme("bearer")));
+public class SwaggerConfig {
+ private static final String DEFAULT_SERVER_URL = "http://localhost:9090";
+
+ @Bean
+ public OpenAPI customOpenAPI(Environment env) {
+ String devUrl = env.getProperty("api.dev.url", DEFAULT_SERVER_URL);
+ String uatUrl = env.getProperty("api.uat.url", DEFAULT_SERVER_URL);
+ String demoUrl = env.getProperty("api.demo.url", DEFAULT_SERVER_URL);
+ return new OpenAPI()
+ .info(new Info().title("Identity API").version("version").description("A microservice for the creation and management of beneficiaries."))
+ .addSecurityItem(new SecurityRequirement().addList("my security"))
+ .components(new Components().addSecuritySchemes("my security",
+ new SecurityScheme().name("my security").type(SecurityScheme.Type.HTTP).scheme("bearer")))
+ .servers(java.util.Arrays.asList(
+ new io.swagger.v3.oas.models.servers.Server().url(devUrl).description("Dev"),
+ new io.swagger.v3.oas.models.servers.Server().url(uatUrl).description("UAT"),
+ new io.swagger.v3.oas.models.servers.Server().url(demoUrl).description("Demo")
+ ));
}
}
diff --git a/src/main/resources/application-swagger.properties b/src/main/resources/application-swagger.properties
index 0b6945e7..2fc8a1cd 100644
--- a/src/main/resources/application-swagger.properties
+++ b/src/main/resources/application-swagger.properties
@@ -1,3 +1,7 @@
+# Swagger server URLs
+api.dev.url=${API_DEV_URL:https://amritwprdev.piramalswasthya.org}
+api.uat.url=${API_UAT_URL:https://uatamrit.piramalswasthya.org}
+api.demo.url=${API_DEMO_URL:https://amritdemo.piramalswasthya.org}
spring.datasource.url=jdbc:h2:mem:swaggerdb
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
From 2ed618d069ad6d18ac3ad539e350cf056cade0f0 Mon Sep 17 00:00:00 2001
From: KOPPIREDDY DURGA PRASAD
<144464542+DurgaPrasad-54@users.noreply.github.com>
Date: Mon, 2 Mar 2026 10:12:25 +0530
Subject: [PATCH 4/6] feat(health,version): add health and version endpoints
(#136)
* feat(health,version): add health and version endpoints
* feat(health,version): add health and version endpoints without auth
* fix(health): remove unused private methods
* fix(health): fix exception issue
* fix(health): redact error details for unauthenticated health checks
* fix code quality issues and reduce cognitive complexity
* feat(health): add MySQL health endpoint
* refactor(health): simplify MySQL health check and remove sensitive details
* fix(health): remove unused imports and variables
* refactor(health): address nitpicks (configurable ES scheme, log noise, graceful shutdown, record)
* fix(health): scope PROCESSLIST lock-wait check to application DB user
* refactor(health): remove unused params and reuse response/error constants
* fix(health): remove unused imports and methods
* chore(health): clean up unused imports, params, and dead helpers
* fix(health): avoid sharing JDBC connections across threads in advanced MySQL checks
* refactor(health): reuse REDIS_COMPONENT constant and extract nested try block
* fix(health): avoid blocking DB I/O under write lock and restore interrupt flag
* fix(health): cancel in-flight futures on generic failure
* feat(health,version): add index existance, read-only detection, canary write for elasticsearch health check
* refactor(health): reduce cognitive complexity, remove dead throws, and clean code smells
---
pom.xml | 34 +-
.../controller/health/HealthController.java | 90 ++
.../controller/version/VersionController.java | 65 +-
.../service/health/HealthService.java | 855 ++++++++++++++++++
.../utils/JwtUserIdValidationFilter.java | 13 +-
5 files changed, 1009 insertions(+), 48 deletions(-)
create mode 100644 src/main/java/com/iemr/common/identity/controller/health/HealthController.java
create mode 100644 src/main/java/com/iemr/common/identity/service/health/HealthService.java
diff --git a/pom.xml b/pom.xml
index 5170d70a..37552818 100644
--- a/pom.xml
+++ b/pom.xml
@@ -245,6 +245,12 @@
h2
runtime
+
+
+ org.elasticsearch.client
+ elasticsearch-rest-client
+ 8.10.0
+
@@ -286,31 +292,29 @@
3.3.0
- pl.project13.maven
- git-commit-id-plugin
- 4.9.10
+ io.github.git-commit-id
+ git-commit-id-maven-plugin
+ 9.0.2
get-the-git-infos
revision
+ initialize
- ${project.basedir}/.git
- git
- false
true
-
- ${project.build.outputDirectory}/git.properties
-
- json
-
- false
- false
- -dirty
-
+ ${project.build.outputDirectory}/git.properties
+
+ ^git.branch$
+ ^git.commit.id.abbrev$
+ ^git.build.version$
+ ^git.build.time$
+
+ false
+ false
diff --git a/src/main/java/com/iemr/common/identity/controller/health/HealthController.java b/src/main/java/com/iemr/common/identity/controller/health/HealthController.java
new file mode 100644
index 00000000..b7cc3641
--- /dev/null
+++ b/src/main/java/com/iemr/common/identity/controller/health/HealthController.java
@@ -0,0 +1,90 @@
+/*
+* 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.identity.controller.health;
+
+import java.time.Instant;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletRequest;
+import com.iemr.common.identity.service.health.HealthService;
+import com.iemr.common.identity.utils.JwtAuthenticationUtil;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.tags.Tag;
+
+
+@RestController
+@RequestMapping("/health")
+@Tag(name = "Health Check", description = "APIs for checking infrastructure health status")
+public class HealthController {
+
+ private static final Logger logger = LoggerFactory.getLogger(HealthController.class);
+
+ private final HealthService healthService;
+ private final JwtAuthenticationUtil jwtAuthenticationUtil;
+
+ public HealthController(HealthService healthService, JwtAuthenticationUtil jwtAuthenticationUtil) {
+ this.healthService = healthService;
+ this.jwtAuthenticationUtil = jwtAuthenticationUtil;
+ }
+ @GetMapping
+ @Operation(summary = "Check infrastructure health",
+ description = "Returns the health status of MySQL, Redis, Elasticsearch, and other configured services")
+ @ApiResponses({
+ @ApiResponse(responseCode = "200", description = "Services are UP or DEGRADED (operational with warnings)"),
+ @ApiResponse(responseCode = "503", description = "One or more critical services are DOWN")
+ })
+ public ResponseEntity