refactor(dify): 重构 API 接口和安全配置
- 重构 API接口路径,修改权限命名配置 - 移除了 WebFlux 相关代码,改为使用 Spring Security 配置
This commit is contained in:
parent
54d4e14761
commit
79ed8b3b9c
18
pom.xml
18
pom.xml
@ -119,15 +119,15 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-r2dbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.r2dbc</groupId>
|
||||
<artifactId>r2dbc-postgresql</artifactId>
|
||||
<version>0.8.13.RELEASE</version>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-starter-data-r2dbc</artifactId>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>io.r2dbc</groupId>-->
|
||||
<!-- <artifactId>r2dbc-postgresql</artifactId>-->
|
||||
<!-- <version>0.8.13.RELEASE</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
|
@ -8,7 +8,7 @@ import org.springframework.web.client.RestClient;
|
||||
* @author zhuang
|
||||
*/
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
public class RestClientConfig {
|
||||
|
||||
@Bean
|
||||
public RestClient restClient() {
|
@ -46,12 +46,12 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOrigins("*")
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE")
|
||||
.allowedHeaders("*")
|
||||
.exposedHeaders("*");
|
||||
}
|
||||
// @Override
|
||||
// public void addCorsMappings(CorsRegistry registry) {
|
||||
// registry.addMapping("/**")
|
||||
// .allowedOrigins("*")
|
||||
// .allowedMethods("GET", "POST", "PUT", "DELETE")
|
||||
// .allowedHeaders("*")
|
||||
// .exposedHeaders("*");
|
||||
// }
|
||||
}
|
||||
|
@ -4,9 +4,20 @@ import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import jakarta.activation.DataSource;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.jdbc.DataSourceBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
|
||||
/**
|
||||
* @author Yao
|
||||
@ -14,6 +25,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
@MapperScan(basePackages = "com.zsc.edu.dify.modules.**.repo")
|
||||
@Configuration
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
@ -25,4 +37,5 @@ public class MybatisPlusConfig {
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ public class SpringSecurityConfig {
|
||||
.requestMatchers(HttpMethod.GET, "/api/rest/user/menu","/api/rest/user/register","/api/rest/user/send-email").permitAll()
|
||||
.requestMatchers(HttpMethod.POST, "/api/rest/user/login","/api/rest/user/register").permitAll()
|
||||
.requestMatchers("/api/rest/user/me").permitAll()
|
||||
.requestMatchers("/v1/**").permitAll()
|
||||
.requestMatchers("/v1/**").authenticated()
|
||||
.requestMatchers("/api/**").authenticated()
|
||||
)
|
||||
// 不用注解,直接通过判断路径实现动态访问权限
|
||||
|
@ -1,83 +0,0 @@
|
||||
package com.zsc.edu.dify.framework.security.flux;
|
||||
import com.zsc.edu.dify.common.util.TreeUtil;
|
||||
import com.zsc.edu.dify.exception.StateException;
|
||||
import com.zsc.edu.dify.framework.security.UserDetailsImpl;
|
||||
import com.zsc.edu.dify.modules.system.entity.Dept;
|
||||
import com.zsc.edu.dify.modules.system.entity.Menu;
|
||||
import com.zsc.edu.dify.modules.system.entity.Role;
|
||||
import com.zsc.edu.dify.modules.system.entity.UserRole;
|
||||
import com.zsc.edu.dify.modules.system.repo.flux.*;
|
||||
import com.zsc.edu.dify.modules.system.service.DeptService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author zhuang
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Service
|
||||
public class FluxUserDetailServiceImpl implements ReactiveUserDetailsService {
|
||||
|
||||
private final UserFluxRepository userRepo;
|
||||
private final MenuFluxRepository menuRepository;
|
||||
private final RoleFluxRepository roleFluxRepository;
|
||||
private final UserRoleFluxRepository userRoleFluxRepository;
|
||||
private final DeptService deptService;
|
||||
@Override
|
||||
public Mono<UserDetails> findByUsername(String username) {
|
||||
return userRepo.findByUsername(username)
|
||||
.flatMap(user -> {
|
||||
if (!user.getEnableState()) {
|
||||
return Mono.error(new StateException("用户 '" + username + "' 已被禁用!请联系管理员"));
|
||||
}
|
||||
// 先获取UserRole列表,并从中提取roleIds
|
||||
return userRoleFluxRepository.findByUserId(user.getId()).collectList()
|
||||
.flatMap(userRoles -> Mono.zip(
|
||||
roleFluxRepository.findByDeptId(user.getDeptId()),
|
||||
deptService.listFluxTree(user.getDeptId()),
|
||||
menuRepository.findByRoleId(user.getRoleId())
|
||||
))
|
||||
.flatMap(tuple -> {
|
||||
Role role = (Role) tuple.getT1();
|
||||
List<Dept> depts = (List<Dept>) tuple.getT2();
|
||||
List<Menu> menus = tuple.getT3();
|
||||
|
||||
user.setRole(role);
|
||||
|
||||
Set<Long> dataScopeDeptIds = depts.stream()
|
||||
.map(Dept::getId)
|
||||
.collect(Collectors.toSet());
|
||||
user.setDataScopeDeptIds(dataScopeDeptIds);
|
||||
|
||||
Set<String> permissions = menus.stream()
|
||||
.map(Menu::getPermissions)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
return Mono.just(UserDetailsImpl.from(user, permissions));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
// @Override
|
||||
// public Mono<UserDetails> findByUsername(String username) {
|
||||
// return userRepo.findByUsername(username)
|
||||
// .flatMap(user -> menuRepository.findByRoleId(user.getRoleId())
|
||||
// .map(ids-> userRoleFluxRepository.findByUserId(user.getId()))
|
||||
// .map(roles-> roleFluxRepository.findByIdIn(ids))
|
||||
// .map(menus -> {
|
||||
// Set<String> permissions = menus.stream().map(Menu::getPermissions).collect(Collectors.toSet());
|
||||
// return UserDetailsImpl.from(user, permissions);
|
||||
// })
|
||||
// );
|
||||
// }
|
||||
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
package com.zsc.edu.dify.framework.security.flux;
|
||||
|
||||
import com.zsc.edu.dify.framework.security.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.ReactiveAuthenticationManager;
|
||||
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
||||
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
|
||||
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.core.userdetails.ReactiveUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
|
||||
import org.springframework.security.web.server.authentication.ServerAuthenticationEntryPointFailureHandler;
|
||||
import org.springframework.security.web.server.authentication.ServerAuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.server.authorization.AuthorizationContext;
|
||||
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
|
||||
import org.springframework.security.web.server.context.WebSessionServerSecurityContextRepository;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.reactive.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
@EnableWebFluxSecurity
|
||||
@AllArgsConstructor
|
||||
@Configuration
|
||||
public class SpringWebFluxSecurityConfig {
|
||||
|
||||
private final ReactiveUserDetailsService userDetailsService;
|
||||
private final CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
|
||||
private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
|
||||
private final CustomAccessDeniedHandler customAccessDeniedHandler;
|
||||
private final SecurityBeanConfig securityBeanConfig;
|
||||
|
||||
|
||||
@Bean
|
||||
public ReactiveAuthenticationManager reactiveAuthenticationManager() {
|
||||
UserDetailsRepositoryReactiveAuthenticationManager authenticationManager =
|
||||
new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
|
||||
authenticationManager.setPasswordEncoder(securityBeanConfig.passwordEncoder());
|
||||
return authenticationManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ReactiveAuthorizationManager<AuthorizationContext> reactiveAuthorizationManager() {
|
||||
return (authenticationMono, context) -> authenticationMono
|
||||
.flatMap(authentication ->
|
||||
userDetailsService.findByUsername(authentication.getName())
|
||||
.map(userDetails -> {
|
||||
SecurityUtil.setUserInfo((UserDetailsImpl) userDetails);
|
||||
return new AuthorizationDecision(true);
|
||||
})
|
||||
)
|
||||
.defaultIfEmpty(new AuthorizationDecision(false));
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
|
||||
// 配置认证过滤器
|
||||
AuthenticationWebFilter authenticationFilter = new AuthenticationWebFilter(reactiveAuthenticationManager());
|
||||
authenticationFilter.setAuthenticationSuccessHandler((ServerAuthenticationSuccessHandler) customAuthenticationSuccessHandler);
|
||||
authenticationFilter.setAuthenticationFailureHandler(new ServerAuthenticationEntryPointFailureHandler((ServerAuthenticationEntryPoint) customAuthenticationEntryPoint));
|
||||
authenticationFilter.setSecurityContextRepository(new WebSessionServerSecurityContextRepository());
|
||||
|
||||
return http
|
||||
.authorizeExchange(exchanges -> exchanges
|
||||
.pathMatchers("/v1/flux/**").access(reactiveAuthorizationManager()) // 通过自定义权限管理器进行权限校验
|
||||
.anyExchange().authenticated()
|
||||
)
|
||||
.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION)
|
||||
.exceptionHandling(handling -> handling
|
||||
.authenticationEntryPoint((ServerAuthenticationEntryPoint) customAuthenticationEntryPoint)
|
||||
.accessDeniedHandler((ServerAccessDeniedHandler) customAccessDeniedHandler)
|
||||
)
|
||||
.csrf(ServerHttpSecurity.CsrfSpec::disable)
|
||||
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
|
||||
.httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.addAllowedOrigin("*");
|
||||
config.addAllowedHeader("*");
|
||||
config.addAllowedMethod("*");
|
||||
config.setAllowCredentials(true);
|
||||
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/v1/flux/**", config);
|
||||
return source;
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import io.github.guoshiqiufeng.dify.chat.DifyChat;
|
||||
import io.github.guoshiqiufeng.dify.chat.dto.request.ChatMessageSendRequest;
|
||||
import io.github.guoshiqiufeng.dify.chat.dto.request.MessageConversationsRequest;
|
||||
import io.github.guoshiqiufeng.dify.chat.dto.response.ChatMessageSendCompletionResponse;
|
||||
import io.github.guoshiqiufeng.dify.chat.dto.response.ChatMessageSendResponse;
|
||||
import io.github.guoshiqiufeng.dify.chat.dto.response.MessageConversationsResponse;
|
||||
import io.github.guoshiqiufeng.dify.core.pojo.DifyPageResult;
|
||||
import jakarta.annotation.Resource;
|
||||
@ -12,6 +13,7 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author yanghq
|
||||
@ -27,6 +29,25 @@ public class V1ChatController {
|
||||
@Resource
|
||||
private AppEntityRepository appEntityRepository;
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*
|
||||
* @param sendRequest 消息参数 (可以自定义参数,调用 difyChat 实例时重新组装即可),
|
||||
* 用户 id可以改为从上下文(token)获取,
|
||||
* apikey 建议在数据库进行存储,前端调用时传智能体 id,从数据库查询
|
||||
*/
|
||||
@PostMapping("/completions/{appid}")
|
||||
@PreAuthorize("hasAuthority('dify:chat:query')")
|
||||
public ChatMessageSendResponse sendChatMessage(
|
||||
@RequestBody ChatMessageSendRequest sendRequest,
|
||||
@PathVariable String appid
|
||||
) {
|
||||
String apiKey = appEntityRepository.selectApiKey(appid);
|
||||
sendRequest.setApiKey(apiKey);
|
||||
return difyChat.send(sendRequest);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 发送消息(流式)
|
||||
*
|
||||
@ -34,10 +55,14 @@ public class V1ChatController {
|
||||
* 用户 id可以改为从上下文(token)获取,
|
||||
* apikey 建议在数据库进行存储,前端调用时传智能体 id,从数据库查询
|
||||
*/
|
||||
@PostMapping(value = "/completions/{appId}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
@PreAuthorize("hasAuthority('difyChat:query')")
|
||||
public Flux<ChatMessageSendCompletionResponse> sendChatMessageStream(@RequestBody ChatMessageSendRequest sendRequest, @PathVariable String appId) {
|
||||
sendRequest.setApiKey(appEntityRepository.selectApiKey(appId));
|
||||
@PostMapping(value = "/completions/stream/{appid}", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
|
||||
// @PreAuthorize("hasAuthority('difyChat:query')")
|
||||
public Flux<ChatMessageSendCompletionResponse> sendChatMessageStream(
|
||||
@RequestBody ChatMessageSendRequest sendRequest,
|
||||
@PathVariable String appid
|
||||
) {
|
||||
String apiKey = appEntityRepository.selectApiKey(appid);
|
||||
sendRequest.setApiKey(apiKey);
|
||||
return difyChat.sendChatMessageStream(sendRequest);
|
||||
}
|
||||
|
||||
@ -47,10 +72,14 @@ public class V1ChatController {
|
||||
* @param request 请求参数
|
||||
* @return 会话列表
|
||||
*/
|
||||
@PostMapping("/conversations")
|
||||
@PreAuthorize("hasAuthority('difyChat:query')")
|
||||
public DifyPageResult<MessageConversationsResponse> conversations(@RequestBody MessageConversationsRequest request) {
|
||||
request.setApiKey("app-mM2UGTE5QVPLCwGvwifnV0g7");
|
||||
@PostMapping("/conversations/{appid}")
|
||||
@PreAuthorize("hasAuthority('dify:chat:query')")
|
||||
public DifyPageResult<MessageConversationsResponse> conversations(
|
||||
@RequestBody MessageConversationsRequest request,
|
||||
@PathVariable String appid
|
||||
) {
|
||||
String apiKey = appEntityRepository.selectApiKey(appid);
|
||||
request.setApiKey(apiKey);
|
||||
return difyChat.conversations(request);
|
||||
}
|
||||
|
||||
@ -60,10 +89,10 @@ public class V1ChatController {
|
||||
* @param taskId 任务id
|
||||
* @param userId 用户id
|
||||
*/
|
||||
@PatchMapping("/stopMessagesStream")
|
||||
@PreAuthorize("hasAuthority('difyChat:update')")
|
||||
public void stopMessagesStream( String taskId, String userId) {
|
||||
difyChat.stopMessagesStream("app-mM2UGTE5QVPLCwGvwifnV0g7", taskId, userId);
|
||||
@PatchMapping("/stream/stop")
|
||||
public void stopMessagesStream(@RequestParam String taskId, @RequestParam String userId, @RequestParam String appid) {
|
||||
String apiKey = appEntityRepository.selectApiKey(appid);
|
||||
difyChat.stopMessagesStream(apiKey, taskId, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,9 +101,10 @@ public class V1ChatController {
|
||||
* @param conversationId 会话id
|
||||
* @param userId 用户id
|
||||
*/
|
||||
@DeleteMapping("/messages/suggested")
|
||||
@PreAuthorize("hasAuthority('difyChat:delete')")
|
||||
public void deleteConversation(String conversationId, String userId) {
|
||||
difyChat.deleteConversation(conversationId, "app-mM2UGTE5QVPLCwGvwifnV0g7", userId);
|
||||
@DeleteMapping("/conversation")
|
||||
@PreAuthorize("hasAuthority('dify:chat:delete')")
|
||||
public void deleteConversation(@RequestParam String conversationId, @RequestParam String userId, @RequestParam String appid) {
|
||||
String apiKey = appEntityRepository.selectApiKey(appid);
|
||||
difyChat.deleteConversation(conversationId, apiKey, userId);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import io.github.guoshiqiufeng.dify.dataset.DifyDataset;
|
||||
import io.github.guoshiqiufeng.dify.dataset.dto.request.*;
|
||||
import io.github.guoshiqiufeng.dify.dataset.dto.response.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@ -14,6 +15,9 @@ public class V1DatasetController {
|
||||
@Resource
|
||||
private DifyDataset difyDataset;
|
||||
|
||||
@Value("${dify.dataset.api-key}")
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 分页查询知识库
|
||||
*
|
||||
@ -21,9 +25,9 @@ public class V1DatasetController {
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/page")
|
||||
@PreAuthorize("hasAuthority('difyDataSet:query')")
|
||||
@PreAuthorize("hasAuthority('dify:dataset:query')")
|
||||
public DifyPageResult<DatasetResponse> page(@RequestBody DatasetPageRequest request){
|
||||
request.setApiKey("dataset-kN5WTJ8jR877YfN1A34JceVg");
|
||||
request.setApiKey(apiKey);
|
||||
return difyDataset.page(request);
|
||||
}
|
||||
|
||||
@ -34,7 +38,7 @@ public class V1DatasetController {
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/createDocumentByFile")
|
||||
@PreAuthorize("hasAuthority('difyDataSet:create')")
|
||||
@PreAuthorize("hasAuthority('dify:dataset:create')")
|
||||
public DocumentCreateResponse createDocumentByFile(DocumentCreateByFileRequest request){
|
||||
return difyDataset.createDocumentByFile(request);
|
||||
}
|
||||
@ -46,9 +50,9 @@ public class V1DatasetController {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/pageDocument")
|
||||
@PreAuthorize("hasAuthority('difyDataSet:query')")
|
||||
@PreAuthorize("hasAuthority('dify:dataset:query')")
|
||||
public DifyPageResult<DocumentInfo> pageDocument(@RequestBody DatasetPageDocumentRequest request){
|
||||
request.setApiKey("dataset-kN5WTJ8jR877YfN1A34JceVg");
|
||||
request.setApiKey(apiKey);
|
||||
return difyDataset.pageDocument(request);
|
||||
}
|
||||
|
||||
@ -60,9 +64,9 @@ public class V1DatasetController {
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/uploadFileInfo")
|
||||
@PreAuthorize("hasAuthority('difyDataSet:query')")
|
||||
@PreAuthorize("hasAuthority('dify:dataset:query')")
|
||||
public UploadFileInfoResponse uploadFileInfo(String datasetId, String documentId){
|
||||
return difyDataset.uploadFileInfo(datasetId, documentId,"dataset-kN5WTJ8jR877YfN1A34JceVg");
|
||||
return difyDataset.uploadFileInfo(datasetId, documentId,apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,9 +77,9 @@ public class V1DatasetController {
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping("/deleteDocument")
|
||||
@PreAuthorize("hasAuthority('difyDataSet:delete')")
|
||||
@PreAuthorize("hasAuthority('dify:dataset:delete')")
|
||||
public DocumentDeleteResponse deleteDocument(String datasetId, String documentId){
|
||||
return difyDataset.deleteDocument(datasetId, documentId, "app-mM2UGTE5QVPLCwGvwifnV0g7");
|
||||
return difyDataset.deleteDocument(datasetId, documentId, apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,7 +89,7 @@ public class V1DatasetController {
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/createSegment")
|
||||
@PreAuthorize("hasAuthority('difyDataSet:create')")
|
||||
@PreAuthorize("hasAuthority('dify:dataset:create')")
|
||||
public SegmentResponse createSegment(@RequestBody SegmentCreateRequest request){
|
||||
return difyDataset.createSegment(request);
|
||||
}
|
||||
@ -97,7 +101,7 @@ public class V1DatasetController {
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/createSegmentChildChunk")
|
||||
@PreAuthorize("hasAuthority('difyDataSet:create')")
|
||||
@PreAuthorize("hasAuthority('dify:dataset:create')")
|
||||
public SegmentChildChunkCreateResponse createSegmentChildChunk(@RequestBody SegmentChildChunkCreateRequest request){
|
||||
return difyDataset.createSegmentChildChunk(request);
|
||||
}
|
||||
@ -109,7 +113,7 @@ public class V1DatasetController {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/retrieve")
|
||||
@PreAuthorize("hasAuthority('difyDataSet:query')")
|
||||
@PreAuthorize("hasAuthority('dify:dataset:query')")
|
||||
public RetrieveResponse retrieve(@RequestBody RetrieveRequest request){
|
||||
return difyDataset.retrieve(request);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class V1ServerController {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/apps")
|
||||
@PreAuthorize("hasAuthority('difyServer:query')")
|
||||
@PreAuthorize("hasAuthority('dify:server:query')")
|
||||
public List<AppsResponseVO> getApps(String mode, String name) {
|
||||
return difyServerService.getApps(mode, name);
|
||||
}
|
||||
@ -42,7 +42,7 @@ public class V1ServerController {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAuthority('difyServer:query')")
|
||||
@PreAuthorize("hasAuthority('dify:server:query')")
|
||||
public AppsResponseVO getApp(@PathVariable("id") String id) {
|
||||
return difyServer.app(id);
|
||||
}
|
||||
@ -53,7 +53,7 @@ public class V1ServerController {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/api-key/{id}")
|
||||
@PreAuthorize("hasAuthority('difyServer:query')")
|
||||
@PreAuthorize("hasAuthority('dify:server:query')")
|
||||
public List<ApiKeyResponseVO> getAppApiKey(@PathVariable("id") String id) {
|
||||
return difyServer.getAppApiKey(id);
|
||||
}
|
||||
@ -64,7 +64,7 @@ public class V1ServerController {
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/api-key/init/{id}")
|
||||
@PreAuthorize("hasAuthority('difyServer:create')")
|
||||
@PreAuthorize("hasAuthority('dify:server:create')")
|
||||
public List<ApiKeyResponseVO> initAppApiKey(@PathVariable("id") String id) {
|
||||
return difyServer.initAppApiKey(id);
|
||||
}
|
||||
@ -74,7 +74,7 @@ public class V1ServerController {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/api-key/dataset")
|
||||
@PreAuthorize("hasAuthority('difyServer:query')")
|
||||
@PreAuthorize("hasAuthority('dify:server:query')")
|
||||
public List<DatasetApiKeyResponseVO> getDatasetApiKey() {
|
||||
return difyServer.getDatasetApiKey();
|
||||
}
|
||||
@ -84,7 +84,7 @@ public class V1ServerController {
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/api-key/dataset/init")
|
||||
@PreAuthorize("hasAuthority('difyServer:create')")
|
||||
@PreAuthorize("hasAuthority('dify:server:create')")
|
||||
public List<DatasetApiKeyResponseVO> initDatasetApiKey() {
|
||||
return difyServer.initDatasetApiKey();
|
||||
}
|
||||
@ -95,8 +95,8 @@ public class V1ServerController {
|
||||
* @param id 应用id
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/app/{id}")
|
||||
@PreAuthorize("hasAuthority('difyServer:update')")
|
||||
@PostMapping("/app/{id}/toggle")
|
||||
@PreAuthorize("hasAuthority('dify:server:update')")
|
||||
public boolean enabledApp(@PathVariable String id) {
|
||||
return difyServerService.enabledApp(id);
|
||||
}
|
||||
@ -105,9 +105,9 @@ public class V1ServerController {
|
||||
* 获取可用应用列表
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/apps/able")
|
||||
@PreAuthorize("hasAuthority('difyServer:query')")
|
||||
public List<AppEntity> getAbleApps() {
|
||||
@GetMapping("/apps/enabled")
|
||||
@PreAuthorize("hasAuthority('dify:server:query')")
|
||||
public List<AppEntity> getEnableApps() {
|
||||
LambdaQueryWrapper<AppEntity> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(AppEntity::isEnabled, true);
|
||||
return difyServerService.list(queryWrapper);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.zsc.edu.dify.modules.dify.controller;
|
||||
|
||||
import com.zsc.edu.dify.modules.dify.repo.AppEntityRepository;
|
||||
import io.github.guoshiqiufeng.dify.core.pojo.DifyPageResult;
|
||||
import io.github.guoshiqiufeng.dify.workflow.DifyWorkflow;
|
||||
import io.github.guoshiqiufeng.dify.workflow.dto.request.WorkflowLogsRequest;
|
||||
@ -11,22 +12,27 @@ import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/v1/work")
|
||||
@RequestMapping("/v1/workflow")
|
||||
public class V1WorkflowController {
|
||||
|
||||
@Resource
|
||||
private DifyWorkflow difyWorkflow;
|
||||
|
||||
|
||||
@Resource
|
||||
private AppEntityRepository appEntityRepository;
|
||||
|
||||
/**
|
||||
* 运行工作流
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/run")
|
||||
@PreAuthorize("hasAuthority('difyWorkFlow:query')")
|
||||
public WorkflowRunResponse runWorkflow(@RequestBody WorkflowRunRequest request) {
|
||||
request.setApiKey("app-ZpkQM6yy767oUTfNSBYq65nB");
|
||||
@PostMapping("/run/{appId}")
|
||||
@PreAuthorize("hasAuthority('dify:workflow:run')")
|
||||
public WorkflowRunResponse runWorkflow(@RequestBody WorkflowRunRequest request,@PathVariable String appId) {
|
||||
String apiKey = appEntityRepository.selectApiKey(appId);
|
||||
request.setApiKey(apiKey);
|
||||
return difyWorkflow.runWorkflow(request);
|
||||
}
|
||||
|
||||
@ -38,7 +44,6 @@ public class V1WorkflowController {
|
||||
*/
|
||||
@PostMapping("/run/stream")
|
||||
public Flux<WorkflowRunStreamResponse> runWorkflowStream(@RequestBody WorkflowRunRequest request) {
|
||||
request.setApiKey("app-ZpkQM6yy767oUTfNSBYq65nB");
|
||||
return difyWorkflow.runWorkflowStream(request);
|
||||
}
|
||||
|
||||
@ -49,9 +54,10 @@ public class V1WorkflowController {
|
||||
* @param userId
|
||||
* @return
|
||||
*/
|
||||
@PatchMapping("/stop")
|
||||
public WorkflowStopResponse stopWorkflowStream( String taskId, String userId){
|
||||
return difyWorkflow.stopWorkflowStream("app-mM2UGTE5QVPLCwGvwifnV0g7", taskId, userId);
|
||||
@PatchMapping("/stop/{appId}")
|
||||
public WorkflowStopResponse stopWorkflowStream( String taskId, String userId, @PathVariable String appId) {
|
||||
String apiKey = appEntityRepository.selectApiKey(appId);
|
||||
return difyWorkflow.stopWorkflowStream(apiKey, taskId, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -60,10 +66,11 @@ public class V1WorkflowController {
|
||||
* @param workflowRunId
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/info")
|
||||
@PreAuthorize("hasAuthority('difyWorkFlow:query')")
|
||||
public WorkflowInfoResponse info(String workflowRunId) {
|
||||
return difyWorkflow.info(workflowRunId, "app-ZpkQM6yy767oUTfNSBYq65nB");
|
||||
@GetMapping("/info/{appId}")
|
||||
@PreAuthorize("hasAuthority('dify:workflow:info')")
|
||||
public WorkflowInfoResponse info(String workflowRunId, @PathVariable String appId) {
|
||||
String apiKey = appEntityRepository.selectApiKey(appId);
|
||||
return difyWorkflow.info(workflowRunId, apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,10 +79,11 @@ public class V1WorkflowController {
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/logs")
|
||||
@PreAuthorize("hasAuthority('difyWorkFlow:query')")
|
||||
public DifyPageResult<WorkflowLogs> logs(@RequestBody WorkflowLogsRequest request) {
|
||||
request.setApiKey("app-ZpkQM6yy767oUTfNSBYq65nB");
|
||||
@PostMapping("/logs/{appId}")
|
||||
@PreAuthorize("hasAuthority('difyWorkFlow:log')")
|
||||
public DifyPageResult<WorkflowLogs> logs(@RequestBody WorkflowLogsRequest request, @PathVariable String appId) {
|
||||
String apiKey = appEntityRepository.selectApiKey(appId);
|
||||
request.setApiKey(apiKey);
|
||||
return difyWorkflow.logs(request);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
package com.zsc.edu.dify.modules.system.repo.flux;
|
||||
|
||||
import com.zsc.edu.dify.modules.system.entity.Menu;
|
||||
import org.springframework.data.r2dbc.repository.Query;
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
@Repository
|
||||
public interface MenuFluxRepository extends ReactiveCrudRepository<Menu,Long> {
|
||||
|
||||
@Query("select * from sys_menu where id in (select menu_id from sys_roles_menus where role_id = :roleId)")
|
||||
Mono<List<Menu>> findByRoleId(Long roleId);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package com.zsc.edu.dify.modules.system.repo.flux;
|
||||
|
||||
import com.zsc.edu.dify.modules.system.entity.Role;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface RoleFluxRepository extends ReactiveCrudRepository<Role,Long> {
|
||||
|
||||
Mono<?> findByDeptId(Long id);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.zsc.edu.dify.modules.system.repo.flux;
|
||||
|
||||
import com.zsc.edu.dify.modules.system.entity.User;
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Repository
|
||||
public interface UserFluxRepository extends ReactiveCrudRepository<User,Long> {
|
||||
|
||||
Mono<User> findByUsername(String username);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.zsc.edu.dify.modules.system.repo.flux;
|
||||
|
||||
import com.zsc.edu.dify.modules.system.entity.UserRole;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
@Repository
|
||||
public interface UserRoleFluxRepository extends ReactiveCrudRepository<UserRole,Long> {
|
||||
|
||||
Flux<List<Long>> findByUserId(Long userId);
|
||||
}
|
@ -11,12 +11,12 @@ mybatis-plus:
|
||||
map-underscore-to-camel-case: true
|
||||
|
||||
spring:
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
r2dbc:
|
||||
url: r2dbc:postgresql://43.139.10.64:15432/dify?ssl=false&TimeZone=Asia/Shanghai
|
||||
username: gitea
|
||||
password: gitea
|
||||
# main:
|
||||
# allow-bean-definition-overriding: true
|
||||
# r2dbc:
|
||||
# url: r2dbc:postgresql://43.139.10.64:15432/dify?ssl=false&TimeZone=Asia/Shanghai
|
||||
# username: gitea
|
||||
# password: gitea
|
||||
datasource:
|
||||
url: jdbc:postgresql://43.139.10.64:15432/dify?ssl=false&TimeZone=Asia/Shanghai
|
||||
username: gitea
|
||||
|
Loading…
Reference in New Issue
Block a user