权限校验

This commit is contained in:
mxd
2022-01-02 20:22:15 +08:00
parent ac5238375b
commit 14dcefb6b9
11 changed files with 95 additions and 31 deletions

View File

@@ -103,7 +103,11 @@ public class WebSocketSessionManager {
public static void sendBySession(MagicConsoleSession session, String content) {
try {
session.getWebSocketSession().sendMessage(new TextMessage(content));
if(session != null){
synchronized (session.getId()){
session.getWebSocketSession().sendMessage(new TextMessage(content));
}
}
} catch (IOException e) {
logger.error("发送WebSocket消息失败", e);
}

View File

@@ -80,7 +80,7 @@ public class MagicController implements JsonCodeConstants {
.stream()
.flatMap(it -> it.flat().stream())
.filter(it -> !Constants.ROOT_ID.equals(it.getId()))
.filter(it -> allowVisit(request, authorization))
.filter(it -> allowVisit(request, authorization, it))
.flatMap(it -> service.listFiles(it.getId()).stream())
.filter(it -> allowVisit(request, authorization, it))
.filter(it -> Objects.nonNull(it.getScript()))

View File

@@ -27,7 +27,8 @@ public class MagicResourceController extends MagicController implements MagicExc
@PostMapping("/resource/folder/save")
@ResponseBody
public JsonBean<String> saveFolder(@RequestBody Group group) {
public JsonBean<String> saveFolder(@RequestBody Group group, HttpServletRequest request) {
isTrue(allowVisit(request, Authorization.SAVE, group), PERMISSION_INVALID);
if (service.saveGroup(group)) {
return new JsonBean<>(group.getId());
}
@@ -36,13 +37,29 @@ public class MagicResourceController extends MagicController implements MagicExc
@PostMapping("/resource/folder/copy")
@ResponseBody
public JsonBean<String> saveFolder(String src, String target) {
public JsonBean<String> saveFolder(String src, String target, HttpServletRequest request) {
Group srcGroup = service.getGroup(src);
notNull(srcGroup, GROUP_NOT_FOUND);
isTrue(allowVisit(request, Authorization.VIEW, srcGroup), PERMISSION_INVALID);
Group targetGroup = srcGroup.copy();
targetGroup.setId(null);
targetGroup.setParentId(target);
targetGroup.setType(srcGroup.getType());
isTrue(allowVisit(request, Authorization.SAVE, targetGroup), PERMISSION_INVALID);
return new JsonBean<>(service.copyGroup(src, target));
}
@PostMapping("/resource/delete")
@ResponseBody
public JsonBean<Boolean> delete(String id, HttpServletRequest request) {
Group group = service.getGroup(id);
if(group == null){
MagicEntity entity = service.file(id);
notNull(entity, FILE_NOT_FOUND);
isTrue(allowVisit(request, Authorization.DELETE, entity), PERMISSION_INVALID);
} else {
isTrue(allowVisit(request, Authorization.DELETE, group), PERMISSION_INVALID);
}
return new JsonBean<>(service.delete(id));
}
@@ -80,7 +97,19 @@ public class MagicResourceController extends MagicController implements MagicExc
@PostMapping("/resource/move")
@ResponseBody
public JsonBean<Boolean> move(String src, String groupId) {
public JsonBean<Boolean> move(String src, String groupId, HttpServletRequest request) {
Group group = service.getGroup(src);
if(group == null){
MagicEntity entity = service.file(src);
notNull(entity, FILE_NOT_FOUND);
entity = entity.copy();
entity.setGroupId(groupId);
isTrue(allowVisit(request, Authorization.SAVE, entity), PERMISSION_INVALID);
} else {
group = group.copy();
group.setParentId(groupId);
isTrue(allowVisit(request, Authorization.DELETE, group), PERMISSION_INVALID);
}
return new JsonBean<>(service.move(src, groupId));
}
@@ -88,6 +117,7 @@ public class MagicResourceController extends MagicController implements MagicExc
@ResponseBody
public JsonBean<Boolean> lock(String id, HttpServletRequest request) {
MagicEntity entity = service.file(id);
notNull(entity, FILE_NOT_FOUND);
isTrue(allowVisit(request, Authorization.LOCK, entity), PERMISSION_INVALID);
return new JsonBean<>(service.lock(id));
}
@@ -96,27 +126,32 @@ public class MagicResourceController extends MagicController implements MagicExc
@ResponseBody
public JsonBean<Boolean> unlock(String id, HttpServletRequest request) {
MagicEntity entity = service.file(id);
notNull(entity, FILE_NOT_FOUND);
isTrue(allowVisit(request, Authorization.UNLOCK, entity), PERMISSION_INVALID);
return new JsonBean<>(service.unlock(id));
}
@GetMapping("/resource")
@ResponseBody
public JsonBean<Map<String, TreeNode<Attributes<Object>>>> resources() {
public JsonBean<Map<String, TreeNode<Attributes<Object>>>> resources(HttpServletRequest request) {
Map<String, TreeNode<Group>> tree = service.tree();
Map<String, TreeNode<Attributes<Object>>> result = new HashMap<>();
tree.forEach((key, value) -> result.put(key, process(value)));
tree.forEach((key, value) -> result.put(key, process(value, request)));
return new JsonBean<>(result);
}
private TreeNode<Attributes<Object>> process(TreeNode<Group> groupNode) {
private TreeNode<Attributes<Object>> process(TreeNode<Group> groupNode, HttpServletRequest request) {
TreeNode<Attributes<Object>> value = new TreeNode<>();
value.setNode(groupNode.getNode());
groupNode.getChildren().stream().map(this::process).forEach(value::addChild);
groupNode.getChildren().stream()
.filter(it -> allowVisit(request, Authorization.VIEW, it.getNode()))
.map(it -> process(it, request))
.forEach(value::addChild);
if (!Constants.ROOT_ID.equals(groupNode.getNode().getId())) {
service
.listFiles(groupNode.getNode().getId())
.stream()
.filter(it -> allowVisit(request, Authorization.VIEW, it))
.map(MagicEntity::simple)
.map((Function<MagicEntity, TreeNode<Attributes<Object>>>) TreeNode::new)
.forEach(value::addChild);

View File

@@ -229,7 +229,8 @@ public class MagicWorkbenchController extends MagicController implements MagicEx
@RequestMapping("/download")
@Valid(authorization = Authorization.DOWNLOAD)
@ResponseBody
public ResponseEntity<?> download(String groupId, @RequestBody(required = false) List<SelectedResource> resources) throws IOException {
public ResponseEntity<?> download(String groupId, @RequestBody(required = false) List<SelectedResource> resources, HttpServletRequest request) throws IOException {
isTrue(allowVisit(request, Authorization.DOWNLOAD), PERMISSION_INVALID);
ByteArrayOutputStream os = new ByteArrayOutputStream();
magicAPIService.download(groupId, resources, os);
if (StringUtils.isBlank(groupId)) {
@@ -242,8 +243,9 @@ public class MagicWorkbenchController extends MagicController implements MagicEx
@RequestMapping("/upload")
@Valid(readonly = false, authorization = Authorization.UPLOAD)
@ResponseBody
public JsonBean<Boolean> upload(MultipartFile file, String mode) throws IOException {
public JsonBean<Boolean> upload(MultipartFile file, String mode, HttpServletRequest request) throws IOException {
notNull(file, FILE_IS_REQUIRED);
isTrue(allowVisit(request, Authorization.UPLOAD), PERMISSION_INVALID);
return new JsonBean<>(magicAPIService.upload(file.getInputStream(), mode));
}
@@ -251,7 +253,9 @@ public class MagicWorkbenchController extends MagicController implements MagicEx
@ResponseBody
@Valid(authorization = Authorization.PUSH)
public JsonBean<?> push(@RequestHeader("magic-push-target") String target, @RequestHeader("magic-push-secret-key") String secretKey,
@RequestHeader("magic-push-mode") String mode, @RequestBody List<SelectedResource> resources) {
@RequestHeader("magic-push-mode") String mode, @RequestBody List<SelectedResource> resources,
HttpServletRequest request) {
isTrue(allowVisit(request, Authorization.PUSH), PERMISSION_INVALID);
return magicAPIService.push(target, secretKey, mode, resources);
}

View File

@@ -95,6 +95,19 @@ public class Group extends Attributes<Object> {
this.options = options;
}
public Group copy(){
Group group = new Group();
group.setId(this.id);
group.setName(this.name);
group.setType(this.type);
group.setPaths(this.paths);
group.setPath(this.path);
group.setProperties(this.properties);
group.setParentId(this.parentId);
group.setOptions(this.options);
return group;
}
@Override
public boolean equals(Object o) {
if (this == o) {

View File

@@ -97,8 +97,6 @@ public interface JsonCodeConstants {
JsonCode FILE_SAVE_FAILURE = new JsonCode(0, "保存失败,同一组下分组名称不能重复且不能包含特殊字符。");
JsonCode GROUP_CONFLICT = new JsonCode(-20, "修改分组后,名称或路径会有冲突,请检查!");
JsonCode PARAMETER_INVALID = new JsonCode(0, "参数验证失败");
JsonCode HEADER_INVALID = new JsonCode(0, "header验证失败");
@@ -109,25 +107,10 @@ public interface JsonCodeConstants {
JsonCode FILE_IS_REQUIRED = new JsonCode(0, "请上传文件");
JsonCode SIGN_IS_INVALID = new JsonCode(0, "签名验证失败");
JsonCode UPLOAD_PATH_CONFLICT = new JsonCode(0, "上传后%s路径会有冲突请检查");
JsonCode SIGN_IS_INVALID = new JsonCode(0, "签名验证失败,请检查秘钥是否正确");
JsonCode API_NOT_FOUND = new JsonCode(1001, "api not found");
JsonCode FUNCTION_NOT_FOUND = new JsonCode(1002, "function not found");
JsonCode WEBSOCKET_NOT_FOUND = new JsonCode(1003, "websocket not found");
JsonCode DATASOURCE_KEY_REQUIRED = new JsonCode(0, "数据源Key不能为空");
JsonCode DATASOURCE_KEY_EXISTS = new JsonCode(0, "数据源%s已存在或名称重复");
JsonCode DATASOURCE_TYPE_NOT_FOUND = new JsonCode(0, "%s not found");
JsonCode DATASOURCE_NOT_FOUND = new JsonCode(0, "找不到对应的数据源");
JsonCode DATASOURCE_TYPE_NOT_SET = new JsonCode(0, "请设置数据源类型");
default void notNull(Object value, JsonCode jsonCode) {
if (value == null) {
throw new InvalidArgumentException(jsonCode);

View File

@@ -93,6 +93,8 @@ public interface MagicResourceService {
<T extends MagicEntity> T file(String id);
Group getGroup(String id);
void export(String groupId, List<SelectedResource> resources, OutputStream os) throws IOException;
boolean lock(String id);

View File

@@ -1,5 +1,6 @@
package org.ssssssss.magicapi.service.impl;
import org.ssssssss.magicapi.model.JsonCodeConstants;
import org.ssssssss.magicapi.model.PathMagicEntity;
import org.ssssssss.magicapi.provider.MagicResourceStorage;
import org.ssssssss.magicapi.service.MagicResourceService;
@@ -7,7 +8,7 @@ import org.ssssssss.magicapi.utils.PathUtils;
import java.util.Objects;
public abstract class AbstractPathMagicResourceStorage<T extends PathMagicEntity> implements MagicResourceStorage<T> {
public abstract class AbstractPathMagicResourceStorage<T extends PathMagicEntity> implements MagicResourceStorage<T>, JsonCodeConstants {
protected MagicResourceService magicResourceService;
@@ -37,4 +38,10 @@ public abstract class AbstractPathMagicResourceStorage<T extends PathMagicEntity
String fullGroupPath = magicResourceService.getGroupPath(entity.getGroupId());
return PathUtils.replaceSlash(String.format("/%s/%s(/%s/%s)", fullGroupName, entity.getName(), fullGroupPath, entity.getPath()));
}
@Override
public void validate(T entity) {
notBlank(entity.getPath(), REQUEST_PATH_REQUIRED);
notBlank(entity.getScript(), SCRIPT_REQUIRED);
}
}

View File

@@ -19,4 +19,9 @@ public class ApiInfoMagicResourceStorage extends AbstractPathMagicResourceStorag
return info.getMethod().toUpperCase() + ":" + buildMappingKey(info, magicResourceService.getGroupPath(info.getGroupId()));
}
@Override
public void validate(ApiInfo entity) {
notBlank(entity.getMethod(), REQUEST_METHOD_REQUIRED);
super.validate(entity);
}
}

View File

@@ -560,6 +560,11 @@ public class DefaultMagicResourceService implements MagicResourceService, JsonCo
return (T) fileCache.get(id);
}
@Override
public Group getGroup(String id) {
return groupCache.get(id);
}
@Override
public void export(String groupId, List<SelectedResource> resources, OutputStream os) throws IOException {
if (StringUtils.isNotBlank(groupId)) {

View File

@@ -1,5 +1,6 @@
package org.ssssssss.magicapi.service.impl;
import org.ssssssss.magicapi.model.ApiInfo;
import org.ssssssss.magicapi.model.FunctionInfo;
public class FunctionInfoMagicResourceStorage extends AbstractPathMagicResourceStorage<FunctionInfo> {
@@ -18,4 +19,9 @@ public class FunctionInfoMagicResourceStorage extends AbstractPathMagicResourceS
public String buildMappingKey(FunctionInfo info) {
return buildMappingKey(info, magicResourceService.getGroupPath(info.getGroupId()));
}
@Override
public void validate(FunctionInfo entity) {
notBlank(entity.getPath(), FUNCTION_PATH_REQUIRED);
}
}