Skip to content

Commit 0dec5b1

Browse files
authored
Merge pull request #61 from PSMRI/release-3.2.0
Release 3.2.0 - AMM-1718
2 parents 7fba020 + a71eaee commit 0dec5b1

10 files changed

Lines changed: 123 additions & 24 deletions

File tree

Dockerfile

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# --- Stage 1: Build the application using Maven ---
2+
FROM maven:3.9.6-eclipse-temurin-17 AS build
3+
4+
WORKDIR /app
5+
6+
COPY . .
7+
8+
# Build the application while caching Maven dependencies to speed up future builds
9+
RUN --mount=type=cache,target=/root/.m2 \
10+
mvn clean package -DENV_VAR=docker -DskipTests -Dgit.skip=true
11+
12+
# --- Stage 2: Run the application with a minimal JRE image ---
13+
FROM eclipse-temurin:17-jre
14+
15+
WORKDIR /app
16+
17+
# Copy the built WAR file from the build stage
18+
COPY --from=build /app/target/*.war app.war
19+
20+
EXPOSE 8080
21+
22+
ENTRYPOINT ["java", "-jar", "app.war"]

pom.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,18 @@
392392
</execution>
393393
</executions>
394394
</plugin>
395+
<plugin>
396+
<groupId>org.springframework.boot</groupId>
397+
<artifactId>spring-boot-maven-plugin</artifactId>
398+
<version>3.2.2</version>
399+
<executions>
400+
<execution>
401+
<goals>
402+
<goal>repackage</goal>
403+
</goals>
404+
</execution>
405+
</executions>
406+
</plugin>
395407
</plugins>
396408
</build>
397409
<reporting>

src/main/environment/common_ci.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ callcentre-server-ip=@env.CALLCENTRE_SERVER_IP@
1515
common-url=@env.COMMON_API@
1616

1717
### Redis IP
18-
spring.redis.host=localhost
18+
spring.redis.host=@env.REDIS_HOST@
1919
jwt.secret=@env.JWT_SECRET_KEY@
2020

2121
#ELK logging file name
@@ -25,4 +25,5 @@ logging.file.name=@env.SCHEDULER_API_LOGGING_FILE_NAME@
2525
springdoc.api-docs.enabled=@env.SWAGGER_DOC_ENABLED@
2626
springdoc.swagger-ui.enabled=@env.SWAGGER_DOC_ENABLED@
2727

28+
cors.allowed-origins=@env.CORS_ALLOWED_ORIGINS@
2829

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# local env
2+
# DB Connections
3+
spring.datasource.url=${DATABASE_URL}
4+
spring.datasource.username=${DATABASE_USERNAME}
5+
spring.datasource.password=${DATABASE_PASSWORD}
6+
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
7+
8+
spring.jpa.show-sql=true
9+
10+
spring.profiles.active=test
11+
12+
callcentre-server-ip=${CALLCENTRE_SERVER_IP}
13+
14+
common-url=${COMMON_API}
15+
16+
### Redis IP
17+
spring.redis.host=${REDIS_HOST}
18+
jwt.secret=${JWT_SECRET_KEY}
19+
20+
#ELK logging file name
21+
logging.file.name=${SCHEDULER_API_LOGGING_FILE_NAME}
22+
23+
springdoc.api-docs.enabled=${SWAGGER_DOC_ENABLED}
24+
springdoc.swagger-ui.enabled=${SWAGGER_DOC_ENABLED}

src/main/environment/common_example.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ jwt.secret=my-32-character-ultra-secure-and-ultra-long-secret
2222
logging.path=logs/
2323
logging.file.name=logs/scheduler-api.log
2424

25+
cors.allowed-origins=http://localhost:*
26+

src/main/java/com/iemr/tm/controller/schedule/SchedulingController.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import org.slf4j.Logger;
2727
import org.slf4j.LoggerFactory;
2828
import org.springframework.beans.factory.annotation.Autowired;
29-
import org.springframework.web.bind.annotation.CrossOrigin;
29+
3030
import org.springframework.web.bind.annotation.PathVariable;
3131
import org.springframework.web.bind.annotation.RequestBody;
3232
import org.springframework.web.bind.annotation.RequestMapping;
@@ -43,7 +43,6 @@
4343

4444
import io.swagger.v3.oas.annotations.Operation;
4545

46-
4746
@RestController
4847
@RequestMapping(value = "/schedule", headers = "Authorization")
4948
public class SchedulingController {
@@ -52,7 +51,6 @@ public class SchedulingController {
5251
@Autowired
5352
private SchedulingService schedulingService;
5453

55-
@CrossOrigin()
5654
@Operation(summary = "Mark availability of specialist")
5755
@RequestMapping(value = "markavailability", method = RequestMethod.POST)
5856
public String markavailability(@RequestBody String specialistInput1) {
@@ -72,7 +70,6 @@ public String markavailability(@RequestBody String specialistInput1) {
7270
return response.toString();
7371
}
7472

75-
@CrossOrigin()
7673
@Operation(summary = "Mark unavailability of specialist")
7774
@RequestMapping(value = "unmarkavailability", method = RequestMethod.POST)
7875
public String unmarkavailability(@RequestBody String specialistInput1) {
@@ -91,7 +88,6 @@ public String unmarkavailability(@RequestBody String specialistInput1) {
9188
return response.toString();
9289
}
9390

94-
@CrossOrigin()
9591
@Operation(summary = "Get available slots of specialist for a particular day")
9692
@RequestMapping(value = "getavailableSlot", method = RequestMethod.POST)
9793
public String getavailableSlot(@RequestBody String specialistInput1) {
@@ -109,7 +105,6 @@ public String getavailableSlot(@RequestBody String specialistInput1) {
109105
return response.toString();
110106
}
111107

112-
@CrossOrigin()
113108
@Operation(summary = "Get available slots of specialist for a particular month")
114109
@RequestMapping(value = { "/monthview/{year}", "/monthview/{year}/{month}",
115110
"/monthview/{year}/{month}/{day}" }, method = RequestMethod.POST)
@@ -131,7 +126,6 @@ public String view(@RequestBody String specialistInput1, @PathVariable("year") I
131126
return response.toString();
132127
}
133128

134-
@CrossOrigin()
135129
@Operation(summary = "Book available slots of specialist of a particular day")
136130
@RequestMapping(value = "bookSlot", method = RequestMethod.POST)
137131
public String bookSlot(@RequestBody String specialistInput1) {
@@ -149,7 +143,6 @@ public String bookSlot(@RequestBody String specialistInput1) {
149143
return response.toString();
150144
}
151145

152-
@CrossOrigin()
153146
@Operation(summary = "Cancel booked slots of specialist of a particular day")
154147
@RequestMapping(value = "cancelBookedSlot", method = RequestMethod.POST)
155148
public String cancelBookedSlot(@RequestBody String specialistInput1) {
@@ -167,7 +160,6 @@ public String cancelBookedSlot(@RequestBody String specialistInput1) {
167160
return response.toString();
168161
}
169162

170-
@CrossOrigin()
171163
@Operation(summary = "Get day view of particular specialization")
172164
@RequestMapping(value = "getdayview", method = RequestMethod.POST)
173165
public String getdayview(@RequestBody String specialistInput1) {

src/main/java/com/iemr/tm/controller/specialist/SpecialistController.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import org.slf4j.Logger;
2727
import org.slf4j.LoggerFactory;
2828
import org.springframework.beans.factory.annotation.Autowired;
29-
import org.springframework.web.bind.annotation.CrossOrigin;
29+
3030
import org.springframework.web.bind.annotation.PathVariable;
3131
import org.springframework.web.bind.annotation.RequestBody;
3232
import org.springframework.web.bind.annotation.RequestMapping;
@@ -41,7 +41,6 @@
4141

4242
import io.swagger.v3.oas.annotations.Operation;
4343

44-
4544
@RestController
4645
@RequestMapping(value = "/specialist", headers = "Authorization")
4746
public class SpecialistController {
@@ -50,7 +49,6 @@ public class SpecialistController {
5049
@Autowired
5150
private SpecialistService specialistService;
5251

53-
@CrossOrigin()
5452
@Operation(summary = "Fetch master specialization")
5553
@RequestMapping(value = "masterspecialization", method = RequestMethod.POST)
5654
public String markavailability() {
@@ -66,7 +64,6 @@ public String markavailability() {
6664
return response.toString();
6765
}
6866

69-
@CrossOrigin()
7067
@Operation(summary = "Fetch list of specialists")
7168
@RequestMapping(value = "getSpecialist", method = RequestMethod.POST)
7269
public String getSpecialist(@RequestBody Specialist specialist) {
@@ -83,7 +80,6 @@ public String getSpecialist(@RequestBody Specialist specialist) {
8380
return response.toString();
8481
}
8582

86-
@CrossOrigin()
8783
@Operation(summary = "Fetch user specialist")
8884
@RequestMapping(value = "info/{userID}", method = RequestMethod.GET)
8985
public String info(@PathVariable("userID") Long userID) {
@@ -101,7 +97,6 @@ public String info(@PathVariable("userID") Long userID) {
10197
return response.toString();
10298
}
10399

104-
@CrossOrigin()
105100
@Operation(summary = "Fetch all specialists")
106101
@RequestMapping(value = "getSpecialistAll", method = RequestMethod.POST)
107102
public String getSpecialistAll(@RequestBody Specialist specialist) {

src/main/java/com/iemr/tm/controller/van/VanController.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import org.slf4j.Logger;
2525
import org.slf4j.LoggerFactory;
2626
import org.springframework.beans.factory.annotation.Autowired;
27-
import org.springframework.web.bind.annotation.CrossOrigin;
27+
2828
import org.springframework.web.bind.annotation.PathVariable;
2929
import org.springframework.web.bind.annotation.RequestMapping;
3030
import org.springframework.web.bind.annotation.RequestMethod;
@@ -36,8 +36,6 @@
3636

3737
import io.swagger.v3.oas.annotations.Operation;
3838

39-
40-
4139
@RestController
4240
@RequestMapping(value = "/van", headers = "Authorization")
4341
public class VanController {
@@ -46,7 +44,6 @@ public class VanController {
4644
@Autowired
4745
private VanService vanService;
4846

49-
@CrossOrigin()
5047
@Operation(summary = "Fetch specialization by van id")
5148
@RequestMapping(value = "getvan/{vanid}", method = RequestMethod.GET)
5249
public String markavailability(@PathVariable("vanid") Integer vanid) {

src/main/java/com/iemr/tm/utils/FilterConfig.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,26 @@
33
import org.springframework.boot.web.servlet.FilterRegistrationBean;
44
import org.springframework.context.annotation.Bean;
55
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.core.Ordered;
7+
import org.springframework.beans.factory.annotation.Value;
68

79
@Configuration
810
public class FilterConfig {
911

12+
@Value("${cors.allowed-origins}")
13+
private String allowedOrigins;
14+
1015
@Bean
1116
public FilterRegistrationBean<JwtUserIdValidationFilter> jwtUserIdValidationFilter(
1217
JwtAuthenticationUtil jwtAuthenticationUtil) {
1318
FilterRegistrationBean<JwtUserIdValidationFilter> registrationBean = new FilterRegistrationBean<>();
14-
registrationBean.setFilter(new JwtUserIdValidationFilter(jwtAuthenticationUtil));
19+
20+
// Pass allowedOrigins explicitly to the filter constructor
21+
JwtUserIdValidationFilter filter = new JwtUserIdValidationFilter(jwtAuthenticationUtil, allowedOrigins);
22+
23+
registrationBean.setFilter(filter);
24+
registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
1525
registrationBean.addUrlPatterns("/*"); // Apply filter to all API endpoints
1626
return registrationBean;
1727
}
18-
1928
}

src/main/java/com/iemr/tm/utils/JwtUserIdValidationFilter.java

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.iemr.tm.utils;
22

33
import java.io.IOException;
4+
import java.util.Arrays;
45

56
import org.slf4j.Logger;
67
import org.slf4j.LoggerFactory;
@@ -17,14 +18,16 @@
1718
import jakarta.servlet.http.HttpServletRequest;
1819
import jakarta.servlet.http.HttpServletResponse;
1920

20-
@Component
2121
public class JwtUserIdValidationFilter implements Filter {
2222

2323
private final JwtAuthenticationUtil jwtAuthenticationUtil;
2424
private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
25+
private final String allowedOrigins;
2526

26-
public JwtUserIdValidationFilter(JwtAuthenticationUtil jwtAuthenticationUtil) {
27+
public JwtUserIdValidationFilter(JwtAuthenticationUtil jwtAuthenticationUtil,
28+
String allowedOrigins) {
2729
this.jwtAuthenticationUtil = jwtAuthenticationUtil;
30+
this.allowedOrigins = allowedOrigins;
2831
}
2932

3033
@Override
@@ -33,6 +36,27 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
3336
HttpServletRequest request = (HttpServletRequest) servletRequest;
3437
HttpServletResponse response = (HttpServletResponse) servletResponse;
3538

39+
String origin = request.getHeader("Origin");
40+
41+
logger.debug("Incoming Origin: {}", origin);
42+
logger.debug("Allowed Origins Configured: {}", allowedOrigins);
43+
44+
if (origin != null && isOriginAllowed(origin)) {
45+
response.setHeader("Access-Control-Allow-Origin", origin);
46+
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
47+
response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, Jwttoken");
48+
response.setHeader("Vary", "Origin");
49+
response.setHeader("Access-Control-Allow-Credentials", "true");
50+
} else {
51+
logger.warn("Origin [{}] is NOT allowed. CORS headers NOT added.", origin);
52+
}
53+
54+
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
55+
logger.info("OPTIONS request - skipping JWT validation");
56+
response.setStatus(HttpServletResponse.SC_OK);
57+
return;
58+
}
59+
3660
String path = request.getRequestURI();
3761
String contextPath = request.getContextPath();
3862
logger.info("JwtUserIdValidationFilter invoked for path: " + path);
@@ -110,12 +134,33 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo
110134
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authorization error: " + e.getMessage());
111135
}
112136
}
137+
138+
private boolean isOriginAllowed(String origin) {
139+
if (origin == null || allowedOrigins == null || allowedOrigins.trim().isEmpty()) {
140+
logger.warn("No allowed origins configured or origin is null");
141+
return false;
142+
}
143+
144+
return Arrays.stream(allowedOrigins.split(","))
145+
.map(String::trim)
146+
.anyMatch(pattern -> {
147+
String regex = pattern
148+
.replace(".", "\\.")
149+
.replace("*", ".*")
150+
.replace("http://localhost:.*", "http://localhost:\\d+"); // special case for wildcard port
151+
152+
boolean matched = origin.matches(regex);
153+
return matched;
154+
});
155+
}
156+
113157
private boolean isMobileClient(String userAgent) {
114158
if (userAgent == null)
115159
return false;
116160
userAgent = userAgent.toLowerCase();
117161
return userAgent.contains("okhttp");
118162
}
163+
119164
private String getJwtTokenFromCookies(HttpServletRequest request) {
120165
Cookie[] cookies = request.getCookies();
121166
if (cookies != null) {

0 commit comments

Comments
 (0)