提交 83239fc6 authored 作者: 黄承天's avatar 黄承天

feat(user): 完成了权限控制部分

上级 d9f50912
package org.matrix.local.config.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.matrix.local.entity.vo.UserInfo;
import org.matrix.local.enums.Authority;
import org.matrix.local.enums.Role;
import org.matrix.local.service.impl.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.util.*;
@Slf4j
@Aspect
@Component
public class AuthorityAOP {
@Autowired
private UserService userService;
@Before("@annotation(org.matrix.local.config.aop.Authorize)")
public void authorize(JoinPoint joinPoint) {
Authorize authorize = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(Authorize.class);
Authority value = authorize.value();
UserInfo userInfo = userService.findNow();
Boolean isAdmin = userService.isAdmin(userInfo);
if (!isAdmin) {
if (Authority.ADMIN.equals(value)) {
throw new RuntimeException("当前用户不具备相应权限");
} else {
Long projectId = Long.valueOf(Optional.of((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
.map(ServletRequestAttributes::getRequest)
.map(request -> request.getParameter("projectId"))
.orElseThrow(() -> new RuntimeException("请在请求参数中附带projectId")));
String role = userService.findRole(userInfo.getId(), projectId);
boolean match = Role.getAuthorities(role).stream().anyMatch(authority -> Objects.equals(authority, value));
if (!match) {
throw new RuntimeException("当前用户不具备相应权限");
}
}
}
}
}
package org.matrix.local.config.aop;
import org.matrix.local.enums.Authority;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Authorize {
Authority value();
}
......@@ -28,6 +28,7 @@ public class Project {
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
@ApiModelProperty("主键id")
private Long id;
......
......@@ -28,6 +28,7 @@ public class User {
/**
* 主键id
*/
@TableId(type = IdType.AUTO)
@ApiModelProperty("主键id")
private Long id;
......@@ -40,4 +41,7 @@ public class User {
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("用户角色")
private String role;
}
package org.matrix.local.entity.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserBindInfo {
@ApiModelProperty("用户id")
private Long userId;
@ApiModelProperty("用户角色")
private String role;
}
package org.matrix.local.entity.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
......@@ -31,6 +32,10 @@ public class UserInfo {
@ApiModelProperty("密码")
private String password;
@JsonIgnore
@ApiModelProperty("用户角色")
private String role;
@ApiModelProperty("与该用户相关的项目")
private List<Project> projects;
......
package org.matrix.local.enums;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
......@@ -18,10 +19,13 @@ public enum Authority {
READ("read","查看数据以及配置"),
EXECUTE("execute","执行测试"),
EDIT("edit","编辑数据以及配置"),
MANAGE("manage","管理用户项目角色");
MANAGE("manage","项目的管理权限"),
ADMIN("admin","管理员权限");
@ApiModelProperty("权限名称")
private final String name;
@ApiModelProperty("权限描述")
private final String description;
}
......@@ -37,4 +37,5 @@ public enum ConfigType {
* 描述
*/
private final String des;
}
......@@ -2,10 +2,12 @@ package org.matrix.local.enums;
import com.google.common.collect.Lists;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
import static org.matrix.local.enums.Authority.*;
......@@ -18,14 +20,32 @@ import static org.matrix.local.enums.Authority.*;
@ApiModel("用户角色")
public enum Role {
NORMAL("normal", "普通用户", Lists.newArrayList(READ, EXECUTE)),
SENIOR("senior", "高级用户", Lists.newArrayList(READ, EXECUTE, EDIT)),
ADMIN("admin", "管理员", Lists.newArrayList(READ, EXECUTE, EDIT, MANAGE));
NORMAL("normal", "普通成员", Lists.newArrayList(READ, EXECUTE)),
SENIOR("senior", "高级成员", Lists.newArrayList(READ, EXECUTE, EDIT)),
CREATOR("creator", "创建者", Lists.newArrayList(READ, EXECUTE, EDIT, MANAGE)),
ADMIN("admin", "管理员", Lists.newArrayList(READ, EXECUTE, EDIT, MANAGE, Authority.ADMIN));
@ApiModelProperty("角色名称")
private final String name;
@ApiModelProperty("角色描述")
private final String description;
@ApiModelProperty("角色拥有的权限")
private final List<Authority> authorities;
public static List<Authority> getAuthorities(String role) {
for (Role value : Role.values()) {
if (Objects.equals(role, value.getName())) {
return value.getAuthorities();
}
}
return Collections.emptyList();
}
public static Set<String> roles() {
return Arrays.stream(Role.values())
.map(Role::getName)
.collect(Collectors.toSet());
}
}
......@@ -4,8 +4,11 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.matrix.local.entity.Project;
import org.matrix.local.entity.relation.UserProject;
import org.matrix.local.enums.Role;
import org.matrix.local.mapper.ProjectMapper;
import org.matrix.local.mapper.UserMapper;
import org.matrix.local.mapper.relation.UserProjectMapper;
import org.matrix.local.service.IProjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -13,6 +16,8 @@ import org.springframework.stereotype.Service;
import java.util.Optional;
import static java.lang.String.format;
import static java.util.Objects.nonNull;
import static org.matrix.local.enums.Role.*;
/**
......@@ -26,6 +31,8 @@ public class ProjectService extends ServiceImpl<ProjectMapper, Project> implemen
private UserMapper userMapper;
@Autowired
private ProjectMapper projectMapper;
@Autowired
private UserProjectMapper userProjectMapper;
/**
* 新增项目
......@@ -33,21 +40,23 @@ public class ProjectService extends ServiceImpl<ProjectMapper, Project> implemen
* 项目名唯一 不可重复
*
* @param project 项目信息对象
* @return 保存的项目id
*/
public void create(Project project) {
public Long create(Project project) {
//检查是否附带了id
Optional.of(project).map(Project::getId)
.ifPresent(id -> {
throw new RuntimeException("新增数据不可附带id");
});
//检查同名项目是否已存在
Optional.of(projectMapper.selectOne(Wrappers.<Project>lambdaQuery().eq(Project::getName, project.getName())))
Optional.ofNullable(projectMapper.selectOne(Wrappers.<Project>lambdaQuery().eq(Project::getName, project.getName())))
.ifPresent(id -> {
throw new RuntimeException(format("该项目名已存在 : %s", project.getName()));
});
//保存
projectMapper.insert(project);
log.info("[项目] 新增项目 : {}", project.getName());
return project.getId();
}
/**
......@@ -60,10 +69,10 @@ public class ProjectService extends ServiceImpl<ProjectMapper, Project> implemen
*/
public void update(Project project) {
//检查id
Long id = Optional.of(project).map(Project::getId)
Long id = Optional.ofNullable(project).map(Project::getId)
.orElseThrow(() -> new RuntimeException("修改数据必须指定id"));
//检查原数据是否存在
Project before = Optional.of(projectMapper.selectById(id))
Project before = Optional.ofNullable(projectMapper.selectById(id))
.orElseThrow(() -> new RuntimeException(format("id为 %s 的项目数据不存在", id)));
//检查同名项目是否已存在
Optional.of(projectMapper.selectOne(Wrappers.<Project>lambdaQuery().eq(Project::getName, project.getName())))
......@@ -82,11 +91,55 @@ public class ProjectService extends ServiceImpl<ProjectMapper, Project> implemen
*/
public void delete(Long id) {
//检查项目是否存在
Project project = Optional.of(projectMapper.selectById(id))
Project project = Optional.ofNullable(projectMapper.selectById(id))
.orElseThrow(() -> new RuntimeException(format("id为 %s 的项目数据不存在", id)));
//保存
userMapper.deleteById(id);
log.info("[项目] 删除项目 : {}", project.getName());
}
/**
* 指定用户在项目中的角色
* 把用户绑定到项目中
* 如果绑定关系已存在 则更新其角色
*
* @param projectId 项目id
* @param userId 用户id
* @param role 用户在项目中的角色
*/
public void bindUserRole(Long projectId, Long userId, String role) {
if (Role.roles().contains(role)) {
if (CREATOR.getName().equals(role) || ADMIN.getName().equals(role)) {
throw new RuntimeException("该角色无法手动设置");
}
UserProject userProject = userProjectMapper.selectOne(Wrappers.<UserProject>lambdaQuery().eq(UserProject::getUserId, userId).eq(UserProject::getProjectId, projectId));
if (nonNull(userProject)) {
userProject.setRole(role);
userProjectMapper.updateById(userProject);
} else {
userProjectMapper.insert(new UserProject()
.setUserId(userId)
.setProjectId(projectId)
.setRole(role));
}
} else {
throw new RuntimeException("不符合约定的角色");
}
}
/**
* 把用户绑定为项目创建者
*
* @param projectId 项目id
* @param userId 用户id
*/
public void bindUserCreator(Long projectId, Long userId) {
String role = CREATOR.getName();
UserProject userProject = new UserProject()
.setUserId(userId)
.setProjectId(projectId)
.setRole(role);
userProjectMapper.insert(userProject);
}
}
......@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.SneakyThrows;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.bson.Document;
import org.matrix.local.entity.Project;
import org.matrix.local.entity.User;
......@@ -50,7 +51,6 @@ public class UserService extends ServiceImpl<UserMapper, User> implements IUserS
@Autowired
private MongoTemplate mongoTemplate;
/**
* 新增用户
* 新增数据不可附带id
......@@ -60,12 +60,12 @@ public class UserService extends ServiceImpl<UserMapper, User> implements IUserS
*/
public void create(User user) {
//检查是否附带了id
Optional.of(user).map(User::getId)
Optional.ofNullable(user).map(User::getId)
.ifPresent(id -> {
throw new RuntimeException("新增数据不可附带id");
});
//检查该账号是否已存在
Optional.of(userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getAccount, user.getAccount())))
Optional.ofNullable(userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getAccount, user.getAccount())))
.ifPresent(id -> {
throw new RuntimeException(format("该账号已存在 : %s", user.getAccount()));
});
......@@ -85,10 +85,10 @@ public class UserService extends ServiceImpl<UserMapper, User> implements IUserS
*/
public void update(User user) {
//检查id
Long id = Optional.of(user).map(User::getId)
Long id = Optional.ofNullable(user).map(User::getId)
.orElseThrow(() -> new RuntimeException("修改数据必须指定id"));
//检查原数据是否存在
User before = Optional.of(userMapper.selectById(id))
User before = Optional.ofNullable(userMapper.selectById(id))
.orElseThrow(() -> new RuntimeException(format("id为 %s 的用户数据不存在", id)));
//保存
String account = before.getAccount();
......@@ -103,7 +103,7 @@ public class UserService extends ServiceImpl<UserMapper, User> implements IUserS
*/
public void delete(Long id) {
//检查账号是否存在
User user = Optional.of(userMapper.selectById(id))
User user = Optional.ofNullable(userMapper.selectById(id))
.orElseThrow(() -> new RuntimeException(format("id为 %s 的用户数据不存在", id)));
//保存
userMapper.deleteById(id);
......@@ -247,10 +247,48 @@ public class UserService extends ServiceImpl<UserMapper, User> implements IUserS
sessionMap.remove(sessionId);
}
/**
* 指定用户id
* 再根据项目id查出当前登录用户在该项目中的角色
*
* @param userId 用户id
* @param projectId 项目id
* @return 角色
*/
public String findRole(Long userId, Long projectId) {
UserProject userProject = userProjectMapper.selectOne(Wrappers.<UserProject>lambdaQuery().eq(UserProject::getUserId, userId).eq(UserProject::getProjectId, projectId));
return Optional.ofNullable(userProject)
.map(UserProject::getRole)
.orElse(Strings.EMPTY);
}
/**
* 根据项目id查出当前登录用户在该项目中的角色
*
* @param projectId 项目id
* @return 角色
*/
public String findRole(Long projectId) {
Long userId = findNow().getId();
return findRole(userId, projectId);
}
/**
* 判断用户是否是管理员账号
*
* @param userInfo 用户信息
* @return bool结果
*/
public Boolean isAdmin(UserInfo userInfo) {
//TODO
return false;
}
//-------------------------------private--------------------------------
private UserInfo userInfo(User user) {
List<Project> projects = userProjectMapper.selectList(Wrappers.<UserProject>lambdaQuery().eq(UserProject::getUserId, user.getId())).stream()
List<Project> projects = userProjectMapper.selectList(Wrappers.<UserProject>lambdaQuery()
.eq(UserProject::getUserId, user.getId())).stream()
.map(UserProject::getProjectId)
.map(projectMapper::selectById)
.filter(Objects::nonNull)
......@@ -260,6 +298,7 @@ public class UserService extends ServiceImpl<UserMapper, User> implements IUserS
user.getName(),
user.getAccount(),
user.getPassword(),
user.getRole(),
projects
);
}
......
package org.matrix.remote.service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.logging.log4j.util.Strings;
import org.matrix.actuators.datasource.IDataSourceService;
import org.matrix.local.entity.Project;
import org.matrix.local.entity.User;
......@@ -36,7 +37,7 @@ public class TransHelper {
private IDataSourceService dataSourceService;
public User user(ZtUser ztUser) {
return new User(Long.valueOf(ztUser.getId()), ztUser.getRealname(), ztUser.getAccount(), ztUser.getPassword());
return new User(Long.valueOf(ztUser.getId()), ztUser.getRealname(), ztUser.getAccount(), ztUser.getPassword(), Role.NORMAL.getName());
}
public Project project(ZtProject ztProject) {
......@@ -54,7 +55,7 @@ public class TransHelper {
.map(id -> ztProjectMapper.selectById(id))
.filter(ztProject -> Objects.equals("0", ztProject.getDeleted()))
.map(this::findProjectId)
.map(projectId -> new UserProject(null, userId, projectId, Role.SENIOR.getName()))
.map(projectId -> new UserProject(null, userId, projectId, Strings.EMPTY))
.collect(Collectors.toList());
} else {
return new ArrayList<>();
......
......@@ -27,7 +27,8 @@ class KtZentaoApplicationTests {
@Test
void test() {
userService.save(new User(null,"none","none","none"));
userService.logout("123");
// userService.create(new User(null,"none","none","none"));
}
......
......@@ -3,12 +3,21 @@ package org.matrix.autotest.controller;
import com.google.common.collect.ImmutableMap;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.matrix.database.vo.CommonResult;
import org.matrix.database.vo.CommonResultObj;
import org.matrix.local.config.aop.Authorize;
import org.matrix.local.entity.Project;
import org.matrix.local.entity.vo.UserBindInfo;
import org.matrix.local.entity.vo.UserInfo;
import org.matrix.local.enums.Authority;
import org.matrix.local.enums.Role;
import org.matrix.local.service.impl.ProjectService;
import org.matrix.local.service.impl.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
......@@ -25,16 +34,29 @@ import java.util.Map;
@Api(tags = "对项目project的基本操作")
public class ProjectController {
@Autowired
private UserService userService;
@Autowired
private ProjectService projectService;
@ApiOperation(value = "新增项目", notes = "新增数据不可附带id;账号名为唯一值不可出现重复;")
@ApiOperation(value = "查询当前用户的相关项目")
@GetMapping
public ResponseEntity<CommonResultObj<List<Project>>> projects() {
UserInfo userInfo = userService.findNow();
return CommonResult.success(userInfo.getProjects(), "查询成功");
}
@ApiOperation(value = "新增项目", notes = "新增数据不可附带id;账号名为唯一值不可出现重复;当前用户将被设置为项目的创建者")
@PostMapping
public ResponseEntity<Map<String, String>> create(@RequestBody Project project) {
projectService.create(project);
Long projectId = projectService.create(project);
UserInfo userInfo = userService.findNow();
Long userId = userInfo.getId();
projectService.bindUserCreator(projectId, userId);
return ResponseEntity.ok(ImmutableMap.of("message", "操作成功"));
}
@Authorize(Authority.MANAGE)
@ApiOperation(value = "修改项目", notes = "根据id修改项目;修改数据必须附带id且指定id的原数据必须存在;项目名为唯一值不可出现重复;")
@PutMapping
public ResponseEntity<Map<String, String>> update(@RequestBody Project project) {
......@@ -42,6 +64,15 @@ public class ProjectController {
return ResponseEntity.ok(ImmutableMap.of("message", "操作成功"));
}
@Authorize(Authority.MANAGE)
@ApiOperation(value = "保存项目绑定的用户角色", notes = "可多个;如果绑定关系已存在则更新其角色;")
@PutMapping("/{projectId}")
public ResponseEntity<Map<String, String>> saveUserRole(@PathVariable Long projectId, @RequestBody List<UserBindInfo> userBindInfos) {
userBindInfos.forEach(userBindInfo -> projectService.bindUserRole(projectId, userBindInfo.getUserId(), userBindInfo.getRole()));
return ResponseEntity.ok(ImmutableMap.of("message", "操作成功"));
}
@Authorize(Authority.MANAGE)
@ApiOperation(value = "删除项目", notes = "根据id删除项目")
@DeleteMapping("/{id}")
public ResponseEntity<Map<String, String>> delete(@PathVariable Long id) {
......@@ -49,4 +80,5 @@ public class ProjectController {
return ResponseEntity.ok(ImmutableMap.of("message", "操作成功"));
}
}
......@@ -3,9 +3,12 @@ package org.matrix.autotest.controller;
import com.google.common.collect.ImmutableMap;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.matrix.local.config.aop.Authorize;
import org.matrix.local.entity.User;
import org.matrix.local.entity.vo.LoginInfo;
import org.matrix.local.entity.vo.UserInfo;
import org.matrix.local.enums.Authority;
import org.matrix.local.enums.Role;
import org.matrix.local.service.impl.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
......@@ -13,7 +16,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.Map;
@Api(tags = "用户相关API")
@Api(tags = "对用户user的基本操作")
@RestController
@RequestMapping("/user")
public class UserController {
......@@ -21,6 +24,7 @@ public class UserController {
@Autowired
private UserService userService;
@Authorize(Authority.ADMIN)
@ApiOperation(value = "新增用户", notes = "新增数据不可附带id;账号名为唯一值不可出现重复;")
@PostMapping
public ResponseEntity<Map<String, String>> create(@RequestBody User user) {
......@@ -28,6 +32,7 @@ public class UserController {
return ResponseEntity.ok(ImmutableMap.of("message", "操作成功"));
}
@Authorize(Authority.ADMIN)
@ApiOperation(value = "修改用户", notes = "根据id修改用户;修改数据必须附带id且指定id的原数据必须存在;账号名为唯一值不可出现重复;只能修改名称和密码而账号名不可修改;")
@PutMapping
public ResponseEntity<Map<String, String>> update(@RequestBody User user) {
......@@ -35,6 +40,7 @@ public class UserController {
return ResponseEntity.ok(ImmutableMap.of("message", "操作成功"));
}
@Authorize(Authority.ADMIN)
@ApiOperation(value = "删除用户", notes = "根据id删除用户")
@DeleteMapping("/{id}")
public ResponseEntity<Map<String, String>> delete(@PathVariable Long id) {
......@@ -60,6 +66,12 @@ public class UserController {
return ResponseEntity.ok(userInfo);
}
@ApiOperation("查看所有角色")
@GetMapping("/roles")
public ResponseEntity<Role[]> authorities() {
return ResponseEntity.ok(Role.values());
}
@ApiOperation("用户登出")
@GetMapping("/logout")
public ResponseEntity<UserInfo> logout() {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论