[add]支持其他平台通过ApiKey调用系统相关接口
parent
00bb8d914a
commit
76208975bf
4
pom.xml
4
pom.xml
|
@ -99,6 +99,10 @@
|
|||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
|
@ -24,6 +25,7 @@ import java.util.Collections;
|
|||
@ServletComponentScan("com.genersoft.iot.vmp.conf")
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@EnableCaching
|
||||
public class VManageBootstrap extends SpringBootServletInitializer {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(VManageBootstrap.class);
|
||||
|
|
|
@ -51,8 +51,11 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||
if (StringUtils.isBlank(jwt)) {
|
||||
jwt = request.getParameter(JwtUtils.getHeader());
|
||||
if (StringUtils.isBlank(jwt)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
jwt = request.getHeader(JwtUtils.getApiKeyHeader());
|
||||
if (StringUtils.isBlank(jwt)) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package com.genersoft.iot.vmp.conf.security;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.security.dto.JwtUser;
|
||||
import com.genersoft.iot.vmp.service.IUserApiKeyService;
|
||||
import com.genersoft.iot.vmp.service.IUserService;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.UserApiKey;
|
||||
import org.jose4j.jwk.JsonWebKey;
|
||||
import org.jose4j.jwk.JsonWebKeySet;
|
||||
import org.jose4j.jwk.RsaJsonWebKey;
|
||||
import org.jose4j.jwk.RsaJwkGenerator;
|
||||
import org.jose4j.jws.AlgorithmIdentifiers;
|
||||
|
@ -20,8 +24,18 @@ import org.springframework.beans.factory.InitializingBean;
|
|||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class JwtUtils implements InitializingBean {
|
||||
|
@ -30,6 +44,8 @@ public class JwtUtils implements InitializingBean {
|
|||
|
||||
public static final String HEADER = "access-token";
|
||||
|
||||
public static final String API_KEY_HEADER = "api-key";
|
||||
|
||||
private static final String AUDIENCE = "Audience";
|
||||
|
||||
private static final String keyId = "3e79646c4dbc408383a9eed09f2b85ae";
|
||||
|
@ -37,17 +53,28 @@ public class JwtUtils implements InitializingBean {
|
|||
/**
|
||||
* token过期时间(分钟)
|
||||
*/
|
||||
public static final long expirationTime = 30 * 24 * 60;
|
||||
public static final long EXPIRATION_TIME = 30 * 24 * 60;
|
||||
|
||||
private static RsaJsonWebKey rsaJsonWebKey;
|
||||
|
||||
private static IUserService userService;
|
||||
|
||||
private static IUserApiKeyService userApiKeyService;
|
||||
|
||||
public static String getApiKeyHeader() {
|
||||
return API_KEY_HEADER;
|
||||
}
|
||||
|
||||
@Resource
|
||||
public void setUserService(IUserService userService) {
|
||||
JwtUtils.userService = userService;
|
||||
}
|
||||
|
||||
@Resource
|
||||
public void setUserApiKeyService(IUserApiKeyService userApiKeyService) {
|
||||
JwtUtils.userApiKeyService = userApiKeyService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
try {
|
||||
|
@ -62,14 +89,38 @@ public class JwtUtils implements InitializingBean {
|
|||
* @throws JoseException JoseException
|
||||
*/
|
||||
private RsaJsonWebKey generateRsaJsonWebKey() throws JoseException {
|
||||
// 生成一个RSA密钥对,该密钥对将用于JWT的签名和验证,包装在JWK中
|
||||
RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
|
||||
// 给JWK一个密钥ID
|
||||
rsaJsonWebKey.setKeyId(keyId);
|
||||
RsaJsonWebKey rsaJsonWebKey = null;
|
||||
try {
|
||||
URL url = getClass().getClassLoader().getResource("jwk.json");
|
||||
if (url != null) {
|
||||
URI uri = url.toURI();
|
||||
Path path = Paths.get(uri);
|
||||
if (Files.exists(path)) {
|
||||
byte[] allBytes = Files.readAllBytes(path);
|
||||
String jwkJson = new String(allBytes, StandardCharsets.UTF_8);
|
||||
final JsonWebKeySet jsonWebKeySet = new JsonWebKeySet(jwkJson);
|
||||
List<JsonWebKey> jsonWebKeys = jsonWebKeySet.getJsonWebKeys();
|
||||
if (!jsonWebKeys.isEmpty()) {
|
||||
JsonWebKey jsonWebKey = jsonWebKeys.get(0);
|
||||
if (jsonWebKey instanceof RsaJsonWebKey) {
|
||||
rsaJsonWebKey = (RsaJsonWebKey) jsonWebKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (URISyntaxException | IOException e) {
|
||||
// ignored
|
||||
}
|
||||
if (rsaJsonWebKey == null) {
|
||||
// 生成一个RSA密钥对,该密钥对将用于JWT的签名和验证,包装在JWK中
|
||||
rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
|
||||
// 给JWK一个密钥ID
|
||||
rsaJsonWebKey.setKeyId(keyId);
|
||||
}
|
||||
return rsaJsonWebKey;
|
||||
}
|
||||
|
||||
public static String createToken(String username) {
|
||||
public static String createToken(String username, Long expirationTime, Map<String, Object> extra) {
|
||||
try {
|
||||
/*
|
||||
* “iss” (issuer) 发行人
|
||||
|
@ -83,13 +134,17 @@ public class JwtUtils implements InitializingBean {
|
|||
claims.setGeneratedJwtId();
|
||||
claims.setIssuedAtToNow();
|
||||
// 令牌将过期的时间 分钟
|
||||
claims.setExpirationTimeMinutesInTheFuture(expirationTime);
|
||||
if (expirationTime != null) {
|
||||
claims.setExpirationTimeMinutesInTheFuture(expirationTime);
|
||||
}
|
||||
claims.setNotBeforeMinutesInThePast(0);
|
||||
claims.setSubject("login");
|
||||
claims.setAudience(AUDIENCE);
|
||||
//添加自定义参数,必须是字符串类型
|
||||
claims.setClaim("userName", username);
|
||||
|
||||
if (extra != null) {
|
||||
extra.forEach(claims::setClaim);
|
||||
}
|
||||
//jws
|
||||
JsonWebSignature jws = new JsonWebSignature();
|
||||
//签名算法RS256
|
||||
|
@ -104,10 +159,17 @@ public class JwtUtils implements InitializingBean {
|
|||
} catch (JoseException e) {
|
||||
logger.error("[Token生成失败]: {}", e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String createToken(String username, Long expirationTime) {
|
||||
return createToken(username, expirationTime, null);
|
||||
}
|
||||
|
||||
public static String createToken(String username) {
|
||||
return createToken(username, EXPIRATION_TIME);
|
||||
}
|
||||
|
||||
public static String getHeader() {
|
||||
return HEADER;
|
||||
}
|
||||
|
@ -118,8 +180,8 @@ public class JwtUtils implements InitializingBean {
|
|||
|
||||
try {
|
||||
JwtConsumer consumer = new JwtConsumerBuilder()
|
||||
.setRequireExpirationTime()
|
||||
.setMaxFutureValidityInMinutes(5256000)
|
||||
//.setRequireExpirationTime()
|
||||
//.setMaxFutureValidityInMinutes(5256000)
|
||||
.setAllowedClockSkewInSeconds(30)
|
||||
.setRequireSubject()
|
||||
//.setExpectedIssuer("")
|
||||
|
@ -129,15 +191,27 @@ public class JwtUtils implements InitializingBean {
|
|||
|
||||
JwtClaims claims = consumer.processToClaims(token);
|
||||
NumericDate expirationTime = claims.getExpirationTime();
|
||||
// 判断是否即将过期, 默认剩余时间小于5分钟未即将过期
|
||||
// 剩余时间 (秒)
|
||||
long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue();
|
||||
if (timeRemaining < 5 * 60) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
|
||||
if (expirationTime != null) {
|
||||
// 判断是否即将过期, 默认剩余时间小于5分钟未即将过期
|
||||
// 剩余时间 (秒)
|
||||
long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue();
|
||||
if (timeRemaining < 5 * 60) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON);
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
} else {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.NORMAL);
|
||||
}
|
||||
|
||||
Long apiKeyId = claims.getClaimValue("apiKeyId", Long.class);
|
||||
if (apiKeyId != null) {
|
||||
UserApiKey userApiKey = userApiKeyService.getUserApiKeyById(apiKeyId.intValue());
|
||||
if (userApiKey == null || !userApiKey.isEnable()) {
|
||||
jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED);
|
||||
}
|
||||
}
|
||||
|
||||
String username = (String) claims.getClaimValue("userName");
|
||||
User user = userService.getUserByUsername(username);
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package com.genersoft.iot.vmp.service;
|
||||
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.UserApiKey;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
public interface IUserApiKeyService {
|
||||
int addApiKey(UserApiKey userApiKey);
|
||||
|
||||
boolean isApiKeyExists(String apiKey);
|
||||
|
||||
PageInfo<UserApiKey> getUserApiKeys(int page, int count);
|
||||
|
||||
int enable(Integer id);
|
||||
|
||||
int disable(Integer id);
|
||||
|
||||
int remark(Integer id, String remark);
|
||||
|
||||
int delete(Integer id);
|
||||
|
||||
UserApiKey getUserApiKeyById(Integer id);
|
||||
|
||||
int reset(Integer id, String apiKey);
|
||||
|
||||
}
|
|
@ -11,6 +11,8 @@ public interface IUserService {
|
|||
|
||||
boolean changePassword(int id, String password);
|
||||
|
||||
User getUserById(int id);
|
||||
|
||||
User getUserByUsername(String username);
|
||||
|
||||
int addUser(User user);
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
package com.genersoft.iot.vmp.service.impl;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.genersoft.iot.vmp.service.IUserApiKeyService;
|
||||
import com.genersoft.iot.vmp.storager.dao.UserApiKeyMapper;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.UserApiKey;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.CacheEvict;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@DS("master")
|
||||
public class UserApiKeyServiceImpl implements IUserApiKeyService {
|
||||
|
||||
@Autowired
|
||||
UserApiKeyMapper userApiKeyMapper;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<Object, Object> redisTemplate;
|
||||
|
||||
@Override
|
||||
public int addApiKey(UserApiKey userApiKey) {
|
||||
return userApiKeyMapper.add(userApiKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApiKeyExists(String apiKey) {
|
||||
return userApiKeyMapper.isApiKeyExists(apiKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageInfo<UserApiKey> getUserApiKeys(int page, int count) {
|
||||
PageHelper.startPage(page, count);
|
||||
List<UserApiKey> userApiKeys = userApiKeyMapper.getUserApiKeys();
|
||||
return new PageInfo<>(userApiKeys);
|
||||
}
|
||||
|
||||
@Cacheable(cacheNames = "userApiKey", key = "#id", sync = true)
|
||||
@Override
|
||||
public UserApiKey getUserApiKeyById(Integer id) {
|
||||
return userApiKeyMapper.selectById(id);
|
||||
}
|
||||
|
||||
@CacheEvict(cacheNames = "userApiKey", key = "#id")
|
||||
@Override
|
||||
public int enable(Integer id) {
|
||||
return userApiKeyMapper.enable(id);
|
||||
}
|
||||
|
||||
@CacheEvict(cacheNames = "userApiKey", key = "#id")
|
||||
@Override
|
||||
public int disable(Integer id) {
|
||||
return userApiKeyMapper.disable(id);
|
||||
}
|
||||
|
||||
@CacheEvict(cacheNames = "userApiKey", key = "#id")
|
||||
@Override
|
||||
public int remark(Integer id, String remark) {
|
||||
return userApiKeyMapper.remark(id, remark);
|
||||
}
|
||||
|
||||
@CacheEvict(cacheNames = "userApiKey", key = "#id")
|
||||
@Override
|
||||
public int delete(Integer id) {
|
||||
return userApiKeyMapper.delete(id);
|
||||
}
|
||||
|
||||
@CacheEvict(cacheNames = "userApiKey", key = "#id")
|
||||
@Override
|
||||
public int reset(Integer id, String apiKey) {
|
||||
return userApiKeyMapper.apiKey(id, apiKey);
|
||||
}
|
||||
|
||||
}
|
|
@ -31,6 +31,11 @@ public class UserServiceImpl implements IUserService {
|
|||
return userMapper.update(user) > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserById(int id) {
|
||||
return userMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserByUsername(String username) {
|
||||
return userMapper.getUserByUsername(username);
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
package com.genersoft.iot.vmp.storager.dao;
|
||||
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.UserApiKey;
|
||||
import org.apache.ibatis.annotations.*;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface UserApiKeyMapper {
|
||||
|
||||
@SelectKey(statement = "SELECT LAST_INSERT_ID() AS id", keyProperty = "id", before = false, resultType = Integer.class)
|
||||
@Insert("INSERT INTO wvp_user_api_key (user_id, app, api_key, expired_at, remark, enable, create_time, update_time) VALUES" +
|
||||
"(#{userId}, #{app}, #{apiKey}, #{expiredAt}, #{remark}, #{enable}, #{createTime}, #{updateTime})")
|
||||
int add(UserApiKey userApiKey);
|
||||
|
||||
@Update(value = {"<script>" +
|
||||
"UPDATE wvp_user_api_key " +
|
||||
"SET update_time = #{updateTime} " +
|
||||
"<if test=\"app != null\">, app = #{app}</if>" +
|
||||
"<if test=\"apiKey != null\">, api_key = #{apiKey}</if>" +
|
||||
"<if test=\"expiredAt != null\">, expired_at = #{expiredAt}</if>" +
|
||||
"<if test=\"remark != null\">, username = #{remark}</if>" +
|
||||
"<if test=\"enable != null\">, enable = #{enable}</if>" +
|
||||
"WHERE id = #{id}" +
|
||||
" </script>"})
|
||||
int update(UserApiKey userApiKey);
|
||||
|
||||
@Update("UPDATE wvp_user_api_key SET enable = true WHERE id = #{id}")
|
||||
int enable(@Param("id") int id);
|
||||
|
||||
@Update("UPDATE wvp_user_api_key SET enable = false WHERE id = #{id}")
|
||||
int disable(@Param("id") int id);
|
||||
|
||||
@Update("UPDATE wvp_user_api_key SET api_key = #{apiKey} WHERE id = #{id}")
|
||||
int apiKey(@Param("id") int id, @Param("apiKey") String apiKey);
|
||||
|
||||
@Update("UPDATE wvp_user_api_key SET remark = #{remark} WHERE id = #{id}")
|
||||
int remark(@Param("id") int id, @Param("remark") String remark);
|
||||
|
||||
@Delete("DELETE FROM wvp_user_api_key WHERE id = #{id}")
|
||||
int delete(@Param("id") int id);
|
||||
|
||||
@Select("SELECT uak.id, uak.user_id, uak.app, uak.api_key, uak.expired_at, uak.remark, uak.enable, uak.create_time, uak.update_time, u.username AS username FROM wvp_user_api_key uak LEFT JOIN wvp_user u on u.id = uak.user_id WHERE uak.id = #{id}")
|
||||
UserApiKey selectById(@Param("id") int id);
|
||||
|
||||
@Select("SELECT uak.id, uak.user_id, uak.app, uak.api_key, uak.expired_at, uak.remark, uak.enable, uak.create_time, uak.update_time, u.username AS username FROM wvp_user_api_key uak LEFT JOIN wvp_user u on u.id = uak.user_id WHERE uak.api_key = #{apiKey}")
|
||||
UserApiKey selectByApiKey(@Param("apiKey") String apiKey);
|
||||
|
||||
@Select("SELECT uak.id, uak.user_id, uak.app, uak.api_key, uak.expired_at, uak.remark, uak.enable, uak.create_time, uak.update_time, u.username AS username FROM wvp_user_api_key uak LEFT JOIN wvp_user u on u.id = uak.user_id")
|
||||
List<UserApiKey> selectAll();
|
||||
|
||||
@Select("SELECT uak.id, uak.user_id, uak.app, uak.api_key, uak.expired_at, uak.remark, uak.enable, uak.create_time, uak.update_time, u.username AS username FROM wvp_user_api_key uak LEFT JOIN wvp_user u on u.id = uak.user_id")
|
||||
List<UserApiKey> getUserApiKeys();
|
||||
|
||||
@Select("SELECT COUNT(0) FROM wvp_user_api_key WHERE api_key = #{apiKey}")
|
||||
boolean isApiKeyExists(@Param("apiKey") String apiKey);
|
||||
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package com.genersoft.iot.vmp.storager.dao.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 用户信息
|
||||
*/
|
||||
@Schema(description = "用户ApiKey信息")
|
||||
public class UserApiKey implements Serializable {
|
||||
|
||||
/**
|
||||
* Id
|
||||
*/
|
||||
@Schema(description = "Id")
|
||||
private int id;
|
||||
|
||||
/**
|
||||
* 用户Id
|
||||
*/
|
||||
@Schema(description = "用户Id")
|
||||
private int userId;
|
||||
|
||||
/**
|
||||
* 应用名
|
||||
*/
|
||||
@Schema(description = "应用名")
|
||||
private String app;
|
||||
|
||||
/**
|
||||
* ApiKey
|
||||
*/
|
||||
@Schema(description = "ApiKey")
|
||||
private String apiKey;
|
||||
|
||||
/**
|
||||
* 过期时间(null=永不过期)
|
||||
*/
|
||||
@Schema(description = "过期时间(null=永不过期)")
|
||||
private String expiredAt;
|
||||
|
||||
/**
|
||||
* 备注信息
|
||||
*/
|
||||
@Schema(description = "备注信息")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
@Schema(description = "是否启用")
|
||||
private boolean enable;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description = "创建时间")
|
||||
private String createTime;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description = "更新时间")
|
||||
private String updateTime;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getApiKey() {
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
public void setApiKey(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
||||
public String getExpiredAt() {
|
||||
return expiredAt;
|
||||
}
|
||||
|
||||
public void setExpiredAt(String expiredAt) {
|
||||
this.expiredAt = expiredAt;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
public boolean isEnable() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
public void setEnable(boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
public String getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
public void setCreateTime(String createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
|
||||
public String getUpdateTime() {
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
public void setUpdateTime(String updateTime) {
|
||||
this.updateTime = updateTime;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
package com.genersoft.iot.vmp.vmanager.user;
|
||||
|
||||
import com.genersoft.iot.vmp.conf.exception.ControllerException;
|
||||
import com.genersoft.iot.vmp.conf.security.JwtUtils;
|
||||
import com.genersoft.iot.vmp.conf.security.SecurityUtils;
|
||||
import com.genersoft.iot.vmp.service.IUserApiKeyService;
|
||||
import com.genersoft.iot.vmp.service.IUserService;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.User;
|
||||
import com.genersoft.iot.vmp.storager.dao.dto.UserApiKey;
|
||||
import com.genersoft.iot.vmp.utils.DateUtil;
|
||||
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Tag(name = "用户ApiKey管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/userApiKey")
|
||||
public class UserApiKeyController {
|
||||
|
||||
public static final int EXPIRATION_TIME = Integer.MAX_VALUE;
|
||||
@Autowired
|
||||
private IUserService userService;
|
||||
|
||||
@Autowired
|
||||
private IUserApiKeyService userApiKeyService;
|
||||
|
||||
/**
|
||||
* 添加用户ApiKey
|
||||
*
|
||||
* @param userId
|
||||
* @param app
|
||||
* @param remark
|
||||
* @param expiresAt
|
||||
* @param enable
|
||||
*/
|
||||
@PostMapping("/add")
|
||||
@Operation(summary = "添加用户ApiKey", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "userId", description = "用户Id", required = true)
|
||||
@Parameter(name = "app", description = "应用名称", required = false)
|
||||
@Parameter(name = "remark", description = "备注信息", required = false)
|
||||
@Parameter(name = "expiredAt", description = "过期时间(不传代表永不过期)", required = false)
|
||||
@Transactional
|
||||
public synchronized void add(
|
||||
@RequestParam(required = true) int userId,
|
||||
@RequestParam(required = false) String app,
|
||||
@RequestParam(required = false) String remark,
|
||||
@RequestParam(required = false) String expiresAt,
|
||||
@RequestParam(required = false) Boolean enable
|
||||
) {
|
||||
User user = userService.getUserById(userId);
|
||||
if (user == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "用户不存在");
|
||||
}
|
||||
|
||||
Long expirationTime = null;
|
||||
if (expiresAt != null) {
|
||||
long timestamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestampMs(expiresAt);
|
||||
expirationTime = (timestamp - System.currentTimeMillis()) / (60 * 1000);
|
||||
if (expirationTime < 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "过期时间不能早于当前时间");
|
||||
}
|
||||
}
|
||||
|
||||
UserApiKey userApiKey = new UserApiKey();
|
||||
userApiKey.setUserId(userId);
|
||||
userApiKey.setApp(app);
|
||||
userApiKey.setApiKey(null);
|
||||
userApiKey.setRemark(remark);
|
||||
userApiKey.setExpiredAt(expiresAt);
|
||||
userApiKey.setEnable(enable != null ? enable : false);
|
||||
userApiKey.setCreateTime(DateUtil.getNow());
|
||||
userApiKey.setUpdateTime(DateUtil.getNow());
|
||||
|
||||
int addResult = userApiKeyService.addApiKey(userApiKey);
|
||||
|
||||
if (addResult <= 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR100);
|
||||
}
|
||||
|
||||
String apiKey;
|
||||
do {
|
||||
Map<String, Object> extra = new HashMap<>(1);
|
||||
extra.put("apiKeyId", userApiKey.getId());
|
||||
apiKey = JwtUtils.createToken(user.getUsername(), expirationTime, extra);
|
||||
} while (userApiKeyService.isApiKeyExists(apiKey));
|
||||
|
||||
int resetResult = userApiKeyService.reset(userApiKey.getId(), apiKey);
|
||||
|
||||
if (resetResult <= 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR100);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询ApiKey
|
||||
*
|
||||
* @param page 当前页
|
||||
* @param count 每页查询数量
|
||||
* @return 分页ApiKey列表
|
||||
*/
|
||||
@GetMapping("/userApiKeys")
|
||||
@Operation(summary = "分页查询用户", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "page", description = "当前页", required = true)
|
||||
@Parameter(name = "count", description = "每页查询数量", required = true)
|
||||
@Transactional
|
||||
public PageInfo<UserApiKey> userApiKeys(@RequestParam(required = true) int page, @RequestParam(required = true) int count) {
|
||||
return userApiKeyService.getUserApiKeys(page, count);
|
||||
}
|
||||
|
||||
@PostMapping("/enable")
|
||||
@Operation(summary = "启用用户ApiKey", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "id", description = "用户ApiKeyId", required = true)
|
||||
@Transactional
|
||||
public void enable(@RequestParam(required = true) Integer id) {
|
||||
// 获取当前登录用户id
|
||||
int currenRoleId = SecurityUtils.getUserInfo().getRole().getId();
|
||||
if (currenRoleId != 1) {
|
||||
// 只用角色id为1才可以管理UserApiKey
|
||||
throw new ControllerException(ErrorCode.ERROR403);
|
||||
}
|
||||
UserApiKey userApiKey = userApiKeyService.getUserApiKeyById(id);
|
||||
if (userApiKey == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "ApiKey不存在");
|
||||
}
|
||||
|
||||
int enableResult = userApiKeyService.enable(id);
|
||||
|
||||
if (enableResult <= 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR100);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/disable")
|
||||
@Operation(summary = "停用用户ApiKey", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "id", description = "用户ApiKeyId", required = true)
|
||||
@Transactional
|
||||
public void disable(@RequestParam(required = true) Integer id) {
|
||||
// 获取当前登录用户id
|
||||
int currenRoleId = SecurityUtils.getUserInfo().getRole().getId();
|
||||
if (currenRoleId != 1) {
|
||||
// 只用角色id为1才可以管理UserApiKey
|
||||
throw new ControllerException(ErrorCode.ERROR403);
|
||||
}
|
||||
UserApiKey userApiKey = userApiKeyService.getUserApiKeyById(id);
|
||||
if (userApiKey == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "ApiKey不存在");
|
||||
}
|
||||
|
||||
int disableResult = userApiKeyService.disable(id);
|
||||
|
||||
if (disableResult <= 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR100);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/reset")
|
||||
@Operation(summary = "重置用户ApiKey", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "id", description = "用户ApiKeyId", required = true)
|
||||
@Transactional
|
||||
public void reset(@RequestParam(required = true) Integer id) {
|
||||
// 获取当前登录用户id
|
||||
int currenRoleId = SecurityUtils.getUserInfo().getRole().getId();
|
||||
if (currenRoleId != 1) {
|
||||
// 只用角色id为1才可以管理UserApiKey
|
||||
throw new ControllerException(ErrorCode.ERROR403);
|
||||
}
|
||||
UserApiKey userApiKey = userApiKeyService.getUserApiKeyById(id);
|
||||
if (userApiKey == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "ApiKey不存在");
|
||||
}
|
||||
User user = userService.getUserById(userApiKey.getUserId());
|
||||
if (user == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "用户不存在");
|
||||
}
|
||||
Long expirationTime = null;
|
||||
if (userApiKey.getExpiredAt() != null) {
|
||||
long timestamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestampMs(userApiKey.getExpiredAt());
|
||||
expirationTime = (timestamp - System.currentTimeMillis()) / (60 * 1000);
|
||||
if (expirationTime < 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "ApiKey已失效");
|
||||
}
|
||||
}
|
||||
String apiKey;
|
||||
do {
|
||||
Map<String, Object> extra = new HashMap<>(1);
|
||||
extra.put("apiKeyId", userApiKey.getId());
|
||||
apiKey = JwtUtils.createToken(user.getUsername(), expirationTime, extra);
|
||||
} while (userApiKeyService.isApiKeyExists(apiKey));
|
||||
|
||||
int resetResult = userApiKeyService.reset(id, apiKey);
|
||||
|
||||
if (resetResult <= 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR100);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/remark")
|
||||
@Operation(summary = "备注用户ApiKey", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "id", description = "用户ApiKeyId", required = true)
|
||||
@Parameter(name = "remark", description = "用户ApiKey备注", required = false)
|
||||
@Transactional
|
||||
public void remark(@RequestParam(required = true) Integer id, @RequestParam(required = false) String remark) {
|
||||
// 获取当前登录用户id
|
||||
int currenRoleId = SecurityUtils.getUserInfo().getRole().getId();
|
||||
if (currenRoleId != 1) {
|
||||
// 只用角色id为1才可以管理UserApiKey
|
||||
throw new ControllerException(ErrorCode.ERROR403);
|
||||
}
|
||||
UserApiKey userApiKey = userApiKeyService.getUserApiKeyById(id);
|
||||
if (userApiKey == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "ApiKey不存在");
|
||||
}
|
||||
int remarkResult = userApiKeyService.remark(id, remark);
|
||||
|
||||
if (remarkResult <= 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR100);
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除用户ApiKey", security = @SecurityRequirement(name = JwtUtils.HEADER))
|
||||
@Parameter(name = "id", description = "用户ApiKeyId", required = true)
|
||||
@Transactional
|
||||
public void delete(@RequestParam(required = true) Integer id) {
|
||||
// 获取当前登录用户id
|
||||
int currenRoleId = SecurityUtils.getUserInfo().getRole().getId();
|
||||
if (currenRoleId != 1) {
|
||||
// 只用角色id为1才可以管理UserApiKey
|
||||
throw new ControllerException(ErrorCode.ERROR403);
|
||||
}
|
||||
UserApiKey userApiKey = userApiKeyService.getUserApiKeyById(id);
|
||||
if (userApiKey == null) {
|
||||
throw new ControllerException(ErrorCode.ERROR400.getCode(), "ApiKey不存在");
|
||||
}
|
||||
|
||||
int deleteResult = userApiKeyService.delete(id);
|
||||
|
||||
if (deleteResult <= 0) {
|
||||
throw new ControllerException(ErrorCode.ERROR100);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,8 @@ spring:
|
|||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 100MB
|
||||
cache:
|
||||
type: redis
|
||||
# REDIS数据库配置
|
||||
redis:
|
||||
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
|
||||
|
|
|
@ -4,6 +4,8 @@ spring:
|
|||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 100MB
|
||||
cache:
|
||||
type: redis
|
||||
# REDIS数据库配置
|
||||
redis:
|
||||
# [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
|
||||
|
|
|
@ -12,7 +12,7 @@ module.exports = {
|
|||
assetsPublicPath: '/',
|
||||
proxyTable: {
|
||||
'/debug': {
|
||||
target: 'http://127.0.0.1:18082',
|
||||
target: 'http://127.0.0.1:8080',
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
'^/debug': '/'
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
<template>
|
||||
<div id="app" style="width: 100%">
|
||||
<div class="page-header" style="margin-bottom: 0">
|
||||
<div class="page-title">
|
||||
<el-page-header @back="goBack" content="ApiKey列表"></el-page-header>
|
||||
</div>
|
||||
<div class="page-header-btn">
|
||||
<el-button icon="el-icon-plus" size="mini" style="margin-right: 1rem;" type="primary" @click="addUserApiKey">
|
||||
添加ApiKey
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<!--ApiKey列表-->
|
||||
<el-table :data="userList" style="width: 100%;font-size: 12px;" :height="winHeight"
|
||||
header-row-class-name="table-header">
|
||||
<el-table-column prop="user.username" label="用户名" min-width="120"/>
|
||||
<el-table-column prop="app" label="应用名" min-width="160"/>
|
||||
<el-table-column prop="apiKey" label="ApiKey" min-width="480"/>
|
||||
<el-table-column prop="enable" label="启用" width="120">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.enable">
|
||||
启用
|
||||
</el-tag>
|
||||
<el-tag v-else type="info">
|
||||
停用
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="expiredAt" label="过期时间" width="160"/>
|
||||
<el-table-column prop="remark" label="备注信息" min-width="160"/>
|
||||
<el-table-column label="操作" min-width="160" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button v-if="scope.row.enable"
|
||||
size="medium" icon="el-icon-circle-close" type="text" @click="disableUserApiKey(scope.row)">
|
||||
停用
|
||||
</el-button>
|
||||
<el-button v-else
|
||||
size="medium" icon="el-icon-circle-check" type="text" @click="enableUserApiKey(scope.row)">
|
||||
启用
|
||||
</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button size="medium" icon="el-icon-refresh" type="text" @click="resetUserApiKey(scope.row)">
|
||||
重置
|
||||
</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="remarkUserApiKey(scope.row)">
|
||||
备注
|
||||
</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button size="medium" icon="el-icon-delete" type="text" @click="deleteUserApiKey(scope.row)"
|
||||
style="color: #f56c6c">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<addUserApiKey ref="addUserApiKey"></addUserApiKey>
|
||||
<remarkUserApiKey ref="remarkUserApiKey"></remarkUserApiKey>
|
||||
<el-pagination
|
||||
style="float: right"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="currentChange"
|
||||
:current-page="currentPage"
|
||||
:page-size="count"
|
||||
:page-sizes="[15, 25, 35, 50]"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:total="total">
|
||||
</el-pagination>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uiHeader from '../layout/UiHeader.vue'
|
||||
import addUserApiKey from "./dialog/addUserApiKey.vue";
|
||||
import remarkUserApiKey from './dialog/remarkUserApiKey.vue'
|
||||
|
||||
export default {
|
||||
name: 'userApiKeyManager',
|
||||
components: {
|
||||
uiHeader,
|
||||
addUserApiKey,
|
||||
remarkUserApiKey
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
userList: [], //设备列表
|
||||
currentUser: {}, //当前操作设备对象
|
||||
winHeight: window.innerHeight - 200,
|
||||
currentPage: 1,
|
||||
count: 15,
|
||||
total: 0,
|
||||
getUserApiKeyListLoading: false
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.initParam();
|
||||
this.initData();
|
||||
},
|
||||
methods: {
|
||||
goBack() {
|
||||
this.$router.back()
|
||||
},
|
||||
initParam() {
|
||||
this.userId = this.$route.params.userId;
|
||||
},
|
||||
initData() {
|
||||
this.getUserApiKeyList();
|
||||
},
|
||||
currentChange(val) {
|
||||
this.currentPage = val;
|
||||
this.getUserApiKeyList();
|
||||
},
|
||||
handleSizeChange(val) {
|
||||
this.count = val;
|
||||
this.getUserApiKeyList();
|
||||
},
|
||||
getUserApiKeyList() {
|
||||
let that = this;
|
||||
this.getUserApiKeyListLoading = true;
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url: `/api/userApiKey/userApiKeys`,
|
||||
params: {
|
||||
page: that.currentPage,
|
||||
count: that.count
|
||||
}
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
that.total = res.data.data.total;
|
||||
that.userList = res.data.data.list;
|
||||
}
|
||||
that.getUserApiKeyListLoading = false;
|
||||
}).catch((error) => {
|
||||
that.getUserApiKeyListLoading = false;
|
||||
});
|
||||
},
|
||||
addUserApiKey() {
|
||||
this.$refs.addUserApiKey.openDialog(this.userId, () => {
|
||||
this.$refs.addUserApiKey.close();
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "ApiKey添加成功",
|
||||
type: "success",
|
||||
});
|
||||
setTimeout(this.getUserApiKeyList, 200)
|
||||
})
|
||||
},
|
||||
remarkUserApiKey(row) {
|
||||
this.$refs.remarkUserApiKey.openDialog(row.id, () => {
|
||||
this.$refs.remarkUserApiKey.close();
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: "备注修改成功",
|
||||
type: "success",
|
||||
});
|
||||
setTimeout(this.getUserApiKeyList, 200)
|
||||
})
|
||||
},
|
||||
enableUserApiKey(row) {
|
||||
let msg = "确定启用此ApiKey?"
|
||||
if (row.online !== 0) {
|
||||
msg = "<strong>确定启用此ApiKey?</strong>"
|
||||
}
|
||||
this.$confirm(msg, '提示', {
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
center: true,
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: `/api/userApiKey/enable?id=${row.id}`
|
||||
}).then((res) => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '启用成功',
|
||||
type: 'success'
|
||||
});
|
||||
this.getUserApiKeyList();
|
||||
}).catch((error) => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '启用失败',
|
||||
type: 'error'
|
||||
});
|
||||
console.error(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
disableUserApiKey(row) {
|
||||
let msg = "确定停用此ApiKey?"
|
||||
if (row.online !== 0) {
|
||||
msg = "<strong>确定停用此ApiKey?</strong>"
|
||||
}
|
||||
this.$confirm(msg, '提示', {
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
center: true,
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: `/api/userApiKey/disable?id=${row.id}`
|
||||
}).then((res) => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '停用成功',
|
||||
type: 'success'
|
||||
});
|
||||
this.getUserApiKeyList();
|
||||
}).catch((error) => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '停用失败',
|
||||
type: 'error'
|
||||
});
|
||||
console.error(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
resetUserApiKey(row) {
|
||||
let msg = "确定重置此ApiKey?"
|
||||
if (row.online !== 0) {
|
||||
msg = "<strong>确定重置此ApiKey?</strong>"
|
||||
}
|
||||
this.$confirm(msg, '提示', {
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
center: true,
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: `/api/userApiKey/reset?id=${row.id}`
|
||||
}).then((res) => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '重置成功',
|
||||
type: 'success'
|
||||
});
|
||||
this.getUserApiKeyList();
|
||||
}).catch((error) => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '重置失败',
|
||||
type: 'error'
|
||||
});
|
||||
console.error(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
deleteUserApiKey(row) {
|
||||
let msg = "确定删除此ApiKey?"
|
||||
if (row.online !== 0) {
|
||||
msg = "<strong>确定删除此ApiKey?</strong>"
|
||||
}
|
||||
this.$confirm(msg, '提示', {
|
||||
dangerouslyUseHTMLString: true,
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
center: true,
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.$axios({
|
||||
method: 'delete',
|
||||
url: `/api/userApiKey/delete?id=${row.id}`
|
||||
}).then((res) => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '删除成功',
|
||||
type: 'success'
|
||||
});
|
||||
this.getUserApiKeyList();
|
||||
}).catch((error) => {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '删除失败',
|
||||
type: 'error'
|
||||
});
|
||||
console.error(error);
|
||||
});
|
||||
}).catch(() => {
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
|
||||
</style>
|
|
@ -23,6 +23,8 @@
|
|||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="changePushKey(scope.row)">修改pushkey</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button size="medium" icon="el-icon-edit" type="text" @click="showUserApiKeyManager(scope.row)">管理ApiKey</el-button>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<el-button size="medium" icon="el-icon-delete" type="text" @click="deleteUser(scope.row)"
|
||||
style="color: #f56c6c">删除
|
||||
</el-button>
|
||||
|
@ -178,7 +180,10 @@ export default {
|
|||
setTimeout(this.getUserList, 200)
|
||||
|
||||
})
|
||||
}
|
||||
},
|
||||
showUserApiKeyManager: function (row) {
|
||||
this.$router.push(`/userApiKeyManager/${row.id}`)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
<template>
|
||||
<div id="addUserApiKey" v-loading="isLoading">
|
||||
<el-dialog
|
||||
title="添加ApiKey"
|
||||
width="40%"
|
||||
top="2rem"
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="showDialog"
|
||||
:destroy-on-close="true"
|
||||
@close="close()"
|
||||
>
|
||||
<div id="shared" style="margin-right: 20px;">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" status-icon label-width="80px">
|
||||
<el-form-item label="应用名" prop="app">
|
||||
<el-input
|
||||
v-model="form.app"
|
||||
property="app"
|
||||
autocomplete="off"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="启用状态" prop="enable" style="text-align: left">
|
||||
<el-switch
|
||||
v-model="form.enable"
|
||||
property="enable"
|
||||
active-text="启用"
|
||||
inactive-text="停用"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="过期时间" prop="expiresAt" style="text-align: left">
|
||||
<el-date-picker v-model="form.expiresAt"
|
||||
style="width: 100%"
|
||||
property="expiresAt"
|
||||
type="datetime"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
format="yyyy-MM-dd HH:mm:ss"
|
||||
placeholder="选择过期时间"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注信息" prop="remark">
|
||||
<el-input v-model="form.remark"
|
||||
type="textarea"
|
||||
property="remark"
|
||||
autocomplete="off"
|
||||
:autosize="{ minRows: 5}"
|
||||
maxlength="255"
|
||||
show-word-limit/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div style="float: right;">
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
<el-button @click="close">取消</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'addUserApiKey',
|
||||
props: {},
|
||||
computed: {},
|
||||
created() {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
userId: null,
|
||||
form: {
|
||||
app: null,
|
||||
enable: true,
|
||||
expiresAt: null,
|
||||
remark: null
|
||||
},
|
||||
rules: {
|
||||
app: [{required: true, trigger: 'blur', message: '应用名不能为空'}]
|
||||
},
|
||||
listChangeCallback: null,
|
||||
showDialog: false,
|
||||
isLoading: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
resetForm() {
|
||||
this.form = {
|
||||
app: null,
|
||||
enable: true,
|
||||
expiresAt: null,
|
||||
remark: null
|
||||
}
|
||||
},
|
||||
openDialog(userId, callback) {
|
||||
this.resetForm()
|
||||
this.userId = userId
|
||||
this.listChangeCallback = callback
|
||||
this.showDialog = true
|
||||
},
|
||||
onSubmit() {
|
||||
this.$refs.formRef.validate((valid) => {
|
||||
if (valid) {
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: '/api/userApiKey/add',
|
||||
params: {
|
||||
userId: this.userId,
|
||||
app: this.form.app,
|
||||
enable: this.form.enable,
|
||||
expiresAt: this.form.expiresAt,
|
||||
remark: this.form.remark,
|
||||
}
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '添加成功',
|
||||
type: 'success'
|
||||
});
|
||||
this.showDialog = false
|
||||
if (this.listChangeCallback) {
|
||||
this.listChangeCallback()
|
||||
}
|
||||
} else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: res.data.msg,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error(error)
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
close() {
|
||||
this.showDialog = false
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -0,0 +1,93 @@
|
|||
<template>
|
||||
<div id="remarkUserApiKey" v-loading="isLoading">
|
||||
<el-dialog
|
||||
title="ApiKey备注"
|
||||
width="40%"
|
||||
top="2rem"
|
||||
:close-on-click-modal="false"
|
||||
:visible.sync="showDialog"
|
||||
:destroy-on-close="true"
|
||||
@close="close()"
|
||||
>
|
||||
<div id="shared" style="margin-right: 20px;">
|
||||
<el-form ref="form" :rules="rules" status-icon label-width="80px">
|
||||
<el-form-item label="备注" prop="oldPassword">
|
||||
<el-input type="textarea" v-model="form.remark" autocomplete="off" :autosize="{ minRows: 5}" maxlength="255" show-word-limit></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<div style="float: right;">
|
||||
<el-button type="primary" @click="onSubmit">保存</el-button>
|
||||
<el-button @click="close">取消</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "remarkUserApiKey",
|
||||
props: {},
|
||||
computed: {},
|
||||
created() {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
userApiKeyId: null,
|
||||
form: {
|
||||
remark: null
|
||||
},
|
||||
rules: {},
|
||||
listChangeCallback: null,
|
||||
showDialog: false,
|
||||
isLoading: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
resetForm() {
|
||||
this.form = {
|
||||
remark: null
|
||||
}
|
||||
},
|
||||
openDialog(userApiKeyId, callback) {
|
||||
this.resetForm()
|
||||
this.userApiKeyId = userApiKeyId
|
||||
this.listChangeCallback = callback
|
||||
this.showDialog = true
|
||||
},
|
||||
onSubmit() {
|
||||
this.$axios({
|
||||
method: 'post',
|
||||
url: "/api/userApiKey/remark",
|
||||
params: {
|
||||
id: this.userApiKeyId,
|
||||
remark: this.form.remark
|
||||
}
|
||||
}).then((res) => {
|
||||
if (res.data.code === 0) {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '备注修改成功!',
|
||||
type: 'success'
|
||||
});
|
||||
this.showDialog = false;
|
||||
this.listChangeCallback()
|
||||
} else {
|
||||
this.$message({
|
||||
showClose: true,
|
||||
message: '备注修改失败',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error(error)
|
||||
});
|
||||
},
|
||||
close() {
|
||||
this.showDialog = false
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
|
@ -20,7 +20,7 @@ import media from '../components/setting/Media.vue'
|
|||
import live from '../components/live.vue'
|
||||
import deviceTree from '../components/common/DeviceTree.vue'
|
||||
import userManager from '../components/UserManager.vue'
|
||||
|
||||
import userApiKeyManager from '../components/UserApiKeyManager.vue'
|
||||
import wasmPlayer from '../components/common/jessibuca.vue'
|
||||
import rtcPlayer from '../components/dialog/rtcPlayer.vue'
|
||||
|
||||
|
@ -125,7 +125,13 @@ export default new VueRouter({
|
|||
path: '/userManager',
|
||||
name: 'userManager',
|
||||
component: userManager,
|
||||
},
|
||||
{
|
||||
path: '/userApiKeyManager/:userId',
|
||||
name: 'userApiKeyManager',
|
||||
component: userApiKeyManager,
|
||||
}
|
||||
,
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -4,6 +4,8 @@ spring:
|
|||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 100MB
|
||||
cache:
|
||||
type: redis
|
||||
# REDIS数据库配置
|
||||
redis:
|
||||
# [可选] 超时时间
|
||||
|
|
|
@ -314,6 +314,17 @@ create table wvp_resources_tree (
|
|||
parentId integer,
|
||||
path character varying(255)
|
||||
);
|
||||
create table wvp_user_api_key (
|
||||
id serial primary key ,
|
||||
user_id bigint,
|
||||
app character varying(255) ,
|
||||
api_key text,
|
||||
expired_at bigint,
|
||||
remark character varying(255),
|
||||
enable bool default true,
|
||||
create_time character varying(50),
|
||||
update_time character varying(50)
|
||||
);
|
||||
|
||||
|
||||
/*初始数据*/
|
||||
|
|
|
@ -314,7 +314,17 @@ create table wvp_resources_tree (
|
|||
parentId integer,
|
||||
path character varying(255)
|
||||
);
|
||||
|
||||
create table wvp_user_api_key (
|
||||
id serial primary key ,
|
||||
user_id bigint,
|
||||
app character varying(255) ,
|
||||
api_key text,
|
||||
expired_at bigint,
|
||||
remark character varying(255),
|
||||
enable bool default true,
|
||||
create_time character varying(50),
|
||||
update_time character varying(50)
|
||||
);
|
||||
|
||||
/*初始数据*/
|
||||
INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
|
||||
|
|
|
@ -314,7 +314,17 @@ create table wvp_resources_tree (
|
|||
parentId integer,
|
||||
path character varying(255)
|
||||
);
|
||||
|
||||
create table wvp_user_api_key (
|
||||
id serial primary key ,
|
||||
user_id bigint,
|
||||
app character varying(255) ,
|
||||
api_key text,
|
||||
expired_at bigint,
|
||||
remark character varying(255),
|
||||
enable bool default true,
|
||||
create_time character varying(50),
|
||||
update_time character varying(50)
|
||||
);
|
||||
|
||||
/*初始数据*/
|
||||
INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
|
||||
|
|
|
@ -314,7 +314,17 @@ create table wvp_resources_tree (
|
|||
parentId integer,
|
||||
path character varying(255)
|
||||
);
|
||||
|
||||
create table wvp_user_api_key (
|
||||
id serial primary key ,
|
||||
user_id bigint,
|
||||
app character varying(255) ,
|
||||
api_key text,
|
||||
expired_at bigint,
|
||||
remark character varying(255),
|
||||
enable bool default true,
|
||||
create_time character varying(50),
|
||||
update_time character varying(50)
|
||||
);
|
||||
|
||||
/*初始数据*/
|
||||
INSERT INTO wvp_user VALUES (1, 'admin','21232f297a57a5a743894a0e4a801fc3',1,'2021-04-13 14:14:57','2021-04-13 14:14:57','3e80d1762a324d5b0ff636e0bd16f1e3');
|
||||
|
|
Loading…
Reference in New Issue