ljw 2025-12-12 16:38:33 +08:00
commit 6de523c327
64 changed files with 1277 additions and 200 deletions

View File

@ -28,6 +28,7 @@
<dependency> <dependency>
<groupId>com.njzscloud</groupId> <groupId>com.njzscloud</groupId>
<artifactId>njzscloud-common-redis</artifactId> <artifactId>njzscloud-common-redis</artifactId>
<scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -6,7 +6,7 @@ var dc = toDashCase(lcc);
var pageVueName = ucc + ".vue"; var pageVueName = ucc + ".vue";
var formVueName = ucc + "Form.vue"; var formVueName = ucc + "Form.vue";
var pageTsName = dc + ".ts"; var pageTsName = "page.ts";
var apiTsName = dc + "-api.ts"; var apiTsName = dc + "-api.ts";
var dTsName = dc + ".d.ts"; var dTsName = dc + ".d.ts";
%> %>

View File

@ -6,7 +6,7 @@ var dc = toDashCase(lcc);
var pageVueName = ucc + ".vue"; var pageVueName = ucc + ".vue";
var formVueName = ucc + "Form.vue"; var formVueName = ucc + "Form.vue";
var pageTsName = dc + ".ts"; var pageTsName = "page.ts";
var apiTsName = dc + "-api.ts"; var apiTsName = dc + "-api.ts";
var dTsName = dc + ".d.ts"; var dTsName = dc + ".d.ts";
%> %>

View File

@ -6,7 +6,7 @@ var dc = toDashCase(lcc);
var pageVueName = ucc + ".vue"; var pageVueName = ucc + ".vue";
var formVueName = ucc + "Form.vue"; var formVueName = ucc + "Form.vue";
var pageTsName = dc + ".ts"; var pageTsName = "page.ts";
var apiTsName = dc + "-api.ts"; var apiTsName = dc + "-api.ts";
var dTsName = dc + ".d.ts"; var dTsName = dc + ".d.ts";
%> %>

View File

@ -6,7 +6,7 @@ var dc = toDashCase(lcc);
var pageVueName = ucc + ".vue"; var pageVueName = ucc + ".vue";
var formVueName = ucc + "Form.vue"; var formVueName = ucc + "Form.vue";
var pageTsName = dc + ".ts"; var pageTsName = "page.ts";
var apiTsName = dc + "-api.ts"; var apiTsName = dc + "-api.ts";
var dTsName = dc + ".d.ts"; var dTsName = dc + ".d.ts";
%> %>

View File

@ -6,7 +6,7 @@ var dc = toDashCase(lcc);
var pageVueName = ucc + ".vue"; var pageVueName = ucc + ".vue";
var formVueName = ucc + "Form.vue"; var formVueName = ucc + "Form.vue";
var pageTsName = dc + ".ts"; var pageTsName = "page.ts";
var apiTsName = dc + "-api.ts"; var apiTsName = dc + "-api.ts";
var dTsName = dc + ".d.ts"; var dTsName = dc + ".d.ts";
%> %>

View File

@ -1,5 +1,7 @@
package com.njzscloud.common.mvc.validator; package com.njzscloud.common.mvc.validator;
public interface Constrained { public interface Constrained {
ValidRule[] rules(); default ValidRule[] rules() {
return new ValidRule[0];
}
} }

View File

@ -2,6 +2,8 @@ package com.njzscloud.common.security.config;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import com.njzscloud.common.security.controller.PermissionController;
import com.njzscloud.common.security.controller.VerificationCodeController;
import com.njzscloud.common.security.handler.AccessDeniedExceptionHandler; import com.njzscloud.common.security.handler.AccessDeniedExceptionHandler;
import com.njzscloud.common.security.handler.AuthExceptionHandler; import com.njzscloud.common.security.handler.AuthExceptionHandler;
import com.njzscloud.common.security.handler.LogoutPostHandler; import com.njzscloud.common.security.handler.LogoutPostHandler;
@ -11,10 +13,11 @@ import com.njzscloud.common.security.module.password.PasswordAuthenticationProvi
import com.njzscloud.common.security.module.password.PasswordLoginPreparer; import com.njzscloud.common.security.module.password.PasswordLoginPreparer;
import com.njzscloud.common.security.module.wechat.mini.WechatMiniAuthenticationProvider; import com.njzscloud.common.security.module.wechat.mini.WechatMiniAuthenticationProvider;
import com.njzscloud.common.security.module.wechat.mini.WechatMiniLoginPreparer; import com.njzscloud.common.security.module.wechat.mini.WechatMiniLoginPreparer;
import com.njzscloud.common.security.permission.DefaultPermissionManager; import com.njzscloud.common.security.permission.DefaultPermissionLoader;
import com.njzscloud.common.security.permission.PermissionLoader;
import com.njzscloud.common.security.permission.PermissionManager; import com.njzscloud.common.security.permission.PermissionManager;
import com.njzscloud.common.security.support.*; import com.njzscloud.common.security.support.*;
import com.njzscloud.common.security.support.controller.VerificationCodeController; import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
@ -54,9 +57,19 @@ public class WebSecurityAutoConfiguration {
} }
@Bean @Bean
@ConditionalOnMissingBean(PermissionManager.class) @ConditionalOnMissingBean(PermissionLoader.class)
public PermissionManager permissionManager() { public PermissionLoader permissionLoader() {
return new DefaultPermissionManager(); return new DefaultPermissionLoader();
}
@Bean
public PermissionController permissionController(PermissionManager permissionManager) {
return new PermissionController(permissionManager);
}
@Bean
public PermissionManager permissionManager(PermissionLoader permissionLoader) {
return new PermissionManager(permissionLoader);
} }
@Bean @Bean
@ -135,7 +148,7 @@ public class WebSecurityAutoConfiguration {
List<LoginPreparer> loginPreparers = loginPreparerObjectProvider.orderedStream().collect(Collectors.toList()); List<LoginPreparer> loginPreparers = loginPreparerObjectProvider.orderedStream().collect(Collectors.toList());
List<AuthenticationProvider> authenticationProviders = abstractAuthenticationProviderObjectProvider.orderedStream().collect(Collectors.toList()); List<AuthenticationProvider> authenticationProviders = abstractAuthenticationProviderObjectProvider.orderedStream().collect(Collectors.toList());
ProviderManager providerManager = new ProviderManager(authenticationProviders); ProviderManager providerManager = new ProviderManager(authenticationProviders);
String[] authAllows = webSecurityProperties.getAuthAllows().toArray(new String[0]);
LogoutPostHandler logoutPostHandler = new LogoutPostHandler(); LogoutPostHandler logoutPostHandler = new LogoutPostHandler();
return http return http
@ -146,15 +159,17 @@ public class WebSecurityAutoConfiguration {
.securityContext(it -> it.securityContextRepository(new TokenSecurityContextRepository())) .securityContext(it -> it.securityContextRepository(new TokenSecurityContextRepository()))
.authorizeHttpRequests(it -> it .authorizeHttpRequests(it -> it
.requestMatchers(authAllows).permitAll()
.anyRequest() .anyRequest()
.access((AuthorizationManager<RequestAuthorizationContext>) (authentication, object) -> { .access((AuthorizationManager<RequestAuthorizationContext>) (authentication, object) -> {
// 获取当前请求路径 // 获取当前请求路径
String requestPath = object.getRequest().getRequestURI(); HttpServletRequest request = object.getRequest();
// 获取当前认证用户 // 获取当前认证用户
Authentication auth = authentication.get(); Authentication auth = authentication.get();
int vote = permissionManager.vote(auth, request);
return new AuthorizationDecision(true); return new AuthorizationDecision(vote >= 0);
}) })
) )
// .addFilter(securityInterceptor) // .addFilter(securityInterceptor)
@ -181,7 +196,7 @@ public class WebSecurityAutoConfiguration {
if (CollUtil.isNotEmpty(authIgnore)) { if (CollUtil.isNotEmpty(authIgnore)) {
ignoring.requestMatchers(ArrayUtil.toArray(authIgnore, String.class)); ignoring.requestMatchers(ArrayUtil.toArray(authIgnore, String.class));
} }
ignoring.requestMatchers("/error"); // ignoring.requestMatchers("/error");
}; };
} }
} }

View File

@ -20,5 +20,9 @@ public class WebSecurityProperties {
* , Ant * , Ant
*/ */
private Set<String> authIgnores = CollUtil.empty(Set.class); private Set<String> authIgnores = CollUtil.empty(Set.class);
/**
* 访
*/
private Set<String> authAllows = CollUtil.empty(Set.class);
} }

View File

@ -1,9 +1,14 @@
package com.njzscloud.common.security.contant; package com.njzscloud.common.security.contant;
import cn.hutool.core.collection.CollUtil;
import com.njzscloud.common.core.ienum.DictInt; import com.njzscloud.common.core.ienum.DictInt;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
/** /**
* client_code * client_code
* *
@ -11,21 +16,43 @@ import lombok.RequiredArgsConstructor;
@Getter @Getter
@RequiredArgsConstructor @RequiredArgsConstructor
public enum ClientCode implements DictInt { public enum ClientCode implements DictInt {
PC(0, "电脑端"), PC(1, "电脑端"),
WX_MINI_APP(1, "微信小程序"), WX_MINI_APP(2, "微信小程序"),
; ;
private final Integer val; private final Integer val;
private final String txt; private final String txt;
public static int getClientCode(List<Integer> clients) {
if (CollUtil.isEmpty(clients)) return 0;
var clientCode = 0;
for (var client : clients) {
clientCode |= client;
}
return clientCode;
}
public static List<ClientCode> getClients(int clientCode) {
return Arrays.stream(ClientCode.class.getEnumConstants()).filter(it -> it.hasClient(clientCode)).toList();
}
public static boolean valid(int clientCode) {
Optional<Integer> max = Arrays.stream(ClientCode.class.getEnumConstants())
.map(ClientCode::getVal)
.reduce((a, b) -> a | b);
return max.orElse(0) >= clientCode;
}
public static Optional<ClientCode> getClient(int clientCode) {
return Arrays.stream(ClientCode.class.getEnumConstants()).filter(it -> it.hasClient(clientCode)).findFirst();
}
/** /**
* *
*/ */
public boolean hasPermission(int clientCode) { public boolean hasClient(int clientCode) {
var mask = 1 << this.val; return (this.val & clientCode) != 0;
return (clientCode & mask) == 0;
} }
} }

View File

