mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-11 12:07:42 +00:00
(feat)Support for managing large models with Dify #1830;2、add user access token; #1829; 3、support change password #1824 (#1839)
This commit is contained in:
@@ -3,6 +3,7 @@ package com.tencent.supersonic.auth.api.authentication.adaptor;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
||||||
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserToken;
|
||||||
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
||||||
import com.tencent.supersonic.common.pojo.User;
|
import com.tencent.supersonic.common.pojo.User;
|
||||||
|
|
||||||
@@ -27,4 +28,16 @@ public interface UserAdaptor {
|
|||||||
List<User> getUserByOrg(String key);
|
List<User> getUserByOrg(String key);
|
||||||
|
|
||||||
Set<String> getUserAllOrgId(String userName);
|
Set<String> getUserAllOrgId(String userName);
|
||||||
|
|
||||||
|
String getPassword(String userName);
|
||||||
|
|
||||||
|
void resetPassword(String userName, String password, String newPassword);
|
||||||
|
|
||||||
|
UserToken generateToken(String name, String userName, long expireTime);
|
||||||
|
|
||||||
|
void deleteUserToken(Long id);
|
||||||
|
|
||||||
|
UserToken getUserToken(Long id);
|
||||||
|
|
||||||
|
List<UserToken> getUserTokens(String userName);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.tencent.supersonic.auth.api.authentication.pojo;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserToken {
|
||||||
|
private Integer id;
|
||||||
|
private String name;
|
||||||
|
private String userName;
|
||||||
|
private String token;
|
||||||
|
private Long expireTime;
|
||||||
|
private Date createDate;
|
||||||
|
private Date expireDate;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.tencent.supersonic.auth.api.authentication.request;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class UserTokenReq {
|
||||||
|
@NotBlank(message = "name can not be null")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotBlank(message = "expireTime can not be null")
|
||||||
|
private long expireTime;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
||||||
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserToken;
|
||||||
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
||||||
import com.tencent.supersonic.common.pojo.User;
|
import com.tencent.supersonic.common.pojo.User;
|
||||||
|
|
||||||
@@ -30,4 +31,16 @@ public interface UserService {
|
|||||||
List<User> getUserByOrg(String key);
|
List<User> getUserByOrg(String key);
|
||||||
|
|
||||||
List<Organization> getOrganizationTree();
|
List<Organization> getOrganizationTree();
|
||||||
|
|
||||||
|
String getPassword(String userName);
|
||||||
|
|
||||||
|
void resetPassword(String userName, String password, String newPassword);
|
||||||
|
|
||||||
|
UserToken generateToken(String name, String userName, long expireTime);
|
||||||
|
|
||||||
|
List<UserToken> getUserTokens(String userName);
|
||||||
|
|
||||||
|
UserToken getUserToken(Long id);
|
||||||
|
|
||||||
|
void deleteUserToken(Long id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.adaptor;
|
package com.tencent.supersonic.auth.authentication.adaptor;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.tencent.supersonic.auth.api.authentication.adaptor.UserAdaptor;
|
import com.tencent.supersonic.auth.api.authentication.adaptor.UserAdaptor;
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
||||||
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserToken;
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
||||||
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
||||||
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO;
|
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO;
|
||||||
|
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserTokenDO;
|
||||||
import com.tencent.supersonic.auth.authentication.persistence.repository.UserRepository;
|
import com.tencent.supersonic.auth.authentication.persistence.repository.UserRepository;
|
||||||
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
||||||
import com.tencent.supersonic.common.pojo.User;
|
import com.tencent.supersonic.common.pojo.User;
|
||||||
@@ -15,8 +19,8 @@ import com.tencent.supersonic.common.util.ContextUtils;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -106,6 +110,68 @@ public class DefaultUserAdaptor implements UserAdaptor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword(String userName) {
|
||||||
|
UserDO userDO = getUser(userName);
|
||||||
|
if (userDO == null) {
|
||||||
|
throw new RuntimeException("user not exist,please register");
|
||||||
|
}
|
||||||
|
return userDO.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetPassword(String userName, String password, String newPassword) {
|
||||||
|
UserRepository userRepository = ContextUtils.getBean(UserRepository.class);
|
||||||
|
Optional<UserDO> userDOOptional = Optional.ofNullable(getUser(userName));
|
||||||
|
|
||||||
|
UserDO userDO = userDOOptional
|
||||||
|
.orElseThrow(() -> new RuntimeException("User does not exist, please register"));
|
||||||
|
|
||||||
|
try {
|
||||||
|
validateOldPassword(userDO, password);
|
||||||
|
updatePassword(userDO, newPassword, userRepository);
|
||||||
|
} catch (PasswordEncryptionException e) {
|
||||||
|
throw new RuntimeException("Password encryption error, please try again", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void validateOldPassword(UserDO userDO, String password)
|
||||||
|
throws PasswordEncryptionException {
|
||||||
|
String oldPassword = encryptPassword(password, userDO.getSalt());
|
||||||
|
if (!userDO.getPassword().equals(oldPassword)) {
|
||||||
|
throw new RuntimeException("Old password is not correct, please try again");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePassword(UserDO userDO, String newPassword, UserRepository userRepository)
|
||||||
|
throws PasswordEncryptionException {
|
||||||
|
try {
|
||||||
|
byte[] salt = AESEncryptionUtil.generateSalt(userDO.getName());
|
||||||
|
userDO.setSalt(AESEncryptionUtil.getStringFromBytes(salt));
|
||||||
|
userDO.setPassword(AESEncryptionUtil.encrypt(newPassword, salt));
|
||||||
|
userRepository.updateUser(userDO);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PasswordEncryptionException("Error encrypting password", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String encryptPassword(String password, String salt)
|
||||||
|
throws PasswordEncryptionException {
|
||||||
|
try {
|
||||||
|
return AESEncryptionUtil.encrypt(password, AESEncryptionUtil.getBytesFromString(salt));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new PasswordEncryptionException("Error encrypting password", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PasswordEncryptionException extends Exception {
|
||||||
|
public PasswordEncryptionException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private UserWithPassword getUserWithPassword(UserReq userReq) {
|
private UserWithPassword getUserWithPassword(UserReq userReq) {
|
||||||
UserDO userDO = getUser(userReq.getName());
|
UserDO userDO = getUser(userReq.getName());
|
||||||
if (userDO == null) {
|
if (userDO == null) {
|
||||||
@@ -136,4 +202,70 @@ public class DefaultUserAdaptor implements UserAdaptor {
|
|||||||
public Set<String> getUserAllOrgId(String userName) {
|
public Set<String> getUserAllOrgId(String userName) {
|
||||||
return Sets.newHashSet();
|
return Sets.newHashSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserToken generateToken(String name, String userName, long expireTime) {
|
||||||
|
TokenService tokenService = ContextUtils.getBean(TokenService.class);
|
||||||
|
UserDO userDO = getUser(userName);
|
||||||
|
if (userDO == null) {
|
||||||
|
throw new RuntimeException("user not exist,please register");
|
||||||
|
}
|
||||||
|
UserWithPassword userWithPassword =
|
||||||
|
new UserWithPassword(userDO.getId(), userDO.getName(), userDO.getDisplayName(),
|
||||||
|
userDO.getEmail(), userDO.getPassword(), userDO.getIsAdmin());
|
||||||
|
|
||||||
|
String token =
|
||||||
|
tokenService.generateToken(UserWithPassword.convert(userWithPassword), expireTime);
|
||||||
|
UserTokenDO userTokenDO = saveUserToken(name, userName, token, expireTime);
|
||||||
|
return convertUserToken(userTokenDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteUserToken(Long id) {
|
||||||
|
UserRepository userRepository = ContextUtils.getBean(UserRepository.class);
|
||||||
|
userRepository.deleteUserToken(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserToken getUserToken(Long id) {
|
||||||
|
UserRepository userRepository = ContextUtils.getBean(UserRepository.class);
|
||||||
|
return convertUserToken(userRepository.getUserToken(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<UserToken> getUserTokens(String userName) {
|
||||||
|
UserRepository userRepository = ContextUtils.getBean(UserRepository.class);
|
||||||
|
List<UserToken> userTokens = userRepository.getUserTokenListByName(userName).stream()
|
||||||
|
.map(this::convertUserToken).collect(Collectors.toList());
|
||||||
|
return userTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserTokenDO saveUserToken(String tokenName, String userName, String token,
|
||||||
|
long expireTime) {
|
||||||
|
UserTokenDO userTokenDO = new UserTokenDO();
|
||||||
|
userTokenDO.setName(tokenName);
|
||||||
|
userTokenDO.setUserName(userName);
|
||||||
|
userTokenDO.setToken(token);
|
||||||
|
userTokenDO.setExpireTime(expireTime);
|
||||||
|
userTokenDO.setCreateTime(new java.util.Date());
|
||||||
|
userTokenDO.setCreateBy(userName);
|
||||||
|
userTokenDO.setUpdateBy(userName);
|
||||||
|
userTokenDO.setExpireDateTime(new java.util.Date(System.currentTimeMillis() + expireTime));
|
||||||
|
UserRepository userRepository = ContextUtils.getBean(UserRepository.class);
|
||||||
|
userRepository.addUserToken(userTokenDO);
|
||||||
|
|
||||||
|
return userTokenDO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserToken convertUserToken(UserTokenDO userTokenDO) {
|
||||||
|
UserToken userToken = new UserToken();
|
||||||
|
userToken.setId(userTokenDO.getId());
|
||||||
|
userToken.setName(userTokenDO.getName());
|
||||||
|
userToken.setUserName(userTokenDO.getUserName());
|
||||||
|
userToken.setToken(userTokenDO.getToken());
|
||||||
|
userToken.setExpireTime(userTokenDO.getExpireTime());
|
||||||
|
userToken.setCreateDate(userTokenDO.getCreateTime());
|
||||||
|
userToken.setExpireDate(userTokenDO.getExpireDateTime());
|
||||||
|
return userToken;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.interceptor;
|
package com.tencent.supersonic.auth.authentication.interceptor;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
||||||
import com.tencent.supersonic.auth.api.authentication.constant.UserConstants;
|
import com.tencent.supersonic.auth.api.authentication.constant.UserConstants;
|
||||||
import com.tencent.supersonic.auth.authentication.service.UserServiceImpl;
|
import com.tencent.supersonic.auth.authentication.service.UserServiceImpl;
|
||||||
@@ -13,7 +15,6 @@ import org.springframework.util.CollectionUtils;
|
|||||||
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
|
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.interceptor;
|
package com.tencent.supersonic.auth.authentication.interceptor;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.annotation.AuthenticationIgnore;
|
import com.tencent.supersonic.auth.api.authentication.annotation.AuthenticationIgnore;
|
||||||
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
||||||
@@ -14,8 +17,6 @@ import io.jsonwebtoken.Claims;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.tencent.supersonic.auth.authentication.persistence.dataobject;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("s2_user_token")
|
||||||
|
public class UserTokenDO {
|
||||||
|
@TableId(type = IdType.AUTO)
|
||||||
|
Integer id;
|
||||||
|
String name;
|
||||||
|
String userName;
|
||||||
|
Long expireTime;
|
||||||
|
String token;
|
||||||
|
String salt;
|
||||||
|
Date createTime;
|
||||||
|
Date updateTime;
|
||||||
|
String createBy;
|
||||||
|
String updateBy;
|
||||||
|
Date expireDateTime;
|
||||||
|
}
|
||||||
@@ -14,4 +14,6 @@ public interface UserDOMapper {
|
|||||||
|
|
||||||
/** @mbg.generated */
|
/** @mbg.generated */
|
||||||
List<UserDO> selectByExample(UserDOExample example);
|
List<UserDO> selectByExample(UserDOExample example);
|
||||||
|
|
||||||
|
void updateByPrimaryKey(UserDO userDO);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.tencent.supersonic.auth.authentication.persistence.mapper;
|
||||||
|
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserTokenDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface UserTokenDOMapper extends BaseMapper<UserTokenDO> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.persistence.repository;
|
package com.tencent.supersonic.auth.authentication.persistence.repository;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO;
|
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO;
|
||||||
|
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserTokenDO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -10,5 +11,17 @@ public interface UserRepository {
|
|||||||
|
|
||||||
void addUser(UserDO userDO);
|
void addUser(UserDO userDO);
|
||||||
|
|
||||||
|
List<UserTokenDO> getUserTokenListByName(String userName);
|
||||||
|
|
||||||
UserDO getUser(String name);
|
UserDO getUser(String name);
|
||||||
|
|
||||||
|
void updateUser(UserDO userDO);
|
||||||
|
|
||||||
|
void addUserToken(UserTokenDO userTokenDO);
|
||||||
|
|
||||||
|
UserTokenDO getUserToken(Long tokenId);
|
||||||
|
|
||||||
|
void deleteUserTokenByName(String userName);
|
||||||
|
|
||||||
|
void deleteUserToken(Long tokenId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.persistence.repository.impl;
|
package com.tencent.supersonic.auth.authentication.persistence.repository.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO;
|
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO;
|
||||||
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDOExample;
|
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDOExample;
|
||||||
|
import com.tencent.supersonic.auth.authentication.persistence.dataobject.UserTokenDO;
|
||||||
import com.tencent.supersonic.auth.authentication.persistence.mapper.UserDOMapper;
|
import com.tencent.supersonic.auth.authentication.persistence.mapper.UserDOMapper;
|
||||||
|
import com.tencent.supersonic.auth.authentication.persistence.mapper.UserTokenDOMapper;
|
||||||
import com.tencent.supersonic.auth.authentication.persistence.repository.UserRepository;
|
import com.tencent.supersonic.auth.authentication.persistence.repository.UserRepository;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
@@ -14,8 +17,11 @@ public class UserRepositoryImpl implements UserRepository {
|
|||||||
|
|
||||||
private UserDOMapper userDOMapper;
|
private UserDOMapper userDOMapper;
|
||||||
|
|
||||||
public UserRepositoryImpl(UserDOMapper userDOMapper) {
|
private UserTokenDOMapper userTokenDOMapper;
|
||||||
|
|
||||||
|
public UserRepositoryImpl(UserDOMapper userDOMapper, UserTokenDOMapper userTokenDOMapper) {
|
||||||
this.userDOMapper = userDOMapper;
|
this.userDOMapper = userDOMapper;
|
||||||
|
this.userTokenDOMapper = userTokenDOMapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -23,6 +29,11 @@ public class UserRepositoryImpl implements UserRepository {
|
|||||||
return userDOMapper.selectByExample(new UserDOExample());
|
return userDOMapper.selectByExample(new UserDOExample());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateUser(UserDO userDO) {
|
||||||
|
userDOMapper.updateByPrimaryKey(userDO);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addUser(UserDO userDO) {
|
public void addUser(UserDO userDO) {
|
||||||
userDOMapper.insert(userDO);
|
userDOMapper.insert(userDO);
|
||||||
@@ -36,4 +47,33 @@ public class UserRepositoryImpl implements UserRepository {
|
|||||||
Optional<UserDO> userDOOptional = userDOS.stream().findFirst();
|
Optional<UserDO> userDOOptional = userDOS.stream().findFirst();
|
||||||
return userDOOptional.orElse(null);
|
return userDOOptional.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<UserTokenDO> getUserTokenListByName(String userName) {
|
||||||
|
QueryWrapper<UserTokenDO> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("user_name", userName);
|
||||||
|
return userTokenDOMapper.selectList(queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addUserToken(UserTokenDO userTokenDO) {
|
||||||
|
userTokenDOMapper.insert(userTokenDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserTokenDO getUserToken(Long tokenId) {
|
||||||
|
return userTokenDOMapper.selectById(tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteUserTokenByName(String userName) {
|
||||||
|
QueryWrapper<UserTokenDO> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("user_name", userName);
|
||||||
|
userTokenDOMapper.delete(queryWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteUserToken(Long tokenId) {
|
||||||
|
userTokenDOMapper.deleteById(tokenId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
||||||
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserToken;
|
||||||
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
||||||
|
import com.tencent.supersonic.auth.api.authentication.request.UserTokenReq;
|
||||||
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
||||||
import com.tencent.supersonic.common.pojo.User;
|
import com.tencent.supersonic.common.pojo.User;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -13,6 +15,7 @@ import org.springframework.web.bind.annotation.PathVariable;
|
|||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -69,4 +72,28 @@ public class UserController {
|
|||||||
public String login(@RequestBody UserReq userCmd, HttpServletRequest request) {
|
public String login(@RequestBody UserReq userCmd, HttpServletRequest request) {
|
||||||
return userService.login(userCmd, request);
|
return userService.login(userCmd, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/generateToken")
|
||||||
|
public UserToken generateToken(@RequestBody UserTokenReq userTokenReq,
|
||||||
|
HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
User user = userService.getCurrentUser(request, response);
|
||||||
|
return userService.generateToken(userTokenReq.getName(), user.getName(),
|
||||||
|
userTokenReq.getExpireTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getUserTokens")
|
||||||
|
public List<UserToken> getUserTokens(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
User user = userService.getCurrentUser(request, response);
|
||||||
|
return userService.getUserTokens(user.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getUserToken")
|
||||||
|
public UserToken getUserToken(@RequestParam(name = "tokenId") Long tokenId) {
|
||||||
|
return userService.getUserToken(tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/deleteUserToken")
|
||||||
|
public void deleteUserToken(@RequestParam(name = "tokenId") Long tokenId) {
|
||||||
|
userService.deleteUserToken(tokenId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
import com.tencent.supersonic.auth.api.authentication.pojo.Organization;
|
||||||
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserToken;
|
||||||
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
import com.tencent.supersonic.auth.api.authentication.request.UserReq;
|
||||||
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
import com.tencent.supersonic.auth.api.authentication.service.UserService;
|
||||||
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
|
import com.tencent.supersonic.auth.api.authentication.utils.UserHolder;
|
||||||
@@ -79,4 +80,34 @@ public class UserServiceImpl implements UserService {
|
|||||||
public String login(UserReq userReq, String appKey) {
|
public String login(UserReq userReq, String appKey) {
|
||||||
return ComponentFactory.getUserAdaptor().login(userReq, appKey);
|
return ComponentFactory.getUserAdaptor().login(userReq, appKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword(String userName) {
|
||||||
|
return ComponentFactory.getUserAdaptor().getPassword(userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetPassword(String userName, String password, String newPassword) {
|
||||||
|
ComponentFactory.getUserAdaptor().resetPassword(userName, password, newPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserToken generateToken(String name, String userName, long expireTime) {
|
||||||
|
return ComponentFactory.getUserAdaptor().generateToken(name, userName, expireTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<UserToken> getUserTokens(String userName) {
|
||||||
|
return ComponentFactory.getUserAdaptor().getUserTokens(userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserToken getUserToken(Long id) {
|
||||||
|
return ComponentFactory.getUserAdaptor().getUserToken(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteUserToken(Long id) {
|
||||||
|
ComponentFactory.getUserAdaptor().deleteUserToken(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.strategy;
|
package com.tencent.supersonic.auth.authentication.strategy;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.constant.UserConstants;
|
import com.tencent.supersonic.auth.api.authentication.constant.UserConstants;
|
||||||
import com.tencent.supersonic.auth.api.authentication.service.UserStrategy;
|
import com.tencent.supersonic.auth.api.authentication.service.UserStrategy;
|
||||||
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
import com.tencent.supersonic.auth.authentication.utils.TokenService;
|
||||||
@@ -7,8 +10,6 @@ import com.tencent.supersonic.common.pojo.User;
|
|||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package com.tencent.supersonic.auth.authentication.utils;
|
package com.tencent.supersonic.auth.authentication.utils;
|
||||||
|
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
import com.tencent.supersonic.auth.api.authentication.config.AuthenticationConfig;
|
||||||
|
import com.tencent.supersonic.auth.api.authentication.pojo.UserWithPassword;
|
||||||
import com.tencent.supersonic.common.pojo.exception.AccessException;
|
import com.tencent.supersonic.common.pojo.exception.AccessException;
|
||||||
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Claims;
|
||||||
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.Jwts;
|
||||||
@@ -9,14 +13,11 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_CREATE_TIME;
|
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_PREFIX;
|
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_PREFIX;
|
||||||
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_NAME;
|
import static com.tencent.supersonic.auth.api.authentication.constant.UserConstants.TOKEN_USER_NAME;
|
||||||
|
|
||||||
@@ -32,33 +33,40 @@ public class TokenService {
|
|||||||
|
|
||||||
public String generateToken(Map<String, Object> claims, HttpServletRequest request) {
|
public String generateToken(Map<String, Object> claims, HttpServletRequest request) {
|
||||||
String appKey = getAppKey(request);
|
String appKey = getAppKey(request);
|
||||||
return generateToken(claims, appKey);
|
long expiration = System.currentTimeMillis() + authenticationConfig.getTokenTimeout();
|
||||||
|
return generateToken(claims, appKey, expiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateToken(Map<String, Object> claims, long expiration) {
|
||||||
|
String appKey = authenticationConfig.getTokenDefaultAppKey();
|
||||||
|
long exp = System.currentTimeMillis() + expiration;
|
||||||
|
return generateToken(claims, appKey, exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String generateToken(Map<String, Object> claims, String appKey) {
|
public String generateToken(Map<String, Object> claims, String appKey) {
|
||||||
return toTokenString(claims, appKey);
|
long expiration = System.currentTimeMillis() + authenticationConfig.getTokenTimeout();
|
||||||
|
return toTokenString(claims, appKey, expiration);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String toTokenString(Map<String, Object> claims, String appKey) {
|
public String generateToken(Map<String, Object> claims, String appKey, long expiration) {
|
||||||
Long tokenTimeout = authenticationConfig.getTokenTimeout();
|
return toTokenString(claims, appKey, expiration);
|
||||||
long expiration = Long.parseLong(claims.get(TOKEN_CREATE_TIME) + "") + tokenTimeout;
|
|
||||||
Date expirationDate = new Date(expiration);
|
|
||||||
String tokenSecret = getTokenSecret(appKey);
|
|
||||||
|
|
||||||
return Jwts.builder().setClaims(claims).setSubject(claims.get(TOKEN_USER_NAME).toString())
|
|
||||||
.setExpiration(expirationDate)
|
|
||||||
.signWith(new SecretKeySpec(tokenSecret.getBytes(StandardCharsets.UTF_8),
|
|
||||||
SignatureAlgorithm.HS512.getJcaName()), SignatureAlgorithm.HS512)
|
|
||||||
.compact();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getTokenSecret(String appKey) {
|
public String generateAppUserToken(HttpServletRequest request) {
|
||||||
Map<String, String> appKeyToSecretMap = authenticationConfig.getAppKeyToSecretMap();
|
String appName = request.getHeader("AppId");
|
||||||
String secret = appKeyToSecretMap.get(appKey);
|
if (StringUtils.isBlank(appName)) {
|
||||||
if (StringUtils.isBlank(secret)) {
|
String message = "AppId is blank, get app_user failed";
|
||||||
throw new AccessException("get secret from appKey failed :" + appKey);
|
log.warn("{}, uri: {}", message, request.getServletPath());
|
||||||
|
throw new AccessException(message);
|
||||||
}
|
}
|
||||||
return secret;
|
|
||||||
|
UserWithPassword appUser = new UserWithPassword(appName);
|
||||||
|
appUser.setId(1L);
|
||||||
|
appUser.setName(appName);
|
||||||
|
appUser.setPassword("c3VwZXJzb25pY0BiaWNvbdktJJYWw6A3rEmBUPzbn/6DNeYnD+y3mAwDKEMS3KVT");
|
||||||
|
appUser.setDisplayName(appName);
|
||||||
|
appUser.setIsAdmin(0);
|
||||||
|
return generateToken(UserWithPassword.convert(appUser), request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Claims> getClaims(HttpServletRequest request) {
|
public Optional<Claims> getClaims(HttpServletRequest request) {
|
||||||
@@ -67,6 +75,17 @@ public class TokenService {
|
|||||||
return getClaims(token, appKey);
|
return getClaims(token, appKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Optional<Claims> getClaims(String token, HttpServletRequest request) {
|
||||||
|
Optional<Claims> claims;
|
||||||
|
try {
|
||||||
|
String appKey = getAppKey(request);
|
||||||
|
claims = getClaims(token, appKey);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new AccessException("parse user info from token failed :" + token);
|
||||||
|
}
|
||||||
|
return claims;
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<Claims> getClaims(String token, String appKey) {
|
public Optional<Claims> getClaims(String token, String appKey) {
|
||||||
try {
|
try {
|
||||||
String tokenSecret = getTokenSecret(appKey);
|
String tokenSecret = getTokenSecret(appKey);
|
||||||
@@ -86,6 +105,26 @@ public class TokenService {
|
|||||||
: token.trim();
|
: token.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String toTokenString(Map<String, Object> claims, String appKey, long expiration) {
|
||||||
|
Date expirationDate = new Date(expiration);
|
||||||
|
String tokenSecret = getTokenSecret(appKey);
|
||||||
|
|
||||||
|
return Jwts.builder().setClaims(claims).setSubject(claims.get(TOKEN_USER_NAME).toString())
|
||||||
|
.setExpiration(expirationDate)
|
||||||
|
.signWith(new SecretKeySpec(tokenSecret.getBytes(StandardCharsets.UTF_8),
|
||||||
|
SignatureAlgorithm.HS512.getJcaName()), SignatureAlgorithm.HS512)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTokenSecret(String appKey) {
|
||||||
|
Map<String, String> appKeyToSecretMap = authenticationConfig.getAppKeyToSecretMap();
|
||||||
|
String secret = appKeyToSecretMap.get(appKey);
|
||||||
|
if (StringUtils.isBlank(secret)) {
|
||||||
|
throw new AccessException("get secret from appKey failed :" + appKey);
|
||||||
|
}
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
public String getAppKey(HttpServletRequest request) {
|
public String getAppKey(HttpServletRequest request) {
|
||||||
String appKey = request.getHeader(authenticationConfig.getTokenHttpHeaderAppKey());
|
String appKey = request.getHeader(authenticationConfig.getTokenHttpHeaderAppKey());
|
||||||
if (StringUtils.isBlank(appKey)) {
|
if (StringUtils.isBlank(appKey)) {
|
||||||
@@ -93,4 +132,8 @@ public class TokenService {
|
|||||||
}
|
}
|
||||||
return appKey;
|
return appKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDefaultAppKey() {
|
||||||
|
return authenticationConfig.getTokenDefaultAppKey();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,4 +122,29 @@
|
|||||||
<include refid="Example_Where_Clause" />
|
<include refid="Example_Where_Clause" />
|
||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<update id="updateByPrimaryKey" parameterType="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserDO">
|
||||||
|
update s2_user
|
||||||
|
<set>
|
||||||
|
<if test="name != null">
|
||||||
|
name = #{name,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="password != null">
|
||||||
|
password = #{password,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="salt != null">
|
||||||
|
salt = #{salt,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="displayName != null">
|
||||||
|
display_name = #{displayName,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="email != null">
|
||||||
|
email = #{email,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="isAdmin != null">
|
||||||
|
is_admin = #{isAdmin,jdbcType=INTEGER},
|
||||||
|
</if>
|
||||||
|
</set>
|
||||||
|
where id = #{id,jdbcType=BIGINT}
|
||||||
|
</update>
|
||||||
</mapper>
|
</mapper>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.tencent.supersonic.auth.authentication.persistence.mapper.UserTokenDOMapper">
|
||||||
|
<resultMap id="BaseResultMap" type="com.tencent.supersonic.auth.authentication.persistence.dataobject.UserTokenDO">
|
||||||
|
<result column="id" jdbcType="BIGINT" property="id" />
|
||||||
|
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||||
|
<result column="token" jdbcType="VARCHAR" property="token" />
|
||||||
|
<result column="expire_time" jdbcType="TIMESTAMP" property="expireTime" />
|
||||||
|
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -2,8 +2,15 @@ package com.tencent.supersonic.common.pojo;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.tencent.supersonic.common.pojo.Parameter;
|
import dev.langchain4j.provider.AzureModelFactory;
|
||||||
import dev.langchain4j.provider.*;
|
import dev.langchain4j.provider.DashscopeModelFactory;
|
||||||
|
import dev.langchain4j.provider.DifyModelFactory;
|
||||||
|
import dev.langchain4j.provider.LocalAiModelFactory;
|
||||||
|
import dev.langchain4j.provider.ModelProvider;
|
||||||
|
import dev.langchain4j.provider.OllamaModelFactory;
|
||||||
|
import dev.langchain4j.provider.OpenAiModelFactory;
|
||||||
|
import dev.langchain4j.provider.QianfanModelFactory;
|
||||||
|
import dev.langchain4j.provider.ZhipuModelFactory;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -52,7 +59,7 @@ public class ChatModelParameters {
|
|||||||
return Lists.newArrayList(OpenAiModelFactory.PROVIDER, OllamaModelFactory.PROVIDER,
|
return Lists.newArrayList(OpenAiModelFactory.PROVIDER, OllamaModelFactory.PROVIDER,
|
||||||
QianfanModelFactory.PROVIDER, ZhipuModelFactory.PROVIDER,
|
QianfanModelFactory.PROVIDER, ZhipuModelFactory.PROVIDER,
|
||||||
LocalAiModelFactory.PROVIDER, DashscopeModelFactory.PROVIDER,
|
LocalAiModelFactory.PROVIDER, DashscopeModelFactory.PROVIDER,
|
||||||
AzureModelFactory.PROVIDER);
|
AzureModelFactory.PROVIDER, DifyModelFactory.PROVIDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Parameter.Dependency> getBaseUrlDependency() {
|
private static List<Parameter.Dependency> getBaseUrlDependency() {
|
||||||
@@ -63,20 +70,23 @@ public class ChatModelParameters {
|
|||||||
QianfanModelFactory.PROVIDER, QianfanModelFactory.DEFAULT_BASE_URL,
|
QianfanModelFactory.PROVIDER, QianfanModelFactory.DEFAULT_BASE_URL,
|
||||||
ZhipuModelFactory.PROVIDER, ZhipuModelFactory.DEFAULT_BASE_URL,
|
ZhipuModelFactory.PROVIDER, ZhipuModelFactory.DEFAULT_BASE_URL,
|
||||||
LocalAiModelFactory.PROVIDER, LocalAiModelFactory.DEFAULT_BASE_URL,
|
LocalAiModelFactory.PROVIDER, LocalAiModelFactory.DEFAULT_BASE_URL,
|
||||||
DashscopeModelFactory.PROVIDER, DashscopeModelFactory.DEFAULT_BASE_URL));
|
DashscopeModelFactory.PROVIDER, DashscopeModelFactory.DEFAULT_BASE_URL,
|
||||||
|
DifyModelFactory.PROVIDER, DifyModelFactory.DEFAULT_BASE_URL));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Parameter.Dependency> getApiKeyDependency() {
|
private static List<Parameter.Dependency> getApiKeyDependency() {
|
||||||
return getDependency(CHAT_MODEL_PROVIDER.getName(),
|
return getDependency(CHAT_MODEL_PROVIDER.getName(),
|
||||||
Lists.newArrayList(OpenAiModelFactory.PROVIDER, QianfanModelFactory.PROVIDER,
|
Lists.newArrayList(OpenAiModelFactory.PROVIDER, QianfanModelFactory.PROVIDER,
|
||||||
ZhipuModelFactory.PROVIDER, LocalAiModelFactory.PROVIDER,
|
ZhipuModelFactory.PROVIDER, LocalAiModelFactory.PROVIDER,
|
||||||
AzureModelFactory.PROVIDER, DashscopeModelFactory.PROVIDER),
|
AzureModelFactory.PROVIDER, DashscopeModelFactory.PROVIDER,
|
||||||
|
DifyModelFactory.PROVIDER),
|
||||||
ImmutableMap.of(OpenAiModelFactory.PROVIDER,
|
ImmutableMap.of(OpenAiModelFactory.PROVIDER,
|
||||||
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), QianfanModelFactory.PROVIDER,
|
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), QianfanModelFactory.PROVIDER,
|
||||||
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), ZhipuModelFactory.PROVIDER,
|
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), ZhipuModelFactory.PROVIDER,
|
||||||
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), LocalAiModelFactory.PROVIDER,
|
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), LocalAiModelFactory.PROVIDER,
|
||||||
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), AzureModelFactory.PROVIDER,
|
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), AzureModelFactory.PROVIDER,
|
||||||
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), DashscopeModelFactory.PROVIDER,
|
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), DashscopeModelFactory.PROVIDER,
|
||||||
|
ModelProvider.DEMO_CHAT_MODEL.getApiKey(), DifyModelFactory.PROVIDER,
|
||||||
ModelProvider.DEMO_CHAT_MODEL.getApiKey()));
|
ModelProvider.DEMO_CHAT_MODEL.getApiKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +98,8 @@ public class ChatModelParameters {
|
|||||||
ZhipuModelFactory.PROVIDER, ZhipuModelFactory.DEFAULT_MODEL_NAME,
|
ZhipuModelFactory.PROVIDER, ZhipuModelFactory.DEFAULT_MODEL_NAME,
|
||||||
LocalAiModelFactory.PROVIDER, LocalAiModelFactory.DEFAULT_MODEL_NAME,
|
LocalAiModelFactory.PROVIDER, LocalAiModelFactory.DEFAULT_MODEL_NAME,
|
||||||
AzureModelFactory.PROVIDER, AzureModelFactory.DEFAULT_MODEL_NAME,
|
AzureModelFactory.PROVIDER, AzureModelFactory.DEFAULT_MODEL_NAME,
|
||||||
DashscopeModelFactory.PROVIDER, DashscopeModelFactory.DEFAULT_MODEL_NAME));
|
DashscopeModelFactory.PROVIDER, DashscopeModelFactory.DEFAULT_MODEL_NAME,
|
||||||
|
DifyModelFactory.PROVIDER, DifyModelFactory.DEFAULT_MODEL_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Parameter.Dependency> getEndpointDependency() {
|
private static List<Parameter.Dependency> getEndpointDependency() {
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package com.tencent.supersonic.common.util;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public class DifyClient {
|
||||||
|
private static final String DEFAULT_USER = "zhaodongsheng";
|
||||||
|
private static final String CONTENT_TYPE_JSON = "application/json";
|
||||||
|
|
||||||
|
private String difyURL;
|
||||||
|
private String difyKey;
|
||||||
|
|
||||||
|
public DifyClient(String difyURL, String difyKey) {
|
||||||
|
this.difyURL = difyURL;
|
||||||
|
this.difyKey = difyKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DifyResult generate(String prompt) {
|
||||||
|
Map<String, String> headers = defaultHeaders();
|
||||||
|
DifyRequest request = new DifyRequest();
|
||||||
|
request.setQuery(prompt);
|
||||||
|
request.setUser(DEFAULT_USER);
|
||||||
|
return sendRequest(request, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DifyResult generate(String prompt, String user) {
|
||||||
|
Map<String, String> headers = defaultHeaders();
|
||||||
|
DifyRequest request = new DifyRequest();
|
||||||
|
request.setQuery(prompt);
|
||||||
|
request.setUser(user);
|
||||||
|
return sendRequest(request, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DifyResult generate(Map<String, String> inputs, String queryText, String user,
|
||||||
|
String conversationId) {
|
||||||
|
Map<String, String> headers = defaultHeaders();
|
||||||
|
DifyRequest request = new DifyRequest();
|
||||||
|
request.setInputs(inputs);
|
||||||
|
request.setQuery(queryText);
|
||||||
|
request.setUser(user);
|
||||||
|
if (conversationId != null && !conversationId.isEmpty()) {
|
||||||
|
request.setConversationId(conversationId);
|
||||||
|
}
|
||||||
|
return sendRequest(request, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DifyResult sendRequest(DifyRequest request, Map<String, String> headers) {
|
||||||
|
try {
|
||||||
|
log.debug("请求dify- header--->" + JsonUtil.toString(headers));
|
||||||
|
log.debug("请求dify- conversionId--->" + JsonUtil.toString(request));
|
||||||
|
return HttpUtils.post(difyURL, JsonUtil.toString(request), headers, DifyResult.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("请求dify失败---->" + e.getMessage());
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String parseSQLResult(String sql) {
|
||||||
|
Pattern pattern = Pattern.compile("```(sql)?(.*)```", Pattern.DOTALL);
|
||||||
|
Matcher matcher = pattern.matcher(sql);
|
||||||
|
if (!matcher.find()) {
|
||||||
|
return sql.trim();
|
||||||
|
} else {
|
||||||
|
return matcher.group(2).trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> defaultHeaders() {
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
if (difyKey.contains("Bearer")) {
|
||||||
|
headers.put("Authorization", difyKey);
|
||||||
|
} else {
|
||||||
|
headers.put("Authorization", "Bearer " + difyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
headers.put("Content-Type", CONTENT_TYPE_JSON);
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.tencent.supersonic.common.util;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DifyRequest {
|
||||||
|
private String query;
|
||||||
|
private Map<String, String> inputs = new HashMap<>();
|
||||||
|
private String responseMode = "blocking";
|
||||||
|
private String user;
|
||||||
|
@JsonProperty("conversation_id")
|
||||||
|
private String conversationId;
|
||||||
|
@JsonProperty("auto_generate_name")
|
||||||
|
private Boolean autoGenerateName = false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.tencent.supersonic.common.util;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DifyResult {
|
||||||
|
private String event = "";
|
||||||
|
private String taskId = "";
|
||||||
|
private String conversationId = "";
|
||||||
|
private String id = "";
|
||||||
|
private String messageId = "";
|
||||||
|
private String answer = "";
|
||||||
|
}
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
package com.tencent.supersonic.common.util;
|
||||||
|
|
||||||
|
import okhttp3.Dispatcher;
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class HttpUtils {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);
|
||||||
|
|
||||||
|
// 重试参考:okhttp3.RealCall.getResponseWithInterceptorChain
|
||||||
|
private static final OkHttpClient client = new OkHttpClient.Builder()
|
||||||
|
.readTimeout(3, TimeUnit.MINUTES).retryOnConnectionFailure(true).build();
|
||||||
|
|
||||||
|
static {
|
||||||
|
Dispatcher dispatcher = client.dispatcher();
|
||||||
|
dispatcher.setMaxRequestsPerHost(300);
|
||||||
|
dispatcher.setMaxRequests(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Response execute(String url) throws IOException {
|
||||||
|
Request request = new Request.Builder().url(url).build();
|
||||||
|
return client.newCall(request).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String get(String url) throws IOException {
|
||||||
|
return doRequest(builder(url).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String get(String url, Map<String, String> headers) throws IOException {
|
||||||
|
return doRequest(headerBuilder(url, headers).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String get(String url, Map<String, String> headers, Map<String, Object> params)
|
||||||
|
throws IOException {
|
||||||
|
return doRequest(headerBuilder(url + buildUrlParams(params), headers).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T get(String url, Class<T> classOfT) throws IOException {
|
||||||
|
return doRequest(builder(url).build(), classOfT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T get(String url, Map<String, String> headers, Class<T> classOfT)
|
||||||
|
throws IOException {
|
||||||
|
return doRequest(headerBuilder(url, headers).build(), classOfT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T get(String url, Map<String, String> headers, Map<String, Object> params,
|
||||||
|
Class<T> classOfT) throws IOException {
|
||||||
|
return doRequest(headerBuilder(url + buildUrlParams(params), headers).build(), classOfT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static <T> T get(String url, TypeReference<T> type) throws IOException {
|
||||||
|
// return doRequest(builder(url).build(), type);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public static <T> T get(String url, Map<String, String> headers, TypeReference<T> type)
|
||||||
|
// throws IOException {
|
||||||
|
// return doRequest(headerBuilder(url, headers).build(), type);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public static <T> T get(String url, Map<String, String> headers, Map<String, Object> params,
|
||||||
|
// TypeReference<T> type) throws IOException {
|
||||||
|
// return doRequest(headerBuilder(url + buildUrlParams(params), headers).build(), type);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public static String post(String url, Object body) throws IOException {
|
||||||
|
return doRequest(postRequest(url, body));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String post(String url, Object body, Map<String, String> headers)
|
||||||
|
throws IOException {
|
||||||
|
return doRequest(postRequest(url, body, headers));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T post(String url, Object body, Class<T> classOfT) throws IOException {
|
||||||
|
return doRequest(postRequest(url, body), classOfT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static <T> T post(String url, Object body, TypeReference<T> type) throws IOException {
|
||||||
|
// return doRequest(postRequest(url, body), type);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public static <T> T post(String url, Object body, Map<String, String> headers,
|
||||||
|
Class<T> classOfT) throws IOException {
|
||||||
|
return doRequest(postRequest(url, body, headers), classOfT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static <T> T post(String url, Object body, Map<String, String> headers,
|
||||||
|
// TypeReference<T> type) throws IOException {
|
||||||
|
// return doRequest(postRequest(url, body, headers), type);
|
||||||
|
// }
|
||||||
|
|
||||||
|
private static Request postRequest(String url, Object body) {
|
||||||
|
return builder(url).post(buildRequestBody(body, null)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Request postRequest(String url, Object body, Map<String, String> headers) {
|
||||||
|
return headerBuilder(url, headers).post(buildRequestBody(body, headers)).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Request.Builder builder(String url) {
|
||||||
|
return new Request.Builder().url(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Request.Builder headerBuilder(String url, Map<String, String> headers) {
|
||||||
|
Request.Builder builder = new Request.Builder().url(url);
|
||||||
|
headers.forEach(builder::addHeader);
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> T doRequest(Request request, Class<T> classOfT) throws IOException {
|
||||||
|
return JsonUtil.toObject(doRequest(request), classOfT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// private static <T> T doRequest(Request request, TypeReference<T> type) throws IOException {
|
||||||
|
// return JsonUtil.toObject(doRequest(request), type);
|
||||||
|
// }
|
||||||
|
|
||||||
|
private static String doRequest(Request request) throws IOException {
|
||||||
|
long beginTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
return response.body().string();
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Http请求失败[" + response.code() + "]:" + response.body().string() + "...");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
logger.info("begin to request : {}, execute costs(ms) : {}", request.url(),
|
||||||
|
System.currentTimeMillis() - beginTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RequestBody buildRequestBody(Object body, Map<String, String> headers) {
|
||||||
|
if (headers != null && headers.containsKey("Content-Type")) {
|
||||||
|
String contentType = headers.get("Content-Type");
|
||||||
|
return RequestBody.create(MediaType.parse(contentType), body.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (body instanceof String && ((String) body).contains("=")) {
|
||||||
|
return RequestBody.create(MediaType.parse("application/x-www-form-urlencoded"),
|
||||||
|
(String) body);
|
||||||
|
}
|
||||||
|
|
||||||
|
return RequestBody.create(MediaType.parse("application/json"), JsonUtil.toString(body));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String buildUrlParams(Map<String, Object> params) {
|
||||||
|
if (params.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "?" + params.entrySet().stream().map(it -> it.getKey() + "=" + it.getValue())
|
||||||
|
.collect(Collectors.joining("&"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package dev.langchain4j.model.dify;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.common.util.AESEncryptionUtil;
|
||||||
|
import com.tencent.supersonic.common.util.DifyClient;
|
||||||
|
import com.tencent.supersonic.common.util.DifyResult;
|
||||||
|
import dev.langchain4j.agent.tool.ToolSpecification;
|
||||||
|
import dev.langchain4j.data.message.AiMessage;
|
||||||
|
import dev.langchain4j.data.message.ChatMessage;
|
||||||
|
import dev.langchain4j.model.chat.ChatLanguageModel;
|
||||||
|
import dev.langchain4j.model.output.Response;
|
||||||
|
import lombok.Builder;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static dev.langchain4j.internal.Utils.getOrDefault;
|
||||||
|
import static dev.langchain4j.internal.Utils.isNullOrEmpty;
|
||||||
|
import static dev.langchain4j.internal.ValidationUtils.ensureNotEmpty;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
|
||||||
|
public class DifyAiChatModel implements ChatLanguageModel {
|
||||||
|
|
||||||
|
private static final String CONTENT_TYPE_JSON = "application/json";
|
||||||
|
|
||||||
|
private final String baseUrl;
|
||||||
|
private final String apiKey;
|
||||||
|
|
||||||
|
private final DifyClient difyClient;
|
||||||
|
private final Integer maxRetries;
|
||||||
|
private final Integer maxToken;
|
||||||
|
|
||||||
|
private final String appName;
|
||||||
|
private final Double temperature;
|
||||||
|
private final Long timeOut;
|
||||||
|
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
public DifyAiChatModel(String baseUrl, String apiKey, Integer maxRetries, Integer maxToken,
|
||||||
|
String modelName, Double temperature, Long timeOut) {
|
||||||
|
this.baseUrl = baseUrl;
|
||||||
|
this.maxRetries = getOrDefault(maxRetries, 3);
|
||||||
|
this.maxToken = getOrDefault(maxToken, 512);
|
||||||
|
try {
|
||||||
|
this.apiKey = AESEncryptionUtil.aesDecryptECB(apiKey);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
this.appName = modelName;
|
||||||
|
this.temperature = temperature;
|
||||||
|
this.timeOut = timeOut;
|
||||||
|
this.difyClient = new DifyClient(this.baseUrl, this.apiKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String generate(String message) {
|
||||||
|
DifyResult difyResult = this.difyClient.generate(message, this.getUserName());
|
||||||
|
return difyResult.getAnswer().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<AiMessage> generate(List<ChatMessage> messages) {
|
||||||
|
return generate(messages, (ToolSpecification) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<AiMessage> generate(List<ChatMessage> messages,
|
||||||
|
List<ToolSpecification> toolSpecifications) {
|
||||||
|
ensureNotEmpty(messages, "messages");
|
||||||
|
DifyResult difyResult =
|
||||||
|
this.difyClient.generate(messages.get(0).text(), this.getUserName());
|
||||||
|
System.out.println(difyResult.toString());
|
||||||
|
|
||||||
|
if (!isNullOrEmpty(toolSpecifications)) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.from(AiMessage.from(difyResult.getAnswer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response<AiMessage> generate(List<ChatMessage> messages,
|
||||||
|
ToolSpecification toolSpecification) {
|
||||||
|
return generate(messages,
|
||||||
|
toolSpecification != null ? singletonList(toolSpecification) : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserName(String userName) {
|
||||||
|
this.userName = userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserName() {
|
||||||
|
return null == userName ? "zhaodongsheng" : userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package dev.langchain4j.provider;
|
||||||
|
|
||||||
|
import com.tencent.supersonic.common.pojo.ChatModelConfig;
|
||||||
|
import com.tencent.supersonic.common.pojo.EmbeddingModelConfig;
|
||||||
|
import com.tencent.supersonic.common.util.AESEncryptionUtil;
|
||||||
|
import dev.langchain4j.model.chat.ChatLanguageModel;
|
||||||
|
import dev.langchain4j.model.dify.DifyAiChatModel;
|
||||||
|
import dev.langchain4j.model.embedding.EmbeddingModel;
|
||||||
|
import dev.langchain4j.model.zhipu.ZhipuAiEmbeddingModel;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class DifyModelFactory implements ModelFactory, InitializingBean {
|
||||||
|
public static final String PROVIDER = "DIFY";
|
||||||
|
|
||||||
|
public static final String DEFAULT_BASE_URL = "https://dify.com/v1/chat-messages";
|
||||||
|
public static final String DEFAULT_MODEL_NAME = "demo-预留-可不填写";
|
||||||
|
public static final String DEFAULT_EMBEDDING_MODEL_NAME = "all-minilm";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ChatLanguageModel createChatModel(ChatModelConfig modelConfig) {
|
||||||
|
return DifyAiChatModel.builder().baseUrl(modelConfig.getBaseUrl())
|
||||||
|
.apiKey(AESEncryptionUtil.aesDecryptECB(modelConfig.getApiKey()))
|
||||||
|
.modelName(modelConfig.getModelName()).timeOut(modelConfig.getTimeOut()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EmbeddingModel createEmbeddingModel(EmbeddingModelConfig embeddingModelConfig) {
|
||||||
|
return ZhipuAiEmbeddingModel.builder().baseUrl(embeddingModelConfig.getBaseUrl())
|
||||||
|
.apiKey(embeddingModelConfig.getApiKey()).model(embeddingModelConfig.getModelName())
|
||||||
|
.maxRetries(embeddingModelConfig.getMaxRetries())
|
||||||
|
.logRequests(embeddingModelConfig.getLogRequests())
|
||||||
|
.logResponses(embeddingModelConfig.getLogResponses()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() {
|
||||||
|
ModelProvider.add(PROVIDER, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -682,3 +682,19 @@ CREATE TABLE IF NOT EXISTS `s2_term` (
|
|||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
);
|
);
|
||||||
COMMENT ON TABLE s2_term IS 'term info';
|
COMMENT ON TABLE s2_term IS 'term info';
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS `s2_user_token` (
|
||||||
|
`id` INT NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` VARCHAR(255) NOT NULL,
|
||||||
|
`user_name` VARCHAR(255) NOT NULL,
|
||||||
|
`expire_time` INT NOT NULL,
|
||||||
|
`token` text NOT NULL,
|
||||||
|
`salt` VARCHAR(255) default NULL,
|
||||||
|
`create_time` DATETIME NOT NULL,
|
||||||
|
`create_by` VARCHAR(255) NOT NULL,
|
||||||
|
`update_time` DATETIME default NULL,
|
||||||
|
`update_by` VARCHAR(255) NOT NULL,
|
||||||
|
`expire_date_time` DATETIME NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
);
|
||||||
|
COMMENT ON TABLE s2_user_token IS 'user token info';
|
||||||
|
|||||||
@@ -603,3 +603,19 @@ CREATE TABLE IF NOT EXISTS `s2_term` (
|
|||||||
`updated_by` varchar(100) DEFAULT NULL ,
|
`updated_by` varchar(100) DEFAULT NULL ,
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT ='术语表';
|
) ENGINE = InnoDB DEFAULT CHARSET = utf8 COMMENT ='术语表';
|
||||||
|
|
||||||
|
CREATE TABLE `s2_user_token` (
|
||||||
|
`id` bigint NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` VARCHAR(255) NOT NULL,
|
||||||
|
`user_name` VARCHAR(255) NOT NULL,
|
||||||
|
`expire_time` BIGINT(20) NOT NULL,
|
||||||
|
`token` text NOT NULL,
|
||||||
|
`salt` VARCHAR(255) default NULL,
|
||||||
|
`create_time` DATETIME NOT NULL,
|
||||||
|
`create_by` VARCHAR(255) NOT NULL,
|
||||||
|
`update_time` DATETIME default NULL,
|
||||||
|
`update_by` VARCHAR(255) NOT NULL,
|
||||||
|
`expire_date_time` DATETIME NOT NULL,
|
||||||
|
unique key name_username (`name`, `user_name`),
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin comment='用户令牌信息表';
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
dev: {
|
dev: {
|
||||||
'/api/': {
|
'/api/': {
|
||||||
target: 'http://10.91.217.39:9080',
|
target: 'http://127.0.0.1:9080',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
|
||||||
|
import { Button, Form, Input, message, Modal, Table } from 'antd';
|
||||||
|
import { useBoolean, useDynamicList, useRequest } from 'ahooks';
|
||||||
|
import {
|
||||||
|
changePassword,
|
||||||
|
generateAccessToken,
|
||||||
|
getUserAccessTokens,
|
||||||
|
removeAccessToken,
|
||||||
|
} from '@/services/user';
|
||||||
|
import { encryptPassword, encryptKey } from '@/utils/utils';
|
||||||
|
import { API } from '@/services/API';
|
||||||
|
import { EditableProTable, ProColumns } from '@ant-design/pro-components';
|
||||||
|
import { CopyOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
|
type DataSourceType = {
|
||||||
|
id: React.Key;
|
||||||
|
name?: string;
|
||||||
|
token?: string;
|
||||||
|
expireDate?: string;
|
||||||
|
createDate?: string;
|
||||||
|
toBeSaved?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface IRef {
|
||||||
|
open: () => void;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChangePasswordModal = forwardRef<IRef>((_, ref) => {
|
||||||
|
const [open, { setTrue: openModal, setFalse: closeModal }] = useBoolean(false);
|
||||||
|
const [dataSource, setDataSource] = useState<readonly DataSourceType[]>([]);
|
||||||
|
|
||||||
|
const getAccessTokens = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getUserAccessTokens();
|
||||||
|
if (res && res.code === 200) {
|
||||||
|
return res.data;
|
||||||
|
} else {
|
||||||
|
message.error(res.msg);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
message.error('获取数据失败,原因:' + error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
open: () => {
|
||||||
|
openModal();
|
||||||
|
},
|
||||||
|
close: () => {
|
||||||
|
closeModal();
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const columns: ProColumns<DataSourceType>[] = [
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
width: '15%',
|
||||||
|
formItemProps: {
|
||||||
|
rules: [{ required: true, message: '此项为必填项' }],
|
||||||
|
},
|
||||||
|
editable: (text, record, index) => !!record.toBeSaved,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '访问令牌',
|
||||||
|
dataIndex: 'token',
|
||||||
|
width: '25%',
|
||||||
|
formItemProps: (form, { rowIndex }) => {
|
||||||
|
return {
|
||||||
|
rules: [{ required: true, message: '此项为必填项' }],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
render: (text, record, index) => {
|
||||||
|
// 脱敏处理, 点击图标可完整token
|
||||||
|
return record.toBeSaved ? (
|
||||||
|
text
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{record.token ? record.token.slice(0, 5) + '********' + record.token.slice(-5) : ''}
|
||||||
|
<Button
|
||||||
|
type="link"
|
||||||
|
size="small"
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(record.token || '');
|
||||||
|
message.info('已复制到剪贴板');
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CopyOutlined />
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
editable: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '过期时间',
|
||||||
|
dataIndex: 'expireDate',
|
||||||
|
valueType: 'date',
|
||||||
|
width: '20%',
|
||||||
|
formItemProps: {
|
||||||
|
rules: [{ required: true, message: '此项为必填项' }],
|
||||||
|
},
|
||||||
|
editable: (text, record, index) => !!record.toBeSaved,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '创建时间',
|
||||||
|
dataIndex: 'createDate',
|
||||||
|
valueType: 'date',
|
||||||
|
editable: false,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
width: '15%',
|
||||||
|
render: (text, record, _, action) => [
|
||||||
|
<a
|
||||||
|
key="delete"
|
||||||
|
onClick={() => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: '删除访问令牌',
|
||||||
|
content: '确定删除此访问令牌吗?',
|
||||||
|
onOk: async () => {
|
||||||
|
const res = await removeAccessToken(record.id as number);
|
||||||
|
|
||||||
|
if (res && res.code !== 200) {
|
||||||
|
message.error('删除失败,原因:' + res.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setDataSource(dataSource.filter((item) => item.id !== record.id));
|
||||||
|
message.success('删除成功');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</a>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title="访问令牌"
|
||||||
|
open={open}
|
||||||
|
onClose={closeModal}
|
||||||
|
onCancel={closeModal}
|
||||||
|
width={1200}
|
||||||
|
footer={false}
|
||||||
|
destroyOnClose
|
||||||
|
>
|
||||||
|
<EditableProTable<DataSourceType>
|
||||||
|
rowKey="id"
|
||||||
|
recordCreatorProps={{
|
||||||
|
position: 'bottom',
|
||||||
|
creatorButtonText: '新增访问令牌',
|
||||||
|
record: () => ({ id: (Math.random() * 1000000).toFixed(0), toBeSaved: true }),
|
||||||
|
}}
|
||||||
|
loading={false}
|
||||||
|
columns={columns}
|
||||||
|
request={async () => {
|
||||||
|
const data = await getAccessTokens();
|
||||||
|
return {
|
||||||
|
data,
|
||||||
|
total: data.length,
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
value={dataSource}
|
||||||
|
onChange={setDataSource}
|
||||||
|
editable={{
|
||||||
|
type: 'single',
|
||||||
|
onSave: async (rowKey, data, row) => {
|
||||||
|
console.log(rowKey, data, row);
|
||||||
|
await generateAccessToken({
|
||||||
|
name: data.name!,
|
||||||
|
expireTime: new Date(data.expireDate!).getTime() - new Date().getTime(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const newTokens = await getAccessTokens();
|
||||||
|
setTimeout(() => {
|
||||||
|
setDataSource(newTokens);
|
||||||
|
}, 100);
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ChangePasswordModal;
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
import React from 'react';
|
import React, { useRef } from 'react';
|
||||||
import { LogoutOutlined } from '@ant-design/icons';
|
import { LogoutOutlined, KeyOutlined, UnlockOutlined } from '@ant-design/icons';
|
||||||
import { useModel } from 'umi';
|
import { useModel } from 'umi';
|
||||||
import HeaderDropdown from '../HeaderDropdown';
|
import HeaderDropdown from '../HeaderDropdown';
|
||||||
import styles from './index.less';
|
import styles from './index.less';
|
||||||
import TMEAvatar from '../TMEAvatar';
|
import TMEAvatar from '../TMEAvatar';
|
||||||
import { AUTH_TOKEN_KEY } from '@/common/constants';
|
import { AUTH_TOKEN_KEY } from '@/common/constants';
|
||||||
|
import ChangePasswordModal, { IRef as IRefChangePasswordModal } from './ChangePasswordModal';
|
||||||
|
import AccessTokensModal, { IRef as IAccessTokensModalRef } from './AccessTokensModal';
|
||||||
import { history } from 'umi';
|
import { history } from 'umi';
|
||||||
|
|
||||||
export type GlobalHeaderRightProps = {
|
export type GlobalHeaderRightProps = {
|
||||||
@@ -27,7 +29,38 @@ const { APP_TARGET } = process.env;
|
|||||||
const AvatarDropdown: React.FC<GlobalHeaderRightProps> = () => {
|
const AvatarDropdown: React.FC<GlobalHeaderRightProps> = () => {
|
||||||
const { initialState = {}, setInitialState } = useModel('@@initialState');
|
const { initialState = {}, setInitialState } = useModel('@@initialState');
|
||||||
const { currentUser = {} } = initialState as any;
|
const { currentUser = {} } = initialState as any;
|
||||||
|
const changePasswordModalRef = useRef<IRefChangePasswordModal>(null);
|
||||||
|
const accessTokensModalRef = useRef<IAccessTokensModalRef>(null);
|
||||||
|
|
||||||
|
const handleAccessToken = () => {
|
||||||
|
accessTokensModalRef.current?.open();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangePassword = () => {
|
||||||
|
changePasswordModalRef.current?.open();
|
||||||
|
};
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<>
|
||||||
|
<KeyOutlined />
|
||||||
|
访问令牌
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
key: 'accessToken',
|
||||||
|
onClick: handleAccessToken,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: (
|
||||||
|
<>
|
||||||
|
<UnlockOutlined />
|
||||||
|
修改密码
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
key: 'changePassword',
|
||||||
|
onClick: handleChangePassword,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: (
|
label: (
|
||||||
<>
|
<>
|
||||||
@@ -48,12 +81,21 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<HeaderDropdown menu={{ items }} disabled={APP_TARGET === 'inner'}>
|
<>
|
||||||
<span className={`${styles.action} ${styles.account}`}>
|
<HeaderDropdown
|
||||||
<TMEAvatar className={styles.avatar} size="small" staffName={currentUser.staffName} />
|
menu={{
|
||||||
<span className={styles.userName}>{currentUser.staffName}</span>
|
items,
|
||||||
</span>
|
}}
|
||||||
</HeaderDropdown>
|
disabled={APP_TARGET === 'inner'}
|
||||||
|
>
|
||||||
|
<span className={`${styles.action} ${styles.account}`}>
|
||||||
|
<TMEAvatar className={styles.avatar} size="small" staffName={currentUser.staffName} />
|
||||||
|
<span className={styles.userName}>{currentUser.staffName}</span>
|
||||||
|
</span>
|
||||||
|
</HeaderDropdown>
|
||||||
|
<ChangePasswordModal ref={changePasswordModalRef} />
|
||||||
|
<AccessTokensModal ref={accessTokensModalRef} />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
import React, { forwardRef, useImperativeHandle } from 'react';
|
||||||
|
import { Form, Input, message, Modal } from 'antd';
|
||||||
|
import { useBoolean } from 'ahooks';
|
||||||
|
import { changePassword } from '@/services/user';
|
||||||
|
import { pick } from 'lodash';
|
||||||
|
import { encryptPassword, encryptKey } from '@/utils/utils';
|
||||||
|
|
||||||
|
export interface IRef {
|
||||||
|
open: () => void;
|
||||||
|
close: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChangePasswordModal = forwardRef<IRef>((_, ref) => {
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const [open, { setTrue: openModal, setFalse: closeModal }] = useBoolean(false);
|
||||||
|
const [confirmLoading, { set: setConfirmLoading }] = useBoolean(false);
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
open: () => {
|
||||||
|
openModal();
|
||||||
|
form.resetFields();
|
||||||
|
},
|
||||||
|
close: () => {
|
||||||
|
closeModal();
|
||||||
|
form.resetFields();
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
try {
|
||||||
|
const values = await form.validateFields();
|
||||||
|
console.log(values);
|
||||||
|
setConfirmLoading(true);
|
||||||
|
// Call API to change password
|
||||||
|
const res = await changePassword({
|
||||||
|
oldPassword: encryptPassword(values.oldPassword, encryptKey),
|
||||||
|
newPassword: encryptPassword(values.newPassword, encryptKey),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res && res.code !== 200) {
|
||||||
|
return message.warning(res.msg);
|
||||||
|
}
|
||||||
|
closeModal();
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Failed:', error);
|
||||||
|
} finally {
|
||||||
|
setConfirmLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title="修改密码"
|
||||||
|
open={open}
|
||||||
|
onOk={handleOk}
|
||||||
|
onClose={closeModal}
|
||||||
|
onCancel={closeModal}
|
||||||
|
confirmLoading={confirmLoading}
|
||||||
|
>
|
||||||
|
<Form form={form}>
|
||||||
|
<Form.Item
|
||||||
|
name="oldPassword"
|
||||||
|
label="原密码"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入原密码!',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
hasFeedback
|
||||||
|
>
|
||||||
|
<Input.Password />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="newPassword"
|
||||||
|
label="新密码"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入新密码!',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
min: 6,
|
||||||
|
max: 10,
|
||||||
|
message: '密码须在6-10字符之间!',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
hasFeedback
|
||||||
|
>
|
||||||
|
<Input.Password />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="confirm"
|
||||||
|
label="确认密码"
|
||||||
|
dependencies={['newPassword']}
|
||||||
|
hasFeedback
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请确认密码!',
|
||||||
|
},
|
||||||
|
({ getFieldValue }) => ({
|
||||||
|
validator(_, value) {
|
||||||
|
if (!value || getFieldValue('newPassword') === value) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error('两次输入的密码不一致!'));
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input.Password />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default ChangePasswordModal;
|
||||||
@@ -23,6 +23,23 @@ declare namespace API {
|
|||||||
access?: 'user' | 'guest' | 'admin';
|
access?: 'user' | 'guest' | 'admin';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface UserItem {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
displayName: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserAccessToken {
|
||||||
|
createDate: string;
|
||||||
|
expireDate: string;
|
||||||
|
expireTime: number;
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
token: string;
|
||||||
|
userName: string;
|
||||||
|
}
|
||||||
|
|
||||||
export type LoginStateType = {
|
export type LoginStateType = {
|
||||||
status?: 'ok' | 'error';
|
status?: 'ok' | 'error';
|
||||||
type?: string;
|
type?: string;
|
||||||
|
|||||||
@@ -20,3 +20,31 @@ export function saveSystemConfig(data: any): Promise<any> {
|
|||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function changePassword(data: { newPassword: string; oldPassword: string }): Promise<any> {
|
||||||
|
return request(`${process.env.AUTH_API_BASE_URL}user/resetPassword`, {
|
||||||
|
method: 'post',
|
||||||
|
data: {
|
||||||
|
newPassword: data.newPassword,
|
||||||
|
password: data.oldPassword,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户accessTokens
|
||||||
|
export async function getUserAccessTokens(): Promise<Result<API.UserItem[]>> {
|
||||||
|
return request.get(`${process.env.AUTH_API_BASE_URL}user/getUserTokens`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generateAccessToken(data: { expireTime: number; name: string }): Promise<any> {
|
||||||
|
return request(`${process.env.AUTH_API_BASE_URL}user/generateToken`, {
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeAccessToken(id: number): Promise<any> {
|
||||||
|
return request(`${process.env.AUTH_API_BASE_URL}user/deleteUserToken?tokenId=${id}`, {
|
||||||
|
method: 'post',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -472,7 +472,7 @@ export const objToArray = (_obj: ObjToArrayParams, keyType: string = 'string') =
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const encryptKey = CryptoJS.enc.Hex.parse(
|
export const encryptKey = CryptoJS.enc.Hex.parse(
|
||||||
'9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08',
|
'9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user