fix(knowledge): share public download tickets across tenant context

This commit is contained in:
2026-07-24 13:51:44 +08:00
parent 442ba66848
commit bdc4ffad9f
2 changed files with 7 additions and 1 deletions
@@ -3,6 +3,7 @@ package org.dromara.aihr.knowledge.service;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.aihr.knowledge.domain.AihrKnowledgeQueryDto.ResourceDownloadLink; import org.dromara.aihr.knowledge.domain.AihrKnowledgeQueryDto.ResourceDownloadLink;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.common.core.constant.HttpStatus; import org.dromara.common.core.constant.HttpStatus;
import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.exception.ServiceException;
import org.dromara.system.service.ISysOssService; import org.dromara.system.service.ISysOssService;
@@ -25,7 +26,8 @@ import java.util.Base64;
public class AihrKnowledgeResourceDownloadService { public class AihrKnowledgeResourceDownloadService {
static final Duration TICKET_TTL = Duration.ofMinutes(2); static final Duration TICKET_TTL = Duration.ofMinutes(2);
private static final String TICKET_PREFIX = "aihr:knowledge:resource-download:"; // The public GET has no tenant context, so this must bypass tenant Redis namespacing.
private static final String TICKET_PREFIX = GlobalConstants.GLOBAL_REDIS_KEY + "aihr:knowledge:resource-download:";
private static final SecureRandom TICKET_RANDOM = new SecureRandom(); private static final SecureRandom TICKET_RANDOM = new SecureRandom();
private final AihrKnowledgeQueryService queryService; private final AihrKnowledgeQueryService queryService;
@@ -3,6 +3,7 @@ package org.dromara.aihr.knowledge;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.dromara.aihr.knowledge.service.AihrKnowledgeQueryService; import org.dromara.aihr.knowledge.service.AihrKnowledgeQueryService;
import org.dromara.aihr.knowledge.service.AihrKnowledgeResourceDownloadService; import org.dromara.aihr.knowledge.service.AihrKnowledgeResourceDownloadService;
import org.dromara.common.core.constant.GlobalConstants;
import org.dromara.system.service.ISysOssService; import org.dromara.system.service.ISysOssService;
import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -14,6 +15,7 @@ import java.time.Duration;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.startsWith;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -35,6 +37,7 @@ class AihrKnowledgeResourceDownloadServiceTest {
var link = new AihrKnowledgeResourceDownloadService(queryService, ossService, redisson).issue(321L); var link = new AihrKnowledgeResourceDownloadService(queryService, ossService, redisson).issue(321L);
assertTrue(link.url().matches("/api/knowledge/resources/321/download\\?ticket=[A-Za-z0-9_-]{43}")); assertTrue(link.url().matches("/api/knowledge/resources/321/download\\?ticket=[A-Za-z0-9_-]{43}"));
verify(redisson).getBucket(startsWith(GlobalConstants.GLOBAL_REDIS_KEY + "aihr:knowledge:resource-download:321:"));
verify(bucket).set(eq(777L), eq(Duration.ofMinutes(2))); verify(bucket).set(eq(777L), eq(Duration.ofMinutes(2)));
} }
@@ -53,6 +56,7 @@ class AihrKnowledgeResourceDownloadServiceTest {
new AihrKnowledgeResourceDownloadService(queryService, ossService, redisson) new AihrKnowledgeResourceDownloadService(queryService, ossService, redisson)
.download(321L, ticket, response); .download(321L, ticket, response);
verify(redisson).getBucket(GlobalConstants.GLOBAL_REDIS_KEY + "aihr:knowledge:resource-download:321:" + ticket);
verify(response).setHeader("Cache-Control", "no-store"); verify(response).setHeader("Cache-Control", "no-store");
verify(response).setHeader("Referrer-Policy", "no-referrer"); verify(response).setHeader("Referrer-Policy", "no-referrer");
verify(ossService).download(777L, response); verify(ossService).download(777L, response);