Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 33 additions & 18 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,17 @@


<dependencies>
<!--
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>co.elastic.logging</groupId>
<artifactId>logback-ecs-encoder</artifactId>
<version>1.3.2</version>
<dependency>
<groupId>co.elastic.logging</groupId>
<artifactId>logback-ecs-encoder</artifactId>
<version>1.3.2</version>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down Expand Up @@ -141,7 +140,7 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
Expand All @@ -163,7 +162,7 @@
<artifactId>json</artifactId>
<version>20231013</version>
</dependency>

<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
Expand Down Expand Up @@ -193,8 +192,7 @@
</exclusion>
</exclusions>
</dependency>
<!--
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
Expand Down Expand Up @@ -239,8 +237,7 @@
</exclusion>
</exclusions>
</dependency>
<!--
https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis -->
<!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session-data-redis -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
Expand All @@ -266,8 +263,7 @@
<artifactId>jackson-datatype-joda</artifactId>
<version>2.17.0</version>
</dependency>
<!--
https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
Expand All @@ -279,8 +275,28 @@
<artifactId>jackson-core</artifactId>
<version>2.17.0-rc1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.12.6</version>
<scope>runtime</scope>
</dependency>
</dependencies>



<build>
Expand Down Expand Up @@ -371,8 +387,7 @@
${target-properties} and
${source-properties}
</echo>
<concat destfile="${target-properties}"
append="yes"
<concat destfile="${target-properties}" append="yes"
force="yes">
<fileset file="${source-properties}">
</fileset>
Expand Down
5 changes: 4 additions & 1 deletion src/main/environment/common_ci.properties
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ tcSpeclistWL=7

### Redis IP
spring.redis.host=localhost
jwt.secret=@env.JWT_SECRET_KEY@


#ELK logging file name
logging.file.name=@env.TM_API_LOGGING_FILE_NAME@
logging.file.name=@env.TM_API_LOGGING_FILE_NAME@

1 change: 1 addition & 0 deletions src/main/environment/common_dev.properties
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,5 @@ tcSpeclistWL=7
prescription=TMPrescription SMS
### Redis IP
spring.redis.host=localhost
jwt.secret=

1 change: 1 addition & 0 deletions src/main/environment/common_test.properties
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ prescription=TMPrescription SMS

### Redis IP
spring.redis.host=localhost
jwt.secret=



1 change: 1 addition & 0 deletions src/main/environment/common_uat.properties
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,6 @@ tcSpeclistWL=7
prescription=TMPrescription SMS
### Redis IP
spring.redis.host=localhost
jwt.secret=


20 changes: 20 additions & 0 deletions src/main/java/com/iemr/tm/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,13 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.web.client.RestTemplate;

import com.iemr.tm.data.login.Users;
import com.iemr.tm.utils.IEMRApplBeans;

@SpringBootApplication
Expand All @@ -45,5 +50,20 @@ public IEMRApplBeans instantiateBeans() {
public RestTemplate getRestTemplate() {
return new RestTemplate();
}

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);

// Use StringRedisSerializer for keys (userId)
template.setKeySerializer(new StringRedisSerializer());

// Use Jackson2JsonRedisSerializer for values (Users objects)
Jackson2JsonRedisSerializer<Users> serializer = new Jackson2JsonRedisSerializer<>(Users.class);
template.setValueSerializer(serializer);

return template;
}
Comment thread
sandipkarmakar3 marked this conversation as resolved.

}
38 changes: 38 additions & 0 deletions src/main/java/com/iemr/tm/config/RedisConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.iemr.tm.config;

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.session.data.redis.config.ConfigureRedisAction;

import com.iemr.tm.data.login.Users;

@Configuration
@EnableCaching
public class RedisConfig {

@Bean
public ConfigureRedisAction configureRedisAction() {
return ConfigureRedisAction.NO_OP;
}

@Bean
public RedisTemplate<String, Users> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Users> template = new RedisTemplate<>();
template.setConnectionFactory(factory);

// Use StringRedisSerializer for keys (userId)
template.setKeySerializer(new StringRedisSerializer());

// Use Jackson2JsonRedisSerializer for values (Users objects)
Jackson2JsonRedisSerializer<Users> serializer = new Jackson2JsonRedisSerializer<>(Users.class);
template.setValueSerializer(serializer);

return template;
}
Comment thread
sandipkarmakar3 marked this conversation as resolved.

}
86 changes: 9 additions & 77 deletions src/main/java/com/iemr/tm/data/login/Users.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,98 +21,30 @@
*/
package com.iemr.tm.data.login;

import java.sql.Timestamp;
import java.io.Serializable;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

import com.google.gson.annotations.Expose;
import lombok.Data;
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Dec 2, 2024

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue

Add validation and security measures for sensitive fields

The entity contains sensitive PII data (Aadhaar, PAN) and credentials without proper validation or security measures.

Recommended improvements:

  1. Add field validation:
@Column(name = "Password")
@JsonIgnore // Remove @Expose
private String password;

@Column(name = "AadhaarNo")
@Pattern(regexp = "^[0-9]{12}$")
@Convert(converter = AttributeEncryptor.class)
private String aadhaarNo;

@Column(name = "PAN")
@Pattern(regexp = "^[A-Z]{5}[0-9]{4}[A-Z]{1}$")
@Convert(converter = AttributeEncryptor.class)
private String pan;
  1. Implement field-level encryption for sensitive data:
