[Developer] #617 apply DDS MCP end-user authorization
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package com.cloudhandson.ddsbackoffice.config;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.time.Duration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DdsMcpIamPropertiesTest {
|
||||
|
||||
@Test
|
||||
void derivesTheOciIdentityDomainTokenEndpoint() {
|
||||
var properties = properties("https://idcs-example.identity.oraclecloud.com", "");
|
||||
|
||||
assertTrue(properties.configured());
|
||||
assertEquals("https://idcs-example.identity.oraclecloud.com/oauth2/v1/token",
|
||||
properties.tokenEndpoint().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotReportPartialOauthConfigurationAsReady() {
|
||||
var properties = new DdsMcpIamProperties("", "", "client", "secret", "", Duration.ofSeconds(10), Duration.ofSeconds(60));
|
||||
|
||||
assertFalse(properties.configured());
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsANonHttpsTokenEndpoint() {
|
||||
var properties = properties("", "http://identity.example.test/oauth2/v1/token");
|
||||
|
||||
assertThrows(IllegalStateException.class, properties::tokenEndpoint);
|
||||
}
|
||||
|
||||
private DdsMcpIamProperties properties(String domainUrl, String tokenUri) {
|
||||
return new DdsMcpIamProperties(domainUrl, tokenUri, "client", "secret", "database-scope",
|
||||
Duration.ofSeconds(10), Duration.ofSeconds(60));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.cloudhandson.ddsbackoffice.service;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.cloudhandson.vpdbackoffice.service.DdsAuthorizationChangeNotifier;
|
||||
import com.cloudhandson.vpdbackoffice.service.DdsAuthorizationSynchronizer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
|
||||
class DdsMcpAuthorizationChangeListenerTest {
|
||||
|
||||
@Test
|
||||
void bridgesACommittedAuthorizationChangeToOneBulkMcpPublish() {
|
||||
DdsMcpEndUserPublisher publisher = org.mockito.Mockito.mock(DdsMcpEndUserPublisher.class);
|
||||
when(publisher.publish()).thenReturn(new com.cloudhandson.ddsbackoffice.domain.DdsMcpEndUserPublishResult(3, 0, 0));
|
||||
DdsMcpAuthorizationChangeListener listener = new DdsMcpAuthorizationChangeListener(publisher);
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
factory.registerSingleton("ddsSynchronizer", (DdsAuthorizationSynchronizer) listener);
|
||||
|
||||
new DdsAuthorizationChangeNotifier(factory.getBeanProvider(DdsAuthorizationSynchronizer.class))
|
||||
.changed("PERMISSION_SAVED");
|
||||
|
||||
verify(publisher).publish();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.cloudhandson.ddsbackoffice.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DdsMcpJdbcApiTest {
|
||||
|
||||
@Test
|
||||
void shipsTheOracleJdbcDdsContextApiNeededByTheMcpExecutor() {
|
||||
assertDoesNotThrow(() -> {
|
||||
Class<?> context = Class.forName("oracle.jdbc.EndUserSecurityContext");
|
||||
context.getMethod("createWithName", CharSequence.class, String.class, CharSequence.class);
|
||||
Class<?> connection = Class.forName("oracle.jdbc.OracleConnection");
|
||||
connection.getMethod("setEndUserSecurityContext", context);
|
||||
connection.getMethod("clearEndUserSecurityContext");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.cloudhandson.ddsbackoffice.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import com.cloudhandson.ddsbackoffice.domain.DdsMcpAuthenticatedUser;
|
||||
import com.cloudhandson.ddsbackoffice.domain.DdsMcpEndUserPrincipal;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DdsMcpSseServiceTest {
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@Test
|
||||
void exposesNoBearerTokenToolParameter() throws Exception {
|
||||
// tools/list never calls the query service; null collaborators keep this
|
||||
// schema-contract test independent from bytecode-agent based mocks.
|
||||
var service = new DdsMcpSseService(objectMapper,
|
||||
new DdsMcpVectorSearchService(null, null, null, null));
|
||||
var user = new DdsMcpAuthenticatedUser(101L, "agent", new DdsMcpEndUserPrincipal(
|
||||
101L, "DDS_U_101", "DDS_U_101_ROLE", "DDS_OCI_IAM_CLIENT_SECRET_DERIVED_V1"));
|
||||
var request = objectMapper.readTree("""
|
||||
{"jsonrpc":"2.0","id":1,"method":"tools/list"}
|
||||
""");
|
||||
|
||||
var response = service.handle(user, request);
|
||||
var schema = response.path("result").path("tools").get(0).path("inputSchema");
|
||||
|
||||
assertThat(response.path("error").isMissingNode()).isTrue();
|
||||
assertThat(schema.path("required").get(0).asText()).isEqualTo("query");
|
||||
assertThat(schema.path("properties").has("bearerToken")).isFalse();
|
||||
assertThat(schema.path("properties").path("embeddingMode").path("enum").toString())
|
||||
.isEqualTo("[\"DEMO\",\"AI\"]");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user