@ -13,6 +13,7 @@ public final class Constants {
public static final String ROLE_AUTHENTICATED = "ROLE_AUTHENTICATED"; public static final String ROLE_AUTHENTICATED = "ROLE_AUTHENTICATED";
public static final String ROLE_ANONYMOUS = "ROLE_ANONYMOUS"; public static final String ROLE_ANONYMOUS = "ROLE_ANONYMOUS";
public static final String ROLE_ADMIN = "ROLE_ADMIN"; public static final String ROLE_ADMIN = "ROLE_ADMIN";
public static final String ROLE_NONE = "ROLE_NONE";
// Redis 订阅频道 权限更新 // Redis 订阅频道 权限更新
public static final String REDIS_TOPIC_PERMISSION_UPDATE = "permission_update"; public static final String REDIS_TOPIC_PERMISSION_UPDATE = "permission_update";

View File

@ -0,0 +1,23 @@
package com.njzscloud.common.security.controller;
import com.njzscloud.common.core.utils.R;
import com.njzscloud.common.security.permission.PermissionManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequestMapping("/permission")
@RequiredArgsConstructor
public class PermissionController {
private final PermissionManager permissionManager;
@GetMapping("/refresh_cache")
public R<?> refresh() {
permissionManager.refresh();
return R.success();
}
}

View File

@ -1,4 +1,4 @@
package com.njzscloud.common.security.support.controller; package com.njzscloud.common.security.controller;
import com.njzscloud.common.core.utils.R; import com.njzscloud.common.core.utils.R;
import com.njzscloud.common.security.support.VerificationCodeService; import com.njzscloud.common.security.support.VerificationCodeService;

View File

@ -0,0 +1,14 @@
package com.njzscloud.common.security.permission;
import java.util.List;
/**
* <br/>
* 访
*/
public class DefaultPermissionLoader implements PermissionLoader {
@Override
public List<RolePermission> load() {
return null;
}
}

View File

@ -1,24 +0,0 @@
package com.njzscloud.common.security.permission;
import com.njzscloud.common.security.contant.EndpointAccessModel;
import java.util.Collections;
import java.util.List;
/**
* <br/>
* 访
*/
public class DefaultPermissionManager extends PermissionManager {
private final List<RolePermission> DEFAULT_ROLE_PERMISSIONS = Collections.singletonList(
new RolePermission()
.setEndpoint("/**")
.setAccessModel(EndpointAccessModel.LOGINED)
);
@Override
protected List<RolePermission> load() {
return DEFAULT_ROLE_PERMISSIONS;
}
}

View File

@ -0,0 +1,7 @@
package com.njzscloud.common.security.permission;
import java.util.List;
public interface PermissionLoader {
List<RolePermission> load();
}

View File

@ -1,14 +1,19 @@
package com.njzscloud.common.security.permission; package com.njzscloud.common.security.permission;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.njzscloud.common.security.contant.Constants; import com.njzscloud.common.security.contant.Constants;
import com.njzscloud.common.security.contant.EndpointAccessModel; import com.njzscloud.common.security.contant.EndpointAccessModel;
import com.njzscloud.common.security.ex.ForbiddenAccessException; import com.njzscloud.common.security.ex.ForbiddenAccessException;
import com.njzscloud.common.security.ex.MissingPermissionException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher; import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher;
import java.util.*; import java.util.*;
@ -18,7 +23,9 @@ import java.util.concurrent.locks.ReentrantLock;
* *
*/ */
@Slf4j @Slf4j
public abstract class PermissionManager { @RequiredArgsConstructor
public class PermissionManager {
private static final int ACCESS_GRANTED = 1;
private static final ReentrantLock PERMISSION_CACHE_LOCK = new ReentrantLock(); private static final ReentrantLock PERMISSION_CACHE_LOCK = new ReentrantLock();
/** /**
@ -27,6 +34,27 @@ public abstract class PermissionManager {
private Map<PathPatternRequestMatcher, Collection<String>> PERMISSION_CACHE; private Map<PathPatternRequestMatcher, Collection<String>> PERMISSION_CACHE;
private Set<PathPatternRequestMatcher> FORBIDDEN_CACHE; private Set<PathPatternRequestMatcher> FORBIDDEN_CACHE;
private static final int ACCESS_ABSTAIN = 0;
private static final int ACCESS_DENIED = -1;
private final PermissionLoader permissionLoader;
public int vote(Authentication authentication, HttpServletRequest request) {
Collection<String> attributes = extractAuthorities(request);
if (authentication == null) {
return ACCESS_DENIED;
}
int result = ACCESS_ABSTAIN;
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (String attribute : attributes) {
result = ACCESS_DENIED;
for (GrantedAuthority authority : authorities) {
if (attribute.equals(authority.getAuthority())) {
return ACCESS_GRANTED;
}
}
}
return result;
}
/** /**
* *
@ -68,9 +96,10 @@ public abstract class PermissionManager {
private void load0() { private void load0() {
// if (log.isDebugEnabled()) log.debug("开始加载权限"); // if (log.isDebugEnabled()) log.debug("开始加载权限");
List<RolePermission> rolePermissions = load(); List<RolePermission> rolePermissions = permissionLoader.load();
if (rolePermissions == null) rolePermissions = new ArrayList<>();
if (rolePermissions == null) rolePermissions = Collections.emptyList(); rolePermissions.add(RolePermission.DEFAULT);
Map<PathPatternRequestMatcher, Collection<String>> permissionMap = new LinkedHashMap<>(); Map<PathPatternRequestMatcher, Collection<String>> permissionMap = new LinkedHashMap<>();
@ -80,7 +109,7 @@ public abstract class PermissionManager {
String endpoint = rolePermission.getEndpoint(); String endpoint = rolePermission.getEndpoint();
String method = rolePermission.getMethod(); String method = rolePermission.getMethod();
EndpointAccessModel accessModel = rolePermission.getAccessModel(); EndpointAccessModel accessModel = rolePermission.getAccessModel();
HttpMethod httpMethod = HttpMethod.valueOf(method); HttpMethod httpMethod = method == null ? null : HttpMethod.valueOf(method);
PathPatternRequestMatcher pathRequestMatcher = PathPatternRequestMatcher.withDefaults().matcher(httpMethod, endpoint); PathPatternRequestMatcher pathRequestMatcher = PathPatternRequestMatcher.withDefaults().matcher(httpMethod, endpoint);
if (accessModel == EndpointAccessModel.FORBIDDEN) { if (accessModel == EndpointAccessModel.FORBIDDEN) {
forbiddenSet.add(pathRequestMatcher); forbiddenSet.add(pathRequestMatcher);
@ -97,6 +126,7 @@ public abstract class PermissionManager {
} else if (accessModel == EndpointAccessModel.AUTHENTICATED) { } else if (accessModel == EndpointAccessModel.AUTHENTICATED) {
String role = rolePermission.getRole(); String role = rolePermission.getRole();
if (StrUtil.isNotBlank(role)) configAttributes.add(role); if (StrUtil.isNotBlank(role)) configAttributes.add(role);
else configAttributes.add(Constants.ROLE_NONE);
} }
} }
@ -106,13 +136,6 @@ public abstract class PermissionManager {
// if (log.isDebugEnabled()) log.debug("本地权限缓存已加载:\n{}", Jackson.toJsonStr(this.getAllRelation())); // if (log.isDebugEnabled()) log.debug("本地权限缓存已加载:\n{}", Jackson.toJsonStr(this.getAllRelation()));
} }
/**
*
*
* @return List&lt;RolePermission&gt;
*/
abstract protected List<RolePermission> load();
/** /**
* *
* *
@ -138,6 +161,16 @@ public abstract class PermissionManager {
return CollUtil.empty(Set.class); return CollUtil.empty(Set.class);
} }
public Collection<String> getAttributes(HttpServletRequest request) {
Collection<String> permission = this.extractAuthorities(request);
String requestURI = request.getRequestURI();
String method = request.getMethod();
String endpoint = method.toUpperCase() + " " + requestURI;
Assert.notEmpty(permission, () -> new MissingPermissionException(StrUtil.format("请求: 【{}】 未指定权限", endpoint)));
return permission;
}
/** /**
* *
* *

View File

@ -1,43 +0,0 @@
package com.njzscloud.common.security.permission;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.njzscloud.common.security.ex.MissingPermissionException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.web.FilterInvocation;
import java.util.Collection;
@Slf4j
@RequiredArgsConstructor
public class PermissionSecurityMetaDataSource {
// org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer
// org.springframework.security.access.vote.RoleVoter PermissionAuthorizationConfigurer
private final PermissionManager permissionManager;
// private final boolean rejectPublicInvocations;
public Collection<String> getAttributes(Object object) throws IllegalArgumentException {
HttpServletRequest request = ((FilterInvocation) object).getRequest();
Collection<String> permission = permissionManager.extractAuthorities(request);
String requestURI = request.getRequestURI();
String method = request.getMethod();
String endpoint = method.toUpperCase() + " " + requestURI;
Assert.notEmpty(permission, () -> new MissingPermissionException(StrUtil.format("请求: 【{}】 未指定权限", endpoint)));
// if (log.isDebugEnabled()) log.debug("允许访问接口:【{}】的角色:【{}】", endpoint, permission);
return permission;
}
public Collection<String> getAllConfigAttributes() {
return permissionManager.getAll();
}
public boolean supports(Class<?> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
}
}

View File

@ -23,23 +23,13 @@ public class PermissionVoter {
int result = ACCESS_ABSTAIN; int result = ACCESS_ABSTAIN;
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
for (String attribute : attributes) { for (String attribute : attributes) {
if (this.supports(attribute)) { result = ACCESS_DENIED;
result = ACCESS_DENIED; for (GrantedAuthority authority : authorities) {
for (GrantedAuthority authority : authorities) { if (attribute.equals(authority.getAuthority())) {
if (attribute.equals(authority.getAuthority())) { return ACCESS_GRANTED;
return ACCESS_GRANTED;
}
} }
} }
} }
return result; return result;
} }
public boolean supports(String attribute) {
return true;
}
public boolean supports(Class<?> clazz) {
return true;
}
} }

View File

@ -12,6 +12,9 @@ import lombok.experimental.Accessors;
@Setter @Setter
@Accessors(chain = true) @Accessors(chain = true)
public class RolePermission { public class RolePermission {
public static RolePermission DEFAULT = new RolePermission()
.setEndpoint("/**")
.setAccessModel(EndpointAccessModel.LOGINED);
/** /**
* *

View File

@ -116,7 +116,8 @@ public abstract class AbstractAuthenticationProvider implements AuthenticationPr
Assert.isFalse(userDetail.getDisabled(), () -> new UserLoginException(ExceptionMsg.CLI_ERR_MSG, "用户已被禁用")); Assert.isFalse(userDetail.getDisabled(), () -> new UserLoginException(ExceptionMsg.CLI_ERR_MSG, "用户已被禁用"));
ClientCode clientCode = loginForm.getClientCode(); ClientCode clientCode = loginForm.getClientCode();
Integer code = userDetail.getClientCode(); Integer code = userDetail.getClientCode();
Assert.isTrue(clientCode.hasPermission(code), () -> new UserLoginException(ExceptionMsg.CLI_ERR_MSG, "当前用户无权使用:" + clientCode.getTxt())); userDetail.setClient(clientCode.getVal());
Assert.isTrue(clientCode.hasClient(code), () -> new UserLoginException(ExceptionMsg.CLI_ERR_MSG, "当前用户无权使用:" + clientCode.getTxt()));
} }
/** /**

View File

@ -23,7 +23,7 @@ public interface IAuthService {
return null; return null;
} }
default UserDetail my(Long userId) { default UserDetail my(Long userId, Integer client) {
return null; return null;
} }
} }

View File

@ -44,6 +44,7 @@ public class UserDetail implements CredentialsContainer, Principal {
private Long accountId; private Long accountId;
private Long tenantId; private Long tenantId;
private Integer clientCode; private Integer clientCode;
private Integer client;
private String tenantName; private String tenantName;
/** /**
* *

View File

@ -18,6 +18,7 @@ import org.mybatis.spring.annotation.MapperScan;
import org.springframework.aop.support.AopUtils; import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
@ -26,12 +27,14 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener; import org.springframework.context.event.EventListener;
import javax.sql.DataSource;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashSet; import java.util.HashSet;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
@Slf4j @Slf4j
@Configuration @Configuration
@ConditionalOnBean(DataSource.class)
@MapperScan("com.njzscloud.common.sichen.mapper") @MapperScan("com.njzscloud.common.sichen.mapper")
@ConditionalOnBooleanProperty(prefix = "sichen.task", name = "enable") @ConditionalOnBooleanProperty(prefix = "sichen.task", name = "enable")
@EnableConfigurationProperties(TaskProperties.class) @EnableConfigurationProperties(TaskProperties.class)

View File

@ -28,10 +28,9 @@ public class WechatUtil {
public synchronized static void auth() { public synchronized static void auth() {
if (tokenExpTime <= new Date().getTime() / 1000 + 60) { if (tokenExpTime <= new Date().getTime() / 1000 + 60) {
GetAccessTokenResult getAccessTokenResult = API.getAccessToken(new GetAccessTokenParam()); GetAccessTokenResult getAccessTokenResult = API.getAccessToken(new GetAccessTokenParam());
Assert.isTrue(getAccessTokenResult.isSucc(), () -> Exceptions.error("微信登录失败"));
accessToken = getAccessTokenResult.getAccess_token(); accessToken = getAccessTokenResult.getAccess_token();
Integer expiresIn = getAccessTokenResult.getExpires_in(); Integer expiresIn = getAccessTokenResult.getExpires_in();
Assert.notBlank(accessToken, () -> Exceptions.error("微信登录失败"));
Assert.notNull(expiresIn, () -> Exceptions.error("微信登录失败"));
tokenExpTime = new Date().getTime() / 1000 + expiresIn; tokenExpTime = new Date().getTime() / 1000 + expiresIn;
} }
} }

View File

@ -1,5 +1,6 @@
package com.njzscloud.common.wechat.result; package com.njzscloud.common.wechat.result;
import cn.hutool.core.util.StrUtil;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@ -17,6 +18,6 @@ public class Code2SessionResult {
private Integer errcode; private Integer errcode;
public boolean isSucc() { public boolean isSucc() {
return errcode != null && errcode == 0; return (errcode != null && errcode == 0) || StrUtil.isNotBlank(openid);
} }
} }

View File

@ -1,5 +1,6 @@
package com.njzscloud.common.wechat.result; package com.njzscloud.common.wechat.result;
import cn.hutool.core.util.StrUtil;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@ -12,4 +13,8 @@ import lombok.experimental.Accessors;
public class GetAccessTokenResult { public class GetAccessTokenResult {
private String access_token; private String access_token;
private Integer expires_in; private Integer expires_in;
public boolean isSucc() {
return StrUtil.isNotBlank(access_token) && (expires_in != null && expires_in > 0);
}
} }

View File

@ -54,10 +54,15 @@
<groupId>com.njzscloud</groupId> <groupId>com.njzscloud</groupId>
<artifactId>njzscloud-common-ws</artifactId> <artifactId>njzscloud-common-ws</artifactId>
</dependency> </dependency>
<!-- <dependency> <dependency>
<groupId>com.njzscloud</groupId>
<artifactId>njzscloud-common-cache</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.njzscloud</groupId> <groupId>com.njzscloud</groupId>
<artifactId>njzscloud-common-redis</artifactId> <artifactId>njzscloud-common-redis</artifactId>
</dependency> --> </dependency>
<dependency> <dependency>
<groupId>com.njzscloud</groupId> <groupId>com.njzscloud</groupId>
<artifactId>njzscloud-common-security</artifactId> <artifactId>njzscloud-common-security</artifactId>

View File

@ -7,6 +7,8 @@ import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.security.util.SecurityUtil; import com.njzscloud.common.security.util.SecurityUtil;
import com.njzscloud.dispose.cst.customer.pojo.entity.CustomerEntity; import com.njzscloud.dispose.cst.customer.pojo.entity.CustomerEntity;
import com.njzscloud.dispose.cst.customer.pojo.param.AddCustomerParam; import com.njzscloud.dispose.cst.customer.pojo.param.AddCustomerParam;
import com.njzscloud.dispose.cst.customer.pojo.param.SearchCustomerParam;
import com.njzscloud.dispose.cst.customer.pojo.result.SearchCustomerResult;
import com.njzscloud.dispose.cst.customer.service.CustomerService; import com.njzscloud.dispose.cst.customer.service.CustomerService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -64,7 +66,7 @@ public class CustomerController {
* *
*/ */
@GetMapping("/detail") @GetMapping("/detail")
public R<CustomerEntity> detail(@RequestParam Long id) { public R<SearchCustomerResult> detail(@RequestParam Long id) {
return R.success(customerService.detail(id)); return R.success(customerService.detail(id));
} }
@ -72,7 +74,7 @@ public class CustomerController {
* *
*/ */
@GetMapping("/paging") @GetMapping("/paging")
public R<PageResult<CustomerEntity>> paging(PageParam pageParam, CustomerEntity customerEntity) { public R<PageResult<SearchCustomerResult>> paging(PageParam pageParam, SearchCustomerParam searchCustomerParam) {
return R.success(customerService.paging(pageParam, customerEntity)); return R.success(customerService.paging(pageParam, searchCustomerParam));
} }
} }

View File

@ -1,12 +1,20 @@
package com.njzscloud.dispose.cst.customer.mapper; package com.njzscloud.dispose.cst.customer.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njzscloud.dispose.cst.customer.pojo.entity.CustomerEntity; import com.njzscloud.dispose.cst.customer.pojo.entity.CustomerEntity;
import com.njzscloud.dispose.cst.customer.pojo.result.SearchCustomerResult;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
/** /**
* *
*/ */
@Mapper @Mapper
public interface CustomerMapper extends BaseMapper<CustomerEntity> { public interface CustomerMapper extends BaseMapper<CustomerEntity> {
IPage<SearchCustomerResult> paging(Page<Object> page, @Param("ew") QueryWrapper<?> ew);
SearchCustomerResult detail(@Param("id") Long id);
} }

View File

@ -0,0 +1,32 @@
package com.njzscloud.dispose.cst.customer.pojo.param;
import com.njzscloud.dispose.cst.customer.constant.IdentityCategory;
import com.njzscloud.dispose.cst.customer.constant.SettlementWay;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
/**
*
*/
@Getter
@Setter
@ToString
@Accessors(chain = true)
public class SearchCustomerParam {
/**
* PingTai-->ChanFei-->QingYun-->XiaoNa-->CaiGou-->
*/
private IdentityCategory identityCategory;
private String keywords;
/**
* YueJie-->YuE-->XianFu-->
*/
private SettlementWay settlementWay;
}

View File

@ -0,0 +1,220 @@
package com.njzscloud.dispose.cst.customer.pojo.result;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.njzscloud.dispose.cst.customer.constant.IdentityCategory;
import com.njzscloud.dispose.cst.customer.constant.SettlementWay;
import com.njzscloud.dispose.cst.org.constant.OrgCategory;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
*
*/
@Getter
@Setter
@ToString
@Accessors(chain = true)
public class SearchCustomerResult {
/**
* Id
*/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
* Id
*/
private Long userId;
/**
* PingTai-->ChanFei-->QingYun-->XiaoNa-->CaiGou-->
*/
private IdentityCategory identityCategory;
/**
* Idcst_org.id
*/
private Long orgId;
/**
*
*/
private String customerName;
/**
*
*/
private String phone;
/**
* YueJie-->YuE-->XianFu-->
*/
private SettlementWay settlementWay;
/**
* 0-->1-->
*/
private Boolean manager;
/**
*
*/
private String nickname;
/**
*
*/
private String avatar;
/**
*
*/
private String username;
/**
* openid
*/
private String wechatOpenid;
/**
*
*/
private LocalDateTime regdate;
/**
* ; 0-->PC1-->2-->
*/
private Integer clientCode;
/**
* ; 0-->1-->
*/
private Boolean disabled;
/**
* GeTiHu-->QiYe-->
*/
private OrgCategory orgCategory;
/**
*
*/
private String uscc;
/**
*
*/
private String orgName;
/**
*
*/
private String businessLicense;
/**
*
*/
private LocalDate licenseStartTime;
/**
*
*/
private LocalDate licenseEndTime;
/**
*
*/
private String legalRepresentative;
/**
*
*/
private String idcard;
/**
*
*/
private LocalDate idcardStartTime;
/**
*
*/
private LocalDate idcardEndTime;
/**
*
*/
private String idcardFront;
/**
*
*/
private String idcardBack;
/**
*
*/
private String province;
/**
*
*/
private String city;
/**
*
*/
private String area;
/**
*
*/
private String town;
/**
*
*/
private String provinceName;
/**
*
*/
private String cityName;
/**
*
*/
private String areaName;
/**
*
*/
private String townName;
/**
*
*/
private String address;
/**
*
*/
private Double lng;
/**
*
*/
private Double lat;
}

View File

@ -2,6 +2,7 @@ package com.njzscloud.dispose.cst.customer.service;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -9,9 +10,12 @@ import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.mp.support.PageParam; import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult; import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.dispose.cst.customer.constant.IdentityCategory; import com.njzscloud.dispose.cst.customer.constant.IdentityCategory;
import com.njzscloud.dispose.cst.customer.constant.SettlementWay;
import com.njzscloud.dispose.cst.customer.mapper.CustomerMapper; import com.njzscloud.dispose.cst.customer.mapper.CustomerMapper;
import com.njzscloud.dispose.cst.customer.pojo.entity.CustomerEntity; import com.njzscloud.dispose.cst.customer.pojo.entity.CustomerEntity;
import com.njzscloud.dispose.cst.customer.pojo.param.AddCustomerParam; import com.njzscloud.dispose.cst.customer.pojo.param.AddCustomerParam;
import com.njzscloud.dispose.cst.customer.pojo.param.SearchCustomerParam;
import com.njzscloud.dispose.cst.customer.pojo.result.SearchCustomerResult;
import com.njzscloud.dispose.cst.org.pojo.param.AddOrgParam; import com.njzscloud.dispose.cst.org.pojo.param.AddOrgParam;
import com.njzscloud.dispose.cst.org.service.OrgService; import com.njzscloud.dispose.cst.org.service.OrgService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -81,14 +85,30 @@ public class CustomerService extends ServiceImpl<CustomerMapper, CustomerEntity>
/** /**
* *
*/ */
public CustomerEntity detail(Long id) { public SearchCustomerResult detail(Long id) {
return this.getById(id); return baseMapper.detail(id);
} }
/** /**
* *
*/ */
public PageResult<CustomerEntity> paging(PageParam pageParam, CustomerEntity customerEntity) { public PageResult<SearchCustomerResult> paging(PageParam pageParam, SearchCustomerParam searchCustomerParam) {
return PageResult.of(this.page(pageParam.toPage(), Wrappers.<CustomerEntity>query(customerEntity))); String keywords = searchCustomerParam.getKeywords();
SettlementWay settlementWay = searchCustomerParam.getSettlementWay();
IdentityCategory identityCategory = searchCustomerParam.getIdentityCategory();
return PageResult.of(baseMapper.paging(pageParam.toPage(), Wrappers.query()
.eq("a.deleted", 0)
.and(StrUtil.isNotBlank(keywords), it -> it
.like("a.customer_name", keywords)
.or().like("a.phone", keywords)
.or().like("b.nickname", keywords)
.or().like("c.username", keywords)
.or().like("c.wechat_openid", keywords)
.or().like("d.org_name", keywords)
.or().like("d.legal_representative", keywords)
)
.eq(settlementWay != null, "a.settlement_way", settlementWay)
.eq(identityCategory != null, "a.identity_category", identityCategory)
));
} }
} }

