Skip to content

Commit

Permalink
added schema validation for IdentityData
Browse files Browse the repository at this point in the history
Signed-off-by: Mohd Kaif Siddique <[email protected]>
  • Loading branch information
Mohd Kaif Siddique committed Nov 25, 2024
1 parent ca033e8 commit eec6ef1
Show file tree
Hide file tree
Showing 10 changed files with 739 additions and 3 deletions.
35 changes: 35 additions & 0 deletions mock-identity-system/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,41 @@
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>com.networknt</groupId>
<artifactId>json-schema-validator</artifactId>
<version>1.5.1</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.1</version>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
import javax.validation.Valid;

import io.mosip.esignet.mock.identitysystem.dto.*;
import io.mosip.esignet.mock.identitysystem.validator.IdentitySchema;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import io.mosip.esignet.mock.identitysystem.exception.MockIdentityException;
Expand All @@ -21,6 +23,7 @@

@RestController
@RequestMapping("/")
@Validated
public class IdentityController {

@Autowired
Expand All @@ -29,7 +32,7 @@ public class IdentityController {
@PostMapping(value = "identity", consumes = { MediaType.APPLICATION_JSON_VALUE }, produces = {
MediaType.APPLICATION_JSON_VALUE })
public ResponseWrapper<IdentityStatus> createIdentity
(@Valid @RequestBody RequestWrapper<IdentityData> requestWrapper) throws MockIdentityException {
(@Valid @RequestBody @IdentitySchema(isCreate=true) RequestWrapper< IdentityData> requestWrapper) throws MockIdentityException {

ResponseWrapper response = new ResponseWrapper<IdentityStatus>();
IdentityStatus identityStatus = new IdentityStatus();
Expand All @@ -43,7 +46,7 @@ public class IdentityController {
@PutMapping(value = "identity", consumes = { MediaType.APPLICATION_JSON_VALUE }, produces = {
MediaType.APPLICATION_JSON_VALUE })
public ResponseWrapper<IdentityStatus> updateIdentity
(@Valid @RequestBody RequestWrapper<IdentityData> requestWrapper) throws MockIdentityException {
(@Valid @RequestBody @IdentitySchema(isCreate=false) RequestWrapper<IdentityData> requestWrapper) throws MockIdentityException {

ResponseWrapper response = new ResponseWrapper<IdentityStatus>();
IdentityStatus identityStatus = new IdentityStatus();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@ public class ErrorConstants {
public static final String INVALID_TRUST_FRAMEWORK = "invalid_trust_framework";
public static final String INVALID_VERIFIED_DATE = "invalid_verified_date";
public static final String CLAIM_ALREADY_EXISTS="Claim already exists";
public static final String INVALID_IDENTITY_DATA= "invalid_identity_data";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.mosip.esignet.mock.identitysystem.validator;


import io.mosip.esignet.mock.identitysystem.util.ErrorConstants;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE_USE, ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdentitySchemaValidator.class)
public @interface IdentitySchema {

String message() default ErrorConstants.INVALID_IDENTITY_DATA;
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};

boolean isCreate();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package io.mosip.esignet.mock.identitysystem.validator;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.networknt.schema.JsonSchema;
import com.networknt.schema.JsonSchemaFactory;
import com.networknt.schema.SpecVersion;
import com.networknt.schema.ValidationMessage;
import io.mosip.esignet.mock.identitysystem.dto.IdentityData;
import io.mosip.esignet.mock.identitysystem.dto.RequestWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.io.IOException;
import java.io.InputStream;
import java.util.Set;

@Component
@Slf4j
public class IdentitySchemaValidator implements ConstraintValidator<IdentitySchema, Object> {

@Value("${mosip.mock.ida.identity.create.schema.url}")
private String createSchemaUrl;

@Value("${mosip.mock.ida.identity.update.schema.url}")
private String updateSchemaUrl;
private boolean isCreate;

private volatile JsonSchema cachedCreateSchema;

private volatile JsonSchema cachedUpdateSchema;

@Autowired
ObjectMapper objectMapper;

@Autowired
ResourceLoader resourceLoader;

@Override
public void initialize(IdentitySchema constraintAnnotation) {
this.isCreate = constraintAnnotation.isCreate();
}

@Override
public boolean isValid(Object object, ConstraintValidatorContext context) {
if (!(object instanceof RequestWrapper)) {
return false;
}
RequestWrapper wrapper= (RequestWrapper) object;
Object requestObject = wrapper.getRequest();
if (!(requestObject instanceof IdentityData)) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate("Invalid request object")
.addPropertyNode("request")
.addConstraintViolation();
return false;
}
IdentityData identityData=(IdentityData) requestObject;
JsonNode identityJsonNode = objectMapper.valueToTree(identityData);
Set<ValidationMessage> errors = isCreate
? getCachedCreateSchema().validate(identityJsonNode)
: getCachedUpdateSchema().validate(identityJsonNode);

if (!errors.isEmpty()) {
log.error("Validation failed for claims: {}", errors);
return false;
}
return true;
}

private JsonSchema getCachedCreateSchema() {
if(cachedCreateSchema !=null ) return cachedCreateSchema;
synchronized (this) {
if (cachedCreateSchema == null) {
InputStream schemaResponse = getResource(createSchemaUrl);
JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012);
cachedCreateSchema = jsonSchemaFactory.getSchema(schemaResponse);
}
}
return cachedCreateSchema;
}

private JsonSchema getCachedUpdateSchema() {
if(cachedUpdateSchema !=null ) return cachedUpdateSchema;
synchronized (this) {
if (cachedUpdateSchema == null) {
InputStream schemaResponse = getResource(updateSchemaUrl);
JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012);
cachedUpdateSchema = jsonSchemaFactory.getSchema(schemaResponse);
}
}
return cachedUpdateSchema;
}

private InputStream getResource(String url) {
try{
Resource resource = resourceLoader.getResource(url);
return resource.getInputStream();
}catch (IOException e){
log.error("Failed to parse data: {}", url, e);
}
throw new RuntimeException("invalid_configuration");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
# mosip.api.internal.url
# mosip.api.public.url

##-----------------------------------------Mock-identity-system properties----------------------------------------------

mosip.mock.ida.identity.create.schema.url=classpath:/mock-identity-create-schema.json
mosip.mock.ida.identity.update.schema.url=classpath:/mock-identity-update-schema.json

##----------------------------------------- Database properties --------------------------------------------------------
mosip.mockidentitysystem.database.hostname=${database.host}
mosip.mockidentitysystem.database.port=${database.port}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
##-----------------------------------------Mock-identity-system properties----------------------------------------------

mosip.mock.ida.identity.create.schema.url=classpath:/mock-identity-create-schema.json
mosip.mock.ida.identity.update.schema.url=classpath:/mock-identity-update-schema.json


##----------------------------------------- Database properties --------------------------------------------------------

spring.datasource.url=jdbc:postgresql://localhost:5455/mosip_mockidentitysystem?currentSchema=mockidentitysystem
Expand Down
Loading

0 comments on commit eec6ef1

Please sign in to comment.