mirror of
https://gitee.com/ssssssss-team/magic-api.git
synced 2026-06-09 18:32:16 +08:00
1、接口&函数锁定和解锁。2、修复无法测试上传的问题
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package org.ssssssss.magicapi.controller;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@@ -8,6 +9,7 @@ import org.ssssssss.magicapi.config.Valid;
|
||||
import org.ssssssss.magicapi.interceptor.Authorization;
|
||||
import org.ssssssss.magicapi.model.ApiInfo;
|
||||
import org.ssssssss.magicapi.model.Backup;
|
||||
import org.ssssssss.magicapi.model.Constants;
|
||||
import org.ssssssss.magicapi.model.JsonBean;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -33,7 +35,9 @@ public class MagicAPIController extends MagicController implements MagicExceptio
|
||||
@ResponseBody
|
||||
@Valid(readonly = false)
|
||||
public JsonBean<Boolean> delete(HttpServletRequest request, String id) {
|
||||
isTrue(allowVisit(request, Authorization.DELETE, getApiInfo(id)), PERMISSION_INVALID);
|
||||
ApiInfo apiInfo = getApiInfo(id);
|
||||
isTrue(allowVisit(request, Authorization.DELETE, apiInfo), PERMISSION_INVALID);
|
||||
isTrue(!Constants.LOCK.equals(apiInfo.getLock()), RESOURCE_LOCKED);
|
||||
return new JsonBean<>(magicAPIService.deleteApi(id));
|
||||
}
|
||||
|
||||
@@ -102,6 +106,7 @@ public class MagicAPIController extends MagicController implements MagicExceptio
|
||||
// 新的分组ID
|
||||
apiInfo.setGroupId(groupId);
|
||||
isTrue(allowVisit(request, Authorization.SAVE, apiInfo), PERMISSION_INVALID);
|
||||
isTrue(!Constants.LOCK.equals(apiInfo.getLock()), RESOURCE_LOCKED);
|
||||
return new JsonBean<>(magicAPIService.moveApi(id, groupId));
|
||||
}
|
||||
|
||||
@@ -113,10 +118,36 @@ public class MagicAPIController extends MagicController implements MagicExceptio
|
||||
@Valid(readonly = false)
|
||||
public JsonBean<String> save(HttpServletRequest request, @RequestBody ApiInfo info) {
|
||||
isTrue(allowVisit(request, Authorization.SAVE, info), PERMISSION_INVALID);
|
||||
if (StringUtils.isNotBlank(info.getId())) {
|
||||
ApiInfo oldInfo = getApiInfo(info.getId());
|
||||
isTrue(!Constants.LOCK.equals(oldInfo.getLock()), RESOURCE_LOCKED);
|
||||
}
|
||||
return new JsonBean<>(magicAPIService.saveApi(info));
|
||||
}
|
||||
|
||||
private ApiInfo getApiInfo(String id){
|
||||
/**
|
||||
* 锁定接口
|
||||
*/
|
||||
@RequestMapping("/lock")
|
||||
@ResponseBody
|
||||
@Valid(readonly = false)
|
||||
public JsonBean<Boolean> lock(HttpServletRequest request, String id) {
|
||||
isTrue(allowVisit(request, Authorization.LOCK, getApiInfo(id)), PERMISSION_INVALID);
|
||||
return new JsonBean<>(magicAPIService.lockApi(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解锁接口
|
||||
*/
|
||||
@RequestMapping("/unlock")
|
||||
@ResponseBody
|
||||
@Valid(readonly = false)
|
||||
public JsonBean<Boolean> unlock(HttpServletRequest request, String id) {
|
||||
isTrue(allowVisit(request, Authorization.UNLOCK, getApiInfo(id)), PERMISSION_INVALID);
|
||||
return new JsonBean<>(magicAPIService.unlockApi(id));
|
||||
}
|
||||
|
||||
private ApiInfo getApiInfo(String id) {
|
||||
ApiInfo apiInfo = magicAPIService.getApiInfo(id);
|
||||
notNull(apiInfo, API_NOT_FOUND);
|
||||
return apiInfo;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.ssssssss.magicapi.controller;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@@ -7,6 +8,7 @@ import org.ssssssss.magicapi.config.MagicConfiguration;
|
||||
import org.ssssssss.magicapi.config.Valid;
|
||||
import org.ssssssss.magicapi.interceptor.Authorization;
|
||||
import org.ssssssss.magicapi.model.Backup;
|
||||
import org.ssssssss.magicapi.model.Constants;
|
||||
import org.ssssssss.magicapi.model.FunctionInfo;
|
||||
import org.ssssssss.magicapi.model.JsonBean;
|
||||
|
||||
@@ -63,6 +65,7 @@ public class MagicFunctionController extends MagicController implements MagicExc
|
||||
FunctionInfo functionInfo = getFunctionInfo(id);
|
||||
functionInfo.setGroupId(groupId);
|
||||
isTrue(allowVisit(request, Authorization.SAVE, functionInfo), PERMISSION_INVALID);
|
||||
isTrue(!Constants.LOCK.equals(functionInfo.getLock()), RESOURCE_LOCKED);
|
||||
return new JsonBean<>(magicAPIService.moveFunction(id, groupId));
|
||||
}
|
||||
|
||||
@@ -72,6 +75,10 @@ public class MagicFunctionController extends MagicController implements MagicExc
|
||||
@Valid(readonly = false)
|
||||
public JsonBean<String> save(HttpServletRequest request, @RequestBody FunctionInfo functionInfo) {
|
||||
isTrue(allowVisit(request, Authorization.SAVE, functionInfo), PERMISSION_INVALID);
|
||||
if (StringUtils.isNotBlank(functionInfo.getId())) {
|
||||
FunctionInfo oldInfo = getFunctionInfo(functionInfo.getId());
|
||||
isTrue(!Constants.LOCK.equals(oldInfo.getLock()), RESOURCE_LOCKED);
|
||||
}
|
||||
return new JsonBean<>(magicAPIService.saveFunction(functionInfo));
|
||||
}
|
||||
|
||||
@@ -79,10 +86,34 @@ public class MagicFunctionController extends MagicController implements MagicExc
|
||||
@ResponseBody
|
||||
@Valid(readonly = false)
|
||||
public JsonBean<Boolean> delete(HttpServletRequest request, String id) {
|
||||
isTrue(allowVisit(request, Authorization.DELETE, getFunctionInfo(id)), PERMISSION_INVALID);
|
||||
FunctionInfo info = getFunctionInfo(id);
|
||||
isTrue(allowVisit(request, Authorization.DELETE, info), PERMISSION_INVALID);
|
||||
isTrue(!Constants.LOCK.equals(info.getLock()), RESOURCE_LOCKED);
|
||||
return new JsonBean<>(magicAPIService.deleteFunction(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 锁定函数
|
||||
*/
|
||||
@RequestMapping("/function/lock")
|
||||
@ResponseBody
|
||||
@Valid(readonly = false)
|
||||
public JsonBean<Boolean> lock(HttpServletRequest request, String id) {
|
||||
isTrue(allowVisit(request, Authorization.LOCK, getFunctionInfo(id)), PERMISSION_INVALID);
|
||||
return new JsonBean<>(magicAPIService.lockFunction(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 解锁函数
|
||||
*/
|
||||
@RequestMapping("/function/unlock")
|
||||
@ResponseBody
|
||||
@Valid(readonly = false)
|
||||
public JsonBean<Boolean> unlock(HttpServletRequest request, String id) {
|
||||
isTrue(allowVisit(request, Authorization.UNLOCK, getFunctionInfo(id)), PERMISSION_INVALID);
|
||||
return new JsonBean<>(magicAPIService.unlockFunction(id));
|
||||
}
|
||||
|
||||
public FunctionInfo getFunctionInfo(String id) {
|
||||
FunctionInfo functionInfo = magicAPIService.getFunctionInfo(id);
|
||||
notNull(functionInfo, FUNCTION_NOT_FOUND);
|
||||
|
||||
@@ -28,5 +28,13 @@ public enum Authorization {
|
||||
/**
|
||||
* 执行推送动作
|
||||
*/
|
||||
PUSH
|
||||
PUSH,
|
||||
/**
|
||||
* 锁定动作
|
||||
*/
|
||||
LOCK,
|
||||
/**
|
||||
* 解锁动作
|
||||
*/
|
||||
UNLOCK
|
||||
}
|
||||
@@ -264,6 +264,7 @@ public class ApiInfo extends MagicEntity {
|
||||
target.setGroupId(this.getGroupId());
|
||||
target.setPath(this.getPath());
|
||||
target.setMethod(this.getMethod());
|
||||
target.setLock(this.getLock());
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,10 @@ public class Constants {
|
||||
|
||||
public static final String UPLOAD_MODE_FULL = "full";
|
||||
|
||||
public static final String LOCK = "1";
|
||||
|
||||
public static final String UNLOCK = "0";
|
||||
|
||||
/**
|
||||
* 执行成功的code值
|
||||
*/
|
||||
|
||||
@@ -19,6 +19,8 @@ public interface JsonCodeConstants {
|
||||
|
||||
JsonCode NAME_CONFLICT = new JsonCode(0, "移动后名称会重复,请修改名称后在试。");
|
||||
|
||||
JsonCode RESOURCE_LOCKED = new JsonCode(0, "当前资源已被锁定,请解锁后在操作。");
|
||||
|
||||
JsonCode REQUEST_PATH_CONFLICT = new JsonCode(0, "该路径已被映射,请换一个请求方法或路径");
|
||||
|
||||
JsonCode FUNCTION_PATH_CONFLICT = new JsonCode(0, "该路径已被映射,请换一个请求方法或路径");
|
||||
|
||||
@@ -14,6 +14,8 @@ public class MagicEntity extends Attributes<Object> implements Cloneable {
|
||||
|
||||
protected Long updateTime;
|
||||
|
||||
protected String lock;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -62,6 +64,14 @@ public class MagicEntity extends Attributes<Object> implements Cloneable {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getLock() {
|
||||
return lock;
|
||||
}
|
||||
|
||||
public void setLock(String lock) {
|
||||
this.lock = lock;
|
||||
}
|
||||
|
||||
public MagicEntity clone() {
|
||||
try {
|
||||
return (MagicEntity) super.clone();
|
||||
|
||||
@@ -47,6 +47,14 @@ public interface MagicAPIService extends MagicModule {
|
||||
*/
|
||||
String saveApi(ApiInfo apiInfo);
|
||||
|
||||
boolean lockApi(String id);
|
||||
|
||||
boolean unlockApi(String id);
|
||||
|
||||
boolean lockFunction(String id);
|
||||
|
||||
boolean unlockFunction(String id);
|
||||
|
||||
/**
|
||||
* 获取接口详情
|
||||
*
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.ssssssss.magicapi.adapter.Resource;
|
||||
import org.ssssssss.magicapi.model.Constants;
|
||||
import org.ssssssss.magicapi.model.MagicEntity;
|
||||
import org.ssssssss.magicapi.utils.JsonUtils;
|
||||
|
||||
@@ -84,6 +85,24 @@ public abstract class StoreServiceProvider<T extends MagicEntity> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean lock(String id){
|
||||
T info = get(id);
|
||||
if(info != null){
|
||||
info.setLock(Constants.LOCK);
|
||||
return update(info);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean unlock(String id){
|
||||
T info = get(id);
|
||||
if(info != null){
|
||||
info.setLock(Constants.UNLOCK);
|
||||
return update(info);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有(提供给页面,无需带script)
|
||||
*/
|
||||
|
||||
@@ -228,6 +228,33 @@ public class DefaultMagicAPIService implements MagicAPIService, JsonCodeConstant
|
||||
return info.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lockApi(String id) {
|
||||
return lockWithNotify(apiServiceProvider.lock(id), id, NOTIFY_ACTION_API);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unlockApi(String id) {
|
||||
return lockWithNotify(apiServiceProvider.unlock(id), id, NOTIFY_ACTION_API);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean lockFunction(String id) {
|
||||
return lockWithNotify(functionServiceProvider.lock(id), id, NOTIFY_ACTION_FUNCTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unlockFunction(String id) {
|
||||
return lockWithNotify(functionServiceProvider.unlock(id), id, NOTIFY_ACTION_FUNCTION);
|
||||
}
|
||||
|
||||
private boolean lockWithNotify(boolean success, String id, int type){
|
||||
if(success){
|
||||
magicNotifyService.sendNotify(new MagicNotify(instanceId, id, NOTIFY_ACTION_UPDATE, type));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiInfo getApiInfo(String id) {
|
||||
return apiServiceProvider.get(id);
|
||||
|
||||
@@ -11,6 +11,14 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.ma-icon-lock:before {
|
||||
content: "\e64f";
|
||||
}
|
||||
|
||||
.ma-icon-unlock:before {
|
||||
content: "\e783";
|
||||
}
|
||||
|
||||
.ma-icon-collapse:before {
|
||||
content: "\e609";
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -18,7 +18,8 @@
|
||||
>
|
||||
<i class="ma-svg-icon" v-if="item._type === 'api'" :class="['request-method-' + item.method]" />
|
||||
<i class="ma-svg-icon" v-if="item._type !== 'api'" :class="['icon-function']" />
|
||||
{{item.name}}<span v-show="!item.id || item.script !== item.ext.tmpScript">*</span>
|
||||
{{item.name}}<i class="ma-icon ma-icon-lock" v-if="item.lock === '1'" />
|
||||
<span v-show="!item.id || item.script !== item.ext.tmpScript">*</span>
|
||||
<i class="ma-icon ma-icon-close" @click.stop="close(item.id || item.tmp_id)"/>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -548,7 +549,7 @@ export default {
|
||||
requestConfig.headers['Content-Type'] = 'multipart/form-data';
|
||||
let formData = new FormData()
|
||||
Object.keys(params).forEach(key => {
|
||||
let value = requestConfig.data[key];
|
||||
let value = params[key];
|
||||
if(value instanceof FileList){
|
||||
value.forEach(file => formData.append(key, file, file.name))
|
||||
}else{
|
||||
@@ -958,12 +959,14 @@ ul li.draggableTargetItem {
|
||||
background: var(--hover-background);
|
||||
}
|
||||
|
||||
ul li i {
|
||||
ul li i:not(.ma-icon-lock) {
|
||||
color: var(--icon-color);
|
||||
margin-left: 5px;
|
||||
font-size: 0.5em;
|
||||
}
|
||||
|
||||
.ma-icon-lock{
|
||||
margin-left: 5px;
|
||||
}
|
||||
.ma-editor-container > div {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
<i class="ma-svg-icon" :class="['request-method-' + item.method]" />
|
||||
<label>{{ item.name }}</label>
|
||||
<span>({{ item.path }})</span>
|
||||
<i class="ma-icon ma-icon-lock" v-if="item.lock === '1'"></i>
|
||||
</div>
|
||||
</template>
|
||||
</magic-tree>
|
||||
@@ -320,6 +321,7 @@ export default {
|
||||
parameters: null,
|
||||
paths: null,
|
||||
option: null,
|
||||
lock: '0',
|
||||
requestBody: null,
|
||||
headers: null,
|
||||
responseBody: null,
|
||||
@@ -449,9 +451,27 @@ export default {
|
||||
this.copyPathToClipboard(item, true)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: `${item.lock === '1' ? '解锁' : '锁定'}`,
|
||||
icon: `ma-icon-${item.lock === '1' ? 'unlock' : 'lock'}`,
|
||||
onClick: () => {
|
||||
let action = item.lock === '1' ? '解锁接口' : '锁定接口';
|
||||
request.send(item.lock === '1' ? 'unlock' : 'lock', {id: item.id}).success(data => {
|
||||
if (data) {
|
||||
bus.$emit('status', `${action}「${item.name}(${item.path})」`)
|
||||
bus.$emit('report', `api_${item.lock === '1' ? 'unlock' : 'lock'}`)
|
||||
item['lock'] = item.lock === '1' ? '0' : '1';
|
||||
this.changeForceUpdate()
|
||||
} else {
|
||||
this.$magicAlert({content: `${action}失败`})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '刷新接口',
|
||||
icon: 'ma-icon-refresh',
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.initData()
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
<i class="ma-svg-icon icon-function" />
|
||||
<label>{{ item.name }}</label>
|
||||
<span>({{ item.path }})</span>
|
||||
<i class="ma-icon ma-icon-lock" v-if="item.lock === '1'"></i>
|
||||
</div>
|
||||
</template>
|
||||
</magic-tree>
|
||||
@@ -319,6 +320,7 @@ export default {
|
||||
path: '',
|
||||
script: null,
|
||||
name: '未定义名称',
|
||||
lock: '0',
|
||||
parameters: null,
|
||||
description: null,
|
||||
level: item.level + 1,
|
||||
@@ -413,9 +415,27 @@ export default {
|
||||
this.open(newItem)
|
||||
}
|
||||
},
|
||||
{
|
||||
label: `${item.lock === '1' ? '解锁' : '锁定'}`,
|
||||
icon: `ma-icon-${item.lock === '1' ? 'unlock' : 'lock'}`,
|
||||
onClick: () => {
|
||||
let action = item.lock === '1' ? '解锁函数' : '锁定函数';
|
||||
request.send(item.lock === '1' ? 'function/unlock' : 'function/lock', {id: item.id}).success(data => {
|
||||
if (data) {
|
||||
bus.$emit('status', `${action}「${item.name}(${item.path})」`)
|
||||
bus.$emit('report', `function_${item.lock === '1' ? 'unlock' : 'lock'}`)
|
||||
item['lock'] = item.lock === '1' ? '0' : '1';
|
||||
this.changeForceUpdate()
|
||||
} else {
|
||||
this.$magicAlert({content: `${action}失败`})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
label: '刷新函数',
|
||||
icon: 'ma-icon-refresh',
|
||||
divided: true,
|
||||
onClick: () => {
|
||||
this.initData()
|
||||
}
|
||||
|
||||
@@ -41,10 +41,21 @@
|
||||
|
||||
.ma-tree-wrapper span {
|
||||
color: var(--toolbox-list-span-color);
|
||||
display: inline-block;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.ma-tree-wrapper .ma-icon-lock {
|
||||
color: var(--toolbox-list-label-color);
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.ma-tree-wrapper label {
|
||||
color: var(--toolbox-list-label-color);
|
||||
display: inline-block;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.ma-tree-wrapper .ma-tree-toolbar-search {
|
||||
|
||||
Reference in New Issue
Block a user