View File

@ -2,11 +2,11 @@ package com.njzscloud.dispose.cst.driver.pojo.entity;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.njzscloud.dispose.common.pojo.entity.BaseEntity;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import com.njzscloud.dispose.common.pojo.entity.BaseEntity;
import java.time.LocalDateTime; import java.time.LocalDateTime;

View File

@ -7,6 +7,7 @@ import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
/** /**
@ -48,12 +49,12 @@ public class OrgEntity {
/** /**
* *
*/ */
private LocalDateTime licenseStartTime; private LocalDate licenseStartTime;
/** /**
* *
*/ */
private LocalDateTime licenseEndTime; private LocalDate licenseEndTime;
/** /**
* *
@ -68,12 +69,12 @@ public class OrgEntity {
/** /**
* *
*/ */
private LocalDateTime idcardStartTime; private LocalDate idcardStartTime;
/** /**
* *
*/ */
private LocalDateTime idcardEndTime; private LocalDate idcardEndTime;
/** /**
* *

View File

@ -1,5 +1,7 @@
package com.njzscloud.dispose.sys.auth.controller; package com.njzscloud.dispose.sys.auth.controller;
import cn.hutool.core.lang.Assert;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.core.utils.R; import com.njzscloud.common.core.utils.R;
import com.njzscloud.common.security.support.UserDetail; import com.njzscloud.common.security.support.UserDetail;
import com.njzscloud.common.security.util.SecurityUtil; import com.njzscloud.common.security.util.SecurityUtil;
@ -25,8 +27,12 @@ public class AuthController {
*/ */
@GetMapping("/my") @GetMapping("/my")
public R<UserDetail> my() { public R<UserDetail> my() {
Long userId = SecurityUtil.currentUserId(); UserDetail userDetail = SecurityUtil.loginUser();
Long userId = userDetail.getUserId();
Integer client = userDetail.getClient();
return R.success(authService.my(userId)); Assert.notNull(client, () -> Exceptions.exception("客户端信息错误"));
return R.success(authService.my(userId, client));
} }
} }