@Component
public class AttributeEncryptor implements AttributeConverter<String, String> {
    // Implement encryption/decryption using your security key
}

Also applies to: 33-33, 34-34, 35-35, 36-36, 37-37, 38-38

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

not required

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@sandipkarmakar3 Understood, I see that the sensitive fields have been removed from the Users class, making the validation suggestions unnecessary.


โœ๏ธ Learnings added
Learnt from: sandipkarmakar3
PR: PSMRI/TM-API#56
File: src/main/java/com/iemr/tm/data/login/Users.java:34-34
Timestamp: 2025-02-03T12:50:15.717Z
Learning: The Users class in TM-API has been simplified to only contain basic fields (userID, userName, Deleted) with sensitive PII data fields intentionally removed.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


@Entity
@Data
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Dec 2, 2024

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue

Security concern: Replace @DaTa with specific Lombok annotations

Using @DaTa on an entity containing sensitive information (password, PAN, Aadhaar) is risky as it generates toString() that could expose this data in logs.

Replace with specific annotations:

-@Data
+@Getter
+@Setter
+@EqualsAndHashCode(exclude = {"password", "pan", "aadhaarNo"})
+@ToString(exclude = {"password", "pan", "aadhaarNo"})
๐Ÿ“ Committable suggestion

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

Suggested change
@Data
@Getter
@Setter
@EqualsAndHashCode(exclude = {"password", "pan", "aadhaarNo"})
@ToString(exclude = {"password", "pan", "aadhaarNo"})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

@Table(name = "m_user")
public class Users {
@JsonIgnoreProperties(ignoreUnknown = true)
public class Users implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Expose
@Column(name = "UserID")
private Long userID;
@Expose
@Column(name = "TitleID") private Short titleID;
@Expose
@Column(name = "FirstName")
private String firstName;
@Expose
@Column(name = "MiddleName")
private String middleName;
@Expose
@Column(name = "lastName")
private String lastName;
@Expose
@Column(name = "GenderID")
private Short genderID;
@Expose
@Column(name = "MaritalStatusID")
private Short maritalStatusID;
@Expose
@Column(name = "AadhaarNo")
private String aadhaarNo;
@Expose
@Column(name = "PAN")
private String pan;
@Expose
@Column(name = "DOB")
private Timestamp dob;
@Expose
@Column(name = "DOJ")
private Timestamp doj;
@Expose
@Column(name = "QualificationID")
private Integer qualificationID;
@Expose
@Column(name = "UserName")
private String userName;
@Expose
@Column(name = "Password")
private String password;
@Expose
@Column(name = "AgentID")
private String agentID;
@Expose
@Column(name = "AgentPassword")
private String agentPassword;
@Expose
@Column(name = "EmailID")
private String emailID;
@Expose
@Column(name = "StatusID")
private Short statusID;
@Expose
@Column(name = "EmergencyContactPerson")
private String emergencyContactPerson;
@Expose
@Column(name = "EmergencyContactNo")
private String emergencyContactNo;
@Expose
@Column(name = "IsSupervisor")
private Boolean isSupervisor;
@Expose
@Column(name = "Deleted")
private Boolean deleted;
@Expose
@Column(name = "CreatedBy")
private String createdBy;
@Expose
@Column(name = "CreatedDate")
private Timestamp createdDate;
@Expose
@Column(name = "ModifiedBy")
private String modifiedBy;
@Expose
@Column(name = "LastModDate")
private Timestamp lastModDate;
@Column(name = "Deleted", insertable = false, updatable = false)
private Boolean Deleted;

}
16 changes: 16 additions & 0 deletions src/main/java/com/iemr/tm/repo/login/UserLoginRepo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.iemr.tm.repo.login;

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

import com.iemr.tm.data.login.Users;

@Repository
public interface UserLoginRepo extends CrudRepository<Users, Long> {

@Query(" SELECT u FROM Users u WHERE u.userID = :userID AND u.Deleted = false ")
public Users getUserByUserID(@Param("userID") Long userID);

}
31 changes: 31 additions & 0 deletions src/main/java/com/iemr/tm/utils/CookieUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.iemr.tm.utils;

import java.util.Arrays;
import java.util.Optional;

import org.springframework.stereotype.Service;

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

@Service
public class CookieUtil {

public Optional<String> getCookieValue(HttpServletRequest request, String cookieName) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookieName.equals(cookie.getName())) {
return Optional.of(cookie.getValue());
}
}
}
return Optional.empty();
}

public String getJwtTokenFromCookie(HttpServletRequest request) {
return Arrays.stream(request.getCookies()).filter(cookie -> "Jwttoken".equals(cookie.getName()))
.map(Cookie::getValue).findFirst().orElse(null);
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/iemr/tm/utils/FilterConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.iemr.tm.utils;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

@Bean
public FilterRegistrationBean<JwtUserIdValidationFilter> jwtUserIdValidationFilter(
JwtAuthenticationUtil jwtAuthenticationUtil) {
FilterRegistrationBean<JwtUserIdValidationFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new JwtUserIdValidationFilter(jwtAuthenticationUtil));
registrationBean.addUrlPatterns("/*"); // Apply filter to all API endpoints
return registrationBean;
}

}
Loading