Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ES-1887] Added additionalConfig validator and new client-mgmt apis #1016

Merged
merged 8 commits into from
Dec 21, 2024
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.ClientAdditionalConfigConstraint;
import lombok.Data;
import lombok.NoArgsConstructor;

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

@ClientAdditionalConfigConstraint
ase-101 marked this conversation as resolved.
Show resolved Hide resolved
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.ClientAdditionalConfigConstraint;
import lombok.Data;
import lombok.NoArgsConstructor;

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

@ClientAdditionalConfigConstraint
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;
}
}
sacrana0 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.mosip.esignet.core.util;

import java.util.*;

public class ClientAdditionalConfigValidatorTestData {

public static Map<String, Object> getValidAdditionalConfig() {
Map<String, Object> validAdditionalConfig = new HashMap<>();
validAdditionalConfig.put("userinfo_response_type", "JWS");
validAdditionalConfig.put("purpose", Map.ofEntries(
Map.entry("type", ""),
Map.entry("title", ""),
Map.entry("subTitle", "")
));
validAdditionalConfig.put("signup_banner_required", true);
validAdditionalConfig.put("forgot_pwd_link_required", true);
validAdditionalConfig.put("consent_expire_in_days", 1);
return validAdditionalConfig;
}

public static List<Map<String, Object>> getInvalidAdditionalConfigs() {
List<Map<String, Object>> invalidAdditionalConfigs = new ArrayList<>();

invalidAdditionalConfigs.add(null);

Map<String, Object> additionalConfig = getValidAdditionalConfig();
additionalConfig.put("userinfo_response_type", "ABC");
invalidAdditionalConfigs.add(additionalConfig);

additionalConfig = getValidAdditionalConfig();
additionalConfig.put("purpose", Collections.emptyMap());
invalidAdditionalConfigs.add(additionalConfig);

additionalConfig = getValidAdditionalConfig();
additionalConfig.put("purpose", Map.ofEntries(
Map.entry("type", ""),
Map.entry("title", 1), //anything other than string
Map.entry("subTitle", "")
));
invalidAdditionalConfigs.add(additionalConfig);

additionalConfig = getValidAdditionalConfig();
additionalConfig.put("signup_banner_required", 1); // anything other than boolean
invalidAdditionalConfigs.add(additionalConfig);

additionalConfig = getValidAdditionalConfig();
additionalConfig.put("forgot_pwd_link_required", 1); // anything other than boolean
invalidAdditionalConfigs.add(additionalConfig);

additionalConfig = getValidAdditionalConfig();
additionalConfig.put("consent_expire_in_days", ""); // anything other than number
invalidAdditionalConfigs.add(additionalConfig);

return invalidAdditionalConfigs;
}

}
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 ClientAdditionalConfigConstraint {
String message() default ErrorConstants.INVALID_ADDITIONAL_CONFIG;

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

Class<? extends Payload>[] payload() default {};
}
ase-101 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.mosip.esignet.core.validator;

import org.springframework.stereotype.Component;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Map;
import java.util.Set;

@Component
public class ClientAdditionalConfigValidator implements
ase-101 marked this conversation as resolved.
Show resolved Hide resolved
ConstraintValidator<ClientAdditionalConfigConstraint, Map<String, Object>> {

private static final Set<String> VALID_RESPONSE_TYPES = Set.of("JWS", "JWE");

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

@Override
public boolean isValid(Map<String, Object> value, ConstraintValidatorContext context) {
if (value == null) {
return false;
}

Object responseType = value.get("userinfo_response_type");
if (!(responseType instanceof String) ||
!VALID_RESPONSE_TYPES.contains(responseType.toString())) {
return false;
}

Object purpose = value.get("purpose");
if (!(purpose instanceof Map) || !isPurposeValid((Map<?, ?>) purpose)) {
return false;
}

if (!(value.get("signup_banner_required") instanceof Boolean)
|| !(value.get("forgot_pwd_link_required") instanceof Boolean)
|| !(value.get("consent_expire_in_days") instanceof Number)) {
return false;
}

return true;
}

private boolean isPurposeValid(Map<?, ?> purpose) {
return purpose.get("type") instanceof String
&& purpose.get("title") instanceof String
&& purpose.get("subTitle") instanceof String;
}
}
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