View File

@ -2,6 +2,7 @@ package com.njzscloud.dispose.sys.auth.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.njzscloud.dispose.sys.auth.pojo.result.EndpointResource; import com.njzscloud.dispose.sys.auth.pojo.result.EndpointResource;
import com.njzscloud.dispose.sys.auth.pojo.result.IdentityInfo;
import com.njzscloud.dispose.sys.auth.pojo.result.MenuResource; import com.njzscloud.dispose.sys.auth.pojo.result.MenuResource;
import com.njzscloud.dispose.sys.auth.pojo.result.MyResult; import com.njzscloud.dispose.sys.auth.pojo.result.MyResult;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@ -17,7 +18,9 @@ public interface AuthMapper {
Set<String> selectRole(@Param("userId") Long userId); Set<String> selectRole(@Param("userId") Long userId);
List<MenuResource> selectUserMenu(@Param("userId") Long userId); List<MenuResource> selectUserMenu(@Param("userId") Long userId, @Param("client") Integer client);
List<EndpointResource> selectUserEndpoint(@Param("userId") Long userId); List<EndpointResource> selectUserEndpoint(@Param("userId") Long userId);
List<IdentityInfo> selectUserIdentity(@Param("userId") Long userId);
} }

View File

@ -1,5 +1,6 @@
package com.njzscloud.dispose.sys.auth.pojo.result; package com.njzscloud.dispose.sys.auth.pojo.result;
import com.njzscloud.common.security.contant.EndpointAccessModel;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@ -37,7 +38,7 @@ public class EndpointResource {
/** /**
* 访; endpoint_access_model * 访; endpoint_access_model
*/ */
private String accessModel; private EndpointAccessModel accessModel;
/** /**
* *

View File

@ -0,0 +1,165 @@
package com.njzscloud.dispose.sys.auth.pojo.result;
import com.njzscloud.dispose.cst.customer.constant.IdentityCategory;
import com.njzscloud.dispose.cst.customer.constant.SettlementWay;
import com.njzscloud.dispose.cst.org.constant.OrgCategory;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.time.LocalDate;
@Getter
@Setter
@ToString
@Accessors(chain = true)
public class IdentityInfo {
/**
* PingTai-->ChanFei-->QingYun-->XiaoNa-->CaiGou-->
*/
private IdentityCategory identityCategory;
private Long customerId;
/**
* Idcst_org.id
*/
private Long orgId;
/**
*
*/
private String customerName;
/**
*
*/
private String phone;
/**
* YueJie-->YuE-->XianFu-->
*/
private SettlementWay settlementWay;
/**
* 0-->1-->
*/
private Boolean manager;
/**
* GeTiHu-->QiYe-->
*/
private OrgCategory orgCategory;
/**
*
*/
private String uscc;
/**
*
*/
private String orgName;
/**
*
*/
private String businessLicense;
/**
*
*/
private LocalDate licenseStartTime;
/**
*
*/
private LocalDate licenseEndTime;
/**
*
*/
private String legalRepresentative;
/**
*
*/
private String idcard;
/**
*
*/
private LocalDate idcardStartTime;
/**
*
*/
private LocalDate idcardEndTime;
/**
*
*/
private String idcardFront;
/**
*
*/
private String idcardBack;
/**
*
*/
private String province;
/**
*
*/
private String city;
/**
*
*/
private String area;
/**
*
*/
private String town;
/**
*
*/
private String provinceName;
/**
*
*/
private String cityName;
/**
*
*/
private String areaName;
/**
*
*/
private String townName;
/**
*
*/
private String address;
/**
*
*/
private Double lng;
/**
*
*/
private Double lat;
}

View File

