This is an automated email from the ASF dual-hosted git repository.

Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new d4c593d4d9  fix: reject AI proxy API key creation for non-existent 
selectors (#7023)
d4c593d4d9 is described below

commit d4c593d4d9f9bf86e37cc5d6a770bffdc4a2437d
Author: Southern <[email protected]>
AuthorDate: Wed Sep 2 13:50:15 2026 +0800

     fix: reject AI proxy API key creation for non-existent selectors (#7023)
    
    - AiProxyApiKeyController.create returns AdminConstants.ID_NOT_EXIST when 
the selector does not exist.
     - Prevent the creation of orphan proxy-api-key records that reference 
non-existent selectors.
     - Add controller unit tests to cover scenarios where the selector exists 
and where it does not.
    
    Co-authored-by: aias00 <[email protected]>
---
 .../admin/controller/AiProxyApiKeyController.java  |  5 +-
 .../controller/AiProxyApiKeyControllerTest.java    | 80 ++++++++++++++++++++++
 2 files changed, 83 insertions(+), 2 deletions(-)

diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/AiProxyApiKeyController.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/AiProxyApiKeyController.java
index 1030c607e1..08957589c5 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/AiProxyApiKeyController.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/AiProxyApiKeyController.java
@@ -76,9 +76,10 @@ public class AiProxyApiKeyController implements 
PagedController<ProxyApiKeyQuery
             @Valid @RequestBody final ProxyApiKeyDTO dto) {
         // derive namespaceId from selector to avoid mismatch
         final SelectorDO selector = selectorMapper.selectById(selectorId);
-        if (Objects.nonNull(selector)) {
-            dto.setNamespaceId(selector.getNamespaceId());
+        if (Objects.isNull(selector)) {
+            return ShenyuAdminResult.error(AdminConstants.ID_NOT_EXIST);
         }
+        dto.setNamespaceId(selector.getNamespaceId());
         int rows = aiProxyApiKeyService.create(dto, selectorId);
         if (rows > 0) {
             final ProxyApiKeyVO vo = 
aiProxyApiKeyService.findById(dto.getId());
diff --git 
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/AiProxyApiKeyControllerTest.java
 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/AiProxyApiKeyControllerTest.java
new file mode 100644
index 0000000000..300f363897
--- /dev/null
+++ 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/controller/AiProxyApiKeyControllerTest.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.controller;
+
+import org.apache.shenyu.admin.mapper.SelectorMapper;
+import org.apache.shenyu.admin.model.dto.ProxyApiKeyDTO;
+import org.apache.shenyu.admin.model.entity.SelectorDO;
+import org.apache.shenyu.admin.model.result.ShenyuAdminResult;
+import org.apache.shenyu.admin.service.AiProxyApiKeyService;
+import org.apache.shenyu.common.constant.AdminConstants;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Test cases for {@link AiProxyApiKeyController}.
+ */
+@ExtendWith(MockitoExtension.class)
+public final class AiProxyApiKeyControllerTest {
+
+    @Mock
+    private AiProxyApiKeyService aiProxyApiKeyService;
+
+    @Mock
+    private SelectorMapper selectorMapper;
+
+    @InjectMocks
+    private AiProxyApiKeyController controller;
+
+    @Test
+    public void shouldRejectCreateWhenSelectorDoesNotExist() {
+        final ProxyApiKeyDTO dto = new ProxyApiKeyDTO();
+        dto.setNamespaceId("client-namespace");
+        when(selectorMapper.selectById("missing-selector")).thenReturn(null);
+
+        final ShenyuAdminResult result = controller.create("missing-selector", 
dto);
+
+        assertEquals(AdminConstants.ID_NOT_EXIST, result.getMessage());
+        assertEquals("client-namespace", dto.getNamespaceId());
+        verify(aiProxyApiKeyService, 
never()).create(any(ProxyApiKeyDTO.class), any(String.class));
+    }
+
+    @Test
+    public void shouldDeriveNamespaceAndDelegateWhenSelectorExists() {
+        final ProxyApiKeyDTO dto = new ProxyApiKeyDTO();
+        dto.setNamespaceId("client-namespace");
+        final SelectorDO selector = 
SelectorDO.builder().namespaceId("selector-namespace").build();
+        when(selectorMapper.selectById("selector-1")).thenReturn(selector);
+        when(aiProxyApiKeyService.create(dto, "selector-1")).thenReturn(0);
+
+        controller.create("selector-1", dto);
+
+        assertEquals("selector-namespace", dto.getNamespaceId());
+        verify(aiProxyApiKeyService).create(eq(dto), eq("selector-1"));
+    }
+}

Reply via email to