feat(namespace): filter paged namespace reads

Signed-off-by: dongmucat <1127093059@qq.com>
This commit is contained in:
dongmucat 2026-07-27 16:18:47 +08:00
parent a55264b130
commit 9de8a51d89
3 changed files with 54 additions and 2 deletions

View file

@ -3,6 +3,7 @@ package com.iflytek.skillhub.controller.portal;
import com.iflytek.skillhub.controller.BaseApiController;
import com.iflytek.skillhub.auth.rbac.PlatformPrincipal;
import com.iflytek.skillhub.domain.namespace.NamespaceRole;
import com.iflytek.skillhub.domain.namespace.NamespaceStatus;
import com.iflytek.skillhub.dto.ApiResponse;
import com.iflytek.skillhub.dto.ApiResponseFactory;
import com.iflytek.skillhub.dto.BatchMemberRequest;
@ -79,11 +80,22 @@ public class NamespaceController extends BaseApiController {
@GetMapping("/me/namespaces/page")
public ApiResponse<PageResponse<MyNamespaceResponse>> listMyNamespacesPage(
Pageable pageable,
@RequestParam(required = false) NamespaceStatus status,
@RequestParam(required = false) String q,
@RequestParam(required = false) String slug,
@RequestParam(required = false) Set<NamespaceRole> roles,
@RequestAttribute("userId") String userId,
@RequestAttribute(value = "userNsRoles", required = false) Map<Long, NamespaceRole> userNsRoles,
@RequestAttribute(value = "platformRoles", required = false) Set<String> platformRoles) {
return ok("response.success.read",
namespacePortalQueryAppService.listMyNamespaces(pageable, userNsRoles, normalizePlatformRoles(platformRoles)));
namespacePortalQueryAppService.listMyNamespaces(
pageable,
userNsRoles,
normalizePlatformRoles(platformRoles),
status,
q,
slug,
roles));
}
@GetMapping("/namespaces/{slug}")

View file

@ -129,7 +129,7 @@ class NamespacePortalControllerTest {
Namespace active = namespace(1L, "active", NamespaceStatus.ACTIVE, NamespaceType.TEAM);
Namespace archived = namespace(3L, "archived", NamespaceStatus.ARCHIVED, NamespaceType.TEAM);
given(namespaceMemberRepository.findByUserId("super-1")).willReturn(List.of());
given(namespaceRepository.findAll(any()))
given(namespaceRepository.search(eq(null), eq(null), eq(null), any()))
.willReturn(new org.springframework.data.domain.PageImpl<>(
List.of(active, archived),
org.springframework.data.domain.PageRequest.of(0, 2),
@ -151,6 +151,38 @@ class NamespacePortalControllerTest {
.andExpect(jsonPath("$.data.size").value(2));
}
@Test
void listMyNamespacesPage_bindsAndAppliesOptionalFilters() throws Exception {
Namespace active = namespace(1L, "team-ai", NamespaceStatus.ACTIVE, NamespaceType.TEAM);
given(namespaceMemberRepository.findByUserId("owner-1"))
.willReturn(List.of(new NamespaceMember(1L, "owner-1", NamespaceRole.OWNER)));
given(namespaceRepository.searchByIdIn(
eq(List.of(1L)),
eq(NamespaceStatus.ACTIVE),
eq("team"),
eq("team-ai"),
any()
)).willReturn(new org.springframework.data.domain.PageImpl<>(
List.of(active),
org.springframework.data.domain.PageRequest.of(0, 20),
1
));
mockMvc.perform(get("/api/v1/me/namespaces/page")
.param("page", "0")
.param("size", "20")
.param("status", "ACTIVE")
.param("q", "team")
.param("slug", "team-ai")
.param("roles", "OWNER", "ADMIN")
.with(auth("owner-1"))
.requestAttr("userId", "owner-1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.items[0].slug").value("team-ai"))
.andExpect(jsonPath("$.data.items[0].currentUserRole").value("OWNER"))
.andExpect(jsonPath("$.data.total").value(1));
}
@Test
void listMyNamespaces_returnsFrozenAndArchivedNamespacesWithCurrentRole() throws Exception {
Namespace namespace = namespace(1L, "team-a", NamespaceStatus.ARCHIVED, NamespaceType.TEAM);

View file

@ -10053,6 +10053,10 @@ export interface operations {
parameters: {
query: {
pageable: components["schemas"]["Pageable"];
status?: "ACTIVE" | "FROZEN" | "ARCHIVED";
q?: string;
slug?: string;
roles?: ("OWNER" | "ADMIN" | "MEMBER")[];
};
header?: never;
path?: never;
@ -10075,6 +10079,10 @@ export interface operations {
parameters: {
query: {
pageable: components["schemas"]["Pageable"];
status?: "ACTIVE" | "FROZEN" | "ARCHIVED";
q?: string;
slug?: string;
roles?: ("OWNER" | "ADMIN" | "MEMBER")[];
};
header?: never;
path?: never;