@ -16,6 +16,7 @@ public class MyResult extends UserDetail {
private List<MenuResource> menus; private List<MenuResource> menus;
private List<EndpointResource> endpoints; private List<EndpointResource> endpoints;
private List<IdentityInfo> identities;
private List<Map<String, Object>> setting; private List<Map<String, Object>> setting;

View File

@ -1,14 +1,17 @@
package com.njzscloud.dispose.sys.auth.service; package com.njzscloud.dispose.sys.auth.service;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.security.module.password.PasswordLoginForm; import com.njzscloud.common.security.module.password.PasswordLoginForm;
import com.njzscloud.common.security.module.wechat.mini.WechatMiniLoginForm; import com.njzscloud.common.security.module.wechat.mini.WechatMiniLoginForm;
import com.njzscloud.common.security.support.IAuthService; import com.njzscloud.common.security.support.IAuthService;
import com.njzscloud.common.security.support.UserDetail; import com.njzscloud.common.security.support.UserDetail;
import com.njzscloud.dispose.sys.auth.mapper.AuthMapper; import com.njzscloud.dispose.sys.auth.mapper.AuthMapper;
import com.njzscloud.dispose.sys.auth.pojo.result.EndpointResource; import com.njzscloud.dispose.sys.auth.pojo.result.EndpointResource;
import com.njzscloud.dispose.sys.auth.pojo.result.IdentityInfo;
import com.njzscloud.dispose.sys.auth.pojo.result.MenuResource; import com.njzscloud.dispose.sys.auth.pojo.result.MenuResource;
import com.njzscloud.dispose.sys.auth.pojo.result.MyResult; import com.njzscloud.dispose.sys.auth.pojo.result.MyResult;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -22,6 +25,9 @@ import java.util.Set;
import static com.njzscloud.common.security.contant.Constants.ROLE_ANONYMOUS; import static com.njzscloud.common.security.contant.Constants.ROLE_ANONYMOUS;
import static com.njzscloud.common.security.contant.Constants.ROLE_AUTHENTICATED; import static com.njzscloud.common.security.contant.Constants.ROLE_AUTHENTICATED;
/**
*
*/
@Slf4j @Slf4j
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
@ -53,14 +59,17 @@ public class AuthService implements IAuthService {
* *
*/ */
@Override @Override
public UserDetail my(Long userId) { public UserDetail my(Long userId, Integer client) {
UserDetail userDetail = authMapper.selectUser(Wrappers.query().eq("a.id", userId).eq("a.deleted", 0)); UserDetail userDetail = authMapper.selectUser(Wrappers.query().eq("b.id", userId).eq("a.deleted", 0));
List<MenuResource> menuResources = authMapper.selectUserMenu(userId); Assert.notNull(userDetail, () -> Exceptions.exception("未查询到用户信息"));
List<MenuResource> menuResources = authMapper.selectUserMenu(userId, client);
List<EndpointResource> endpointResources = authMapper.selectUserEndpoint(userId); List<EndpointResource> endpointResources = authMapper.selectUserEndpoint(userId);
List<IdentityInfo> identityInfoList = authMapper.selectUserIdentity(userId);
Set<String> roles = authMapper.selectRole(userId); Set<String> roles = authMapper.selectRole(userId);
roles.add(ROLE_AUTHENTICATED); roles.add(ROLE_AUTHENTICATED);
roles.add(ROLE_ANONYMOUS); roles.add(ROLE_ANONYMOUS);
return BeanUtil.copyProperties(userDetail, MyResult.class) return BeanUtil.copyProperties(userDetail, MyResult.class)
.setIdentities(identityInfoList)
.setMenus(menuResources) .setMenus(menuResources)
.setEndpoints(endpointResources) .setEndpoints(endpointResources)
.setRoles(roles) .setRoles(roles)

View File

@ -4,6 +4,9 @@ import com.njzscloud.common.core.ienum.DictStr;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.Optional;
/** /**
* request_method * request_method
* HTTP * HTTP
@ -18,4 +21,9 @@ public enum RequestMethod implements DictStr {
private final String val; private final String val;
private final String txt; private final String txt;
public static RequestMethod resolve(String name) {
Optional<RequestMethod> first = Arrays.stream(RequestMethod.class.getEnumConstants()).filter(it -> it.val.equals(name)).findFirst();
return first.orElse(null);
}
} }

View File

@ -1,8 +1,11 @@
package com.njzscloud.dispose.sys.endpoint.controller; package com.njzscloud.dispose.sys.endpoint.controller;
import com.njzscloud.common.core.utils.R; import com.njzscloud.common.core.utils.R;
import com.njzscloud.dispose.sys.endpoint.pojo.entity.EndpointEntity; import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.dispose.sys.endpoint.pojo.param.AddEndpointParam;
import com.njzscloud.dispose.sys.endpoint.pojo.param.EndpointSearchParam; import com.njzscloud.dispose.sys.endpoint.pojo.param.EndpointSearchParam;
import com.njzscloud.dispose.sys.endpoint.pojo.param.ModifyEndpointParam;
import com.njzscloud.dispose.sys.endpoint.pojo.result.EndpointDetailResult; import com.njzscloud.dispose.sys.endpoint.pojo.result.EndpointDetailResult;
import com.njzscloud.dispose.sys.endpoint.service.EndpointService; import com.njzscloud.dispose.sys.endpoint.service.EndpointService;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@ -26,8 +29,8 @@ public class EndpointController {
* *
*/ */
@PostMapping("/add") @PostMapping("/add")
public R<?> add(@RequestBody EndpointEntity endpointEntity) { public R<?> add(@RequestBody AddEndpointParam addEndpointParam) {
endpointService.add(endpointEntity); endpointService.add(addEndpointParam);
return R.success(); return R.success();
} }
@ -35,8 +38,8 @@ public class EndpointController {
* *
*/ */
@PostMapping("/modify") @PostMapping("/modify")
public R<?> modify(@RequestBody EndpointEntity endpointEntity) { public R<?> modify(@RequestBody ModifyEndpointParam modifyEndpointParam) {
endpointService.modify(endpointEntity); endpointService.modify(modifyEndpointParam);
return R.success(); return R.success();
} }
@ -53,7 +56,7 @@ public class EndpointController {
* *
*/ */
@GetMapping("/detail") @GetMapping("/detail")
public R<EndpointEntity> detail(@RequestParam Long id) { public R<EndpointDetailResult> detail(@RequestParam("id") Long id) {
return R.success(endpointService.detail(id)); return R.success(endpointService.detail(id));
} }
@ -65,4 +68,20 @@ public class EndpointController {
return R.success(endpointService.listAll(endpointSearchParam)); return R.success(endpointService.listAll(endpointSearchParam));
} }
/**
*
*/
@GetMapping("/paging")
public R<PageResult<EndpointDetailResult>> paging(PageParam pageParam, EndpointSearchParam endpointSearchParam) {
return R.success(endpointService.paging(pageParam, endpointSearchParam));
}
/**
*
*/
@GetMapping("/reload")
public R<?> reload() {
endpointService.saveAll();
return R.success();
}
} }

View File

@ -0,0 +1,49 @@
package com.njzscloud.dispose.sys.endpoint.pojo.param;
import com.njzscloud.common.security.contant.EndpointAccessModel;
import com.njzscloud.dispose.sys.endpoint.contant.RequestMethod;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
/**
*
*/
@Getter
@Setter
@ToString
@Accessors(chain = true)
public class AddEndpointParam {
/**
* ; request_method
*/
@NotNull(message = "请求方式不能为空")
private RequestMethod requestMethod;
/**
* ; /
*/
private String routingPath;
/**
* ; / , Ant
*/
@NotBlank(message = "端点地址不能为空")
private String endpointPath;
/**
* 访; endpoint_access_model
*/
@NotNull(message = "访问模式不能为空")
private EndpointAccessModel accessModel;
/**
*
*/
private String memo;
}

View File

@ -0,0 +1,55 @@
package com.njzscloud.dispose.sys.endpoint.pojo.param;
import com.njzscloud.common.security.contant.EndpointAccessModel;
import com.njzscloud.dispose.sys.endpoint.contant.RequestMethod;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
/**
*
*/
@Getter
@Setter
@ToString
@Accessors(chain = true)
public class ModifyEndpointParam {
/**
* Id
*/
@NotNull
private Long id;
/**
* ; request_method
*/
@NotNull(message = "请求方式不能为空")
private RequestMethod requestMethod;
/**
* ; /
*/
private String routingPath;
/**
* ; / , Ant
*/
@NotBlank(message = "端点地址不能为空")
private String endpointPath;
/**
* 访; endpoint_access_model
*/
@NotNull(message = "访问模式不能为空")
private EndpointAccessModel accessModel;
/**
*
*/
private String memo;
}

View File

@ -1,19 +1,37 @@
package com.njzscloud.dispose.sys.endpoint.service; package com.njzscloud.dispose.sys.endpoint.service;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.core.utils.GroupUtil;
import com.njzscloud.common.mp.support.PageParam;
import com.njzscloud.common.mp.support.PageResult;
import com.njzscloud.common.security.contant.EndpointAccessModel;
import com.njzscloud.dispose.sys.endpoint.contant.RequestMethod;
import com.njzscloud.dispose.sys.endpoint.mapper.EndpointMapper; import com.njzscloud.dispose.sys.endpoint.mapper.EndpointMapper;
import com.njzscloud.dispose.sys.endpoint.pojo.entity.EndpointEntity; import com.njzscloud.dispose.sys.endpoint.pojo.entity.EndpointEntity;
import com.njzscloud.dispose.sys.endpoint.pojo.param.AddEndpointParam;
import com.njzscloud.dispose.sys.endpoint.pojo.param.EndpointSearchParam; import com.njzscloud.dispose.sys.endpoint.pojo.param.EndpointSearchParam;
import com.njzscloud.dispose.sys.endpoint.pojo.param.ModifyEndpointParam;
import com.njzscloud.dispose.sys.endpoint.pojo.result.EndpointDetailResult; import com.njzscloud.dispose.sys.endpoint.pojo.result.EndpointDetailResult;
import com.njzscloud.dispose.sys.resource.contant.ResourceOrigin;
import com.njzscloud.dispose.sys.resource.pojo.entity.ResourceEntity;
import com.njzscloud.dispose.sys.resource.pojo.result.ControllerMappingResult;
import com.njzscloud.dispose.sys.resource.service.ResourceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.util.List; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -21,20 +39,65 @@ import java.util.stream.Collectors;
*/ */
@Slf4j @Slf4j
@Service @Service
@RequiredArgsConstructor
public class EndpointService extends ServiceImpl<EndpointMapper, EndpointEntity> implements IService<EndpointEntity> { public class EndpointService extends ServiceImpl<EndpointMapper, EndpointEntity> implements IService<EndpointEntity> {
private final ResourceService resourceService;
private final RequestMappingHandlerMapping requestMappingHandlerMapping;
/** /**
* *
*/ */
public void add(EndpointEntity endpointEntity) { @Transactional(rollbackFor = Exception.class)
public void add(AddEndpointParam addEndpointParam) {
EndpointEntity endpointEntity = BeanUtil.copyProperties(addEndpointParam, EndpointEntity.class);
RequestMethod requestMethod = addEndpointParam.getRequestMethod();
String endpointPath = addEndpointParam.getEndpointPath();
boolean exists = this.exists(Wrappers.<EndpointEntity>lambdaQuery()
.eq(EndpointEntity::getRequestMethod, requestMethod)
.eq(EndpointEntity::getEndpointPath, endpointPath)
);
Assert.isFalse(exists, () -> Exceptions.exception("端点重复"));
this.save(endpointEntity); this.save(endpointEntity);
String sn = requestMethod + endpointPath;
resourceService.save(new ResourceEntity()
.setSn(sn)
.setDataId(endpointEntity.getId())
.setTableName(ResourceOrigin.Endpoint.getVal())
.setMemo("端点资源-" + requestMethod + " " + endpointPath));
} }
/** /**
* *
*/ */
public void modify(EndpointEntity endpointEntity) { @Transactional(rollbackFor = Exception.class)
public void modify(ModifyEndpointParam modifyEndpointParam) {
Long id = modifyEndpointParam.getId();
EndpointEntity oldData = this.getById(id);
Assert.notNull(oldData, () -> Exceptions.exception("要修改的数据不存在"));
RequestMethod requestMethod = modifyEndpointParam.getRequestMethod();
String endpointPath = modifyEndpointParam.getEndpointPath();
boolean exists = this.exists(Wrappers.<EndpointEntity>lambdaQuery()
.eq(EndpointEntity::getRequestMethod, requestMethod)
.eq(EndpointEntity::getEndpointPath, endpointPath)
.ne(EndpointEntity::getId, id)
);
Assert.isFalse(exists, () -> Exceptions.exception("端点重复"));
EndpointEntity endpointEntity = BeanUtil.copyProperties(modifyEndpointParam, EndpointEntity.class);
this.updateById(endpointEntity); this.updateById(endpointEntity);
String sn = requestMethod + endpointPath;
resourceService.update(Wrappers.<ResourceEntity>lambdaUpdate()
.eq(ResourceEntity::getTableName, ResourceOrigin.Endpoint.getVal())
.eq(ResourceEntity::getDataId, id)
.set(ResourceEntity::getMemo, "端点资源-" + requestMethod + " " + endpointPath)
.set(ResourceEntity::getSn, sn)
);
} }
/** /**
@ -42,26 +105,121 @@ public class EndpointService extends ServiceImpl<EndpointMapper, EndpointEntity>
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void del(List<Long> ids) { public void del(List<Long> ids) {
boolean occupied = resourceService.occupied(ids, ResourceOrigin.Endpoint);
Assert.isFalse(occupied, () -> Exceptions.exception("端点已被分配,不能删除"));
this.removeBatchByIds(ids); this.removeBatchByIds(ids);
resourceService.delRes(ids, ResourceOrigin.Endpoint);
} }
/** /**
* *
*/ */
public EndpointEntity detail(Long id) { public EndpointDetailResult detail(Long id) {
return this.getById(id); EndpointEntity endpointEntity = this.getById(id);
return BeanUtil.copyProperties(endpointEntity, EndpointDetailResult.class);
}
/**
*
*/
public PageResult<EndpointDetailResult> paging(PageParam pageParam, EndpointSearchParam endpointSearchParam) {
String endpointPath = endpointSearchParam.getEndpointPath();
return PageResult.of(this.page(pageParam.toPage(), Wrappers.<EndpointEntity>lambdaQuery()
.like(StrUtil.isNotBlank(endpointPath), EndpointEntity::getEndpointPath, endpointPath)
.orderByAsc(EndpointEntity::getRequestMethod, EndpointEntity::getRoutingPath, EndpointEntity::getEndpointPath)
).convert(it -> BeanUtil.copyProperties(it, EndpointDetailResult.class)));
} }
/** /**
* *
*/ */
public List<EndpointDetailResult> listAll(EndpointSearchParam endpointSearchParam) { public List<EndpointDetailResult> listAll(EndpointSearchParam endpointSearchParam) {
String endpointPath = endpointSearchParam.getEndpointPath();
return this.list(Wrappers.<EndpointEntity>lambdaQuery() return this.list(Wrappers.<EndpointEntity>lambdaQuery()
.like(StrUtil.isNotBlank(endpointSearchParam.getEndpointPath()), EndpointEntity::getEndpointPath, endpointSearchParam.getEndpointPath()) .like(StrUtil.isNotBlank(endpointPath), EndpointEntity::getEndpointPath, endpointPath)
.orderByAsc(EndpointEntity::getRequestMethod, EndpointEntity::getRoutingPath, EndpointEntity::getEndpointPath) .orderByAsc(EndpointEntity::getRequestMethod, EndpointEntity::getRoutingPath, EndpointEntity::getEndpointPath)
) )
.stream() .stream()
.map(it -> BeanUtil.copyProperties(it, EndpointDetailResult.class)) .map(it -> BeanUtil.copyProperties(it, EndpointDetailResult.class))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Transactional(rollbackFor = Exception.class)
public void saveAll() {
List<ControllerMappingResult> controllerMappingResults = scanAllControllerMappings();
List<EndpointEntity> oldEndpoints = this.list();
Map<String, EndpointEntity> map = GroupUtil.k_o(oldEndpoints, it -> it.getRequestMethod() + it.getEndpointPath());
Set<String> endpointPaths = map.keySet();
List<EndpointEntity> list = controllerMappingResults
.stream()
.filter(it -> it.getControllerClassName().startsWith("com.njzscloud") && !endpointPaths.contains(it.getHttpMethods() + it.getFullUrl()))
.map(it -> new EndpointEntity()
.setEndpointPath(it.getFullUrl())
.setRoutingPath("")
.setMemo("")
.setAccessModel(EndpointAccessModel.LOGINED)
.setRequestMethod(RequestMethod.resolve(it.getHttpMethods())))
.toList();
this.saveBatch(list);
List<ResourceEntity> resourceEntities = list.stream().map(it -> {
RequestMethod requestMethod = it.getRequestMethod();
String endpointPath = it.getEndpointPath();
return new ResourceEntity()
.setSn(requestMethod + endpointPath)
.setDataId(it.getId())
.setTableName(ResourceOrigin.Endpoint.getVal())
.setMemo("接口资源-" + requestMethod + " " + endpointPath)
;
}).toList();
resourceService.saveBatch(resourceEntities);
}
public List<ControllerMappingResult> scanAllControllerMappings() {
List<ControllerMappingResult> result = new ArrayList<>();
// 1. 获取所有RequestMappingInfo包含映射规则和对应的HandlerMethod
Map<RequestMappingInfo, HandlerMethod> handlerMethods = requestMappingHandlerMapping.getHandlerMethods();
// 2. 遍历解析每个映射规则
for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : handlerMethods.entrySet()) {
RequestMappingInfo requestMappingInfo = entry.getKey();
HandlerMethod handlerMethod = entry.getValue();
// 封装DTO
ControllerMappingResult dto = new ControllerMappingResult();
// === 解析控制器类信息 ===
Class<?> controllerClass = handlerMethod.getBeanType();
dto.setControllerClassName(controllerClass.getCanonicalName());
// === 解析方法级路径 ===
Set<String> methodPatterns = requestMappingInfo.getPatternValues();
// 方法路径通常只有一个,取第一个即可
// === 拼接完整URL ===
String fullUrl = methodPatterns.iterator().next();
// 处理重复的/(如类路径/endpoint + 方法路径/add → /endpoint/add类路径/endpoint/ + 方法路径/add → /endpoint/add
fullUrl = fullUrl.replaceAll("//+", "/");
dto.setFullUrl(fullUrl);
// === 解析请求方法GET/POST等 ===
RequestMethodsRequestCondition methodsCondition = requestMappingInfo.getMethodsCondition();
Set<org.springframework.web.bind.annotation.RequestMethod> methods = methodsCondition.getMethods();
Optional<org.springframework.web.bind.annotation.RequestMethod> first = methods.stream().findFirst();
Optional<String> s = first.map(Enum::name);
dto.setHttpMethods(s.orElse(""));
// === 解析方法名 ===
dto.setMethodName(handlerMethod.getMethod().getName());
result.add(dto);
}
return result;
}
} }

View File

@ -2,6 +2,7 @@ package com.njzscloud.dispose.sys.menu.pojo.entity;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import com.njzscloud.common.mp.support.handler.j.JsonTypeHandler; import com.njzscloud.common.mp.support.handler.j.JsonTypeHandler;
import com.njzscloud.common.security.contant.ClientCode;
import com.njzscloud.dispose.sys.menu.contant.MenuCategory; import com.njzscloud.dispose.sys.menu.contant.MenuCategory;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@ -26,6 +27,9 @@ public class MenuEntity {
private Long id; private Long id;
private String sn; private String sn;
private ClientCode clientCode;
/** /**
* Id; 1 0 * Id; 1 0
*/ */

View File

@ -4,8 +4,10 @@ import cn.hutool.core.util.StrUtil;
import com.njzscloud.common.mvc.validator.Constrained; import com.njzscloud.common.mvc.validator.Constrained;
import com.njzscloud.common.mvc.validator.Constraint; import com.njzscloud.common.mvc.validator.Constraint;
import com.njzscloud.common.mvc.validator.ValidRule; import com.njzscloud.common.mvc.validator.ValidRule;
import com.njzscloud.common.security.contant.ClientCode;
import com.njzscloud.dispose.sys.menu.contant.MenuCategory; import com.njzscloud.dispose.sys.menu.contant.MenuCategory;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@ -16,6 +18,9 @@ import lombok.Setter;
@Setter @Setter
@Constraint @Constraint
public class MenuAddParam implements Constrained { public class MenuAddParam implements Constrained {
@NotNull
private ClientCode clientCode;
/** /**
* Id; 1 0 * Id; 1 0
*/ */

View File

@ -3,6 +3,7 @@ package com.njzscloud.dispose.sys.menu.pojo.param;
import com.njzscloud.common.mvc.validator.Constrained; import com.njzscloud.common.mvc.validator.Constrained;
import com.njzscloud.common.mvc.validator.Constraint; import com.njzscloud.common.mvc.validator.Constraint;
import com.njzscloud.common.mvc.validator.ValidRule; import com.njzscloud.common.mvc.validator.ValidRule;
import com.njzscloud.common.security.contant.ClientCode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@ -20,6 +21,7 @@ public class MenuModifyParam implements Constrained {
* Id * Id
*/ */
private Long id; private Long id;
private ClientCode clientCode;
/** /**
* Id; 1 0 * Id; 1 0

View File

@ -16,6 +16,7 @@ public class MenuSearchParam {
private Long pid; private Long pid;
private Integer clientCode;
/** /**
* *

View File

@ -1,5 +1,6 @@
package com.njzscloud.dispose.sys.menu.pojo.result; package com.njzscloud.dispose.sys.menu.pojo.result;
import com.njzscloud.common.security.contant.ClientCode;
import com.njzscloud.dispose.sys.menu.contant.MenuCategory; import com.njzscloud.dispose.sys.menu.contant.MenuCategory;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
@ -22,6 +23,8 @@ public class MenuDetailResult {
*/ */
private Long id; private Long id;
private String sn; private String sn;
private ClientCode clientCode;
/** /**
* Id; 1 0 * Id; 1 0
*/ */

View File

@ -21,8 +21,8 @@ import com.njzscloud.dispose.sys.menu.pojo.result.MenuDetailResult;
import com.njzscloud.dispose.sys.resource.contant.ResourceOrigin; import com.njzscloud.dispose.sys.resource.contant.ResourceOrigin;
import com.njzscloud.dispose.sys.resource.pojo.entity.ResourceEntity; import com.njzscloud.dispose.sys.resource.pojo.entity.ResourceEntity;
import com.njzscloud.dispose.sys.resource.service.ResourceService; import com.njzscloud.dispose.sys.resource.service.ResourceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -35,10 +35,10 @@ import java.util.stream.Collectors;
*/ */
@Slf4j @Slf4j
@Service @Service
@RequiredArgsConstructor
public class MenuService extends ServiceImpl<MenuMapper, MenuEntity> implements IService<MenuEntity> { public class MenuService extends ServiceImpl<MenuMapper, MenuEntity> implements IService<MenuEntity> {
@Autowired private final ResourceService resourceService;
private ResourceService resourceService;
/** /**
* *
@ -195,11 +195,13 @@ public class MenuService extends ServiceImpl<MenuMapper, MenuEntity> implements
Long pid = menuSearchParam.getPid(); Long pid = menuSearchParam.getPid();
String title = menuSearchParam.getTitle(); String title = menuSearchParam.getTitle();
String routeName = menuSearchParam.getRouteName(); String routeName = menuSearchParam.getRouteName();
return this.list(Wrappers.<MenuEntity>lambdaQuery() Integer clientCode = menuSearchParam.getClientCode();
.eq(pid != null, MenuEntity::getPid, pid) return this.list(Wrappers.<MenuEntity>query()
.like(StrUtil.isNotBlank(title), MenuEntity::getTitle, title) .eq(pid != null, "pid", pid)
.like(StrUtil.isNotBlank(routeName), MenuEntity::getRouteName, routeName) .and(clientCode != null && clientCode >= 0, it -> it.ne("clientCode & " + clientCode, 0))
.orderByAsc(Arrays.asList(MenuEntity::getTier, MenuEntity::getSort, MenuEntity::getId))) .like(StrUtil.isNotBlank(title), "title", title)
.like(StrUtil.isNotBlank(routeName), "route_name", routeName)
.orderByAsc(Arrays.asList("tier", "sort", "id")))
.stream() .stream()
.map(it -> BeanUtil.copyProperties(it, MenuDetailResult.class)) .map(it -> BeanUtil.copyProperties(it, MenuDetailResult.class))
.collect(Collectors.toList()); .collect(Collectors.toList());

View File

@ -11,7 +11,7 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor
public enum ResourceOrigin implements DictStr { public enum ResourceOrigin implements DictStr {
Menu("sys_menu", "菜单"), Menu("sys_menu", "菜单"),
Endpoint("sys_endpoint", "接口"), Endpoint("sys_endpoint", "端点"),
; ;
private final String val; private final String val;

View File

@ -37,8 +37,11 @@ public class ResourceController {
} }
@GetMapping("/list_role_res") @GetMapping("/list_role_res")
public R<List<ResourceEntity>> listRoleRes(@RequestParam(value = "roleId") String roleId) { public R<List<ResourceEntity>> listRoleRes(
return R.success(resourceService.listRoleRes(roleId)); @RequestParam(value = "roleId") String roleId,
@RequestParam(value = "tableName", required = false) String tableName
) {
return R.success(resourceService.listRoleRes(roleId, tableName));
} }
} }

View File

@ -3,6 +3,7 @@ package com.njzscloud.dispose.sys.resource.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.njzscloud.common.security.permission.RolePermission;
import com.njzscloud.dispose.sys.resource.pojo.entity.ResourceEntity; import com.njzscloud.dispose.sys.resource.pojo.entity.ResourceEntity;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@ -16,5 +17,8 @@ import java.util.List;
public interface ResourceMapper extends BaseMapper<ResourceEntity> { public interface ResourceMapper extends BaseMapper<ResourceEntity> {
List<String> occupied(@Param(Constants.WRAPPER) QueryWrapper<Object> ew); List<String> occupied(@Param(Constants.WRAPPER) QueryWrapper<Object> ew);
List<ResourceEntity> listRoleRes(@Param("roleId") String roleId); List<ResourceEntity> listRoleRes(@Param("ew") QueryWrapper<?> ew);
List<RolePermission> loadPermission();
} }

View File

@ -0,0 +1,29 @@
package com.njzscloud.dispose.sys.resource.pojo.result;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
@Getter
@Setter
@ToString
@Accessors(chain = true)
public class ControllerMappingResult {
/**
* com.xxx.controller.EndpointController
*/
private String controllerClassName;
/**
* add
*/
private String methodName;
/**
* /endpoint/add
*/
private String fullUrl;
/**
* GET/POST/PUT/DELETE
*/
private String httpMethods;
}

View File

@ -1,8 +1,11 @@
package com.njzscloud.dispose.sys.resource.service; package com.njzscloud.dispose.sys.resource.service;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njzscloud.common.security.permission.PermissionLoader;
import com.njzscloud.common.security.permission.RolePermission;
import com.njzscloud.dispose.sys.resource.contant.ResourceOrigin; import com.njzscloud.dispose.sys.resource.contant.ResourceOrigin;
import com.njzscloud.dispose.sys.resource.mapper.ResourceMapper; import com.njzscloud.dispose.sys.resource.mapper.ResourceMapper;
import com.njzscloud.dispose.sys.resource.pojo.entity.ResourceEntity; import com.njzscloud.dispose.sys.resource.pojo.entity.ResourceEntity;
@ -19,8 +22,7 @@ import java.util.List;
@Slf4j @Slf4j
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class ResourceService extends ServiceImpl<ResourceMapper, ResourceEntity> implements IService<ResourceEntity> { public class ResourceService extends ServiceImpl<ResourceMapper, ResourceEntity> implements PermissionLoader, IService<ResourceEntity> {
/** /**
* *
*/ */
@ -42,7 +44,14 @@ public class ResourceService extends ServiceImpl<ResourceMapper, ResourceEntity>
return !roles.isEmpty(); return !roles.isEmpty();
} }
public List<ResourceEntity> listRoleRes(String roleId) { public List<ResourceEntity> listRoleRes(String roleId, String tableName) {
return baseMapper.listRoleRes(roleId); return baseMapper.listRoleRes(Wrappers.query()
.eq("b.role_id", roleId)
.eq(StrUtil.isNotBlank(tableName), "a.table_name", tableName));
}
@Override
public List<RolePermission> load() {
return baseMapper.loadPermission();
} }
} }

View File

@ -17,7 +17,7 @@ import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.time.LocalDateTime; import java.time.LocalDate;
import java.util.List; import java.util.List;
@Getter @Getter
@ -25,10 +25,12 @@ import java.util.List;
@ToString @ToString
@Accessors(chain = true) @Accessors(chain = true)
public class UserRegisterParam implements Constrained { public class UserRegisterParam implements Constrained {
@NotNull(message = "鉴权方式不能为空")
private AuthWay authWay; private AuthWay authWay;
/** /**
* *
*/ */
@NotBlank(message = "姓名不能为空")
private String nickname; private String nickname;
/** /**
* *
@ -37,6 +39,7 @@ public class UserRegisterParam implements Constrained {
/** /**
* *
*/ */
@NotBlank(message = "手机号不能为空")
private String phone; private String phone;
/** /**
* *
@ -56,12 +59,14 @@ public class UserRegisterParam implements Constrained {
/** /**
* *
*/ */
@Valid
@NotNull(message = "客户信息不能为空") @NotNull(message = "客户信息不能为空")
private Customer customer; private Customer customer;
/** /**
* *
*/ */
@Valid
private Org org; private Org org;
/** /**
@ -72,7 +77,6 @@ public class UserRegisterParam implements Constrained {
@Override @Override
public ValidRule[] rules() { public ValidRule[] rules() {
return new ValidRule[]{ return new ValidRule[]{
ValidRule.of(() -> StrUtil.isNotBlank(nickname), "用户昵称不能为空"),
ValidRule.of(() -> account != null, "账号信息不能为空"), ValidRule.of(() -> account != null, "账号信息不能为空"),
ValidRule.of(() -> !customer.getManager() || org != null, "组织信息不能为空"), ValidRule.of(() -> !customer.getManager() || org != null, "组织信息不能为空"),
}; };
@ -90,6 +94,7 @@ public class UserRegisterParam implements Constrained {
/** /**
* *
*/ */
@NotBlank(message = "账号不能为空")
private String username; private String username;
/** /**
* *
@ -98,6 +103,7 @@ public class UserRegisterParam implements Constrained {
/** /**
* *
*/ */
@NotBlank(message = "密码不能为空")
private String secret; private String secret;
/** /**
* openid * openid
@ -106,7 +112,7 @@ public class UserRegisterParam implements Constrained {
/** /**
* ; client_code * ; client_code
*/ */
private ClientCode clientCode; private Integer clientCode;
@Override @Override
public ValidRule[] rules() { public ValidRule[] rules() {
@ -115,16 +121,16 @@ public class UserRegisterParam implements Constrained {
|| (StrUtil.isNotBlank(phone) && StrUtil.isNotBlank(secret)) || (StrUtil.isNotBlank(phone) && StrUtil.isNotBlank(secret))
|| StrUtil.isNotBlank(wechatCode), "账号信息不能为空"), || StrUtil.isNotBlank(wechatCode), "账号信息不能为空"),
ValidRule.of(() -> clientCode != null, "客户端信息不能为空"), ValidRule.of(() -> clientCode != null, "客户端信息不能为空"),
ValidRule.of(() -> clientCode > 0 && ClientCode.valid(clientCode), "客户端信息无效"),
}; };
} }
} }
@Getter @Getter
@Setter @Setter
@Constraint @Constraint
@Accessors(chain = true) @Accessors(chain = true)
public static class Customer { public static class Customer implements Constrained {
private Long userId; private Long userId;
/** /**
@ -161,7 +167,7 @@ public class UserRegisterParam implements Constrained {
@Setter @Setter
@Constraint @Constraint
@Accessors(chain = true) @Accessors(chain = true)
public static class Org { public static class Org implements Constrained {
/** /**
* Id * Id
@ -194,12 +200,12 @@ public class UserRegisterParam implements Constrained {
/** /**
* *
*/ */
private LocalDateTime licenseStartTime; private LocalDate licenseStartTime;
/** /**
* *
*/ */
private LocalDateTime licenseEndTime; private LocalDate licenseEndTime;
/** /**
* *
@ -214,12 +220,14 @@ public class UserRegisterParam implements Constrained {
/** /**
* *
*/ */
private LocalDateTime idcardStartTime; @NotNull(message = "法人身份证有效期不能为空")
private LocalDate idcardStartTime;
/** /**
* *
*/ */
private LocalDateTime idcardEndTime; @NotNull(message = "法人身份证有效期不能为空")
private LocalDate idcardEndTime;
/** /**
* *

View File

@ -4,8 +4,10 @@ spring:
username: root username: root
password: admin888999 password: admin888999
security: security:
auth-ignores: auth-allows:
- /oss/** - /oss/**
- /endpoint/reload
- /permission/refresh_cache
oss: oss:
type: ali type: ali

View File

@ -1,4 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.njzscloud.dispose.cst.customer.pojo.entity.CustomerEntity"> <mapper namespace="com.njzscloud.dispose.cst.customer.mapper.CustomerMapper">
<sql id="searchCustomer">
SELECT a.id,
a.user_id,
a.identity_category,
a.org_id,
a.customer_name,
a.phone,
a.settlement_way,
a.manager,
b.nickname,
b.avatar,
c.id account_id,
c.username,
c.wechat_openid,
c.regdate,
c.client_code,
d.org_category,
d.uscc,
d.org_name,
d.business_license,
d.license_start_time,
d.license_end_time,
d.legal_representative,
d.idcard,
d.idcard_start_time,
d.idcard_end_time,
d.idcard_front,
d.idcard_back,
d.province,
d.city,
d.area,
d.town,
d.province_name,
d.city_name,
d.area_name,
d.town_name,
d.address,
d.lng,
d.lat
FROM cst_customer a
INNER JOIN sys_user b ON b.id = a.user_id AND b.deleted = 0
INNER JOIN sys_user_account c ON c.user_id = b.id AND b.deleted = 0
LEFT JOIN cst_org d ON c.id = a.org_id AND d.deleted = 0
</sql>
<resultMap id="searchCustomerResultMap" autoMapping="true" type="com.njzscloud.dispose.cst.customer.pojo.result.SearchCustomerResult">
</resultMap>
<select id="paging" resultMap="searchCustomerResultMap">
<include refid="searchCustomer"/>
<if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
${ew.customSqlSegment}
</if>
</select>
<select id="detail" resultMap="searchCustomerResultMap">
<include refid="searchCustomer"/>
WHERE a.deleted = 0
AND a.id = ${id}
</select>
</mapper> </mapper>

View File

@ -13,7 +13,6 @@
<select id="selectUser" resultMap="selectUserMap"> <select id="selectUser" resultMap="selectUserMap">
SELECT a.id account_id, SELECT a.id account_id,
a.user_id, a.user_id,
a.user_id id,
a.secret, a.secret,
b.nickname, b.nickname,
b.avatar, b.avatar,
@ -50,6 +49,7 @@
FROM sys_role a FROM sys_role a
INNER JOIN sys_user_role b ON b.role_id = a.id AND b.user_id = #{userId}) INNER JOIN sys_user_role b ON b.role_id = a.id AND b.user_id = #{userId})
WHERE a.deleted = 0 WHERE a.deleted = 0
AND a.client_code <![CDATA[ & ]]> ${client} != 0
</select> </select>
<select id="selectUserEndpoint" resultType="com.njzscloud.dispose.sys.auth.pojo.result.EndpointResource"> <select id="selectUserEndpoint" resultType="com.njzscloud.dispose.sys.auth.pojo.result.EndpointResource">
@ -65,5 +65,41 @@
FROM sys_role a FROM sys_role a
INNER JOIN sys_user_role b ON b.role_id = a.id AND b.user_id = #{userId}) INNER JOIN sys_user_role b ON b.role_id = a.id AND b.user_id = #{userId})
</select> </select>
<select id="selectUserIdentity" resultType="com.njzscloud.dispose.sys.auth.pojo.result.IdentityInfo">
SELECT a.identity_category,
a.id customer_id,
a.org_id,
a.customer_name,
a.phone,
a.settlement_way,
a.manager,
b.org_category,
b.uscc,
b.org_name,
b.business_license,
b.license_start_time,
b.license_end_time,
b.legal_representative,
b.idcard,
b.idcard_start_time,
b.idcard_end_time,
b.idcard_front,
b.idcard_back,
b.province,
b.city,
b.area,
b.town,
b.province_name,
b.city_name,
b.area_name,
b.town_name,
b.address,
b.lng,
b.lat
FROM cst_customer a
LEFT JOIN cst_org b ON b.id = a.org_id AND b.deleted = 0
WHERE a.deleted = 0
AND a.user_id = #{userId}
</select>
</mapper> </mapper>

View File

@ -19,6 +19,19 @@
a.memo a.memo
FROM sys_resource a FROM sys_resource a
INNER JOIN sys_role_resource b ON b.res_id = a.id INNER JOIN sys_role_resource b ON b.res_id = a.id
WHERE b.role_id = ${roleId} <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
${ew.customSqlSegment}
</if>
</select>
<select id="loadPermission" resultType="com.njzscloud.common.security.permission.RolePermission">
SELECT b.request_method,
b.endpoint_path endpoint,
b.access_model,
d.role_code `role`
FROM sys_resource a
INNER JOIN sys_endpoint b ON b.id = a.data_id
LEFT JOIN sys_role_resource c ON c.res_id = a.id
LEFT JOIN sys_role d ON d.id = c.role_id
WHERE a.table_name = 'sys_endpoint'
</select> </select>
</mapper> </mapper>

View File

@ -81,6 +81,11 @@
<artifactId>njzscloud-common-mvc</artifactId> <artifactId>njzscloud-common-mvc</artifactId>
<version>0.0.1</version> <version>0.0.1</version>
</dependency> </dependency>
<dependency>
<groupId>com.njzscloud</groupId>
<artifactId>njzscloud-common-cache</artifactId>
<version>0.0.1</version>
</dependency>
<dependency> <dependency>
<groupId>com.njzscloud</groupId> <groupId>com.njzscloud</groupId>
<artifactId>njzscloud-common-redis</artifactId> <artifactId>njzscloud-common-redis</artifactId>

View File

@ -5899,6 +5899,71 @@
"attr20": "", "attr20": "",
"origin": "IMPORT" "origin": "IMPORT"
}, },
{
"id": "7D98C996-2848-4BDB-9A41-27A1E3A209FD",
"defKey": "client_code",
"defName": "客户端",
"intro": "位权码",
"baseDataType": "INT",
"bizDomainType": "",
"dbDataType": "INT",
"dataLen": "",
"numScale": "",
"primaryKey": 0,
"notNull": 1,
"autoIncrement": 0,
"defaultValue": "0",
"stndDictId": "",
"stndFieldId": "",
"stndDictKey": "client_code",
"stndFieldKey": "",
"stndComplianceLevel": "",
"stndComplianceType": "",
"dictFrom": "Manual",
"dictItems": [
{
"itemKey": "0",
"itemName": "WEB 后台",
"intro": "第 0 位",
"id": "68123977-C53D-4AAA-9B8E-44CCFFF96518"
},
{
"itemKey": "1",
"itemName": "微信小程序",
"intro": "第 1 位",
"id": "0AB3C4CB-01C5-40E7-8C3C-C5EF71BC4BAC"
},
{
"itemKey": "2",
"itemName": "手机 APP",
"intro": "第 2 位",
"id": "22B26C48-0C87-442F-ABDC-D9E9D2D2DB9D"
}
],
"fieldTier": "",
"mark": null,
"attr1": "",
"attr2": "",
"attr3": "",
"attr4": "",
"attr5": "",
"attr6": "",
"attr7": "",
"attr8": "",
"attr9": "",
"attr10": "",
"attr11": "",
"attr12": "",
"attr13": "",
"attr14": "",
"attr15": "",
"attr16": "",
"attr17": "",
"attr18": "PDManer",
"attr19": "68EE2E5E-F775-458D-8686-B8834995C062",
"attr20": "",
"origin": "UI"
},
{ {
"id": "887EF609-A47C-45A4-942C-8AA5DA81AD76", "id": "887EF609-A47C-45A4-942C-8AA5DA81AD76",
"defKey": "sn", "defKey": "sn",
@ -6240,9 +6305,9 @@
"dataLen": 1, "dataLen": 1,
"numScale": "", "numScale": "",
"primaryKey": 0, "primaryKey": 0,
"notNull": 0, "notNull": 1,
"autoIncrement": 0, "autoIncrement": 0,
"defaultValue": "", "defaultValue": "0",
"stndDictId": "", "stndDictId": "",
"stndDictKey": "", "stndDictKey": "",
"stndFieldId": "", "stndFieldId": "",
@ -6324,9 +6389,9 @@
"dataLen": 128, "dataLen": 128,
"numScale": "", "numScale": "",
"primaryKey": 0, "primaryKey": 0,
"notNull": 0, "notNull": 1,
"autoIncrement": 0, "autoIncrement": 0,
"defaultValue": "", "defaultValue": "''",
"stndDictId": "", "stndDictId": "",
"stndDictKey": "", "stndDictKey": "",
"stndFieldId": "", "stndFieldId": "",
@ -6366,9 +6431,9 @@
"dataLen": 255, "dataLen": 255,
"numScale": "", "numScale": "",
"primaryKey": 0, "primaryKey": 0,
"notNull": 0, "notNull": 1,
"autoIncrement": 0, "autoIncrement": 0,
"defaultValue": "", "defaultValue": "''",
"stndDictId": "", "stndDictId": "",
"stndFieldId": "", "stndFieldId": "",
"stndDictKey": "", "stndDictKey": "",
@ -22933,9 +22998,9 @@
"defKey": "license_start_time", "defKey": "license_start_time",
"defName": "营业执照有效期", "defName": "营业执照有效期",
"intro": null, "intro": null,
"baseDataType": "DATETIME", "baseDataType": "DATE",
"bizDomainType": "", "bizDomainType": "",
"dbDataType": "DATETIME", "dbDataType": "DATE",
"dataLen": null, "dataLen": null,
"numScale": null, "numScale": null,
"primaryKey": 0, "primaryKey": 0,
@ -22979,9 +23044,9 @@
"defKey": "license_end_time", "defKey": "license_end_time",
"defName": "营业执照有效期", "defName": "营业执照有效期",
"intro": null, "intro": null,
"baseDataType": "DATETIME", "baseDataType": "DATE",
"bizDomainType": "", "bizDomainType": "",
"dbDataType": "DATETIME", "dbDataType": "DATE",
"dataLen": null, "dataLen": null,
"numScale": null, "numScale": null,
"primaryKey": 0, "primaryKey": 0,
@ -23117,9 +23182,9 @@
"defKey": "idcard_start_time", "defKey": "idcard_start_time",
"defName": "法人身份证有效期", "defName": "法人身份证有效期",
"intro": null, "intro": null,
"baseDataType": "DATETIME", "baseDataType": "DATE",
"bizDomainType": "", "bizDomainType": "",
"dbDataType": "DATETIME", "dbDataType": "DATE",
"dataLen": "", "dataLen": "",
"numScale": null, "numScale": null,
"primaryKey": 0, "primaryKey": 0,
@ -23163,9 +23228,9 @@
"defKey": "idcard_end_time", "defKey": "idcard_end_time",
"defName": "法人身份证有效期", "defName": "法人身份证有效期",
"intro": null, "intro": null,
"baseDataType": "DATETIME", "baseDataType": "DATE",
"bizDomainType": "", "bizDomainType": "",
"dbDataType": "DATETIME", "dbDataType": "DATE",
"dataLen": "", "dataLen": "",
"numScale": null, "numScale": null,
"primaryKey": 0, "primaryKey": 0,
@ -42968,7 +43033,7 @@
"readonly": false, "readonly": false,
"allowWs": false "allowWs": false
}, },
"updateTime": 1765359635412, "updateTime": 1765434816305,
"signature": "e1b11ecff62865e7eb000c6c88e1e638", "signature": "f39d1018f0ed556230f3489a43a16da7",
"branchId": "1111" "branchId": "1111"
} }