diff --git a/antdsp-admin/.gitignore b/antdsp-admin/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b83d22266ac8aa2f8df2edef68082c789727841d --- /dev/null +++ b/antdsp-admin/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/antdsp-admin/src/main/java/com/antdsp/common/AntdspResponse.java b/antdsp-admin/src/main/java/com/antdsp/common/AntdspResponse.java index 284b33763a427870ccd4f7b51d3971368670ac9d..05ffe9414fcadb3afd0baaad5f9a6ea3b0f56a05 100644 --- a/antdsp-admin/src/main/java/com/antdsp/common/AntdspResponse.java +++ b/antdsp-admin/src/main/java/com/antdsp/common/AntdspResponse.java @@ -59,7 +59,7 @@ public class AntdspResponse { } public static AntdspResponse error(String msg) { - return error(ResponseCode.REJECT , msg); + return error(ResponseCode.ERROR , msg); } public static AntdspResponse error(ResponseCode code , String msg) { diff --git a/antdsp-admin/src/main/java/com/antdsp/common/ResponseCode.java b/antdsp-admin/src/main/java/com/antdsp/common/ResponseCode.java index 91ab81dde5a0df9019c835e29f8a743e29609591..cd7fc48d08f91bb377650410d3c632708c626cac 100644 --- a/antdsp-admin/src/main/java/com/antdsp/common/ResponseCode.java +++ b/antdsp-admin/src/main/java/com/antdsp/common/ResponseCode.java @@ -3,6 +3,7 @@ package com.antdsp.common; public enum ResponseCode { OK(1200 , "正常"), + ERROR(1201,"未正常处理"), REJECT(1207 , "拒绝"), UNAUTHORIZED(1401 , "未登录"), FORBIDDEN(1403 , "权限不足"); diff --git a/antdsp-admin/src/main/java/com/antdsp/common/configuration/CorsConfiguration.java b/antdsp-admin/src/main/java/com/antdsp/common/configuration/CorsConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..b0acba48ea075cc6018d55acedc0953034abcb9d --- /dev/null +++ b/antdsp-admin/src/main/java/com/antdsp/common/configuration/CorsConfiguration.java @@ -0,0 +1,30 @@ +package com.antdsp.common.configuration; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.CorsRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * + *

title:CorsConfiguration

+ *

Description: 跨域访问

+ *

Copyright: Copyright (c) 2019

+ * + * @author lijiantao + * @date 2019年6月13日 + * @email a496401006@qq.com + * + */ +@Configuration +public class CorsConfiguration implements WebMvcConfigurer{ + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600);; + } + +} diff --git a/antdsp-admin/src/main/java/com/antdsp/common/configuration/ShiroConfiguration.java b/antdsp-admin/src/main/java/com/antdsp/common/configuration/ShiroConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..09fa7ef61a4e170a77a60474c7fca64645de9291 --- /dev/null +++ b/antdsp-admin/src/main/java/com/antdsp/common/configuration/ShiroConfiguration.java @@ -0,0 +1,79 @@ +package com.antdsp.common.configuration; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.realm.Realm; +import org.apache.shiro.session.mgt.SessionManager; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.antdsp.common.shiro.AntdspShiroRealm; +import com.antdsp.common.shiro.AntdspShiroSessionManager; + +/** + * + *

title: ShiroConfiguration

+ *

Description:

+ *

Copyright: Copyright (c) 2019

+ * + * @author lijiantao + * @date 2019年6月12日 + * @email a496401006@qq.com + * + */ +@Configuration +public class ShiroConfiguration { + + @Bean + public Realm shiroRealm() { + AntdspShiroRealm realm = new AntdspShiroRealm(); + return realm; + } + + @Bean("securityManager") + public SecurityManager securityManager() { + DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); + securityManager.setRealm(shiroRealm()); + securityManager.setSessionManager(shiroSessionManager()); + return securityManager; + } + + @Bean + public SessionManager shiroSessionManager() { + AntdspShiroSessionManager sessionManger = new AntdspShiroSessionManager(); + return sessionManger; + } + + @Bean + public ShiroFilterFactoryBean shirofilterFactoryBean(SecurityManager securityManager) { + ShiroFilterFactoryBean shiroFilterFactory = new ShiroFilterFactoryBean(); + shiroFilterFactory.setSecurityManager(securityManager); + + Map filterMap = new HashMap<>(); + filterMap.put("/login","anon"); + filterMap.put("/logout","anon"); + filterMap.put("/unauth","anon"); + filterMap.put("/**","authc"); + + shiroFilterFactory.setFilterChainDefinitionMap(filterMap); + shiroFilterFactory.setSuccessUrl("/login_success"); + shiroFilterFactory.setUnauthorizedUrl("/unauth"); + shiroFilterFactory.setLoginUrl("/login"); + + return shiroFilterFactory; + } + + //使用shiro的权限注解 + @Bean + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){ + AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); + authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); + return authorizationAttributeSourceAdvisor; + } + +} diff --git a/antdsp-admin/src/main/java/com/antdsp/common/shiro/AntdspShiroRealm.java b/antdsp-admin/src/main/java/com/antdsp/common/shiro/AntdspShiroRealm.java new file mode 100644 index 0000000000000000000000000000000000000000..c5d4869b53e0d525b81e4a609acc62b8faba8987 --- /dev/null +++ b/antdsp-admin/src/main/java/com/antdsp/common/shiro/AntdspShiroRealm.java @@ -0,0 +1,78 @@ +package com.antdsp.common.shiro; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.DisabledAccountException; +import org.apache.shiro.authc.SimpleAuthenticationInfo; +import org.apache.shiro.authc.UnknownAccountException; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.subject.PrincipalCollection; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.StringUtils; + +import com.antdsp.dao.jpa.UserJpa; +import com.antdsp.dao.jpa.system.MenuJpa; +import com.antdsp.data.entity.User; +import com.antdsp.data.entity.system.SystemMenu; +import com.antdsp.data.entityeenum.UserStatus; + +public class AntdspShiroRealm extends AuthorizingRealm{ + + @Autowired + private UserJpa userJpa; + + @Autowired + private MenuJpa menuJpa; + + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { + + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); + + User user = (User) principals.getPrimaryPrincipal(); + List permissMenus = this.menuJpa.findPermissMenus(user.getId()); + Set permisses = new HashSet<>(); + for(SystemMenu menu : permissMenus) { + String permission = menu.getPermission(); + if(!StringUtils.isEmpty(permission)) { + permisses.add(permission); + } + } + + info.addStringPermissions(permisses); + return info; + } + + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + + UsernamePasswordToken passwordToken = (UsernamePasswordToken) token; + + String username = passwordToken.getUsername(); + String password = new String(passwordToken.getPassword()); + + User user = userJpa.queryUserByLoginName(username); + if(user == null) { + throw new UnknownAccountException("用户名/密码错误"); + } + if(!user.getPassword().equals(password)) { + throw new UnknownAccountException("用户名/密码错误"); + } + if(UserStatus.DISABLED.equals(user.getStatus())) { + throw new DisabledAccountException("用户名已经禁止使用"); + } + + SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user , user.getPassword() , getName()); + + return info; + } + +} diff --git a/antdsp-admin/src/main/java/com/antdsp/common/shiro/AntdspShiroSessionManager.java b/antdsp-admin/src/main/java/com/antdsp/common/shiro/AntdspShiroSessionManager.java new file mode 100644 index 0000000000000000000000000000000000000000..201e5ea3456a1a3199079be63ea31ec39c573cfa --- /dev/null +++ b/antdsp-admin/src/main/java/com/antdsp/common/shiro/AntdspShiroSessionManager.java @@ -0,0 +1,40 @@ +package com.antdsp.common.shiro; + +import java.io.Serializable; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.apache.shiro.web.servlet.ShiroHttpServletRequest; +import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; +import org.apache.shiro.web.util.WebUtils; +import org.springframework.util.StringUtils; + +public class AntdspShiroSessionManager extends DefaultWebSessionManager{ + + private static final String AUTHORIZATION = "Authorization"; + private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request"; + + public AntdspShiroSessionManager() { + super(); + } + + @Override + protected Serializable getSessionId(ServletRequest request, ServletResponse response) { + // TODO Auto-generated method stub + HttpServletRequest httpRequest = WebUtils.toHttp(request); + + String sessionId = httpRequest.getHeader(AUTHORIZATION); + if(!StringUtils.isEmpty(sessionId)) { + request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE); + request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId); + request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID , true); + + return sessionId; + }else { + return super.getSessionId(request, response); + } + } + +} diff --git a/antdsp-admin/src/main/java/com/antdsp/web/dto/LoginUserInfo.java b/antdsp-admin/src/main/java/com/antdsp/web/dto/LoginUserInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..838cda9f384b747a7309be434aee6ea08a0096c3 --- /dev/null +++ b/antdsp-admin/src/main/java/com/antdsp/web/dto/LoginUserInfo.java @@ -0,0 +1,21 @@ +package com.antdsp.web.dto; + +public class LoginUserInfo { + + private String loginname; + private String password; + + public String getLoginname() { + return loginname; + } + public void setLoginname(String loginname) { + this.loginname = loginname; + } + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + +} diff --git a/antdsp-admin/src/main/java/com/antdsp/web/dto/SystemUserDto.java b/antdsp-admin/src/main/java/com/antdsp/web/dto/SystemUserDto.java new file mode 100644 index 0000000000000000000000000000000000000000..f6b0a5308e2c1d31c21e4bb756cfe56317ec933a --- /dev/null +++ b/antdsp-admin/src/main/java/com/antdsp/web/dto/SystemUserDto.java @@ -0,0 +1,40 @@ +package com.antdsp.web.dto; + +import java.util.List; + +import com.antdsp.data.entity.User; +import com.antdsp.data.entity.system.SystemRole; + +public class SystemUserDto { + private User user; + + private List roleIds; + + private List roles; + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public List getRoleIds() { + return roleIds; + } + + public void setRoleIds(List roleIds) { + this.roleIds = roleIds; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + +} diff --git a/antdsp-admin/src/main/java/com/antdsp/web/rest/Login.java b/antdsp-admin/src/main/java/com/antdsp/web/rest/Login.java index f98e90158ddf6e258850825388307688290c77ed..5aeaafbb16c78ff74d952083abc74e27a18cae5b 100644 --- a/antdsp-admin/src/main/java/com/antdsp/web/rest/Login.java +++ b/antdsp-admin/src/main/java/com/antdsp/web/rest/Login.java @@ -1,5 +1,62 @@ package com.antdsp.web.rest; -public class Login { +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import com.antdsp.common.AntdspResponse; +import com.antdsp.common.ResponseCode; +import com.antdsp.web.dto.LoginUserInfo; +@RestController +public class Login { + + @GetMapping("/login") + public AntdspResponse login() { + return AntdspResponse.error(ResponseCode.UNAUTHORIZED , "请先登录"); + } + + @PostMapping("/login") + public AntdspResponse login(@RequestBody LoginUserInfo userInfo) { + Subject subject = SecurityUtils.getSubject(); + UsernamePasswordToken token = new UsernamePasswordToken(userInfo.getLoginname() , userInfo.getPassword()); + try { + subject.login(token); + Session session = subject.getSession(); +// session.setTimeout(180000); + return AntdspResponse.success(session.getId().toString()); + }catch(AuthenticationException e) { + return AntdspResponse.error(e.getMessage()); + } + + } + + @GetMapping("/login_success") + public AntdspResponse loginsuccess() { + Subject subject = SecurityUtils.getSubject(); + Session session = subject.getSession(); + return AntdspResponse.success(session.getId().toString()); + } + + @GetMapping("/unauth") + public AntdspResponse unauth() { + return new AntdspResponse(ResponseCode.FORBIDDEN , false); + } + + @GetMapping("/logout") + public AntdspResponse logout() { + + Subject subject = SecurityUtils.getSubject(); + subject.logout(); + return AntdspResponse.success("退出登录成功"); + } + } diff --git a/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemMenuApi.java b/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemMenuApi.java index fb45c00a1dc730ac8feb7b296c28387d5bcfc2b2..444ca2cc62c30b1091b7fc2fbcc1f3b6a4f7ae16 100644 --- a/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemMenuApi.java +++ b/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemMenuApi.java @@ -3,6 +3,8 @@ package com.antdsp.web.rest.sys; import java.util.List; import java.util.stream.Collectors; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.DeleteMapping; @@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.RestController; import com.antdsp.common.AntdspResponse; import com.antdsp.dao.jpa.system.MenuJpa; +import com.antdsp.data.entity.User; import com.antdsp.data.entity.system.SystemMenu; import com.antdsp.data.entityeenum.MenuType; import com.antdsp.web.dto.MenuTree; @@ -36,9 +39,7 @@ public class SystemMenuApi { rootMenu.setPath("/"); List allMenus = this.menuJpa.findAll(); - this.child(rootMenu, allMenus); - return rootMenu; } @@ -60,7 +61,11 @@ public class SystemMenuApi { @Transactional public AntdspResponse update(@RequestBody MenuTree menu) { - SystemMenu oldMenu = this.menuJpa.getOne(menu.getId()); + SystemMenu oldMenu = this.menuJpa.findById(menu.getId()).orElse(null); + + if(oldMenu == null) { + return AntdspResponse.error("操作失败,未找到菜单信息"); + } this.dtoToData(menu, oldMenu); oldMenu.onPreUpdate(); @@ -71,7 +76,7 @@ public class SystemMenuApi { @DeleteMapping("/{id:\\d+}") public AntdspResponse delete(@PathVariable("id") Long id) { - SystemMenu oldMenu = this.menuJpa.getOne(id); + SystemMenu oldMenu = this.menuJpa.findById(id).orElse(null); if(oldMenu == null) { return AntdspResponse.error("未找到操作对象"); } @@ -80,6 +85,27 @@ public class SystemMenuApi { return AntdspResponse.success(); } + /** + * 获取当前登录人的路由信息 + * @return + */ + @GetMapping("/route") + public MenuTree queryRouteMenu() { + + Subject subject = SecurityUtils.getSubject(); + User current = (User) subject.getPrincipal(); + + List allMenuAntButtons = this.menuJpa.findPermissMenus(current.getId()); + List allMenus = allMenuAntButtons.stream().filter(item->MenuType.MENU.equals(item.getMenuType())).collect(Collectors.toList()); + + MenuTree rootMenu = new MenuTree(); + rootMenu.setId(0L); + rootMenu.setName("antdsp"); + rootMenu.setPath("/"); + this.child(rootMenu, allMenus); + return rootMenu; + + } private void dtoToData(MenuTree menu , SystemMenu systemenu) { diff --git a/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemRoleApi.java b/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemRoleApi.java index be389d70feeab6890678eede0e8af5e1cb749c13..56a80c8e1fda964d2283a1c4e3e8e21e5b224105 100644 --- a/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemRoleApi.java +++ b/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemRoleApi.java @@ -1,11 +1,7 @@ package com.antdsp.web.rest.sys; -import java.math.BigInteger; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.stream.Stream; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; @@ -35,7 +31,6 @@ import com.antdsp.common.pagination.PaginationData; import com.antdsp.dao.jpa.system.RoleJpa; import com.antdsp.data.entity.system.SystemRole; import com.antdsp.web.dto.RoleDto; -import com.antdsp.web.dto.RoleMenu; /** * @@ -80,23 +75,17 @@ public class SystemRoleApi { @GetMapping("/{id:\\d+}") public RoleDto detail(@PathVariable("id") Long id) { - SystemRole role = this.roleJpa.getOne(id); - RoleDto dto = new RoleDto(); + SystemRole role = this.roleJpa.findById(id).orElse(null); + if(role == null) { + return dto; + } + dto.setDescription(role.getDescription()); dto.setId(role.getId()); dto.setRoleName(role.getRoleName()); - String sqlStr = "SELECT r.menu_id FROM tb_role_menu r LEFT JOIN tb_system_menu sr ON r.menu_id = sr.id WHERE r.role_id = :roleId AND sr.menu_type = 'BUTTON' "; - - Map params = new HashMap<>(); - params.put("roleId", id); - - List list = this.roleJpa.queryAllBySQL(sqlStr, params); - List menuIds = new ArrayList<>(); - for(BigInteger item : list) { - menuIds.add(item.longValue()); - } + List menuIds = this.roleJpa.queryRoleMenuId(id); dto.setMenuIds(menuIds); return dto; } @@ -127,7 +116,7 @@ public class SystemRoleApi { public AntdspResponse update(@RequestBody RoleDto role) { Long roleId = role.getId(); - SystemRole data = this.roleJpa.getOne(roleId); + SystemRole data = this.roleJpa.findById(roleId).orElse(null); if(data == null) { return AntdspResponse.error("未找到角色信息"); } @@ -136,27 +125,30 @@ public class SystemRoleApi { data.onPreUpdate(); this.roleJpa.save(data); - String deleteStr = "DELETE FROM `tb_role_menu` WHERE `role_id` = :roleId"; - Map params = new HashMap<>(); - params.put("roleId", roleId); - - this.roleJpa.executeSQL(deleteStr , params); + this.roleJpa.deleteRoleMenuByRoleId(roleId); this.saveRoleMenu(role.getMenuIds(), roleId); + return AntdspResponse.success(); } @DeleteMapping("/{id:\\d+}") - @Transactional + @Transactional() public AntdspResponse delete(@PathVariable("id") Long id) { - SystemRole role = this.roleJpa.getOne(id); + SystemRole role = this.roleJpa.findById(id).orElse(null); if(role == null) { return AntdspResponse.error("未找到角色信息"); } this.roleJpa.delete(role); + this.roleJpa.deleteRoleMenuByRoleId(role.getId()); return AntdspResponse.success(); } + @GetMapping("queryRoleNameAndIds") + public List queryRoleNameAndIds(){ + return this.roleJpa.findRoleNameAndIds(); + } + private int saveRoleMenu(List menuIds , Long roleId) { if(menuIds != null &&menuIds.size() > 0) { StringBuffer sqlStr = new StringBuffer("INSERT INTO `tb_role_menu` (`role_id`,`menu_id`) VALUES "); diff --git a/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemUserApi.java b/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemUserApi.java index 95054ff8bd85f8d2b9e2fe3b75567ce3a5ea894a..94ecfa7fbd0905052679104058c60ed94022dc4b 100644 --- a/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemUserApi.java +++ b/antdsp-admin/src/main/java/com/antdsp/web/rest/sys/SystemUserApi.java @@ -1,15 +1,16 @@ package com.antdsp.web.rest.sys; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -17,6 +18,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Order; import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.DeleteMapping; @@ -31,8 +33,11 @@ import org.springframework.web.bind.annotation.RestController; import com.antdsp.common.AntdspResponse; import com.antdsp.common.pagination.PaginationData; import com.antdsp.dao.jpa.UserJpa; +import com.antdsp.dao.jpa.system.RoleJpa; import com.antdsp.data.entity.User; +import com.antdsp.data.entity.system.SystemRole; import com.antdsp.data.entityeenum.UserStatus; +import com.antdsp.web.dto.SystemUserDto; @RestController @RequestMapping("/system/user") @@ -41,6 +46,9 @@ public class SystemUserApi { @Autowired private UserJpa userJpa; + @Autowired + private RoleJpa roleJpa; + @GetMapping("") public PaginationData list(int page , int count , String loginname , UserStatus status){ @@ -67,9 +75,38 @@ public class SystemUserApi { return pagination; } + @GetMapping("/{id:\\d+}") + public SystemUserDto detail(@PathVariable("id") Long userId) { + + List roles = this.roleJpa.findRoleNameAndIds(); + SystemUserDto result = new SystemUserDto(); + result.setRoles(roles); + + if(userId == 0) { + return result; + } + + User user = this.userJpa.findById(userId).orElse(null); + if(user == null) { + return result; + } + + List roleIds = this.userJpa.queryUserRoleId(userId); + result.setRoleIds(roleIds); + user.setPassword(""); + result.setUser(user); + result.setRoles(roles); + + return result; + } + @PostMapping("") @Transactional - public AntdspResponse add(@RequestBody User user) { + public AntdspResponse add(@RequestBody SystemUserDto dto) { + + User user = dto.getUser(); + User current = current(); + List roleIds = dto.getRoleIds(); User olduser = userJpa.queryUserByLoginName(user.getLoginname()); if(olduser != null) { @@ -77,35 +114,74 @@ public class SystemUserApi { } user.setAvatar(""); - user.setCreator(""); - user.setModifier(""); + user.setCreator(current.getLoginname()); + user.setModifier(current.getLoginname()); user.setStatus(UserStatus.NORMAL); user.onPreInsert(); - this.userJpa.save(user); + + Long userId = this.userJpa.save(user).getId(); + this.saveRoleUser(userId, roleIds); return AntdspResponse.success("保存成功"); } @PutMapping("/{id:\\d+}") @Transactional - public AntdspResponse update(@RequestBody User user) { + public AntdspResponse update(@RequestBody SystemUserDto dto) { - User oldUser = userJpa.getOne(user.getId()); + User user = dto.getUser(); + User current = current(); + List roleIds = dto.getRoleIds(); + + User oldUser = userJpa.findById(user.getId()).orElse(null); oldUser.setEmail(user.getEmail()); oldUser.setQq(user.getQq()); oldUser.setRealname(user.getRealname()); + oldUser.setModifier(current.getLoginname()); oldUser.onPreUpdate(); this.userJpa.save(oldUser); + this.userJpa.deleteUserRoleId(user.getId()); + + this.saveRoleUser(oldUser.getId(), roleIds); + return AntdspResponse.success("保存成功"); } @DeleteMapping("/{id:\\d+}") + @RequiresPermissions(value= {"user:delete"}) @Transactional public AntdspResponse delete(@PathVariable("id") Long id) { - User oldUser = userJpa.getOne(id); + User oldUser = userJpa.findById(id).orElse(null); + if(oldUser == null) { + return AntdspResponse.error("删除失败,未找到用户信息"); + } this.userJpa.delete(oldUser); + this.userJpa.deleteUserRoleId(id); + return AntdspResponse.success(); } + + @GetMapping("/current") + public User current() { + Subject subject = SecurityUtils.getSubject(); + User current = (User) subject.getPrincipal(); + current.setPassword(""); + return current; + } + + private int saveRoleUser(Long userId, List roleIds) { + if(roleIds != null && roleIds.size() > 0) { + StringBuffer sqlStr = new StringBuffer("INSERT INTO `tb_role_user` (`role_id`, `user_id`) VALUES "); + sqlStr.append("("+roleIds.get(0)+ ", " + userId+")"); + if(roleIds.size()>2) { + for(int i= 1 ; i< roleIds.size(); i++) { + sqlStr.append(",("+roleIds.get(i)+ ", " + userId+")"); + } + } + return this.userJpa.executeSQL(sqlStr.toString(), null); + } + return 0; + } } diff --git a/antdsp-admin/src/main/resources/application-dev.yml b/antdsp-admin/src/main/resources/application-dev.yml index 99f09a446f1c3d4cf5c406d7cb7e5422ad562cda..673bd66818f68ef53562ceddd08967e5412364ad 100644 --- a/antdsp-admin/src/main/resources/application-dev.yml +++ b/antdsp-admin/src/main/resources/application-dev.yml @@ -2,11 +2,12 @@ spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://localhost:3306/antdsp?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai + url: jdbc:mysql://192.168.1.231:3306/antdsp?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root password: 123456 initial-size: 10 jpa: hibernate: ddl-auto: update - show-sql: true \ No newline at end of file + show-sql: true + database-platform: org.hibernate.dialect.MySQL5InnoDBDialect \ No newline at end of file diff --git a/antdsp-admin/src/main/web/config/router.config.js b/antdsp-admin/src/main/web/config/router.config.js index 673bdc8d53116cda0609cf1acd2d53cea230c811..2246bc7477d2f841d9749a15c24f0f3909d5c800 100644 --- a/antdsp-admin/src/main/web/config/router.config.js +++ b/antdsp-admin/src/main/web/config/router.config.js @@ -1,4 +1,10 @@ export default [ + //login + { + path: '/login', + name: 'login', + component: './Login/Index', + }, // app { path: '/', @@ -7,7 +13,8 @@ export default [ authority: 'admin', routes: [ { - path: '/', redirect: '/system/user', + path: '/', + redirect: '/system/user', }, // dashboard { @@ -32,7 +39,7 @@ export default [ name: 'role', icon: 'team', component: './System/Role/Index', - } + }, ], }, { diff --git a/antdsp-admin/src/main/web/package.json b/antdsp-admin/src/main/web/package.json index 8b71bcb175acf76707b4dcbccf4faf0b8bb3bd83..60cbd32ecf3d9b999609f74a67d7dfd8796d22ca 100644 --- a/antdsp-admin/src/main/web/package.json +++ b/antdsp-admin/src/main/web/package.json @@ -32,11 +32,6 @@ "tslint": "npm run tslint:fix", "tslint:fix": "tslint --fix 'src/**/*.ts*'" }, - "husky": { - "hooks": { - "pre-commit": "npm run lint-staged" - } - }, "lint-staged": { "**/*.less": "stylelint --syntax less", "**/*.{js,jsx}": "npm run lint-staged:js", @@ -53,6 +48,7 @@ "dependencies": { "@antv/data-set": "^0.10.1", "antd": "^3.16.1", + "axios": "^0.19.0", "bizcharts": "^3.4.3", "bizcharts-plugin-slider": "^2.1.1-beta.1", "classnames": "^2.2.6", @@ -60,6 +56,7 @@ "enquire-js": "^0.2.1", "express": "^4.16.4", "gg-editor": "^2.0.2", + "js-md5": "^0.7.3", "lodash": "^4.17.11", "lodash-decorators": "^6.0.1", "memoize-one": "^5.0.0", diff --git a/antdsp-admin/src/main/web/src/components/GlobalHeader/RightContent.js b/antdsp-admin/src/main/web/src/components/GlobalHeader/RightContent.js index d40e1166c670af5955030dff1278d2747aa2e655..3755c0392b66f38bbfb72597448e040ecddf0ea4 100644 --- a/antdsp-admin/src/main/web/src/components/GlobalHeader/RightContent.js +++ b/antdsp-admin/src/main/web/src/components/GlobalHeader/RightContent.js @@ -78,14 +78,6 @@ export default class GlobalHeaderRight extends PureComponent { - - - - - - - - @@ -116,63 +108,7 @@ export default class GlobalHeaderRight extends PureComponent { console.log('enter', value); // eslint-disable-line }} /> - - - - - - { - console.log(item, tabProps); // eslint-disable-line - this.changeReadState(item, tabProps); - }} - loading={fetchingNotices} - locale={{ - emptyText: formatMessage({ id: 'component.noticeIcon.empty' }), - clear: formatMessage({ id: 'component.noticeIcon.clear' }), - viewMore: formatMessage({ id: 'component.noticeIcon.view-more' }), - notification: formatMessage({ id: 'component.globalHeader.notification' }), - message: formatMessage({ id: 'component.globalHeader.message' }), - event: formatMessage({ id: 'component.globalHeader.event' }), - }} - onClear={onNoticeClear} - onPopupVisibleChange={onNoticeVisibleChange} - onViewMore={() => message.info('Click on view more')} - clearClose - > - - - - - {currentUser.name ? ( + {currentUser.realname ? ( - {currentUser.name} + {currentUser.realname} ) : ( diff --git a/antdsp-admin/src/main/web/src/components/SelectLang/index.js b/antdsp-admin/src/main/web/src/components/SelectLang/index.js index 3ce3fb8d3634b21f8471135e0a5da1db9c63d9d0..0151a980aef22eb3899f32dd9ff1cc4a9a5f97da 100644 --- a/antdsp-admin/src/main/web/src/components/SelectLang/index.js +++ b/antdsp-admin/src/main/web/src/components/SelectLang/index.js @@ -13,18 +13,18 @@ export default class SelectLang extends PureComponent { render() { const { className } = this.props; const selectedLang = getLocale(); - const locales = ['zh-CN', 'zh-TW', 'en-US', 'pt-BR']; + const locales = ['zh-CN', 'en-US']; const languageLabels = { 'zh-CN': '简体中文', - 'zh-TW': '繁体中文', + // 'zh-TW': '繁体中文', 'en-US': 'English', - 'pt-BR': 'Português', + // 'pt-BR': 'Português', }; const languageIcons = { 'zh-CN': '🇨🇳', - 'zh-TW': '🇭🇰', + // 'zh-TW': '🇭🇰', 'en-US': '🇬🇧', - 'pt-BR': '🇧🇷', + // 'pt-BR': '🇧🇷', }; const langMenu = ( diff --git a/antdsp-admin/src/main/web/src/locales/zh-CN/menu.js b/antdsp-admin/src/main/web/src/locales/zh-CN/menu.js index 3cb2b0620dfa937f2b228c64d908a9bfca2d0370..ef574614d5a1b8d38da5551fbfe917c4f41a23b0 100644 --- a/antdsp-admin/src/main/web/src/locales/zh-CN/menu.js +++ b/antdsp-admin/src/main/web/src/locales/zh-CN/menu.js @@ -3,5 +3,7 @@ export default { 'menu.system': '系统管理', 'menu.system.user': '用户管理', 'menu.system.menu': '菜单管理', - 'menu.system.role': '角色管理' + 'menu.system.role': '角色管理', + 'menu.account.center': '个人中心', + 'menu.account.logout': '退出登录', }; diff --git a/antdsp-admin/src/main/web/src/models/login.js b/antdsp-admin/src/main/web/src/models/login.js index b5d226aa6bb893f569ba9a3b868116f34bf0e3ed..122a452af5d733be08cda2f91add30cd6061f72c 100644 --- a/antdsp-admin/src/main/web/src/models/login.js +++ b/antdsp-admin/src/main/web/src/models/login.js @@ -4,6 +4,7 @@ import { fakeAccountLogin, getFakeCaptcha } from '@/services/api'; import { setAuthority } from '@/utils/authority'; import { getPageQuery } from '@/utils/utils'; import { reloadAuthorized } from '@/utils/Authorized'; +import { loginAction, logoutAction } from '@/services/login' export default { namespace: 'login', @@ -13,14 +14,15 @@ export default { }, effects: { - *login({ payload }, { call, put }) { - const response = yield call(fakeAccountLogin, payload); - yield put({ - type: 'changeLoginStatus', - payload: response, - }); - // Login successfully - if (response.status === 'ok') { + *login({ payload ,callback}, { call, put }) { + const response = yield call(loginAction, payload); + + if(response.success){ + yield put({ + type: 'changeLoginStatus', + payload: { authority: 'admin', sessionId: response.message }, + }); + reloadAuthorized(); const urlParams = new URL(window.location.href); const params = getPageQuery(); @@ -32,11 +34,16 @@ export default { if (redirect.match(/^\/.*#/)) { redirect = redirect.substr(redirect.indexOf('#') + 1); } + if(redirect.indexOf('/antdsp') == 0){ + redirect = redirect.substr(7); + } } else { redirect = null; } } yield put(routerRedux.replace(redirect || '/')); + }else { + if(callback) callback(response); } }, @@ -44,20 +51,20 @@ export default { yield call(getFakeCaptcha, payload); }, - *logout(_, { put }) { + *logout(_, { call , put }) { + + yield call(logoutAction); + yield put({ type: 'changeLoginStatus', - payload: { - status: false, - currentAuthority: 'guest', - }, + payload: { authority: 'guest', sessionId: null}, }); reloadAuthorized(); // redirect - if (window.location.pathname !== '/user/login') { + if (window.location.pathname !== '/login') { yield put( routerRedux.replace({ - pathname: '/user/login', + pathname: '/login', search: stringify({ redirect: window.location.href, }), @@ -69,7 +76,7 @@ export default { reducers: { changeLoginStatus(state, { payload }) { - setAuthority(payload.currentAuthority); + setAuthority(payload.authority , payload.sessionId); return { ...state, status: payload.status, diff --git a/antdsp-admin/src/main/web/src/models/menu.js b/antdsp-admin/src/main/web/src/models/menu.js index 3d98f2d846434bc3da4a1b220a9f60f3643edbc7..9459ff198e1d56637a780bf4f9a056cb6095070b 100644 --- a/antdsp-admin/src/main/web/src/models/menu.js +++ b/antdsp-admin/src/main/web/src/models/menu.js @@ -3,6 +3,7 @@ import isEqual from 'lodash/isEqual'; import { formatMessage } from 'umi-plugin-react/locale'; import Authorized from '@/utils/Authorized'; import { menu } from '../defaultSettings'; +import { queryRoleMenus } from '@/services/system' const { check } = Authorized; @@ -108,10 +109,12 @@ export default { }, effects: { - *getMenuData({ payload }, { put }) { + *getMenuData({ payload }, {call , put }) { const { routes, authority, path } = payload; const originalMenuData = memoizeOneFormatter(routes, authority, path); - const menuData = filterMenuData(originalMenuData); + // const menuData = filterMenuData(originalMenuData); + const roleMenus = yield call(queryRoleMenus); + const menuData = roleMenus.children || []; const breadcrumbNameMap = memoizeOneGetBreadcrumbNameMap(originalMenuData); yield put({ type: 'save', diff --git a/antdsp-admin/src/main/web/src/pages/Login/Index.js b/antdsp-admin/src/main/web/src/pages/Login/Index.js new file mode 100644 index 0000000000000000000000000000000000000000..af69fe2b2656947b26c7e1777268e0e8dbc65cd8 --- /dev/null +++ b/antdsp-admin/src/main/web/src/pages/Login/Index.js @@ -0,0 +1,90 @@ +import { PureComponent } from 'react'; +import { connect } from 'dva'; +import { Card, Form, Input, Icon, Button, message } from 'antd'; +import Block from '@/custom/Block'; +import styles from './style.less'; +import md5 from 'js-md5' + +const FormItem = Form.Item; + +@connect(({ login })=>({ + login +})) +@Form.create() +export default class Login extends PureComponent{ + + state={ + btnLoading: false + } + + handlerLogin=()=>{ + const { form, dispatch } = this.props; + + this.setState({btnLoading: true}); + + form.validateFields((err , fieldsValue)=>{ + if(err) return this.setState({btnLoading: false}); + + const loginname = fieldsValue.loginname; + let password = fieldsValue.password; + dispatch({ + type: 'login/login', + payload:{ + loginname: loginname, + password: md5(password) + }, + callback:(result)=>{ + message.error(result.message); + this.setState({btnLoading: false}); + } + }) + + }); + } + + render(){ + + const { + form: { getFieldDecorator }, + } = this.props; + + return( +
+
+
+
Antdsp Login Page
+
+
+ + {getFieldDecorator('loginname',{ + initialValue: 'jt-lee', + rules: [{ + required: true, + message: '请输入登录名', + }] + })( + } placeholder="用户名" /> + )} + + + {getFieldDecorator('password',{ + initialValue: '123456', + rules: [{ + required: true, + message: '请输入密码', + }] + })( + } type="password" placeholder="密 码" /> + )} + + + + +
+
+
+
+
+ ) + } +} \ No newline at end of file diff --git a/antdsp-admin/src/main/web/src/pages/Login/style.less b/antdsp-admin/src/main/web/src/pages/Login/style.less new file mode 100644 index 0000000000000000000000000000000000000000..fa972d7664b279f2f546c9b7732a0bd87ce03b02 --- /dev/null +++ b/antdsp-admin/src/main/web/src/pages/Login/style.less @@ -0,0 +1,21 @@ +@import '~antd/lib/style/themes/default.less'; + +.container{ + display: flex; + height: 100%; + flex-direction: column; + background-color: #20815d; +} + +.main{ + width: 360px; + color: #fff; + margin: 0 auto; + margin-top: 150px; + .title{ + text-align: center; + font-size: 32px; + font-weight: bold; + margin-bottom: 20px; + } +} \ No newline at end of file diff --git a/antdsp-admin/src/main/web/src/pages/System/User/Index.js b/antdsp-admin/src/main/web/src/pages/System/User/Index.js index 1185b4c620b3626960429bb3585f279b30a6861c..5bfafcfd0e1205b81611292be58a165bc38ab861 100644 --- a/antdsp-admin/src/main/web/src/pages/System/User/Index.js +++ b/antdsp-admin/src/main/web/src/pages/System/User/Index.js @@ -1,365 +1,434 @@ -import { PureComponent, Fragment } from "react"; +import { PureComponent, Fragment } from 'react'; import { connect } from 'dva'; import PageHeaderWrapper from '@/components/PageHeaderWrapper'; import Block from '@/custom/Block'; -import { Card, Form, Button, Table, Divider, Input, Select, Modal, message, Popconfirm } from "antd"; +import { + Card, + Form, + Button, + Table, + Divider, + Input, + Select, + Modal, + message, + Popconfirm, + Checkbox, +} from 'antd'; +import md5 from 'js-md5' const FormItem = Form.Item; const UserStatus = { - "NORMAL": "正常", - "FORBIDDEN": "异常" -} + NORMAL: '正常', + FORBIDDEN: '异常', +}; -@connect(({ systemuser , loading })=>({ - systemuser, - loading: loading.models.systemuser +@connect(({ systemuser, loading }) => ({ + systemuser, + loading: loading.models.systemuser, })) @Form.create() -export default class extends PureComponent{ - - state={ - confirmLoading: false, - visible: false, - current:{}, - formValue: { - page: 1, - count: 10, - } - } - - componentDidMount(){ - const { dispatch } = this.props; - dispatch({ - type: 'systemuser/fetchAll', - payload:{ +export default class extends PureComponent { + state = { + confirmLoading: false, + visible: false, + current: {}, + formValue: { + page: 1, + count: 10, + }, + }; + + componentDidMount() { + const { dispatch } = this.props; + dispatch({ + type: 'systemuser/fetchAll', + payload: { + page: 1, + count: 10, + }, + }); + } + + handlerQueryOnClick = () => { + const { form, dispatch } = this.props; + form.validateFields((err, fieldsValue) => { + let { formValue } = this.state.formValue; + formValue = { + ...fieldsValue, + page: 1, + count: 10, + }; + this.setState({ formValue }); + + dispatch({ + type: 'systemuser/fetchAll', + payload: { + ...formValue, + }, + }); + }); + }; + + renderQueryForm = () => { + const { getFieldDecorator } = this.props.form; + + return ( + +
+ + {getFieldDecorator('loginname')()} + + + {getFieldDecorator('status')( + + )} + + + + +
+
+ ); + }; + + handlerTableOnChange = (pagination, filters, sorter) => { + const { dispatch } = this.props; + let { formValue } = this.state; + + formValue = { + ...formValue, + page: pagination.current, + count: pagination.pageSize, + }; + + this.setState({ + formValue: { + ...formValue, + }, + }); + + dispatch({ + type: 'systemuser/fetchAll', + payload: { + ...formValue, + }, + }); + }; + + showModal = currentObj => { + + const { dispatch } = this.props; + + dispatch({ + type: 'systemuser/fetchOne', + payload:{ + id: currentObj.id || 0 + } + }); + + this.setState({ + confirmLoading: false, + visible: true + }) + }; + + handlerModalOnOk = e => { + e.preventDefault(); + this.setState({ + confirmLoading: true, + }); + const { form } = this.formRef.props; + const { dispatch } = this.props; + form.validateFields((err, fieldsValue) => { + if (err) return this.setState({ confirmLoading: false }); + + const { detail } = this.props.systemuser; + let password = fieldsValue.password; + const roleIds = fieldsValue.roleIds; + delete fieldsValue.roleIds; + if(password){ + fieldsValue.password = md5(password); + } + + let currentObj = { + ...detail.user, + ...fieldsValue, + }; + dispatch({ + type: 'systemuser/save', + payload: { + user: currentObj, + roleIds: roleIds, + }, + callback: result => { + if (result.success) { + this.setState({ + confirmLoading: false, + visible: false, + }); + dispatch({ + type: 'systemuser/fetchAll', + payload: { page: 1, count: 10, - } - }) - } - - handlerQueryOnClick=()=>{ - const { form , dispatch } = this.props; - form.validateFields((err , fieldsValue)=>{ - let { formValue } = this.state.formValue; - formValue = { - ...fieldsValue, - page: 1, - count: 10 - }; - this.setState({formValue}); - - dispatch({ - type: 'systemuser/fetchAll', - payload: { - ...formValue - } - }) - }); - } - - renderQueryForm=()=>{ - - const{ getFieldDecorator } = this.props.form; - - return( - -
- - {getFieldDecorator("loginname")( - - )} - - - {getFieldDecorator("status")( - - )} - - - - -
-
- ) - } - - handlerTableOnChange=(pagination , filters , sorter)=>{ - const { dispatch } = this.props; - let { formValue } = this.state; - - formValue = { - ...formValue, - page: pagination.current, - count: pagination.pageSize, - } - - this.setState({ - formValue:{ - ...formValue, - } - }); - - dispatch({ - type: 'systemuser/fetchAll', - payload:{ - ...formValue, - } - }) - } - - showModal=(currentObj)=>{ - this.setState({ - current: currentObj, - confirmLoading: false, - visible: true, - }) - } - - handlerModalOnOk=(e)=>{ - - e.preventDefault(); - this.setState({ - confirmLoading : true , - }); - const { form } = this.formRef.props; - const { dispatch } = this.props; - form.validateFields((err , fieldsValue)=>{ - if(err) return this.setState({confirmLoading: false}); - - const {current} = this.state; - let currentObj = { - ...current, - ...fieldsValue - }; - dispatch({ - type: 'systemuser/save', - payload:{ - user: currentObj - }, - callback: (result)=>{ - - if(result.success){ - this.setState({ - confirmLoading: false, - visible: false, - }); - dispatch({ - type: 'systemuser/fetchAll', - payload:{ - page: 1, - count: 10 - } - }); - }else { - message.error(result.message); - this.setState({confirmLoading: false}); - } - } + }, }); - }); - } - - handlerDelOnClick=(e , id)=>{ - const { dispatch } = this.props; - dispatch({ - type: 'systemuser/del', - payload:{ - id: id + } else { + message.error(result.message); + this.setState({ confirmLoading: false }); + } + }, + }); + }); + }; + + handlerDelOnClick = (e, id) => { + const { dispatch } = this.props; + dispatch({ + type: 'systemuser/del', + payload: { + id: id, + }, + callback: result => { + if (result.success) { + dispatch({ + type: 'systemuser/fetchAll', + payload: { + ...this.state.formValue, }, - callback:(result)=>{ - if(result.success){ - dispatch({ - type: 'systemuser/fetchAll', - payload:{ - ...this.state.formValue - } - }); - }else { - message.error(result.message); - } - } - }); - } - - render(){ - - const { systemuser:{UserList}, loading } = this.props; - - const columns = [{ - title: '头像', - dataIndex: 'avatar', - },{ - title: '登录名', - dataIndex: 'loginname', - },{ - title: '真实姓名', - dataIndex: 'realname', - },{ - title: 'Email', - dataIndex: 'email', - },{ - title: 'QQ', - dataIndex: 'qq', - },{ - title: '状态', - dataIndex: 'status', - },{ - title: '操作', - render:(record)=>{ - return ( - - {this.showModal(record)}}>编辑 - - {this.handlerDelOnClick(e ,record.id)}}> - 删除 - - - ) - } - }] - - return ( - - - {this.renderQueryForm()} - - - - - - {this.setState({visible: false})}} - onOk={this.handlerModalOnOk} - confirmLoading={this.state.confirmLoading} - destroyOnClose={true} - > - - this.formRef= formRef} current={this.state.current} /> - - - - ) - } + }); + } else { + message.error(result.message); + } + }, + }); + }; + + render() { + const { + systemuser: { UserList, detail }, + loading, + } = this.props; + + const columns = [ + { + title: '头像', + dataIndex: 'avatar', + }, + { + title: '登录名', + dataIndex: 'loginname', + }, + { + title: '真实姓名', + dataIndex: 'realname', + }, + { + title: 'Email', + dataIndex: 'email', + }, + { + title: 'QQ', + dataIndex: 'qq', + }, + { + title: '状态', + dataIndex: 'status', + render: value => {UserStatus[value]}, + }, + { + title: '操作', + render: record => { + return ( + + { + this.showModal(record); + }} + > + 编辑 + + + { + this.handlerDelOnClick(e, record.id); + }} + > + + 删除 + + + + ); + }, + }, + ]; + + return ( + + + {this.renderQueryForm()} + + + + +
+ { + this.setState({ visible: false }); + }} + onOk={this.handlerModalOnOk} + confirmLoading={this.state.confirmLoading} + destroyOnClose={true} + > + (this.formRef = formRef)} + detail={detail} + /> + + + + ); + } } - @Form.create() -export class EditUser extends PureComponent{ - - compareToPassword=(rule , value , callback)=>{ - const form = this.props.form; - if (value && value !== form.getFieldValue('password')) { - callback('两次密码输入不一致'); - } else { - callback(); - } +export class EditUser extends PureComponent { + compareToPassword = (rule, value, callback) => { + const form = this.props.form; + if (value && value !== form.getFieldValue('password')) { + callback('两次密码输入不一致'); + } else { + callback(); } + }; - render(){ - - const { getFieldDecorator } = this.props.form; - const { current } = this.props; + roleToNameId(roleNameId){ + + let newRoleNameId=[]; - const flag = (Object.keys(current).length == 0); - - const formItemLayout = { - labelCol:{ - xs: { span : 4}, - sm: { span : 4 }, - }, - wrapperCol:{ - xs: { span : 12}, - sm: { span : 12 }, - } + roleNameId.map((item=>{ + let nameid = { + label: item.roleName, + value: item.id, } + newRoleNameId.push(nameid); + })); + return newRoleNameId; +} - return( + render() { + const { getFieldDecorator } = this.props.form; + const { detail: { user , roleIds , roles} } = this.props; + + const flag = Object.keys(user).length == 0; + + const formItemLayout = { + labelCol: { + xs: { span: 4 }, + sm: { span: 4 }, + }, + wrapperCol: { + xs: { span: 12 }, + sm: { span: 12 }, + }, + }; + + return ( +
+
+ + {getFieldDecorator('loginname', { + initialValue: user.loginname, + rules: [ + { + required: true, + message: '请输入登录名', + }, + ], + })()} + + {flag ? (
- - - {getFieldDecorator('loginname',{ - initialValue: current.loginname, - rules:[ - { - required: true, - message: '请输入登录名', - } - ] - })( - - )} - + + {getFieldDecorator('password', { + rules: [ + { + required: true, + message: '请输入密码', + }, + ], + })()} + + + {getFieldDecorator('repassword', { + rules: [ { - flag ? -
- - {getFieldDecorator("password",{ - rules:[ - { - required: true, - message: '请输入密码', - } - ] - })( - - )} - - - {getFieldDecorator("repassword",{ - rules:[ - { - required: true, - message: '请输入密码', - },{ - validator:this.compareToPassword, - } - ] - })( - - )} - -
- : - null - } - - {getFieldDecorator("realname",{ - initialValue: current.realname, - })( - - )} - - - {getFieldDecorator("email",{ - initialValue: current.email, - })( - - )} - - - {getFieldDecorator("qq",{ - initialValue: current.qq, - })( - - )} - - + required: true, + message: '请输入密码', + }, + { + validator: this.compareToPassword, + }, + ], + })()} +
- ) - } -} \ No newline at end of file + ) : null} + + {getFieldDecorator('realname', { + initialValue: user.realname, + })()} + + + {getFieldDecorator('email', { + initialValue: user.email, + })()} + + + {getFieldDecorator('qq', { + initialValue: user.qq, + })()} + + + { + getFieldDecorator('roleIds',{ + initialValue: flag ? [] : roleIds + })( + + ) + } + + +
+ ); + } +} diff --git a/antdsp-admin/src/main/web/src/pages/System/User/models/user.js b/antdsp-admin/src/main/web/src/pages/System/User/models/user.js index 3460b77a727ba984928cc6646d869a6a28150593..ce228601c88c07a58177cc96516747e0dd3d8bc8 100644 --- a/antdsp-admin/src/main/web/src/pages/System/User/models/user.js +++ b/antdsp-admin/src/main/web/src/pages/System/User/models/user.js @@ -2,7 +2,9 @@ import { fetchAllUser, addUser, updateUser, - delUserById + delUserById, + queryRoles, + fetchUser } from '@/services/system'; export default { @@ -12,6 +14,11 @@ export default { UserList:{ data:[], pagination:{} + }, + detail:{ + user: {}, + roleIds:[], + roles: [], } }, @@ -27,15 +34,29 @@ export default { const user = payload.user; let response ; if(!user.id){ - response = yield call(addUser , user); + response = yield call(addUser , payload); }else { - response = yield call(updateUser , user); + response = yield call(updateUser , payload); } if(callback) callback(response); }, *del({payload , callback},{call}){ const response = yield call(delUserById , payload); if(callback) callback(response); + }, + *fetchRoles({callback}, {call}){ + const response = yield call(queryRoles); + console.log(response); + if(callback) callback(response); + }, + *fetchOne({payload},{call , put}){ + + const response = yield call(fetchUser , payload); + + yield put({ + type: "reducersDetail", + payload: response, + }) } }, @@ -47,6 +68,16 @@ export default { ...action.payload } } + }, + reducersDetail(state, { payload}){ + return { + ...state, + detail: { + user: payload.user || {}, + roleIds: payload.roleIds || [], + roles: payload.roles || [], + }, + } } } } \ No newline at end of file diff --git a/antdsp-admin/src/main/web/src/services/login.js b/antdsp-admin/src/main/web/src/services/login.js new file mode 100644 index 0000000000000000000000000000000000000000..dab0ddb7d12ad75e06931522aabd4ba992a027f3 --- /dev/null +++ b/antdsp-admin/src/main/web/src/services/login.js @@ -0,0 +1,17 @@ +import { stringify } from 'qs'; +import request from '@/utils/request'; + +const API_BASE = "/antdsp-api"; + +export async function loginAction(param){ + return request(`${API_BASE}/login`,{ + method: 'POST', + data: { + ...param + } + }) +} + +export async function logoutAction(param){ + return request(`${API_BASE}/logout`); +} \ No newline at end of file diff --git a/antdsp-admin/src/main/web/src/services/system.js b/antdsp-admin/src/main/web/src/services/system.js index f4f4fee4356af091bef001339f4f83f8d932659d..7d58febf84d61e8fd55a72102b811f28bea819d0 100644 --- a/antdsp-admin/src/main/web/src/services/system.js +++ b/antdsp-admin/src/main/web/src/services/system.js @@ -21,7 +21,8 @@ export async function addUser(params){ } export async function updateUser(params){ - return request(`${USER_API}/${params.id}`,{ + const userId = params.user.id; + return request(`${USER_API}/${userId}`,{ method: 'PUT', data:{ ...params @@ -35,6 +36,12 @@ export async function delUserById(params){ }); } +export async function fetchUser(params){ + return request(`${USER_API}/${params.id}`,{ + method: 'GET' + }); +} + export async function fetchAllMenu(){ return request(`${MENU_API}`) } @@ -93,4 +100,12 @@ export async function delRoleById(param){ export async function fetchRoleById(param){ return request(`${ROLE_API}/${param.id}`); +} + +export async function queryRoles(){ + return request(`${ROLE_API}/queryRoleNameAndIds`); +} + +export async function queryRoleMenus(){ + return request(`${MENU_API}/route`); } \ No newline at end of file diff --git a/antdsp-admin/src/main/web/src/services/user.js b/antdsp-admin/src/main/web/src/services/user.js index 89e03c6f67b2ba505e429b2c9afbcb40142508aa..bc16023b57b2cae3284ff213d4254e6d30f42eaa 100644 --- a/antdsp-admin/src/main/web/src/services/user.js +++ b/antdsp-admin/src/main/web/src/services/user.js @@ -5,5 +5,5 @@ export async function query() { } export async function queryCurrent() { - return request('/api/currentUser'); + return request('/antdsp-api/system/user/current'); } diff --git a/antdsp-admin/src/main/web/src/utils/authority.js b/antdsp-admin/src/main/web/src/utils/authority.js index bb1aa23bc6156a94173a0477e1f8d45b937d2c91..2cb59f4afb6b040e2147b86b5c9a1820648dde1d 100644 --- a/antdsp-admin/src/main/web/src/utils/authority.js +++ b/antdsp-admin/src/main/web/src/utils/authority.js @@ -1,8 +1,10 @@ +import { setAuthorization } from './request'; + // use localStorage to store the authority info, which might be sent from server in actual project. export function getAuthority(str) { // return localStorage.getItem('antd-pro-authority') || ['admin', 'user']; const authorityString = - typeof str === 'undefined' ? localStorage.getItem('antd-pro-authority') : str; + typeof str === 'undefined' ? localStorage.getItem('antdsp-authority') : str; // authorityString could be admin, "admin", ["admin"] let authority; try { @@ -13,13 +15,11 @@ export function getAuthority(str) { if (typeof authority === 'string') { return [authority]; } - // preview.pro.ant.design only do not use in your production ; preview.pro.ant.design 专用环境变量,请不要在你的项目中使用它。 - if (!authority && ANT_DESIGN_PRO_ONLY_DO_NOT_USE_IN_YOUR_PRODUCTION === 'site') { - return ['admin']; - } - return authority; + return authority || ['guest']; } -export function setAuthority(authority) { +export function setAuthority(authority,sessionId) { const proAuthority = typeof authority === 'string' ? [authority] : authority; - return localStorage.setItem('antd-pro-authority', JSON.stringify(proAuthority)); + if(sessionId) setAuthorization(sessionId); + return localStorage.setItem('antdsp-authority', JSON.stringify(proAuthority)); } + diff --git a/antdsp-admin/src/main/web/src/utils/request.js b/antdsp-admin/src/main/web/src/utils/request.js index 0801b1d4b1cb0dc8c1bc86ce7f70e9a3457b364e..67cabd4ca52474f987570735c95223dc1cf1c971 100644 --- a/antdsp-admin/src/main/web/src/utils/request.js +++ b/antdsp-admin/src/main/web/src/utils/request.js @@ -2,10 +2,12 @@ * request 网络请求工具 * 更详细的api文档: https://bigfish.alipay.com/doc/api#request */ -import { extend } from 'umi-request'; +import { extend , fetch } from 'umi-request'; import { notification } from 'antd'; import router from 'umi/router'; +var Authorization = ""; + const codeMessage = { 200: '服务器成功返回请求的数据。', 201: '新建或修改数据成功。', @@ -67,6 +69,43 @@ const errorHandler = error => { const request = extend({ errorHandler, // 默认错误处理 credentials: 'include', // 默认请求是否带上cookie + headers:{ + Authorization: Authorization, + } }); +//response 的拦截器, response 为一个Response 对象 , options 为request 参数 +fetch.interceptors.response.use(async function (response , options) { + const result = await response.clone().json(); + + if(typeof result.success === 'undefined'){ + return response; + }else if(result.success){ + return response; + }else { + customErrorHandler(result); + } + return response; +}); + +const customErrorHandler = error =>{ + const { code , message } = error; + if(code == 1401){ + notification.error({ + message: '未登录或登录已过期,请重新登录。', + }); + window.g_app._store.dispatch({ + type: 'login/logout', + }); + return; + } + notification.error({ + message: `请求错误 ${code}: ${message}`, + }); +} + +export function setAuthorization(authorization){ + Authorization = authorization; +} + export default request; diff --git a/antdsp-core/.gitignore b/antdsp-core/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b83d22266ac8aa2f8df2edef68082c789727841d --- /dev/null +++ b/antdsp-core/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/antdsp-core/src/main/java/com/antdsp/dao/jpa/AntdspBaseRepository.java b/antdsp-core/src/main/java/com/antdsp/dao/jpa/AntdspBaseRepository.java index f2d5183d602b9fd8b51f74c1828edf9251cb1d64..fa99ea3f9a901531a1bd2c13047284473f229816 100644 --- a/antdsp-core/src/main/java/com/antdsp/dao/jpa/AntdspBaseRepository.java +++ b/antdsp-core/src/main/java/com/antdsp/dao/jpa/AntdspBaseRepository.java @@ -24,7 +24,39 @@ import org.springframework.data.repository.NoRepositoryBean; @NoRepositoryBean public interface AntdspBaseRepository extends JpaRepository , JpaSpecificationExecutor{ + /** + * 执行SQL语句(update, insert, delete),表名、字段名和数据库对应 + * @param sqlString SQL语句 + * @param params 参数 + * @return + */ int executeSQL(String sqlString , Map params); - List queryAllBySQL(String sqlStr , Map params); + /** + * 一般的SQL语句(select),表名、字段名和数据库对应 + * @param sqlString + * @param params + * @return + */ + List queryBySQL(String sqlStr , Map params, Class clazz); + + /** + * (select) 多表联合查询,表名、字段名和实体类对应 + * @param sqlStr + * @param params + * @return + */ + List selectUnion(String queryStr , Map params , Class clazz); + + /** + * 分页(select) 多表联合查询,表名、字段名和实体类对应 + * @param sqlStr + * @param params + * @param clazz + * @param start + * @param count + * @return + */ + List selectUnion(String queryStr , Map params , Class clazz, int start, int count); + } diff --git a/antdsp-core/src/main/java/com/antdsp/dao/jpa/AntdspBaseRepositoryImpl.java b/antdsp-core/src/main/java/com/antdsp/dao/jpa/AntdspBaseRepositoryImpl.java index 57760e48f837fe6384f49120960110520c4ff917..2ca6fcfc7281a92990af727e9aeb6fd47b5c03fb 100644 --- a/antdsp-core/src/main/java/com/antdsp/dao/jpa/AntdspBaseRepositoryImpl.java +++ b/antdsp-core/src/main/java/com/antdsp/dao/jpa/AntdspBaseRepositoryImpl.java @@ -7,6 +7,7 @@ import java.util.Map; import javax.persistence.EntityManager; import javax.persistence.Query; +import javax.persistence.TypedQuery; import org.springframework.data.jpa.repository.support.SimpleJpaRepository; @@ -54,11 +55,32 @@ public class AntdspBaseRepositoryImpl extends Simple } @Override - public List queryAllBySQL(String sqlStr, Map params) { + public List selectUnion(String queryStr, Map params, Class clazz) { - Query query = em.createNativeQuery(sqlStr); + TypedQuery query = em.createQuery(queryStr, clazz); this.querySetParameter(query, params); return query.getResultList(); } + @Override + public List selectUnion(String queryStr, Map params, Class clazz, int start, int count) { + + TypedQuery query = em.createQuery(queryStr, clazz); + this.querySetParameter(query, params); + query.setFirstResult(start).setMaxResults(count); + return query.getResultList(); + } + + @Override + public List queryBySQL(String sqlStr, Map params, Class clazz) { + + Query query; + if(clazz == null) { + query = em.createNativeQuery(sqlStr); + }else { + query = em.createNativeQuery(sqlStr, clazz); + } + this.querySetParameter(query, params); + return query.getResultList(); + } } diff --git a/antdsp-core/src/main/java/com/antdsp/dao/jpa/UserJpa.java b/antdsp-core/src/main/java/com/antdsp/dao/jpa/UserJpa.java index 49432db813ddfcbaf199fa758e65a76b4ae451dd..073914031804ec3bb0ed34e197eee2f8ac61c8b5 100644 --- a/antdsp-core/src/main/java/com/antdsp/dao/jpa/UserJpa.java +++ b/antdsp-core/src/main/java/com/antdsp/dao/jpa/UserJpa.java @@ -1,7 +1,8 @@ package com.antdsp.dao.jpa; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import java.util.List; + +import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; @@ -9,9 +10,16 @@ import org.springframework.stereotype.Repository; import com.antdsp.data.entity.User; @Repository("userJpa") -public interface UserJpa extends JpaRepository , JpaSpecificationExecutor{ +public interface UserJpa extends AntdspBaseRepository{ @Query("From User WHERE loginname = :loginName AND status = 'NORMAL'") User queryUserByLoginName(@Param("loginName") String loginName); + + @Query(value="SELECT s.role_id FROM `tb_role_user` s WHERE s.user_id = :userId ", nativeQuery=true) + List queryUserRoleId(@Param("userId") Long userId); + + @Modifying + @Query(value="DELETE FROM `tb_role_user` WHERE user_id = :userId " , nativeQuery=true) + void deleteUserRoleId(@Param("userId") Long userId); } diff --git a/antdsp-core/src/main/java/com/antdsp/dao/jpa/system/MenuJpa.java b/antdsp-core/src/main/java/com/antdsp/dao/jpa/system/MenuJpa.java index 6bb2c54070c17c3cb16a0741da7880179c8dbd41..74f9b09a7dd99380808aafa77da0281a72d0253f 100644 --- a/antdsp-core/src/main/java/com/antdsp/dao/jpa/system/MenuJpa.java +++ b/antdsp-core/src/main/java/com/antdsp/dao/jpa/system/MenuJpa.java @@ -1,12 +1,24 @@ package com.antdsp.dao.jpa.system; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import java.util.List; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import com.antdsp.dao.jpa.AntdspBaseRepository; import com.antdsp.data.entity.system.SystemMenu; @Repository("menuJpa") -public interface MenuJpa extends JpaRepository , JpaSpecificationExecutor{ +public interface MenuJpa extends AntdspBaseRepository{ + + /** + * 根据userId查询所有权限菜单 + * @param userId + * @return + */ + @Query(value="SELECT m.* FROM `tb_system_menu` m , `tb_role_menu` rm , `tb_role_user` ru WHERE " + + " rm.role_id = ru.role_id AND rm.menu_id = m.id AND ru.user_id = :userId " , nativeQuery=true) + List findPermissMenus(@Param("userId") Long userId); } diff --git a/antdsp-core/src/main/java/com/antdsp/dao/jpa/system/RoleJpa.java b/antdsp-core/src/main/java/com/antdsp/dao/jpa/system/RoleJpa.java index b7e3ed71bc3b4d5ebd01e23358c2f719b5cc7329..145762339599ea1a99b2bb53a080101d2bf13fa8 100644 --- a/antdsp-core/src/main/java/com/antdsp/dao/jpa/system/RoleJpa.java +++ b/antdsp-core/src/main/java/com/antdsp/dao/jpa/system/RoleJpa.java @@ -1,5 +1,10 @@ package com.antdsp.dao.jpa.system; +import java.util.List; + +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import com.antdsp.dao.jpa.AntdspBaseRepository; @@ -7,5 +12,21 @@ import com.antdsp.data.entity.system.SystemRole; @Repository("roleJpa") public interface RoleJpa extends AntdspBaseRepository{ + + @Query("FROM SystemRole s ORDER BY s.created") + List findRoleNameAndIds(); + + /** + * 根据roleId查询角色下所有的菜单信息 + * @param roleId + * @return + */ + @Query(value="SELECT r.menu_id FROM tb_role_menu r LEFT JOIN tb_system_menu sr ON r.menu_id = sr.id WHERE " + + " r.role_id = :roleId AND sr.menu_type = 'BUTTON' " , nativeQuery=true) + List queryRoleMenuId(@Param("roleId")Long roleId); + + @Modifying + @Query(value="DELETE FROM `tb_role_menu` WHERE `role_id` = :roleId", nativeQuery=true) + void deleteRoleMenuByRoleId(@Param("roleId")Long roleId); } diff --git a/antdsp-core/src/main/java/com/antdsp/data/entityeenum/UserStatus.java b/antdsp-core/src/main/java/com/antdsp/data/entityeenum/UserStatus.java index ab9fab3d5b42c9d84efa6105decb1bb02e7b6984..98dfada1b78b57ba0cced3fe38ab6fe384a50aeb 100644 --- a/antdsp-core/src/main/java/com/antdsp/data/entityeenum/UserStatus.java +++ b/antdsp-core/src/main/java/com/antdsp/data/entityeenum/UserStatus.java @@ -2,6 +2,7 @@ package com.antdsp.data.entityeenum; public enum UserStatus { NORMAL("正常"), + DISABLED("已禁用"), FORBIDDEN("异常"); private String value;