mirror of
https://github.com/iflytek/skillhub.git
synced 2026-10-07 02:57:51 +00:00
fix(security): whitelist only public skill GET routes
- require authentication for skill star and rating GET endpoints before the public skill-read rules - keep documented public skill detail, version, download, resolve, and tag listing endpoints readable anonymously - add regression coverage for anonymous star and rating access denial plus public tag listing
This commit is contained in:
parent
ec8f7ec838
commit
ad8bb9c6fd
4 changed files with 77 additions and 1 deletions
|
|
@ -107,4 +107,10 @@ class SkillRatingControllerTest {
|
|||
.content("{\"score\": 4}"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
void get_user_rating_unauthenticated_returns_401() throws Exception {
|
||||
mockMvc.perform(get("/api/v1/skills/10/rating"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,4 +126,10 @@ class SkillStarControllerTest {
|
|||
.andExpect(jsonPath("$.timestamp").isNotEmpty())
|
||||
.andExpect(jsonPath("$.requestId").isNotEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void check_starred_unauthenticated_returns_401() throws Exception {
|
||||
mockMvc.perform(get("/api/v1/skills/10/star"))
|
||||
.andExpect(status().isUnauthorized());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
package com.iflytek.skillhub.controller;
|
||||
|
||||
import com.iflytek.skillhub.domain.namespace.NamespaceMemberRepository;
|
||||
import com.iflytek.skillhub.domain.skill.SkillTag;
|
||||
import com.iflytek.skillhub.domain.skill.service.SkillTagService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
@ActiveProfiles("test")
|
||||
class SkillTagControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockBean
|
||||
private SkillTagService skillTagService;
|
||||
|
||||
@MockBean
|
||||
private NamespaceMemberRepository namespaceMemberRepository;
|
||||
|
||||
@Test
|
||||
void list_tags_is_public() throws Exception {
|
||||
when(skillTagService.listTags(eq("team"), eq("demo")))
|
||||
.thenReturn(List.of(new SkillTag(1L, "latest", 2L, "user-1")));
|
||||
|
||||
mockMvc.perform(get("/api/v1/skills/team/demo/tags"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(0))
|
||||
.andExpect(jsonPath("$.data[0].tagName").value("latest"))
|
||||
.andExpect(jsonPath("$.timestamp").isNotEmpty())
|
||||
.andExpect(jsonPath("$.requestId").isNotEmpty());
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +79,23 @@ public class SecurityConfig {
|
|||
"/api/compat/v1/search",
|
||||
"/api/compat/v1/resolve/**"
|
||||
).permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/api/v1/skills", "/api/v1/skills/**").permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/api/v1/skills/*/star", "/api/v1/skills/*/rating").authenticated()
|
||||
.requestMatchers(
|
||||
HttpMethod.GET,
|
||||
"/api/v1/skills",
|
||||
"/api/v1/skills/*/*",
|
||||
"/api/v1/skills/*/*/versions",
|
||||
"/api/v1/skills/*/*/versions/*",
|
||||
"/api/v1/skills/*/*/versions/*/files",
|
||||
"/api/v1/skills/*/*/versions/*/file",
|
||||
"/api/v1/skills/*/*/resolve",
|
||||
"/api/v1/skills/*/*/download",
|
||||
"/api/v1/skills/*/*/versions/*/download",
|
||||
"/api/v1/skills/*/*/tags",
|
||||
"/api/v1/skills/*/*/tags/*/files",
|
||||
"/api/v1/skills/*/*/tags/*/file",
|
||||
"/api/v1/skills/*/*/tags/*/download"
|
||||
).permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/api/v1/namespaces", "/api/v1/namespaces/*").permitAll()
|
||||
.requestMatchers("/api/v1/admin/**").hasAnyRole("SUPER_ADMIN", "SKILL_ADMIN", "USER_ADMIN", "AUDITOR")
|
||||
.anyRequest().authenticated()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue