Kaynağa Gözat

增加接口层权限与数据校验

luoshi 2 yıl önce
ebeveyn
işleme
b65c8c0cea

+ 20 - 15
src/main/java/com/qmth/ops/api/controller/admin/AppController.java

@@ -3,7 +3,10 @@ package com.qmth.ops.api.controller.admin;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.qmth.ops.api.constants.OpsApiConstants;
 import com.qmth.ops.api.security.AdminSession;
-import com.qmth.ops.biz.domain.*;
+import com.qmth.ops.biz.domain.App;
+import com.qmth.ops.biz.domain.AppDTO;
+import com.qmth.ops.biz.domain.AppUser;
+import com.qmth.ops.biz.domain.Role;
 import com.qmth.ops.biz.query.AppQuery;
 import com.qmth.ops.biz.service.AppService;
 import com.qmth.ops.biz.service.AppUserService;
@@ -32,47 +35,49 @@ public class AppController {
 
     @PostMapping("/query")
     public IPage<AppDTO> query(@RequestAttribute AdminSession accessEntity, AppQuery query) {
-        User user = accessEntity.getUser();
-        if (user.getRole() == Role.DEV || user.getRole() == Role.TEST) {
-            query.setUserId(user.getId());
-        }
+        query.setUser(accessEntity.getUser());
         return appService.query(query);
     }
 
     @PostMapping("/list")
     public List<AppDTO> list(@RequestAttribute AdminSession accessEntity, AppQuery query) {
-        User user = accessEntity.getUser();
-        if (user.getRole() == Role.DEV || user.getRole() == Role.TEST) {
-            query.setUserId(user.getId());
-        }
+        query.setUser(accessEntity.getUser());
         return appService.list(query);
     }
 
     @PostMapping("/insert")
-    public AppDTO insert(App app) {
+    public AppDTO insert(@RequestAttribute AdminSession accessEntity, App app) {
+        accessEntity.validateRole(Role.ADMIN);
         appService.insert(app);
         return appService.findDTO(app.getId());
     }
 
     @PostMapping("/update")
-    public AppDTO update(App app) {
+    public AppDTO update(@RequestAttribute AdminSession accessEntity, App app) {
+        accessEntity.validateRole(Role.ADMIN);
         appService.update(app);
         return appService.findDTO(app.getId());
     }
 
-    @PostMapping("/version/master")
-    public AppDTO updateMasterVersion(@RequestParam Long id, @RequestParam Long versionId) {
+    @PostMapping("/master_version")
+    public AppDTO updateMasterVersion(@RequestAttribute AdminSession accessEntity, @RequestParam Long id,
+            @RequestParam Long versionId) {
+        accessEntity.validateRole(Role.ADMIN);
         appService.setMasterVersion(appService.getById(id), versionService.getById(versionId));
         return appService.findDTO(id);
     }
 
     @PostMapping("/user/bind")
-    public AppUser bindUser(@RequestParam Long id, @RequestParam Long userId) {
+    public AppUser bindUser(@RequestAttribute AdminSession accessEntity, @RequestParam Long id,
+            @RequestParam Long userId) {
+        accessEntity.validateRole(Role.ADMIN);
         return appUserService.insert(appService.getById(id), userService.getById(userId));
     }
 
     @PostMapping("/user/unbind")
-    public AppUser unbindUser(@RequestParam Long id, @RequestParam Long userId) {
+    public AppUser unbindUser(@RequestAttribute AdminSession accessEntity, @RequestParam Long id,
+            @RequestParam Long userId) {
+        accessEntity.validateRole(Role.ADMIN);
         appUserService.delete(appService.getById(id), userService.getById(userId));
         return new AppUser(id, userId);
     }

+ 26 - 9
src/main/java/com/qmth/ops/api/controller/admin/ConfigController.java

@@ -2,9 +2,11 @@ package com.qmth.ops.api.controller.admin;
 
 import com.qmth.ops.api.binder.FileFormatBinder;
 import com.qmth.ops.api.constants.OpsApiConstants;
+import com.qmth.ops.api.security.AdminSession;
 import com.qmth.ops.biz.domain.ConfigGroup;
 import com.qmth.ops.biz.domain.ConfigItem;
 import com.qmth.ops.biz.domain.FileFormat;
+import com.qmth.ops.biz.domain.Role;
 import com.qmth.ops.biz.service.*;
 import org.springframework.web.bind.WebDataBinder;
 import org.springframework.web.bind.annotation.*;
@@ -33,6 +35,9 @@ public class ConfigController {
     @Resource
     private VersionService versionService;
 
+    @Resource
+    private EnvService envService;
+
     @InitBinder
     public void initBinder(WebDataBinder dataBinder) {
         dataBinder.addCustomFormatter(new FileFormatBinder());
@@ -44,34 +49,46 @@ public class ConfigController {
     }
 
     @PostMapping("/baseline")
-    public List<ConfigItem> listBaseline(@RequestParam Long appId, @RequestParam Long versionId,
-            @RequestParam Long moduleId) {
+    public List<ConfigItem> listBaseline(@RequestAttribute AdminSession accessEntity, @RequestParam Long appId,
+            @RequestParam Long versionId, @RequestParam Long moduleId) {
+        accessEntity.validateApp(appService.getById(appId));
         return configService.listBaseline(appId, versionId, moduleId);
     }
 
     @PostMapping("/baseline/update")
-    public Object updateBaseline(@RequestParam Long appId, @RequestParam Long versionId, @RequestParam Long moduleId,
-            @RequestParam MultipartFile file, @RequestParam FileFormat extension,
-            @RequestParam(required = false) Long inheritVersionId) throws IOException {
+    public Object updateBaseline(@RequestAttribute AdminSession accessEntity, @RequestParam Long appId,
+            @RequestParam Long versionId, @RequestParam Long moduleId, @RequestParam MultipartFile file,
+            @RequestParam FileFormat extension, @RequestParam(required = false) Long inheritVersionId)
+            throws IOException {
+        accessEntity.validateRole(Role.DEV);
+        accessEntity.validateApp(appService.getById(appId));
         return configService.updateBaseline(appService.getById(appId), versionService.getById(versionId),
                 moduleService.getById(moduleId), file.getInputStream(), extension,
                 inheritVersionId != null ? versionService.getById(inheritVersionId) : null);
     }
 
     @PostMapping("/baseline/item/update")
-    public ConfigItem updateBaselineItem(ConfigItem item) {
+    public ConfigItem updateBaselineItem(@RequestAttribute AdminSession accessEntity, ConfigItem item) {
+        accessEntity.validateRole(Role.DEV);
+        accessEntity.validateApp(appService.getById(item.getAppId()));
         return configService.updateBaselineItem(item);
     }
 
     @PostMapping("/list")
-    public List<ConfigItem> listConfigItem(@RequestParam Long appId, @RequestParam Long versionId,
-            @RequestParam Long moduleId, @RequestParam Long envId) {
+    public List<ConfigItem> listConfigItem(@RequestAttribute AdminSession accessEntity, @RequestParam Long appId,
+            @RequestParam Long versionId, @RequestParam Long moduleId, @RequestParam Long envId) {
+        accessEntity.validateApp(appService.getById(appId));
+        accessEntity.validateEnv(envService.getById(envId).getType());
         return configService.listConfigItem(appId, versionId, moduleId, envId);
     }
 
     @PostMapping("/item/update")
-    public ConfigItem updateConfigItem(ConfigItem item) {
+    public ConfigItem updateConfigItem(@RequestAttribute AdminSession accessEntity, ConfigItem item) {
+        accessEntity.validateRole(Role.TEST, Role.OPS);
+        accessEntity.validateApp(appService.getById(item.getAppId()));
+        accessEntity.validateEnv(envService.getById(item.getEnvId()).getType());
         return configService.updateConfigItem(item);
     }
+
 }
 

+ 13 - 3
src/main/java/com/qmth/ops/api/controller/admin/EnvController.java

@@ -4,10 +4,14 @@ import com.qmth.boot.api.annotation.Aac;
 import com.qmth.boot.api.annotation.BOOL;
 import com.qmth.ops.api.constants.OpsApiConstants;
 import com.qmth.ops.api.dto.CodeNameBean;
+import com.qmth.ops.api.security.AdminSession;
 import com.qmth.ops.biz.domain.Env;
 import com.qmth.ops.biz.domain.EnvType;
+import com.qmth.ops.biz.domain.Role;
+import com.qmth.ops.biz.service.AppService;
 import com.qmth.ops.biz.service.EnvService;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -19,6 +23,9 @@ import java.util.List;
 @RequestMapping(OpsApiConstants.ADMIN_URI_PREFIX + "/env")
 public class EnvController {
 
+    @Resource
+    private AppService appService;
+
     @Resource
     private EnvService envService;
 
@@ -29,17 +36,20 @@ public class EnvController {
     }
 
     @PostMapping("/insert")
-    public Env insert(Env env) {
+    public Env insert(@RequestAttribute AdminSession accessEntity, Env env) {
+        accessEntity.validateRole(Role.ADMIN);
         return envService.insert(env);
     }
 
     @PostMapping("/update")
-    public Env update(Env env) {
+    public Env update(@RequestAttribute AdminSession accessEntity, Env env) {
+        accessEntity.validateRole(Role.ADMIN);
         return envService.update(env);
     }
 
     @PostMapping("/list")
-    public List<Env> list(Long appId) {
+    public List<Env> list(@RequestAttribute AdminSession accessEntity, Long appId) {
+        accessEntity.validateApp(appService.getById(appId));
         return envService.list(appId);
     }
 

+ 13 - 3
src/main/java/com/qmth/ops/api/controller/admin/ModuleController.java

@@ -1,10 +1,14 @@
 package com.qmth.ops.api.controller.admin;
 
 import com.qmth.ops.api.constants.OpsApiConstants;
+import com.qmth.ops.api.security.AdminSession;
 import com.qmth.ops.biz.domain.Module;
+import com.qmth.ops.biz.domain.Role;
 import com.qmth.ops.biz.query.ModuleQuery;
+import com.qmth.ops.biz.service.AppService;
 import com.qmth.ops.biz.service.ModuleService;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -15,21 +19,27 @@ import java.util.List;
 @RequestMapping(OpsApiConstants.ADMIN_URI_PREFIX + "/module")
 public class ModuleController {
 
+    @Resource
+    private AppService appService;
+
     @Resource
     private ModuleService moduleService;
 
     @PostMapping("/insert")
-    public Module insert(Module module) {
+    public Module insert(@RequestAttribute AdminSession accessEntity, Module module) {
+        accessEntity.validateRole(Role.ADMIN);
         return moduleService.insert(module);
     }
 
     @PostMapping("/update")
-    public Module update(Module module) {
+    public Module update(@RequestAttribute AdminSession accessEntity, Module module) {
+        accessEntity.validateRole(Role.ADMIN);
         return moduleService.update(module);
     }
 
     @PostMapping("/list")
-    public List<Module> list(ModuleQuery query) {
+    public List<Module> list(@RequestAttribute AdminSession accessEntity, ModuleQuery query) {
+        accessEntity.validateApp(appService.getById(query.getAppId()));
         return moduleService.list(query);
     }
 

+ 9 - 2
src/main/java/com/qmth/ops/api/controller/admin/UserController.java

@@ -6,10 +6,13 @@ import com.qmth.boot.core.exception.ParameterException;
 import com.qmth.ops.api.constants.OpsApiConstants;
 import com.qmth.ops.api.dto.LoginResult;
 import com.qmth.ops.api.security.AdminSession;
+import com.qmth.ops.biz.domain.Role;
 import com.qmth.ops.biz.domain.User;
 import com.qmth.ops.biz.query.UserQuery;
+import com.qmth.ops.biz.service.AppUserService;
 import com.qmth.ops.biz.service.UserService;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -22,6 +25,9 @@ public class UserController {
     @Resource
     private UserService userService;
 
+    @Resource
+    private AppUserService appUserService;
+
     @PostMapping("/login")
     @Aac(auth = BOOL.FALSE)
     public LoginResult login(User request) {
@@ -32,11 +38,12 @@ public class UserController {
         if (!user.buildPassword(request.getPassword()).equals(user.getPassword())) {
             throw new ParameterException("密码错误");
         }
-        return new AdminSession(user).getLoginResult();
+        return new AdminSession(user, appUserService).getLoginResult();
     }
 
     @PostMapping("/query")
-    public UserQuery query(UserQuery query) {
+    public UserQuery query(@RequestAttribute AdminSession accessEntity, UserQuery query) {
+        accessEntity.validateRole(Role.ADMIN);
         return userService.query(query);
     }
 }

+ 13 - 5
src/main/java/com/qmth/ops/api/controller/admin/VersionController.java

@@ -2,6 +2,8 @@ package com.qmth.ops.api.controller.admin;
 
 import com.qmth.ops.api.binder.VersionNumberBinder;
 import com.qmth.ops.api.constants.OpsApiConstants;
+import com.qmth.ops.api.security.AdminSession;
+import com.qmth.ops.biz.domain.Role;
 import com.qmth.ops.biz.domain.Version;
 import com.qmth.ops.biz.query.VersionQuery;
 import com.qmth.ops.biz.service.AppService;
@@ -28,17 +30,23 @@ public class VersionController {
     }
 
     @PostMapping("/insert")
-    public Version insert(@RequestParam Long appId, @RequestParam VersionNumber name) {
+    public Version insert(@RequestAttribute AdminSession accessEntity, @RequestParam Long appId,
+            @RequestParam VersionNumber name) {
+        accessEntity.validateRole(Role.DEV);
+        accessEntity.validateApp(appService.getById(appId));
         return versionService.insert(appService.getById(appId), name);
     }
 
+    @PostMapping("/update")
+    public Version list(@RequestAttribute AdminSession accessEntity, Version version) {
+        accessEntity.validateRole(Role.DEV);
+        accessEntity.validateApp(appService.getById(versionService.getById(version.getId()).getAppId()));
+        return versionService.update(version);
+    }
+
     @PostMapping("/query")
     public VersionQuery list(VersionQuery query) {
         return versionService.query(query);
     }
 
-    @PostMapping("/update")
-    public Version list(Version version) {
-        return versionService.update(version);
-    }
 }

+ 2 - 2
src/main/java/com/qmth/ops/api/controller/export/ConfigExportController.java

@@ -65,7 +65,7 @@ public class ConfigExportController {
     private void exportConfigFile(String appCode, String moduleCode, String envCode, String versionNumber,
             String exportSecret, FileFormat format, HttpServletResponse response) throws IOException {
         User user = userService.findByExportSecret(exportSecret);
-        if (user == null || user.getRole() != Role.OPS) {
+        if (user == null || !user.hasRole(Role.OPS)) {
             throw new UnauthorizedException("鉴权失败");
         }
         App app = appService.findByCode(appCode);
@@ -78,7 +78,7 @@ public class ConfigExportController {
         }
         Env env = envService.findByAppAndCode(app.getId(), envCode);
         if (env == null) {
-            throw new ParameterException("module.code不存在");
+            throw new ParameterException("env.code不存在");
         }
         Version version = versionNumber != null ?
                 versionService.findByAppAndNumber(app.getId(),

+ 3 - 3
src/main/java/com/qmth/ops/api/dto/LoginResult.java

@@ -4,17 +4,17 @@ import com.qmth.ops.biz.domain.Role;
 
 public class LoginResult {
 
-    private Role role;
+    private Role[] role;
 
     private String session;
 
     private String token;
 
-    public Role getRole() {
+    public Role[] getRole() {
         return role;
     }
 
-    public void setRole(Role role) {
+    public void setRole(Role[] role) {
         this.role = role;
     }
 

+ 5 - 1
src/main/java/com/qmth/ops/api/security/AdminAuthorizationService.java

@@ -5,6 +5,7 @@ import com.qmth.boot.core.security.service.AuthorizationService;
 import com.qmth.boot.tools.signature.SignatureType;
 import com.qmth.ops.api.constants.OpsApiConstants;
 import com.qmth.ops.biz.domain.User;
+import com.qmth.ops.biz.service.AppUserService;
 import com.qmth.ops.biz.service.UserService;
 
 import javax.annotation.Resource;
@@ -15,11 +16,14 @@ public class AdminAuthorizationService implements AuthorizationService<AdminSess
     @Resource
     private UserService userService;
 
+    @Resource
+    private AppUserService appUserService;
+
     @Override
     public AdminSession findByIdentity(String identity, SignatureType signatureType, String path) {
         User user = userService.getById(Long.parseLong(identity));
         if (user != null) {
-            return new AdminSession(user);
+            return new AdminSession(user, appUserService);
         }
         return null;
     }

+ 27 - 1
src/main/java/com/qmth/ops/api/security/AdminSession.java

@@ -1,15 +1,23 @@
 package com.qmth.ops.api.security;
 
+import com.qmth.boot.core.exception.UnauthorizedException;
 import com.qmth.boot.core.security.model.AccessEntity;
 import com.qmth.ops.api.dto.LoginResult;
+import com.qmth.ops.biz.domain.App;
+import com.qmth.ops.biz.domain.EnvType;
+import com.qmth.ops.biz.domain.Role;
 import com.qmth.ops.biz.domain.User;
+import com.qmth.ops.biz.service.AppUserService;
 
 public class AdminSession implements AccessEntity {
 
     private User user;
 
-    public AdminSession(User user) {
+    private AppUserService appUserService;
+
+    public AdminSession(User user, AppUserService appUserService) {
         this.user = user;
+        this.appUserService = appUserService;
     }
 
     public LoginResult getLoginResult() {
@@ -24,6 +32,24 @@ public class AdminSession implements AccessEntity {
         return user;
     }
 
+    public void validateRole(Role... roles) {
+        if (!user.hasRole(roles)) {
+            throw new UnauthorizedException("没有操作权限");
+        }
+    }
+
+    public void validateApp(App app) {
+        if (!user.hasRole(Role.OPS, Role.ADMIN) && !appUserService.exist(app, user)) {
+            throw new UnauthorizedException("没有应用操作权限");
+        }
+    }
+
+    public void validateEnv(EnvType envType) {
+        if (!user.hasRole(envType.getRole())) {
+            throw new UnauthorizedException("没有环境操作权限");
+        }
+    }
+
     @Override
     public String getIdentity() {
         return user.getId().toString();

+ 9 - 2
src/main/java/com/qmth/ops/biz/domain/EnvType.java

@@ -2,18 +2,25 @@ package com.qmth.ops.biz.domain;
 
 public enum EnvType {
 
-    TEST("测试环境"), PROD("生产环境");
+    TEST("测试环境", Role.TEST, Role.OPS, Role.ADMIN), PROD("生产环境", Role.OPS, Role.ADMIN);
 
     private String name;
 
-    private EnvType(String name) {
+    private Role[] role;
+
+    private EnvType(String name, Role... role) {
         this.name = name;
+        this.role = role;
     }
 
     public String getName() {
         return name;
     }
 
+    public Role[] getRole() {
+        return role;
+    }
+
     public String getCode() {
         return toString().toUpperCase();
     }

+ 16 - 3
src/main/java/com/qmth/ops/biz/domain/User.java

@@ -1,9 +1,12 @@
 package com.qmth.ops.biz.domain;
 
 import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.qmth.boot.tools.models.ByteArray;
+import org.apache.commons.lang3.ArrayUtils;
 
 import java.io.Serializable;
 
@@ -21,7 +24,8 @@ public class User implements Serializable {
 
     private String password;
 
-    private Role role;
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private Role[] role;
 
     private String exportSecret;
 
@@ -61,11 +65,11 @@ public class User implements Serializable {
         this.name = name;
     }
 
-    public Role getRole() {
+    public Role[] getRole() {
         return role;
     }
 
-    public void setRole(Role role) {
+    public void setRole(Role[] role) {
         this.role = role;
     }
 
@@ -102,4 +106,13 @@ public class User implements Serializable {
         return ByteArray.fromString(loginName + createTime).toBase64();
     }
 
+    public boolean hasRole(Role... roles) {
+        for (Role role : roles) {
+            if (ArrayUtils.contains(this.role, role)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
 }

+ 8 - 0
src/main/java/com/qmth/ops/biz/query/AppQuery.java

@@ -2,6 +2,8 @@ package com.qmth.ops.biz.query;
 
 import com.qmth.boot.mybatis.query.BaseQuery;
 import com.qmth.ops.biz.domain.App;
+import com.qmth.ops.biz.domain.Role;
+import com.qmth.ops.biz.domain.User;
 
 public class AppQuery extends BaseQuery<App> {
 
@@ -47,4 +49,10 @@ public class AppQuery extends BaseQuery<App> {
         this.userId = userId;
     }
 
+    public void setUser(User user) {
+        if (!user.hasRole(Role.OPS, Role.ADMIN)) {
+            setUserId(user.getId());
+        }
+    }
+
 }

+ 1 - 1
src/main/java/com/qmth/ops/biz/query/UserQuery.java

@@ -40,7 +40,7 @@ public class UserQuery extends BaseQuery<User> {
     }
 
     public LambdaQueryWrapper<User> build() {
-        return new LambdaQueryWrapper<User>().eq(id != null, User::getId, id).eq(role != null, User::getRole, role)
+        return new LambdaQueryWrapper<User>().eq(id != null, User::getId, id).in(role != null, User::getRole, role)
                 .likeRight(loginNameStartWith != null, User::getLoginName, loginNameStartWith);
     }
 }

+ 1 - 1
src/main/resources/script/init.sql

@@ -76,7 +76,7 @@ CREATE TABLE `user`
     `login_name`    varchar(64)         NOT NULL DEFAULT '',
     `name`          varchar(64)         NOT NULL DEFAULT '',
     `password`      varchar(64)         NOT NULL DEFAULT '',
-    `role`          varchar(16)         NOT NULL DEFAULT '',
+    `role`          varchar(64)         NOT NULL DEFAULT '',
     `export_secret` varchar(64)         NOT NULL DEFAULT '',
     `create_time`   bigint(20)          NOT NULL,
     `update_time`   bigint(20)          NOT NULL,