diff --git a/src/main/java/net/geedge/asw/common/util/HttpContextUtils.java b/src/main/java/net/geedge/asw/common/util/HttpContextUtils.java new file mode 100644 index 0000000..8984043 --- /dev/null +++ b/src/main/java/net/geedge/asw/common/util/HttpContextUtils.java @@ -0,0 +1,21 @@ +/** + + * + + * + * + */ + +package net.geedge.asw.common.util; + +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + + +public class HttpContextUtils { + + public static HttpServletRequest getHttpServletRequest() { + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + } +} diff --git a/src/main/java/net/geedge/asw/common/util/IPUtils.java b/src/main/java/net/geedge/asw/common/util/IPUtils.java new file mode 100644 index 0000000..bad806a --- /dev/null +++ b/src/main/java/net/geedge/asw/common/util/IPUtils.java @@ -0,0 +1,82 @@ +/** + + * + + * + * + */ + +package net.geedge.asw.common.util; + +import cn.hutool.log.Log; +import jakarta.servlet.http.HttpServletRequest; +import org.apache.commons.lang3.StringUtils; + + +/** + * IP地址 + * + * @author Mark sunlightcs@gmail.com + */ +public class IPUtils { + private static Log logger = Log.get(); + + /** + * 获取IP地址 + * + * 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址 + * 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址 + */ + public static String getIpAddr(HttpServletRequest request) { + String ip = null; + try { + ip = request.getHeader("x-forwarded-for"); + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + } catch (Exception e) { + logger.error("IPUtils ERROR ",e); + } + +// //使用代理,则获取第一个IP地址 +// if(StringUtils.isEmpty(ip) && ip.length() > 15) { +// if(ip.indexOf(",") > 0) { +// ip = ip.substring(0, ip.indexOf(",")); +// } +// } + + return ip; + } + /** + * 功能:判断一个IP是不是在一个网段下的 + * 格式:isInRange("192.168.8.3", "192.168.9.10/22"); + */ + public static boolean isInRange(String ip, String cidr) { + String[] ips = ip.split("\\."); + int ipAddr = (Integer.parseInt(ips[0]) << 24) + | (Integer.parseInt(ips[1]) << 16) + | (Integer.parseInt(ips[2]) << 8) | Integer.parseInt(ips[3]); + int type = Integer.parseInt(cidr.replaceAll(".*/", "")); + int mask = 0xFFFFFFFF << (32 - type); + String cidrIp = cidr.replaceAll("/.*", ""); + String[] cidrIps = cidrIp.split("\\."); + int cidrIpAddr = (Integer.parseInt(cidrIps[0]) << 24) + | (Integer.parseInt(cidrIps[1]) << 16) + | (Integer.parseInt(cidrIps[2]) << 8) + | Integer.parseInt(cidrIps[3]); + + return (ipAddr & mask) == (cidrIpAddr & mask); + } +} diff --git a/src/main/java/net/geedge/asw/common/util/RCode.java b/src/main/java/net/geedge/asw/common/util/RCode.java index 2f0da60..afbc88a 100644 --- a/src/main/java/net/geedge/asw/common/util/RCode.java +++ b/src/main/java/net/geedge/asw/common/util/RCode.java @@ -22,6 +22,10 @@ public enum RCode { ROLE_ID_CANNOT_EMPTY(100010, "role id cannot be empty"),// 权限 ID 不能为空 USER_NOT_EXIST(100011, "user does not exist"), ROLE_NOT_EXIST(100012, "role does not exist"), + SYS_USER_NAME_CANNOT_EMPTY(100013, "username cannot be empty"), + SYS_ACCESS_LEVEL_CANNOT_EMPTY(100014, "accessLevel cannot be empty"), + SYS_WORKSPACE_ROLES_CANNOT_EMPTY(100015, "workspaceRoles cannot be empty"), + SYS_USER_BUILT_IN(100016, "Built-in user are not allowed to delete or update"), // Application @@ -59,6 +63,7 @@ public enum RCode { WORKSPACE_CANNOT_DELETE(401007, "Built-in workspace cannot be deleted"), WORKSPACE_VISIBILITY_ERROR(401008, "workspace visibility error"), WORKSPACE_BUILT_IN(401009, "Built-in workspace cannot be update"), + WORKSPACE_NOT_EXIST(401010, "Workspace does not exist"), //PCAP PCAP_UPLOAD_WEB_SHARK_ERROR(501001, "web shark upload pcap error"), diff --git a/src/main/java/net/geedge/asw/module/sys/controller/SysUserController.java b/src/main/java/net/geedge/asw/module/sys/controller/SysUserController.java index f97314c..f7e5494 100644 --- a/src/main/java/net/geedge/asw/module/sys/controller/SysUserController.java +++ b/src/main/java/net/geedge/asw/module/sys/controller/SysUserController.java @@ -2,20 +2,17 @@ package net.geedge.asw.module.sys.controller; import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import net.geedge.asw.common.util.*; -import net.geedge.asw.module.sys.entity.SysRoleEntity; import net.geedge.asw.module.sys.entity.SysUserEntity; -import net.geedge.asw.module.sys.entity.SysUserRoleEntity; -import net.geedge.asw.module.sys.service.ISysRoleService; -import net.geedge.asw.module.sys.service.ISysUserRoleService; import net.geedge.asw.module.sys.service.ISysUserService; +import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity; +import net.geedge.asw.module.workspace.service.IWorkspaceMemberService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; -import java.util.stream.Collectors; +import java.util.Map; @RestController @RequestMapping("/api/v1/user") @@ -24,80 +21,63 @@ public class SysUserController { private static final Log log = Log.get(); @Autowired private ISysUserService userService; + @Autowired - private ISysRoleService roleService; - @Autowired - private ISysUserRoleService uerRoleService; + private IWorkspaceMemberService workspaceMemberService; @GetMapping("/{id}") public R detail(@PathVariable("id") String id) { SysUserEntity entity = userService.getById(id); if (T.ObjectUtil.isNotNull(entity)) { entity.setPwd(null); - List userRoleList = uerRoleService.list(new LambdaQueryWrapper().eq(SysUserRoleEntity::getUserId, entity.getId())); - if (T.CollUtil.isNotEmpty(userRoleList)) { - List roleIds = userRoleList.stream().map(SysUserRoleEntity::getRoleId).collect(Collectors.toList()); - List roleList = roleService.listByIds(roleIds); - entity.setRoles(roleList); - } + Map params = T.MapUtil.builder("userId", id).build(); + List workspaceMemberEntityList = workspaceMemberService.queryList(params); + entity.setWorkspaceRoles(workspaceMemberEntityList); + SysUserEntity createUser = userService.getOne(new LambdaQueryWrapper().eq(SysUserEntity::getCreateUserId, entity.getCreateUserId())); + createUser.setPwd(null); + entity.setCreateUser(createUser); + SysUserEntity updateUser = userService.getOne(new LambdaQueryWrapper().eq(SysUserEntity::getUpdateUserId, entity.getUpdateUserId())); + updateUser.setPwd(null); + entity.setUpdateUser(updateUser); } return R.ok().putData("record", entity); } @GetMapping - public R list(String ids, String q, - @RequestParam(defaultValue = "1") Integer current, - @RequestParam(defaultValue = "20") Integer size, - @RequestParam(defaultValue = "name") String orderBy) { - QueryWrapper queryWrapper = new QueryWrapper<>(); - // 不查询 pwd 列 - queryWrapper.select(SysUserEntity.class, entity -> !entity.getColumn().equals("pwd")); - queryWrapper.in(T.StrUtil.isNotEmpty(ids), "id", T.StrUtil.split(ids, ',')); - if (T.StrUtil.isNotBlank(q)) { - queryWrapper.and(wrapper -> wrapper.like("name", q).or().like("user_name", q)); - } - Page page = Page.of(current, size); - page.addOrder(T.PageUtil.decodeOrderByStr(orderBy)); - page = userService.page(page, queryWrapper); + public R list(@RequestParam Map params) { + Page page = userService.queryList(params); return R.ok(page); } @PostMapping public R add(@RequestBody SysUserEntity entity) { - T.VerifyUtil.is(entity).notNull().and(entity.getName()).notEmpty(RCode.NAME_CANNOT_EMPTY) - .and(entity.getUserName()).notEmpty().and(entity.getPwd()).notEmpty(); - SysUserEntity one = userService.getOne( - new QueryWrapper().lambda().eq(SysUserEntity::getUserName, entity.getUserName())); - if (T.ObjectUtil.isNotNull(one)) { - throw ASWException.builder().rcode(RCode.SYS_DUPLICATE_RECORD).build(); - } - // 密码加密 - entity.setPwd(T.AesUtil.encrypt(entity.getPwd(), Constants.AES_KEY)); - entity.setCreateTimestamp(T.DateUtil.current()); - userService.saveOrUpdateUser(entity); + T.VerifyUtil.is(entity).notNull() + .and(entity.getName()).notEmpty(RCode.NAME_CANNOT_EMPTY) + .and(entity.getUserName()).notEmpty(RCode.SYS_USER_NAME_CANNOT_EMPTY) + .and(entity.getAccessLevel()).notEmpty(RCode.SYS_ACCESS_LEVEL_CANNOT_EMPTY) + .and(entity.getWorkspaceRoles()).notEmpty(RCode.SYS_WORKSPACE_ROLES_CANNOT_EMPTY); + + userService.saveUser(entity); return R.ok().putData("id", entity.getId()); } @PutMapping public R update(@RequestBody SysUserEntity entity) { - T.VerifyUtil.is(entity).notNull().and(entity.getId()).notEmpty(RCode.ID_CANNOT_EMPTY); - if (T.StrUtil.isNotBlank(entity.getPwd())) { - // 密码加密 - entity.setPwd(T.AesUtil.encrypt(entity.getPwd(), Constants.AES_KEY)); - } else { - entity.setPwd(null); - } - entity.setUserName(null);// username 不允许修改 - entity.setCreateTimestamp(null); - userService.saveOrUpdateUser(entity); + T.VerifyUtil.is(entity).notNull() + .and(entity.getId()).notEmpty(RCode.ID_CANNOT_EMPTY) + .and(entity.getName()).notEmpty(RCode.NAME_CANNOT_EMPTY) + .and(entity.getUserName()).notEmpty(RCode.SYS_USER_NAME_CANNOT_EMPTY) + .and(entity.getAccessLevel()).notEmpty(RCode.SYS_ACCESS_LEVEL_CANNOT_EMPTY) + .and(entity.getWorkspaceRoles()).notEmpty(RCode.SYS_WORKSPACE_ROLES_CANNOT_EMPTY); + userService.updateUser(entity); return R.ok().putData("id", entity.getId()); } @DeleteMapping - public R delete(String[] ids) { + public R delete(String ids) { T.VerifyUtil.is(ids).notEmpty(); - userService.removeBatchByIds(T.ListUtil.of(ids)); - log.info("delete user, ids: {}", T.ArrayUtil.toString(ids)); + userService.delete(ids); + log.info("delete user, ids: {}", ids); return R.ok(); } diff --git a/src/main/java/net/geedge/asw/module/sys/dao/SysUserDao.java b/src/main/java/net/geedge/asw/module/sys/dao/SysUserDao.java index fa2dbc4..5d6bc9f 100644 --- a/src/main/java/net/geedge/asw/module/sys/dao/SysUserDao.java +++ b/src/main/java/net/geedge/asw/module/sys/dao/SysUserDao.java @@ -1,12 +1,18 @@ package net.geedge.asw.module.sys.dao; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import net.geedge.asw.module.sys.entity.SysUserEntity; +import java.util.List; +import java.util.Map; + @Mapper public interface SysUserDao extends BaseMapper{ + List queryList(Page page, Map params); + } diff --git a/src/main/java/net/geedge/asw/module/sys/entity/SysUserEntity.java b/src/main/java/net/geedge/asw/module/sys/entity/SysUserEntity.java index 77aafd5..7e05713 100644 --- a/src/main/java/net/geedge/asw/module/sys/entity/SysUserEntity.java +++ b/src/main/java/net/geedge/asw/module/sys/entity/SysUserEntity.java @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; +import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity; @Data @TableName("sys_user") @@ -23,13 +24,31 @@ public class SysUserEntity { private String pwd; - @TableField(exist = false) - private String roleIds; - - @TableField(exist = false) - private List roles; - private String accessLevel; + private String language; + + private String lastLoginIp; + + private Long lastLoginTimestamp; + + private String createUserId; + + private String updateUserId; + private Long createTimestamp; + + private Long updateTimestamp; + + @TableField(exist = false) + private List workspaceRoles; + + + @TableField(exist = false) + private SysUserEntity createUser; + + @TableField(exist = false) + private SysUserEntity updateUser; + + } diff --git a/src/main/java/net/geedge/asw/module/sys/service/ISysUserService.java b/src/main/java/net/geedge/asw/module/sys/service/ISysUserService.java index 9dfed51..6be8492 100644 --- a/src/main/java/net/geedge/asw/module/sys/service/ISysUserService.java +++ b/src/main/java/net/geedge/asw/module/sys/service/ISysUserService.java @@ -1,10 +1,18 @@ package net.geedge.asw.module.sys.service; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; - import net.geedge.asw.module.sys.entity.SysUserEntity; +import java.util.Map; + public interface ISysUserService extends IService{ - public void saveOrUpdateUser(SysUserEntity entity); + void updateUser(SysUserEntity entity); + + Page queryList(Map params); + + void saveUser(SysUserEntity entity); + + void delete(String ids); } diff --git a/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java b/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java index 775b3d7..c8f109f 100644 --- a/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/sys/service/impl/SysAuthServiceImpl.java @@ -2,23 +2,18 @@ package net.geedge.asw.module.sys.service.impl; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.lang.Pair; import cn.hutool.core.map.MapUtil; import cn.hutool.log.Log; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import net.geedge.asw.common.util.ASWException; -import net.geedge.asw.common.util.Constants; -import net.geedge.asw.common.util.RCode; -import net.geedge.asw.common.util.T; +import jakarta.servlet.http.HttpServletRequest; +import net.geedge.asw.common.util.*; import net.geedge.asw.module.sys.dao.SysRoleDao; import net.geedge.asw.module.sys.dao.SysUserDao; import net.geedge.asw.module.sys.entity.SysMenuEntity; import net.geedge.asw.module.sys.entity.SysRoleEntity; import net.geedge.asw.module.sys.entity.SysUserEntity; import net.geedge.asw.module.sys.service.ISysAuthService; -import net.geedge.asw.module.workbook.entity.WorkbookMemberEntity; -import net.geedge.asw.module.workbook.service.IWorkbookMemberService; import net.geedge.asw.module.workspace.entity.WorkspaceEntity; import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity; import net.geedge.asw.module.workspace.service.IWorkspaceMemberService; @@ -26,7 +21,6 @@ import net.geedge.asw.module.workspace.service.IWorkspaceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -58,6 +52,12 @@ public class SysAuthServiceImpl implements ISysAuthService { throw ASWException.builder().rcode(RCode.SYS_USER_PWD_ERROR).build(); } StpUtil.login(userEntity.getId()); + + HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); + userEntity.setLastLoginTimestamp(System.currentTimeMillis()); + // 设置IP地址 + userEntity.setLastLoginIp(IPUtils.getIpAddr(request)); + userDao.updateById(userEntity); log.info("user login success, userName: {}", userName); return userEntity; } diff --git a/src/main/java/net/geedge/asw/module/sys/service/impl/SysUserServiceImpl.java b/src/main/java/net/geedge/asw/module/sys/service/impl/SysUserServiceImpl.java index 4eeb300..72f9906 100644 --- a/src/main/java/net/geedge/asw/module/sys/service/impl/SysUserServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/sys/service/impl/SysUserServiceImpl.java @@ -1,38 +1,152 @@ package net.geedge.asw.module.sys.service.impl; +import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.geedge.asw.common.util.ASWException; +import net.geedge.asw.common.util.Constants; +import net.geedge.asw.common.util.RCode; import net.geedge.asw.common.util.T; import net.geedge.asw.module.sys.dao.SysUserDao; +import net.geedge.asw.module.sys.entity.SysRoleEntity; import net.geedge.asw.module.sys.entity.SysUserEntity; -import net.geedge.asw.module.sys.entity.SysUserRoleEntity; +import net.geedge.asw.module.sys.service.ISysRoleService; import net.geedge.asw.module.sys.service.ISysUserService; +import net.geedge.asw.module.workspace.entity.WorkspaceEntity; +import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity; +import net.geedge.asw.module.workspace.service.IWorkspaceMemberService; +import net.geedge.asw.module.workspace.service.IWorkspaceService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Arrays; import java.util.List; +import java.util.Map; @Service public class SysUserServiceImpl extends ServiceImpl implements ISysUserService { @Autowired - private SysUserRoleServiceImpl userRoleService; + private ISysRoleService roleService; + + @Autowired + private IWorkspaceMemberService workspaceMemberService; + + @Autowired + private IWorkspaceService workspaceService; + + @Override + public Page queryList(Map params) { + + Page page = T.PageUtil.getPage(params); + List jobList = this.getBaseMapper().queryList(page, params); + page.setRecords(jobList); + return page; + } @Override @Transactional - public void saveOrUpdateUser(SysUserEntity entity) { - if (T.StrUtil.isNotBlank(entity.getId())) { - userRoleService.remove(new QueryWrapper().eq("user_id", entity.getId())); + public void updateUser(SysUserEntity entity) { + + SysUserEntity user = this.getById(StpUtil.getLoginIdAsString()); + if (!T.StrUtil.equalsIgnoreCase(user.getAccessLevel(), "administrator")){ + throw ASWException.builder().rcode(RCode.SYS_NO_AUTH).build(); } + + if (T.StrUtil.equalsIgnoreCase(entity.getId(), "admin")){ + throw ASWException.builder().rcode(RCode.SYS_USER_BUILT_IN).build(); + } + + SysUserEntity one = this.getOne( + new QueryWrapper().lambda().eq(SysUserEntity::getUserName, entity.getUserName())); + if (T.ObjectUtil.isNotNull(one) && !T.StrUtil.equals(entity.getId(), one.getId())) { + throw ASWException.builder().rcode(RCode.SYS_DUPLICATE_RECORD).build(); + } + // 密码加密 + if (T.StrUtil.isNotEmpty(entity.getPwd())){ + entity.setPwd(T.AesUtil.encrypt(entity.getPwd(), Constants.AES_KEY)); + } + entity.setUpdateUserId(StpUtil.getLoginIdAsString()); + entity.setUpdateTimestamp(System.currentTimeMillis()); + // 保存 user - this.saveOrUpdate(entity); - // 保存 user role关系 - List urList = T.ListUtil.list(false); - for (String roleId : T.StrUtil.split(entity.getRoleIds(), ",")) { - urList.add(SysUserRoleEntity.builder().roleId(roleId).userId(entity.getId()).build()); - } - userRoleService.saveBatch(urList); + this.updateById(entity); + + // save workspace member + this.saveWorkspaceRole(entity.getWorkspaceRoles(), entity.getId()); } + @Override + @Transactional + public void saveUser(SysUserEntity entity) { + SysUserEntity user = this.getById(StpUtil.getLoginIdAsString()); + if (!T.StrUtil.equalsIgnoreCase(user.getAccessLevel(), "administrator")){ + throw ASWException.builder().rcode(RCode.SYS_NO_AUTH).build(); + } + + SysUserEntity one = this.getOne( + new QueryWrapper().lambda().eq(SysUserEntity::getUserName, entity.getUserName())); + if (T.ObjectUtil.isNotNull(one)) { + throw ASWException.builder().rcode(RCode.SYS_DUPLICATE_RECORD).build(); + } + // 密码加密 + entity.setPwd(T.AesUtil.encrypt(entity.getPwd(), Constants.AES_KEY)); + entity.setCreateUserId(StpUtil.getLoginIdAsString()); + entity.setUpdateUserId(StpUtil.getLoginIdAsString()); + entity.setCreateTimestamp(System.currentTimeMillis()); + entity.setUpdateTimestamp(System.currentTimeMillis()); + + // 以当前时间为最后登陆时间 + entity.setLastLoginTimestamp(System.currentTimeMillis()); + // save user + this.save(entity); + + // save workspace member + this.saveWorkspaceRole(entity.getWorkspaceRoles(), entity.getId()); + } + + private void saveWorkspaceRole(List workspaceRoles, String userId) { + + List workspaceEntityList = workspaceService.list(); + List roleEntityList = roleService.list(); + List workspaceIds = workspaceEntityList.stream().map(x -> x.getId()).toList(); + List roleIds = roleEntityList.stream().map(x -> x.getId()).toList(); + + for (WorkspaceMemberEntity workspaceRole : workspaceRoles) { + WorkspaceEntity workspace = workspaceRole.getWorkspace(); + if (!workspaceIds.contains(workspace.getId())){ + throw ASWException.builder().rcode(RCode.WORKSPACE_NOT_EXIST).build(); + } + SysRoleEntity role = workspaceRole.getRole(); + if (!roleIds.contains(role.getId())){ + throw ASWException.builder().rcode(RCode.ROLE_NOT_EXIST).build(); + } + workspaceRole.setUserId(userId); + workspaceRole.setWorkspaceId(workspace.getId()); + workspaceRole.setRoleId(role.getId()); + workspaceRole.setCreateUserId(StpUtil.getLoginIdAsString()); + workspaceRole.setCreateTimestamp(System.currentTimeMillis()); + } + + workspaceMemberService.remove(new LambdaQueryWrapper().eq(WorkspaceMemberEntity::getUserId, userId)); + workspaceMemberService.saveBatch(workspaceRoles); + } + + @Override + @Transactional + public void delete(String ids) { + SysUserEntity user = this.getById(StpUtil.getLoginIdAsString()); + if (!T.StrUtil.equalsIgnoreCase(user.getAccessLevel(), "administrator")){ + throw ASWException.builder().rcode(RCode.SYS_NO_AUTH).build(); + } + List idList = Arrays.asList(ids.split(",")); + if (idList.contains("admin")){ + throw ASWException.builder().rcode(RCode.SYS_NO_AUTH).build(); + } + this.removeBatchByIds(idList); + workspaceMemberService.remove(new LambdaQueryWrapper().in(WorkspaceMemberEntity::getUserId, idList)); + } } diff --git a/src/main/java/net/geedge/asw/module/workspace/controller/WorkspaceController.java b/src/main/java/net/geedge/asw/module/workspace/controller/WorkspaceController.java index 276cd6f..9e5de29 100644 --- a/src/main/java/net/geedge/asw/module/workspace/controller/WorkspaceController.java +++ b/src/main/java/net/geedge/asw/module/workspace/controller/WorkspaceController.java @@ -58,6 +58,7 @@ public class WorkspaceController { public R save(@RequestBody WorkspaceEntity workspace) { VerifyUtil.is(workspace).notNull() .and(workspace.getName()).notEmpty(RCode.WORKSPACE_NAME_CANNOT_EMPTY) + .and(workspace.getMembers()).notEmpty(RCode.WORKSPACE_MEMBER_CANNOT_EMPTY) .and(workspace.getVisibility()).notEmpty(RCode.WORKSPACE_VISIBILITY_CANNOT_EMPTY); WorkspaceEntity workspaceEntity = workspaceService.saveWorkspace(workspace); @@ -70,6 +71,7 @@ public class WorkspaceController { VerifyUtil.is(workspace).notNull() .and(workspace.getId()).notEmpty(RCode.WORKSPACE_ID_CANNOT_EMPTY) .and(workspace.getName()).notEmpty(RCode.WORKSPACE_NAME_CANNOT_EMPTY) + .and(workspace.getMembers()).notEmpty(RCode.WORKSPACE_MEMBER_CANNOT_EMPTY) .and(workspace.getVisibility()).notEmpty(RCode.WORKSPACE_VISIBILITY_CANNOT_EMPTY); WorkspaceEntity workspaceEntity = workspaceService.updateWorkspace(workspace); @@ -86,7 +88,9 @@ public class WorkspaceController { @GetMapping("/{workspaceId}/member") public R getMember(@PathVariable String workspaceId) { - List memberEntityList = workspaceMemberService.queryList(workspaceId); + + Map params = T.MapUtil.builder("workspaceId", workspaceId).build(); + List memberEntityList = workspaceMemberService.queryList(params); return R.ok().putData("record", memberEntityList); } diff --git a/src/main/java/net/geedge/asw/module/workspace/dao/WorkspaceMemberDao.java b/src/main/java/net/geedge/asw/module/workspace/dao/WorkspaceMemberDao.java index 69dec56..4e0087d 100644 --- a/src/main/java/net/geedge/asw/module/workspace/dao/WorkspaceMemberDao.java +++ b/src/main/java/net/geedge/asw/module/workspace/dao/WorkspaceMemberDao.java @@ -3,11 +3,13 @@ package net.geedge.asw.module.workspace.dao; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; +import java.util.Map; @Mapper public interface WorkspaceMemberDao extends BaseMapper { - List queryList(String workspaceId); + List queryList(@Param("params") Map params); } \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/workspace/entity/WorkspaceMemberEntity.java b/src/main/java/net/geedge/asw/module/workspace/entity/WorkspaceMemberEntity.java index 72baae1..0fd1e12 100644 --- a/src/main/java/net/geedge/asw/module/workspace/entity/WorkspaceMemberEntity.java +++ b/src/main/java/net/geedge/asw/module/workspace/entity/WorkspaceMemberEntity.java @@ -28,4 +28,7 @@ public class WorkspaceMemberEntity { @TableField(exist = false) private SysUserEntity createUser; + @TableField(exist = false) + private WorkspaceEntity workspace; + } \ No newline at end of file diff --git a/src/main/java/net/geedge/asw/module/workspace/service/IWorkspaceMemberService.java b/src/main/java/net/geedge/asw/module/workspace/service/IWorkspaceMemberService.java index d5dd209..4da0d8d 100644 --- a/src/main/java/net/geedge/asw/module/workspace/service/IWorkspaceMemberService.java +++ b/src/main/java/net/geedge/asw/module/workspace/service/IWorkspaceMemberService.java @@ -4,10 +4,11 @@ import com.baomidou.mybatisplus.extension.service.IService; import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity; import java.util.List; +import java.util.Map; public interface IWorkspaceMemberService extends IService{ - List queryList(String workspaceId); + List queryList(Map params); List saveMember(String workspaceId ,List workspaces); diff --git a/src/main/java/net/geedge/asw/module/workspace/service/impl/WorkspaceMemberServiceImpl.java b/src/main/java/net/geedge/asw/module/workspace/service/impl/WorkspaceMemberServiceImpl.java index 68b5e5e..3bd7b6a 100644 --- a/src/main/java/net/geedge/asw/module/workspace/service/impl/WorkspaceMemberServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/workspace/service/impl/WorkspaceMemberServiceImpl.java @@ -16,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Map; @Service public class WorkspaceMemberServiceImpl extends ServiceImpl implements IWorkspaceMemberService { @@ -30,8 +31,8 @@ public class WorkspaceMemberServiceImpl extends ServiceImpl queryList(String workspaceId) { - List list = this.baseMapper.queryList(workspaceId); + public List queryList(Map params) { + List list = this.baseMapper.queryList(params); return list; } @@ -39,7 +40,8 @@ public class WorkspaceMemberServiceImpl extends ServiceImpl saveMember(String workspaceId, List workspaces) { validateInfo(workspaceId, workspaces); workspaceMemberService.saveBatch(workspaces); - List memberEntityList = workspaceMemberService.queryList(workspaceId); + Map params = T.MapUtil.builder("workspaceId", workspaceId).build(); + List memberEntityList = workspaceMemberService.queryList(params); return memberEntityList; } @@ -48,7 +50,8 @@ public class WorkspaceMemberServiceImpl extends ServiceImpl().eq(WorkspaceMemberEntity::getWorkspaceId, workspaceId)); workspaceMemberService.saveBatch(workspaces); - List memberEntityList = workspaceMemberService.queryList(workspaceId); + Map params = T.MapUtil.builder("workspaceId", workspaceId).build(); + List memberEntityList = workspaceMemberService.queryList(params); return memberEntityList; } diff --git a/src/main/java/net/geedge/asw/module/workspace/service/impl/WorkspaceServiceImpl.java b/src/main/java/net/geedge/asw/module/workspace/service/impl/WorkspaceServiceImpl.java index 1bc3587..eeace9a 100644 --- a/src/main/java/net/geedge/asw/module/workspace/service/impl/WorkspaceServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/workspace/service/impl/WorkspaceServiceImpl.java @@ -48,15 +48,14 @@ public class WorkspaceServiceImpl extends ServiceImpl members = workspace.getMembers(); - members.stream().forEach(x -> { - x.setWorkspaceId(workspace.getId()); - x.setCreateTimestamp(System.currentTimeMillis()); - x.setCreateUserId(StpUtil.getLoginIdAsString()); - }); - workspaceMemberService.saveBatch(members); - } + List members = workspace.getMembers(); + members.stream().forEach(x -> { + x.setWorkspaceId(workspace.getId()); + x.setCreateTimestamp(System.currentTimeMillis()); + x.setCreateUserId(StpUtil.getLoginIdAsString()); + }); + workspaceMemberService.saveBatch(members); + return workspace; } @@ -68,16 +67,15 @@ public class WorkspaceServiceImpl extends ServiceImpl members = workspace.getMembers(); - members.stream().forEach(x -> { - x.setWorkspaceId(workspace.getId()); - x.setCreateTimestamp(System.currentTimeMillis()); - x.setCreateUserId(StpUtil.getLoginIdAsString()); - }); - workspaceMemberService.remove(new LambdaQueryWrapper().eq(WorkspaceMemberEntity::getWorkspaceId, workspace.getId())); - workspaceMemberService.saveBatch(members); - } + List members = workspace.getMembers(); + members.stream().forEach(x -> { + x.setWorkspaceId(workspace.getId()); + x.setCreateTimestamp(System.currentTimeMillis()); + x.setCreateUserId(StpUtil.getLoginIdAsString()); + }); + workspaceMemberService.remove(new LambdaQueryWrapper().eq(WorkspaceMemberEntity::getWorkspaceId, workspace.getId())); + workspaceMemberService.saveBatch(members); + return workspace; } @@ -94,12 +92,9 @@ public class WorkspaceServiceImpl extends ServiceImpl list = workspaceService.list(new LambdaQueryWrapper().eq(WorkspaceEntity::getName, workspace.getName())); if (!isUpdate && T.CollectionUtil.isNotEmpty(list)) { diff --git a/src/main/resources/db/mapper/sys/SysUserMapper.xml b/src/main/resources/db/mapper/sys/SysUserMapper.xml new file mode 100644 index 0000000..2c98ab4 --- /dev/null +++ b/src/main/resources/db/mapper/sys/SysUserMapper.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db/mapper/workspace/WorkspaceMemberMapper.xml b/src/main/resources/db/mapper/workspace/WorkspaceMemberMapper.xml index bb9cf15..125b712 100644 --- a/src/main/resources/db/mapper/workspace/WorkspaceMemberMapper.xml +++ b/src/main/resources/db/mapper/workspace/WorkspaceMemberMapper.xml @@ -25,6 +25,11 @@ + + + + + diff --git a/src/main/resources/db/migration/R__AZ_sys_i18n.sql b/src/main/resources/db/migration/R__AZ_sys_i18n.sql index d2e0818..2b7eab0 100644 --- a/src/main/resources/db/migration/R__AZ_sys_i18n.sql +++ b/src/main/resources/db/migration/R__AZ_sys_i18n.sql @@ -93,5 +93,16 @@ INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_ INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (143, '501001', 'PCAP_UPLOAD_WEB_SHARK_ERROR', 'pcap 上传失败', 'zh', '', 'admin', 1724030366000); INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (145, '201009', 'APP_PACKAGE_NAME_FORMAT_ERROR', 'application package name format error', 'en', '', 'admin', 1724030366000); INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (147, '201009', 'APP_PACKAGE_NAME_FORMAT_ERROR', '应用安装包名称格式错误', 'zh', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (149, '100013', 'SYS_USER_NAME_CANNOT_EMPTY', 'username cannot be empty', 'en', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (151, '100013', 'SYS_USER_NAME_CANNOT_EMPTY', '用户名称不能为空', 'zh', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (153, '100014', 'SYS_ACCESS_LEVEL_CANNOT_EMPTY', 'accessLevel cannot be empty', 'en', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (155, '100014', 'SYS_ACCESS_LEVEL_CANNOT_EMPTY', '访问级别不能为空', 'zh', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (157, '100015', 'SYS_WORKSPACE_ROLES_CANNOT_EMPTY', 'workspaceRoles cannot be empty', 'en', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (159, '100015', 'SYS_WORKSPACE_ROLES_CANNOT_EMPTY', '工作空间用户与权限不能为空', 'zh', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (161, '100016', 'SYS_USER_BUILT_IN', 'Built-in user are not allowed to delete or update', 'en', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (163, '100016', 'SYS_USER_BUILT_IN', '内置用户不允许删除或更新', 'zh', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (165, '401010', 'WORKSPACE_NOT_EXIST', 'Workspace does not exist', 'en', '', 'admin', 1724030366000); +INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (167, '401010', 'WORKSPACE_NOT_EXIST', '工作空间不存在', 'zh', '', 'admin', 1724030366000); + SET FOREIGN_KEY_CHECKS = 1; diff --git a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql index b32a2f8..268c649 100644 --- a/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql +++ b/src/main/resources/db/migration/V1.0.01__INIT_TABLES.sql @@ -9,13 +9,19 @@ CREATE TABLE `sys_user` ( `user_name` varchar(255) NOT NULL, `pwd` varchar(255) NOT NULL, `access_level` varchar(255) NOT NULL, - `create_timestamp` bigint(20) NOT NULL, + `language` VARCHAR(256) NOT NULL DEFAULT 'en' COMMENT '语言', + `last_login_ip` VARCHAR(256) NOT NULL DEFAULT '' COMMENT '最后登录IP', + `last_login_timestamp` BIGINT(20) NOT NULL COMMENT '最后登录时间', + `create_timestamp` BIGINT(20) NOT NULL COMMENT '创建时间戳', + `update_timestamp` BIGINT(20) NOT NULL COMMENT '更新时间戳', + `create_user_id` VARCHAR(64) NOT NULL COMMENT '创建人id', + `update_user_id` VARCHAR(64) NOT NULL COMMENT '更新人id', PRIMARY KEY (`id`), UNIQUE KEY `idx_user_name` (`user_name`) USING BTREE, KEY `idx_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 添加内置用户 -INSERT INTO `sys_user`(`id`, `name`, `user_name`, `pwd`, `access_level`, `create_timestamp`) VALUES ('admin', 'admin', 'admin', 'ad9d757e620d5d9cd8e32c3dbcf37525', 'administrator', UNIX_TIMESTAMP(NOW())*1000); +INSERT INTO `sys_user`(`id`, `name`, `user_name`, `pwd`, `access_level`, `language`, `last_login_ip`, `last_login_timestamp`, `create_timestamp`, `update_timestamp`, `create_user_id`, `update_user_id`) VALUES ('admin', 'admin', 'admin', 'ad9d757e620d5d9cd8e32c3dbcf37525', 'administrator', 'en', '', UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000, UNIX_TIMESTAMP(NOW())*1000, 'admin', 'admin'); /** * 1、新增 sys_role 表 @@ -394,7 +400,7 @@ CREATE TABLE `workspace` ( KEY `idx_name` (`name`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -INSERT INTO `workspace` (`id`, `name`, `tags`, `visibility`, `description`, `create_timestamp`, `update_timestamp`, `create_user_id`, `update_user_id`) VALUES ('1', 'default', '', 'public', '', 1722482392000, 1722482392000, 'admin', 'admin'); +INSERT INTO `workspace` (`id`, `name`, `tags`, `visibility`, `description`, `create_timestamp`, `update_timestamp`, `create_user_id`, `update_user_id`) VALUES ('1', 'default', '', 'private', '', 1722482392000, 1722482392000, 'admin', 'admin'); DROP TABLE IF EXISTS `workspace_member`; CREATE TABLE `workspace_member` ( @@ -406,4 +412,6 @@ CREATE TABLE `workspace_member` ( KEY `idx_workspace_id` (`workspace_id`) USING BTREE, KEY `idx_user_id` (`user_id`) USING BTREE, KEY `idx_role_id` (`role_id`) USING BTREE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; \ No newline at end of file +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +INSERT INTO `workspace_member` (`workspace_id`, `user_id`, `role_id`, `create_timestamp`, `create_user_id`) VALUES ('1', 'admin', 'admin', 1724291229000, 'admin');