Skip to content

Commit

Permalink
[ES-1887] Added additionalConfig validator and new client-mgmt apis (#…
Browse files Browse the repository at this point in the history
…1016)

* Added additionalConfig validator and new client-mgmt apis

Signed-off-by: Sachin Rana <[email protected]>

* handled review comments

Signed-off-by: Sachin Rana <[email protected]>

* resolved review comments

Signed-off-by: Sachin Rana <[email protected]>

* resolved review comments

Signed-off-by: Sachin Rana <[email protected]>

* worked on testcases, code improvement and db script changes

Signed-off-by: Sachin Rana <[email protected]>

* removed redundant constraint

Signed-off-by: Sachin Rana <[email protected]>

---------

Signed-off-by: Sachin Rana <[email protected]>
Signed-off-by: sacrana0 <[email protected]>
  • Loading branch information
sacrana0 authored Dec 21, 2024
1 parent 7fd41aa commit 48c2cf8
Show file tree
Hide file tree
Showing 20 changed files with 1,509 additions and 790 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,7 @@ public ClientDetailResponseV2 updateClient(String clientId, ClientDetailUpdateRe
}

public ClientDetail buildClient(ClientDetailCreateRequestV2 clientDetailCreateRequestV2) {
Optional<ClientDetail> result = clientDetailRepository.findById(clientDetailCreateRequestV2.getClientId());
if (result.isPresent()) {
if (clientDetailRepository.existsById(clientDetailCreateRequestV2.getClientId())) {
log.error("Duplicate Client Id : {}", ErrorConstants.DUPLICATE_CLIENT_ID);
throw new EsignetException(ErrorConstants.DUPLICATE_CLIENT_ID);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public void createClientV2_withValidDetail_thenPass() throws Exception {

@Test
public void createClientV2_withExistingClientId_thenFail() {
Mockito.when(clientDetailRepository.findById("client_id_v1")).thenReturn(Optional.of(new ClientDetail()));
Mockito.when(clientDetailRepository.existsById("client_id_v1")).thenReturn(true);
ClientDetailCreateRequestV2 clientCreateV2ReqDto = new ClientDetailCreateRequestV2();
clientCreateV2ReqDto.setClientId("client_id_v1");
try {
Expand Down Expand Up @@ -164,7 +164,7 @@ public void createClientV3_withValidDetail_thenPass() {

@Test
public void createClientV3_withExistingClientId_thenFail() {
Mockito.when(clientDetailRepository.findById("client_id_v1")).thenReturn(Optional.of(new ClientDetail()));
Mockito.when(clientDetailRepository.existsById("client_id_v1")).thenReturn(true);
ClientDetailCreateRequestV3 clientCreateV3ReqDto = new ClientDetailCreateRequestV3();
clientCreateV3ReqDto.setClientId("client_id_v1");
try {
Expand Down
2 changes: 1 addition & 1 deletion db_scripts/mosip_esignet/db.sql
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ CREATE DATABASE mosip_esignet
OWNER = postgres
TEMPLATE = template0;

COMMENT ON DATABASE mosip_idp IS 'e-Signet related data is stored in this database';
COMMENT ON DATABASE mosip_esignet IS 'e-Signet related data is stored in this database';

\c mosip_esignet postgres

Expand Down
17 changes: 1 addition & 16 deletions db_scripts/mosip_esignet/dml.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,4 @@
----- TRUNCATE esignet.client_detail TABLE Data and It's reference Data and COPY Data from CSV file -----
TRUNCATE TABLE esignet.client_detail cascade ;

\COPY esignet.key_policy_def (APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) FROM './dml/esignet-key_policy_def.csv' delimiter ',' HEADER csv;















\COPY esignet.key_policy_def (APP_ID,KEY_VALIDITY_DURATION,PRE_EXPIRE_DAYS,ACCESS_ALLOWED,IS_ACTIVE,CR_BY,CR_DTIMES) FROM './dml/esignet-key_policy_def.csv' delimiter ',' HEADER csv;
11 changes: 3 additions & 8 deletions db_upgrade_script/mosip_esignet/sql/1.5.0_to_1.5.1_upgrade.sql
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,12 @@ EXCEPTION
END;
$$ LANGUAGE plpgsql;

-- Add the new column with a default value
ALTER TABLE client_detail
ADD COLUMN additional_config jsonb DEFAULT '{}'::jsonb;

-- Update existing entries to set the default value for the new column
UPDATE client_detail
SET additional_config = '{}'::jsonb
WHERE additional_config IS NULL;

DO $$
BEGIN
-- Add the new column with a default value
ALTER TABLE client_detail ADD COLUMN additional_config jsonb;

IF NOT is_column_jsonb('client_detail', 'public_key') THEN

-- create backup
Expand Down
6 changes: 4 additions & 2 deletions docker-compose/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,18 @@ CREATE TABLE esignet.client_detail(
redirect_uris character varying NOT NULL,
claims character varying NOT NULL,
acr_values character varying NOT NULL,
public_key character varying NOT NULL,
public_key jsonb NOT NULL,
grant_types character varying NOT NULL,
auth_methods character varying NOT NULL,
status character varying(20) NOT NULL,
additional_config jsonb,
cr_dtimes timestamp NOT NULL,
upd_dtimes timestamp,
CONSTRAINT pk_clntdtl_id PRIMARY KEY (id),
CONSTRAINT uk_clntdtl_key UNIQUE (public_key)
);

CREATE UNIQUE INDEX unique_n_value ON client_detail ((public_key->>'n'));

create table esignet.consent_detail (
id UUID NOT NULL,
client_id VARCHAR NOT NULL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

public class ErrorConstants {

public static final String INVALID_ADDITIONAL_CONFIG="invalid_additional_config";
public static final String INVALID_REQUEST="invalid_request";
public static final String INVALID_CLIENT_ID="invalid_client_id";
public static final String INVALID_CLIENT_NAME="invalid_client_name";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.mosip.esignet.core.dto;

import lombok.AllArgsConstructor;
import io.mosip.esignet.core.validator.ClientAdditionalConfig;
import lombok.Data;
import lombok.NoArgsConstructor;

Expand All @@ -10,6 +10,8 @@
@Data
@NoArgsConstructor
public class ClientDetailCreateRequestV3 extends ClientDetailCreateRequestV2 {

@ClientAdditionalConfig
private Map<String, Object> additionalConfig;

public ClientDetailCreateRequestV3(String clientId, String clientName, Map<String, Object> publicKey, String relyingPartyId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.mosip.esignet.core.dto;

import lombok.AllArgsConstructor;
import io.mosip.esignet.core.validator.ClientAdditionalConfig;
import lombok.Data;
import lombok.NoArgsConstructor;

Expand All @@ -10,10 +10,12 @@
@Data
@NoArgsConstructor
public class ClientDetailUpdateRequestV3 extends ClientDetailUpdateRequestV2 {

@ClientAdditionalConfig
private Map<String, Object> additionalConfig;

public ClientDetailUpdateRequestV3(String logUri, List<String> redirectUris, List<String> userClaims, List<String> authContextRefs, String status, List<String> grantTypes, String clientName, List<String> clientAuthMethods, Map<String,String> clientNameLangMap, Map<String, Object> additionalConfig){
super(logUri,redirectUris,userClaims,authContextRefs,status,grantTypes,clientName,clientAuthMethods, clientNameLangMap);
this.additionalConfig=additionalConfig;
public ClientDetailUpdateRequestV3(String logUri, List<String> redirectUris, List<String> userClaims, List<String> authContextRefs, String status, List<String> grantTypes, String clientName, List<String> clientAuthMethods, Map<String, String> clientNameLangMap, Map<String, Object> additionalConfig) {
super(logUri, redirectUris, userClaims, authContextRefs, status, grantTypes, clientName, clientAuthMethods, clientNameLangMap);
this.additionalConfig = additionalConfig;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.mosip.esignet.core.validator;

import io.mosip.esignet.core.constants.ErrorConstants;

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

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = ClientAdditionalConfigValidator.class)
@Documented
public @interface ClientAdditionalConfig {
String message() default ErrorConstants.INVALID_ADDITIONAL_CONFIG;

Class<?>[] groups() default {};

Class<? extends Payload>[] payload() default {};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package io.mosip.esignet.core.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.core.exception.EsignetException;
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 javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Set;

@Slf4j
public class ClientAdditionalConfigValidator implements
ConstraintValidator<ClientAdditionalConfig, Map<String, Object>> {

@Value("${mosip.esignet.additional-config.schema.url}")
private String schemaUrl;

private volatile JsonSchema cachedSchema;

@Autowired
private ObjectMapper objectMapper;

@Autowired
private ResourceLoader resourceLoader;

@Override
public void initialize(ClientAdditionalConfig constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}

@Override
public boolean isValid(Map<String, Object> additionalConfig, ConstraintValidatorContext context) {
if (additionalConfig == null) {
return false;
}
Set<ValidationMessage> errors = null;
try {
JsonNode jsonNode = objectMapper.valueToTree(additionalConfig);
errors = getCachedSchema().validate(jsonNode);
if (errors.isEmpty()) return true;
} catch (Exception e) {
log.error("Error validating additional_config schema: ", e);
}
log.error("Validation failed for additional_config ---> {}", errors);
return false;
}

private JsonSchema getCachedSchema() throws EsignetException {
if(cachedSchema!=null ) return cachedSchema;
synchronized (this) {
if (cachedSchema == null) {
InputStream schemaResponse = getResource(schemaUrl);
JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V202012);
cachedSchema = jsonSchemaFactory.getSchema(schemaResponse);
}
}
return cachedSchema;
}

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 EsignetException("invalid_configuration");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.mosip.esignet.core;

import io.mosip.esignet.core.exception.InvalidClientException;
import io.mosip.esignet.core.util.ClientAdditionalConfigConverter;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class ClientAdditionalConfigConverterTest {

private ClientAdditionalConfigConverter converter;

@BeforeEach
void setUp() {
converter = new ClientAdditionalConfigConverter();
}

@Test
public void convertToDatabaseColumn_NullMap_ReturnsNull() {
Assertions.assertNull(converter.convertToDatabaseColumn(null));
}

@Test
public void convertToEntityAttribute_NullJson_ReturnsNull() {
Assertions.assertNull(converter.convertToEntityAttribute(null));
}

@Test
public void convertToEntityAttribute_InvalidJson_ThrowsException() {
String invalidJson = "{\"invalid: value}";
Assertions.assertThrows(InvalidClientException.class, () ->
converter.convertToEntityAttribute(invalidJson)
);
}

}
Loading

0 comments on commit 48c2cf8

Please sign in to comment.