From 46eb9a0303a757c9165cc0b6c8b63397c3b94935 Mon Sep 17 00:00:00 2001 From: alikes Date: Tue, 2 Feb 2021 14:12:58 +0800 Subject: [PATCH] sentinel --- ruoyi-api/ruoyi-api-system/pom.xml | 7 + .../ruoyi/system/api/RemoteUserService.java | 35 +- .../factory/RemoteUserFallbackFactory.java | 21 +- .../com/ruoyi/system/api/model/LoginUser.java | 302 +- .../system/api/model/RoleAndPermission.java | 29 + .../com/ruoyi/system/api/model/UserInfo.java | 61 + .../ruoyi/auth/config/AuthServerConfig.java | 132 + .../ruoyi/auth/config/WebSecurityConfig.java | 73 + .../auth/controller/TokenController.java | 20 +- .../ruoyi/auth/controller/UserController.java | 22 + .../auth/exception/CustomOauthException.java | 20 + .../CustomOauthExceptionSerializer.java | 49 + .../CustomWebResponseExceptionTranslator.java | 20 + .../AuthenticationSuccessEventHandler.java | 39 + .../ruoyi/auth/service/SysLoginService.java | 9 +- ruoyi-auth/src/main/resources/bootstrap.yml | 7 +- ruoyi-common/ruoyi-common-core/pom.xml | 11 + .../common/core/constant/CacheConstants.java | 10 + .../core/constant/SecurityConstants.java | 56 + .../common/core/utils/SecurityUtils.java | 179 +- .../ruoyi/common/log/aspect/LogAspect.java | 3 +- ruoyi-common/ruoyi-common-security/pom.xml | 8 +- .../annotation/EnableCustomConfig.java | 9 +- .../security/aspect/PreAuthorizeAspect.java | 12 +- .../security/config/AuthIgnoreConfig.java | 31 + .../security/config/CommonUserConverter.java | 75 + .../security/config/MethodSecurityConfig.java | 26 + .../security/config/ResourceServerConfig.java | 82 + ...SecurityImportBeanDefinitionRegistrar.java | 24 + .../feign/FeignAutoConfiguration.java | 40 +- .../common/security/feign/FeignConfig.java | 20 + .../feign/FeignRequestInterceptor.java | 90 +- .../feign/OAuth2FeignRequestInterceptor.java | 33 + .../handler/CustomAccessDeniedHandler.java | 34 + .../handler/CustomLoginSuccessHandler.java | 36 + .../security/service/PermissionService.java | 168 + .../service/RedisClientDetailsService.java | 31 + .../common/security/service/TokenService.java | 25 +- .../service/UserDetailsServiceImpl.java | 84 + .../common/security/utils/SecurityUtils.java | 101 + .../config/SwaggerAutoConfiguration.java | 26 +- .../com/ruoyi/gateway/filter/AuthFilter.java | 250 +- .../src/main/resources/bootstrap.yml | 9 +- .../src/main/resources/bootstrap.yml | 7 +- .../gen/service/GenTableServiceImpl.java | 2 +- .../src/main/resources/bootstrap.yml | 7 +- .../job/controller/SysJobController.java | 2 +- .../src/main/resources/bootstrap.yml | 7 +- ruoyi-modules/ruoyi-sentinel/pom.xml | 31 + .../RuoYiSentinelDashboardApplication.java | 7 +- .../sentinel/dashboard/config/WebConfig.java | 22 +- .../controller/v2/BaseController.java | 17 + .../controller/v2/FlowControllerV2.java | 7 +- .../rule/nacos/DegradeRuleNacosProvider.java | 52 + .../rule/nacos/DegradeRuleNacosPublisher.java | 50 + .../dashboard/rule/nacos/NacosConfig.java | 13 +- .../src/main/resources/application.properties | 26 - .../src/main/resources/application.yml | 50 + .../src/main/resources/bootstrap.yml | 24 + .../app/scripts/controllers/degrade_v2.js | 204 + .../scripts/services/degrade_service_v2.js | 97 + .../resources/app/views/degrade_v2.html | 98 + .../src/main/webapp/resources/yarn.lock | 3324 +++++++++++++++++ .../controller/SysConfigController.java | 2 +- .../system/controller/SysDeptController.java | 2 +- .../controller/SysDictDataController.java | 3 +- .../controller/SysDictTypeController.java | 2 +- .../system/controller/SysMenuController.java | 2 +- .../controller/SysNoticeController.java | 2 +- .../system/controller/SysPostController.java | 2 +- .../controller/SysProfileController.java | 2 +- .../system/controller/SysRoleController.java | 2 +- .../system/controller/SysUserController.java | 9 +- .../service/impl/SysMenuServiceImpl.java | 2 +- .../service/impl/SysUserServiceImpl.java | 2 +- .../src/main/resources/bootstrap.yml | 7 +- ruoyi-ui/src/api/login.js | 136 +- ruoyi-ui/src/store/modules/user.js | 271 +- ruoyi-ui/src/utils/auth.js | 70 +- ruoyi-ui/src/views/login.vue | 407 +- .../src/main/resources/bootstrap.yml | 7 +- sql/ry_config_20210128.sql | 2 +- 82 files changed, 6495 insertions(+), 803 deletions(-) create mode 100644 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/RoleAndPermission.java create mode 100644 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/UserInfo.java create mode 100644 ruoyi-auth/src/main/java/com/ruoyi/auth/config/AuthServerConfig.java create mode 100644 ruoyi-auth/src/main/java/com/ruoyi/auth/config/WebSecurityConfig.java create mode 100644 ruoyi-auth/src/main/java/com/ruoyi/auth/controller/UserController.java create mode 100644 ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomOauthException.java create mode 100644 ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomOauthExceptionSerializer.java create mode 100644 ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomWebResponseExceptionTranslator.java create mode 100644 ruoyi-auth/src/main/java/com/ruoyi/auth/handler/AuthenticationSuccessEventHandler.java create mode 100644 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/SecurityConstants.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/AuthIgnoreConfig.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/CommonUserConverter.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/MethodSecurityConfig.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/ResourceServerConfig.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityImportBeanDefinitionRegistrar.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignConfig.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/OAuth2FeignRequestInterceptor.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/CustomAccessDeniedHandler.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/CustomLoginSuccessHandler.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/PermissionService.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/RedisClientDetailsService.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/UserDetailsServiceImpl.java create mode 100644 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SecurityUtils.java create mode 100644 ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/BaseController.java create mode 100644 ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/DegradeRuleNacosProvider.java create mode 100644 ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/DegradeRuleNacosPublisher.java delete mode 100755 ruoyi-modules/ruoyi-sentinel/src/main/resources/application.properties create mode 100644 ruoyi-modules/ruoyi-sentinel/src/main/resources/application.yml create mode 100644 ruoyi-modules/ruoyi-sentinel/src/main/resources/bootstrap.yml create mode 100755 ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/scripts/controllers/degrade_v2.js create mode 100755 ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/scripts/services/degrade_service_v2.js create mode 100755 ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/views/degrade_v2.html create mode 100644 ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/yarn.lock diff --git a/ruoyi-api/ruoyi-api-system/pom.xml b/ruoyi-api/ruoyi-api-system/pom.xml index edeb4b40..21ad999e 100644 --- a/ruoyi-api/ruoyi-api-system/pom.xml +++ b/ruoyi-api/ruoyi-api-system/pom.xml @@ -22,6 +22,13 @@ com.ruoyi ruoyi-common-core + + + + org.springframework.security + spring-security-core + provided + diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java index 5140d416..69243fec 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteUserService.java @@ -1,5 +1,7 @@ package com.ruoyi.system.api; +import com.ruoyi.system.api.model.RoleAndPermission; +import com.ruoyi.system.api.model.UserInfo; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -8,6 +10,8 @@ import com.ruoyi.common.core.domain.R; import com.ruoyi.system.api.factory.RemoteUserFallbackFactory; import com.ruoyi.system.api.model.LoginUser; +import java.util.Set; + /** * 用户服务 * @@ -23,5 +27,34 @@ public interface RemoteUserService * @return 结果 */ @GetMapping(value = "/user/info/{username}") - public R getUserInfo(@PathVariable("username") String username); + public R getUserInfo(@PathVariable("username") String username); + + /** + * 根据用户id查询角色 + * + * @param userId 用户名 + * @return 结果 + */ + @GetMapping(value = "/user/roles/{userId}") + public R> getRoles(@PathVariable("userId") Long userId); + + /** + * 根据用户id查询权限 + * @param userId + * @return + */ + @GetMapping(value = "/user/permissions/{userId}") + public R> getPermissions(@PathVariable("userId") Long userId); + + + /** + * 根据用户id查询角色和权限 + * + * @param userId 用户名 + * @return 结果 + */ + @GetMapping(value = "/user/rolesAndPermissions/{userId}") + public R getRolesAndPermissions(@PathVariable("userId") Long userId); + + } diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteUserFallbackFactory.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteUserFallbackFactory.java index 6254ac7c..b737cfb9 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteUserFallbackFactory.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteUserFallbackFactory.java @@ -1,5 +1,7 @@ package com.ruoyi.system.api.factory; +import com.ruoyi.system.api.model.RoleAndPermission; +import com.ruoyi.system.api.model.UserInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -8,6 +10,8 @@ import com.ruoyi.system.api.RemoteUserService; import com.ruoyi.system.api.model.LoginUser; import feign.hystrix.FallbackFactory; +import java.util.Set; + /** * 用户服务降级处理 * @@ -25,10 +29,25 @@ public class RemoteUserFallbackFactory implements FallbackFactory getUserInfo(String username) + public R getUserInfo(String username) { return R.fail("获取用户失败:" + throwable.getMessage()); } + + @Override + public R> getRoles(Long userId) { + return R.fail("获取用户角色失败:" + throwable.getMessage()); + } + + @Override + public R> getPermissions(Long userId) { + return R.fail("获取用户权限失败:" + throwable.getMessage()); + } + + @Override + public R getRolesAndPermissions(Long userId) { + return R.fail("获取用户角色和权限失败:" + throwable.getMessage()); + } }; } } diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/LoginUser.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/LoginUser.java index 2f00e102..4fdb8df7 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/LoginUser.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/LoginUser.java @@ -1,15 +1,28 @@ package com.ruoyi.system.api.model; import java.io.Serializable; -import java.util.Set; +import java.util.*; +import java.util.function.Function; + import com.ruoyi.system.api.domain.SysUser; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.CredentialsContainer; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.crypto.factory.PasswordEncoderFactories; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.util.Assert; /** * 用户信息 * * @author ruoyi */ -public class LoginUser implements Serializable +@Slf4j +public class LoginUser implements Serializable, UserDetails,CredentialsContainer { private static final long serialVersionUID = 1L; @@ -21,7 +34,7 @@ public class LoginUser implements Serializable /** * 用户名id */ - private Long userid; + private Long userId; /** * 用户名 @@ -58,6 +71,63 @@ public class LoginUser implements Serializable */ private SysUser sysUser; + private String password; + + private Set authorities; + + private boolean accountNonExpired; + + private boolean accountNonLocked; + + private boolean credentialsNonExpired; + + private boolean enabled; + + public LoginUser() { + this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities)); + } + + public LoginUser(String username, String password, Collection authorities) { + this.username = username; + this.password = password; + this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities)); + } + + public LoginUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection authorities) { + this.enabled = enabled; + this.accountNonExpired = accountNonExpired; + this.credentialsNonExpired = credentialsNonExpired; + this.accountNonLocked = accountNonLocked; + this.username = username; + this.password = password; + this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities)); + } + + public void setAuthorities(Set authorities) { + this.authorities = authorities; + } + + public LoginUser(Long userid, String username, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection authorities) { + this.enabled = enabled; + this.accountNonExpired = accountNonExpired; + this.credentialsNonExpired = credentialsNonExpired; + this.accountNonLocked = accountNonLocked; + this.username = username; + this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities)); + this.userId = userid; + } + + public LoginUser(Long userid, String username,String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection authorities) { + this.enabled = enabled; + this.accountNonExpired = accountNonExpired; + this.credentialsNonExpired = credentialsNonExpired; + this.accountNonLocked = accountNonLocked; + this.username = username; + this.password = password; + this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities)); + this.userId = userid; + } + public String getToken() { return token; @@ -68,16 +138,17 @@ public class LoginUser implements Serializable this.token = token; } - public Long getUserid() + public Long getUserId() { - return userid; + return userId; } - public void setUserid(Long userid) + public void setUserId(Long userId) { - this.userid = userid; + this.userId = userId; } + @Override public String getUsername() { return username; @@ -147,4 +218,221 @@ public class LoginUser implements Serializable { this.sysUser = sysUser; } + + @Override + public Collection getAuthorities() { + return this.authorities; + } + + @Override + public String getPassword() { + return this.password; + } + + @Override + public boolean isEnabled() { + return this.enabled; + } + + @Override + public boolean isAccountNonExpired() { + return this.accountNonExpired; + } + + @Override + public boolean isAccountNonLocked() { + return this.accountNonLocked; + } + + @Override + public boolean isCredentialsNonExpired() { + return this.credentialsNonExpired; + } + + @Override + public void eraseCredentials() { + this.password = null; + } + + private static SortedSet sortAuthorities(Collection authorities) { + Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection"); + SortedSet sortedAuthorities = new TreeSet(new LoginUser.AuthorityComparator()); + Iterator var2 = authorities.iterator(); + + while(var2.hasNext()) { + GrantedAuthority grantedAuthority = (GrantedAuthority)var2.next(); + Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements"); + sortedAuthorities.add(grantedAuthority); + } + + return sortedAuthorities; + } + + @Override + public boolean equals(Object rhs) { + return rhs instanceof LoginUser ? this.username.equals(((LoginUser)rhs).username) : false; + } + + @Override + public int hashCode() { + return this.username.hashCode(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(super.toString()).append(": "); + sb.append("Username: ").append(this.username).append("; "); + sb.append("Password: [PROTECTED]; "); + sb.append("Enabled: ").append(this.enabled).append("; "); + sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; "); + sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; "); + sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; "); + if (!this.authorities.isEmpty()) { + sb.append("Granted Authorities: "); + boolean first = true; + Iterator var3 = this.authorities.iterator(); + + while(var3.hasNext()) { + GrantedAuthority auth = (GrantedAuthority)var3.next(); + if (!first) { + sb.append(","); + } + + first = false; + sb.append(auth); + } + } else { + sb.append("Not granted any authorities"); + } + + return sb.toString(); + } + + public static LoginUser.UserBuilder withUsername(String username) { + return builder().username(username); + } + + public static LoginUser.UserBuilder builder() { + return new LoginUser.UserBuilder(); + } + + /** @deprecated */ + @Deprecated + public static LoginUser.UserBuilder withDefaultPasswordEncoder() { + log.warn("User.withDefaultPasswordEncoder() is considered unsafe for production and is only intended for sample applications."); + PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); + LoginUser.UserBuilder var10000 = builder(); + encoder.getClass(); + return var10000.passwordEncoder(encoder::encode); + } + + public static LoginUser.UserBuilder withUserDetails(UserDetails userDetails) { + return withUsername(userDetails.getUsername()).password(userDetails.getPassword()).accountExpired(!userDetails.isAccountNonExpired()).accountLocked(!userDetails.isAccountNonLocked()).authorities(userDetails.getAuthorities()).credentialsExpired(!userDetails.isCredentialsNonExpired()).disabled(!userDetails.isEnabled()); + } + + public static class UserBuilder { + private String username; + private String password; + private List authorities; + private boolean accountExpired; + private boolean accountLocked; + private boolean credentialsExpired; + private boolean disabled; + private Function passwordEncoder; + + private UserBuilder() { + this.passwordEncoder = (password) -> { + return password; + }; + } + + public LoginUser.UserBuilder username(String username) { + Assert.notNull(username, "username cannot be null"); + this.username = username; + return this; + } + + public LoginUser.UserBuilder password(String password) { + Assert.notNull(password, "password cannot be null"); + this.password = password; + return this; + } + + public LoginUser.UserBuilder passwordEncoder(Function encoder) { + Assert.notNull(encoder, "encoder cannot be null"); + this.passwordEncoder = encoder; + return this; + } + + public LoginUser.UserBuilder roles(String... roles) { + List authorities = new ArrayList(roles.length); + String[] var3 = roles; + int var4 = roles.length; + + for(int var5 = 0; var5 < var4; ++var5) { + String role = var3[var5]; + Assert.isTrue(!role.startsWith("ROLE_"), () -> { + return role + " cannot start with ROLE_ (it is automatically added)"; + }); + authorities.add(new SimpleGrantedAuthority("ROLE_" + role)); + } + + return this.authorities((Collection)authorities); + } + + public LoginUser.UserBuilder authorities(GrantedAuthority... authorities) { + return this.authorities((Collection)Arrays.asList(authorities)); + } + + public LoginUser.UserBuilder authorities(Collection authorities) { + this.authorities = new ArrayList(authorities); + return this; + } + + public LoginUser.UserBuilder authorities(String... authorities) { + return this.authorities((Collection) AuthorityUtils.createAuthorityList(authorities)); + } + + public LoginUser.UserBuilder accountExpired(boolean accountExpired) { + this.accountExpired = accountExpired; + return this; + } + + public LoginUser.UserBuilder accountLocked(boolean accountLocked) { + this.accountLocked = accountLocked; + return this; + } + + public LoginUser.UserBuilder credentialsExpired(boolean credentialsExpired) { + this.credentialsExpired = credentialsExpired; + return this; + } + + public LoginUser.UserBuilder disabled(boolean disabled) { + this.disabled = disabled; + return this; + } + + public UserDetails build() { + String encodedPassword = (String)this.passwordEncoder.apply(this.password); + return new User(this.username, encodedPassword, !this.disabled, !this.accountExpired, !this.credentialsExpired, !this.accountLocked, this.authorities); + } + } + + private static class AuthorityComparator implements Comparator, Serializable { + private static final long serialVersionUID = 530L; + + private AuthorityComparator() { + } + + @Override + public int compare(GrantedAuthority g1, GrantedAuthority g2) { + if (g2.getAuthority() == null) { + return -1; + } else { + return g1.getAuthority() == null ? 1 : g1.getAuthority().compareTo(g2.getAuthority()); + } + } + } } diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/RoleAndPermission.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/RoleAndPermission.java new file mode 100644 index 00000000..7740f995 --- /dev/null +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/RoleAndPermission.java @@ -0,0 +1,29 @@ +package com.ruoyi.system.api.model; + +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; + +import java.io.Serializable; +import java.util.Set; + +/** + * 角色表 sys_role + * + * @author ruoyi + */ +@Data +public class RoleAndPermission implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 角色集合 + */ + private Set roles ; + + /** + * 权限集合 + */ + private Set permissions ; + +} diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/UserInfo.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/UserInfo.java new file mode 100644 index 00000000..ed7c3615 --- /dev/null +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/model/UserInfo.java @@ -0,0 +1,61 @@ +package com.ruoyi.system.api.model; + +import com.ruoyi.system.api.domain.SysUser; + +import java.io.Serializable; +import java.util.Set; + +/** + * 用户信息 + * + * @author ruoyi + */ +public class UserInfo implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** + * 用户基本信息 + */ + private SysUser sysUser; + + /** + * 权限标识集合 + */ + private Set permissions; + + /** + * 角色集合 + */ + private Set roles; + + public SysUser getSysUser() + { + return sysUser; + } + + public void setSysUser(SysUser sysUser) + { + this.sysUser = sysUser; + } + + public Set getPermissions() + { + return permissions; + } + + public void setPermissions(Set permissions) + { + this.permissions = permissions; + } + + public Set getRoles() + { + return roles; + } + + public void setRoles(Set roles) + { + this.roles = roles; + } +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/config/AuthServerConfig.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/config/AuthServerConfig.java new file mode 100644 index 00000000..f68f3554 --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/config/AuthServerConfig.java @@ -0,0 +1,132 @@ +package com.ruoyi.auth.config; + +import com.ruoyi.auth.exception.CustomWebResponseExceptionTranslator; +import com.ruoyi.common.core.constant.CacheConstants; +import com.ruoyi.common.core.constant.SecurityConstants; +import com.ruoyi.common.security.service.RedisClientDetailsService; +import com.ruoyi.system.api.model.LoginUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; + +import javax.sql.DataSource; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * OAuth2 认证服务配置 + * + * @author ruoyi + */ +@Configuration +@EnableAuthorizationServer +public class AuthServerConfig extends AuthorizationServerConfigurerAdapter +{ + @Autowired + private AuthenticationManager authenticationManager; + + @Autowired + private DataSource dataSource; + + @Autowired + private RedisConnectionFactory redisConnectionFactory; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private TokenEnhancer tokenEnhancer; + + /** + * 定义授权和令牌端点以及令牌服务 + */ + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) + { + endpoints + // 请求方式 + .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST) + // 指定token存储位置 + .tokenStore(tokenStore()) + // 自定义生成令牌 + .tokenEnhancer(tokenEnhancer) + // 用户账号密码认证 + .userDetailsService(userDetailsService) + // 指定认证管理器 + .authenticationManager(authenticationManager) + // 是否重复使用 refresh_token + .reuseRefreshTokens(false) + // 自定义异常处理 + .exceptionTranslator(new CustomWebResponseExceptionTranslator()); + } + + /** + * 配置令牌端点(Token Endpoint)的安全约束 + */ + @Override + public void configure(AuthorizationServerSecurityConfigurer oauthServer) + { + oauthServer.allowFormAuthenticationForClients().checkTokenAccess("permitAll()"); + } + + /** + * 声明 ClientDetails实现 + */ + public RedisClientDetailsService clientDetailsService() + { + RedisClientDetailsService clientDetailsService = new RedisClientDetailsService(dataSource); + return clientDetailsService; + } + + /** + * 配置客户端详情 + */ + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception + { + clients.withClientDetails(clientDetailsService()); + } + + /** + * 基于 Redis 实现,令牌保存到缓存 + */ + @Bean + public TokenStore tokenStore() + { + RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory); + tokenStore.setPrefix(CacheConstants.OAUTH_ACCESS); + return tokenStore; + } + + /** + * 自定义生成令牌 + */ + @Bean + public TokenEnhancer tokenEnhancer() + { + return (accessToken, authentication) -> { + if (authentication.getUserAuthentication() != null) + { + Map additionalInformation = new LinkedHashMap(); + LoginUser user = (LoginUser) authentication.getUserAuthentication().getPrincipal(); + additionalInformation.put(SecurityConstants.DETAILS_USER_ID, user.getUserId()); + additionalInformation.put(SecurityConstants.DETAILS_USERNAME, user.getUsername()); + ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation); + } + return accessToken; + }; + } +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/config/WebSecurityConfig.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/config/WebSecurityConfig.java new file mode 100644 index 00000000..23cee929 --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/config/WebSecurityConfig.java @@ -0,0 +1,73 @@ +package com.ruoyi.auth.config; + +import com.ruoyi.common.security.service.UserDetailsServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +import javax.annotation.Resource; + +/** + * Security 安全认证相关配置 + * Oauth2依赖于Security 默认情况下WebSecurityConfig执行比ResourceServerConfig优先 + * + * @author ruoyi + */ +@Order(99) +@Configuration +public class WebSecurityConfig extends WebSecurityConfigurerAdapter +{ +// @Resource(name= "defaultUserDetailsService") +// private UserDetailsService userDetailsService; + + @Bean + public PasswordEncoder passwordEncoder() + { + return new BCryptPasswordEncoder(); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception + { + return super.authenticationManagerBean(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception + { + auth.userDetailsService(getUserDetailsService()).passwordEncoder(passwordEncoder()); + } + + @Override + protected void configure(HttpSecurity http) throws Exception + { + http + .authorizeRequests() + .antMatchers( + "/actuator/**", + "/oauth/*", + "/token/**", + "/logout", + "/login" + ).permitAll() + .anyRequest().authenticated() + .and().csrf().disable(); + } + + @Bean + public UserDetailsService getUserDetailsService() { + return new UserDetailsServiceImpl(); + } + + +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java index b90c8002..e31599c3 100644 --- a/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/TokenController.java @@ -1,6 +1,8 @@ package com.ruoyi.auth.controller; import javax.servlet.http.HttpServletRequest; + +import com.ruoyi.system.api.model.UserInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -27,16 +29,16 @@ public class TokenController @Autowired private SysLoginService sysLoginService; - @PostMapping("login") - public R login(@RequestBody LoginBody form) - { - // 用户登录 - LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword()); - // 获取登录token - return R.ok(tokenService.createToken(userInfo)); - } +// @PostMapping("login") +// public R login(@RequestBody LoginBody form) +// { +// // 用户登录 +// UserInfo userInfo = sysLoginService.login(form.getUsername(), form.getPassword()); +// // 获取登录token +// return R.ok(tokenService.createToken(userInfo)); +// } - @DeleteMapping("logout") + @DeleteMapping("token/logout") public R logout(HttpServletRequest request) { LoginUser loginUser = tokenService.getLoginUser(request); diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/UserController.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/UserController.java new file mode 100644 index 00000000..9947a432 --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/controller/UserController.java @@ -0,0 +1,22 @@ +package com.ruoyi.auth.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.security.Principal; + +/** + * 身份信息获取 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/oauth") +public class UserController +{ + @RequestMapping("/user") + public Principal user(Principal user) + { + return user; + } +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomOauthException.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomOauthException.java new file mode 100644 index 00000000..7ead34a2 --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomOauthException.java @@ -0,0 +1,20 @@ +package com.ruoyi.auth.exception; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; + +/** + * oauth2自定义异常 + * + * @author ruoyi + **/ +@JsonSerialize(using = CustomOauthExceptionSerializer.class) +public class CustomOauthException extends OAuth2Exception +{ + private static final long serialVersionUID = 1L; + + public CustomOauthException(String msg) + { + super(msg); + } +} \ No newline at end of file diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomOauthExceptionSerializer.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomOauthExceptionSerializer.java new file mode 100644 index 00000000..5f69208c --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomOauthExceptionSerializer.java @@ -0,0 +1,49 @@ +package com.ruoyi.auth.exception; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import com.ruoyi.common.core.constant.HttpStatus; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.core.web.domain.AjaxResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +/** + * 自定义异常返回 + * + * @author ruoyi + **/ +public class CustomOauthExceptionSerializer extends StdSerializer +{ + private static final long serialVersionUID = 1L; + + private static final Logger log = LoggerFactory.getLogger(CustomOauthExceptionSerializer.class); + + public static final String BAD_CREDENTIALS = "Bad credentials"; + + public CustomOauthExceptionSerializer() + { + super(CustomOauthException.class); + } + + @Override + public void serialize(CustomOauthException e, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) + throws IOException + { + jsonGenerator.writeStartObject(); + jsonGenerator.writeNumberField(AjaxResult.CODE_TAG, HttpStatus.ERROR); + if (StringUtils.equals(e.getMessage(), BAD_CREDENTIALS)) + { + jsonGenerator.writeStringField(AjaxResult.MSG_TAG, "用户名或密码错误"); + } + else + { + log.warn("oauth2 认证异常 {} ", e); + jsonGenerator.writeStringField(AjaxResult.MSG_TAG, e.getMessage()); + } + jsonGenerator.writeEndObject(); + } +} \ No newline at end of file diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomWebResponseExceptionTranslator.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomWebResponseExceptionTranslator.java new file mode 100644 index 00000000..9b56c084 --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/exception/CustomWebResponseExceptionTranslator.java @@ -0,0 +1,20 @@ +package com.ruoyi.auth.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; + +/** + * OAuth2 自定义异常处理 + * + * @author ruoyi + */ +public class CustomWebResponseExceptionTranslator implements WebResponseExceptionTranslator +{ + @Override + public ResponseEntity translate(Exception e) + { + return ResponseEntity.status(HttpStatus.OK).body(new CustomOauthException(e.getMessage())); + } +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/handler/AuthenticationSuccessEventHandler.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/handler/AuthenticationSuccessEventHandler.java new file mode 100644 index 00000000..fbf646e4 --- /dev/null +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/handler/AuthenticationSuccessEventHandler.java @@ -0,0 +1,39 @@ +package com.ruoyi.auth.handler; + +import com.ruoyi.common.core.constant.Constants; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.system.api.RemoteLogService; +import com.ruoyi.system.api.model.LoginUser; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.security.authentication.event.AuthenticationSuccessEvent; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Component; + +/** + * 认证成功处理 + * + * @author ruoyi + */ +@Component +public class AuthenticationSuccessEventHandler implements ApplicationListener +{ + @Autowired + private RemoteLogService remoteLogService; + + @Override + public void onApplicationEvent(AuthenticationSuccessEvent event) + { + Authentication authentication = (Authentication) event.getSource(); + if (StringUtils.isNotEmpty(authentication.getAuthorities()) + && authentication.getPrincipal() instanceof LoginUser) + { + LoginUser user = (LoginUser) authentication.getPrincipal(); + + String username = user.getUsername(); + + // 记录用户登录日志 + remoteLogService.saveLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功"); + } + } +} diff --git a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java index a8662048..e854dd7a 100644 --- a/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java +++ b/ruoyi-auth/src/main/java/com/ruoyi/auth/service/SysLoginService.java @@ -1,5 +1,6 @@ package com.ruoyi.auth.service; +import com.ruoyi.system.api.model.UserInfo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.ruoyi.common.core.constant.Constants; @@ -7,7 +8,7 @@ import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.enums.UserStatus; import com.ruoyi.common.core.exception.BaseException; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.system.api.RemoteLogService; import com.ruoyi.system.api.RemoteUserService; @@ -31,7 +32,7 @@ public class SysLoginService /** * 登录 */ - public LoginUser login(String username, String password) + public UserInfo login(String username, String password) { // 用户名或密码为空 错误 if (StringUtils.isAnyBlank(username, password)) @@ -54,7 +55,7 @@ public class SysLoginService throw new BaseException("用户名不在指定范围"); } // 查询用户信息 - R userResult = remoteUserService.getUserInfo(username); + R userResult = remoteUserService.getUserInfo(username); if (R.FAIL == userResult.getCode()) { @@ -66,7 +67,7 @@ public class SysLoginService remoteLogService.saveLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在"); throw new BaseException("登录用户:" + username + " 不存在"); } - LoginUser userInfo = userResult.getData(); + UserInfo userInfo = userResult.getData(); SysUser user = userResult.getData().getSysUser(); if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) { diff --git a/ruoyi-auth/src/main/resources/bootstrap.yml b/ruoyi-auth/src/main/resources/bootstrap.yml index 037cd7a7..ee43a9e0 100644 --- a/ruoyi-auth/src/main/resources/bootstrap.yml +++ b/ruoyi-auth/src/main/resources/bootstrap.yml @@ -14,11 +14,12 @@ spring: nacos: discovery: # 服务注册地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 config: # 配置中心地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 # 配置文件格式 file-extension: yml # 共享配置 - shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml index 44654085..307bf744 100644 --- a/ruoyi-common/ruoyi-common-core/pom.xml +++ b/ruoyi-common/ruoyi-common-core/pom.xml @@ -101,6 +101,17 @@ swagger-annotations + + org.springframework.boot + spring-boot-configuration-processor + true + + + + org.projectlombok + lombok + + diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java index 8f666dd1..d727836a 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java @@ -36,4 +36,14 @@ public class CacheConstants * 授权信息字段 */ public static final String AUTHORIZATION_HEADER = "authorization"; + + /** + * oauth 缓存前缀 + */ + public static final String OAUTH_ACCESS = "oauth:access:"; + + /** + * oauth 客户端信息 + */ + public static final String CLIENT_DETAILS_KEY = "oauth:client:details"; } diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/SecurityConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/SecurityConstants.java new file mode 100644 index 00000000..9e0123d3 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/SecurityConstants.java @@ -0,0 +1,56 @@ +package com.ruoyi.common.core.constant; + +/** + * 权限相关通用常量 + * + * @author ruoyi + */ +public class SecurityConstants +{ + /** + * 令牌类型 + */ + public static final String BEARER_TOKEN_TYPE = "Bearer"; + + /** + * 授权token url + */ + public static final String AUTH_TOKEN = "/oauth/token"; + + /** + * 注销token url + */ + public static final String TOKEN_LOGOUT = "/token/logout"; + + /** + * 用户ID字段 + */ + public static final String DETAILS_USER_ID = "user_id"; + + /** + * 用户名字段 + */ + public static final String DETAILS_USERNAME = "username"; + + /** + * sys_oauth_client_details 表的字段,不包括client_id、client_secret + */ + public static final String CLIENT_FIELDS = "client_id, client_secret, resource_ids, scope, " + + "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, " + + "refresh_token_validity, additional_information, autoapprove"; + + /** + * JdbcClientDetailsService 查询语句 + */ + public static final String BASE_FIND_STATEMENT = "select " + CLIENT_FIELDS + " from sys_oauth_client_details"; + + /** + * 按条件client_id 查询 + */ + public static final String DEFAULT_SELECT_STATEMENT = BASE_FIND_STATEMENT + " where client_id = ?"; + + /** + * 默认的查询语句 + */ + public static final String DEFAULT_FIND_STATEMENT = BASE_FIND_STATEMENT + " order by client_id"; +} diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java index f2225bea..f6176546 100644 --- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java +++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java @@ -1,88 +1,91 @@ -package com.ruoyi.common.core.utils; - -import javax.servlet.http.HttpServletRequest; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import com.ruoyi.common.core.constant.CacheConstants; -import com.ruoyi.common.core.text.Convert; - -/** - * 权限获取工具类 - * - * @author ruoyi - */ -public class SecurityUtils -{ - /** - * 获取用户 - */ - public static String getUsername() - { - String username = ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USERNAME); - return ServletUtils.urlDecode(username); - } - - /** - * 获取用户ID - */ - public static Long getUserId() - { - return Convert.toLong(ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USER_ID)); - } - - /** - * 获取请求token - */ - public static String getToken() - { - return getToken(ServletUtils.getRequest()); - } - - /** - * 根据request获取请求token - */ - public static String getToken(HttpServletRequest request) - { - String token = ServletUtils.getRequest().getHeader(CacheConstants.HEADER); - if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX)) - { - token = token.replace(CacheConstants.TOKEN_PREFIX, ""); - } - return token; - } - - /** - * 是否为管理员 - * - * @param userId 用户ID - * @return 结果 - */ - public static boolean isAdmin(Long userId) - { - return userId != null && 1L == userId; - } - - /** - * 生成BCryptPasswordEncoder密码 - * - * @param password 密码 - * @return 加密字符串 - */ - public static String encryptPassword(String password) - { - BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - return passwordEncoder.encode(password); - } - - /** - * 判断密码是否相同 - * - * @param rawPassword 真实密码 - * @param encodedPassword 加密后字符 - * @return 结果 - */ - public static boolean matchesPassword(String rawPassword, String encodedPassword) - { - BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); - return passwordEncoder.matches(rawPassword, encodedPassword); - } -} +//package com.ruoyi.common.core.utils; +// +//import javax.servlet.http.HttpServletRequest; +//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +//import com.ruoyi.common.core.constant.CacheConstants; +//import com.ruoyi.common.core.text.Convert; +// +///** +// * 权限获取工具类 +// * +// * @author ruoyi +// */ +//public class SecurityUtils +//{ +// /** +// * 获取用户 +// */ +// public static String getUsername() +// { +// String username = ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USERNAME); +// return ServletUtils.urlDecode(username); +// } +// +// /** +// * 获取用户ID +// */ +// public static Long getUserId() +// { +// return Convert.toLong(ServletUtils.getRequest().getHeader(CacheConstants.DETAILS_USER_ID)); +// } +// +// /** +// * 获取请求token +// */ +// public static String getToken() +// { +// return getToken(ServletUtils.getRequest()); +// } +// +// /** +// * 根据request获取请求token +// */ +// public static String getToken(HttpServletRequest request) +// { +// String token = ServletUtils.getRequest().getHeader(CacheConstants.HEADER); +// if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX)) +// { +// token = token.replace(CacheConstants.TOKEN_PREFIX, ""); +// } +// return token; +// } +// +// /** +// * 是否为管理员 +// * +// * @param userId 用户ID +// * @return 结果 +// */ +// public static boolean isAdmin(Long userId) +// { +// return userId != null && 1L == userId; +// } +// +// /** +// * 生成BCryptPasswordEncoder密码 +// * +// * @param password 密码 +// * @return 加密字符串 +// */ +// public static String encryptPassword(String password) +// { +// BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); +// return passwordEncoder.encode(password); +// } +// +// /** +// * 判断密码是否相同 +// * +// * @param rawPassword 真实密码 +// * @param encodedPassword 加密后字符 +// * @return 结果 +// */ +// public static boolean matchesPassword(String rawPassword, String encodedPassword) +// { +// BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); +// return passwordEncoder.matches(rawPassword, encodedPassword); +// } +// +// +// +//} diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java index e76018e7..55555839 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java @@ -6,6 +6,8 @@ import java.util.Iterator; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + +import com.ruoyi.common.security.utils.SecurityUtils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.AfterReturning; @@ -20,7 +22,6 @@ import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import com.alibaba.fastjson.JSON; -import com.ruoyi.common.core.utils.SecurityUtils; import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.ip.IpUtils; diff --git a/ruoyi-common/ruoyi-common-security/pom.xml b/ruoyi-common/ruoyi-common-security/pom.xml index b1f7319a..35061d65 100644 --- a/ruoyi-common/ruoyi-common-security/pom.xml +++ b/ruoyi-common/ruoyi-common-security/pom.xml @@ -15,7 +15,13 @@ - + + + + org.springframework.cloud + spring-cloud-starter-oauth2 + + com.ruoyi diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/EnableCustomConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/EnableCustomConfig.java index fa2a8b29..05951318 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/EnableCustomConfig.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/annotation/EnableCustomConfig.java @@ -6,12 +6,14 @@ import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; + +import com.ruoyi.common.security.config.SecurityImportBeanDefinitionRegistrar; +import com.ruoyi.common.security.feign.FeignConfig; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.context.annotation.Import; import org.springframework.scheduling.annotation.EnableAsync; import com.ruoyi.common.security.config.ApplicationConfig; -import com.ruoyi.common.security.feign.FeignAutoConfiguration; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @@ -24,8 +26,7 @@ import com.ruoyi.common.security.feign.FeignAutoConfiguration; // 开启线程异步执行 @EnableAsync // 自动加载类 -@Import({ ApplicationConfig.class, FeignAutoConfiguration.class }) -public @interface EnableCustomConfig -{ +@Import({ ApplicationConfig.class, FeignConfig.class , SecurityImportBeanDefinitionRegistrar.class}) +public @interface EnableCustomConfig { } diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/PreAuthorizeAspect.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/PreAuthorizeAspect.java index 3a44d82b..a6c25fdc 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/PreAuthorizeAspect.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/aspect/PreAuthorizeAspect.java @@ -8,6 +8,7 @@ import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import org.springframework.util.PatternMatchUtils; @@ -111,11 +112,11 @@ public class PreAuthorizeAspect public boolean hasPermi(String permission) { LoginUser userInfo = tokenService.getLoginUser(); - if (StringUtils.isEmpty(userInfo) || CollectionUtils.isEmpty(userInfo.getPermissions())) + if (StringUtils.isEmpty(userInfo) || CollectionUtils.isEmpty(userInfo.getAuthorities())) { return false; } - return hasPermissions(userInfo.getPermissions(), permission); + return hasPermissions(userInfo.getAuthorities(), permission); } /** @@ -142,7 +143,7 @@ public class PreAuthorizeAspect { return false; } - Collection authorities = userInfo.getPermissions(); + Collection authorities = userInfo.getAuthorities(); for (String permission : permissions) { if (permission != null && hasPermissions(authorities, permission)) @@ -217,9 +218,8 @@ public class PreAuthorizeAspect * @param permission 权限字符串 * @return 用户是否具备某权限 */ - private boolean hasPermissions(Collection authorities, String permission) + private boolean hasPermissions(Collection authorities, String permission) { - return authorities.stream().filter(StringUtils::hasText) - .anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(permission, x)); + return authorities.stream().filter(grantedAuthority-> {return StringUtils.hasText(grantedAuthority.getAuthority());}).anyMatch(grantedAuthority -> ALL_PERMISSION.contains(grantedAuthority.getAuthority()) || PatternMatchUtils.simpleMatch(permission, grantedAuthority.getAuthority())); } } diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/AuthIgnoreConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/AuthIgnoreConfig.java new file mode 100644 index 00000000..125f822c --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/AuthIgnoreConfig.java @@ -0,0 +1,31 @@ +package com.ruoyi.common.security.config; + +import org.springframework.beans.factory.annotation.Configurable; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * 忽略服务间的认证 + * + * @author ruoyi + **/ +@Component +@Configurable +@ConfigurationProperties(prefix = "security.oauth2.ignore") +public class AuthIgnoreConfig +{ + private List urls = new ArrayList<>(); + + public List getUrls() + { + return urls; + } + + public void setUrls(List urls) + { + this.urls = urls; + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/CommonUserConverter.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/CommonUserConverter.java new file mode 100644 index 00000000..59d0353e --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/CommonUserConverter.java @@ -0,0 +1,75 @@ +package com.ruoyi.common.security.config; + +import com.ruoyi.common.core.constant.SecurityConstants; +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.system.api.model.LoginUser; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter; +import org.springframework.util.StringUtils; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * https://my.oschina.net/giegie/blog/3023768 根据checktoken 的结果转化用户信息 + * + * @author lengleng + */ +public class CommonUserConverter implements UserAuthenticationConverter +{ + private static final String N_A = "N/A"; + + /** + * 将授权信息返回到资源服务 + */ + @Override + public Map convertUserAuthentication(Authentication userAuthentication) + { + Map authMap = new LinkedHashMap<>(); + authMap.put(USERNAME, userAuthentication.getName()); + if (userAuthentication.getAuthorities() != null && !userAuthentication.getAuthorities().isEmpty()) + { + authMap.put(AUTHORITIES, AuthorityUtils.authorityListToSet(userAuthentication.getAuthorities())); + } + return authMap; + } + + /** + * 获取用户认证信息 + */ + @Override + public Authentication extractAuthentication(Map map) + { + if (map.containsKey(USERNAME)) + { + Collection authorities = getAuthorities(map); + Long userId = Convert.toLong(map.get(SecurityConstants.DETAILS_USER_ID)); + String username = (String) map.get(SecurityConstants.DETAILS_USERNAME); + LoginUser user = new LoginUser(userId,username, true, true, true, true, authorities); + return new UsernamePasswordAuthenticationToken(user, N_A, authorities); + } + return null; + } + + /** + * 获取权限资源信息 + */ + private Collection getAuthorities(Map map) + { + Object authorities = map.get(AUTHORITIES); + if (authorities instanceof String) + { + return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities); + } + if (authorities instanceof Collection) + { + return AuthorityUtils.commaSeparatedStringToAuthorityList( + StringUtils.collectionToCommaDelimitedString((Collection) authorities)); + } + throw new IllegalArgumentException("Authorities must be either a String or a Collection"); + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/MethodSecurityConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/MethodSecurityConfig.java new file mode 100644 index 00000000..f3342766 --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/MethodSecurityConfig.java @@ -0,0 +1,26 @@ +package com.ruoyi.common.security.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; + +/** + * + * @EnableGlobalMethodSecurity(securedEnabled=true) + * 开启@Secured 注解过滤权限 + * + * @EnableGlobalMethodSecurity(jsr250Enabled=true) + * 开启@RolesAllowed 注解过滤权限 + * + * @EnableGlobalMethodSecurity(prePostEnabled=true) + * 使用表达式时间方法级别的安全性 4个注解可用 + * -@PreAuthorize 在方法调用之前,基于表达式的计算结果来限制对方法的访问 + * -@PostAuthorize 允许方法调用,但是如果表达式计算结果为false,将抛出一个安全性异常 + * -@PostFilter 允许方法调用,但必须按照表达式来过滤方法的结果 + * -@PreFilter 允许方法调用,但必须在进入方法之前过滤输入值 + * + */ +@Configuration +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class MethodSecurityConfig { + +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/ResourceServerConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/ResourceServerConfig.java new file mode 100644 index 00000000..6aa3ba89 --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/ResourceServerConfig.java @@ -0,0 +1,82 @@ +package com.ruoyi.common.security.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.oauth2.OAuth2ClientProperties; +import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties; +import org.springframework.cloud.client.loadbalancer.LoadBalanced; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; +import org.springframework.security.oauth2.provider.token.RemoteTokenServices; +import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; +import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter; +import org.springframework.web.client.DefaultResponseErrorHandler; +import org.springframework.web.client.RestTemplate; + +/** + * oauth2 服务配置 + * + * @author ruoyi + */ +@Configuration +@EnableResourceServer +public class ResourceServerConfig extends ResourceServerConfigurerAdapter +{ + @Autowired + private ResourceServerProperties resourceServerProperties; + + @Autowired + private OAuth2ClientProperties oAuth2ClientProperties; + + @Bean + public AuthIgnoreConfig authIgnoreConfig() + { + return new AuthIgnoreConfig(); + } + + @Bean + @LoadBalanced + public RestTemplate restTemplate() + { + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); + return restTemplate; + } + + @Bean + public ResourceServerTokenServices tokenServices() + { + RemoteTokenServices remoteTokenServices = new RemoteTokenServices(); + DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter(); + UserAuthenticationConverter userTokenConverter = new CommonUserConverter(); + accessTokenConverter.setUserTokenConverter(userTokenConverter); + remoteTokenServices.setCheckTokenEndpointUrl(resourceServerProperties.getTokenInfoUri()); + remoteTokenServices.setClientId(oAuth2ClientProperties.getClientId()); + remoteTokenServices.setClientSecret(oAuth2ClientProperties.getClientSecret()); + remoteTokenServices.setRestTemplate(restTemplate()); + remoteTokenServices.setAccessTokenConverter(accessTokenConverter); + return remoteTokenServices; + } + + @Override + public void configure(HttpSecurity http) throws Exception + { + http.csrf().disable(); + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = http + .authorizeRequests(); + // 不登录可以访问 + authIgnoreConfig().getUrls().forEach(url -> registry.antMatchers(url).permitAll()); + registry.anyRequest().authenticated(); + } + + @Override + public void configure(ResourceServerSecurityConfigurer resources) + { + resources.tokenServices(tokenServices()); + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityImportBeanDefinitionRegistrar.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityImportBeanDefinitionRegistrar.java new file mode 100644 index 00000000..4bb6069b --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/config/SecurityImportBeanDefinitionRegistrar.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.security.config; + +import com.ruoyi.common.core.utils.StringUtils; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.type.AnnotationMetadata; + +/** + * 导入 SecurityImportBeanDefinitionRegistrar 自动加载类 + * + * @author ruoyi + */ +public class SecurityImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar +{ + @Override + public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) + { + Class aClass = ResourceServerConfig.class; + String beanName = StringUtils.uncapitalize(aClass.getSimpleName()); + BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(ResourceServerConfig.class); + registry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition()); + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignAutoConfiguration.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignAutoConfiguration.java index 934a9598..97a5262f 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignAutoConfiguration.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignAutoConfiguration.java @@ -1,20 +1,20 @@ -package com.ruoyi.common.security.feign; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import feign.RequestInterceptor; - -/** - * Feign 配置注册 - * - * @author ruoyi - **/ -@Configuration -public class FeignAutoConfiguration -{ - @Bean - public RequestInterceptor requestInterceptor() - { - return new FeignRequestInterceptor(); - } -} +//package com.ruoyi.common.security.feign; +// +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import feign.RequestInterceptor; +// +///** +// * Feign 配置注册 +// * +// * @author ruoyi +// **/ +//@Configuration +//public class FeignAutoConfiguration +//{ +// @Bean +// public RequestInterceptor requestInterceptor() +// { +// return new FeignRequestInterceptor(); +// } +//} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignConfig.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignConfig.java new file mode 100644 index 00000000..970f8449 --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignConfig.java @@ -0,0 +1,20 @@ +package com.ruoyi.common.security.feign; + +import feign.RequestInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * Feign配置注册 + * + * @author ruoyi + **/ +@Configuration +public class FeignConfig +{ + @Bean + public RequestInterceptor requestInterceptor() + { + return new OAuth2FeignRequestInterceptor(); + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignRequestInterceptor.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignRequestInterceptor.java index 2642dd12..53df5275 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignRequestInterceptor.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/FeignRequestInterceptor.java @@ -1,45 +1,45 @@ -package com.ruoyi.common.security.feign; - -import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import org.springframework.stereotype.Component; -import com.ruoyi.common.core.constant.CacheConstants; -import com.ruoyi.common.core.utils.ServletUtils; -import com.ruoyi.common.core.utils.StringUtils; -import feign.RequestInterceptor; -import feign.RequestTemplate; - -/** - * feign 请求拦截器 - * - * @author ruoyi - */ -@Component -public class FeignRequestInterceptor implements RequestInterceptor -{ - @Override - public void apply(RequestTemplate requestTemplate) - { - HttpServletRequest httpServletRequest = ServletUtils.getRequest(); - if (StringUtils.isNotNull(httpServletRequest)) - { - Map headers = ServletUtils.getHeaders(httpServletRequest); - // 传递用户信息请求头,防止丢失 - String userId = headers.get(CacheConstants.DETAILS_USER_ID); - if (StringUtils.isNotEmpty(userId)) - { - requestTemplate.header(CacheConstants.DETAILS_USER_ID, userId); - } - String userName = headers.get(CacheConstants.DETAILS_USERNAME); - if (StringUtils.isNotEmpty(userName)) - { - requestTemplate.header(CacheConstants.DETAILS_USERNAME, userName); - } - String authentication = headers.get(CacheConstants.AUTHORIZATION_HEADER); - if (StringUtils.isNotEmpty(authentication)) - { - requestTemplate.header(CacheConstants.AUTHORIZATION_HEADER, authentication); - } - } - } -} \ No newline at end of file +//package com.ruoyi.common.security.feign; +// +//import java.util.Map; +//import javax.servlet.http.HttpServletRequest; +//import org.springframework.stereotype.Component; +//import com.ruoyi.common.core.constant.CacheConstants; +//import com.ruoyi.common.core.utils.ServletUtils; +//import com.ruoyi.common.core.utils.StringUtils; +//import feign.RequestInterceptor; +//import feign.RequestTemplate; +// +///** +// * feign 请求拦截器 +// * +// * @author ruoyi +// */ +//@Component +//public class FeignRequestInterceptor implements RequestInterceptor +//{ +// @Override +// public void apply(RequestTemplate requestTemplate) +// { +// HttpServletRequest httpServletRequest = ServletUtils.getRequest(); +// if (StringUtils.isNotNull(httpServletRequest)) +// { +// Map headers = ServletUtils.getHeaders(httpServletRequest); +// // 传递用户信息请求头,防止丢失 +// String userId = headers.get(CacheConstants.DETAILS_USER_ID); +// if (StringUtils.isNotEmpty(userId)) +// { +// requestTemplate.header(CacheConstants.DETAILS_USER_ID, userId); +// } +// String userName = headers.get(CacheConstants.DETAILS_USERNAME); +// if (StringUtils.isNotEmpty(userName)) +// { +// requestTemplate.header(CacheConstants.DETAILS_USERNAME, userName); +// } +// String authentication = headers.get(CacheConstants.AUTHORIZATION_HEADER); +// if (StringUtils.isNotEmpty(authentication)) +// { +// requestTemplate.header(CacheConstants.AUTHORIZATION_HEADER, authentication); +// } +// } +// } +//} \ No newline at end of file diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/OAuth2FeignRequestInterceptor.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/OAuth2FeignRequestInterceptor.java new file mode 100644 index 00000000..e2e28289 --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/feign/OAuth2FeignRequestInterceptor.java @@ -0,0 +1,33 @@ +package com.ruoyi.common.security.feign; + +import com.ruoyi.common.core.constant.SecurityConstants; +import feign.RequestInterceptor; +import feign.RequestTemplate; +import org.springframework.http.HttpHeaders; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; +import org.springframework.stereotype.Component; + +/** + * feign 请求拦截器 + * + * @author ruoyi + */ +@Component +public class OAuth2FeignRequestInterceptor implements RequestInterceptor +{ + @Override + public void apply(RequestTemplate requestTemplate) + { + SecurityContext securityContext = SecurityContextHolder.getContext(); + Authentication authentication = securityContext.getAuthentication(); + if (authentication != null && authentication.getDetails() instanceof OAuth2AuthenticationDetails) + { + OAuth2AuthenticationDetails dateils = (OAuth2AuthenticationDetails) authentication.getDetails(); + requestTemplate.header(HttpHeaders.AUTHORIZATION, + String.format("%s %s", SecurityConstants.BEARER_TOKEN_TYPE, dateils.getTokenValue())); + } + } +} \ No newline at end of file diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/CustomAccessDeniedHandler.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/CustomAccessDeniedHandler.java new file mode 100644 index 00000000..133f4064 --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/CustomAccessDeniedHandler.java @@ -0,0 +1,34 @@ +package com.ruoyi.common.security.handler; + +import com.alibaba.fastjson.JSON; +import com.ruoyi.common.core.constant.HttpStatus; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.utils.ServletUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 自定义访问无权限资源时的异常 + * + * @author ruoyi + */ +@Component +public class CustomAccessDeniedHandler extends OAuth2AccessDeniedHandler +{ + private final Logger logger = LoggerFactory.getLogger(CustomAccessDeniedHandler.class); + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException authException) + { + logger.info("权限不足,请联系管理员 {}", request.getRequestURI()); + + String msg = authException.getMessage(); + ServletUtils.renderString(response, JSON.toJSONString(R.fail(HttpStatus.FORBIDDEN, msg))); + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/CustomLoginSuccessHandler.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/CustomLoginSuccessHandler.java new file mode 100644 index 00000000..4e22b58e --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/handler/CustomLoginSuccessHandler.java @@ -0,0 +1,36 @@ +package com.ruoyi.common.security.handler; + +import com.ruoyi.common.core.domain.R; +import com.ruoyi.system.api.RemoteUserService; +import com.ruoyi.system.api.model.LoginUser; +import com.ruoyi.system.api.model.UserInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * + * @author alikes + */ +@Component +public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler { + + @Autowired + private RemoteUserService remoteUserService; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + if(authentication instanceof LoginUser){ + LoginUser loginUser = (LoginUser) authentication; + R res = remoteUserService.getUserInfo(loginUser.getSysUser().getUserName()); + loginUser.setRoles(res.getData().getRoles()); + loginUser.setPermissions(res.getData().getPermissions()); + } + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/PermissionService.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/PermissionService.java new file mode 100644 index 00000000..0a06f549 --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/PermissionService.java @@ -0,0 +1,168 @@ +package com.ruoyi.common.security.service; + +import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.system.api.model.LoginUser; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; +import org.springframework.util.PatternMatchUtils; +import org.springframework.util.StringUtils; + +import java.util.Collection; + +/** + * 自定义权限实现 + * + * @author ruoyi + */ +@Service("ss") +public class PermissionService +{ + /** 所有权限标识 */ + private static final String ALL_PERMISSION = "*:*:*"; + + /** 管理员角色权限标识 */ + private static final String SUPER_ADMIN = "admin"; + + private static final String ROLE_DELIMETER = ","; + + private static final String PERMISSION_DELIMETER = ","; + + /** + * 验证用户是否具备某权限 + * + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + public boolean hasPermi(String permission) + { + if (StringUtils.isEmpty(permission)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities())) + { + return false; + } + return hasPermissions(loginUser.getAuthorities(), permission); + } + + /** + * 验证用户是否不具备某权限,与 hasPermi逻辑相反 + * + * @param permission 权限字符串 + * @return 用户是否不具备某权限 + */ + public boolean lacksPermi(String permission) + { + return hasPermi(permission) != true; + } + + /** + * 验证用户是否具有以下任意一个权限 + * + * @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表 + * @return 用户是否具有以下任意一个权限 + */ + public boolean hasAnyPermi(String permissions) + { + if (StringUtils.isEmpty(permissions)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities())) + { + return false; + } + Collection authorities = loginUser.getAuthorities(); + for (String permission : permissions.split(PERMISSION_DELIMETER)) + { + if (permission != null && hasPermissions(authorities, permission)) + { + return true; + } + } + return false; + } + + /** + * 判断用户是否拥有某个角色 + * + * @param role 角色字符串 + * @return 用户是否具备某角色 + */ + public boolean hasRole(String role) + { + if (StringUtils.isEmpty(role)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities())) + { + return false; + } + for (GrantedAuthority authorities : loginUser.getAuthorities()) + { + String roleKey = authorities.getAuthority(); + if (SUPER_ADMIN.contains(roleKey) || roleKey.contains(role)) + { + return true; + } + } + return false; + } + + /** + * 验证用户是否不具备某角色,与 isRole逻辑相反。 + * + * @param role 角色名称 + * @return 用户是否不具备某角色 + */ + public boolean lacksRole(String role) + { + return hasRole(role) != true; + } + + /** + * 验证用户是否具有以下任意一个角色 + * + * @param roles 以 ROLE_NAMES_DELIMETER 为分隔符的角色列表 + * @return 用户是否具有以下任意一个角色 + */ + public boolean hasAnyRoles(String roles) + { + if (StringUtils.isEmpty(roles)) + { + return false; + } + LoginUser loginUser = SecurityUtils.getLoginUser(); + if (StringUtils.isEmpty(loginUser) || CollectionUtils.isEmpty(loginUser.getAuthorities())) + { + return false; + } + for (String role : roles.split(ROLE_DELIMETER)) + { + if (hasRole(role)) + { + return true; + } + } + return false; + } + + /** + * 判断是否包含权限 + * + * @param authorities 权限列表 + * @param permission 权限字符串 + * @return 用户是否具备某权限 + */ + private boolean hasPermissions(Collection authorities, String permission) + { + return authorities.stream().map(GrantedAuthority::getAuthority).filter(StringUtils::hasText) + .anyMatch(x -> ALL_PERMISSION.contains(x) || PatternMatchUtils.simpleMatch(permission, x)); + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/RedisClientDetailsService.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/RedisClientDetailsService.java new file mode 100644 index 00000000..8dd6a87a --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/RedisClientDetailsService.java @@ -0,0 +1,31 @@ +package com.ruoyi.common.security.service; + +import com.ruoyi.common.core.constant.CacheConstants; +import com.ruoyi.common.core.constant.SecurityConstants; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; + +import javax.sql.DataSource; + +/** + * 重写原生方法支持redis缓存 + * + * @author ruoyi + */ +public class RedisClientDetailsService extends JdbcClientDetailsService +{ + public RedisClientDetailsService(DataSource dataSource) + { + super(dataSource); + super.setSelectClientDetailsSql(SecurityConstants.DEFAULT_SELECT_STATEMENT); + super.setFindClientDetailsSql(SecurityConstants.DEFAULT_FIND_STATEMENT); + } + + @Override + @Cacheable(value = CacheConstants.CLIENT_DETAILS_KEY, key = "#clientId", unless = "#result == null") + public ClientDetails loadClientByClientId(String clientId) + { + return super.loadClientByClientId(clientId); + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java index a4e84283..c6e7205d 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java @@ -4,12 +4,13 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; + +import com.ruoyi.common.security.utils.SecurityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.utils.IdUtils; -import com.ruoyi.common.core.utils.SecurityUtils; import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.ip.IpUtils; @@ -41,7 +42,7 @@ public class TokenService // 生成token String token = IdUtils.fastUUID(); loginUser.setToken(token); - loginUser.setUserid(loginUser.getSysUser().getUserId()); + loginUser.setUserId(loginUser.getSysUser().getUserId()); loginUser.setUsername(loginUser.getSysUser().getUserName()); loginUser.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest())); refreshToken(loginUser); @@ -71,15 +72,17 @@ public class TokenService */ public LoginUser getLoginUser(HttpServletRequest request) { - // 获取请求携带的令牌 - String token = SecurityUtils.getToken(request); - if (StringUtils.isNotEmpty(token)) - { - String userKey = getTokenKey(token); - LoginUser user = redisService.getCacheObject(userKey); - return user; - } - return null; +// // 获取请求携带的令牌 +// String token = SecurityUtils.getToken(request); +// if (StringUtils.isNotEmpty(token)) +// { +// String userKey = getTokenKey(token); +// LoginUser user = redisService.getCacheObject(userKey); +// LoginUser user = SecurityUtils.getLoginUser(); +// +// } +// return null; + return SecurityUtils.getLoginUser(); } /** diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/UserDetailsServiceImpl.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/UserDetailsServiceImpl.java new file mode 100644 index 00000000..29b1c99a --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/UserDetailsServiceImpl.java @@ -0,0 +1,84 @@ +package com.ruoyi.common.security.service; + +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.enums.UserStatus; +import com.ruoyi.common.core.exception.BaseException; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.system.api.RemoteUserService; +import com.ruoyi.system.api.domain.SysUser; +import com.ruoyi.system.api.model.LoginUser; +import com.ruoyi.system.api.model.UserInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * 用户信息处理 + * + * @author ruoyi + */ +@Service("defaultUserDetailsService") +public class UserDetailsServiceImpl implements UserDetailsService +{ + private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class); + + @Autowired + private RemoteUserService remoteUserService; + + @Override + public LoginUser loadUserByUsername(String username) + { + R userResult = remoteUserService.getUserInfo(username); + checkUser(userResult, username); + return getUserDetails(userResult); + } + + public void checkUser(R userResult, String username) + { + if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) + { + log.info("登录用户:{} 不存在.", username); + throw new UsernameNotFoundException("登录用户:" + username + " 不存在"); + } + else if (UserStatus.DELETED.getCode().equals(userResult.getData().getSysUser().getDelFlag())) + { + log.info("登录用户:{} 已被删除.", username); + throw new BaseException("对不起,您的账号:" + username + " 已被删除"); + } + else if (UserStatus.DISABLE.getCode().equals(userResult.getData().getSysUser().getStatus())) + { + log.info("登录用户:{} 已被停用.", username); + throw new BaseException("对不起,您的账号:" + username + " 已停用"); + } + } + + private LoginUser getUserDetails(R result) + { + UserInfo info = result.getData(); + Set dbAuthsSet = new HashSet(); + if (StringUtils.isNotEmpty(info.getRoles())) + { + // 获取角色 + dbAuthsSet.addAll(info.getRoles()); + // 获取权限 + dbAuthsSet.addAll(info.getPermissions()); + } + + Collection authorities = AuthorityUtils.createAuthorityList(dbAuthsSet.toArray(new String[0])); + SysUser user = info.getSysUser(); + LoginUser loginUser = new LoginUser(user.getUserId(), user.getUserName(), user.getPassword(), true, true, true, true, authorities); + loginUser.setPermissions(info.getPermissions()); + loginUser.setRoles(info.getRoles()); + return loginUser; + } +} diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SecurityUtils.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SecurityUtils.java new file mode 100644 index 00000000..7ad7d15d --- /dev/null +++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/utils/SecurityUtils.java @@ -0,0 +1,101 @@ +package com.ruoyi.common.security.utils; + +import com.ruoyi.common.core.text.Convert; +import com.ruoyi.system.api.model.LoginUser; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +/** + * 权限获取工具类 + * + * @author ruoyi + */ +public class SecurityUtils +{ + /** + * 获取Authentication + */ + public static Authentication getAuthentication() + { + return SecurityContextHolder.getContext().getAuthentication(); + } + + /** + * 获取用户 + */ + public static String getUsername() + { + return getLoginUser().getUsername(); + } + + /** + * 获取用户 + */ + public static LoginUser getLoginUser(Authentication authentication) + { + Object principal = authentication.getPrincipal(); + if (principal instanceof LoginUser) + { + return (LoginUser) principal; + } + return null; + } + + + /** + * 获取用户ID + */ + public static Long getUserId(){ + return Convert.toLong(getLoginUser().getUserId()); + } + + /** + * 获取用户 + */ + public static LoginUser getLoginUser() + { + Authentication authentication = getAuthentication(); + if (authentication == null) + { + return null; + } + return getLoginUser(authentication); + } + + /** + * 生成BCryptPasswordEncoder密码 + * + * @param password 密码 + * @return 加密字符串 + */ + public static String encryptPassword(String password) + { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.encode(password); + } + + /** + * 判断密码是否相同 + * + * @param rawPassword 真实密码 + * @param encodedPassword 加密后字符 + * @return 结果 + */ + public static boolean matchesPassword(String rawPassword, String encodedPassword) + { + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + return passwordEncoder.matches(rawPassword, encodedPassword); + } + + /** + * 是否为管理员 + * + * @param userId 用户ID + * @return 结果 + */ + public static boolean isAdmin(Long userId) + { + return userId != null && 1L == userId; + } +} diff --git a/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerAutoConfiguration.java b/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerAutoConfiguration.java index 1a9597dc..4c960729 100644 --- a/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerAutoConfiguration.java +++ b/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerAutoConfiguration.java @@ -13,11 +13,7 @@ import com.google.common.base.Predicates; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.ApiKey; -import springfox.documentation.service.AuthorizationScope; -import springfox.documentation.service.Contact; -import springfox.documentation.service.SecurityReference; +import springfox.documentation.service.*; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.Docket; @@ -96,9 +92,20 @@ public class SwaggerAutoConfiguration .securityReferences(defaultAuth()) .forPaths(PathSelectors.regex("^(?!auth).*$")) .build()); + securityContexts.add(SecurityContext.builder() + .securityReferences(defaultAuth()) + .forPaths(PathSelectors.regex(swaggerProperties().getAuthorization().getAuthRegex())) + .build()); return securityContexts; } +// private SecurityContext securityContext(){ +// return SecurityContext.builder() +// .securityReferences(defaultAuth()) +// .forPaths(PathSelectors.regex(swaggerProperties().getAuthorization().getAuthRegex())) +// .build(); +// } + /** * 默认的全局鉴权策略 * @@ -114,6 +121,15 @@ public class SwaggerAutoConfiguration return securityReferences; } + private OAuth securitySchema() + { + ArrayList authorizationScopeList = new ArrayList<>(); + swaggerProperties().getAuthorization().getAuthorizationScopeList().forEach(authorizationScope -> authorizationScopeList.add(new AuthorizationScope(authorizationScope.getScope(), authorizationScope.getDescription()))); + ArrayList grantTypes = new ArrayList<>(); + swaggerProperties().getAuthorization().getTokenUrlList().forEach(tokenUrl -> grantTypes.add(new ResourceOwnerPasswordCredentialsGrant(tokenUrl))); + return new OAuth(swaggerProperties().getAuthorization().getName(), authorizationScopeList, grantTypes); + } + private ApiInfo apiInfo(SwaggerProperties swaggerProperties) { return new ApiInfoBuilder() diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java index 1bd39940..a816b98a 100644 --- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java +++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java @@ -1,125 +1,125 @@ -package com.ruoyi.gateway.filter; - -import javax.annotation.Resource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.gateway.filter.GatewayFilterChain; -import org.springframework.cloud.gateway.filter.GlobalFilter; -import org.springframework.core.Ordered; -import org.springframework.core.io.buffer.DataBufferFactory; -import org.springframework.data.redis.core.ValueOperations; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.http.server.reactive.ServerHttpResponse; -import org.springframework.stereotype.Component; -import org.springframework.web.server.ServerWebExchange; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONObject; -import com.ruoyi.common.core.constant.CacheConstants; -import com.ruoyi.common.core.constant.Constants; -import com.ruoyi.common.core.domain.R; -import com.ruoyi.common.core.utils.ServletUtils; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.redis.service.RedisService; -import com.ruoyi.gateway.config.properties.IgnoreWhiteProperties; -import reactor.core.publisher.Mono; - -/** - * 网关鉴权 - * - * @author ruoyi - */ -@Component -public class AuthFilter implements GlobalFilter, Ordered -{ - private static final Logger log = LoggerFactory.getLogger(AuthFilter.class); - - private final static long EXPIRE_TIME = Constants.TOKEN_EXPIRE * 60; - - // 排除过滤的 uri 地址,nacos自行添加 - @Autowired - private IgnoreWhiteProperties ignoreWhite; - - @Resource(name = "stringRedisTemplate") - private ValueOperations sops; - - @Autowired - private RedisService redisService; - - @Override - public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) - { - String url = exchange.getRequest().getURI().getPath(); - // 跳过不需要验证的路径 - if (StringUtils.matches(url, ignoreWhite.getWhites())) - { - return chain.filter(exchange); - } - String token = getToken(exchange.getRequest()); - if (StringUtils.isBlank(token)) - { - return setUnauthorizedResponse(exchange, "令牌不能为空"); - } - String userStr = sops.get(getTokenKey(token)); - if (StringUtils.isNull(userStr)) - { - return setUnauthorizedResponse(exchange, "登录状态已过期"); - } - JSONObject obj = JSONObject.parseObject(userStr); - String userid = obj.getString("userid"); - String username = obj.getString("username"); - if (StringUtils.isBlank(userid) || StringUtils.isBlank(username)) - { - return setUnauthorizedResponse(exchange, "令牌验证失败"); - } - - // 设置过期时间 - redisService.expire(getTokenKey(token), EXPIRE_TIME); - // 设置用户信息到请求 - ServerHttpRequest mutableReq = exchange.getRequest().mutate().header(CacheConstants.DETAILS_USER_ID, userid) - .header(CacheConstants.DETAILS_USERNAME, ServletUtils.urlEncode(username)).build(); - ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build(); - - return chain.filter(mutableExchange); - } - - private Mono setUnauthorizedResponse(ServerWebExchange exchange, String msg) - { - ServerHttpResponse response = exchange.getResponse(); - response.getHeaders().setContentType(MediaType.APPLICATION_JSON); - response.setStatusCode(HttpStatus.OK); - - log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath()); - - return response.writeWith(Mono.fromSupplier(() -> { - DataBufferFactory bufferFactory = response.bufferFactory(); - return bufferFactory.wrap(JSON.toJSONBytes(R.fail(msg))); - })); - } - - private String getTokenKey(String token) - { - return CacheConstants.LOGIN_TOKEN_KEY + token; - } - - /** - * 获取请求token - */ - private String getToken(ServerHttpRequest request) - { - String token = request.getHeaders().getFirst(CacheConstants.HEADER); - if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX)) - { - token = token.replace(CacheConstants.TOKEN_PREFIX, ""); - } - return token; - } - - @Override - public int getOrder() - { - return -200; - } -} \ No newline at end of file +//package com.ruoyi.gateway.filter; +// +//import javax.annotation.Resource; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.cloud.gateway.filter.GatewayFilterChain; +//import org.springframework.cloud.gateway.filter.GlobalFilter; +//import org.springframework.core.Ordered; +//import org.springframework.core.io.buffer.DataBufferFactory; +//import org.springframework.data.redis.core.ValueOperations; +//import org.springframework.http.HttpStatus; +//import org.springframework.http.MediaType; +//import org.springframework.http.server.reactive.ServerHttpRequest; +//import org.springframework.http.server.reactive.ServerHttpResponse; +//import org.springframework.stereotype.Component; +//import org.springframework.web.server.ServerWebExchange; +//import com.alibaba.fastjson.JSON; +//import com.alibaba.fastjson.JSONObject; +//import com.ruoyi.common.core.constant.CacheConstants; +//import com.ruoyi.common.core.constant.Constants; +//import com.ruoyi.common.core.domain.R; +//import com.ruoyi.common.core.utils.ServletUtils; +//import com.ruoyi.common.core.utils.StringUtils; +//import com.ruoyi.common.redis.service.RedisService; +//import com.ruoyi.gateway.config.properties.IgnoreWhiteProperties; +//import reactor.core.publisher.Mono; +// +///** +// * 网关鉴权 +// * +// * @author ruoyi +// */ +//@Component +//public class AuthFilter implements GlobalFilter, Ordered +//{ +// private static final Logger log = LoggerFactory.getLogger(AuthFilter.class); +// +// private final static long EXPIRE_TIME = Constants.TOKEN_EXPIRE * 60; +// +// // 排除过滤的 uri 地址,nacos自行添加 +// @Autowired +// private IgnoreWhiteProperties ignoreWhite; +// +// @Resource(name = "stringRedisTemplate") +// private ValueOperations sops; +// +// @Autowired +// private RedisService redisService; +// +// @Override +// public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) +// { +// String url = exchange.getRequest().getURI().getPath(); +// // 跳过不需要验证的路径 +// if (StringUtils.matches(url, ignoreWhite.getWhites())) +// { +// return chain.filter(exchange); +// } +// String token = getToken(exchange.getRequest()); +// if (StringUtils.isBlank(token)) +// { +// return setUnauthorizedResponse(exchange, "令牌不能为空"); +// } +// String userStr = sops.get(getTokenKey(token)); +// if (StringUtils.isNull(userStr)) +// { +// return setUnauthorizedResponse(exchange, "登录状态已过期"); +// } +// JSONObject obj = JSONObject.parseObject(userStr); +// String userid = obj.getString("userid"); +// String username = obj.getString("username"); +// if (StringUtils.isBlank(userid) || StringUtils.isBlank(username)) +// { +// return setUnauthorizedResponse(exchange, "令牌验证失败"); +// } +// +// // 设置过期时间 +// redisService.expire(getTokenKey(token), EXPIRE_TIME); +// // 设置用户信息到请求 +// ServerHttpRequest mutableReq = exchange.getRequest().mutate().header(CacheConstants.DETAILS_USER_ID, userid) +// .header(CacheConstants.DETAILS_USERNAME, ServletUtils.urlEncode(username)).build(); +// ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build(); +// +// return chain.filter(mutableExchange); +// } +// +// private Mono setUnauthorizedResponse(ServerWebExchange exchange, String msg) +// { +// ServerHttpResponse response = exchange.getResponse(); +// response.getHeaders().setContentType(MediaType.APPLICATION_JSON); +// response.setStatusCode(HttpStatus.OK); +// +// log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath()); +// +// return response.writeWith(Mono.fromSupplier(() -> { +// DataBufferFactory bufferFactory = response.bufferFactory(); +// return bufferFactory.wrap(JSON.toJSONBytes(R.fail(msg))); +// })); +// } +// +// private String getTokenKey(String token) +// { +// return CacheConstants.LOGIN_TOKEN_KEY + token; +// } +// +// /** +// * 获取请求token +// */ +// private String getToken(ServerHttpRequest request) +// { +// String token = request.getHeaders().getFirst(CacheConstants.HEADER); +// if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX)) +// { +// token = token.replace(CacheConstants.TOKEN_PREFIX, ""); +// } +// return token; +// } +// +// @Override +// public int getOrder() +// { +// return -200; +// } +//} \ No newline at end of file diff --git a/ruoyi-gateway/src/main/resources/bootstrap.yml b/ruoyi-gateway/src/main/resources/bootstrap.yml index 5f9f269e..6f61b940 100644 --- a/ruoyi-gateway/src/main/resources/bootstrap.yml +++ b/ruoyi-gateway/src/main/resources/bootstrap.yml @@ -16,14 +16,15 @@ spring: nacos: discovery: # 服务注册地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 config: # 配置中心地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 # 配置文件格式 file-extension: yml # 共享配置 - shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} sentinel: # 取消控制台懒加载 eager: true @@ -34,7 +35,7 @@ spring: datasource: ds1: nacos: - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 dataId: sentinel-ruoyi-gateway groupId: DEFAULT_GROUP data-type: json diff --git a/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml index 51520521..b783f3c6 100644 --- a/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml @@ -14,11 +14,12 @@ spring: nacos: discovery: # 服务注册地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 config: # 配置中心地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 # 配置文件格式 file-extension: yml # 共享配置 - shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/service/GenTableServiceImpl.java b/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/service/GenTableServiceImpl.java index 1e656200..5d98b882 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/service/GenTableServiceImpl.java +++ b/ruoyi-modules/ruoyi-gen/src/main/java/com/ruoyi/gen/service/GenTableServiceImpl.java @@ -25,7 +25,7 @@ import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.constant.GenConstants; import com.ruoyi.common.core.exception.CustomException; import com.ruoyi.common.core.text.CharsetKit; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.file.FileUtils; import com.ruoyi.gen.domain.GenTable; diff --git a/ruoyi-modules/ruoyi-gen/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-gen/src/main/resources/bootstrap.yml index 752cdbdf..e73ad5db 100644 --- a/ruoyi-modules/ruoyi-gen/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/ruoyi-gen/src/main/resources/bootstrap.yml @@ -14,11 +14,12 @@ spring: nacos: discovery: # 服务注册地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 config: # 配置中心地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 # 配置文件格式 file-extension: yml # 共享配置 - shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/controller/SysJobController.java b/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/controller/SysJobController.java index 3c224aa6..709d0c9f 100644 --- a/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/controller/SysJobController.java +++ b/ruoyi-modules/ruoyi-job/src/main/java/com/ruoyi/job/controller/SysJobController.java @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.core.exception.job.TaskException; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; diff --git a/ruoyi-modules/ruoyi-job/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-job/src/main/resources/bootstrap.yml index 480a180f..6f7cd803 100644 --- a/ruoyi-modules/ruoyi-job/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/ruoyi-job/src/main/resources/bootstrap.yml @@ -14,11 +14,12 @@ spring: nacos: discovery: # 服务注册地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 config: # 配置中心地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 # 配置文件格式 file-extension: yml # 共享配置 - shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/ruoyi-modules/ruoyi-sentinel/pom.xml b/ruoyi-modules/ruoyi-sentinel/pom.xml index 508a4b4b..6541edeb 100644 --- a/ruoyi-modules/ruoyi-sentinel/pom.xml +++ b/ruoyi-modules/ruoyi-sentinel/pom.xml @@ -26,6 +26,33 @@ + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-config + + + + + org.springframework.boot + spring-boot-starter-actuator + + + + + com.ruoyi + ruoyi-api-system + + + + com.alibaba.csp sentinel-core @@ -145,6 +172,10 @@ 1.16.1 test + + + + diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/RuoYiSentinelDashboardApplication.java b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/RuoYiSentinelDashboardApplication.java index 04b230f1..3f77f8e4 100755 --- a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/RuoYiSentinelDashboardApplication.java +++ b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/RuoYiSentinelDashboardApplication.java @@ -17,15 +17,20 @@ package com.alibaba.csp.sentinel.dashboard; import com.alibaba.csp.sentinel.init.InitExecutor; +//import com.ruoyi.common.security.annotation.EnableCustomConfig; +//import com.ruoyi.common.security.annotation.EnableRyFeignClients; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; /** * Sentinel dashboard application. * * @author Carpenter Lee */ -@SpringBootApplication +//@EnableCustomConfig +//@EnableRyFeignClients +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) public class RuoYiSentinelDashboardApplication { public static void main(String[] args) { diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java index 92e51e54..af323e9f 100755 --- a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java +++ b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/config/WebConfig.java @@ -47,8 +47,8 @@ public class WebConfig implements WebMvcConfigurer { private final Logger logger = LoggerFactory.getLogger(WebConfig.class); - @Autowired - private LoginAuthenticationFilter loginAuthenticationFilter; +// @Autowired +// private LoginAuthenticationFilter loginAuthenticationFilter; @Autowired private AuthorizationInterceptor authorizationInterceptor; @@ -104,13 +104,13 @@ public class WebConfig implements WebMvcConfigurer { }); } - @Bean - public FilterRegistrationBean authenticationFilterRegistration() { - FilterRegistrationBean registration = new FilterRegistrationBean<>(); - registration.setFilter(loginAuthenticationFilter); - registration.addUrlPatterns("/*"); - registration.setName("authenticationFilter"); - registration.setOrder(0); - return registration; - } +// @Bean +// public FilterRegistrationBean authenticationFilterRegistration() { +// FilterRegistrationBean registration = new FilterRegistrationBean<>(); +// registration.setFilter(loginAuthenticationFilter); +// registration.addUrlPatterns("/*"); +// registration.setName("authenticationFilter"); +// registration.setOrder(0); +// return registration; +// } } diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/BaseController.java b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/BaseController.java new file mode 100644 index 00000000..f478a962 --- /dev/null +++ b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/BaseController.java @@ -0,0 +1,17 @@ +package com.alibaba.csp.sentinel.dashboard.controller.v2; + +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; + +import java.util.List; + +/** + * 控制器基类 + * @author alikes + */ +public class BaseController { + +} diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/FlowControllerV2.java b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/FlowControllerV2.java index 81228a4c..54ff7c01 100755 --- a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/FlowControllerV2.java +++ b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/v2/FlowControllerV2.java @@ -19,14 +19,13 @@ import java.util.Date; import java.util.List; import com.alibaba.csp.sentinel.dashboard.auth.AuthAction; -import com.alibaba.csp.sentinel.dashboard.auth.AuthService; import com.alibaba.csp.sentinel.dashboard.auth.AuthService.PrivilegeType; +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.util.StringUtil; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.dashboard.repository.rule.InMemoryRuleRepositoryAdapter; -import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; -import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; import com.alibaba.csp.sentinel.dashboard.domain.Result; import org.slf4j.Logger; @@ -51,7 +50,7 @@ import org.springframework.web.bind.annotation.RestController; */ @RestController @RequestMapping(value = "/v2/flow") -public class FlowControllerV2 { +public class FlowControllerV2 extends BaseController { private final Logger logger = LoggerFactory.getLogger(FlowControllerV2.class); diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/DegradeRuleNacosProvider.java b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/DegradeRuleNacosProvider.java new file mode 100644 index 00000000..a334b095 --- /dev/null +++ b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/DegradeRuleNacosProvider.java @@ -0,0 +1,52 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.dashboard.rule.nacos; + +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity; +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRuleProvider; +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.util.StringUtil; +import com.alibaba.nacos.api.config.ConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * 降级规则 + * @author alikes + */ +@Component("degradeRuleNacosProvider") +public class DegradeRuleNacosProvider implements DynamicRuleProvider> { + + @Autowired + private ConfigService configService; + + @Autowired + private Converter> converter; + + @Override + public List getRules(String appName) throws Exception { + String rules = configService.getConfig(appName + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, + NacosConfigUtil.GROUP_ID, 3000); + if (StringUtil.isEmpty(rules)) { + return new ArrayList<>(); + } + return converter.convert(rules); + } +} diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/DegradeRuleNacosPublisher.java b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/DegradeRuleNacosPublisher.java new file mode 100644 index 00000000..228b70f2 --- /dev/null +++ b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/DegradeRuleNacosPublisher.java @@ -0,0 +1,50 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.csp.sentinel.dashboard.rule.nacos; + +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity; +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; +import com.alibaba.csp.sentinel.dashboard.rule.DynamicRulePublisher; +import com.alibaba.csp.sentinel.datasource.Converter; +import com.alibaba.csp.sentinel.util.AssertUtil; +import com.alibaba.nacos.api.config.ConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @author Eric Zhao + * @since 1.4.0 + */ +@Component("degradeRuleNacosPublisher") +public class DegradeRuleNacosPublisher implements DynamicRulePublisher> { + + @Autowired + private ConfigService configService; + @Autowired + private Converter, String> converter; + + @Override + public void publish(String app, List rules) throws Exception { + AssertUtil.notEmpty(app, "app name cannot be empty"); + if (rules == null) { + return; + } + configService.publishConfig(app + NacosConfigUtil.FLOW_DATA_ID_POSTFIX, + NacosConfigUtil.GROUP_ID, converter.convert(rules)); + } +} diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/NacosConfig.java b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/NacosConfig.java index 2e91ab74..116b739f 100644 --- a/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/NacosConfig.java +++ b/ruoyi-modules/ruoyi-sentinel/src/main/java/com/alibaba/csp/sentinel/dashboard/rule/nacos/NacosConfig.java @@ -15,6 +15,7 @@ */ package com.alibaba.csp.sentinel.dashboard.rule.nacos; +import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.DegradeRuleEntity; import com.alibaba.csp.sentinel.dashboard.datasource.entity.rule.FlowRuleEntity; import com.alibaba.csp.sentinel.datasource.Converter; import com.alibaba.fastjson.JSON; @@ -36,7 +37,7 @@ import java.util.Properties; @Configuration public class NacosConfig { - @Value("${spring.nacos.server-addr}") + @Value("${spring.cloud.nacos.config.server-addr}") private String serverAddr; @Bean @@ -49,6 +50,16 @@ public class NacosConfig { return s -> JSON.parseArray(s, FlowRuleEntity.class); } + @Bean + public Converter, String> degradeRuleEntityEncoder() { + return JSON::toJSONString; + } + + @Bean + public Converter> degradeRuleEntityDecoder() { + return s -> JSON.parseArray(s, DegradeRuleEntity.class); + } + @Bean public ConfigService nacosConfigService() throws Exception { if(StringUtils.isEmpty(serverAddr)){//不配置时,使用默认配置 diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/resources/application.properties b/ruoyi-modules/ruoyi-sentinel/src/main/resources/application.properties deleted file mode 100755 index 42245637..00000000 --- a/ruoyi-modules/ruoyi-sentinel/src/main/resources/application.properties +++ /dev/null @@ -1,26 +0,0 @@ -#spring settings -spring.http.encoding.force=true -spring.http.encoding.charset=UTF-8 -spring.http.encoding.enabled=true - -#cookie name setting -server.servlet.session.cookie.name=sentinel_dashboard_cookie - -#logging settings -logging.level.org.springframework.web=INFO -logging.file=${user.home}/logs/csp/sentinel-dashboard.log -logging.pattern.file= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n -#logging.pattern.console= %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n - -#auth settings -auth.filter.exclude-urls=/,/auth/login,/auth/logout,/registry/machine,/version -auth.filter.exclude-url-suffixes=htm,html,js,css,map,ico,ttf,woff,png -# If auth.enabled=false, Sentinel console disable login -auth.username=sentinel -auth.password=sentinel - -# Inject the dashboard version. It's required to enable -# filtering in pom.xml for this resource file. -sentinel.dashboard.version=${project.version} -spring.nacos.server-addr=127.0.0.1:8848 -server.port=8718 \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/resources/application.yml b/ruoyi-modules/ruoyi-sentinel/src/main/resources/application.yml new file mode 100644 index 00000000..8974ac7a --- /dev/null +++ b/ruoyi-modules/ruoyi-sentinel/src/main/resources/application.yml @@ -0,0 +1,50 @@ +## Tomcat +#server: +# port: 8718 +# servlet: +# encoding: +# enabled: true +# force: true +# charset: UTF-8 +# session: +# cookie: +# name: sentinel_dashboard_cookie +#logging: +# level: +# org: +# springframework: +# web: INFO +# file: +# name: ${user.home}/logs/csp/sentinel-dashboard.log +# pattern: +# file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" +#auth: +# filter: +# exclude-urls: "/,/auth/login,/auth/logout,/registry/machine,/version" +# exclude-url-suffixes: "htm,html,js,css,map,ico,ttf,woff,png" +# username: sentinel +# password: sentinel +#sentinel: +# dashboard: +# version: ${project.version} +## Spring +#spring: +# application: +# # 应用名称 +# name: ruoyi-sentinel +# profiles: +# # 环境配置 +# active: dev +# cloud: +# nacos: +# discovery: +# # 服务注册地址 +# server-addr: 175.25.50.135:8848 +# config: +# # 配置中心地址 +# server-addr: 175.25.50.135:8848 +# # 配置文件格式 +# file-extension: yml +# # 共享配置 +# shared-configs: +# - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-sentinel/src/main/resources/bootstrap.yml new file mode 100644 index 00000000..67260b69 --- /dev/null +++ b/ruoyi-modules/ruoyi-sentinel/src/main/resources/bootstrap.yml @@ -0,0 +1,24 @@ +sentinel: + dashboard: + version: ${project.version} +# Spring +spring: + application: + # 应用名称 + name: ruoyi-sentinel + profiles: + # 环境配置 + active: dev + cloud: + nacos: + discovery: + # 服务注册地址 + server-addr: 175.25.50.135:8848 + config: + # 配置中心地址 + server-addr: 175.25.50.135:8848 + # 配置文件格式 + file-extension: yml + # 共享配置 + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/scripts/controllers/degrade_v2.js b/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/scripts/controllers/degrade_v2.js new file mode 100755 index 00000000..d2eac6da --- /dev/null +++ b/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/scripts/controllers/degrade_v2.js @@ -0,0 +1,204 @@ +var app = angular.module('sentinelDashboardApp'); + +app.controller('DegradeCtl', ['$scope', '$stateParams', 'DegradeService', 'ngDialog', 'MachineService', + function ($scope, $stateParams, DegradeService, ngDialog, MachineService) { + //初始化 + $scope.app = $stateParams.app; + $scope.rulesPageConfig = { + pageSize: 10, + currentPageIndex: 1, + totalPage: 1, + totalCount: 0, + }; + $scope.macsInputConfig = { + searchField: ['text', 'value'], + persist: true, + create: false, + maxItems: 1, + render: { + item: function (data, escape) { + return '
' + escape(data.text) + '
'; + } + }, + onChange: function (value, oldValue) { + $scope.macInputModel = value; + } + }; + getMachineRules(); + function getMachineRules() { + if (!$scope.macInputModel) { + return; + } + var mac = $scope.macInputModel.split(':'); + DegradeService.queryMachineRules($scope.app, mac[0], mac[1]).success( + function (data) { + if (data.code == 0 && data.data) { + $scope.rules = data.data; + $scope.rulesPageConfig.totalCount = $scope.rules.length; + } else { + $scope.rules = []; + $scope.rulesPageConfig.totalCount = 0; + } + }); + }; + $scope.getMachineRules = getMachineRules; + + var degradeRuleDialog; + $scope.editRule = function (rule) { + $scope.currentRule = angular.copy(rule); + $scope.degradeRuleDialog = { + title: '编辑降级规则', + type: 'edit', + confirmBtnText: '保存' + }; + degradeRuleDialog = ngDialog.open({ + template: '/app/views/dialog/degrade-rule-dialog.html', + width: 680, + overlay: true, + scope: $scope + }); + }; + + $scope.addNewRule = function () { + var mac = $scope.macInputModel.split(':'); + $scope.currentRule = { + grade: 0, + app: $scope.app, + ip: mac[0], + port: mac[1], + limitApp: 'default', + minRequestAmount: 5, + statIntervalMs: 1000, + }; + $scope.degradeRuleDialog = { + title: '新增降级规则', + type: 'add', + confirmBtnText: '新增' + }; + degradeRuleDialog = ngDialog.open({ + template: '/app/views/dialog/degrade-rule-dialog.html', + width: 680, + overlay: true, + scope: $scope + }); + }; + + $scope.saveRule = function () { + if (!DegradeService.checkRuleValid($scope.currentRule)) { + return; + } + if ($scope.degradeRuleDialog.type === 'add') { + addNewRule($scope.currentRule); + } else if ($scope.degradeRuleDialog.type === 'edit') { + saveRule($scope.currentRule, true); + } + }; + + function parseDegradeMode(grade) { + switch (grade) { + case 0: + return '慢调用比例'; + case 1: + return '异常比例'; + case 2: + return '异常数'; + default: + return '未知'; + } + } + + var confirmDialog; + $scope.deleteRule = function (rule) { + $scope.currentRule = rule; + $scope.confirmDialog = { + title: '删除降级规则', + type: 'delete_rule', + attentionTitle: '请确认是否删除如下降级规则', + attention: '资源名: ' + rule.resource + + ', 降级模式: ' + parseDegradeMode(rule.grade) + ', 阈值: ' + rule.count, + confirmBtnText: '删除', + }; + confirmDialog = ngDialog.open({ + template: '/app/views/dialog/confirm-dialog.html', + scope: $scope, + overlay: true + }); + }; + + $scope.confirm = function () { + if ($scope.confirmDialog.type == 'delete_rule') { + deleteRule($scope.currentRule); + } else { + console.error('error'); + } + }; + + function deleteRule(rule) { + DegradeService.deleteRule(rule).success(function (data) { + if (data.code == 0) { + getMachineRules(); + confirmDialog.close(); + } else { + alert('失败:' + data.msg); + } + }); + }; + + function addNewRule(rule) { + DegradeService.newRule(rule).success(function (data) { + if (data.code == 0) { + getMachineRules(); + degradeRuleDialog.close(); + } else { + alert('失败:' + data.msg); + } + }); + }; + + function saveRule(rule, edit) { + DegradeService.saveRule(rule).success(function (data) { + if (data.code == 0) { + getMachineRules(); + if (edit) { + degradeRuleDialog.close(); + } else { + confirmDialog.close(); + } + } else { + alert('失败:' + data.msg); + } + }); + } + queryAppMachines(); + function queryAppMachines() { + MachineService.getAppMachines($scope.app).success( + function (data) { + if (data.code == 0) { + // $scope.machines = data.data; + if (data.data) { + $scope.machines = []; + $scope.macsInputOptions = []; + data.data.forEach(function (item) { + if (item.healthy) { + $scope.macsInputOptions.push({ + text: item.ip + ':' + item.port, + value: item.ip + ':' + item.port + }); + } + }); + } + if ($scope.macsInputOptions.length > 0) { + $scope.macInputModel = $scope.macsInputOptions[0].value; + } + } else { + $scope.macsInputOptions = []; + } + } + ); + }; + $scope.$watch('macInputModel', function () { + if ($scope.macInputModel) { + getMachineRules(); + } + }); + }]); diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/scripts/services/degrade_service_v2.js b/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/scripts/services/degrade_service_v2.js new file mode 100755 index 00000000..afca761e --- /dev/null +++ b/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/scripts/services/degrade_service_v2.js @@ -0,0 +1,97 @@ +var app = angular.module('sentinelDashboardApp'); + +app.service('DegradeService', ['$http', function ($http) { + this.queryMachineRules = function (app, ip, port) { + var param = { + app: app, + ip: ip, + port: port + }; + return $http({ + url: '/V2/degrade/rules', + params: param, + method: 'GET' + }); + }; + + this.newRule = function (rule) { + return $http({ + url: '/degrade/rule', + data: rule, + method: 'POST' + }); + }; + + this.saveRule = function (rule) { + var param = { + id: rule.id, + resource: rule.resource, + limitApp: rule.limitApp, + grade: rule.grade, + count: rule.count, + timeWindow: rule.timeWindow, + statIntervalMs: rule.statIntervalMs, + minRequestAmount: rule.minRequestAmount, + slowRatioThreshold: rule.slowRatioThreshold, + }; + return $http({ + url: '/degrade/rule/' + rule.id, + data: param, + method: 'PUT' + }); + }; + + this.deleteRule = function (rule) { + return $http({ + url: '/degrade/rule/' + rule.id, + method: 'DELETE' + }); + }; + + this.checkRuleValid = function (rule) { + if (rule.resource === undefined || rule.resource === '') { + alert('资源名称不能为空'); + return false; + } + if (rule.grade === undefined || rule.grade < 0) { + alert('未知的降级策略'); + return false; + } + if (rule.count === undefined || rule.count === '' || rule.count < 0) { + alert('降级阈值不能为空或小于 0'); + return false; + } + if (rule.timeWindow == undefined || rule.timeWindow === '' || rule.timeWindow <= 0) { + alert('熔断时长必须大于 0s'); + return false; + } + if (rule.minRequestAmount == undefined || rule.minRequestAmount <= 0) { + alert('最小请求数目需大于 0'); + return false; + } + if (rule.statIntervalMs == undefined || rule.statIntervalMs <= 0) { + alert('统计窗口时长需大于 0s'); + return false; + } + if (rule.statIntervalMs !== undefined && rule.statIntervalMs > 60 * 1000 * 2) { + alert('统计窗口时长不能超过 120 分钟'); + return false; + } + // 异常比率类型. + if (rule.grade == 1 && rule.count > 1) { + alert('异常比率超出范围:[0.0 - 1.0]'); + return false; + } + if (rule.grade == 0) { + if (rule.slowRatioThreshold == undefined) { + alert('慢调用比率不能为空'); + return false; + } + if (rule.slowRatioThreshold < 0 || rule.slowRatioThreshold > 1) { + alert('慢调用比率超出范围:[0.0 - 1.0]'); + return false; + } + } + return true; + }; +}]); diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/views/degrade_v2.html b/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/views/degrade_v2.html new file mode 100755 index 00000000..c2b67528 --- /dev/null +++ b/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/app/views/degrade_v2.html @@ -0,0 +1,98 @@ +
+
+ {{app}} +
+
+ +
+
+ +
+ +
+
+
+
+
+ 降级规则 + + + +
+ +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + +
+ 资源名 + + 降级策略 + + 阈值 + + 熔断时长(s) + + 操作 +
{{rule.resource}} + 慢调用比例 + 异常比例 + 异常数 + + {{rule.count}} + + {{rule.timeWindow}}s + + + +
+
+ + + +
+ +
+ +
+ +
+ diff --git a/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/yarn.lock b/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/yarn.lock new file mode 100644 index 00000000..0f114239 --- /dev/null +++ b/ruoyi-modules/ruoyi-sentinel/src/main/webapp/resources/yarn.lock @@ -0,0 +1,3324 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@uirouter/core@5.0.20": + "integrity" "sha1-nCfY0U1QNYBAhA/QDp04w2vhrcU=" + "resolved" "http://registry.npm.alibaba-inc.com/@uirouter/core/download/@uirouter/core-5.0.20.tgz" + "version" "5.0.20" + +"accepts@~1.3.4": + "integrity" "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=" + "resolved" "http://registry.npm.alibaba-inc.com/accepts/download/accepts-1.3.5.tgz" + "version" "1.3.5" + dependencies: + "mime-types" "~2.1.18" + "negotiator" "0.6.1" + +"amdefine@>=0.0.4": + "integrity" "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + "resolved" "http://registry.npm.alibaba-inc.com/amdefine/download/amdefine-1.0.1.tgz" + "version" "1.0.1" + +"angular-animate@^1.4.0": + "integrity" "sha1-SNHSLK8AV7V7UPiCto1Rwpeqd0c=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-animate/download/angular-animate-1.7.2.tgz" + "version" "1.7.2" + +"angular-bootstrap@^0.12.2": + "integrity" "sha1-3pkAp9sIen6dpHMEqcL3f5wGmCc=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-bootstrap/download/angular-bootstrap-0.12.2.tgz" + "version" "0.12.2" + +"angular-clipboard@^1.6.2": + "integrity" "sha1-RwjlodyU85QKuJhh6h4ZsmdUFU8=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-clipboard/download/angular-clipboard-1.6.2.tgz" + "version" "1.6.2" + +"angular-cookies@^1.4.0": + "integrity" "sha1-y6OpGB0qSMLYGV/3/jKQVfupcLo=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-cookies/download/angular-cookies-1.7.2.tgz" + "version" "1.7.2" + +"angular-date-time-input@^1.2.1": + "integrity" "sha1-bXt+tH+yz2GYylZMXdW8UVYnnXY=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-date-time-input/download/angular-date-time-input-1.2.1.tgz" + "version" "1.2.1" + dependencies: + "angular" "^1.x" + "moment" "^2.15.x" + +"angular-loading-bar@^0.9.0": + "integrity" "sha1-N+9Swl8QLCFuezzf0vxaXflijkU=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-loading-bar/download/angular-loading-bar-0.9.0.tgz" + "version" "0.9.0" + +"angular-mocks@^1.4.0": + "integrity" "sha1-iivHp841VpekirAOVIuI549x+lI=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-mocks/download/angular-mocks-1.7.2.tgz" + "version" "1.7.2" + +"angular-resource@^1.4.0": + "integrity" "sha1-NtHd9AaCuY96lYA9Y6ZMxM5Wcqg=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-resource/download/angular-resource-1.7.2.tgz" + "version" "1.7.2" + +"angular-route@^1.4.0": + "integrity" "sha1-okt6DI7wmj1OLKIN5/hODoV6Ya4=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-route/download/angular-route-1.7.2.tgz" + "version" "1.7.2" + +"angular-selectize2@^v1.2.3": + "integrity" "sha1-rJJvgtckbYcBC6W+N/BKrfkRbZU=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-selectize2/download/angular-selectize2-1.2.3.tgz" + "version" "1.2.3" + +"angular-table-resize@^2.0.1": + "integrity" "sha1-yZaAqAOA9SEu/HHRTfk3uTdOmOk=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-table-resize/download/angular-table-resize-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "angular" "^1.5.7" + "jquery" "^3.0.0" + +"angular-touch@^1.4.0": + "integrity" "sha1-VLoh5nUgsPv2ocenz6RfvY/Fnvc=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-touch/download/angular-touch-1.7.2.tgz" + "version" "1.7.2" + +"angular-ui-notification@^0.3.6": + "integrity" "sha1-MzvL6ComUUgrOcNZWzy/qI4wvPc=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-ui-notification/download/angular-ui-notification-0.3.6.tgz" + "version" "0.3.6" + +"angular-ui-router@^1.0.18": + "integrity" "sha1-nB9KVMimX3xrcKm00IGPXxL7AaE=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-ui-router/download/angular-ui-router-1.0.19.tgz" + "version" "1.0.19" + dependencies: + "@uirouter/core" "5.0.20" + +"angular-utils-pagination@^0.11.1": + "integrity" "sha1-7618iHm+swrT13cH+T49DvUfLGY=" + "resolved" "http://registry.npm.alibaba-inc.com/angular-utils-pagination/download/angular-utils-pagination-0.11.1.tgz" + "version" "0.11.1" + +"angular@^1.4.8", "angular@^1.5.7", "angular@^1.6.4", "angular@^1.x": + "integrity" "sha1-aHuVXb5cUz+Nc0YEYXB68ANgJR8=" + "resolved" "http://registry.npm.alibaba-inc.com/angular/download/angular-1.7.2.tgz" + "version" "1.7.2" + +"angularjs-bootstrap-datetimepicker@^1.1.4": + "integrity" "sha1-iKT+oORv6PRWHirDKWT/WJ5UZKk=" + "resolved" "http://registry.npm.alibaba-inc.com/angularjs-bootstrap-datetimepicker/download/angularjs-bootstrap-datetimepicker-1.1.4.tgz" + "version" "1.1.4" + dependencies: + "angular" "^1.6.4" + "moment" "^2.18.1" + +"ansi-colors@^2.0.5": + "integrity" "sha512-yAdfUZ+c2wetVNIFsNRn44THW+Lty6S5TwMpUfLA/UaGhiXbBv/F8E60/1hMLd0cnF/CDoWH8vzVaI5bAcHCjw==" + "resolved" "https://registry.npmjs.org/ansi-colors/-/ansi-colors-2.0.5.tgz" + "version" "2.0.5" + +"ansi-cyan@^0.1.1": + "integrity" "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=" + "resolved" "http://registry.npm.alibaba-inc.com/ansi-cyan/download/ansi-cyan-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "ansi-wrap" "0.1.0" + +"ansi-gray@^0.1.1": + "integrity" "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=" + "resolved" "http://registry.npm.alibaba-inc.com/ansi-gray/download/ansi-gray-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "ansi-wrap" "0.1.0" + +"ansi-red@^0.1.1": + "integrity" "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=" + "resolved" "http://registry.npm.alibaba-inc.com/ansi-red/download/ansi-red-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "ansi-wrap" "0.1.0" + +"ansi-regex@^0.2.0", "ansi-regex@^0.2.1": + "integrity" "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=" + "resolved" "http://registry.npm.alibaba-inc.com/ansi-regex/download/ansi-regex-0.2.1.tgz" + "version" "0.2.1" + +"ansi-regex@^2.0.0": + "integrity" "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "resolved" "http://registry.npm.alibaba-inc.com/ansi-regex/download/ansi-regex-2.1.1.tgz" + "version" "2.1.1" + +"ansi-styles@^1.1.0": + "integrity" "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=" + "resolved" "http://registry.npm.alibaba-inc.com/ansi-styles/download/ansi-styles-1.1.0.tgz" + "version" "1.1.0" + +"ansi-styles@^2.2.1": + "integrity" "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + "resolved" "http://registry.npm.alibaba-inc.com/ansi-styles/download/ansi-styles-2.2.1.tgz" + "version" "2.2.1" + +"ansi-wrap@0.1.0": + "integrity" "sha1-qCJQ3bABXponyoLoLqYDu/pF768=" + "resolved" "http://registry.npm.alibaba-inc.com/ansi-wrap/download/ansi-wrap-0.1.0.tgz" + "version" "0.1.0" + +"ansicolors@~0.2.1": + "integrity" "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=" + "resolved" "http://registry.npm.alibaba-inc.com/ansicolors/download/ansicolors-0.2.1.tgz" + "version" "0.2.1" + +"archy@^1.0.0": + "integrity" "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + "resolved" "http://registry.npm.alibaba-inc.com/archy/download/archy-1.0.0.tgz" + "version" "1.0.0" + +"arr-diff@^1.0.1": + "integrity" "sha1-aHwydYFjWI/vfeezb6vklesaOZo=" + "resolved" "http://registry.npm.alibaba-inc.com/arr-diff/download/arr-diff-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "arr-flatten" "^1.0.1" + "array-slice" "^0.2.3" + +"arr-diff@^4.0.0": + "integrity" "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + "resolved" "http://registry.npm.alibaba-inc.com/arr-diff/download/arr-diff-4.0.0.tgz" + "version" "4.0.0" + +"arr-flatten@^1.0.1", "arr-flatten@^1.1.0": + "integrity" "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=" + "resolved" "http://registry.npm.alibaba-inc.com/arr-flatten/download/arr-flatten-1.1.0.tgz" + "version" "1.1.0" + +"arr-union@^2.0.1": + "integrity" "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=" + "resolved" "http://registry.npm.alibaba-inc.com/arr-union/download/arr-union-2.1.0.tgz" + "version" "2.1.0" + +"arr-union@^3.1.0": + "integrity" "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" + "resolved" "http://registry.npm.alibaba-inc.com/arr-union/download/arr-union-3.1.0.tgz" + "version" "3.1.0" + +"array-differ@^1.0.0": + "integrity" "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + "resolved" "http://registry.npm.alibaba-inc.com/array-differ/download/array-differ-1.0.0.tgz" + "version" "1.0.0" + +"array-each@^1.0.1": + "integrity" "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" + "resolved" "http://registry.npm.alibaba-inc.com/array-each/download/array-each-1.0.1.tgz" + "version" "1.0.1" + +"array-find-index@^1.0.1": + "integrity" "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + "resolved" "http://registry.npm.alibaba-inc.com/array-find-index/download/array-find-index-1.0.2.tgz" + "version" "1.0.2" + +"array-slice@^0.2.3": + "integrity" "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=" + "resolved" "http://registry.npm.alibaba-inc.com/array-slice/download/array-slice-0.2.3.tgz" + "version" "0.2.3" + +"array-slice@^1.0.0": + "integrity" "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=" + "resolved" "http://registry.npm.taobao.org/array-slice/download/array-slice-1.1.0.tgz" + "version" "1.1.0" + +"array-uniq@^1.0.2": + "integrity" "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + "resolved" "http://registry.npm.alibaba-inc.com/array-uniq/download/array-uniq-1.0.3.tgz" + "version" "1.0.3" + +"array-unique@^0.2.1": + "integrity" "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + "resolved" "http://registry.npm.alibaba-inc.com/array-unique/download/array-unique-0.2.1.tgz" + "version" "0.2.1" + +"array-unique@^0.3.2": + "integrity" "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + "resolved" "http://registry.npm.alibaba-inc.com/array-unique/download/array-unique-0.3.2.tgz" + "version" "0.3.2" + +"assign-symbols@^1.0.0": + "integrity" "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" + "resolved" "http://registry.npm.alibaba-inc.com/assign-symbols/download/assign-symbols-1.0.0.tgz" + "version" "1.0.0" + +"async@^2.6.0": + "integrity" "sha1-skWiPKcZMAROxT+kaqAKPofGphA=" + "resolved" "http://registry.npm.alibaba-inc.com/async/download/async-2.6.1.tgz" + "version" "2.6.1" + dependencies: + "lodash" "^4.17.10" + +"atob@^2.1.1": + "integrity" "sha1-ri1acpR38onWDdf5amMUoi3Wwio=" + "resolved" "http://registry.npm.alibaba-inc.com/atob/download/atob-2.1.1.tgz" + "version" "2.1.1" + +"balanced-match@^1.0.0": + "integrity" "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "resolved" "http://registry.npm.alibaba-inc.com/balanced-match/download/balanced-match-1.0.0.tgz" + "version" "1.0.0" + +"base@^0.11.1": + "integrity" "sha1-e95c7RRbbVUakNuH+DxVi060io8=" + "resolved" "http://registry.npm.alibaba-inc.com/base/download/base-0.11.2.tgz" + "version" "0.11.2" + dependencies: + "cache-base" "^1.0.1" + "class-utils" "^0.3.5" + "component-emitter" "^1.2.1" + "define-property" "^1.0.0" + "isobject" "^3.0.1" + "mixin-deep" "^1.2.0" + "pascalcase" "^0.1.1" + +"batch@0.6.1": + "integrity" "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + "resolved" "http://registry.npm.alibaba-inc.com/batch/download/batch-0.6.1.tgz" + "version" "0.6.1" + +"beeper@^1.0.0": + "integrity" "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=" + "resolved" "http://registry.npm.alibaba-inc.com/beeper/download/beeper-1.1.1.tgz" + "version" "1.1.1" + +"body@^5.1.0": + "integrity" "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=" + "resolved" "https://registry.npmjs.org/body/-/body-5.1.0.tgz" + "version" "5.1.0" + dependencies: + "continuable-cache" "^0.3.1" + "error" "^7.0.0" + "raw-body" "~1.1.0" + "safe-json-parse" "~1.0.1" + +"bootstrap-switch@^3.3.4": + "integrity" "sha1-cOCusqh3wNx2aZHeEI4hcPwpov8=" + "resolved" "http://registry.npm.alibaba-inc.com/bootstrap-switch/download/bootstrap-switch-3.3.4.tgz" + "version" "3.3.4" + +"bootstrap-tagsinput@~0.7.1": + "integrity" "sha1-/+Owa74qEGlF7ygUVoAFqU8hGTc=" + "resolved" "http://registry.npm.alibaba-inc.com/bootstrap-tagsinput/download/bootstrap-tagsinput-0.7.1.tgz" + "version" "0.7.1" + +"brace-expansion@^1.0.0", "brace-expansion@^1.1.7": + "integrity" "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=" + "resolved" "http://registry.npm.alibaba-inc.com/brace-expansion/download/brace-expansion-1.1.11.tgz" + "version" "1.1.11" + dependencies: + "balanced-match" "^1.0.0" + "concat-map" "0.0.1" + +"braces@^2.3.1": + "integrity" "sha1-WXn9PxTNUxVl5fot8av/8d+u5yk=" + "resolved" "http://registry.npm.alibaba-inc.com/braces/download/braces-2.3.2.tgz" + "version" "2.3.2" + dependencies: + "arr-flatten" "^1.1.0" + "array-unique" "^0.3.2" + "extend-shallow" "^2.0.1" + "fill-range" "^4.0.0" + "isobject" "^3.0.1" + "repeat-element" "^1.1.2" + "snapdragon" "^0.8.1" + "snapdragon-node" "^2.0.1" + "split-string" "^3.0.2" + "to-regex" "^3.0.1" + +"builtin-modules@^1.0.0": + "integrity" "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + "resolved" "http://registry.npm.alibaba-inc.com/builtin-modules/download/builtin-modules-1.1.1.tgz" + "version" "1.1.1" + +"bytes@1": + "integrity" "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=" + "resolved" "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz" + "version" "1.0.0" + +"cache-base@^1.0.1": + "integrity" "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=" + "resolved" "http://registry.npm.alibaba-inc.com/cache-base/download/cache-base-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "collection-visit" "^1.0.0" + "component-emitter" "^1.2.1" + "get-value" "^2.0.6" + "has-value" "^1.0.0" + "isobject" "^3.0.1" + "set-value" "^2.0.0" + "to-object-path" "^0.3.0" + "union-value" "^1.0.0" + "unset-value" "^1.0.0" + +"camelcase-keys@^2.0.0": + "integrity" "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=" + "resolved" "http://registry.npm.alibaba-inc.com/camelcase-keys/download/camelcase-keys-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "camelcase" "^2.0.0" + "map-obj" "^1.0.0" + +"camelcase@^2.0.0": + "integrity" "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + "resolved" "http://registry.npm.alibaba-inc.com/camelcase/download/camelcase-2.1.1.tgz" + "version" "2.1.1" + +"cardinal@^1.0.0": + "integrity" "sha1-UOIcGwqjdyn5N33vGWtanOyTLuk=" + "resolved" "http://registry.npm.alibaba-inc.com/cardinal/download/cardinal-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "ansicolors" "~0.2.1" + "redeyed" "~1.0.0" + +"chalk@^0.5.0": + "integrity" "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=" + "resolved" "http://registry.npm.alibaba-inc.com/chalk/download/chalk-0.5.1.tgz" + "version" "0.5.1" + dependencies: + "ansi-styles" "^1.1.0" + "escape-string-regexp" "^1.0.0" + "has-ansi" "^0.1.0" + "strip-ansi" "^0.3.0" + "supports-color" "^0.2.0" + +"chalk@^1.0.0": + "integrity" "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=" + "resolved" "http://registry.npm.alibaba-inc.com/chalk/download/chalk-1.1.3.tgz" + "version" "1.1.3" + dependencies: + "ansi-styles" "^2.2.1" + "escape-string-regexp" "^1.0.2" + "has-ansi" "^2.0.0" + "strip-ansi" "^3.0.0" + "supports-color" "^2.0.0" + +"class-utils@^0.3.5": + "integrity" "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=" + "resolved" "http://registry.npm.alibaba-inc.com/class-utils/download/class-utils-0.3.6.tgz" + "version" "0.3.6" + dependencies: + "arr-union" "^3.1.0" + "define-property" "^0.2.5" + "isobject" "^3.0.0" + "static-extend" "^0.1.1" + +"clean-css@^3.1.9": + "integrity" "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=" + "resolved" "https://registry.npm.taobao.org/clean-css/download/clean-css-3.4.28.tgz" + "version" "3.4.28" + dependencies: + "commander" "2.8.x" + "source-map" "0.4.x" + +"cli@~1.0.0": + "integrity" "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=" + "resolved" "http://registry.npm.alibaba-inc.com/cli/download/cli-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "exit" "0.1.2" + "glob" "^7.1.1" + +"clone-buffer@^1.0.0": + "integrity" "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + "resolved" "http://registry.npm.alibaba-inc.com/clone-buffer/download/clone-buffer-1.0.0.tgz" + "version" "1.0.0" + +"clone-stats@^0.0.1", "clone-stats@~0.0.1": + "integrity" "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + "resolved" "http://registry.npm.alibaba-inc.com/clone-stats/download/clone-stats-0.0.1.tgz" + "version" "0.0.1" + +"clone-stats@^1.0.0": + "integrity" "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + "resolved" "http://registry.npm.alibaba-inc.com/clone-stats/download/clone-stats-1.0.0.tgz" + "version" "1.0.0" + +"clone@^0.2.0": + "integrity" "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=" + "resolved" "https://registry.npm.taobao.org/clone/download/clone-0.2.0.tgz" + "version" "0.2.0" + +"clone@^1.0.0", "clone@^1.0.2": + "integrity" "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + "resolved" "http://registry.npm.alibaba-inc.com/clone/download/clone-1.0.4.tgz" + "version" "1.0.4" + +"clone@^2.1.1": + "integrity" "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + "resolved" "http://registry.npm.alibaba-inc.com/clone/download/clone-2.1.1.tgz" + "version" "2.1.1" + +"cloneable-readable@^1.0.0": + "integrity" "sha1-1ZHe5Kj4vBXaQ86X3O66E9Q+KmU=" + "resolved" "http://registry.npm.alibaba-inc.com/cloneable-readable/download/cloneable-readable-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "inherits" "^2.0.1" + "process-nextick-args" "^2.0.0" + "readable-stream" "^2.3.5" + +"collection-visit@^1.0.0": + "integrity" "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=" + "resolved" "http://registry.npm.alibaba-inc.com/collection-visit/download/collection-visit-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "map-visit" "^1.0.0" + "object-visit" "^1.0.0" + +"color-support@^1.1.3": + "integrity" "sha1-k4NDeaHMmgxh+C9S8NBDIiUb1aI=" + "resolved" "http://registry.npm.alibaba-inc.com/color-support/download/color-support-1.1.3.tgz" + "version" "1.1.3" + +"commander@~2.17.1": + "integrity" "sha1-vXerfebelCBc6sxy8XFtKfIKd78=" + "resolved" "http://registry.npm.taobao.org/commander/download/commander-2.17.1.tgz" + "version" "2.17.1" + +"commander@2.0.0": + "integrity" "sha1-0bhvkB+LZL2UG96tr5JFMDk76Sg=" + "resolved" "http://registry.npm.alibaba-inc.com/commander/download/commander-2.0.0.tgz" + "version" "2.0.0" + +"commander@2.8.x": + "integrity" "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=" + "resolved" "https://registry.npm.taobao.org/commander/download/commander-2.8.1.tgz" + "version" "2.8.1" + dependencies: + "graceful-readlink" ">= 1.0.0" + +"component-emitter@^1.2.1": + "integrity" "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" + "resolved" "http://registry.npm.alibaba-inc.com/component-emitter/download/component-emitter-1.2.1.tgz" + "version" "1.2.1" + +"concat-map@0.0.1": + "integrity" "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "resolved" "http://registry.npm.alibaba-inc.com/concat-map/download/concat-map-0.0.1.tgz" + "version" "0.0.1" + +"concat-with-sourcemaps@^1.0.0": + "integrity" "sha1-1OqT8FriV5CVG5nns7CeOQikCC4=" + "resolved" "http://registry.npm.alibaba-inc.com/concat-with-sourcemaps/download/concat-with-sourcemaps-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "source-map" "^0.6.1" + +"connect-livereload@^0.6.0": + "integrity" "sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==" + "resolved" "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.6.1.tgz" + "version" "0.6.1" + +"connect@^3.3.3", "connect@^3.6.6": + "integrity" "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=" + "resolved" "http://registry.npm.alibaba-inc.com/connect/download/connect-3.6.6.tgz" + "version" "3.6.6" + dependencies: + "debug" "2.6.9" + "finalhandler" "1.1.0" + "parseurl" "~1.3.2" + "utils-merge" "1.0.1" + +"console-browserify@1.1.x": + "integrity" "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=" + "resolved" "http://registry.npm.alibaba-inc.com/console-browserify/download/console-browserify-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "date-now" "^0.1.4" + +"continuable-cache@^0.3.1": + "integrity" "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=" + "resolved" "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz" + "version" "0.3.1" + +"copy-descriptor@^0.1.0": + "integrity" "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" + "resolved" "http://registry.npm.alibaba-inc.com/copy-descriptor/download/copy-descriptor-0.1.1.tgz" + "version" "0.1.1" + +"core-util-is@~1.0.0": + "integrity" "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "resolved" "http://registry.npm.alibaba-inc.com/core-util-is/download/core-util-is-1.0.2.tgz" + "version" "1.0.2" + +"csscomb-core@3.0.0-3.1": + "integrity" "sha1-tBHI18/g3z8v4d+E0b1kpvAEbGg=" + "resolved" "http://registry.npm.alibaba-inc.com/csscomb-core/download/csscomb-core-3.0.0-3.1.tgz" + "version" "3.0.0-3.1" + dependencies: + "gonzales-pe" "3.0.0-28" + "minimatch" "0.2.12" + "vow" "0.4.4" + "vow-fs" "0.3.2" + +"csscomb@^3.1.7": + "integrity" "sha1-qKc4iE9Am6817JRhr8UuHHW9I6I=" + "resolved" "http://registry.npm.alibaba-inc.com/csscomb/download/csscomb-3.1.8.tgz" + "version" "3.1.8" + dependencies: + "commander" "2.0.0" + "csscomb-core" "3.0.0-3.1" + "gonzales-pe" "3.0.0-28" + "vow" "0.4.4" + +"csv-parse@^2.0.0": + "integrity" "sha1-ZXSJl+zDcZxZRiLbG56g4ut9Vrs=" + "resolved" "http://registry.npm.alibaba-inc.com/csv-parse/download/csv-parse-2.5.0.tgz" + "version" "2.5.0" + +"currently-unhandled@^0.4.1": + "integrity" "sha1-mI3zP+qxke95mmE2nddsF635V+o=" + "resolved" "http://registry.npm.alibaba-inc.com/currently-unhandled/download/currently-unhandled-0.4.1.tgz" + "version" "0.4.1" + dependencies: + "array-find-index" "^1.0.1" + +"date-now@^0.1.4": + "integrity" "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" + "resolved" "http://registry.npm.alibaba-inc.com/date-now/download/date-now-0.1.4.tgz" + "version" "0.1.4" + +"dateformat@^1.0.7-1.2.3": + "integrity" "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=" + "resolved" "http://registry.npm.alibaba-inc.com/dateformat/download/dateformat-1.0.12.tgz" + "version" "1.0.12" + dependencies: + "get-stdin" "^4.0.1" + "meow" "^3.3.0" + +"dateformat@^2.0.0": + "integrity" "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=" + "resolved" "http://registry.npm.alibaba-inc.com/dateformat/download/dateformat-2.2.0.tgz" + "version" "2.2.0" + +"debug@^2.2.0", "debug@^2.3.3", "debug@2.6.9": + "integrity" "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=" + "resolved" "http://registry.npm.alibaba-inc.com/debug/download/debug-2.6.9.tgz" + "version" "2.6.9" + dependencies: + "ms" "2.0.0" + +"debug@^3.1.0": + "integrity" "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==" + "resolved" "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz" + "version" "3.2.6" + dependencies: + "ms" "^2.1.1" + +"decamelize@^1.1.2": + "integrity" "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "resolved" "http://registry.npm.alibaba-inc.com/decamelize/download/decamelize-1.2.0.tgz" + "version" "1.2.0" + +"decode-uri-component@^0.2.0": + "integrity" "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "resolved" "http://registry.npm.alibaba-inc.com/decode-uri-component/download/decode-uri-component-0.2.0.tgz" + "version" "0.2.0" + +"defaults@^1.0.0": + "integrity" "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=" + "resolved" "https://registry.npm.taobao.org/defaults/download/defaults-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "clone" "^1.0.2" + +"define-property@^0.2.5": + "integrity" "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=" + "resolved" "http://registry.npm.alibaba-inc.com/define-property/download/define-property-0.2.5.tgz" + "version" "0.2.5" + dependencies: + "is-descriptor" "^0.1.0" + +"define-property@^1.0.0": + "integrity" "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=" + "resolved" "http://registry.npm.alibaba-inc.com/define-property/download/define-property-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-descriptor" "^1.0.0" + +"define-property@^2.0.2": + "integrity" "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=" + "resolved" "http://registry.npm.alibaba-inc.com/define-property/download/define-property-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "is-descriptor" "^1.0.2" + "isobject" "^3.0.1" + +"depd@~1.1.2": + "integrity" "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "resolved" "http://registry.npm.alibaba-inc.com/depd/download/depd-1.1.2.tgz" + "version" "1.1.2" + +"deprecated@^0.0.1": + "integrity" "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=" + "resolved" "https://registry.npm.taobao.org/deprecated/download/deprecated-0.0.1.tgz" + "version" "0.0.1" + +"destroy@~1.0.4": + "integrity" "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "resolved" "http://registry.npm.alibaba-inc.com/destroy/download/destroy-1.0.4.tgz" + "version" "1.0.4" + +"detect-file@^1.0.0": + "integrity" "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" + "resolved" "http://registry.npm.alibaba-inc.com/detect-file/download/detect-file-1.0.0.tgz" + "version" "1.0.0" + +"dom-serializer@0": + "integrity" "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==" + "resolved" "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "domelementtype" "^1.3.0" + "entities" "^1.1.1" + +"domelementtype@^1.3.0", "domelementtype@1": + "integrity" "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + "resolved" "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz" + "version" "1.3.1" + +"domhandler@2.3": + "integrity" "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=" + "resolved" "http://registry.npm.alibaba-inc.com/domhandler/download/domhandler-2.3.0.tgz" + "version" "2.3.0" + dependencies: + "domelementtype" "1" + +"domutils@1.5": + "integrity" "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=" + "resolved" "http://registry.npm.alibaba-inc.com/domutils/download/domutils-1.5.1.tgz" + "version" "1.5.1" + dependencies: + "dom-serializer" "0" + "domelementtype" "1" + +"duplexer2@0.0.2": + "integrity" "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=" + "resolved" "http://registry.npm.alibaba-inc.com/duplexer2/download/duplexer2-0.0.2.tgz" + "version" "0.0.2" + dependencies: + "readable-stream" "~1.1.9" + +"ee-first@1.1.1": + "integrity" "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + "resolved" "http://registry.npm.alibaba-inc.com/ee-first/download/ee-first-1.1.1.tgz" + "version" "1.1.1" + +"encodeurl@~1.0.1", "encodeurl@~1.0.2": + "integrity" "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + "resolved" "http://registry.npm.alibaba-inc.com/encodeurl/download/encodeurl-1.0.2.tgz" + "version" "1.0.2" + +"end-of-stream@~0.1.5": + "integrity" "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=" + "resolved" "https://registry.npm.taobao.org/end-of-stream/download/end-of-stream-0.1.5.tgz" + "version" "0.1.5" + dependencies: + "once" "~1.3.0" + +"entities@^1.1.1": + "integrity" "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + "resolved" "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz" + "version" "1.1.2" + +"entities@1.0": + "integrity" "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" + "resolved" "http://registry.npm.alibaba-inc.com/entities/download/entities-1.0.0.tgz" + "version" "1.0.0" + +"error-ex@^1.2.0": + "integrity" "sha1-tKxAZIEH/c3PriQvQovqihTU8b8=" + "resolved" "http://registry.npm.alibaba-inc.com/error-ex/download/error-ex-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "is-arrayish" "^0.2.1" + +"error@^7.0.0": + "integrity" "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=" + "resolved" "https://registry.npmjs.org/error/-/error-7.0.2.tgz" + "version" "7.0.2" + dependencies: + "string-template" "~0.2.1" + "xtend" "~4.0.0" + +"escape-html@~1.0.3": + "integrity" "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + "resolved" "http://registry.npm.alibaba-inc.com/escape-html/download/escape-html-1.0.3.tgz" + "version" "1.0.3" + +"escape-string-regexp@^1.0.0", "escape-string-regexp@^1.0.2": + "integrity" "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "resolved" "http://registry.npm.alibaba-inc.com/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz" + "version" "1.0.5" + +"esprima@~3.0.0": + "integrity" "sha1-U88kes2ncxPlUcOqLnM0LT+099k=" + "resolved" "http://registry.npm.alibaba-inc.com/esprima/download/esprima-3.0.0.tgz" + "version" "3.0.0" + +"etag@~1.8.1": + "integrity" "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + "resolved" "http://registry.npm.alibaba-inc.com/etag/download/etag-1.8.1.tgz" + "version" "1.8.1" + +"exit@0.1.2", "exit@0.1.x": + "integrity" "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" + "resolved" "http://registry.npm.alibaba-inc.com/exit/download/exit-0.1.2.tgz" + "version" "0.1.2" + +"expand-brackets@^2.1.4": + "integrity" "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=" + "resolved" "http://registry.npm.alibaba-inc.com/expand-brackets/download/expand-brackets-2.1.4.tgz" + "version" "2.1.4" + dependencies: + "debug" "^2.3.3" + "define-property" "^0.2.5" + "extend-shallow" "^2.0.1" + "posix-character-classes" "^0.1.0" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.1" + +"expand-tilde@^2.0.0", "expand-tilde@^2.0.2": + "integrity" "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=" + "resolved" "http://registry.npm.alibaba-inc.com/expand-tilde/download/expand-tilde-2.0.2.tgz" + "version" "2.0.2" + dependencies: + "homedir-polyfill" "^1.0.1" + +"extend-shallow@^1.1.2": + "integrity" "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=" + "resolved" "http://registry.npm.alibaba-inc.com/extend-shallow/download/extend-shallow-1.1.4.tgz" + "version" "1.1.4" + dependencies: + "kind-of" "^1.1.0" + +"extend-shallow@^2.0.1": + "integrity" "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=" + "resolved" "http://registry.npm.alibaba-inc.com/extend-shallow/download/extend-shallow-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "is-extendable" "^0.1.0" + +"extend-shallow@^3.0.0", "extend-shallow@^3.0.2": + "integrity" "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=" + "resolved" "http://registry.npm.alibaba-inc.com/extend-shallow/download/extend-shallow-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "assign-symbols" "^1.0.0" + "is-extendable" "^1.0.1" + +"extend@^3.0.0": + "integrity" "sha1-+LETa0Bx+9jrFAr/hYsQGewpFfo=" + "resolved" "https://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz" + "version" "3.0.2" + +"extglob@^2.0.4": + "integrity" "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=" + "resolved" "http://registry.npm.alibaba-inc.com/extglob/download/extglob-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "array-unique" "^0.3.2" + "define-property" "^1.0.0" + "expand-brackets" "^2.1.4" + "extend-shallow" "^2.0.1" + "fragment-cache" "^0.2.1" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.1" + +"fancy-log@^1.1.0", "fancy-log@^1.2.0", "fancy-log@^1.3.2": + "integrity" "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=" + "resolved" "http://registry.npm.alibaba-inc.com/fancy-log/download/fancy-log-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "ansi-gray" "^0.1.1" + "color-support" "^1.1.3" + "time-stamp" "^1.0.0" + +"faye-websocket@~0.10.0": + "integrity" "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=" + "resolved" "http://registry.npm.alibaba-inc.com/faye-websocket/download/faye-websocket-0.10.0.tgz" + "version" "0.10.0" + dependencies: + "websocket-driver" ">=0.5.1" + +"filesize@~2.0.0": + "integrity" "sha1-eAWUHGD83+Y/RtfqNYxZreEcEyU=" + "resolved" "http://registry.npm.alibaba-inc.com/filesize/download/filesize-2.0.4.tgz" + "version" "2.0.4" + +"fill-range@^4.0.0": + "integrity" "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=" + "resolved" "http://registry.npm.alibaba-inc.com/fill-range/download/fill-range-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "extend-shallow" "^2.0.1" + "is-number" "^3.0.0" + "repeat-string" "^1.6.1" + "to-regex-range" "^2.1.0" + +"finalhandler@1.1.0": + "integrity" "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=" + "resolved" "http://registry.npm.alibaba-inc.com/finalhandler/download/finalhandler-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "debug" "2.6.9" + "encodeurl" "~1.0.1" + "escape-html" "~1.0.3" + "on-finished" "~2.3.0" + "parseurl" "~1.3.2" + "statuses" "~1.3.1" + "unpipe" "~1.0.0" + +"find-index@^0.1.1": + "integrity" "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=" + "resolved" "https://registry.npm.taobao.org/find-index/download/find-index-0.1.1.tgz" + "version" "0.1.1" + +"find-up@^1.0.0": + "integrity" "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=" + "resolved" "http://registry.npm.alibaba-inc.com/find-up/download/find-up-1.1.2.tgz" + "version" "1.1.2" + dependencies: + "path-exists" "^2.0.0" + "pinkie-promise" "^2.0.0" + +"findup-sync@^2.0.0": + "integrity" "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=" + "resolved" "https://registry.npm.taobao.org/findup-sync/download/findup-sync-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "detect-file" "^1.0.0" + "is-glob" "^3.1.0" + "micromatch" "^3.0.4" + "resolve-dir" "^1.0.1" + +"findup-sync@^3.0.0": + "integrity" "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==" + "resolved" "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "detect-file" "^1.0.0" + "is-glob" "^4.0.0" + "micromatch" "^3.0.4" + "resolve-dir" "^1.0.1" + +"fined@^1.0.1": + "integrity" "sha1-0AvszxqitHXRbUI7Aji3E6LEo3s=" + "resolved" "https://registry.npm.taobao.org/fined/download/fined-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "expand-tilde" "^2.0.2" + "is-plain-object" "^2.0.3" + "object.defaults" "^1.1.0" + "object.pick" "^1.2.0" + "parse-filepath" "^1.0.1" + +"first-chunk-stream@^1.0.0": + "integrity" "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=" + "resolved" "https://registry.npm.taobao.org/first-chunk-stream/download/first-chunk-stream-1.0.0.tgz" + "version" "1.0.0" + +"flagged-respawn@^1.0.0": + "integrity" "sha1-595vEnnd2cqarIpZcdYYYGs6q0E=" + "resolved" "https://registry.npm.taobao.org/flagged-respawn/download/flagged-respawn-1.0.1.tgz" + "version" "1.0.1" + +"for-in@^1.0.1", "for-in@^1.0.2": + "integrity" "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + "resolved" "http://registry.npm.alibaba-inc.com/for-in/download/for-in-1.0.2.tgz" + "version" "1.0.2" + +"for-own@^1.0.0": + "integrity" "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=" + "resolved" "http://registry.npm.alibaba-inc.com/for-own/download/for-own-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "for-in" "^1.0.1" + +"fragment-cache@^0.2.1": + "integrity" "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=" + "resolved" "http://registry.npm.alibaba-inc.com/fragment-cache/download/fragment-cache-0.2.1.tgz" + "version" "0.2.1" + dependencies: + "map-cache" "^0.2.2" + +"fresh@0.5.2": + "integrity" "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + "resolved" "http://registry.npm.alibaba-inc.com/fresh/download/fresh-0.5.2.tgz" + "version" "0.5.2" + +"fs.realpath@^1.0.0": + "integrity" "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "resolved" "http://registry.npm.alibaba-inc.com/fs.realpath/download/fs.realpath-1.0.0.tgz" + "version" "1.0.0" + +"gaze@^0.5.1": + "integrity" "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=" + "resolved" "https://registry.npm.taobao.org/gaze/download/gaze-0.5.2.tgz" + "version" "0.5.2" + dependencies: + "globule" "~0.1.0" + +"get-stdin@^4.0.1": + "integrity" "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + "resolved" "http://registry.npm.alibaba-inc.com/get-stdin/download/get-stdin-4.0.1.tgz" + "version" "4.0.1" + +"get-value@^2.0.3", "get-value@^2.0.6": + "integrity" "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" + "resolved" "http://registry.npm.alibaba-inc.com/get-value/download/get-value-2.0.6.tgz" + "version" "2.0.6" + +"glob-stream@^3.1.5": + "integrity" "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=" + "resolved" "https://registry.npm.taobao.org/glob-stream/download/glob-stream-3.1.18.tgz" + "version" "3.1.18" + dependencies: + "glob" "^4.3.1" + "glob2base" "^0.0.12" + "minimatch" "^2.0.1" + "ordered-read-streams" "^0.1.0" + "through2" "^0.6.1" + "unique-stream" "^1.0.0" + +"glob-watcher@^0.0.6": + "integrity" "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=" + "resolved" "https://registry.npm.taobao.org/glob-watcher/download/glob-watcher-0.0.6.tgz" + "version" "0.0.6" + dependencies: + "gaze" "^0.5.1" + +"glob@^4.3.1": + "integrity" "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=" + "resolved" "https://registry.npm.taobao.org/glob/download/glob-4.5.3.tgz" + "version" "4.5.3" + dependencies: + "inflight" "^1.0.4" + "inherits" "2" + "minimatch" "^2.0.1" + "once" "^1.3.0" + +"glob@^7.0.5": + "integrity" "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=" + "resolved" "http://registry.npm.alibaba-inc.com/glob/download/glob-7.1.2.tgz" + "version" "7.1.2" + dependencies: + "fs.realpath" "^1.0.0" + "inflight" "^1.0.4" + "inherits" "2" + "minimatch" "^3.0.4" + "once" "^1.3.0" + "path-is-absolute" "^1.0.0" + +"glob@^7.1.1": + "integrity" "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==" + "resolved" "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz" + "version" "7.1.3" + dependencies: + "fs.realpath" "^1.0.0" + "inflight" "^1.0.4" + "inherits" "2" + "minimatch" "^3.0.4" + "once" "^1.3.0" + "path-is-absolute" "^1.0.0" + +"glob@~3.1.21": + "integrity" "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=" + "resolved" "https://registry.npm.taobao.org/glob/download/glob-3.1.21.tgz" + "version" "3.1.21" + dependencies: + "graceful-fs" "~1.2.0" + "inherits" "1" + "minimatch" "~0.2.11" + +"glob@3.2.8": + "integrity" "sha1-VQb0MRchvMYYx9jboUQYh1AwcHM=" + "resolved" "http://registry.npm.alibaba-inc.com/glob/download/glob-3.2.8.tgz" + "version" "3.2.8" + dependencies: + "inherits" "2" + "minimatch" "~0.2.11" + +"glob2base@^0.0.12": + "integrity" "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=" + "resolved" "https://registry.npm.taobao.org/glob2base/download/glob2base-0.0.12.tgz" + "version" "0.0.12" + dependencies: + "find-index" "^0.1.1" + +"global-modules@^1.0.0": + "integrity" "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=" + "resolved" "http://registry.npm.alibaba-inc.com/global-modules/download/global-modules-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "global-prefix" "^1.0.1" + "is-windows" "^1.0.1" + "resolve-dir" "^1.0.0" + +"global-prefix@^1.0.1": + "integrity" "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=" + "resolved" "http://registry.npm.alibaba-inc.com/global-prefix/download/global-prefix-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "expand-tilde" "^2.0.2" + "homedir-polyfill" "^1.0.1" + "ini" "^1.3.4" + "is-windows" "^1.0.1" + "which" "^1.2.14" + +"globule@~0.1.0": + "integrity" "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=" + "resolved" "https://registry.npm.taobao.org/globule/download/globule-0.1.0.tgz" + "version" "0.1.0" + dependencies: + "glob" "~3.1.21" + "lodash" "~1.0.1" + "minimatch" "~0.2.11" + +"glogg@^1.0.0": + "integrity" "sha1-3PdY5EeJzD89MsHzVio2duajSBA=" + "resolved" "http://registry.npm.alibaba-inc.com/glogg/download/glogg-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "sparkles" "^1.0.0" + +"gonzales-pe@3.0.0-28": + "integrity" "sha1-3VC0HdFbaCooxA5fD/IAeQGsYr0=" + "resolved" "http://registry.npm.alibaba-inc.com/gonzales-pe/download/gonzales-pe-3.0.0-28.tgz" + "version" "3.0.0-28" + +"graceful-fs@^3.0.0": + "integrity" "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=" + "resolved" "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-3.0.11.tgz" + "version" "3.0.11" + dependencies: + "natives" "^1.1.0" + +"graceful-fs@^4.1.2": + "integrity" "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "resolved" "http://registry.npm.alibaba-inc.com/graceful-fs/download/graceful-fs-4.1.11.tgz" + "version" "4.1.11" + +"graceful-fs@~1.2.0": + "integrity" "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=" + "resolved" "https://registry.npm.taobao.org/graceful-fs/download/graceful-fs-1.2.3.tgz" + "version" "1.2.3" + +"graceful-fs@~2.0.0": + "integrity" "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=" + "resolved" "http://registry.npm.alibaba-inc.com/graceful-fs/download/graceful-fs-2.0.3.tgz" + "version" "2.0.3" + +"graceful-fs@~4.1.4": + "integrity" "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + "resolved" "http://registry.npm.alibaba-inc.com/graceful-fs/download/graceful-fs-4.1.11.tgz" + "version" "4.1.11" + +"graceful-readlink@>= 1.0.0": + "integrity" "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + "resolved" "http://registry.npm.alibaba-inc.com/graceful-readlink/download/graceful-readlink-1.0.1.tgz" + "version" "1.0.1" + +"gulp-clean@^0.4.0": + "integrity" "sha1-O8JecITmQbvXveBXz5DAHFDZWVA=" + "resolved" "http://registry.npm.alibaba-inc.com/gulp-clean/download/gulp-clean-0.4.0.tgz" + "version" "0.4.0" + dependencies: + "fancy-log" "^1.3.2" + "plugin-error" "^0.1.2" + "rimraf" "^2.6.2" + "through2" "^2.0.3" + "vinyl" "^2.1.0" + +"gulp-concat@^2.6.1": + "integrity" "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=" + "resolved" "http://registry.npm.alibaba-inc.com/gulp-concat/download/gulp-concat-2.6.1.tgz" + "version" "2.6.1" + dependencies: + "concat-with-sourcemaps" "^1.0.0" + "through2" "^2.0.0" + "vinyl" "^2.0.0" + +"gulp-connect@^5.7.0": + "integrity" "sha512-8tRcC6wgXMLakpPw9M7GRJIhxkYdgZsXwn7n56BA2bQYGLR9NOPhMzx7js+qYDy6vhNkbApGKURjAw1FjY4pNA==" + "resolved" "https://registry.npmjs.org/gulp-connect/-/gulp-connect-5.7.0.tgz" + "version" "5.7.0" + dependencies: + "ansi-colors" "^2.0.5" + "connect" "^3.6.6" + "connect-livereload" "^0.6.0" + "fancy-log" "^1.3.2" + "map-stream" "^0.0.7" + "send" "^0.16.2" + "serve-index" "^1.9.1" + "serve-static" "^1.13.2" + "tiny-lr" "^1.1.1" + +"gulp-csscomb@^3.0.8": + "integrity" "sha1-3zSCSlgKTH0zUcHo67ateh1aibc=" + "resolved" "http://registry.npm.alibaba-inc.com/gulp-csscomb/download/gulp-csscomb-3.0.8.tgz" + "version" "3.0.8" + dependencies: + "csscomb" "^3.1.7" + "gulp-util" "^3.0.7" + "through2" "^2.0.1" + +"gulp-cssmin@^0.2.0": + "integrity" "sha1-h6s8ad05sg1dljVcZQStakR7HnI=" + "resolved" "http://registry.npm.alibaba-inc.com/gulp-cssmin/download/gulp-cssmin-0.2.0.tgz" + "version" "0.2.0" + dependencies: + "clean-css" "^3.1.9" + "filesize" "~2.0.0" + "graceful-fs" "~4.1.4" + "gulp-rename" "~1.1.0" + "gulp-util" "~2.2.0" + "map-stream" "0.0.4" + "temp-write" "~0.1.0" + +"gulp-jshint@^2.1.0": + "integrity" "sha1-v6+Sf3ju4mPFu6xfY+MU1Ep71B4=" + "resolved" "http://registry.npm.alibaba-inc.com/gulp-jshint/download/gulp-jshint-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "lodash" "^4.12.0" + "minimatch" "^3.0.3" + "plugin-error" "^0.1.2" + "rcloader" "^0.2.2" + "through2" "^2.0.0" + +"gulp-load-plugins@^1.6.0": + "integrity" "sha512-HlCODki0WHJvQIgAsJYOTkyo0c7TsDCetvfhrdGz9JYPL6A4mFRMGmKfoi6JmXjA/vvzg+fkT91c9FBh7rnkyg==" + "resolved" "https://registry.npmjs.org/gulp-load-plugins/-/gulp-load-plugins-1.6.0.tgz" + "version" "1.6.0" + dependencies: + "array-unique" "^0.2.1" + "fancy-log" "^1.2.0" + "findup-sync" "^3.0.0" + "gulplog" "^1.0.0" + "has-gulplog" "^0.1.0" + "micromatch" "^3.1.10" + "resolve" "^1.1.7" + +"gulp-rename@~1.1.0": + "integrity" "sha1-kwkKqvTThsB/IFOKaIjxXvunJ6E=" + "resolved" "http://registry.npm.alibaba-inc.com/gulp-rename/download/gulp-rename-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "map-stream" ">=0.0.4" + +"gulp-serv@0.0.1": + "integrity" "sha1-8bNhdWfusKUkW2Vw+dSjqBmcZ04=" + "resolved" "http://registry.npm.alibaba-inc.com/gulp-serv/download/gulp-serv-0.0.1.tgz" + "version" "0.0.1" + dependencies: + "connect" "^3.3.3" + "serve-static" "^1.7.1" + +"gulp-uglify@^3.0.0": + "integrity" "sha1-jT7uRmUhvqaxD9dd/3Kt+LfqLZc=" + "resolved" "http://registry.npm.taobao.org/gulp-uglify/download/gulp-uglify-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "gulplog" "^1.0.0" + "has-gulplog" "^0.1.0" + "lodash" "^4.13.1" + "make-error-cause" "^1.1.1" + "safe-buffer" "^5.1.2" + "through2" "^2.0.0" + "uglify-js" "^3.0.5" + "vinyl-sourcemaps-apply" "^0.2.0" + +"gulp-util@^3.0.0", "gulp-util@^3.0.7": + "integrity" "sha1-AFTh50RQLifATBh8PsxQXdVLu08=" + "resolved" "http://registry.npm.alibaba-inc.com/gulp-util/download/gulp-util-3.0.8.tgz" + "version" "3.0.8" + dependencies: + "array-differ" "^1.0.0" + "array-uniq" "^1.0.2" + "beeper" "^1.0.0" + "chalk" "^1.0.0" + "dateformat" "^2.0.0" + "fancy-log" "^1.1.0" + "gulplog" "^1.0.0" + "has-gulplog" "^0.1.0" + "lodash._reescape" "^3.0.0" + "lodash._reevaluate" "^3.0.0" + "lodash._reinterpolate" "^3.0.0" + "lodash.template" "^3.0.0" + "minimist" "^1.1.0" + "multipipe" "^0.1.2" + "object-assign" "^3.0.0" + "replace-ext" "0.0.1" + "through2" "^2.0.0" + "vinyl" "^0.5.0" + +"gulp-util@~2.2.0": + "integrity" "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=" + "resolved" "http://registry.npm.alibaba-inc.com/gulp-util/download/gulp-util-2.2.20.tgz" + "version" "2.2.20" + dependencies: + "chalk" "^0.5.0" + "dateformat" "^1.0.7-1.2.3" + "lodash._reinterpolate" "^2.4.1" + "lodash.template" "^2.4.1" + "minimist" "^0.2.0" + "multipipe" "^0.1.0" + "through2" "^0.5.0" + "vinyl" "^0.2.1" + +"gulp@^3.9.1": + "integrity" "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=" + "resolved" "https://registry.npm.taobao.org/gulp/download/gulp-3.9.1.tgz" + "version" "3.9.1" + dependencies: + "archy" "^1.0.0" + "chalk" "^1.0.0" + "deprecated" "^0.0.1" + "gulp-util" "^3.0.0" + "interpret" "^1.0.0" + "liftoff" "^2.1.0" + "minimist" "^1.1.0" + "orchestrator" "^0.3.0" + "pretty-hrtime" "^1.0.0" + "semver" "^4.1.0" + "tildify" "^1.0.0" + "v8flags" "^2.0.2" + "vinyl-fs" "^0.3.0" + +"gulplog@^1.0.0": + "integrity" "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=" + "resolved" "http://registry.npm.alibaba-inc.com/gulplog/download/gulplog-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "glogg" "^1.0.0" + +"has-ansi@^0.1.0": + "integrity" "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=" + "resolved" "http://registry.npm.alibaba-inc.com/has-ansi/download/has-ansi-0.1.0.tgz" + "version" "0.1.0" + dependencies: + "ansi-regex" "^0.2.0" + +"has-ansi@^2.0.0": + "integrity" "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=" + "resolved" "http://registry.npm.alibaba-inc.com/has-ansi/download/has-ansi-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "ansi-regex" "^2.0.0" + +"has-gulplog@^0.1.0": + "integrity" "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=" + "resolved" "http://registry.npm.alibaba-inc.com/has-gulplog/download/has-gulplog-0.1.0.tgz" + "version" "0.1.0" + dependencies: + "sparkles" "^1.0.0" + +"has-value@^0.3.1": + "integrity" "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=" + "resolved" "http://registry.npm.alibaba-inc.com/has-value/download/has-value-0.3.1.tgz" + "version" "0.3.1" + dependencies: + "get-value" "^2.0.3" + "has-values" "^0.1.4" + "isobject" "^2.0.0" + +"has-value@^1.0.0": + "integrity" "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=" + "resolved" "http://registry.npm.alibaba-inc.com/has-value/download/has-value-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "get-value" "^2.0.6" + "has-values" "^1.0.0" + "isobject" "^3.0.0" + +"has-values@^0.1.4": + "integrity" "sha1-bWHeldkd/Km5oCCJrThL/49it3E=" + "resolved" "http://registry.npm.alibaba-inc.com/has-values/download/has-values-0.1.4.tgz" + "version" "0.1.4" + +"has-values@^1.0.0": + "integrity" "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=" + "resolved" "http://registry.npm.alibaba-inc.com/has-values/download/has-values-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-number" "^3.0.0" + "kind-of" "^4.0.0" + +"homedir-polyfill@^1.0.1": + "integrity" "sha1-TCu8inWJmP7r9e1oWA921GdotLw=" + "resolved" "http://registry.npm.alibaba-inc.com/homedir-polyfill/download/homedir-polyfill-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "parse-passwd" "^1.0.0" + +"hosted-git-info@^2.1.4": + "integrity" "sha1-l/I2l3vW4SVAiTD/bePuxigewEc=" + "resolved" "http://registry.npm.alibaba-inc.com/hosted-git-info/download/hosted-git-info-2.7.1.tgz" + "version" "2.7.1" + +"htmlparser2@3.8.x": + "integrity" "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=" + "resolved" "http://registry.npm.alibaba-inc.com/htmlparser2/download/htmlparser2-3.8.3.tgz" + "version" "3.8.3" + dependencies: + "domelementtype" "1" + "domhandler" "2.3" + "domutils" "1.5" + "entities" "1.0" + "readable-stream" "1.1" + +"http-errors@~1.6.2": + "integrity" "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=" + "resolved" "http://registry.npm.alibaba-inc.com/http-errors/download/http-errors-1.6.3.tgz" + "version" "1.6.3" + dependencies: + "depd" "~1.1.2" + "inherits" "2.0.3" + "setprototypeof" "1.1.0" + "statuses" ">= 1.4.0 < 2" + +"http-parser-js@>=0.4.0": + "integrity" "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==" + "resolved" "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz" + "version" "0.5.0" + +"humanize@^0.0.9": + "integrity" "sha1-GZT/rs3+nEQe0r2sdFK3u0yeQaQ=" + "resolved" "http://registry.npm.alibaba-inc.com/humanize/download/humanize-0.0.9.tgz" + "version" "0.0.9" + +"indent-string@^2.1.0": + "integrity" "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=" + "resolved" "http://registry.npm.alibaba-inc.com/indent-string/download/indent-string-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "repeating" "^2.0.0" + +"inflight@^1.0.4": + "integrity" "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=" + "resolved" "http://registry.npm.alibaba-inc.com/inflight/download/inflight-1.0.6.tgz" + "version" "1.0.6" + dependencies: + "once" "^1.3.0" + "wrappy" "1" + +"inherits@^2.0.1", "inherits@~2.0.1", "inherits@~2.0.3", "inherits@2", "inherits@2.0.3": + "integrity" "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "resolved" "http://registry.npm.alibaba-inc.com/inherits/download/inherits-2.0.3.tgz" + "version" "2.0.3" + +"inherits@1": + "integrity" "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=" + "resolved" "https://registry.npm.taobao.org/inherits/download/inherits-1.0.2.tgz" + "version" "1.0.2" + +"ini@^1.3.4": + "integrity" "sha1-7uJfVtscnsYIXgwid4CD9Zar+Sc=" + "resolved" "http://registry.npm.alibaba-inc.com/ini/download/ini-1.3.5.tgz" + "version" "1.3.5" + +"interpret@^1.0.0": + "integrity" "sha1-1QYaYiS+WOgIOYX1AU2EQ1lXYpY=" + "resolved" "https://registry.npm.taobao.org/interpret/download/interpret-1.2.0.tgz" + "version" "1.2.0" + +"is-absolute@^1.0.0": + "integrity" "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=" + "resolved" "http://registry.npm.taobao.org/is-absolute/download/is-absolute-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-relative" "^1.0.0" + "is-windows" "^1.0.1" + +"is-accessor-descriptor@^0.1.6": + "integrity" "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=" + "resolved" "http://registry.npm.alibaba-inc.com/is-accessor-descriptor/download/is-accessor-descriptor-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "kind-of" "^3.0.2" + +"is-accessor-descriptor@^1.0.0": + "integrity" "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=" + "resolved" "http://registry.npm.alibaba-inc.com/is-accessor-descriptor/download/is-accessor-descriptor-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "kind-of" "^6.0.0" + +"is-arrayish@^0.2.1": + "integrity" "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + "resolved" "http://registry.npm.alibaba-inc.com/is-arrayish/download/is-arrayish-0.2.1.tgz" + "version" "0.2.1" + +"is-buffer@^1.1.5": + "integrity" "sha1-76ouqdqg16suoTqXsritUf776L4=" + "resolved" "http://registry.npm.alibaba-inc.com/is-buffer/download/is-buffer-1.1.6.tgz" + "version" "1.1.6" + +"is-builtin-module@^1.0.0": + "integrity" "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=" + "resolved" "http://registry.npm.alibaba-inc.com/is-builtin-module/download/is-builtin-module-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "builtin-modules" "^1.0.0" + +"is-data-descriptor@^0.1.4": + "integrity" "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=" + "resolved" "http://registry.npm.alibaba-inc.com/is-data-descriptor/download/is-data-descriptor-0.1.4.tgz" + "version" "0.1.4" + dependencies: + "kind-of" "^3.0.2" + +"is-data-descriptor@^1.0.0": + "integrity" "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=" + "resolved" "http://registry.npm.alibaba-inc.com/is-data-descriptor/download/is-data-descriptor-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "kind-of" "^6.0.0" + +"is-descriptor@^0.1.0": + "integrity" "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=" + "resolved" "http://registry.npm.alibaba-inc.com/is-descriptor/download/is-descriptor-0.1.6.tgz" + "version" "0.1.6" + dependencies: + "is-accessor-descriptor" "^0.1.6" + "is-data-descriptor" "^0.1.4" + "kind-of" "^5.0.0" + +"is-descriptor@^1.0.0": + "integrity" "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=" + "resolved" "http://registry.npm.alibaba-inc.com/is-descriptor/download/is-descriptor-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "is-accessor-descriptor" "^1.0.0" + "is-data-descriptor" "^1.0.0" + "kind-of" "^6.0.2" + +"is-descriptor@^1.0.2": + "integrity" "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=" + "resolved" "http://registry.npm.alibaba-inc.com/is-descriptor/download/is-descriptor-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "is-accessor-descriptor" "^1.0.0" + "is-data-descriptor" "^1.0.0" + "kind-of" "^6.0.2" + +"is-extendable@^0.1.0", "is-extendable@^0.1.1": + "integrity" "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + "resolved" "http://registry.npm.alibaba-inc.com/is-extendable/download/is-extendable-0.1.1.tgz" + "version" "0.1.1" + +"is-extendable@^1.0.1": + "integrity" "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=" + "resolved" "http://registry.npm.alibaba-inc.com/is-extendable/download/is-extendable-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "is-plain-object" "^2.0.4" + +"is-extglob@^2.1.0", "is-extglob@^2.1.1": + "integrity" "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "resolved" "http://registry.npm.alibaba-inc.com/is-extglob/download/is-extglob-2.1.1.tgz" + "version" "2.1.1" + +"is-finite@^1.0.0": + "integrity" "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=" + "resolved" "http://registry.npm.alibaba-inc.com/is-finite/download/is-finite-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "number-is-nan" "^1.0.0" + +"is-glob@^3.1.0": + "integrity" "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=" + "resolved" "https://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "is-extglob" "^2.1.0" + +"is-glob@^4.0.0": + "integrity" "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==" + "resolved" "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz" + "version" "4.0.1" + dependencies: + "is-extglob" "^2.1.1" + +"is-number@^3.0.0": + "integrity" "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=" + "resolved" "http://registry.npm.alibaba-inc.com/is-number/download/is-number-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "kind-of" "^3.0.2" + +"is-plain-object@^2.0.3", "is-plain-object@^2.0.4": + "integrity" "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=" + "resolved" "http://registry.npm.alibaba-inc.com/is-plain-object/download/is-plain-object-2.0.4.tgz" + "version" "2.0.4" + dependencies: + "isobject" "^3.0.1" + +"is-relative@^1.0.0": + "integrity" "sha1-obtpNc6MXboei5dUubLcwCDiJg0=" + "resolved" "http://registry.npm.taobao.org/is-relative/download/is-relative-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "is-unc-path" "^1.0.0" + +"is-unc-path@^1.0.0": + "integrity" "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=" + "resolved" "http://registry.npm.taobao.org/is-unc-path/download/is-unc-path-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "unc-path-regex" "^0.1.2" + +"is-utf8@^0.2.0": + "integrity" "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + "resolved" "http://registry.npm.alibaba-inc.com/is-utf8/download/is-utf8-0.2.1.tgz" + "version" "0.2.1" + +"is-windows@^1.0.1", "is-windows@^1.0.2": + "integrity" "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=" + "resolved" "http://registry.npm.alibaba-inc.com/is-windows/download/is-windows-1.0.2.tgz" + "version" "1.0.2" + +"is-wsl@^1.1.0": + "integrity" "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + "resolved" "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz" + "version" "1.1.0" + +"isarray@~1.0.0": + "integrity" "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "resolved" "http://registry.npm.alibaba-inc.com/isarray/download/isarray-1.0.0.tgz" + "version" "1.0.0" + +"isarray@0.0.1": + "integrity" "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "resolved" "http://registry.npm.alibaba-inc.com/isarray/download/isarray-0.0.1.tgz" + "version" "0.0.1" + +"isarray@1.0.0": + "integrity" "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "resolved" "http://registry.npm.alibaba-inc.com/isarray/download/isarray-1.0.0.tgz" + "version" "1.0.0" + +"isexe@^2.0.0": + "integrity" "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "resolved" "http://registry.npm.alibaba-inc.com/isexe/download/isexe-2.0.0.tgz" + "version" "2.0.0" + +"isobject@^2.0.0": + "integrity" "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=" + "resolved" "http://registry.npm.alibaba-inc.com/isobject/download/isobject-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "isarray" "1.0.0" + +"isobject@^3.0.0", "isobject@^3.0.1": + "integrity" "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + "resolved" "http://registry.npm.alibaba-inc.com/isobject/download/isobject-3.0.1.tgz" + "version" "3.0.1" + +"jquery@^3.0.0": + "integrity" "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw==" + "resolved" "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz" + "version" "3.4.1" + +"jshint@^2.10.2": + "integrity" "sha512-e7KZgCSXMJxznE/4WULzybCMNXNAd/bf5TSrvVEq78Q/K8ZwFpmBqQeDtNiHc3l49nV4E/+YeHU/JZjSUIrLAA==" + "resolved" "https://registry.npmjs.org/jshint/-/jshint-2.10.2.tgz" + "version" "2.10.2" + dependencies: + "cli" "~1.0.0" + "console-browserify" "1.1.x" + "exit" "0.1.x" + "htmlparser2" "3.8.x" + "lodash" "~4.17.11" + "minimatch" "~3.0.2" + "shelljs" "0.3.x" + "strip-json-comments" "1.0.x" + +"kind-of@^1.1.0": + "integrity" "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=" + "resolved" "http://registry.npm.alibaba-inc.com/kind-of/download/kind-of-1.1.0.tgz" + "version" "1.1.0" + +"kind-of@^3.0.2": + "integrity" "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=" + "resolved" "http://registry.npm.alibaba-inc.com/kind-of/download/kind-of-3.2.2.tgz" + "version" "3.2.2" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^3.0.3": + "integrity" "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=" + "resolved" "http://registry.npm.alibaba-inc.com/kind-of/download/kind-of-3.2.2.tgz" + "version" "3.2.2" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^3.2.0": + "integrity" "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=" + "resolved" "http://registry.npm.alibaba-inc.com/kind-of/download/kind-of-3.2.2.tgz" + "version" "3.2.2" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^4.0.0": + "integrity" "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=" + "resolved" "http://registry.npm.alibaba-inc.com/kind-of/download/kind-of-4.0.0.tgz" + "version" "4.0.0" + dependencies: + "is-buffer" "^1.1.5" + +"kind-of@^5.0.0": + "integrity" "sha1-cpyR4thXt6QZofmqZWhcTDP1hF0=" + "resolved" "http://registry.npm.alibaba-inc.com/kind-of/download/kind-of-5.1.0.tgz" + "version" "5.1.0" + +"kind-of@^6.0.0", "kind-of@^6.0.2": + "integrity" "sha1-ARRrNqYhjmTljzqNZt5df8b20FE=" + "resolved" "http://registry.npm.alibaba-inc.com/kind-of/download/kind-of-6.0.2.tgz" + "version" "6.0.2" + +"liftoff@^2.1.0": + "integrity" "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=" + "resolved" "https://registry.npm.taobao.org/liftoff/download/liftoff-2.5.0.tgz" + "version" "2.5.0" + dependencies: + "extend" "^3.0.0" + "findup-sync" "^2.0.0" + "fined" "^1.0.1" + "flagged-respawn" "^1.0.0" + "is-plain-object" "^2.0.4" + "object.map" "^1.0.0" + "rechoir" "^0.6.2" + "resolve" "^1.1.7" + +"livereload-js@^2.3.0": + "integrity" "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==" + "resolved" "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz" + "version" "2.4.0" + +"load-json-file@^1.0.0": + "integrity" "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=" + "resolved" "http://registry.npm.alibaba-inc.com/load-json-file/download/load-json-file-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "graceful-fs" "^4.1.2" + "parse-json" "^2.2.0" + "pify" "^2.0.0" + "pinkie-promise" "^2.0.0" + "strip-bom" "^2.0.0" + +"lodash._basecopy@^3.0.0": + "integrity" "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._basecopy/download/lodash._basecopy-3.0.1.tgz" + "version" "3.0.1" + +"lodash._basetostring@^3.0.0": + "integrity" "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._basetostring/download/lodash._basetostring-3.0.1.tgz" + "version" "3.0.1" + +"lodash._basevalues@^3.0.0": + "integrity" "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._basevalues/download/lodash._basevalues-3.0.0.tgz" + "version" "3.0.0" + +"lodash._escapehtmlchar@~2.4.1": + "integrity" "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._escapehtmlchar/download/lodash._escapehtmlchar-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "lodash._htmlescapes" "~2.4.1" + +"lodash._escapestringchar@~2.4.1": + "integrity" "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._escapestringchar/download/lodash._escapestringchar-2.4.1.tgz" + "version" "2.4.1" + +"lodash._getnative@^3.0.0": + "integrity" "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._getnative/download/lodash._getnative-3.9.1.tgz" + "version" "3.9.1" + +"lodash._htmlescapes@~2.4.1": + "integrity" "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._htmlescapes/download/lodash._htmlescapes-2.4.1.tgz" + "version" "2.4.1" + +"lodash._isiterateecall@^3.0.0": + "integrity" "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._isiterateecall/download/lodash._isiterateecall-3.0.9.tgz" + "version" "3.0.9" + +"lodash._isnative@~2.4.1": + "integrity" "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._isnative/download/lodash._isnative-2.4.1.tgz" + "version" "2.4.1" + +"lodash._objecttypes@~2.4.1": + "integrity" "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._objecttypes/download/lodash._objecttypes-2.4.1.tgz" + "version" "2.4.1" + +"lodash._reescape@^3.0.0": + "integrity" "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._reescape/download/lodash._reescape-3.0.0.tgz" + "version" "3.0.0" + +"lodash._reevaluate@^3.0.0": + "integrity" "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._reevaluate/download/lodash._reevaluate-3.0.0.tgz" + "version" "3.0.0" + +"lodash._reinterpolate@^2.4.1", "lodash._reinterpolate@~2.4.1": + "integrity" "sha1-TxInqlqHEfxjL1sHofRgequLMiI=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._reinterpolate/download/lodash._reinterpolate-2.4.1.tgz" + "version" "2.4.1" + +"lodash._reinterpolate@^3.0.0": + "integrity" "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._reinterpolate/download/lodash._reinterpolate-3.0.0.tgz" + "version" "3.0.0" + +"lodash._reunescapedhtml@~2.4.1": + "integrity" "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._reunescapedhtml/download/lodash._reunescapedhtml-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "lodash._htmlescapes" "~2.4.1" + "lodash.keys" "~2.4.1" + +"lodash._root@^3.0.0": + "integrity" "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._root/download/lodash._root-3.0.1.tgz" + "version" "3.0.1" + +"lodash._shimkeys@~2.4.1": + "integrity" "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash._shimkeys/download/lodash._shimkeys-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "lodash._objecttypes" "~2.4.1" + +"lodash.assign@^4.2.0": + "integrity" "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.assign/download/lodash.assign-4.2.0.tgz" + "version" "4.2.0" + +"lodash.clonedeep@^4.3.2": + "integrity" "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.clonedeep/download/lodash.clonedeep-4.5.0.tgz" + "version" "4.5.0" + +"lodash.defaults@~2.4.1": + "integrity" "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.defaults/download/lodash.defaults-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "lodash._objecttypes" "~2.4.1" + "lodash.keys" "~2.4.1" + +"lodash.escape@^3.0.0": + "integrity" "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.escape/download/lodash.escape-3.2.0.tgz" + "version" "3.2.0" + dependencies: + "lodash._root" "^3.0.0" + +"lodash.escape@~2.4.1": + "integrity" "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.escape/download/lodash.escape-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "lodash._escapehtmlchar" "~2.4.1" + "lodash._reunescapedhtml" "~2.4.1" + "lodash.keys" "~2.4.1" + +"lodash.isarguments@^3.0.0": + "integrity" "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.isarguments/download/lodash.isarguments-3.1.0.tgz" + "version" "3.1.0" + +"lodash.isarray@^3.0.0": + "integrity" "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.isarray/download/lodash.isarray-3.0.4.tgz" + "version" "3.0.4" + +"lodash.isobject@^3.0.2": + "integrity" "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.isobject/download/lodash.isobject-3.0.2.tgz" + "version" "3.0.2" + +"lodash.isobject@~2.4.1": + "integrity" "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.isobject/download/lodash.isobject-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "lodash._objecttypes" "~2.4.1" + +"lodash.keys@^3.0.0": + "integrity" "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.keys/download/lodash.keys-3.1.2.tgz" + "version" "3.1.2" + dependencies: + "lodash._getnative" "^3.0.0" + "lodash.isarguments" "^3.0.0" + "lodash.isarray" "^3.0.0" + +"lodash.keys@~2.4.1": + "integrity" "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.keys/download/lodash.keys-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "lodash._isnative" "~2.4.1" + "lodash._shimkeys" "~2.4.1" + "lodash.isobject" "~2.4.1" + +"lodash.merge@^4.6.0": + "integrity" "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "resolved" "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + "version" "4.6.2" + +"lodash.restparam@^3.0.0": + "integrity" "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.restparam/download/lodash.restparam-3.6.1.tgz" + "version" "3.6.1" + +"lodash.template@^2.4.1": + "integrity" "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.template/download/lodash.template-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "lodash._escapestringchar" "~2.4.1" + "lodash._reinterpolate" "~2.4.1" + "lodash.defaults" "~2.4.1" + "lodash.escape" "~2.4.1" + "lodash.keys" "~2.4.1" + "lodash.templatesettings" "~2.4.1" + "lodash.values" "~2.4.1" + +"lodash.template@^3.0.0": + "integrity" "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.template/download/lodash.template-3.6.2.tgz" + "version" "3.6.2" + dependencies: + "lodash._basecopy" "^3.0.0" + "lodash._basetostring" "^3.0.0" + "lodash._basevalues" "^3.0.0" + "lodash._isiterateecall" "^3.0.0" + "lodash._reinterpolate" "^3.0.0" + "lodash.escape" "^3.0.0" + "lodash.keys" "^3.0.0" + "lodash.restparam" "^3.0.0" + "lodash.templatesettings" "^3.0.0" + +"lodash.templatesettings@^3.0.0": + "integrity" "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.templatesettings/download/lodash.templatesettings-3.1.1.tgz" + "version" "3.1.1" + dependencies: + "lodash._reinterpolate" "^3.0.0" + "lodash.escape" "^3.0.0" + +"lodash.templatesettings@~2.4.1": + "integrity" "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.templatesettings/download/lodash.templatesettings-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "lodash._reinterpolate" "~2.4.1" + "lodash.escape" "~2.4.1" + +"lodash.values@~2.4.1": + "integrity" "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=" + "resolved" "http://registry.npm.alibaba-inc.com/lodash.values/download/lodash.values-2.4.1.tgz" + "version" "2.4.1" + dependencies: + "lodash.keys" "~2.4.1" + +"lodash@^4.12.0", "lodash@^4.13.1", "lodash@^4.17.10", "lodash@^4.17.15", "lodash@~4.17.11": + "integrity" "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + "resolved" "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz" + "version" "4.17.15" + +"lodash@~1.0.1": + "integrity" "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=" + "resolved" "https://registry.npm.taobao.org/lodash/download/lodash-1.0.2.tgz" + "version" "1.0.2" + +"loud-rejection@^1.0.0": + "integrity" "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=" + "resolved" "http://registry.npm.alibaba-inc.com/loud-rejection/download/loud-rejection-1.6.0.tgz" + "version" "1.6.0" + dependencies: + "currently-unhandled" "^0.4.1" + "signal-exit" "^3.0.0" + +"lru-cache@2": + "integrity" "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" + "resolved" "http://registry.npm.alibaba-inc.com/lru-cache/download/lru-cache-2.7.3.tgz" + "version" "2.7.3" + +"make-error-cause@^1.1.1": + "integrity" "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=" + "resolved" "http://registry.npm.taobao.org/make-error-cause/download/make-error-cause-1.2.2.tgz" + "version" "1.2.2" + dependencies: + "make-error" "^1.2.0" + +"make-error@^1.2.0": + "integrity" "sha1-7+ToH22yjK3WBccPKcgxtY73dsg=" + "resolved" "http://registry.npm.taobao.org/make-error/download/make-error-1.3.5.tgz" + "version" "1.3.5" + +"make-iterator@^1.0.0": + "integrity" "sha1-KbM/MSqo9UfEpeSQ9Wr87JkTOtY=" + "resolved" "http://registry.npm.taobao.org/make-iterator/download/make-iterator-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "kind-of" "^6.0.2" + +"map-cache@^0.2.0", "map-cache@^0.2.2": + "integrity" "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + "resolved" "http://registry.npm.alibaba-inc.com/map-cache/download/map-cache-0.2.2.tgz" + "version" "0.2.2" + +"map-obj@^1.0.0", "map-obj@^1.0.1": + "integrity" "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + "resolved" "http://registry.npm.alibaba-inc.com/map-obj/download/map-obj-1.0.1.tgz" + "version" "1.0.1" + +"map-stream@^0.0.7": + "integrity" "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=" + "resolved" "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz" + "version" "0.0.7" + +"map-stream@>=0.0.4": + "integrity" "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + "resolved" "http://registry.npm.alibaba-inc.com/map-stream/download/map-stream-0.1.0.tgz" + "version" "0.1.0" + +"map-stream@0.0.4": + "integrity" "sha1-XsbekCE+9sey65Nn6a3o2k79tos=" + "resolved" "http://registry.npm.alibaba-inc.com/map-stream/download/map-stream-0.0.4.tgz" + "version" "0.0.4" + +"map-visit@^1.0.0": + "integrity" "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=" + "resolved" "http://registry.npm.alibaba-inc.com/map-visit/download/map-visit-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "object-visit" "^1.0.0" + +"meow@^3.3.0": + "integrity" "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=" + "resolved" "http://registry.npm.alibaba-inc.com/meow/download/meow-3.7.0.tgz" + "version" "3.7.0" + dependencies: + "camelcase-keys" "^2.0.0" + "decamelize" "^1.1.2" + "loud-rejection" "^1.0.0" + "map-obj" "^1.0.1" + "minimist" "^1.1.3" + "normalize-package-data" "^2.3.4" + "object-assign" "^4.0.1" + "read-pkg-up" "^1.0.1" + "redent" "^1.0.0" + "trim-newlines" "^1.0.0" + +"micromatch@^3.0.4", "micromatch@^3.1.10": + "integrity" "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=" + "resolved" "http://registry.npm.alibaba-inc.com/micromatch/download/micromatch-3.1.10.tgz" + "version" "3.1.10" + dependencies: + "arr-diff" "^4.0.0" + "array-unique" "^0.3.2" + "braces" "^2.3.1" + "define-property" "^2.0.2" + "extend-shallow" "^3.0.2" + "extglob" "^2.0.4" + "fragment-cache" "^0.2.1" + "kind-of" "^6.0.2" + "nanomatch" "^1.2.9" + "object.pick" "^1.3.0" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.2" + +"microplugin@0.0.3": + "integrity" "sha1-H8Lhu3yeGegr2Eu6kTe75xJQ2M0=" + "resolved" "http://registry.npm.alibaba-inc.com/microplugin/download/microplugin-0.0.3.tgz" + "version" "0.0.3" + +"mime-db@~1.38.0": + "integrity" "sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==" + "resolved" "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz" + "version" "1.38.0" + +"mime-types@~2.1.17", "mime-types@~2.1.18": + "integrity" "sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==" + "resolved" "https://registry.npmjs.org/mime-types/-/mime-types-2.1.22.tgz" + "version" "2.1.22" + dependencies: + "mime-db" "~1.38.0" + +"mime@1.4.1": + "integrity" "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + "resolved" "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz" + "version" "1.4.1" + +"minimatch@^2.0.1": + "integrity" "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=" + "resolved" "https://registry.npm.taobao.org/minimatch/download/minimatch-2.0.10.tgz" + "version" "2.0.10" + dependencies: + "brace-expansion" "^1.0.0" + +"minimatch@^3.0.3": + "integrity" "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=" + "resolved" "http://registry.npm.alibaba-inc.com/minimatch/download/minimatch-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "brace-expansion" "^1.1.7" + +"minimatch@^3.0.4": + "integrity" "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "brace-expansion" "^1.1.7" + +"minimatch@~0.2.11": + "integrity" "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=" + "resolved" "http://registry.npm.alibaba-inc.com/minimatch/download/minimatch-0.2.14.tgz" + "version" "0.2.14" + dependencies: + "lru-cache" "2" + "sigmund" "~1.0.0" + +"minimatch@~3.0.2": + "integrity" "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==" + "resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz" + "version" "3.0.4" + dependencies: + "brace-expansion" "^1.1.7" + +"minimatch@0.2.12": + "integrity" "sha1-6oKgEqxmLH3fqhRPHBR+aUb12vs=" + "resolved" "http://registry.npm.alibaba-inc.com/minimatch/download/minimatch-0.2.12.tgz" + "version" "0.2.12" + dependencies: + "lru-cache" "2" + "sigmund" "~1.0.0" + +"minimist@^0.2.0": + "integrity" "sha1-Tf/lJdriuGTGbC4jxicdev3s784=" + "resolved" "http://registry.npm.alibaba-inc.com/minimist/download/minimist-0.2.0.tgz" + "version" "0.2.0" + +"minimist@^1.1.0": + "integrity" "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "resolved" "http://registry.npm.alibaba-inc.com/minimist/download/minimist-1.2.0.tgz" + "version" "1.2.0" + +"minimist@^1.1.3": + "integrity" "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "resolved" "http://registry.npm.alibaba-inc.com/minimist/download/minimist-1.2.0.tgz" + "version" "1.2.0" + +"minimist@~0.0.1": + "integrity" "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" + "resolved" "http://registry.npm.alibaba-inc.com/minimist/download/minimist-0.0.10.tgz" + "version" "0.0.10" + +"minimist@0.0.8": + "integrity" "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + "resolved" "https://registry.npm.taobao.org/minimist/download/minimist-0.0.8.tgz" + "version" "0.0.8" + +"mixin-deep@^1.2.0": + "integrity" "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==" + "resolved" "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz" + "version" "1.3.2" + dependencies: + "for-in" "^1.0.2" + "is-extendable" "^1.0.1" + +"mkdirp@^0.5.0": + "integrity" "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=" + "resolved" "https://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmkdirp%2Fdownload%2Fmkdirp-0.5.1.tgz" + "version" "0.5.1" + dependencies: + "minimist" "0.0.8" + +"moment@^2.12.0", "moment@^2.15.x", "moment@^2.18.1": + "integrity" "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + "resolved" "http://registry.npm.alibaba-inc.com/moment/download/moment-2.22.2.tgz" + "version" "2.22.2" + +"ms@^2.1.1": + "integrity" "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "resolved" "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz" + "version" "2.1.1" + +"ms@2.0.0": + "integrity" "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "resolved" "http://registry.npm.alibaba-inc.com/ms/download/ms-2.0.0.tgz" + "version" "2.0.0" + +"multipipe@^0.1.0", "multipipe@^0.1.2": + "integrity" "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=" + "resolved" "http://registry.npm.alibaba-inc.com/multipipe/download/multipipe-0.1.2.tgz" + "version" "0.1.2" + dependencies: + "duplexer2" "0.0.2" + +"nanomatch@^1.2.9": + "integrity" "sha1-uHqKpPwN6P5r6IiVs4mD/yZb0Rk=" + "resolved" "http://registry.npm.alibaba-inc.com/nanomatch/download/nanomatch-1.2.13.tgz" + "version" "1.2.13" + dependencies: + "arr-diff" "^4.0.0" + "array-unique" "^0.3.2" + "define-property" "^2.0.2" + "extend-shallow" "^3.0.2" + "fragment-cache" "^0.2.1" + "is-windows" "^1.0.2" + "kind-of" "^6.0.2" + "object.pick" "^1.3.0" + "regex-not" "^1.0.0" + "snapdragon" "^0.8.1" + "to-regex" "^3.0.1" + +"natives@^1.1.0": + "integrity" "sha1-pgO0pJirdxc2ErnqGs3sTZgPALs=" + "resolved" "https://registry.npm.taobao.org/natives/download/natives-1.1.6.tgz" + "version" "1.1.6" + +"negotiator@0.6.1": + "integrity" "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + "resolved" "http://registry.npm.alibaba-inc.com/negotiator/download/negotiator-0.6.1.tgz" + "version" "0.6.1" + +"ng-dialog@^0.6.6": + "integrity" "sha1-qtekfI5ByAf3AxPbEpbb6d4x2n0=" + "resolved" "http://registry.npm.alibaba-inc.com/ng-dialog/download/ng-dialog-0.6.6.tgz" + "version" "0.6.6" + +"ng-tags-input@~3.0.0": + "integrity" "sha1-X7BgMuAtOKrQLUQ+P1r8UeEn+ks=" + "resolved" "http://registry.npm.alibaba-inc.com/ng-tags-input/download/ng-tags-input-3.0.0.tgz" + "version" "3.0.0" + +"node-uuid@1.4.0": + "integrity" "sha1-B/myM3Vy/2J1x3Xh1IUT86RdemU=" + "resolved" "http://registry.npm.alibaba-inc.com/node-uuid/download/node-uuid-1.4.0.tgz" + "version" "1.4.0" + +"normalize-package-data@^2.3.2", "normalize-package-data@^2.3.4": + "integrity" "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=" + "resolved" "http://registry.npm.alibaba-inc.com/normalize-package-data/download/normalize-package-data-2.4.0.tgz" + "version" "2.4.0" + dependencies: + "hosted-git-info" "^2.1.4" + "is-builtin-module" "^1.0.0" + "semver" "2 || 3 || 4 || 5" + "validate-npm-package-license" "^3.0.1" + +"number-is-nan@^1.0.0": + "integrity" "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "resolved" "http://registry.npm.alibaba-inc.com/number-is-nan/download/number-is-nan-1.0.1.tgz" + "version" "1.0.1" + +"object-assign@^3.0.0": + "integrity" "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=" + "resolved" "http://registry.npm.alibaba-inc.com/object-assign/download/object-assign-3.0.0.tgz" + "version" "3.0.0" + +"object-assign@^4.0.1": + "integrity" "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "resolved" "http://registry.npm.alibaba-inc.com/object-assign/download/object-assign-4.1.1.tgz" + "version" "4.1.1" + +"object-assign@^4.1.0": + "integrity" "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "resolved" "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + "version" "4.1.1" + +"object-copy@^0.1.0": + "integrity" "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=" + "resolved" "http://registry.npm.alibaba-inc.com/object-copy/download/object-copy-0.1.0.tgz" + "version" "0.1.0" + dependencies: + "copy-descriptor" "^0.1.0" + "define-property" "^0.2.5" + "kind-of" "^3.0.3" + +"object-visit@^1.0.0": + "integrity" "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=" + "resolved" "http://registry.npm.alibaba-inc.com/object-visit/download/object-visit-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "isobject" "^3.0.0" + +"object.defaults@^1.1.0": + "integrity" "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=" + "resolved" "http://registry.npm.alibaba-inc.com/object.defaults/download/object.defaults-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "array-each" "^1.0.1" + "array-slice" "^1.0.0" + "for-own" "^1.0.0" + "isobject" "^3.0.0" + +"object.map@^1.0.0": + "integrity" "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=" + "resolved" "http://registry.npm.alibaba-inc.com/object.map/download/object.map-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "for-own" "^1.0.0" + "make-iterator" "^1.0.0" + +"object.pick@^1.2.0", "object.pick@^1.3.0": + "integrity" "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=" + "resolved" "http://registry.npm.alibaba-inc.com/object.pick/download/object.pick-1.3.0.tgz" + "version" "1.3.0" + dependencies: + "isobject" "^3.0.1" + +"oclazyload@^1.1.0": + "integrity" "sha1-qYBzIvGQggqBwCLy7xcB0DbYPoc=" + "resolved" "http://registry.npm.alibaba-inc.com/oclazyload/download/oclazyload-1.1.0.tgz" + "version" "1.1.0" + +"on-finished@~2.3.0": + "integrity" "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=" + "resolved" "http://registry.npm.alibaba-inc.com/on-finished/download/on-finished-2.3.0.tgz" + "version" "2.3.0" + dependencies: + "ee-first" "1.1.1" + +"once@^1.3.0", "once@~1.3.0": + "integrity" "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=" + "resolved" "http://registry.npm.alibaba-inc.com/once/download/once-1.3.3.tgz" + "version" "1.3.3" + dependencies: + "wrappy" "1" + +"open@^6.3.0": + "integrity" "sha512-6AHdrJxPvAXIowO/aIaeHZ8CeMdDf7qCyRNq8NwJpinmCdXhz+NZR7ie1Too94lpciCDsG+qHGO9Mt0svA4OqA==" + "resolved" "https://registry.npmjs.org/open/-/open-6.3.0.tgz" + "version" "6.3.0" + dependencies: + "is-wsl" "^1.1.0" + +"optimist@^0.6.1": + "integrity" "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=" + "resolved" "http://registry.npm.alibaba-inc.com/optimist/download/optimist-0.6.1.tgz" + "version" "0.6.1" + dependencies: + "minimist" "~0.0.1" + "wordwrap" "~0.0.2" + +"orchestrator@^0.3.0": + "integrity" "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=" + "resolved" "https://registry.npm.taobao.org/orchestrator/download/orchestrator-0.3.8.tgz" + "version" "0.3.8" + dependencies: + "end-of-stream" "~0.1.5" + "sequencify" "~0.0.7" + "stream-consume" "~0.1.0" + +"ordered-read-streams@^0.1.0": + "integrity" "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=" + "resolved" "https://registry.npm.taobao.org/ordered-read-streams/download/ordered-read-streams-0.1.0.tgz" + "version" "0.1.0" + +"os-homedir@^1.0.0": + "integrity" "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "resolved" "https://registry.npm.taobao.org/os-homedir/download/os-homedir-1.0.2.tgz" + "version" "1.0.2" + +"parse-filepath@^1.0.1": + "integrity" "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=" + "resolved" "http://registry.npm.alibaba-inc.com/parse-filepath/download/parse-filepath-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "is-absolute" "^1.0.0" + "map-cache" "^0.2.0" + "path-root" "^0.1.1" + +"parse-json@^2.2.0": + "integrity" "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=" + "resolved" "http://registry.npm.alibaba-inc.com/parse-json/download/parse-json-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "error-ex" "^1.2.0" + +"parse-passwd@^1.0.0": + "integrity" "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + "resolved" "http://registry.npm.alibaba-inc.com/parse-passwd/download/parse-passwd-1.0.0.tgz" + "version" "1.0.0" + +"parseurl@~1.3.2": + "integrity" "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + "resolved" "http://registry.npm.alibaba-inc.com/parseurl/download/parseurl-1.3.2.tgz" + "version" "1.3.2" + +"pascalcase@^0.1.1": + "integrity" "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" + "resolved" "http://registry.npm.alibaba-inc.com/pascalcase/download/pascalcase-0.1.1.tgz" + "version" "0.1.1" + +"path-exists@^2.0.0": + "integrity" "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=" + "resolved" "http://registry.npm.alibaba-inc.com/path-exists/download/path-exists-2.1.0.tgz" + "version" "2.1.0" + dependencies: + "pinkie-promise" "^2.0.0" + +"path-is-absolute@^1.0.0": + "integrity" "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "resolved" "http://registry.npm.alibaba-inc.com/path-is-absolute/download/path-is-absolute-1.0.1.tgz" + "version" "1.0.1" + +"path-parse@^1.0.5": + "integrity" "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=" + "resolved" "http://registry.npm.alibaba-inc.com/path-parse/download/path-parse-1.0.5.tgz" + "version" "1.0.5" + +"path-root-regex@^0.1.0": + "integrity" "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" + "resolved" "http://registry.npm.alibaba-inc.com/path-root-regex/download/path-root-regex-0.1.2.tgz" + "version" "0.1.2" + +"path-root@^0.1.1": + "integrity" "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=" + "resolved" "http://registry.npm.alibaba-inc.com/path-root/download/path-root-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "path-root-regex" "^0.1.0" + +"path-type@^1.0.0": + "integrity" "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=" + "resolved" "http://registry.npm.alibaba-inc.com/path-type/download/path-type-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "graceful-fs" "^4.1.2" + "pify" "^2.0.0" + "pinkie-promise" "^2.0.0" + +"pify@^2.0.0": + "integrity" "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "resolved" "http://registry.npm.alibaba-inc.com/pify/download/pify-2.3.0.tgz" + "version" "2.3.0" + +"pinkie-promise@^2.0.0": + "integrity" "sha1-ITXW36ejWMBprJsXh3YogihFD/o=" + "resolved" "http://registry.npm.alibaba-inc.com/pinkie-promise/download/pinkie-promise-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "pinkie" "^2.0.0" + +"pinkie@^2.0.0": + "integrity" "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + "resolved" "http://registry.npm.alibaba-inc.com/pinkie/download/pinkie-2.0.4.tgz" + "version" "2.0.4" + +"plugin-error@^0.1.2": + "integrity" "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=" + "resolved" "http://registry.npm.alibaba-inc.com/plugin-error/download/plugin-error-0.1.2.tgz" + "version" "0.1.2" + dependencies: + "ansi-cyan" "^0.1.1" + "ansi-red" "^0.1.1" + "arr-diff" "^1.0.1" + "arr-union" "^2.0.1" + "extend-shallow" "^1.1.2" + +"posix-character-classes@^0.1.0": + "integrity" "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" + "resolved" "http://registry.npm.alibaba-inc.com/posix-character-classes/download/posix-character-classes-0.1.1.tgz" + "version" "0.1.1" + +"pretty-hrtime@^1.0.0": + "integrity" "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" + "resolved" "http://registry.npm.alibaba-inc.com/pretty-hrtime/download/pretty-hrtime-1.0.3.tgz" + "version" "1.0.3" + +"process-nextick-args@^2.0.0", "process-nextick-args@~2.0.0": + "integrity" "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" + "resolved" "http://registry.npm.alibaba-inc.com/process-nextick-args/download/process-nextick-args-2.0.0.tgz" + "version" "2.0.0" + +"qs@^6.4.0": + "integrity" "sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA==" + "resolved" "https://registry.npmjs.org/qs/-/qs-6.6.0.tgz" + "version" "6.6.0" + +"range-parser@~1.2.0": + "integrity" "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + "resolved" "http://registry.npm.alibaba-inc.com/range-parser/download/range-parser-1.2.0.tgz" + "version" "1.2.0" + +"raw-body@~1.1.0": + "integrity" "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=" + "resolved" "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz" + "version" "1.1.7" + dependencies: + "bytes" "1" + "string_decoder" "0.10" + +"rcfinder@^0.1.6": + "integrity" "sha1-8+gPOH3fmugK4wpBADKWQuroERU=" + "resolved" "http://registry.npm.alibaba-inc.com/rcfinder/download/rcfinder-0.1.9.tgz" + "version" "0.1.9" + dependencies: + "lodash.clonedeep" "^4.3.2" + +"rcloader@^0.2.2": + "integrity" "sha1-WNIpi0YtC5v9ITPSoex0+9cFxxc=" + "resolved" "http://registry.npm.alibaba-inc.com/rcloader/download/rcloader-0.2.2.tgz" + "version" "0.2.2" + dependencies: + "lodash.assign" "^4.2.0" + "lodash.isobject" "^3.0.2" + "lodash.merge" "^4.6.0" + "rcfinder" "^0.1.6" + +"read-pkg-up@^1.0.1": + "integrity" "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=" + "resolved" "http://registry.npm.alibaba-inc.com/read-pkg-up/download/read-pkg-up-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "find-up" "^1.0.0" + "read-pkg" "^1.0.0" + +"read-pkg@^1.0.0": + "integrity" "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=" + "resolved" "http://registry.npm.alibaba-inc.com/read-pkg/download/read-pkg-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "load-json-file" "^1.0.0" + "normalize-package-data" "^2.3.2" + "path-type" "^1.0.0" + +"readable-stream@^2.1.5": + "integrity" "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=" + "resolved" "http://registry.npm.alibaba-inc.com/readable-stream/download/readable-stream-2.3.6.tgz" + "version" "2.3.6" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.3" + "isarray" "~1.0.0" + "process-nextick-args" "~2.0.0" + "safe-buffer" "~5.1.1" + "string_decoder" "~1.1.1" + "util-deprecate" "~1.0.1" + +"readable-stream@^2.3.5": + "integrity" "sha1-sRwn2IuP8fvgcGQ8+UsMea4bCq8=" + "resolved" "http://registry.npm.alibaba-inc.com/readable-stream/download/readable-stream-2.3.6.tgz" + "version" "2.3.6" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.3" + "isarray" "~1.0.0" + "process-nextick-args" "~2.0.0" + "safe-buffer" "~5.1.1" + "string_decoder" "~1.1.1" + "util-deprecate" "~1.0.1" + +"readable-stream@>=1.0.33-1 <1.1.0-0": + "integrity" "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=" + "resolved" "https://registry.npm.taobao.org/readable-stream/download/readable-stream-1.0.34.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freadable-stream%2Fdownload%2Freadable-stream-1.0.34.tgz" + "version" "1.0.34" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.1" + "isarray" "0.0.1" + "string_decoder" "~0.10.x" + +"readable-stream@~1.0.17": + "integrity" "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=" + "resolved" "http://registry.npm.alibaba-inc.com/readable-stream/download/readable-stream-1.0.34.tgz" + "version" "1.0.34" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.1" + "isarray" "0.0.1" + "string_decoder" "~0.10.x" + +"readable-stream@~1.1.9", "readable-stream@1.1": + "integrity" "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=" + "resolved" "http://registry.npm.alibaba-inc.com/readable-stream/download/readable-stream-1.1.14.tgz" + "version" "1.1.14" + dependencies: + "core-util-is" "~1.0.0" + "inherits" "~2.0.1" + "isarray" "0.0.1" + "string_decoder" "~0.10.x" + +"rechoir@^0.6.2": + "integrity" "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=" + "resolved" "http://registry.npm.alibaba-inc.com/rechoir/download/rechoir-0.6.2.tgz" + "version" "0.6.2" + dependencies: + "resolve" "^1.1.6" + +"redent@^1.0.0": + "integrity" "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=" + "resolved" "http://registry.npm.alibaba-inc.com/redent/download/redent-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "indent-string" "^2.1.0" + "strip-indent" "^1.0.1" + +"redeyed@~1.0.0": + "integrity" "sha1-6WwZO0DAgWsArshCaY5hGF5VSYo=" + "resolved" "http://registry.npm.alibaba-inc.com/redeyed/download/redeyed-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "esprima" "~3.0.0" + +"regex-not@^1.0.0", "regex-not@^1.0.2": + "integrity" "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=" + "resolved" "http://registry.npm.alibaba-inc.com/regex-not/download/regex-not-1.0.2.tgz" + "version" "1.0.2" + dependencies: + "extend-shallow" "^3.0.2" + "safe-regex" "^1.1.0" + +"remove-trailing-separator@^1.0.1": + "integrity" "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + "resolved" "http://registry.npm.alibaba-inc.com/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz" + "version" "1.1.0" + +"repeat-element@^1.1.2": + "integrity" "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + "resolved" "http://registry.npm.alibaba-inc.com/repeat-element/download/repeat-element-1.1.2.tgz" + "version" "1.1.2" + +"repeat-string@^1.6.1": + "integrity" "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "resolved" "http://registry.npm.alibaba-inc.com/repeat-string/download/repeat-string-1.6.1.tgz" + "version" "1.6.1" + +"repeating@^2.0.0": + "integrity" "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=" + "resolved" "http://registry.npm.alibaba-inc.com/repeating/download/repeating-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "is-finite" "^1.0.0" + +"replace-ext@^1.0.0": + "integrity" "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + "resolved" "http://registry.npm.alibaba-inc.com/replace-ext/download/replace-ext-1.0.0.tgz" + "version" "1.0.0" + +"replace-ext@0.0.1": + "integrity" "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + "resolved" "http://registry.npm.alibaba-inc.com/replace-ext/download/replace-ext-0.0.1.tgz" + "version" "0.0.1" + +"resolve-dir@^1.0.0", "resolve-dir@^1.0.1": + "integrity" "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=" + "resolved" "http://registry.npm.alibaba-inc.com/resolve-dir/download/resolve-dir-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "expand-tilde" "^2.0.0" + "global-modules" "^1.0.0" + +"resolve-url@^0.2.1": + "integrity" "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" + "resolved" "http://registry.npm.alibaba-inc.com/resolve-url/download/resolve-url-0.2.1.tgz" + "version" "0.2.1" + +"resolve@^1.1.6", "resolve@^1.1.7": + "integrity" "sha1-gvHsGaQjrB+9CAsLqwa6NuhKeiY=" + "resolved" "http://registry.npm.alibaba-inc.com/resolve/download/resolve-1.8.1.tgz" + "version" "1.8.1" + dependencies: + "path-parse" "^1.0.5" + +"ret@~0.1.10": + "integrity" "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=" + "resolved" "http://registry.npm.alibaba-inc.com/ret/download/ret-0.1.15.tgz" + "version" "0.1.15" + +"rimraf@^2.6.2": + "integrity" "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=" + "resolved" "http://registry.npm.alibaba-inc.com/rimraf/download/rimraf-2.6.2.tgz" + "version" "2.6.2" + dependencies: + "glob" "^7.0.5" + +"safe-buffer@^5.1.2", "safe-buffer@~5.1.0", "safe-buffer@~5.1.1": + "integrity" "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" + "resolved" "http://registry.npm.alibaba-inc.com/safe-buffer/download/safe-buffer-5.1.2.tgz" + "version" "5.1.2" + +"safe-json-parse@~1.0.1": + "integrity" "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=" + "resolved" "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz" + "version" "1.0.1" + +"safe-regex@^1.1.0": + "integrity" "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=" + "resolved" "http://registry.npm.alibaba-inc.com/safe-regex/download/safe-regex-1.1.0.tgz" + "version" "1.1.0" + dependencies: + "ret" "~0.1.10" + +"selectize@^0.12.1": + "integrity" "sha1-ws8Iy6pMsGxembtFKRnXGwgGkNY=" + "resolved" "http://registry.npm.alibaba-inc.com/selectize/download/selectize-0.12.6.tgz" + "version" "0.12.6" + dependencies: + "microplugin" "0.0.3" + "sifter" "^0.5.1" + +"semver@^4.1.0", "semver@2 || 3 || 4 || 5": + "integrity" "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + "resolved" "http://registry.npm.alibaba-inc.com/semver/download/semver-4.3.6.tgz" + "version" "4.3.6" + +"send@^0.16.2": + "integrity" "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==" + "resolved" "https://registry.npmjs.org/send/-/send-0.16.2.tgz" + "version" "0.16.2" + dependencies: + "debug" "2.6.9" + "depd" "~1.1.2" + "destroy" "~1.0.4" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "etag" "~1.8.1" + "fresh" "0.5.2" + "http-errors" "~1.6.2" + "mime" "1.4.1" + "ms" "2.0.0" + "on-finished" "~2.3.0" + "range-parser" "~1.2.0" + "statuses" "~1.4.0" + +"send@0.16.2": + "integrity" "sha1-bsyh4PjBVtFBWXVZhI32RzCmu8E=" + "resolved" "http://registry.npm.alibaba-inc.com/send/download/send-0.16.2.tgz" + "version" "0.16.2" + dependencies: + "debug" "2.6.9" + "depd" "~1.1.2" + "destroy" "~1.0.4" + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "etag" "~1.8.1" + "fresh" "0.5.2" + "http-errors" "~1.6.2" + "mime" "1.4.1" + "ms" "2.0.0" + "on-finished" "~2.3.0" + "range-parser" "~1.2.0" + "statuses" "~1.4.0" + +"sequencify@~0.0.7": + "integrity" "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=" + "resolved" "https://registry.npm.taobao.org/sequencify/download/sequencify-0.0.7.tgz" + "version" "0.0.7" + +"serve-index@^1.9.1": + "integrity" "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=" + "resolved" "http://registry.npm.alibaba-inc.com/serve-index/download/serve-index-1.9.1.tgz" + "version" "1.9.1" + dependencies: + "accepts" "~1.3.4" + "batch" "0.6.1" + "debug" "2.6.9" + "escape-html" "~1.0.3" + "http-errors" "~1.6.2" + "mime-types" "~2.1.17" + "parseurl" "~1.3.2" + +"serve-static@^1.13.2", "serve-static@^1.7.1": + "integrity" "sha1-CV6Ecv1bRiN9tQzkhqQ/S4bGzsE=" + "resolved" "http://registry.npm.alibaba-inc.com/serve-static/download/serve-static-1.13.2.tgz" + "version" "1.13.2" + dependencies: + "encodeurl" "~1.0.2" + "escape-html" "~1.0.3" + "parseurl" "~1.3.2" + "send" "0.16.2" + +"set-value@^2.0.0", "set-value@^2.0.1": + "integrity" "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==" + "resolved" "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz" + "version" "2.0.1" + dependencies: + "extend-shallow" "^2.0.1" + "is-extendable" "^0.1.1" + "is-plain-object" "^2.0.3" + "split-string" "^3.0.1" + +"setprototypeof@1.1.0": + "integrity" "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=" + "resolved" "http://registry.npm.alibaba-inc.com/setprototypeof/download/setprototypeof-1.1.0.tgz" + "version" "1.1.0" + +"shelljs@0.3.x": + "integrity" "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=" + "resolved" "http://registry.npm.alibaba-inc.com/shelljs/download/shelljs-0.3.0.tgz" + "version" "0.3.0" + +"sifter@^0.5.1": + "integrity" "sha1-XmUH/owRSyso2Qtr9OW2NuYR5Is=" + "resolved" "http://registry.npm.alibaba-inc.com/sifter/download/sifter-0.5.3.tgz" + "version" "0.5.3" + dependencies: + "async" "^2.6.0" + "cardinal" "^1.0.0" + "csv-parse" "^2.0.0" + "humanize" "^0.0.9" + "optimist" "^0.6.1" + +"sigmund@~1.0.0": + "integrity" "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + "resolved" "http://registry.npm.alibaba-inc.com/sigmund/download/sigmund-1.0.1.tgz" + "version" "1.0.1" + +"signal-exit@^3.0.0": + "integrity" "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + "resolved" "http://registry.npm.alibaba-inc.com/signal-exit/download/signal-exit-3.0.2.tgz" + "version" "3.0.2" + +"snapdragon-node@^2.0.1": + "integrity" "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=" + "resolved" "http://registry.npm.alibaba-inc.com/snapdragon-node/download/snapdragon-node-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "define-property" "^1.0.0" + "isobject" "^3.0.0" + "snapdragon-util" "^3.0.1" + +"snapdragon-util@^3.0.1": + "integrity" "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=" + "resolved" "http://registry.npm.alibaba-inc.com/snapdragon-util/download/snapdragon-util-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "kind-of" "^3.2.0" + +"snapdragon@^0.8.1": + "integrity" "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=" + "resolved" "http://registry.npm.alibaba-inc.com/snapdragon/download/snapdragon-0.8.2.tgz" + "version" "0.8.2" + dependencies: + "base" "^0.11.1" + "debug" "^2.2.0" + "define-property" "^0.2.5" + "extend-shallow" "^2.0.1" + "map-cache" "^0.2.2" + "source-map" "^0.5.6" + "source-map-resolve" "^0.5.0" + "use" "^3.1.0" + +"source-map-resolve@^0.5.0": + "integrity" "sha1-cuLMNAlVQ+Q7LGKyxMENSpBU8lk=" + "resolved" "http://registry.npm.alibaba-inc.com/source-map-resolve/download/source-map-resolve-0.5.2.tgz" + "version" "0.5.2" + dependencies: + "atob" "^2.1.1" + "decode-uri-component" "^0.2.0" + "resolve-url" "^0.2.1" + "source-map-url" "^0.4.0" + "urix" "^0.1.0" + +"source-map-url@^0.4.0": + "integrity" "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=" + "resolved" "http://registry.npm.alibaba-inc.com/source-map-url/download/source-map-url-0.4.0.tgz" + "version" "0.4.0" + +"source-map@^0.5.1": + "integrity" "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "resolved" "http://registry.npm.alibaba-inc.com/source-map/download/source-map-0.5.7.tgz" + "version" "0.5.7" + +"source-map@^0.5.6": + "integrity" "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + "resolved" "http://registry.npm.alibaba-inc.com/source-map/download/source-map-0.5.7.tgz" + "version" "0.5.7" + +"source-map@^0.6.1": + "integrity" "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" + "resolved" "http://registry.npm.alibaba-inc.com/source-map/download/source-map-0.6.1.tgz" + "version" "0.6.1" + +"source-map@^0.7.3": + "integrity" "sha1-UwL4FpAxc1ImVECS5kmB91F1A4M=" + "resolved" "http://registry.npm.alibaba-inc.com/source-map/download/source-map-0.7.3.tgz" + "version" "0.7.3" + +"source-map@~0.6.1": + "integrity" "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" + "resolved" "http://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz" + "version" "0.6.1" + +"source-map@0.4.x": + "integrity" "sha1-66T12pwNyZneaAMti092FzZSA2s=" + "resolved" "https://registry.npm.taobao.org/source-map/download/source-map-0.4.4.tgz" + "version" "0.4.4" + dependencies: + "amdefine" ">=0.0.4" + +"sparkles@^1.0.0": + "integrity" "sha1-AI22XtzmxQ7sDF4ijhlFBh3QQ3w=" + "resolved" "http://registry.npm.alibaba-inc.com/sparkles/download/sparkles-1.0.1.tgz" + "version" "1.0.1" + +"spdx-correct@^3.0.0": + "integrity" "sha1-BaW01xU6GVvJLDxCW2nzsqlSTII=" + "resolved" "http://registry.npm.alibaba-inc.com/spdx-correct/download/spdx-correct-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "spdx-expression-parse" "^3.0.0" + "spdx-license-ids" "^3.0.0" + +"spdx-exceptions@^2.1.0": + "integrity" "sha1-LHrmEFbHFKW5ubKyr30xHvXHj+k=" + "resolved" "http://registry.npm.alibaba-inc.com/spdx-exceptions/download/spdx-exceptions-2.1.0.tgz" + "version" "2.1.0" + +"spdx-expression-parse@^3.0.0": + "integrity" "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=" + "resolved" "http://registry.npm.alibaba-inc.com/spdx-expression-parse/download/spdx-expression-parse-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "spdx-exceptions" "^2.1.0" + "spdx-license-ids" "^3.0.0" + +"spdx-license-ids@^3.0.0": + "integrity" "sha1-enzShHDMbToc/m1miG9rxDDTrIc=" + "resolved" "http://registry.npm.alibaba-inc.com/spdx-license-ids/download/spdx-license-ids-3.0.0.tgz" + "version" "3.0.0" + +"split-string@^3.0.1", "split-string@^3.0.2": + "integrity" "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=" + "resolved" "http://registry.npm.alibaba-inc.com/split-string/download/split-string-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "extend-shallow" "^3.0.0" + +"static-extend@^0.1.1": + "integrity" "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=" + "resolved" "http://registry.npm.alibaba-inc.com/static-extend/download/static-extend-0.1.2.tgz" + "version" "0.1.2" + dependencies: + "define-property" "^0.2.5" + "object-copy" "^0.1.0" + +"statuses@>= 1.4.0 < 2": + "integrity" "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + "resolved" "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + "version" "1.5.0" + +"statuses@~1.3.1": + "integrity" "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + "resolved" "http://registry.npm.alibaba-inc.com/statuses/download/statuses-1.3.1.tgz" + "version" "1.3.1" + +"statuses@~1.4.0": + "integrity" "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + "resolved" "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz" + "version" "1.4.0" + +"stream-consume@~0.1.0": + "integrity" "sha1-0721mMK9CugrjKx6xQsRB6eZbEg=" + "resolved" "http://registry.npm.taobao.org/stream-consume/download/stream-consume-0.1.1.tgz" + "version" "0.1.1" + +"string_decoder@~0.10.x", "string_decoder@0.10": + "integrity" "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "resolved" "http://registry.npm.alibaba-inc.com/string_decoder/download/string_decoder-0.10.31.tgz" + "version" "0.10.31" + +"string_decoder@~1.1.1": + "integrity" "sha1-nPFhG6YmhdcDCunkujQUnDrwP8g=" + "resolved" "http://registry.npm.alibaba-inc.com/string_decoder/download/string_decoder-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "safe-buffer" "~5.1.0" + +"string-template@~0.2.1": + "integrity" "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" + "resolved" "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz" + "version" "0.2.1" + +"strip-ansi@^0.3.0": + "integrity" "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=" + "resolved" "http://registry.npm.alibaba-inc.com/strip-ansi/download/strip-ansi-0.3.0.tgz" + "version" "0.3.0" + dependencies: + "ansi-regex" "^0.2.1" + +"strip-ansi@^3.0.0": + "integrity" "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=" + "resolved" "http://registry.npm.alibaba-inc.com/strip-ansi/download/strip-ansi-3.0.1.tgz" + "version" "3.0.1" + dependencies: + "ansi-regex" "^2.0.0" + +"strip-bom@^1.0.0": + "integrity" "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=" + "resolved" "https://registry.npm.taobao.org/strip-bom/download/strip-bom-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "first-chunk-stream" "^1.0.0" + "is-utf8" "^0.2.0" + +"strip-bom@^2.0.0": + "integrity" "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" + "resolved" "http://registry.npm.alibaba-inc.com/strip-bom/download/strip-bom-2.0.0.tgz" + "version" "2.0.0" + dependencies: + "is-utf8" "^0.2.0" + +"strip-indent@^1.0.1": + "integrity" "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=" + "resolved" "http://registry.npm.alibaba-inc.com/strip-indent/download/strip-indent-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "get-stdin" "^4.0.1" + +"strip-json-comments@1.0.x": + "integrity" "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=" + "resolved" "http://registry.npm.alibaba-inc.com/strip-json-comments/download/strip-json-comments-1.0.4.tgz" + "version" "1.0.4" + +"supports-color@^0.2.0": + "integrity" "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=" + "resolved" "http://registry.npm.alibaba-inc.com/supports-color/download/supports-color-0.2.0.tgz" + "version" "0.2.0" + +"supports-color@^2.0.0": + "integrity" "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + "resolved" "http://registry.npm.alibaba-inc.com/supports-color/download/supports-color-2.0.0.tgz" + "version" "2.0.0" + +"temp-write@~0.1.0": + "integrity" "sha1-C2Rng43Xf79/YqDJPah5cy/9qTI=" + "resolved" "http://registry.npm.alibaba-inc.com/temp-write/download/temp-write-0.1.1.tgz" + "version" "0.1.1" + dependencies: + "graceful-fs" "~2.0.0" + "tempfile" "~0.1.2" + +"tempfile@~0.1.2": + "integrity" "sha1-fWtxAEcznTn4RzJ6BW2t8YMQMBA=" + "resolved" "http://registry.npm.alibaba-inc.com/tempfile/download/tempfile-0.1.3.tgz" + "version" "0.1.3" + dependencies: + "uuid" "~1.4.0" + +"through2@^0.5.0": + "integrity" "sha1-390BLrnHAOIyP9M084rGIqs3Lac=" + "resolved" "http://registry.npm.alibaba-inc.com/through2/download/through2-0.5.1.tgz" + "version" "0.5.1" + dependencies: + "readable-stream" "~1.0.17" + "xtend" "~3.0.0" + +"through2@^0.6.1": + "integrity" "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=" + "resolved" "https://registry.npm.taobao.org/through2/download/through2-0.6.5.tgz" + "version" "0.6.5" + dependencies: + "readable-stream" ">=1.0.33-1 <1.1.0-0" + "xtend" ">=4.0.0 <4.1.0-0" + +"through2@^2.0.0", "through2@^2.0.1", "through2@^2.0.3": + "integrity" "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=" + "resolved" "http://registry.npm.alibaba-inc.com/through2/download/through2-2.0.3.tgz" + "version" "2.0.3" + dependencies: + "readable-stream" "^2.1.5" + "xtend" "~4.0.1" + +"tildify@^1.0.0": + "integrity" "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=" + "resolved" "https://registry.npm.taobao.org/tildify/download/tildify-1.2.0.tgz" + "version" "1.2.0" + dependencies: + "os-homedir" "^1.0.0" + +"time-stamp@^1.0.0": + "integrity" "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=" + "resolved" "http://registry.npm.alibaba-inc.com/time-stamp/download/time-stamp-1.1.0.tgz" + "version" "1.1.0" + +"tiny-lr@^1.1.1": + "integrity" "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==" + "resolved" "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz" + "version" "1.1.1" + dependencies: + "body" "^5.1.0" + "debug" "^3.1.0" + "faye-websocket" "~0.10.0" + "livereload-js" "^2.3.0" + "object-assign" "^4.1.0" + "qs" "^6.4.0" + +"to-object-path@^0.3.0": + "integrity" "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=" + "resolved" "http://registry.npm.alibaba-inc.com/to-object-path/download/to-object-path-0.3.0.tgz" + "version" "0.3.0" + dependencies: + "kind-of" "^3.0.2" + +"to-regex-range@^2.1.0": + "integrity" "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=" + "resolved" "http://registry.npm.alibaba-inc.com/to-regex-range/download/to-regex-range-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "is-number" "^3.0.0" + "repeat-string" "^1.6.1" + +"to-regex@^3.0.1", "to-regex@^3.0.2": + "integrity" "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=" + "resolved" "http://registry.npm.alibaba-inc.com/to-regex/download/to-regex-3.0.2.tgz" + "version" "3.0.2" + dependencies: + "define-property" "^2.0.2" + "extend-shallow" "^3.0.2" + "regex-not" "^1.0.2" + "safe-regex" "^1.1.0" + +"trim-newlines@^1.0.0": + "integrity" "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + "resolved" "http://registry.npm.alibaba-inc.com/trim-newlines/download/trim-newlines-1.0.0.tgz" + "version" "1.0.0" + +"uglify-js@^3.0.5": + "integrity" "sha1-rwLxgMEgfXZDLkc+0koo9KeCuuM=" + "resolved" "http://registry.npm.taobao.org/uglify-js/download/uglify-js-3.4.9.tgz" + "version" "3.4.9" + dependencies: + "commander" "~2.17.1" + "source-map" "~0.6.1" + +"unc-path-regex@^0.1.2": + "integrity" "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + "resolved" "http://registry.npm.alibaba-inc.com/unc-path-regex/download/unc-path-regex-0.1.2.tgz" + "version" "0.1.2" + +"union-value@^1.0.0": + "integrity" "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==" + "resolved" "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "arr-union" "^3.1.0" + "get-value" "^2.0.6" + "is-extendable" "^0.1.1" + "set-value" "^2.0.1" + +"unique-stream@^1.0.0": + "integrity" "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=" + "resolved" "https://registry.npm.taobao.org/unique-stream/download/unique-stream-1.0.0.tgz" + "version" "1.0.0" + +"unpipe@~1.0.0": + "integrity" "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "resolved" "http://registry.npm.alibaba-inc.com/unpipe/download/unpipe-1.0.0.tgz" + "version" "1.0.0" + +"unset-value@^1.0.0": + "integrity" "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=" + "resolved" "http://registry.npm.alibaba-inc.com/unset-value/download/unset-value-1.0.0.tgz" + "version" "1.0.0" + dependencies: + "has-value" "^0.3.1" + "isobject" "^3.0.0" + +"urix@^0.1.0": + "integrity" "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=" + "resolved" "http://registry.npm.alibaba-inc.com/urix/download/urix-0.1.0.tgz" + "version" "0.1.0" + +"use@^3.1.0": + "integrity" "sha1-1QyMrHmhn7wg8pEfVuuXP04QBw8=" + "resolved" "http://registry.npm.alibaba-inc.com/use/download/use-3.1.1.tgz" + "version" "3.1.1" + +"user-home@^1.1.1": + "integrity" "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" + "resolved" "https://registry.npm.taobao.org/user-home/download/user-home-1.1.1.tgz" + "version" "1.1.1" + +"util-deprecate@~1.0.1": + "integrity" "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "resolved" "http://registry.npm.alibaba-inc.com/util-deprecate/download/util-deprecate-1.0.2.tgz" + "version" "1.0.2" + +"utils-merge@1.0.1": + "integrity" "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "resolved" "http://registry.npm.alibaba-inc.com/utils-merge/download/utils-merge-1.0.1.tgz" + "version" "1.0.1" + +"uuid@~1.4.0": + "integrity" "sha1-RTAZ9oaWam34PNxSROfJkOzDMvw=" + "resolved" "http://registry.npm.alibaba-inc.com/uuid/download/uuid-1.4.2.tgz" + "version" "1.4.2" + +"v8flags@^2.0.2": + "integrity" "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=" + "resolved" "https://registry.npm.taobao.org/v8flags/download/v8flags-2.1.1.tgz" + "version" "2.1.1" + dependencies: + "user-home" "^1.1.1" + +"validate-npm-package-license@^3.0.1": + "integrity" "sha1-gWQ7y+8b3+zUYjeT3EZIlIupgzg=" + "resolved" "http://registry.npm.alibaba-inc.com/validate-npm-package-license/download/validate-npm-package-license-3.0.3.tgz" + "version" "3.0.3" + dependencies: + "spdx-correct" "^3.0.0" + "spdx-expression-parse" "^3.0.0" + +"vinyl-fs@^0.3.0": + "integrity" "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=" + "resolved" "https://registry.npm.taobao.org/vinyl-fs/download/vinyl-fs-0.3.14.tgz" + "version" "0.3.14" + dependencies: + "defaults" "^1.0.0" + "glob-stream" "^3.1.5" + "glob-watcher" "^0.0.6" + "graceful-fs" "^3.0.0" + "mkdirp" "^0.5.0" + "strip-bom" "^1.0.0" + "through2" "^0.6.1" + "vinyl" "^0.4.0" + +"vinyl-sourcemaps-apply@^0.2.0": + "integrity" "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=" + "resolved" "http://registry.npm.alibaba-inc.com/vinyl-sourcemaps-apply/download/vinyl-sourcemaps-apply-0.2.1.tgz" + "version" "0.2.1" + dependencies: + "source-map" "^0.5.1" + +"vinyl@^0.2.1": + "integrity" "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=" + "resolved" "http://registry.npm.alibaba-inc.com/vinyl/download/vinyl-0.2.3.tgz" + "version" "0.2.3" + dependencies: + "clone-stats" "~0.0.1" + +"vinyl@^0.4.0": + "integrity" "sha1-LzVsh6VQolVGHza76ypbqL94SEc=" + "resolved" "https://registry.npm.taobao.org/vinyl/download/vinyl-0.4.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvinyl%2Fdownload%2Fvinyl-0.4.6.tgz" + "version" "0.4.6" + dependencies: + "clone" "^0.2.0" + "clone-stats" "^0.0.1" + +"vinyl@^0.5.0": + "integrity" "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=" + "resolved" "http://registry.npm.alibaba-inc.com/vinyl/download/vinyl-0.5.3.tgz" + "version" "0.5.3" + dependencies: + "clone" "^1.0.0" + "clone-stats" "^0.0.1" + "replace-ext" "0.0.1" + +"vinyl@^2.0.0": + "integrity" "sha1-2FsH2pbkWNJbL/4Z/s6fLKoT7YY=" + "resolved" "http://registry.npm.alibaba-inc.com/vinyl/download/vinyl-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "clone" "^2.1.1" + "clone-buffer" "^1.0.0" + "clone-stats" "^1.0.0" + "cloneable-readable" "^1.0.0" + "remove-trailing-separator" "^1.0.1" + "replace-ext" "^1.0.0" + +"vinyl@^2.1.0": + "integrity" "sha1-2FsH2pbkWNJbL/4Z/s6fLKoT7YY=" + "resolved" "http://registry.npm.alibaba-inc.com/vinyl/download/vinyl-2.2.0.tgz" + "version" "2.2.0" + dependencies: + "clone" "^2.1.1" + "clone-buffer" "^1.0.0" + "clone-stats" "^1.0.0" + "cloneable-readable" "^1.0.0" + "remove-trailing-separator" "^1.0.1" + "replace-ext" "^1.0.0" + +"vow-fs@0.3.2": + "integrity" "sha1-6isDTYXh24wnfrLpqG0cFfXTjno=" + "resolved" "http://registry.npm.alibaba-inc.com/vow-fs/download/vow-fs-0.3.2.tgz" + "version" "0.3.2" + dependencies: + "glob" "3.2.8" + "node-uuid" "1.4.0" + "vow" "0.4.4" + "vow-queue" "0.3.1" + +"vow-queue@0.3.1": + "integrity" "sha1-WYxRoVsKgabV/AX0dhzrRi3h6Gg=" + "resolved" "http://registry.npm.alibaba-inc.com/vow-queue/download/vow-queue-0.3.1.tgz" + "version" "0.3.1" + dependencies: + "vow" "~0.4.0" + +"vow@~0.4.0", "vow@0.4.4": + "integrity" "sha1-yf5GCRKdf1qmIVCOvmS1HJW8e5g=" + "resolved" "http://registry.npm.alibaba-inc.com/vow/download/vow-0.4.4.tgz" + "version" "0.4.4" + +"websocket-driver@>=0.5.1": + "integrity" "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=" + "resolved" "http://registry.npm.alibaba-inc.com/websocket-driver/download/websocket-driver-0.7.0.tgz" + "version" "0.7.0" + dependencies: + "http-parser-js" ">=0.4.0" + "websocket-extensions" ">=0.1.1" + +"websocket-extensions@>=0.1.1": + "integrity" "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==" + "resolved" "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz" + "version" "0.1.3" + +"which@^1.2.14": + "integrity" "sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo=" + "resolved" "http://registry.npm.alibaba-inc.com/which/download/which-1.3.1.tgz" + "version" "1.3.1" + dependencies: + "isexe" "^2.0.0" + +"wordwrap@~0.0.2": + "integrity" "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + "resolved" "http://registry.npm.alibaba-inc.com/wordwrap/download/wordwrap-0.0.3.tgz" + "version" "0.0.3" + +"wrappy@1": + "integrity" "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "resolved" "http://registry.npm.alibaba-inc.com/wrappy/download/wrappy-1.0.2.tgz" + "version" "1.0.2" + +"xtend@>=4.0.0 <4.1.0-0", "xtend@~4.0.0", "xtend@~4.0.1": + "integrity" "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "resolved" "http://registry.npm.alibaba-inc.com/xtend/download/xtend-4.0.1.tgz" + "version" "4.0.1" + +"xtend@~3.0.0": + "integrity" "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=" + "resolved" "http://registry.npm.alibaba-inc.com/xtend/download/xtend-3.0.0.tgz" + "version" "3.0.0" diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysConfigController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysConfigController.java index 29cf1053..7672d4d2 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysConfigController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysConfigController.java @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.core.constant.UserConstants; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDeptController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDeptController.java index 45a277b7..b79d2513 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDeptController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDeptController.java @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.core.constant.UserConstants; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictDataController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictDataController.java index 53acf3c2..c81c89f7 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictDataController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictDataController.java @@ -4,6 +4,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletResponse; + +import com.ruoyi.common.security.utils.SecurityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; @@ -14,7 +16,6 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.core.utils.SecurityUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.web.controller.BaseController; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictTypeController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictTypeController.java index 8ef58ef4..5c9be5df 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictTypeController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysDictTypeController.java @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.core.constant.UserConstants; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMenuController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMenuController.java index 92ba93ce..a7337f51 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMenuController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysMenuController.java @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.core.constant.Constants; import com.ruoyi.common.core.constant.UserConstants; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysNoticeController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysNoticeController.java index 7773c009..619e5f9c 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysNoticeController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysNoticeController.java @@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.TableDataInfo; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysPostController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysPostController.java index 6da7a1da..e97ec855 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysPostController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysPostController.java @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.core.constant.UserConstants; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java index c8334da3..6a9aa3d4 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java @@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.ruoyi.common.core.domain.R; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.ServletUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.web.controller.BaseController; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java index 08ad193f..98cd5986 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysRoleController.java @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.core.constant.UserConstants; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.web.controller.BaseController; import com.ruoyi.common.core.web.domain.AjaxResult; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java index 3265e176..fadf0ec5 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysUserController.java @@ -5,7 +5,11 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; + +import com.ruoyi.common.security.utils.SecurityUtils; +import com.ruoyi.system.api.model.UserInfo; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -18,7 +22,6 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.domain.R; -import com.ruoyi.common.core.utils.SecurityUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.poi.ExcelUtil; import com.ruoyi.common.core.web.controller.BaseController; @@ -101,7 +104,7 @@ public class SysUserController extends BaseController * 获取当前用户信息 */ @GetMapping("/info/{username}") - public R info(@PathVariable("username") String username) + public R info(@PathVariable("username") String username) { SysUser sysUser = userService.selectUserByUserName(username); if (StringUtils.isNull(sysUser)) @@ -112,7 +115,7 @@ public class SysUserController extends BaseController Set roles = permissionService.getRolePermission(sysUser.getUserId()); // 权限集合 Set permissions = permissionService.getMenuPermission(sysUser.getUserId()); - LoginUser sysUserVo = new LoginUser(); + UserInfo sysUserVo = new UserInfo(); sysUserVo.setSysUser(sysUser); sysUserVo.setRoles(roles); sysUserVo.setPermissions(permissions); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java index 74c74518..de169bf8 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java @@ -11,7 +11,7 @@ import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.ruoyi.common.core.constant.UserConstants; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.system.api.domain.SysRole; import com.ruoyi.system.api.domain.SysUser; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index bcae0580..33815865 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -9,7 +9,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.ruoyi.common.core.constant.UserConstants; import com.ruoyi.common.core.exception.CustomException; -import com.ruoyi.common.core.utils.SecurityUtils; +import com.ruoyi.common.security.utils.SecurityUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.datascope.annotation.DataScope; import com.ruoyi.system.api.domain.SysRole; diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml index 554d7979..c2383424 100644 --- a/ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/ruoyi-system/src/main/resources/bootstrap.yml @@ -14,11 +14,12 @@ spring: nacos: discovery: # 服务注册地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 config: # 配置中心地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 # 配置文件格式 file-extension: yml # 共享配置 - shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/ruoyi-ui/src/api/login.js b/ruoyi-ui/src/api/login.js index 8b396863..26267277 100644 --- a/ruoyi-ui/src/api/login.js +++ b/ruoyi-ui/src/api/login.js @@ -1,46 +1,90 @@ -import request from '@/utils/request' - -const client_id = 'web' -const client_secret = '123456' -const scope = 'server' - -// 登录方法 -export function login(username, password, code, uuid) { - return request({ - url: '/auth/login', - method: 'post', - data: { username, password, code, uuid } - }) -} - -// 刷新方法 -export function refreshToken() { - return request({ - url: '/auth/refresh', - method: 'post' - }) -} - -// 获取用户详细信息 -export function getInfo() { - return request({ - url: '/system/user/getInfo', - method: 'get' - }) -} - -// 退出方法 -export function logout() { - return request({ - url: '/auth/logout', - method: 'delete' - }) -} - -// 获取验证码 -export function getCodeImg() { - return request({ - url: '/code', - method: 'get' - }) -} \ No newline at end of file +import request from '@/utils/request' + +const client_id = 'web' +const client_secret = '123456' +const scope = 'server' + +// // 登录方法 +// export function login(username, password, code, uuid) { +// return request({ +// url: '/auth/login', +// method: 'post', +// data: { username, password, code, uuid } +// }) +// } +// +// // 刷新方法 +// export function refreshToken() { +// return request({ +// url: '/auth/refresh', +// method: 'post' +// }) +// } +// +// // 获取用户详细信息 +// export function getInfo() { +// return request({ +// url: '/system/user/getInfo', +// method: 'get' +// }) +// } +// +// // 退出方法 +// export function logout() { +// return request({ +// url: '/auth/logout', +// method: 'delete' +// }) +// } +// +// // 获取验证码 +// export function getCodeImg() { +// return request({ +// url: '/code', +// method: 'get' +// }) +// } + +// 登录方法 +export function login(username, password, code, uuid) { + const grant_type = 'password' + return request({ + url: '/auth/oauth/token', + method: 'post', + params: { username, password, code, uuid, client_id, client_secret, grant_type, scope } + }) +} + +// 刷新方法 +export function refreshToken(refresh_token) { + const grant_type = 'refresh_token' + return request({ + url: '/auth/oauth/token', + method: 'post', + params: { client_id, client_secret, grant_type, scope, refresh_token } + }) +} + +// 获取用户详细信息 +export function getInfo() { + return request({ + url: '/system/user/getInfo', + method: 'get' + }) +} + +// 退出方法 +export function logout() { + return request({ + url: '/auth/token/logout', + method: 'delete' + }) +} + +// 获取验证码 +export function getCodeImg() { + return request({ + url: '/code', + method: 'get' + }) +} diff --git a/ruoyi-ui/src/store/modules/user.js b/ruoyi-ui/src/store/modules/user.js index 5e2349fd..21ab0042 100644 --- a/ruoyi-ui/src/store/modules/user.js +++ b/ruoyi-ui/src/store/modules/user.js @@ -1,115 +1,156 @@ -import { login, logout, getInfo, refreshToken } from '@/api/login' -import { getToken, setToken, setExpiresIn, removeToken } from '@/utils/auth' - -const user = { - state: { - token: getToken(), - name: '', - avatar: '', - roles: [], - permissions: [] - }, - - mutations: { - SET_TOKEN: (state, token) => { - state.token = token - }, - SET_EXPIRES_IN: (state, time) => { - state.expires_in = time - }, - SET_NAME: (state, name) => { - state.name = name - }, - SET_AVATAR: (state, avatar) => { - state.avatar = avatar - }, - SET_ROLES: (state, roles) => { - state.roles = roles - }, - SET_PERMISSIONS: (state, permissions) => { - state.permissions = permissions - } - }, - - actions: { - // 登录 - Login({ commit }, userInfo) { - const username = userInfo.username.trim() - const password = userInfo.password - const code = userInfo.code - const uuid = userInfo.uuid - return new Promise((resolve, reject) => { - login(username, password, code, uuid).then(res => { - let data = res.data - setToken(data.access_token) - commit('SET_TOKEN', data.access_token) - setExpiresIn(data.expires_in) - commit('SET_EXPIRES_IN', data.expires_in) - resolve() - }).catch(error => { - reject(error) - }) - }) - }, - - // 获取用户信息 - GetInfo({ commit, state }) { - return new Promise((resolve, reject) => { - getInfo(state.token).then(res => { - const user = res.user - const avatar = user.avatar == "" ? require("@/assets/images/profile.jpg") : user.avatar; - if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 - commit('SET_ROLES', res.roles) - commit('SET_PERMISSIONS', res.permissions) - } else { - commit('SET_ROLES', ['ROLE_DEFAULT']) - } - commit('SET_NAME', user.userName) - commit('SET_AVATAR', avatar) - resolve(res) - }).catch(error => { - reject(error) - }) - }) - }, - - // 刷新token - RefreshToken({commit, state}) { - return new Promise((resolve, reject) => { - refreshToken(state.token).then(res => { - setExpiresIn(res.data) - commit('SET_EXPIRES_IN', res.data) - resolve() - }).catch(error => { - reject(error) - }) - }) - }, - - // 退出系统 - LogOut({ commit, state }) { - return new Promise((resolve, reject) => { - logout(state.token).then(() => { - commit('SET_TOKEN', '') - commit('SET_ROLES', []) - commit('SET_PERMISSIONS', []) - removeToken() - resolve() - }).catch(error => { - reject(error) - }) - }) - }, - - // 前端 登出 - FedLogOut({ commit }) { - return new Promise(resolve => { - commit('SET_TOKEN', '') - removeToken() - resolve() - }) - } - } -} - -export default user +import { login, logout, getInfo, refreshToken } from '@/api/login' +import { getToken, setToken,getRefreshToken, setRefreshToken, setExpiresIn, removeToken } from '@/utils/auth' + +const user = { + state: { + token: getToken(), + refresh_token: getRefreshToken(), + name: '', + avatar: '', + roles: [], + permissions: [] + }, + + mutations: { + SET_TOKEN: (state, token) => { + state.token = token + }, + SET_EXPIRES_IN: (state, time) => { + state.expires_in = time + }, + SET_REFRESH_TOKEN: (state, token) => { + state.refresh_token = token + }, + SET_NAME: (state, name) => { + state.name = name + }, + SET_AVATAR: (state, avatar) => { + state.avatar = avatar + }, + SET_ROLES: (state, roles) => { + state.roles = roles + }, + SET_PERMISSIONS: (state, permissions) => { + state.permissions = permissions + } + }, + + actions: { + // // 登录 + // Login({ commit }, userInfo) { + // const username = userInfo.username.trim() + // const password = userInfo.password + // const code = userInfo.code + // const uuid = userInfo.uuid + // return new Promise((resolve, reject) => { + // login(username, password, code, uuid).then(res => { + // let data = res.data + // setToken(data.access_token) + // commit('SET_TOKEN', data.access_token) + // setExpiresIn(data.expires_in) + // commit('SET_EXPIRES_IN', data.expires_in) + // resolve() + // }).catch(error => { + // reject(error) + // }) + // }) + // }, + // 登录 + Login({ commit }, userInfo) { + const username = userInfo.username.trim() + const password = userInfo.password + const code = userInfo.code + const uuid = userInfo.uuid + return new Promise((resolve, reject) => { + login(username, password, code, uuid).then(res => { + setToken(res.access_token) + commit('SET_TOKEN', res.access_token) + setRefreshToken(res.refresh_token) + commit('SET_REFRESH_TOKEN', res.refresh_token) + setExpiresIn(res.expires_in) + commit('SET_EXPIRES_IN', res.expires_in) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 获取用户信息 + GetInfo({ commit, state }) { + return new Promise((resolve, reject) => { + getInfo(state.token).then(res => { + const user = res.user + const avatar = user.avatar == "" ? require("@/assets/images/profile.jpg") : user.avatar; + if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 + commit('SET_ROLES', res.roles) + commit('SET_PERMISSIONS', res.permissions) + } else { + commit('SET_ROLES', ['ROLE_DEFAULT']) + } + commit('SET_NAME', user.userName) + commit('SET_AVATAR', avatar) + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + + // // 刷新token + // RefreshToken({commit, state}) { + // return new Promise((resolve, reject) => { + // refreshToken(state.token).then(res => { + // setExpiresIn(res.data) + // commit('SET_EXPIRES_IN', res.data) + // resolve() + // }).catch(error => { + // reject(error) + // }) + // }) + // }, + + // 刷新token + RefreshToken({commit, state}) { + return new Promise((resolve, reject) => { + refreshToken(state.refresh_token).then(res => { + setToken(res.access_token) + commit('SET_TOKEN', res.access_token) + setRefreshToken(res.refresh_token) + commit('SET_REFRESH_TOKEN', res.refresh_token) + setExpiresIn(res.expires_in) + commit('SET_EXPIRES_IN', res.expires_in) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 退出系统 + LogOut({ commit, state }) { + return new Promise((resolve, reject) => { + logout(state.token).then(() => { + commit('SET_TOKEN', '') + commit('SET_ROLES', []) + commit('SET_PERMISSIONS', []) + removeToken() + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 前端 登出 + FedLogOut({ commit }) { + return new Promise(resolve => { + commit('SET_TOKEN', '') + removeToken() + resolve() + }) + } + } +} + +export default user diff --git a/ruoyi-ui/src/utils/auth.js b/ruoyi-ui/src/utils/auth.js index 7fa75596..3931c655 100644 --- a/ruoyi-ui/src/utils/auth.js +++ b/ruoyi-ui/src/utils/auth.js @@ -1,29 +1,41 @@ -import Cookies from 'js-cookie' - -const TokenKey = 'Admin-Token' - -const ExpiresInKey = 'Admin-Expires-In' - -export function getToken() { - return Cookies.get(TokenKey) -} - -export function setToken(token) { - return Cookies.set(TokenKey, token) -} - -export function removeToken() { - return Cookies.remove(TokenKey) -} - -export function getExpiresIn() { - return Cookies.get(ExpiresInKey) || -1 -} - -export function setExpiresIn(time) { - return Cookies.set(ExpiresInKey, time) -} - -export function removeExpiresIn() { - return Cookies.remove(ExpiresInKey) -} +import Cookies from 'js-cookie' + +const TokenKey = 'Admin-Token' +const RefreshTokenKey = 'Admin-Refresh-Token' +const ExpiresInKey = 'Admin-Expires-In' + +export function getToken() { + return Cookies.get(TokenKey) +} + +export function setToken(token) { + return Cookies.set(TokenKey, token) +} + +export function removeToken() { + return Cookies.remove(TokenKey) +} + +export function getRefreshToken() { + return Cookies.get(RefreshTokenKey) || `` +} + +export function setRefreshToken(token) { + return Cookies.set(RefreshTokenKey, token) +} + +export function removeRefreshToken() { + return Cookies.remove(RefreshTokenKey) +} + +export function getExpiresIn() { + return Cookies.get(ExpiresInKey) || -1 +} + +export function setExpiresIn(time) { + return Cookies.set(ExpiresInKey, time) +} + +export function removeExpiresIn() { + return Cookies.remove(ExpiresInKey) +} diff --git a/ruoyi-ui/src/views/login.vue b/ruoyi-ui/src/views/login.vue index 8ec1aca4..bcf7e55e 100644 --- a/ruoyi-ui/src/views/login.vue +++ b/ruoyi-ui/src/views/login.vue @@ -1,203 +1,204 @@ - - - - - + + + + + diff --git a/ruoyi-visual/ruoyi-monitor/src/main/resources/bootstrap.yml b/ruoyi-visual/ruoyi-monitor/src/main/resources/bootstrap.yml index ec9acb3a..d493ed7d 100644 --- a/ruoyi-visual/ruoyi-monitor/src/main/resources/bootstrap.yml +++ b/ruoyi-visual/ruoyi-monitor/src/main/resources/bootstrap.yml @@ -14,11 +14,12 @@ spring: nacos: discovery: # 服务注册地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 config: # 配置中心地址 - server-addr: 127.0.0.1:8848 + server-addr: 175.25.50.135:8848 # 配置文件格式 file-extension: yml # 共享配置 - shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} + shared-configs: + - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} diff --git a/sql/ry_config_20210128.sql b/sql/ry_config_20210128.sql index 8ffb1230..6909255a 100644 --- a/sql/ry_config_20210128.sql +++ b/sql/ry_config_20210128.sql @@ -36,7 +36,7 @@ insert into config_info(id, data_id, group_id, content, md5, gmt_create, gmt_mod (2,'ruoyi-gateway-dev.yml','DEFAULT_GROUP','spring:\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n cloud:\r\n gateway:\r\n discovery:\r\n locator:\r\n lowerCaseServiceId: true\r\n enabled: true\r\n routes:\r\n # 认证中心\r\n - id: ruoyi-auth\r\n uri: lb://ruoyi-auth\r\n predicates:\r\n - Path=/auth/**\r\n filters:\r\n # 验证码处理\r\n - CacheRequestFilter\r\n - ValidateCodeFilter\r\n - StripPrefix=1\r\n # 代码生成\r\n - id: ruoyi-gen\r\n uri: lb://ruoyi-gen\r\n predicates:\r\n - Path=/code/**\r\n filters:\r\n - StripPrefix=1\r\n # 定时任务\r\n - id: ruoyi-job\r\n uri: lb://ruoyi-job\r\n predicates:\r\n - Path=/schedule/**\r\n filters:\r\n - StripPrefix=1\r\n # 系统模块\r\n - id: ruoyi-system\r\n uri: lb://ruoyi-system\r\n predicates:\r\n - Path=/system/**\r\n filters:\r\n - StripPrefix=1\r\n # 文件服务\r\n - id: ruoyi-file\r\n uri: lb://ruoyi-file\r\n predicates:\r\n - Path=/file/**\r\n filters:\r\n - StripPrefix=1\r\n\r\n# 不校验白名单\r\nignore:\r\n whites:\r\n - /auth/logout\r\n - /auth/login\r\n - /*/v2/api-docs\r\n - /csrf\r\n','ef4a58daf989827334b3aac1c9d68392','2020-05-14 14:17:55','2020-11-18 17:53:23',NULL,'0:0:0:0:0:0:0:1','','','网关模块','null','null','yaml','null'), (3,'ruoyi-auth-dev.yml','DEFAULT_GROUP','spring: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n','868c15010a7a15c027d4c90a48aabb3e','2020-11-20 00:00:00','2020-11-20 00:00:00',NULL,'0:0:0:0:0:0:0:1','','','认证中心','null','null','yaml','null'), (4,'ruoyi-monitor-dev.yml','DEFAULT_GROUP','# spring\r\nspring: \r\n security:\r\n user:\r\n name: ruoyi\r\n password: 123456\r\n boot:\r\n admin:\r\n ui:\r\n title: 若依服务状态监控\r\n','d8997d0707a2fd5d9fc4e8409da38129','2020-11-20 00:00:00','2020-12-21 16:28:07',NULL,'0:0:0:0:0:0:0:1','','','监控中心','null','null','yaml','null'), -(5,'ruoyi-system-dev.yml','DEFAULT_GROUP','# spring配置\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n druid:\r\n stat-view-servlet:\r\n enabled: true\r\n loginUsername: admin\r\n loginPassword: 123456\r\n dynamic:\r\n druid:\r\n initial-size: 5\r\n min-idle: 5\r\n maxActive: 20\r\n maxWait: 60000\r\n timeBetweenEvictionRunsMillis: 60000\r\n minEvictableIdleTimeMillis: 300000\r\n validationQuery: SELECT 1 FROM DUAL\r\n testWhileIdle: true\r\n testOnBorrow: false\r\n testOnReturn: false\r\n poolPreparedStatements: true\r\n maxPoolPreparedStatementPerConnectionSize: 20\r\n filters: stat,wall,slf4j\r\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\r\n datasource:\r\n # 主库数据源\r\n master:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n # 从库数据源\r\n # slave:\r\n # username: \r\n # password: \r\n # url: \r\n # driver-class-name: \r\n # seata: true # 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\r\n\r\n# seata配置\r\nseata:\r\n # 默认关闭,如需启用spring.datasource.dynami.seata需要同时开启\r\n enabled: false\r\n # Seata 应用编号,默认为 ${spring.application.name}\r\n application-id: ${spring.application.name}\r\n # Seata 事务组编号,用于 TC 集群名\r\n tx-service-group: ${spring.application.name}-group\r\n # 关闭自动代理\r\n enable-auto-data-source-proxy: false\r\n # 服务配置项\r\n service:\r\n # 虚拟组和分组的映射\r\n vgroup-mapping:\r\n ruoyi-system-group: default\r\n config:\r\n type: nacos\r\n nacos:\r\n serverAddr: 127.0.0.1:8848\r\n group: SEATA_GROUP\r\n namespace:\r\n registry:\r\n type: nacos\r\n nacos:\r\n application: seata-server\r\n server-addr: 127.0.0.1:8848\r\n namespace:\r\n\r\n# mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.system\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger配置\r\nswagger:\r\n title: 系统模块接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip','ac8913dee679e65bb7d482df5f267d4e','2020-11-20 00:00:00','2021-01-27 10:42:25',NULL,'0:0:0:0:0:0:0:1','','','系统模块','null','null','yaml','null'), +(5,'ruoyi-system-dev.yml','DEFAULT_GROUP','# spring配置\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n druid:\r\n stat-view-servlet:\r\n enabled: true\r\n loginUsername: admin\r\n loginPassword: 123456\r\n dynamic:\r\n druid:\r\n initial-size: 5\r\n min-idle: 5\r\n maxActive: 20\r\n maxWait: 60000\r\n timeBetweenEvictionRunsMillis: 60000\r\n minEvictableIdleTimeMillis: 300000\r\n validationQuery: SELECT 1 FROM DUAL\r\n testWhileIdle: true\r\n testOnBorrow: false\r\n testOnReturn: false\r\n poolPreparedStatements: true\r\n maxPoolPreparedStatementPerConnectionSize: 20\r\n filters: stat,wall,slf4j\r\n connectionProperties: druid.stat.mergeSql\\=true;druid.stat.slowSqlMillis\\=5000\r\n datasource:\r\n # 主库数据源\r\n master:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n # 从库数据源\r\n # slave:\r\n # username: \r\n # password: \r\n # url: \r\n # driver-class-name: \r\n # seata: true # 开启seata代理,开启后默认每个数据源都代理,如果某个不需要代理可单独关闭\r\n\r\n# seata配置\r\nseata:\r\n # 默认关闭,如需启用spring.datasource.dynami.seata需要同时开启\r\n enabled: false\r\n # Seata 应用编号,默认为 ${spring.application.name}\r\n application-id: ${spring.application.name}\r\n # Seata 事务组编号,用于 TC 集群名\r\n tx-service-group: ${spring.application.name}-group\r\n # 关闭自动代理\r\n enable-auto-data-source-proxy: false\r\n # 服务配置项\r\n service:\r\n # 虚拟组和分组的映射\r\n vgroup-mapping:\r\n ruoyi-system-group: default\r\n config:\r\n type: nacos\r\n nacos:\r\n serverAddr: 175.25.50.135:8848\r\n group: SEATA_GROUP\r\n namespace:\r\n registry:\r\n type: nacos\r\n nacos:\r\n application: seata-server\r\n server-addr: 175.25.50.135:8848\r\n namespace:\r\n\r\n# mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.system\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger配置\r\nswagger:\r\n title: 系统模块接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip','ac8913dee679e65bb7d482df5f267d4e','2020-11-20 00:00:00','2021-01-27 10:42:25',NULL,'0:0:0:0:0:0:0:1','','','系统模块','null','null','yaml','null'), (6,'ruoyi-gen-dev.yml','DEFAULT_GROUP','# spring配置\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource: \r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.gen.domain\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger配置\r\nswagger:\r\n title: 代码生成接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n\r\n# 代码生成\r\ngen: \r\n # 作者\r\n author: ruoyi\r\n # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool\r\n packageName: com.ruoyi.system\r\n # 自动去除表前缀,默认是false\r\n autoRemovePre: false\r\n # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)\r\n tablePrefix: sys_\r\n','8c79f64a4cca9b821a03dc8b27a2d8eb','2020-11-20 00:00:00','2021-01-26 10:36:45',NULL,'0:0:0:0:0:0:0:1','','','代码生成','null','null','yaml','null'), (7,'ruoyi-job-dev.yml','DEFAULT_GROUP','# spring配置\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.job.domain\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger配置\r\nswagger:\r\n title: 定时任务接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n','d6dfade9a2c93c463ae857cd503cb172','2020-11-20 00:00:00','2021-01-26 10:36:04',NULL,'0:0:0:0:0:0:0:1','','','定时任务','null','null','yaml','null'), (8,'ruoyi-file-dev.yml','DEFAULT_GROUP','# 本地文件上传 \r\nfile:\r\n domain: http://127.0.0.1:9300\r\n path: D:/ruoyi/uploadPath\r\n prefix: /statics\r\n\r\n# FastDFS配置\r\nfdfs:\r\n domain: http://8.129.231.12\r\n soTimeout: 3000\r\n connectTimeout: 2000\r\n trackerList: 8.129.231.12:22122\r\n\r\n# Minio配置\r\nminio:\r\n url: http://8.129.231.12:9000\r\n accessKey: minioadmin\r\n secretKey: minioadmin\r\n bucketName: test','5382b93f3d8059d6068c0501fdd41195','2020-11-20 00:00:00','2020-12-21 21:01:59',NULL,'0:0:0:0:0:0:0:1','','','文件服务','null','null','yaml','null'),