924a8158 by lv

框架变更

1 parent 8174f2d0
Showing 1000 changed files with 4538 additions and 0 deletions

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

1 # http://editorconfig.org
2 root = true
3
4 # 空格替代Tab缩进在各种编辑工具下效果一致
5 [*]
6 indent_style = space
7 indent_size = 4
8 charset = utf-8
9 end_of_line = lf
10 trim_trailing_whitespace = true
11 insert_final_newline = true
12
13 [*.java]
14 indent_style = tab
15
16 [*.{json,yml}]
17 indent_size = 2
18
19 [*.md]
20 insert_final_newline = false
21 trim_trailing_whitespace = false
1 # maven #
2 target
3
4 logs
5
6 # windows #
7 Thumbs.db
8
9 # Mac #
10 .DS_Store
11
12 # eclipse #
13 .settings
14 .project
15 .classpath
16 .log
17 *.class
18
19 # idea #
20 .idea
21 *.iml
22
23 # Package Files #
24 *.jar
25 *.war
26 *.ear
27 /target
1 #Californium CoAP Properties file
2 #Tue Oct 08 10:11:32 CST 2019
3 HTTP_SERVER_SOCKET_BUFFER_SIZE=8192
4 UDP_CONNECTOR_OUT_CAPACITY=2147483647
5 CONGESTION_CONTROL_ALGORITHM=Cocoa
6 USE_CONGESTION_CONTROL=false
7 ACK_TIMEOUT=2000
8 MAX_ACTIVE_PEERS=150000
9 TCP_CONNECT_TIMEOUT=10000
10 NOTIFICATION_CHECK_INTERVAL_COUNT=100
11 MAX_MESSAGE_SIZE=1024
12 MID_TRACKER_GROUPS=16
13 DEDUPLICATOR=DEDUPLICATOR_MARK_AND_SWEEP
14 TCP_CONNECTION_IDLE_TIMEOUT=10
15 COAP_PORT=5683
16 ACK_TIMEOUT_SCALE=2.0
17 PREFERRED_BLOCK_SIZE=512
18 NETWORK_STAGE_RECEIVER_THREAD_COUNT=1
19 DTLS_AUTO_RESUME_TIMEOUT=30000
20 DTLS_RESPONSE_MATCHING=STRICT
21 PROTOCOL_STAGE_THREAD_COUNT=4
22 MAX_TRANSMIT_WAIT=93000
23 UDP_CONNECTOR_RECEIVE_BUFFER=0
24 EXCHANGE_LIFETIME=247000
25 HTTP_SERVER_SOCKET_TIMEOUT=100000
26 CROP_ROTATION_PERIOD=2000
27 UDP_CONNECTOR_DATAGRAM_SIZE=2048
28 MAX_RETRANSMIT=4
29 MAX_PEER_INACTIVITY_PERIOD=600
30 MAX_RESOURCE_BODY_SIZE=8192
31 NOTIFICATION_CHECK_INTERVAL=86400000
32 LEISURE=5000
33 HTTP_CACHE_RESPONSE_MAX_AGE=86400
34 BLOCKWISE_STATUS_LIFETIME=300000
35 UDP_CONNECTOR_SEND_BUFFER=0
36 MID_TACKER=GROUPED
37 TCP_WORKER_THREADS=1
38 NETWORK_STAGE_SENDER_THREAD_COUNT=1
39 NON_LIFETIME=145000
40 TOKEN_SIZE_LIMIT=8
41 HTTP_PORT=8080
42 MARK_AND_SWEEP_INTERVAL=10000
43 HEALTH_STATUS_INTERVAL=60
44 ACK_RANDOM_FACTOR=1.5
45 SECURE_SESSION_TIMEOUT=86400
46 NSTART=1
47 USE_RANDOM_MID_START=true
48 HTTP_CACHE_SIZE=32
49 PROBING_RATE=1.0
50 NOTIFICATION_REREGISTRATION_BACKOFF=2000
51 COAP_SECURE_PORT=5684
1 FROM anapsix/alpine-java:8_server-jre_unlimited
2
3 MAINTAINER smallchill@163.com
4
5 RUN mkdir -p /blade/auth
6
7 WORKDIR /blade/auth
8
9 EXPOSE 8010
10
11 ADD ./target/blade-auth.jar ./app.jar
12
13 ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
14
15 CMD ["--spring.profiles.active=test"]
1 ## 目前主要支持的oauth协议
2 一、 授权码模式
3 授权码模式(authorization_code)主要针对第三方应用,是最为复杂也最为安全的一种模式,操作步骤如下
4 1. 访问地址:http://localhost:8100/oauth/authorize?client_id=blade&redirect_uri=http://example.com&code=233333&response_type=code
5 2. 获取跳转后的code值(http://example.com/?code=VhYNLR)之后,调用 http://localhost/blade-auth/oauth/token 传入对应的参数
6
7 请求头:
8 Authorization : Basic YmxhZGU6YmxhZGU= ("YmxhZGU6YmxhZGU="为clientId:clientSecret串转换为的base64编码)
9
10 表单:
11 grant_type:authorization_code
12 scope:all
13 code:VhYNLR
14 redirect_uri: http://example.com
15
16 二、 密码模式
17 密码模式(password)主要针对自家应用,可信度较高,所以可以使用简便安全共存的模式,操作步骤如下
18 1. 直接调用 http://localhost/blade-auth/oauth/token 传入对应的参数
19
20 请求头:
21 Authorization : Basic YmxhZGU6YmxhZGU= ("YmxhZGU6YmxhZGU="为clientId:clientSecret串转换为的base64编码)
22
23 表单:
24 grant_type:password
25 scope:all
26 username:admin
27 password:123456
28
29 ## 获取到token后如何获取用户信息
30 1. 拼接请求头
31 Authorization :bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0ZXN0IjoidGVzdCIsInVzZXJfbmFtZSI6ImFkbWluIiwic2NvcGUiOlsiYWxsIl0sImV4cCI6MTU1MzE2MTA5NSwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjE0YmMyYjAyLTgxY2UtNDFiNC04ZTI3LTA5YWE0ZmU4ZWMwYyIsImNsaWVudF9pZCI6ImJsYWRlIn0.jTmioQDq-fSNNn7YCwl3wP0JE-etSWtzLDe545mDbP4
32 2. 调用 http://localhost/blade-auth/oauth/user-info 既可获得对应用户信息
...\ No newline at end of file ...\ No newline at end of file
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
6 <modelVersion>4.0.0</modelVersion>
7
8 <parent>
9 <artifactId>BladeX</artifactId>
10 <groupId>org.springblade</groupId>
11 <version>2.0.0.RELEASE</version>
12 </parent>
13
14 <artifactId>blade-auth</artifactId>
15 <name>${project.artifactId}</name>
16 <version>${bladex.project.version}</version>
17 <packaging>jar</packaging>
18
19 <dependencies>
20 <!--Blade-->
21 <dependency>
22 <groupId>org.springblade</groupId>
23 <artifactId>blade-common</artifactId>
24 <version>${bladex.project.version}</version>
25 </dependency>
26 <dependency>
27 <groupId>org.springblade</groupId>
28 <artifactId>blade-core-cloud</artifactId>
29 <version>${bladex.tool.version}</version>
30 <exclusions>
31 <exclusion>
32 <groupId>org.springblade</groupId>
33 <artifactId>blade-core-secure</artifactId>
34 </exclusion>
35 </exclusions>
36 </dependency>
37 <dependency>
38 <groupId>org.springblade</groupId>
39 <artifactId>blade-user-api</artifactId>
40 <version>${bladex.project.version}</version>
41 <exclusions>
42 <exclusion>
43 <groupId>org.springblade</groupId>
44 <artifactId>blade-core-secure</artifactId>
45 </exclusion>
46 </exclusions>
47 </dependency>
48 <dependency>
49 <groupId>org.springblade</groupId>
50 <artifactId>blade-system-api</artifactId>
51 <version>${bladex.project.version}</version>
52 <exclusions>
53 <exclusion>
54 <groupId>org.springblade</groupId>
55 <artifactId>blade-core-secure</artifactId>
56 </exclusion>
57 </exclusions>
58 </dependency>
59 <dependency>
60 <groupId>org.springblade</groupId>
61 <artifactId>blade-starter-swagger</artifactId>
62 <version>${bladex.tool.version}</version>
63 </dependency>
64 <dependency>
65 <groupId>org.springframework.cloud</groupId>
66 <artifactId>spring-cloud-starter-security</artifactId>
67 </dependency>
68 <dependency>
69 <groupId>org.springframework.security.oauth.boot</groupId>
70 <artifactId>spring-security-oauth2-autoconfigure</artifactId>
71 <version>2.1.3.RELEASE</version>
72 </dependency>
73 <dependency>
74 <groupId>org.springframework.boot</groupId>
75 <artifactId>spring-boot-starter-jdbc</artifactId>
76 <exclusions>
77 <exclusion>
78 <artifactId>tomcat-jdbc</artifactId>
79 <groupId>org.apache.tomcat</groupId>
80 </exclusion>
81 </exclusions>
82 </dependency>
83 <dependency>
84 <groupId>org.springframework.boot</groupId>
85 <artifactId>spring-boot-starter-data-redis</artifactId>
86 </dependency>
87 <dependency>
88 <groupId>org.springframework.security</groupId>
89 <artifactId>spring-security-jwt</artifactId>
90 </dependency>
91 <dependency>
92 <groupId>io.jsonwebtoken</groupId>
93 <artifactId>jjwt</artifactId>
94 <version>0.9.1</version>
95 </dependency>
96 <!-- MySQL -->
97 <dependency>
98 <groupId>mysql</groupId>
99 <artifactId>mysql-connector-java</artifactId>
100 <version>8.0.15</version>
101 </dependency>
102 </dependencies>
103
104 <build>
105 <plugins>
106 <plugin>
107 <groupId>com.spotify</groupId>
108 <artifactId>docker-maven-plugin</artifactId>
109 <version>${docker.plugin.version}</version>
110 <configuration>
111 <imageName>${docker.registry.url}/blade/${project.artifactId}:${project.version}</imageName>
112 <dockerDirectory>${project.basedir}</dockerDirectory>
113 <dockerHost>${docker.registry.host}</dockerHost>
114 <resources>
115 <resource>
116 <targetPath>/</targetPath>
117 <directory>${project.build.directory}</directory>
118 <include>${project.build.finalName}.jar</include>
119 </resource>
120 </resources>
121 <registryUrl>${docker.registry.url}</registryUrl>
122 <serverId>${docker.registry.url}</serverId>
123 <pushImage>true</pushImage>
124 </configuration>
125 </plugin>
126 <plugin>
127 <groupId>org.apache.maven.plugins</groupId>
128 <artifactId>maven-antrun-plugin</artifactId>
129 <executions>
130 <execution>
131 <phase>package</phase>
132 <goals>
133 <goal>run</goal>
134 </goals>
135 <configuration>
136 <tasks>
137 <copy overwrite="true"
138 tofile="${session.executionRootDirectory}/target/${project.artifactId}.jar"
139 file="${project.build.directory}/${project.artifactId}.jar" />
140 </tasks>
141 </configuration>
142 </execution>
143 </executions>
144 </plugin>
145 </plugins>
146 </build>
147
148 </project>
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth;
18
19
20 import org.springblade.core.cloud.feign.EnableBladeFeign;
21 import org.springblade.core.launch.BladeApplication;
22 import org.springblade.core.launch.constant.AppConstant;
23 import org.springframework.cloud.client.SpringCloudApplication;
24
25 /**
26 * 用户认证服务器
27 *
28 * @author Chill
29 */
30 @EnableBladeFeign
31 @SpringCloudApplication
32 public class AuthApplication {
33
34 public static void main(String[] args) {
35 BladeApplication.run(AppConstant.APPLICATION_AUTH_NAME, AuthApplication.class, args);
36 }
37
38 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.config;
18
19 import lombok.AllArgsConstructor;
20 import lombok.SneakyThrows;
21 import org.springblade.auth.constant.AuthConstant;
22 import org.springblade.auth.service.BladeClientDetailsServiceImpl;
23 import org.springframework.context.annotation.Configuration;
24 import org.springframework.core.annotation.Order;
25 import org.springframework.security.authentication.AuthenticationManager;
26 import org.springframework.security.core.userdetails.UserDetailsService;
27 import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
28 import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
29 import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
30 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
31 import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
32 import org.springframework.security.oauth2.provider.token.TokenEnhancer;
33 import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
34 import org.springframework.security.oauth2.provider.token.TokenStore;
35 import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
36
37 import javax.sql.DataSource;
38 import java.util.ArrayList;
39 import java.util.List;
40
41 /**
42 * 认证服务器配置
43 *
44 * @author Chill
45 */
46 @Order
47 @Configuration
48 @AllArgsConstructor
49 @EnableAuthorizationServer
50 public class BladeAuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
51
52 private final DataSource dataSource;
53
54 private AuthenticationManager authenticationManager;
55
56 private UserDetailsService userDetailsService;
57
58 private TokenStore tokenStore;
59
60 private JwtAccessTokenConverter jwtAccessTokenConverter;
61
62 private TokenEnhancer jwtTokenEnhancer;
63
64 @Override
65 public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
66 endpoints.tokenStore(tokenStore)
67 .authenticationManager(authenticationManager)
68 .userDetailsService(userDetailsService);
69 //扩展token返回结果
70 if (jwtAccessTokenConverter != null && jwtTokenEnhancer != null) {
71 TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
72 List<TokenEnhancer> enhancerList = new ArrayList<>();
73 enhancerList.add(jwtTokenEnhancer);
74 enhancerList.add(jwtAccessTokenConverter);
75 tokenEnhancerChain.setTokenEnhancers(enhancerList);
76 //jwt
77 endpoints.tokenEnhancer(tokenEnhancerChain)
78 .accessTokenConverter(jwtAccessTokenConverter);
79 }
80 }
81
82 /**
83 * 配置客户端信息
84 */
85 @Override
86 @SneakyThrows
87 public void configure(ClientDetailsServiceConfigurer clients) {
88 BladeClientDetailsServiceImpl clientDetailsService = new BladeClientDetailsServiceImpl(dataSource);
89 clientDetailsService.setSelectClientDetailsSql(AuthConstant.DEFAULT_SELECT_STATEMENT);
90 clientDetailsService.setFindClientDetailsSql(AuthConstant.DEFAULT_FIND_STATEMENT);
91 clients.withClientDetails(clientDetailsService);
92 }
93
94 @Override
95 public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
96 oauthServer
97 .allowFormAuthenticationForClients()
98 .tokenKeyAccess("permitAll()")
99 .checkTokenAccess("isAuthenticated()");
100 }
101 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.config;
18
19 import lombok.AllArgsConstructor;
20 import lombok.SneakyThrows;
21 import org.springframework.context.annotation.Configuration;
22 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
23 import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
24 import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
25 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
26
27 /**
28 * 自定义登录成功配置
29 *
30 * @author Chill
31 */
32 @Configuration
33 @AllArgsConstructor
34 @EnableResourceServer
35 public class BladeResourceServerConfiguration extends ResourceServerConfigurerAdapter {
36
37 /**
38 * 自定义登录成功处理器
39 */
40 private AuthenticationSuccessHandler appLoginInSuccessHandler;
41
42 @Override
43 @SneakyThrows
44 public void configure(HttpSecurity http) {
45 http.headers().frameOptions().disable();
46 http.formLogin()
47 .successHandler(appLoginInSuccessHandler)
48 .and()
49 .authorizeRequests()
50 .antMatchers("/actuator/**", "/token/**", "/mobile/**", "/v2/api-docs", "/v2/api-docs-ext").permitAll()
51 .anyRequest().authenticated().and()
52 .csrf().disable();
53 }
54
55 }
1 //package org.springblade.auth.config;
2 //
3 //import org.springblade.core.tool.api.R;
4 //import org.springframework.security.core.AuthenticationException;
5 //import org.springframework.security.web.AuthenticationEntryPoint;
6 //import org.springframework.stereotype.Component;
7 //
8 //import javax.servlet.http.HttpServletRequest;
9 //import javax.servlet.http.HttpServletResponse;
10 //import java.io.IOException;
11 //import java.io.PrintWriter;
12 //import java.io.Serializable;
13 //
14 ///**
15 // * @author: JoeTao
16 // * createAt: 2018/9/20
17 // */
18 //@Component
19 //public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
20 //
21 // private static final long serialVersionUID = -8970718410437077606L;
22 //
23 // @Override
24 // public void commence(HttpServletRequest request,
25 // HttpServletResponse response,
26 // AuthenticationException authException) throws IOException {
27 // //验证为未登陆状态会进入此方法,认证错误
28 // System.out.println("认证失败:" + authException.getMessage());
29 // response.setStatus(200);
30 // response.setCharacterEncoding("UTF-8");
31 // response.setContentType("application/json; charset=utf-8");
32 // PrintWriter printWriter = response.getWriter();
33 // String body = R.fail(401, "认证失败").toString();
34 // printWriter.write(body);
35 // printWriter.flush();
36 // }
37 //}
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.config;
18
19 import org.springblade.auth.support.BladeJwtTokenEnhancer;
20 import org.springblade.core.launch.constant.TokenConstant;
21 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
22 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
23 import org.springframework.context.annotation.Bean;
24 import org.springframework.context.annotation.Configuration;
25 import org.springframework.security.oauth2.provider.token.TokenEnhancer;
26 import org.springframework.security.oauth2.provider.token.TokenStore;
27 import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
28 import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
29
30 /**
31 * JwtTokenStore
32 *
33 * @author Chill
34 */
35 @Configuration
36 @ConditionalOnProperty(prefix = "blade.security.oauth2", name = "storeType", havingValue = "jwt", matchIfMissing = true)
37 public class JwtTokenStoreConfiguration {
38
39 /**
40 * 使用jwtTokenStore存储token
41 */
42 @Bean
43 public TokenStore jwtTokenStore() {
44 return new JwtTokenStore(jwtAccessTokenConverter());
45 }
46
47 /**
48 * 用于生成jwt
49 */
50 @Bean
51 public JwtAccessTokenConverter jwtAccessTokenConverter() {
52 JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
53 accessTokenConverter.setSigningKey(TokenConstant.SIGN_KEY);
54 return accessTokenConverter;
55 }
56
57 /**
58 * 用于扩展jwt
59 */
60 @Bean
61 @ConditionalOnMissingBean(name = "jwtTokenEnhancer")
62 public TokenEnhancer jwtTokenEnhancer() {
63 return new BladeJwtTokenEnhancer();
64 }
65
66 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.config;
18
19 import lombok.AllArgsConstructor;
20 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
21 import org.springframework.context.annotation.Bean;
22 import org.springframework.context.annotation.Configuration;
23 import org.springframework.data.redis.connection.RedisConnectionFactory;
24 import org.springframework.security.oauth2.provider.token.TokenStore;
25 import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
26
27 /**
28 * Redis TokenStore
29 *
30 * @author Chill
31 */
32 @Configuration
33 @AllArgsConstructor
34 public class RedisTokenStoreConfiguration {
35 /**
36 * redis连接工厂
37 */
38 private RedisConnectionFactory redisConnectionFactory;
39
40 /**
41 * 用于存放token
42 */
43 @Bean
44 @ConditionalOnProperty(prefix = "blade.security.oauth2", name = "storeType", havingValue = "redis")
45 public TokenStore redisTokenStore() {
46 return new RedisTokenStore(redisConnectionFactory);
47 }
48 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.config;
18
19 import lombok.AllArgsConstructor;
20 import lombok.SneakyThrows;
21 import org.springblade.auth.support.BladePasswordEncoderFactories;
22 import org.springframework.context.annotation.Bean;
23 import org.springframework.context.annotation.Configuration;
24 import org.springframework.security.authentication.AuthenticationManager;
25 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
26 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
27 import org.springframework.security.crypto.password.PasswordEncoder;
28
29 /**
30 * Security配置
31 *
32 * @author Chill
33 */
34 @Configuration
35 @AllArgsConstructor
36 public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
37
38 @Bean
39 @Override
40 @SneakyThrows
41 public AuthenticationManager authenticationManagerBean() {
42 return super.authenticationManagerBean();
43 }
44
45 @Bean
46 public PasswordEncoder passwordEncoder() {
47 return BladePasswordEncoderFactories.createDelegatingPasswordEncoder();
48 }
49
50 @Override
51 @SneakyThrows
52 protected void configure(HttpSecurity http) {
53 http.httpBasic().and().csrf().disable();
54 }
55
56 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.constant;
18
19 /**
20 * 授权校验常量
21 *
22 * @author Chill
23 */
24 public interface AuthConstant {
25
26 /**
27 * 密码加密规则
28 */
29 String ENCRYPT = "{blade}";
30
31 /**
32 * blade_client表字段
33 */
34 String CLIENT_FIELDS = "client_id, CONCAT('{noop}',client_secret) as client_secret, resource_ids, scope, authorized_grant_types, " +
35 "web_server_redirect_uri, authorities, access_token_validity, " +
36 "refresh_token_validity, additional_information, autoapprove";
37
38 /**
39 * blade_client查询语句
40 */
41 String BASE_STATEMENT = "select " + CLIENT_FIELDS + " from blade_client";
42
43 /**
44 * blade_client查询排序
45 */
46 String DEFAULT_FIND_STATEMENT = BASE_STATEMENT + " order by client_id";
47
48 /**
49 * 查询client_id
50 */
51 String DEFAULT_SELECT_STATEMENT = BASE_STATEMENT + " where client_id = ?";
52
53 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.endpoint;
18
19 import lombok.AllArgsConstructor;
20 import lombok.extern.slf4j.Slf4j;
21 import org.springblade.core.tool.api.R;
22 import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.beans.factory.annotation.Qualifier;
24 import org.springframework.security.core.Authentication;
25 import org.springframework.security.oauth2.provider.endpoint.FrameworkEndpoint;
26 import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
27 import org.springframework.web.bind.annotation.*;
28
29 /**
30 * BladeEndPoint
31 *
32 * @author Chill
33 */
34 @Slf4j
35 @RestController
36 @AllArgsConstructor
37 @FrameworkEndpoint
38 public class BladeTokenEndPoint {
39
40 @GetMapping("/oauth/user-info")
41 public R<Authentication> currentUser(Authentication authentication) {
42 return R.data(authentication);
43 }
44
45 @Autowired
46 ConsumerTokenServices consumerTokenServices;
47
48 @RequestMapping(method = RequestMethod.DELETE, value = "/oauth/token/delete")
49 @ResponseBody
50 public String revokeToken(String access_token) {
51 if (consumerTokenServices.revokeToken(access_token)){
52 return "注销成功";
53 }else{
54 return "注销失败";
55 }
56 }
57
58
59
60
61
62 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.handler;
18
19 import lombok.AllArgsConstructor;
20 import lombok.extern.slf4j.Slf4j;
21 import org.springblade.auth.utils.TokenUtil;
22 import org.springblade.core.tool.jackson.JsonUtil;
23 import org.springframework.http.MediaType;
24 import org.springframework.security.core.Authentication;
25 import org.springframework.security.crypto.password.PasswordEncoder;
26 import org.springframework.security.oauth2.common.OAuth2AccessToken;
27 import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
28 import org.springframework.security.oauth2.provider.*;
29 import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
30 import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
31 import org.springframework.stereotype.Component;
32
33 import javax.servlet.ServletException;
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpServletResponse;
36 import java.io.IOException;
37 import java.util.HashMap;
38
39 /**
40 * APP登录成功处理器
41 *
42 * @author Chill
43 */
44 @Slf4j
45 @AllArgsConstructor
46 @Component("appLoginInSuccessHandler")
47 public class AppLoginInSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
48
49 private PasswordEncoder passwordEncoder;
50
51 private ClientDetailsService clientDetailsService;
52
53 private AuthorizationServerTokenServices authorizationServerTokenServices;
54
55 @Override
56 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
57 log.info("【AppLoginInSuccessHandler】 onAuthenticationSuccess authentication={}", authentication);
58
59 String[] tokens = TokenUtil.extractAndDecodeHeader();
60 assert tokens.length == 2;
61 String clientId = tokens[0];
62 String clientSecret = tokens[1];
63
64 ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
65 if (clientDetails == null) {
66 throw new UnapprovedClientAuthenticationException("clientId 对应的配置信息不存在" + clientId);
67 } else if (!passwordEncoder.matches(clientSecret, clientDetails.getClientSecret())) {
68 throw new UnapprovedClientAuthenticationException("clientSecret 不匹配" + clientId);
69 }
70
71 TokenRequest tokenRequest = new TokenRequest(new HashMap<>(16), clientId, clientDetails.getScope(), "app");
72 OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
73 OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
74 OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
75
76 response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
77 response.getWriter().write(JsonUtil.toJson(token));
78 }
79
80 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.service;
18
19 import lombok.SneakyThrows;
20 import org.springframework.security.oauth2.provider.ClientDetails;
21 import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
22
23 import javax.sql.DataSource;
24
25 /**
26 * 客户端信息
27 *
28 * @author Chill
29 */
30 public class BladeClientDetailsServiceImpl extends JdbcClientDetailsService {
31
32 public BladeClientDetailsServiceImpl(DataSource dataSource) {
33 super(dataSource);
34 }
35
36 /**
37 * 缓存客户端信息
38 *
39 * @param clientId 客户端id
40 */
41 @Override
42 @SneakyThrows
43 public ClientDetails loadClientByClientId(String clientId) {
44 return super.loadClientByClientId(clientId);
45 }
46 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.service;
18
19 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
20 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
21 import lombok.Getter;
22 import org.springframework.security.core.GrantedAuthority;
23 import org.springframework.security.core.userdetails.User;
24
25 import java.util.Collection;
26
27 /**
28 * 用户信息拓展
29 *
30 * @author Chill
31 */
32 @Getter
33 public class BladeUserDetails extends User {
34
35 /**
36 * 用户id
37 */
38 @JsonSerialize(using = ToStringSerializer.class)
39 private Long userId;
40 /**
41 * 租户编号
42 */
43 private String tenantCode;
44 /**
45 * 昵称
46 */
47 private String name;
48 /**
49 * 账号
50 */
51 private String account;
52 /**
53 * 角色id
54 */
55 private String roleId;
56 /**
57 * 角色名
58 */
59 private String roleName;
60 /**
61 * 头像
62 */
63 private String avatar;
64
65 private Integer type;
66
67 BladeUserDetails(Long userId, String tenantCode, String name, String roleId, String roleName, String avatar, String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities,Integer type) {
68 super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
69 this.userId = userId;
70 this.tenantCode = tenantCode;
71 this.name = name;
72 this.account = username;
73 this.roleId = roleId;
74 this.roleName = roleName;
75 this.avatar = avatar;
76 this.type=type;
77 }
78
79 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.service;
18
19 import lombok.AllArgsConstructor;
20 import lombok.SneakyThrows;
21 import org.springblade.auth.constant.AuthConstant;
22 import org.springblade.auth.utils.TokenUtil;
23 import org.springblade.core.tool.api.R;
24 import org.springblade.core.tool.utils.Func;
25 import org.springblade.core.tool.utils.WebUtil;
26 import org.springblade.system.user.entity.User;
27 import org.springblade.system.user.entity.UserInfo;
28 import org.springblade.system.user.feign.IUserClient;
29 import org.springframework.security.core.authority.AuthorityUtils;
30 import org.springframework.security.core.userdetails.UserDetails;
31 import org.springframework.security.core.userdetails.UserDetailsService;
32 import org.springframework.security.core.userdetails.UsernameNotFoundException;
33 import org.springframework.stereotype.Service;
34
35 import javax.servlet.http.HttpServletRequest;
36
37 /**
38 * 用户信息
39 *
40 * @author Chill
41 */
42 @Service
43 @AllArgsConstructor
44 public class BladeUserDetailsServiceImpl implements UserDetailsService {
45
46 private IUserClient userClient;
47
48 @Override
49 @SneakyThrows
50 public UserDetails loadUserByUsername(String username) {
51 HttpServletRequest request = WebUtil.getRequest();
52 String tenantCode = Func.toStr(request.getHeader(TokenUtil.TENANT_HEADER_KEY), TokenUtil.DEFAULT_TENANT_CODE);
53 R<UserInfo> result = userClient.userInfo(tenantCode, username);
54 if (result.isSuccess()) {
55 User user = result.getData().getUser();
56 if (user == null) {
57 throw new UsernameNotFoundException(TokenUtil.USER_NOT_FOUND);
58 }
59 return new BladeUserDetails(user.getId(),
60 user.getTenantCode(), user.getName(), user.getRoleId(), Func.join(result.getData().getRoles()), TokenUtil.DEFAULT_AVATAR,
61 username, AuthConstant.ENCRYPT + user.getPassword(), true, true, true, true,
62 AuthorityUtils.commaSeparatedStringToAuthorityList(Func.join(result.getData().getRoles())),user.getType());
63 } else {
64 throw new UsernameNotFoundException(result.getMsg());
65 }
66 }
67
68 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.support;
18
19 import org.springblade.auth.service.BladeUserDetails;
20 import org.springblade.auth.utils.TokenUtil;
21 import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
22 import org.springframework.security.oauth2.common.OAuth2AccessToken;
23 import org.springframework.security.oauth2.provider.OAuth2Authentication;
24 import org.springframework.security.oauth2.provider.token.TokenEnhancer;
25
26 import java.util.HashMap;
27 import java.util.Map;
28
29 /**
30 * jwt返回参数增强
31 *
32 * @author Chill
33 */
34 public class BladeJwtTokenEnhancer implements TokenEnhancer {
35 @Override
36 public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
37 BladeUserDetails principal = (BladeUserDetails) authentication.getUserAuthentication().getPrincipal();
38 Map<String, Object> info = new HashMap<>(16);
39 info.put(TokenUtil.CLIENT_ID, TokenUtil.getClientIdFromHeader());
40 info.put(TokenUtil.USER_ID, principal.getUserId());
41 info.put(TokenUtil.ROLE_ID, principal.getRoleId());
42 info.put(TokenUtil.TENANT_CODE, principal.getTenantCode());
43 info.put(TokenUtil.ACCOUNT, principal.getAccount());
44 info.put(TokenUtil.USER_NAME, principal.getUsername());
45 info.put(TokenUtil.NICK_NAME, principal.getName());
46 info.put(TokenUtil.ROLE_NAME, principal.getRoleName());
47 info.put(TokenUtil.AVATAR, principal.getAvatar());
48 info.put(TokenUtil.LICENSE, TokenUtil.LICENSE_NAME);
49 ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);
50 return accessToken;
51 }
52 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.support;
18
19 import org.springframework.security.crypto.password.PasswordEncoder;
20
21 /**
22 * 无密码加密
23 *
24 * @author Chill
25 */
26 public class BladeNoOpPasswordEncoder implements PasswordEncoder {
27
28 @Override
29 public String encode(CharSequence rawPassword) {
30 return rawPassword.toString();
31 }
32
33 @Override
34 public boolean matches(CharSequence rawPassword, String encodedPassword) {
35 return rawPassword.toString().equals(encodedPassword);
36 }
37
38 /**
39 * Get the singleton {@link BladeNoOpPasswordEncoder}.
40 */
41 public static PasswordEncoder getInstance() {
42 return INSTANCE;
43 }
44
45 private static final PasswordEncoder INSTANCE = new BladeNoOpPasswordEncoder();
46
47 private BladeNoOpPasswordEncoder() {
48 }
49
50 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.support;
18
19 import org.springblade.core.tool.utils.DigestUtil;
20 import org.springframework.security.crypto.password.PasswordEncoder;
21
22 /**
23 * 自定义密码加密
24 *
25 * @author Chill
26 */
27 public class BladePasswordEncoder implements PasswordEncoder {
28
29 @Override
30 public String encode(CharSequence rawPassword) {
31 return DigestUtil.encrypt((String) rawPassword);
32 }
33
34 @Override
35 public boolean matches(CharSequence rawPassword, String encodedPassword) {
36 return encodedPassword.equals(encode(rawPassword));
37 }
38
39 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.support;
18
19 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
20 import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
21 import org.springframework.security.crypto.password.PasswordEncoder;
22 import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
23 import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
24
25 import java.util.HashMap;
26 import java.util.Map;
27
28 /**
29 * 自定义密码工厂
30 *
31 * @author Chill
32 */
33 public class BladePasswordEncoderFactories {
34
35 /**
36 * Creates a {@link DelegatingPasswordEncoder} with default mappings. Additional
37 * mappings may be added and the encoding will be updated to conform with best
38 * practices. However, due to the nature of {@link DelegatingPasswordEncoder} the
39 * updates should not impact users. The mappings current are:
40 *
41 * <ul>
42 * <li>blade - {@link BladePasswordEncoder} (sha1(md5("password")))</li>
43 * <li>bcrypt - {@link BCryptPasswordEncoder} (Also used for encoding)</li>
44 * <li>noop - {@link BladeNoOpPasswordEncoder}</li>
45 * <li>pbkdf2 - {@link Pbkdf2PasswordEncoder}</li>
46 * <li>scrypt - {@link SCryptPasswordEncoder}</li>
47 * </ul>
48 *
49 * @return the {@link PasswordEncoder} to use
50 */
51 @SuppressWarnings("deprecation")
52 public static PasswordEncoder createDelegatingPasswordEncoder() {
53 String encodingId = "blade";
54 Map<String, PasswordEncoder> encoders = new HashMap<>(16);
55 encoders.put(encodingId, new BladePasswordEncoder());
56 encoders.put("bcrypt", new BCryptPasswordEncoder());
57 encoders.put("noop", BladeNoOpPasswordEncoder.getInstance());
58 encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
59 encoders.put("scrypt", new SCryptPasswordEncoder());
60
61 return new DelegatingPasswordEncoder(encodingId, encoders);
62 }
63
64 private BladePasswordEncoderFactories() {
65 }
66
67 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.auth.utils;
18
19 import lombok.SneakyThrows;
20 import org.springblade.core.launch.constant.TokenConstant;
21 import org.springblade.core.tool.utils.Charsets;
22 import org.springblade.core.tool.utils.StringPool;
23 import org.springblade.core.tool.utils.WebUtil;
24 import org.springframework.security.authentication.BadCredentialsException;
25 import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
26
27 import java.util.Base64;
28 import java.util.Calendar;
29
30 /**
31 * 认证工具类
32 *
33 * @author Chill
34 */
35 public class TokenUtil {
36
37 public final static String AVATAR = TokenConstant.AVATAR;
38 public final static String ACCOUNT = TokenConstant.ACCOUNT;
39 public final static String USER_NAME = TokenConstant.USER_NAME;
40 public final static String NICK_NAME = TokenConstant.NICK_NAME;
41 public final static String USER_ID = TokenConstant.USER_ID;
42 public final static String ROLE_ID = TokenConstant.ROLE_ID;
43 public final static String ROLE_NAME = TokenConstant.ROLE_NAME;
44 public final static String TENANT_CODE = TokenConstant.TENANT_CODE;
45 public final static String CLIENT_ID = TokenConstant.CLIENT_ID;
46 public final static String LICENSE = TokenConstant.LICENSE;
47 public final static String LICENSE_NAME = TokenConstant.LICENSE_NAME;
48
49
50 public final static String TENANT_HEADER_KEY = "Tenant-Code";
51 public final static String DEFAULT_TENANT_CODE = "000000";
52 public final static String USER_NOT_FOUND = "用户名或密码错误";
53 public final static String HEADER_KEY = "Authorization";
54 public final static String HEADER_PREFIX = "Basic ";
55 public final static String DEFAULT_AVATAR = "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png";
56
57 /**
58 * 解码
59 */
60 @SneakyThrows
61 public static String[] extractAndDecodeHeader() {
62 String header = WebUtil.getRequest().getHeader(TokenUtil.HEADER_KEY);
63 if (header == null || !header.startsWith(TokenUtil.HEADER_PREFIX)) {
64 throw new UnapprovedClientAuthenticationException("请求头中无client信息");
65 }
66
67 byte[] base64Token = header.substring(6).getBytes(Charsets.UTF_8_NAME);
68
69 byte[] decoded;
70 try {
71 decoded = Base64.getDecoder().decode(base64Token);
72 } catch (IllegalArgumentException var7) {
73 throw new BadCredentialsException("Failed to decode basic authentication token");
74 }
75
76 String token = new String(decoded, Charsets.UTF_8_NAME);
77 int index = token.indexOf(StringPool.COLON);
78 if (index == -1) {
79 throw new BadCredentialsException("Invalid basic authentication token");
80 } else {
81 return new String[]{token.substring(0, index), token.substring(index + 1)};
82 }
83 }
84
85 /**
86 * 获取请求头中的客户端id
87 */
88 public static String getClientIdFromHeader() {
89 String[] tokens = extractAndDecodeHeader();
90 assert tokens.length == 2;
91 return tokens[0];
92 }
93
94 /**
95 * 获取token过期时间(次日凌晨3点)
96 *
97 * @return expire
98 */
99 public static int getTokenValiditySecond() {
100 Calendar cal = Calendar.getInstance();
101 cal.add(Calendar.DAY_OF_YEAR, 1);
102 cal.set(Calendar.HOUR_OF_DAY, 3);
103 cal.set(Calendar.SECOND, 0);
104 cal.set(Calendar.MINUTE, 0);
105 cal.set(Calendar.MILLISECOND, 0);
106 return (int) (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
107 }
108
109 /**
110 * 获取refreshToken过期时间
111 *
112 * @return expire
113 */
114 public static int getRefreshTokenValiditySeconds() {
115 return 60 * 60 * 24 * 15;
116 }
117
118 }
1 #服务器端口
2 server:
3 port: 8100
4
5 #数据源配置
6 spring:
7 datasource:
8 driver-class-name: com.mysql.cj.jdbc.Driver
9 url: ${blade.datasource.dev.url}
10 username: ${blade.datasource.dev.username}
11 password: ${blade.datasource.dev.password}
1 #服务器端口
2 server:
3 port: 8100
4
5 #数据源配置
6 spring:
7 datasource:
8 driver-class-name: com.mysql.cj.jdbc.Driver
9 url: ${blade.datasource.prod.url}
10 username: ${blade.datasource.prod.username}
11 password: ${blade.datasource.prod.password}
1 #服务器端口
2 server:
3 port: 8100
4
5 #数据源配置
6 spring:
7 datasource:
8 driver-class-name: com.mysql.cj.jdbc.Driver
9 url: ${blade.datasource.test.url}
10 username: ${blade.datasource.test.username}
11 password: ${blade.datasource.test.password}
1 swagger:
2 base-packages:
3 - org.springblade
4 - org.springframework.security.oauth2.provider.endpoint
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <parent>
6 <artifactId>BladeX</artifactId>
7 <groupId>org.springblade</groupId>
8 <version>2.0.0.RELEASE</version>
9 </parent>
10 <modelVersion>4.0.0</modelVersion>
11
12 <artifactId>blade-common</artifactId>
13 <name>${project.artifactId}</name>
14 <version>${bladex.project.version}</version>
15 <packaging>jar</packaging>
16
17 <dependencies>
18 <dependency>
19 <groupId>org.springblade</groupId>
20 <artifactId>blade-core-launch</artifactId>
21 <version>${bladex.tool.version}</version>
22 </dependency>
23 <dependency>
24 <groupId>org.springblade</groupId>
25 <artifactId>blade-core-auto</artifactId>
26 <version>${bladex.tool.version}</version>
27 <scope>provided</scope>
28 </dependency>
29 <!--<dependency>
30 <groupId>org.springblade</groupId>
31 <artifactId>blade-core-tool</artifactId>
32 <version>${bladex.tool.version}</version>
33 </dependency>-->
34 <!--<dependency>-->
35 <!--<groupId>com.aliyun</groupId>-->
36 <!--<artifactId>aliyun-java-sdk-core</artifactId>-->
37 <!--<version>4.1.0</version>-->
38 <!--</dependency>-->
39 </dependencies>
40
41 <build>
42 <plugins>
43 <plugin>
44 <groupId>org.springframework.boot</groupId>
45 <artifactId>spring-boot-maven-plugin</artifactId>
46 <configuration>
47 <skip>true</skip>
48 <finalName>${project.name}</finalName>
49 </configuration>
50 </plugin>
51 <plugin>
52 <groupId>com.spotify</groupId>
53 <artifactId>docker-maven-plugin</artifactId>
54 <version>${docker.plugin.version}</version>
55 <configuration>
56 <skipDockerBuild>true</skipDockerBuild>
57 </configuration>
58 </plugin>
59 </plugins>
60 </build>
61
62 </project>
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.common.cache;
18
19 /**
20 * 缓存名
21 *
22 * @author Chill
23 */
24 public interface CacheNames {
25
26 String NOTICE_ONE = "notice:one";
27
28 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.common.config;
18
19
20 import lombok.AllArgsConstructor;
21 import org.springframework.context.annotation.Configuration;
22
23 /**
24 * 公共封装包配置类
25 *
26 * @author Chill
27 */
28 @Configuration
29 @AllArgsConstructor
30 public class BladeCommonConfiguration {
31
32 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.common.constant;
18
19 import org.springblade.core.launch.constant.AppConstant;
20
21 /**
22 * 通用常量
23 *
24 * @author Chill
25 */
26 public interface CommonConstant {
27
28 /**118.31.247.145
29 * nacos dev 地址
30 */
31 String NACOS_DEV_ADDR = "118.31.247.145:8848";
32
33 /**
34 * nacos prod 地址
35 */
36 String NACOS_PROD_ADDR = "118.31.247.145:8848";
37
38 /**
39 * nacos test 地址
40 */
41 String NACOS_TEST_ADDR = "118.31.247.145:8848";
42
43 /**
44 * sentinel dev 地址
45 */
46 String SENTINEL_DEV_ADDR = "118.31.247.145:8858";
47
48 /**
49 * sentinel prod 地址
50 */
51 String SENTINEL_PROD_ADDR = "118.31.247.145:8858";
52
53 /**
54 * sentinel test 地址
55 */
56 String SENTINEL_TEST_ADDR = "118.31.247.145:8858";
57
58 /**
59 * sword 系统名
60 */
61 String SWORD_NAME = "sword";
62
63 /**
64 * saber 系统名
65 */
66 String SABER_NAME = "saber";
67
68 /**
69 * 顶级父节点id
70 */
71 Long TOP_PARENT_ID = 0L;
72
73 /**
74 * 顶级父节点名称
75 */
76 String TOP_PARENT_NAME = "顶级";
77
78
79 /**
80 * 默认密码
81 */
82 String DEFAULT_PASSWORD = "654321";
83
84 /**
85 * 动态获取nacos地址
86 *
87 * @param profile 环境变量
88 * @return addr
89 */
90 static String nacosAddr(String profile) {
91 switch (profile) {
92 case (AppConstant.PROD_CODE):
93 return NACOS_PROD_ADDR;
94 case (AppConstant.TEST_CODE):
95 return NACOS_TEST_ADDR;
96 default:
97 return NACOS_DEV_ADDR;
98 }
99 }
100
101 /**
102 * 动态获取sentinel地址
103 *
104 * @param profile 环境变量
105 * @return addr
106 */
107 static String sentinelAddr(String profile) {
108 switch (profile) {
109 case (AppConstant.PROD_CODE):
110 return SENTINEL_PROD_ADDR;
111 case (AppConstant.TEST_CODE):
112 return SENTINEL_TEST_ADDR;
113 default:
114 return SENTINEL_DEV_ADDR;
115 }
116 }
117
118 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.common.launch;
18
19 import org.springblade.common.constant.CommonConstant;
20 import org.springblade.core.auto.service.AutoService;
21 import org.springblade.core.launch.service.LauncherService;
22 import org.springframework.boot.builder.SpringApplicationBuilder;
23
24 import java.util.Properties;
25
26 /**
27 * 启动参数拓展
28 *
29 * @author smallchil
30 */
31 @AutoService(LauncherService.class)
32 public class LauncherServiceImpl implements LauncherService {
33
34 @Override
35 public void launcher(SpringApplicationBuilder builder, String appName, String profile, boolean isLocalDev) {
36 Properties props = System.getProperties();
37 props.setProperty("spring.cloud.nacos.discovery.server-addr", CommonConstant.nacosAddr(profile));
38 props.setProperty("spring.cloud.nacos.config.server-addr", CommonConstant.nacosAddr(profile));
39 props.setProperty("spring.cloud.sentinel.transport.dashboard", CommonConstant.sentinelAddr(profile));
40 }
41
42 }
1 package org.springblade.common.utils;
2
3 public class CommonPageUtil {
4 /**
5 * 获取limit start
6 * @param pageIndex
7 * @param pageSize
8 * @return
9 */
10 public static Integer startIndex(Integer pageIndex,Integer pageSize){
11 if(pageIndex == null || pageIndex < 1){
12 return 0;
13 }else if(pageSize == null || pageSize < 1){
14 pageSize = 15;
15 }
16 return (pageIndex -1)*pageSize;
17 }
18
19 /**
20 * 获取limit size
21 * @param pageSize
22 * @return
23 */
24 public static Integer pageSize(Integer pageSize){
25 if(pageSize == null || pageSize < 1){
26 return 15;
27 }
28 return pageSize;
29 }
30 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.common.utils;
18
19 /**
20 * 通用工具类
21 *
22 * @author Chill
23 */
24 public class CommonUtil {
25
26 }
1 package org.springblade.common.utils;
2
3 import org.springframework.util.ObjectUtils;
4
5 import java.sql.Array;
6 import java.text.SimpleDateFormat;
7 import java.util.ArrayList;
8 import java.util.Date;
9
10 public class OrderNoUtil {
11
12 public static String getOrderNoForRepare(){
13 Date t = new Date();
14
15 SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
16 String orderNo = df.format(t)+getRandomNo(4);
17 return orderNo;
18 }
19
20 public static String getRandomNo(int length ){
21 String result = "";
22 java.util.Random r=new java.util.Random();
23 for(int i=0;i<length;i++){
24 result +=r.nextInt();
25 }
26 return result;
27 }
28 public static String getSimNO(){
29 Date t = new Date();
30
31 SimpleDateFormat df = new SimpleDateFormat("yyMMddHHmmss");
32 String orderNo = df.format(t)+getRandomNo(2).replaceAll("-","");
33 for(int i=0;i<(32-orderNo.length());i++){
34 orderNo += "0";
35 }
36 return orderNo;
37 }
38
39 }
1 package org.springblade.common.utils.captcha;
2
3 import lombok.Data;
4
5 import java.awt.image.BufferedImage;
6
7 /**
8 * @author 吕鸿磊
9 * @date 2019-07-30 18:39
10 */
11 @Data
12 public class CaptchaBean {
13 private String result;
14 private String[] codeArray;
15 private BufferedImage bufferedImage;
16 }
1 package org.springblade.common.utils.captcha;
2
3 import java.awt.*;
4 import java.awt.geom.AffineTransform;
5 import java.awt.image.BufferedImage;
6 import java.util.Random;
7
8 /**
9 * @author 吕鸿磊
10 * @date 2019-07-30 17:52
11 */
12 public class CaptchaUtil {
13 private static char[] ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
14 int codecnt=4;
15 Random random = new Random();
16 int width = 90;
17 int height = 30;
18 int lineNum = 2;
19 Color color = new Color(253, 251, 255);
20 boolean transform=false;
21
22 public static void main(String[] args) {
23 CaptchaBean captchaBean = new CaptchaUtil().generateCaptcha();
24 System.out.println(captchaBean.toString());
25 }
26 public static CaptchaBean getCaptcha(){
27 return new CaptchaUtil().generateCaptcha();
28 }
29
30 public CaptchaBean generateCaptcha() {
31 // 1.build image
32 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
33 Graphics graphics = image.getGraphics();
34 graphics.setColor(color);
35 // graphics.setColor(getRandColor(200, 250));
36 graphics.fillRect(0, 0, width, height);
37
38 //2.mixSource
39 mixSource(image);
40
41 //3.drawCode
42 CaptchaBean result = drawCode(graphics);
43 result.setBufferedImage(image);
44 return result;
45 }
46
47 public CaptchaBean generateCode() {
48 CaptchaBean captchaBean = new CaptchaBean();
49 String[] codeArray = new String[codecnt];
50 StringBuffer builder = new StringBuffer();
51 for (int i = 0; i < codecnt; i++) {
52 char c = ch[random.nextInt(ch.length)];
53 String ch = String.valueOf(c);
54 codeArray[i] = ch;
55 builder.append(ch);
56 }
57 captchaBean.setCodeArray(codeArray);
58 captchaBean.setResult(builder.toString());
59 return captchaBean;
60 }
61
62 public void mixSource(BufferedImage image) {
63 drawPoint(image);
64 drawLine(image);
65 }
66
67 public void drawLine(BufferedImage image) {
68 Graphics graphics = image.getGraphics();
69 for (int i = 0; i < lineNum; i++) {
70 int xs = random.nextInt(width);
71 int ys = random.nextInt(height);
72 int xe = xs + random.nextInt(width);
73 int ye = ys + random.nextInt(height);
74 graphics.setColor(getRandColor(1, 255));
75 graphics.drawLine(xs, ys, xe, ye);
76 }
77 }
78
79 public void drawPoint(BufferedImage image) {
80 // 添加噪点
81 float yawpRate = 0.05f;// 噪声率
82 int area = (int) (yawpRate * width * height);
83 for (int i = 0; i < area; i++) {
84 int x = random.nextInt(width);
85 int y = random.nextInt(height);
86 image.setRGB(x, y, random.nextInt(255));
87 }
88 }
89
90 public CaptchaBean drawCode(Graphics graphics) {
91 //1.genarate code
92 CaptchaBean captcha = generateCode();
93
94 //2.drapCode
95 Font font = getFont(16);
96 graphics.setFont(font);
97 if(captcha!=null&&captcha.getCodeArray()!=null
98 &&captcha.getResult()!=null&&captcha.getCodeArray().length>0) {
99 for(int i=0;i<captcha.getCodeArray().length;i++) {
100 String code = String.valueOf(captcha.getCodeArray()[i]);
101
102 // 文字变形设置
103 if(transform) {
104 AffineTransform fontAT = new AffineTransform();
105 int rotate = random.nextInt(25);
106 fontAT.rotate(random.nextBoolean() ? Math.toRadians(rotate) : -Math
107 .toRadians(rotate / 2));
108 Font fx = new Font(new String[] { "Times New Roman", "Verdana",
109 "arial" }[random.nextInt(2)], random.nextInt(5),
110 14 + random.nextInt(8)).deriveFont(fontAT);
111 graphics.setFont(fx);
112 }
113
114 // 产生随机的颜色分量来构造颜色值,这样输出的每一位数字的颜色值都不同
115 // int red = random.nextInt(255);
116 // int green = random.nextInt(255);
117 // int blue = random.nextInt(255);
118 // 将随机产生的颜色将验证码绘制到图像中
119 graphics.setColor(getRandColor(1, 255));
120 // graphics.drawString(code, (i*20)+5, 10+random.nextInt(10));
121 graphics.drawString(code, (i*width/5)+5, height/2+ random.nextInt(height/4));
122 }
123 }
124 return captcha;
125 }
126
127 // 得到随机颜色
128 public Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色
129 if (fc > 255) {
130 fc = 255;
131 }
132 if (bc > 255) {
133 bc = 255;
134 }
135 int r = fc + random.nextInt(bc - fc);
136 int g = fc + random.nextInt(bc - fc);
137 int b = fc + random.nextInt(bc - fc);
138 return new Color(r, g, b);
139 }
140
141 private Font getFont(int size) {
142 Random random = new Random();
143 Font font[] = new Font[5];
144 font[0] = new Font("Ravie", Font.BOLD, size);
145 font[1] = new Font("Antique Olive Compact", Font.BOLD, size);
146 font[2] = new Font("Fixedsys", Font.BOLD, size);
147 font[3] = new Font("Wide Latin", Font.BOLD, size);
148 font[4] = new Font("Gill Sans Ultra Bold", Font.BOLD, size);
149 return font[random.nextInt(5)];
150 }
151
152 }
153
154
1 ${AnsiColor.BLUE} ______ _ _ ___ ___
2 ${AnsiColor.BLUE} | ___ \| | | | \ \ / /
3 ${AnsiColor.BLUE} | |_/ /| | __ _ __| | ___ \ V /
4 ${AnsiColor.BLUE} | ___ \| | / _` | / _` | / _ \ > <
5 ${AnsiColor.BLUE} | |_/ /| || (_| || (_| || __/ / . \
6 ${AnsiColor.BLUE} \____/ |_| \__,_| \__,_| \___|/__/ \__\
7
8 ${AnsiColor.BLUE}:: BladeX :: ${spring.application.name}:${AnsiColor.RED}${blade.env}${AnsiColor.BLUE} :: Running SpringBoot ${spring-boot.version} :: ${AnsiColor.BRIGHT_BLACK}
1 FROM anapsix/alpine-java:8_server-jre_unlimited
2
3 MAINTAINER smallchill@163.com
4
5 RUN mkdir -p /blade/gateway
6
7 WORKDIR /blade/gateway
8
9 EXPOSE 80
10
11 ADD ./target/blade-gateway.jar ./app.jar
12
13 ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
14
15 CMD ["--spring.profiles.active=test"]
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <parent>
6 <artifactId>BladeX</artifactId>
7 <groupId>org.springblade</groupId>
8 <version>2.0.0.RELEASE</version>
9 </parent>
10 <modelVersion>4.0.0</modelVersion>
11
12 <artifactId>blade-gateway</artifactId>
13 <name>${project.artifactId}</name>
14 <version>${bladex.project.version}</version>
15 <packaging>jar</packaging>
16
17 <dependencies>
18 <!--Blade-->
19 <dependency>
20 <groupId>org.springblade</groupId>
21 <artifactId>blade-core-launch</artifactId>
22 <version>${bladex.tool.version}</version>
23 <exclusions>
24 <exclusion>
25 <groupId>org.springframework.boot</groupId>
26 <artifactId>spring-boot-starter-web</artifactId>
27 </exclusion>
28 <exclusion>
29 <groupId>org.springframework.boot</groupId>
30 <artifactId>spring-boot-starter-undertow</artifactId>
31 </exclusion>
32 </exclusions>
33 </dependency>
34 <dependency>
35 <groupId>org.springblade</groupId>
36 <artifactId>blade-common</artifactId>
37 <version>${bladex.project.version}</version>
38 <exclusions>
39 <exclusion>
40 <groupId>org.springblade</groupId>
41 <artifactId>blade-core-launch</artifactId>
42 </exclusion>
43 </exclusions>
44 </dependency>
45 <!--Spring-->
46 <dependency>
47 <groupId>org.springframework.cloud</groupId>
48 <artifactId>spring-cloud-starter-gateway</artifactId>
49 </dependency>
50 <dependency>
51 <groupId>org.springframework.boot</groupId>
52 <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
53 </dependency>
54 <dependency>
55 <groupId>de.codecentric</groupId>
56 <artifactId>spring-boot-admin-starter-client</artifactId>
57 <version>${spring.boot.admin.version}</version>
58 </dependency>
59 <!--Hystrix-->
60 <dependency>
61 <groupId>org.springframework.cloud</groupId>
62 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
63 <exclusions>
64 <exclusion>
65 <groupId>commons-logging</groupId>
66 <artifactId>commons-logging</artifactId>
67 </exclusion>
68 </exclusions>
69 </dependency>
70 <!-- Nacos -->
71 <dependency>
72 <groupId>org.springframework.cloud</groupId>
73 <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
74 <version>${alibaba.cloud.version}</version>
75 </dependency>
76 <dependency>
77 <groupId>org.springframework.cloud</groupId>
78 <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
79 <version>${alibaba.cloud.version}</version>
80 </dependency>
81 <!--Swagger-->
82 <dependency>
83 <groupId>io.springfox</groupId>
84 <artifactId>springfox-swagger2</artifactId>
85 <version>${swagger.version}</version>
86 <exclusions>
87 <exclusion>
88 <groupId>io.swagger</groupId>
89 <artifactId>swagger-models</artifactId>
90 </exclusion>
91 </exclusions>
92 </dependency>
93 <dependency>
94 <groupId>io.swagger</groupId>
95 <artifactId>swagger-models</artifactId>
96 <version>${swagger.models.version}</version>
97 </dependency>
98 <!--<dependency>
99 <groupId>io.springfox</groupId>
100 <artifactId>springfox-swagger-ui</artifactId>
101 <version>${swagger.version}</version>
102 </dependency>-->
103 <dependency>
104 <groupId>com.github.xiaoymin</groupId>
105 <artifactId>swagger-bootstrap-ui</artifactId>
106 <version>${swagger.bootstrapui.version}</version>
107 </dependency>
108 </dependencies>
109
110 <build>
111 <plugins>
112 <plugin>
113 <groupId>com.spotify</groupId>
114 <artifactId>docker-maven-plugin</artifactId>
115 <version>${docker.plugin.version}</version>
116 <configuration>
117 <imageName>${docker.registry.url}/blade/${project.artifactId}:${project.version}</imageName>
118 <dockerDirectory>${project.basedir}</dockerDirectory>
119 <dockerHost>${docker.registry.host}</dockerHost>
120 <resources>
121 <resource>
122 <targetPath>/</targetPath>
123 <directory>${project.build.directory}</directory>
124 <include>${project.build.finalName}.jar</include>
125 </resource>
126 </resources>
127 <registryUrl>${docker.registry.url}</registryUrl>
128 <serverId>${docker.registry.url}</serverId>
129 <pushImage>true</pushImage>
130 </configuration>
131 </plugin>
132 <plugin>
133 <groupId>org.apache.maven.plugins</groupId>
134 <artifactId>maven-antrun-plugin</artifactId>
135 <executions>
136 <execution>
137 <phase>package</phase>
138 <goals>
139 <goal>run</goal>
140 </goals>
141 <configuration>
142 <tasks>
143 <copy overwrite="true"
144 tofile="${session.executionRootDirectory}/target/${project.artifactId}.jar"
145 file="${project.build.directory}/${project.artifactId}.jar" />
146 </tasks>
147 </configuration>
148 </execution>
149 </executions>
150 </plugin>
151 </plugins>
152 </build>
153
154 </project>
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.gateway;
18
19 import org.springblade.core.launch.constant.AppConstant;
20 import org.springblade.core.launch.BladeApplication;
21 import org.springframework.cloud.client.SpringCloudApplication;
22 import org.springframework.cloud.netflix.hystrix.EnableHystrix;
23 import org.springframework.scheduling.annotation.EnableScheduling;
24
25 /**
26 * 项目启动
27 *
28 * @author Chill
29 */
30 @EnableHystrix
31 @EnableScheduling
32 @SpringCloudApplication
33 public class GateWayApplication {
34
35 public static void main(String[] args) {
36 BladeApplication.run(AppConstant.APPLICATION_GATEWAY_NAME, GateWayApplication.class, args);
37 }
38
39 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.gateway.config;
18
19
20 import org.springblade.gateway.handler.ErrorExceptionHandler;
21 import org.springframework.beans.factory.ObjectProvider;
22 import org.springframework.boot.autoconfigure.AutoConfigureBefore;
23 import org.springframework.boot.autoconfigure.web.ResourceProperties;
24 import org.springframework.boot.autoconfigure.web.ServerProperties;
25 import org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration;
26 import org.springframework.boot.context.properties.EnableConfigurationProperties;
27 import org.springframework.boot.web.reactive.error.ErrorAttributes;
28 import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
29 import org.springframework.context.ApplicationContext;
30 import org.springframework.context.annotation.Bean;
31 import org.springframework.context.annotation.Configuration;
32 import org.springframework.core.Ordered;
33 import org.springframework.core.annotation.Order;
34 import org.springframework.http.codec.ServerCodecConfigurer;
35 import org.springframework.web.reactive.result.view.ViewResolver;
36
37 import java.util.Collections;
38 import java.util.List;
39
40 /**
41 * 异常处理配置类
42 *
43 * @author Chill
44 */
45 @Configuration
46 @AutoConfigureBefore(ErrorWebFluxAutoConfiguration.class)
47 @EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
48 public class ErrorHandlerConfiguration {
49
50 private final ServerProperties serverProperties;
51
52 private final ApplicationContext applicationContext;
53
54 private final ResourceProperties resourceProperties;
55
56 private final List<ViewResolver> viewResolvers;
57
58 private final ServerCodecConfigurer serverCodecConfigurer;
59
60 public ErrorHandlerConfiguration(ServerProperties serverProperties,
61 ResourceProperties resourceProperties,
62 ObjectProvider<List<ViewResolver>> viewResolversProvider,
63 ServerCodecConfigurer serverCodecConfigurer,
64 ApplicationContext applicationContext) {
65 this.serverProperties = serverProperties;
66 this.applicationContext = applicationContext;
67 this.resourceProperties = resourceProperties;
68 this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
69 this.serverCodecConfigurer = serverCodecConfigurer;
70 }
71
72 @Bean
73 @Order(Ordered.HIGHEST_PRECEDENCE)
74 public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
75 ErrorExceptionHandler exceptionHandler = new ErrorExceptionHandler(
76 errorAttributes,
77 this.resourceProperties,
78 this.serverProperties.getError(),
79 this.applicationContext);
80 exceptionHandler.setViewResolvers(this.viewResolvers);
81 exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
82 exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
83 return exceptionHandler;
84 }
85
86 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17
18 package org.springblade.gateway.config;
19
20 import lombok.AllArgsConstructor;
21 import lombok.extern.slf4j.Slf4j;
22 import org.springblade.gateway.handler.*;
23 import org.springframework.context.annotation.Bean;
24 import org.springframework.context.annotation.Configuration;
25 import org.springframework.http.HttpHeaders;
26 import org.springframework.http.HttpMethod;
27 import org.springframework.http.HttpStatus;
28 import org.springframework.http.MediaType;
29 import org.springframework.http.server.reactive.ServerHttpRequest;
30 import org.springframework.http.server.reactive.ServerHttpResponse;
31 import org.springframework.web.cors.reactive.CorsUtils;
32 import org.springframework.web.filter.reactive.HiddenHttpMethodFilter;
33 import org.springframework.web.reactive.function.server.RequestPredicates;
34 import org.springframework.web.reactive.function.server.RouterFunction;
35 import org.springframework.web.reactive.function.server.RouterFunctions;
36 import org.springframework.web.server.ServerWebExchange;
37 import org.springframework.web.server.WebFilter;
38 import org.springframework.web.server.WebFilterChain;
39 import reactor.core.publisher.Mono;
40
41 /**
42 * 路由配置信息
43 *
44 * @author Chill
45 */
46 @Slf4j
47 @Configuration
48 @AllArgsConstructor
49 public class RouterFunctionConfiguration {
50
51 /**
52 * 这里为支持的请求头,如果有自定义的header字段请自己添加
53 */
54 private static final String ALLOWED_HEADERS = "x-requested-with, blade-auth, Content-Type, Authorization, credential, X-XSRF-TOKEN, token, username, client";
55 private static final String ALLOWED_METHODS = "*";
56 private static final String ALLOWED_ORIGIN = "*";
57 private static final String ALLOWED_EXPOSE = "*";
58 private static final String MAX_AGE = "18000L";
59
60 private final HystrixFallbackHandler hystrixFallbackHandler;
61 private final SwaggerResourceHandler swaggerResourceHandler;
62 private final SwaggerSecurityHandler swaggerSecurityHandler;
63 private final SwaggerUiHandler swaggerUiHandler;
64
65 @Bean
66 public WebFilter corsFilter() {
67 return (ServerWebExchange ctx, WebFilterChain chain) -> {
68 ServerHttpRequest request = ctx.getRequest();
69 if (CorsUtils.isCorsRequest(request)) {
70 ServerHttpResponse response = ctx.getResponse();
71 HttpHeaders headers = response.getHeaders();
72 headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
73 headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
74 headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
75 headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
76 headers.add("Access-Control-Max-Age", MAX_AGE);
77 headers.add("Access-Control-Allow-Credentials", "true");
78 if (request.getMethod() == HttpMethod.OPTIONS) {
79 response.setStatusCode(HttpStatus.OK);
80 return Mono.empty();
81 }
82 }
83 return chain.filter(ctx);
84 };
85 }
86
87 @Bean
88 public RouterFunction routerFunction() {
89 return RouterFunctions.route(
90 RequestPredicates.path("/fallback")
91 .and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), hystrixFallbackHandler)
92 .andRoute(RequestPredicates.GET("/swagger-resources")
93 .and(RequestPredicates.accept(MediaType.ALL)), swaggerResourceHandler)
94 .andRoute(RequestPredicates.GET("/swagger-resources/configuration/ui")
95 .and(RequestPredicates.accept(MediaType.ALL)), swaggerUiHandler)
96 .andRoute(RequestPredicates.GET("/swagger-resources/configuration/security")
97 .and(RequestPredicates.accept(MediaType.ALL)), swaggerSecurityHandler);
98
99 }
100
101 /**
102 * 解决springboot2.0.5版本出现的 Only one connection receive subscriber allowed.
103 * 参考:https://github.com/spring-cloud/spring-cloud-gateway/issues/541
104 */
105 @Bean
106 public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
107 return new HiddenHttpMethodFilter() {
108 @Override
109 public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
110 return chain.filter(exchange);
111 }
112 };
113 }
114
115 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.gateway.controller;
18
19 import lombok.AllArgsConstructor;
20 import lombok.extern.slf4j.Slf4j;
21 import org.springframework.cloud.client.ServiceInstance;
22 import org.springframework.cloud.client.discovery.DiscoveryClient;
23 import org.springframework.web.bind.annotation.GetMapping;
24 import org.springframework.web.bind.annotation.RequestMapping;
25 import org.springframework.web.bind.annotation.RestController;
26
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30
31 /**
32 * 服务发现控制器
33 *
34 * @author Chill
35 */
36 @Slf4j
37 @RestController
38 @AllArgsConstructor
39 @RequestMapping("/discovery")
40 public class DiscoveryClientController {
41
42 private final DiscoveryClient discoveryClient;
43
44 /**
45 * 获取服务实例
46 */
47 @GetMapping("/instances")
48 public Map<String, List<ServiceInstance>> instances() {
49 Map<String, List<ServiceInstance>> instances = new HashMap<>(16);
50 List<String> services = discoveryClient.getServices();
51 services.forEach(s -> {
52 List<ServiceInstance> list = discoveryClient.getInstances(s);
53 instances.put(s, list);
54 });
55 return instances;
56 }
57
58 }
1 package org.springblade.gateway.filter;
2
3 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
4 import org.springframework.cloud.gateway.filter.GlobalFilter;
5 import org.springframework.core.Ordered;
6 import org.springframework.http.server.reactive.ServerHttpRequest;
7 import org.springframework.stereotype.Component;
8 import org.springframework.util.StringUtils;
9 import org.springframework.web.server.ServerWebExchange;
10 import reactor.core.publisher.Mono;
11
12 import java.util.Arrays;
13 import java.util.stream.Collectors;
14
15 import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
16 import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;
17
18 /**
19 * <p>
20 * 全局拦截器,作用所有的微服务
21 * <p>
22 * 1. 对请求头中参数进行处理 from 参数进行清洗
23 * 2. 重写StripPrefix = 1,支持全局
24 *
25 * @author lengleng
26 */
27 @Component
28 public class RequestGlobalFilter implements GlobalFilter, Ordered {
29
30 /**
31 * Process the Web request and (optionally) delegate to the next
32 * {@code WebFilter} through the given {@link GatewayFilterChain}.
33 *
34 * @param exchange the current server exchange
35 * @param chain provides a way to delegate to the next filter
36 * @return {@code Mono<Void>} to indicate when request processing is complete
37 */
38 @Override
39 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
40 // 1. 清洗请求头中from 参数
41 ServerHttpRequest request = exchange.getRequest().mutate()
42 .headers(httpHeaders -> httpHeaders.remove("X"))
43 .build();
44
45 // 2. 重写StripPrefix
46 addOriginalRequestUrl(exchange, request.getURI());
47 String rawPath = request.getURI().getRawPath();
48 String newPath = "/" + Arrays.stream(StringUtils.tokenizeToStringArray(rawPath, "/"))
49 .skip(1L).collect(Collectors.joining("/"));
50 ServerHttpRequest newRequest = request.mutate()
51 .path(newPath)
52 .build();
53 exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, newRequest.getURI());
54
55 return chain.filter(exchange.mutate().request(newRequest.mutate().build()).build());
56 }
57
58 @Override
59 public int getOrder() {
60 return -1000;
61 }
62
63 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.gateway.handler;
18
19 import org.springframework.boot.autoconfigure.web.ErrorProperties;
20 import org.springframework.boot.autoconfigure.web.ResourceProperties;
21 import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
22 import org.springframework.boot.web.reactive.error.ErrorAttributes;
23 import org.springframework.cloud.gateway.support.NotFoundException;
24 import org.springframework.context.ApplicationContext;
25 import org.springframework.http.HttpStatus;
26 import org.springframework.web.reactive.function.server.*;
27 import org.springframework.web.server.ResponseStatusException;
28
29 import java.util.HashMap;
30 import java.util.Map;
31
32 /**
33 * 异常处理
34 *
35 * @author Chill
36 */
37 public class ErrorExceptionHandler extends DefaultErrorWebExceptionHandler {
38
39 public ErrorExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,
40 ErrorProperties errorProperties, ApplicationContext applicationContext) {
41 super(errorAttributes, resourceProperties, errorProperties, applicationContext);
42 }
43
44 /**
45 * 获取异常属性
46 */
47 @Override
48 protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
49 int code = 500;
50 Throwable error = super.getError(request);
51 if (error instanceof NotFoundException) {
52 code = 404;
53 }
54 if (error instanceof ResponseStatusException) {
55 code = ((ResponseStatusException) error).getStatus().value();
56 }
57 return response(code, this.buildMessage(request, error));
58 }
59
60 /**
61 * 指定响应处理方法为JSON处理的方法
62 *
63 * @param errorAttributes
64 */
65 @Override
66 protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
67 return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
68 }
69
70 /**
71 * 根据code获取对应的HttpStatus
72 *
73 * @param errorAttributes
74 */
75 @Override
76 protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) {
77 int statusCode = (int) errorAttributes.get("code");
78 return HttpStatus.valueOf(statusCode);
79 }
80
81 /**
82 * 构建异常信息
83 *
84 * @param request
85 * @param ex
86 * @return
87 */
88 private String buildMessage(ServerRequest request, Throwable ex) {
89 StringBuilder message = new StringBuilder("Failed to handle request [");
90 message.append(request.methodName());
91 message.append(" ");
92 message.append(request.uri());
93 message.append("]");
94 if (ex != null) {
95 message.append(": ");
96 message.append(ex.getMessage());
97 }
98 return message.toString();
99 }
100
101 /**
102 * 构建返回的JSON数据格式
103 *
104 * @param status 状态码
105 * @param errorMessage 异常信息
106 * @return
107 */
108 public static Map<String, Object> response(int status, String errorMessage) {
109 Map<String, Object> map = new HashMap<>(16);
110 map.put("code", status);
111 map.put("message", errorMessage);
112 map.put("data", null);
113 return map;
114 }
115
116 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17
18 package org.springblade.gateway.handler;
19
20 import lombok.extern.slf4j.Slf4j;
21 import org.springframework.http.HttpStatus;
22 import org.springframework.http.MediaType;
23 import org.springframework.stereotype.Component;
24 import org.springframework.web.reactive.function.BodyInserters;
25 import org.springframework.web.reactive.function.server.HandlerFunction;
26 import org.springframework.web.reactive.function.server.ServerRequest;
27 import org.springframework.web.reactive.function.server.ServerResponse;
28 import reactor.core.publisher.Mono;
29
30 /**
31 * Hystrix 降级处理
32 *
33 * @author lengleng
34 */
35 @Slf4j
36 @Component
37 public class HystrixFallbackHandler implements HandlerFunction<ServerResponse> {
38 @Override
39 public Mono<ServerResponse> handle(ServerRequest serverRequest) {
40 log.error("网关执行请求:{}失败,hystrix服务降级处理", serverRequest.uri());
41 return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value())
42 .contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromObject("服务异常"));
43 }
44 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17
18 package org.springblade.gateway.handler;
19
20 import lombok.AllArgsConstructor;
21 import lombok.extern.slf4j.Slf4j;
22 import org.springframework.http.HttpStatus;
23 import org.springframework.http.MediaType;
24 import org.springframework.stereotype.Component;
25 import org.springframework.web.reactive.function.BodyInserters;
26 import org.springframework.web.reactive.function.server.HandlerFunction;
27 import org.springframework.web.reactive.function.server.ServerRequest;
28 import org.springframework.web.reactive.function.server.ServerResponse;
29 import reactor.core.publisher.Mono;
30 import springfox.documentation.swagger.web.SwaggerResourcesProvider;
31
32 /**
33 * SwaggerResourceHandler
34 *
35 * @author lengleng
36 */
37 @Slf4j
38 @Component
39 @AllArgsConstructor
40 public class SwaggerResourceHandler implements HandlerFunction<ServerResponse> {
41 private final SwaggerResourcesProvider swaggerResources;
42
43 /**
44 * Handle the given request.
45 *
46 * @param request the request to handler
47 * @return the response
48 */
49 @Override
50 public Mono<ServerResponse> handle(ServerRequest request) {
51 return ServerResponse.status(HttpStatus.OK)
52 .contentType(MediaType.APPLICATION_JSON_UTF8)
53 .body(BodyInserters.fromObject(swaggerResources.get()));
54 }
55 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17
18 package org.springblade.gateway.handler;
19
20 import lombok.extern.slf4j.Slf4j;
21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.http.HttpStatus;
23 import org.springframework.http.MediaType;
24 import org.springframework.stereotype.Component;
25 import org.springframework.web.reactive.function.BodyInserters;
26 import org.springframework.web.reactive.function.server.HandlerFunction;
27 import org.springframework.web.reactive.function.server.ServerRequest;
28 import org.springframework.web.reactive.function.server.ServerResponse;
29 import reactor.core.publisher.Mono;
30 import springfox.documentation.swagger.web.SecurityConfiguration;
31 import springfox.documentation.swagger.web.SecurityConfigurationBuilder;
32
33 import java.util.Optional;
34
35 /**
36 * SwaggerSecurityHandler
37 *
38 * @author lengleng
39 */
40 @Slf4j
41 @Component
42 public class SwaggerSecurityHandler implements HandlerFunction<ServerResponse> {
43 @Autowired(required = false)
44 private SecurityConfiguration securityConfiguration;
45
46 /**
47 * Handle the given request.
48 *
49 * @param request the request to handler
50 * @return the response
51 */
52 @Override
53 public Mono<ServerResponse> handle(ServerRequest request) {
54 return ServerResponse.status(HttpStatus.OK)
55 .contentType(MediaType.APPLICATION_JSON_UTF8)
56 .body(BodyInserters.fromObject(
57 Optional.ofNullable(securityConfiguration)
58 .orElse(SecurityConfigurationBuilder.builder().build())));
59 }
60 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17
18 package org.springblade.gateway.handler;
19
20 import lombok.extern.slf4j.Slf4j;
21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.http.HttpStatus;
23 import org.springframework.http.MediaType;
24 import org.springframework.stereotype.Component;
25 import org.springframework.web.reactive.function.BodyInserters;
26 import org.springframework.web.reactive.function.server.HandlerFunction;
27 import org.springframework.web.reactive.function.server.ServerRequest;
28 import org.springframework.web.reactive.function.server.ServerResponse;
29 import reactor.core.publisher.Mono;
30 import springfox.documentation.swagger.web.UiConfiguration;
31 import springfox.documentation.swagger.web.UiConfigurationBuilder;
32
33 import java.util.Optional;
34
35 /**
36 * SwaggerUiHandler
37 *
38 * @author lengleng
39 */
40 @Slf4j
41 @Component
42 public class SwaggerUiHandler implements HandlerFunction<ServerResponse> {
43 @Autowired(required = false)
44 private UiConfiguration uiConfiguration;
45
46 /**
47 * Handle the given request.
48 *
49 * @param request the request to handler
50 * @return the response
51 */
52 @Override
53 public Mono<ServerResponse> handle(ServerRequest request) {
54 return ServerResponse.status(HttpStatus.OK)
55 .contentType(MediaType.APPLICATION_JSON_UTF8)
56 .body(BodyInserters.fromObject(
57 Optional.ofNullable(uiConfiguration)
58 .orElse(UiConfigurationBuilder.builder().build())));
59 }
60 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17
18 package org.springblade.gateway.provider;
19
20 import lombok.AllArgsConstructor;
21 import org.springblade.core.launch.constant.AppConstant;
22 import org.springframework.cloud.gateway.config.GatewayProperties;
23 import org.springframework.cloud.gateway.route.RouteLocator;
24 import org.springframework.cloud.gateway.support.NameUtils;
25 import org.springframework.context.annotation.Primary;
26 import org.springframework.stereotype.Component;
27 import springfox.documentation.swagger.web.SwaggerResource;
28 import springfox.documentation.swagger.web.SwaggerResourcesProvider;
29
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34
35 /**
36 * 聚合接口文档注册
37 *
38 * @author Sywd
39 */
40 @Primary
41 @Component
42 @AllArgsConstructor
43 public class SwaggerProvider implements SwaggerResourcesProvider {
44 public static final String API_URI = "/v2/api-docs-ext";
45 private final RouteLocator routeLocator;
46 private final GatewayProperties gatewayProperties;
47
48 private static Map<String, String> routeMap = new HashMap<>();
49
50 static {
51 routeMap.put(AppConstant.APPLICATION_AUTH_NAME, "授权模块");
52 routeMap.put(AppConstant.APPLICATION_DESK_NAME, "工作台模块");
53 routeMap.put(AppConstant.APPLICATION_SYSTEM_NAME, "系统模块");
54 routeMap.put(AppConstant.APPLICATION_USER_NAME, "用户模块");
55 routeMap.put("blade-apartment", "智能公寓模块");
56 }
57
58 @Override
59 public List<SwaggerResource> get() {
60 List<SwaggerResource> resources = new ArrayList<>();
61 List<String> routes = new ArrayList<>();
62 routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
63 gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()))
64 .forEach(routeDefinition -> routeDefinition.getPredicates().stream()
65 .filter(predicateDefinition -> "Path".equalsIgnoreCase(predicateDefinition.getName()))
66 .forEach(predicateDefinition -> resources.add(swaggerResource(routeDefinition.getId(),
67 predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
68 .replace("/**", API_URI)))));
69 return resources;
70 }
71
72 private SwaggerResource swaggerResource(String name, String location) {
73 SwaggerResource swaggerResource = new SwaggerResource();
74 swaggerResource.setName((routeMap.get(name) == null ? name : routeMap.get(name)));
75 swaggerResource.setLocation(location);
76 swaggerResource.setSwaggerVersion("2.0");
77 return swaggerResource;
78 }
79
80 }
1 server:
2 port: 80
3
4 # 需要配置的服务名
5 blade:
6 service:
7 blade-auth: blade-auth
8 blade-desk: blade-desk
9 blade-system: blade-system
10 blade-apartment: blade-apartment
11 blade-user: blade-user
12
13 spring:
14 cloud:
15 gateway:
16 routes:
17 # 认证中心
18 - id: ${blade.service.blade-auth}
19 uri: lb://${blade.service.blade-auth}
20 predicates:
21 - Path=/${blade.service.blade-auth}/**
22 # 首页模块
23 - id: ${blade.service.blade-desk}
24 uri: lb://${blade.service.blade-desk}
25 predicates:
26 - Path=/${blade.service.blade-desk}/**
27 # 用户模块
28 - id: ${blade.service.blade-user}
29 uri: lb://${blade.service.blade-user}
30 predicates:
31 - Path=/${blade.service.blade-user}/**
32 # 系统模块
33 - id: ${blade.service.blade-system}
34 uri: lb://${blade.service.blade-system}
35 predicates:
36 - Path=/${blade.service.blade-system}/**
37 # 智能公寓模块
38 - id: ${blade.service.blade-apartment}
39 uri: lb://${blade.service.blade-apartment}
40 predicates:
41 - Path=/${blade.service.blade-apartment}/**
42 discovery:
43 locator:
44 enabled: true
45 loadbalancer:
46 retry:
47 enabled: true
48
49
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <parent>
6 <artifactId>blade-ops-api</artifactId>
7 <groupId>org.springblade</groupId>
8 <version>2.0.0.RELEASE</version>
9 </parent>
10 <modelVersion>4.0.0</modelVersion>
11
12 <artifactId>blade-flow-api</artifactId>
13 <name>${project.artifactId}</name>
14 <version>${bladex.project.version}</version>
15 <packaging>jar</packaging>
16
17
18
19 </project>
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.flow.core.constant;
18
19 /**
20 * 流程常量.
21 *
22 * @author Chill
23 */
24 public interface ProcessConstant {
25
26 /**
27 * 请假流程标识
28 */
29 String LEAVE_KEY = "Leave";
30
31 /**
32 * 报销流程标识
33 */
34 String Expense_KEY = "Expense";
35
36 /**
37 * 同意标识
38 */
39 String PASS_KEY = "pass";
40
41 /**
42 * 同意代号
43 */
44 String PASS_ALIAS = "ok";
45
46 /**
47 * 同意默认批复
48 */
49 String PASS_COMMENT = "同意";
50
51 /**
52 * 驳回默认批复
53 */
54 String NOT_PASS_COMMENT = "驳回";
55
56 /**
57 * 创建人变量名
58 */
59 String TASK_VARIABLE_CREATE_USER = "createUser";
60
61 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.flow.core.entity;
18
19 import lombok.Data;
20 import org.springblade.flow.core.constant.ProcessConstant;
21
22 import java.io.Serializable;
23 import java.util.Date;
24 import java.util.Map;
25
26 /**
27 * 工作流通用实体类
28 *
29 * @author Chill
30 */
31 @Data
32 public class BladeFlow implements Serializable {
33 private static final long serialVersionUID = 1L;
34
35 /**
36 * 任务编号
37 */
38 private String taskId;
39 /**
40 * 任务名称
41 */
42 private String taskName;
43 /**
44 * 任务定义Key
45 */
46 private String taskDefinitionKey;
47 /**
48 * 任务执行人编号
49 */
50 private String assignee;
51 /**
52 * 任务执行人名称
53 */
54 private String assigneeName;
55 /**
56 * 流程分类
57 */
58 private String category;
59 /**
60 * 流程分类名
61 */
62 private String categoryName;
63 /**
64 * 创建时间
65 */
66 private Date createTime;
67 /**
68 * 结束时间
69 */
70 private Date endTime;
71 /**
72 * 签收时间
73 */
74 private Date claimTime;
75 /**
76 * 历史任务结束时间
77 */
78 private Date historyTaskEndTime;
79 /**
80 * 执行ID
81 */
82 private String executionId;
83 /**
84 * 流程实例ID
85 */
86 private String processInstanceId;
87 /**
88 * 流程ID
89 */
90 private String processDefinitionId;
91 /**
92 * 流程标识
93 */
94 private String processDefinitionKey;
95 /**
96 * 流程名
97 */
98 private String processDefinitionName;
99 /**
100 * 流程版本
101 */
102 private int processDefinitionVersion;
103 /**
104 * 流程说明
105 */
106 private String processDefinitionDesc;
107 /**
108 * 流程简图名
109 */
110 private String processDefinitionDiagramResName;
111 /**
112 * 流程重命名
113 */
114 private String processDefinitionResName;
115 /**
116 * 历史任务流程实例ID 查看流程图会用到
117 */
118 private String historyProcessInstanceId;
119 /**
120 * 流程实例是否结束
121 */
122 private String processIsFinished;
123 /**
124 * 历史活动流程
125 */
126 private String historyActivityName;
127 /**
128 * 历史活动耗时
129 */
130 private String historyActivityDurationTime;
131 /**
132 * 业务绑定Table
133 */
134 private String businessTable;
135 /**
136 * 业务绑定ID
137 */
138 private String businessId;
139 /**
140 * 任务状态
141 */
142 private String status;
143 /**
144 * 任务意见
145 */
146 private String comment;
147 /**
148 * 是否通过
149 */
150 private boolean isPass;
151 /**
152 * 是否通过代号
153 */
154 private String flag;
155 /**
156 * 开始查询日期
157 */
158 private Date beginDate;
159 /**
160 * 结束查询日期
161 */
162 private Date endDate;
163 /**
164 * 流程参数
165 */
166 private Map<String, Object> variables;
167
168 /**
169 * 获取是否通过
170 */
171 public boolean isPass() {
172 return ProcessConstant.PASS_ALIAS.equals(flag) || ProcessConstant.PASS_COMMENT.equals(comment);
173 }
174
175 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.flow.core.entity;
18
19 import com.baomidou.mybatisplus.annotation.TableField;
20 import lombok.Data;
21 import lombok.EqualsAndHashCode;
22 import org.springblade.core.mp.base.BaseEntity;
23
24 /**
25 * FlowEntity
26 *
27 * @author Chill
28 */
29 @Data
30 @EqualsAndHashCode(callSuper = true)
31 public class FlowEntity extends BaseEntity {
32
33 @TableField(exist = false)
34 private BladeFlow flow;
35
36 public BladeFlow getFlow() {
37 if (flow == null) {
38 flow = new BladeFlow();
39 }
40 return flow;
41 }
42
43 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.flow.core.feign;
18
19 import org.springblade.core.launch.constant.AppConstant;
20 import org.springblade.core.tool.api.R;
21 import org.springblade.flow.core.entity.BladeFlow;
22 import org.springframework.cloud.openfeign.FeignClient;
23 import org.springframework.web.bind.annotation.GetMapping;
24 import org.springframework.web.bind.annotation.PostMapping;
25 import org.springframework.web.bind.annotation.RequestBody;
26 import org.springframework.web.bind.annotation.RequestParam;
27
28 import java.util.Map;
29
30 /**
31 * 工作流远程调用接口.
32 *
33 * @author Chill
34 */
35 @FeignClient(
36 value = AppConstant.APPLICATION_FLOW_NAME,
37 fallback = IFlowClientFallback.class
38 )
39 public interface IFlowClient {
40
41 String API_PREFIX = "/client";
42 String START_PROCESS_INSTANCE_BY_ID = API_PREFIX + "start-process-instance-by-id";
43 String START_PROCESS_INSTANCE_BY_KEY = API_PREFIX + "start-process-instance-by-key";
44 String COMPLETE_TASK = API_PREFIX + "complete-task";
45 String TASK_VARIABLE = API_PREFIX + "task-variable";
46 String TASK_VARIABLES = API_PREFIX + "task-variables";
47
48 /**
49 * 开启流程
50 *
51 * @param processDefinitionId 流程id
52 * @param businessKey 业务key
53 * @param variables 参数
54 * @return BladeFlow
55 */
56 @PostMapping(START_PROCESS_INSTANCE_BY_ID)
57 R<BladeFlow> startProcessInstanceById(@RequestParam("processDefinitionId") String processDefinitionId, @RequestParam("businessKey") String businessKey, @RequestBody Map<String, Object> variables);
58
59 /**
60 * 开启流程
61 *
62 * @param processDefinitionKey 流程标识
63 * @param businessKey 业务key
64 * @param variables 参数
65 * @return BladeFlow
66 */
67 @PostMapping(START_PROCESS_INSTANCE_BY_KEY)
68 R<BladeFlow> startProcessInstanceByKey(@RequestParam("processDefinitionKey") String processDefinitionKey, @RequestParam("businessKey") String businessKey, @RequestBody Map<String, Object> variables);
69
70 /**
71 * 完成任务
72 *
73 * @param taskId 任务id
74 * @param processInstanceId 流程实例id
75 * @param comment 评论
76 * @param variables 参数
77 * @return R
78 */
79 @PostMapping(COMPLETE_TASK)
80 R completeTask(@RequestParam("taskId") String taskId, @RequestParam("processInstanceId") String processInstanceId, @RequestParam("comment") String comment, @RequestBody Map<String, Object> variables);
81
82 /**
83 * 获取流程变量
84 *
85 * @param taskId 任务id
86 * @param variableName 变量名
87 * @return R
88 */
89 @GetMapping(TASK_VARIABLE)
90 R<Object> taskVariable(@RequestParam("taskId") String taskId, @RequestParam("variableName") String variableName);
91
92 /**
93 * 获取流程变量集合
94 *
95 * @param taskId 任务id
96 * @return R
97 */
98 @GetMapping(TASK_VARIABLES)
99 R<Map<String, Object>> taskVariables(@RequestParam("taskId") String taskId);
100 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.flow.core.feign;
18
19 import org.springblade.core.tool.api.R;
20 import org.springblade.flow.core.entity.BladeFlow;
21 import org.springframework.stereotype.Component;
22
23 import java.util.Map;
24
25 /**
26 * 流程远程调用失败处理类
27 *
28 * @author Chill
29 */
30 @Component
31 public class IFlowClientFallback implements IFlowClient {
32
33 @Override
34 public R<BladeFlow> startProcessInstanceById(String processDefinitionId, String businessKey, Map<String, Object> variables) {
35 return R.fail("远程调用失败");
36 }
37
38 @Override
39 public R<BladeFlow> startProcessInstanceByKey(String processDefinitionKey, String businessKey, Map<String, Object> variables) {
40 return R.fail("远程调用失败");
41 }
42
43 @Override
44 public R completeTask(String taskId, String processInstanceId, String comment, Map<String, Object> variables) {
45 return R.fail("远程调用失败");
46 }
47
48 @Override
49 public R<Object> taskVariable(String taskId, String variableName) {
50 return R.fail("远程调用失败");
51 }
52
53 @Override
54 public R<Map<String, Object>> taskVariables(String taskId) {
55 return R.fail("远程调用失败");
56 }
57
58 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.flow.core.utils;
18
19 import org.springblade.core.tool.utils.Func;
20 import org.springblade.core.tool.utils.StringUtil;
21 import org.springblade.flow.core.constant.ProcessConstant;
22
23 import java.util.HashMap;
24 import java.util.Map;
25
26 /**
27 * 工作流工具类
28 *
29 * @author Chill
30 */
31 public class FlowUtil {
32
33 /**
34 * 定义流程key对应的表名
35 */
36 private final static Map<String, String> BUSINESS_TABLE = new HashMap<>();
37
38 static {
39 BUSINESS_TABLE.put(ProcessConstant.LEAVE_KEY, "blade_process_leave");
40 }
41
42 /**
43 * 通过流程key获取业务表名
44 *
45 * @param key 流程key
46 */
47 public static String getBusinessTable(String key) {
48 String businessTable = BUSINESS_TABLE.get(key);
49 if (Func.isEmpty(businessTable)) {
50 throw new RuntimeException("流程启动失败,未找到相关业务表");
51 }
52 return businessTable;
53 }
54
55 /**
56 * 获取业务标识
57 *
58 * @param businessTable 业务表
59 * @param businessId 业务表主键
60 * @return businessKey
61 */
62 public static String getBusinessKey(String businessTable, String businessId) {
63 return StringUtil.format("{}:{}", businessTable, businessId);
64 }
65
66 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.flow.core.utils;
18
19 import org.springblade.core.secure.utils.SecureUtil;
20 import org.springblade.core.tool.utils.Func;
21 import org.springblade.core.tool.utils.StringUtil;
22
23 import static org.springblade.core.launch.constant.FlowConstant.TASK_USR_PREFIX;
24
25 /**
26 * 工作流任务工具类
27 *
28 * @author Chill
29 */
30 public class TaskUtil {
31
32 /**
33 * 获取任务用户格式
34 *
35 * @return taskUser
36 */
37 public static String getTaskUser() {
38 return StringUtil.format("{}{}", TASK_USR_PREFIX, SecureUtil.getUserId());
39 }
40
41 /**
42 * 获取任务用户格式
43 *
44 * @param userId 用户id
45 * @return taskUser
46 */
47 public static String getTaskUser(String userId) {
48 return StringUtil.format("{}{}", TASK_USR_PREFIX, userId);
49 }
50
51
52 /**
53 * 获取用户主键
54 *
55 * @param taskUser 任务用户
56 * @return userId
57 */
58 public static Long getUserId(String taskUser) {
59 return Func.toLong(StringUtil.removePrefix(taskUser, TASK_USR_PREFIX));
60 }
61
62 /**
63 * 获取用户组格式
64 *
65 * @return candidateGroup
66 */
67 public static String getCandidateGroup() {
68 return SecureUtil.getUserRole();
69 }
70
71 }
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <parent>
6 <artifactId>BladeX</artifactId>
7 <groupId>org.springblade</groupId>
8 <version>2.0.0.RELEASE</version>
9 </parent>
10 <modelVersion>4.0.0</modelVersion>
11
12 <artifactId>blade-ops-api</artifactId>
13 <name>${project.artifactId}</name>
14 <version>2.0.0.RELEASE</version>
15 <packaging>pom</packaging>
16 <description>BladeX 微服务API集合</description>
17
18 <modules>
19 <module>blade-flow-api</module>
20 </modules>
21
22 <dependencies>
23 <dependency>
24 <groupId>org.springblade</groupId>
25 <artifactId>blade-starter-mybatis</artifactId>
26 <version>${bladex.tool.version}</version>
27 </dependency>
28 <dependency>
29 <groupId>org.springframework.cloud</groupId>
30 <artifactId>spring-cloud-starter-openfeign</artifactId>
31 </dependency>
32 <dependency>
33 <groupId>org.springblade</groupId>
34 <artifactId>blade-core-auto</artifactId>
35 <version>${bladex.tool.version}</version>
36 <scope>provided</scope>
37 </dependency>
38 </dependencies>
39
40 <build>
41 <plugins>
42 <plugin>
43 <groupId>org.springframework.boot</groupId>
44 <artifactId>spring-boot-maven-plugin</artifactId>
45 <configuration>
46 <skip>true</skip>
47 <finalName>${project.name}</finalName>
48 </configuration>
49 </plugin>
50 <plugin>
51 <groupId>com.spotify</groupId>
52 <artifactId>docker-maven-plugin</artifactId>
53 <version>${docker.plugin.version}</version>
54 <configuration>
55 <skipDockerBuild>true</skipDockerBuild>
56 </configuration>
57 </plugin>
58 </plugins>
59 </build>
60
61 </project>
1 FROM anapsix/alpine-java:8_server-jre_unlimited
2
3 MAINTAINER smallchill@163.com
4
5 RUN mkdir -p /blade/admin
6
7 WORKDIR /blade/admin
8
9 EXPOSE 7002
10
11 ADD ./target/blade-admin.jar ./app.jar
12
13 ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"]
14
15 CMD ["--spring.profiles.active=test"]
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5 <parent>
6 <artifactId>blade-ops</artifactId>
7 <groupId>org.springblade</groupId>
8 <version>2.0.0.RELEASE</version>
9 </parent>
10 <modelVersion>4.0.0</modelVersion>
11
12 <artifactId>blade-admin</artifactId>
13 <name>${project.artifactId}</name>
14 <version>${bladex.project.version}</version>
15 <packaging>jar</packaging>
16
17 <dependencies>
18 <!--Blade-->
19 <dependency>
20 <groupId>org.springblade</groupId>
21 <artifactId>blade-common</artifactId>
22 <version>${bladex.project.version}</version>
23 </dependency>
24 <dependency>
25 <groupId>org.springblade</groupId>
26 <artifactId>blade-core-launch</artifactId>
27 <version>${bladex.tool.version}</version>
28 </dependency>
29 <dependency>
30 <groupId>org.springblade</groupId>
31 <artifactId>blade-core-tool</artifactId>
32 <version>${bladex.tool.version}</version>
33 </dependency>
34 <dependency>
35 <groupId>org.springblade</groupId>
36 <artifactId>blade-core-cloud</artifactId>
37 <version>${bladex.tool.version}</version>
38 <exclusions>
39 <exclusion>
40 <groupId>org.springblade</groupId>
41 <artifactId>blade-core-secure</artifactId>
42 </exclusion>
43 </exclusions>
44 </dependency>
45 <!--Admin-Server-->
46 <dependency>
47 <groupId>de.codecentric</groupId>
48 <artifactId>spring-boot-admin-starter-server</artifactId>
49 <version>${spring.boot.admin.version}</version>
50 </dependency>
51 </dependencies>
52
53 <build>
54 <plugins>
55 <plugin>
56 <groupId>com.spotify</groupId>
57 <artifactId>docker-maven-plugin</artifactId>
58 <version>${docker.plugin.version}</version>
59 <configuration>
60 <imageName>${docker.registry.url}/blade/${project.artifactId}:${project.version}</imageName>
61 <dockerDirectory>${project.basedir}</dockerDirectory>
62 <dockerHost>${docker.registry.host}</dockerHost>
63 <resources>
64 <resource>
65 <targetPath>/</targetPath>
66 <directory>${project.build.directory}</directory>
67 <include>${project.build.finalName}.jar</include>
68 </resource>
69 </resources>
70 <registryUrl>${docker.registry.url}</registryUrl>
71 <serverId>${docker.registry.url}</serverId>
72 <pushImage>true</pushImage>
73 </configuration>
74 </plugin>
75 <plugin>
76 <groupId>org.apache.maven.plugins</groupId>
77 <artifactId>maven-antrun-plugin</artifactId>
78 <executions>
79 <execution>
80 <phase>package</phase>
81 <goals>
82 <goal>run</goal>
83 </goals>
84 <configuration>
85 <tasks>
86 <copy overwrite="true"
87 tofile="${session.executionRootDirectory}/target/${project.artifactId}.jar"
88 file="${project.build.directory}/${project.artifactId}.jar" />
89 </tasks>
90 </configuration>
91 </execution>
92 </executions>
93 </plugin>
94 </plugins>
95 </build>
96
97 </project>
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.admin;
18
19 import de.codecentric.boot.admin.server.config.EnableAdminServer;
20 import org.springblade.core.launch.BladeApplication;
21 import org.springblade.core.launch.constant.AppConstant;
22 import org.springframework.cloud.client.SpringCloudApplication;
23
24 /**
25 * admin启动器
26 *
27 * @author Chill
28 */
29 @EnableAdminServer
30 @SpringCloudApplication
31 public class AdminApplication {
32
33 public static void main(String[] args) {
34 BladeApplication.run(AppConstant.APPLICATION_ADMIN_NAME, AdminApplication.class, args);
35 }
36
37 }
1 server:
2 port: 7002
3 undertow:
4 # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
5 io-threads: 4
6 # 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
7 worker-threads: 20
8 # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
9 buffer-size: 1024
10 # 是否分配的直接内存
11 direct-buffers: true
12
13 spring:
14 boot:
15 admin:
16 discovery:
17 ignored-services: consul
1 <?xml version="1.0"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
6 <parent>
7 <groupId>org.springblade</groupId>
8 <artifactId>blade-ops</artifactId>
9 <version>2.0.0.RELEASE</version>
10 </parent>
11
12 <modelVersion>4.0.0</modelVersion>
13
14 <artifactId>blade-develop</artifactId>
15 <name>${project.artifactId}</name>
16 <version>${bladex.project.version}</version>
17 <packaging>jar</packaging>
18
19 <dependencies>
20 <!--Blade-->
21 <dependency>
22 <groupId>org.springblade</groupId>
23 <artifactId>blade-core-boot</artifactId>
24 <version>${bladex.tool.version}</version>
25 </dependency>
26 <dependency>
27 <groupId>org.springblade</groupId>
28 <artifactId>blade-starter-develop</artifactId>
29 <version>${bladex.tool.version}</version>
30 </dependency>
31 <dependency>
32 <groupId>org.springblade</groupId>
33 <artifactId>blade-common</artifactId>
34 <version>${bladex.project.version}</version>
35 </dependency>
36 <dependency>
37 <groupId>org.springblade</groupId>
38 <artifactId>blade-dict-api</artifactId>
39 <version>${bladex.project.version}</version>
40 </dependency>
41 </dependencies>
42
43 <build>
44 <plugins>
45 <plugin>
46 <groupId>com.spotify</groupId>
47 <artifactId>docker-maven-plugin</artifactId>
48 <version>${docker.plugin.version}</version>
49 <configuration>
50 <skipDockerBuild>true</skipDockerBuild>
51 </configuration>
52 </plugin>
53 <plugin>
54 <groupId>org.apache.maven.plugins</groupId>
55 <artifactId>maven-antrun-plugin</artifactId>
56 <executions>
57 <execution>
58 <phase>package</phase>
59 <goals>
60 <goal>run</goal>
61 </goals>
62 <configuration>
63 <tasks>
64 <copy overwrite="true"
65 tofile="${session.executionRootDirectory}/target/${project.artifactId}.jar"
66 file="${project.build.directory}/${project.artifactId}.jar" />
67 </tasks>
68 </configuration>
69 </execution>
70 </executions>
71 </plugin>
72 </plugins>
73 </build>
74
75 </project>
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.develop;
18
19 import org.springblade.core.cloud.feign.EnableBladeFeign;
20 import org.springblade.core.launch.BladeApplication;
21 import org.springblade.core.launch.constant.AppConstant;
22 import org.springframework.cloud.client.SpringCloudApplication;
23
24 /**
25 * Develop启动器
26 *
27 * @author Chill
28 */
29 @EnableBladeFeign
30 @SpringCloudApplication
31 public class DevelopApplication {
32
33 public static void main(String[] args) {
34 BladeApplication.run(AppConstant.APPLICATION_DEVELOP_NAME, DevelopApplication.class, args);
35 }
36
37 }
38
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.develop.controller;
18
19 import com.baomidou.mybatisplus.core.metadata.IPage;
20 import io.swagger.annotations.*;
21 import lombok.AllArgsConstructor;
22 import org.springblade.core.boot.ctrl.BladeController;
23 import org.springblade.core.mp.support.Condition;
24 import org.springblade.core.mp.support.Query;
25 import org.springblade.core.secure.annotation.PreAuth;
26 import org.springblade.core.tool.api.R;
27 import org.springblade.core.tool.constant.RoleConstant;
28 import org.springblade.core.tool.utils.Func;
29 import org.springblade.develop.entity.Code;
30 import org.springblade.develop.service.ICodeService;
31 import org.springblade.develop.support.BladeCodeGenerator;
32 import org.springframework.data.redis.core.RedisTemplate;
33 import org.springframework.web.bind.annotation.*;
34 import springfox.documentation.annotations.ApiIgnore;
35
36 import javax.validation.Valid;
37 import java.util.Collection;
38 import java.util.Map;
39
40 /**
41 * 控制器
42 *
43 * @author Chill
44 */
45 @RestController
46 @AllArgsConstructor
47 @RequestMapping("/code")
48 @Api(value = "代码生成", tags = "代码生成")
49 @PreAuth(RoleConstant.HAS_ROLE_ADMINISTRATOR)
50 public class CodeController extends BladeController {
51
52 private ICodeService codeService;
53
54 /**
55 * 详情
56 */
57 @GetMapping("/detail")
58 @ApiOperation(value = "详情", notes = "传入code", position = 1)
59 public R<Code> detail(Code code) {
60 Code detail = codeService.getOne(Condition.getQueryWrapper(code));
61 return R.data(detail);
62 }
63
64 /**
65 * 分页
66 */
67 @GetMapping("/list")
68 @ApiImplicitParams({
69 @ApiImplicitParam(name = "codeName", value = "模块名", paramType = "query", dataType = "string"),
70 @ApiImplicitParam(name = "tableName", value = "表名", paramType = "query", dataType = "string"),
71 @ApiImplicitParam(name = "modelName", value = "实体名", paramType = "query", dataType = "string")
72 })
73 @ApiOperation(value = "分页", notes = "传入code", position = 2)
74 public R<IPage<Code>> list(@ApiIgnore @RequestParam Map<String, Object> code, Query query) {
75 IPage<Code> pages = codeService.page(Condition.getPage(query), Condition.getQueryWrapper(code, Code.class));
76 return R.data(pages);
77 }
78
79 /**
80 * 新增或修改
81 */
82 @PostMapping("/submit")
83 @ApiOperation(value = "新增或修改", notes = "传入code", position = 6)
84 public R submit(@Valid @RequestBody Code code) {
85 return R.status(codeService.saveOrUpdate(code));
86 }
87
88
89 /**
90 * 删除
91 */
92 @PostMapping("/remove")
93 @ApiOperation(value = "删除", notes = "传入ids", position = 7)
94 public R remove(@ApiParam(value = "主键集合", required = true) @RequestParam String ids) {
95 return R.status(codeService.removeByIds(Func.toLongList(ids)));
96 }
97
98 /**
99 * 代码生成
100 */
101 @PostMapping("/gen-code")
102 @ApiOperation(value = "代码生成", notes = "传入ids", position = 8)
103 public R genCode(@ApiParam(value = "主键集合", required = true) @RequestParam String ids, @RequestParam(defaultValue = "sword") String system) {
104 Collection<Code> codes = codeService.listByIds(Func.toLongList(ids));
105 codes.forEach(code -> {
106 BladeCodeGenerator generator = new BladeCodeGenerator();
107 generator.setSystemName(system);
108 generator.setServiceName(code.getServiceName());
109 generator.setCodeName(code.getCodeName());
110 generator.setPackageName(code.getPackageName());
111 generator.setPackageDir(code.getApiPath());
112 generator.setPackageWebDir(code.getWebPath());
113 generator.setTablePrefix(Func.toStrArray(code.getTablePrefix()));
114 generator.setIncludeTables(Func.toStrArray(code.getTableName()));
115 // 设置是否继承基础业务字段
116 generator.setHasSuperEntity(false);
117 generator.run();
118 });
119 return R.success("代码生成成功");
120 }
121
122 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.develop.entity;
18
19 import com.baomidou.mybatisplus.annotation.IdType;
20 import com.baomidou.mybatisplus.annotation.TableId;
21 import com.baomidou.mybatisplus.annotation.TableLogic;
22 import com.baomidou.mybatisplus.annotation.TableName;
23 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
24 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
25 import io.swagger.annotations.ApiModel;
26 import io.swagger.annotations.ApiModelProperty;
27 import lombok.Data;
28
29 import java.io.Serializable;
30
31 /**
32 * 实体类
33 *
34 * @author Chill
35 */
36 @Data
37 @TableName("blade_code")
38 @ApiModel(value = "Code对象", description = "Code对象")
39 public class Code implements Serializable {
40
41 private static final long serialVersionUID = 1L;
42
43 /**
44 * 主键
45 */
46 @JsonSerialize(using = ToStringSerializer.class)
47 @ApiModelProperty(value = "主键")
48 @TableId(value = "id", type = IdType.ID_WORKER)
49 private Long id;
50
51 /**
52 * 模块名称
53 */
54 @ApiModelProperty(value = "服务名称")
55 private String serviceName;
56
57 /**
58 * 模块名称
59 */
60 @ApiModelProperty(value = "模块名称")
61 private String codeName;
62
63 /**
64 * 表名
65 */
66 @ApiModelProperty(value = "表名")
67 private String tableName;
68
69 /**
70 * 实体名
71 */
72 @ApiModelProperty(value = "表前缀")
73 private String tablePrefix;
74
75 /**
76 * 主键名
77 */
78 @ApiModelProperty(value = "主键名")
79 private String pkName;
80
81 /**
82 * 后端包名
83 */
84 @ApiModelProperty(value = "后端包名")
85 private String packageName;
86
87 /**
88 * 后端路径
89 */
90 @ApiModelProperty(value = "后端路径")
91 private String apiPath;
92
93 /**
94 * 前端路径
95 */
96 @ApiModelProperty(value = "前端路径")
97 private String webPath;
98
99 /**
100 * 是否已删除
101 */
102 @TableLogic
103 @ApiModelProperty(value = "是否已删除")
104 private Integer isDeleted;
105
106
107 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.develop.mapper;
18
19 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
20 import org.springblade.develop.entity.Code;
21
22 /**
23 * Mapper 接口
24 *
25 * @author Chill
26 */
27 public interface CodeMapper extends BaseMapper<Code> {
28
29 }
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3 <mapper namespace="org.springblade.develop.mapper.CodeMapper">
4
5 <!-- 通用查询映射结果 -->
6 <resultMap id="codeResultMap" type="org.springblade.develop.entity.Code">
7 <id column="id" property="id"/>
8 <result column="service_name" property="serviceName"/>
9 <result column="code_name" property="codeName"/>
10 <result column="table_name" property="tableName"/>
11 <result column="pk_name" property="pkName"/>
12 <result column="table_prefix" property="tablePrefix"/>
13 <result column="package_name" property="packageName"/>
14 <result column="api_path" property="apiPath"/>
15 <result column="web_path" property="webPath"/>
16 <result column="is_deleted" property="isDeleted"/>
17 </resultMap>
18
19 <!-- 通用查询结果列 -->
20 <sql id="baseColumnList">
21 select
22 id, service_name, code_name, table_name, pk_name, model_name, package_name, api_path, web_path, is_deleted
23 </sql>
24
25 </mapper>
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.develop.service;
18
19
20 import com.baomidou.mybatisplus.extension.service.IService;
21 import org.springblade.develop.entity.Code;
22
23 /**
24 * 服务类
25 *
26 * @author Chill
27 */
28 public interface ICodeService extends IService<Code> {
29
30 }
1 /*
2 * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * Neither the name of the dreamlu.net developer nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 * Author: Chill 庄骞 (smallchill@163.com)
16 */
17 package org.springblade.develop.service.impl;
18
19 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
20 import org.springblade.develop.entity.Code;
21 import org.springblade.develop.mapper.CodeMapper;
22 import org.springblade.develop.service.ICodeService;
23 import org.springframework.stereotype.Service;
24
25 /**
26 * 服务实现类
27 *
28 * @author Chill
29 */
30 @Service
31 public class CodeServiceImpl extends ServiceImpl<CodeMapper, Code> implements ICodeService {
32
33 }
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'address', '智能公寓管理', 'menu', '/store/address', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'address_add', '新增', 'add', '/store/address/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'address_edit', '修改', 'edit', '/store/address/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'address_delete', '删除', 'delete', '/api/blade-store/address/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'address_view', '查看', 'view', '/store/address/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'agentprofile', '智能公寓管理', 'menu', '/user/agentprofile', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'agentprofile_add', '新增', 'add', '/user/agentprofile/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'agentprofile_edit', '修改', 'edit', '/user/agentprofile/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'agentprofile_delete', '删除', 'delete', '/api/blade-user/agentprofile/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'agentprofile_view', '查看', 'view', '/user/agentprofile/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'apartmentroom', '智能公寓管理', 'menu', '/user/apartmentroom', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'apartmentroom_add', '新增', 'add', '/user/apartmentroom/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'apartmentroom_edit', '修改', 'edit', '/user/apartmentroom/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'apartmentroom_delete', '删除', 'delete', '/api/blade-user/apartmentroom/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'apartmentroom_view', '查看', 'view', '/user/apartmentroom/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'apartmentuser', '智能公寓管理', 'menu', '/user/apartmentuser', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'apartmentuser_add', '新增', 'add', '/user/apartmentuser/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'apartmentuser_edit', '修改', 'edit', '/user/apartmentuser/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'apartmentuser_delete', '删除', 'delete', '/api/blade-user/apartmentuser/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'apartmentuser_view', '查看', 'view', '/user/apartmentuser/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'blockauth', '智能公寓管理', 'menu', '/user/blockauth', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'blockauth_add', '新增', 'add', '/user/blockauth/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'blockauth_edit', '修改', 'edit', '/user/blockauth/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'blockauth_delete', '删除', 'delete', '/api/blade-user/blockauth/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'blockauth_view', '查看', 'view', '/user/blockauth/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'category', '智能公寓管理', 'menu', '/store/category', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'category_add', '新增', 'add', '/store/category/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'category_edit', '修改', 'edit', '/store/category/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'category_delete', '删除', 'delete', '/api/blade-store/category/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'category_view', '查看', 'view', '/store/category/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'coupon', '智能公寓管理', 'menu', '/store/coupon', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'coupon_add', '新增', 'add', '/store/coupon/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'coupon_edit', '修改', 'edit', '/store/coupon/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'coupon_delete', '删除', 'delete', '/api/blade-store/coupon/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'coupon_view', '查看', 'view', '/store/coupon/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'customerservice', '智能公寓管理', 'menu', '/user/customerservice', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'customerservice_add', '新增', 'add', '/user/customerservice/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'customerservice_edit', '修改', 'edit', '/user/customerservice/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'customerservice_delete', '删除', 'delete', '/api/blade-user/customerservice/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'customerservice_view', '查看', 'view', '/user/customerservice/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'customerservicestaff', '智能公寓管理', 'menu', '/user/customerservicestaff', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'customerservicestaff_add', '新增', 'add', '/user/customerservicestaff/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'customerservicestaff_edit', '修改', 'edit', '/user/customerservicestaff/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'customerservicestaff_delete', '删除', 'delete', '/api/blade-user/customerservicestaff/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'customerservicestaff_view', '查看', 'view', '/user/customerservicestaff/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'equipment', '智能公寓管理', 'menu', '/user/equipment', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'equipment_add', '新增', 'add', '/user/equipment/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'equipment_edit', '修改', 'edit', '/user/equipment/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'equipment_delete', '删除', 'delete', '/api/blade-user/equipment/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'equipment_view', '查看', 'view', '/user/equipment/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'equipmentalarmlog', '智能公寓管理', 'menu', '/user/equipmentalarmlog', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'equipmentalarmlog_add', '新增', 'add', '/user/equipmentalarmlog/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'equipmentalarmlog_edit', '修改', 'edit', '/user/equipmentalarmlog/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'equipmentalarmlog_delete', '删除', 'delete', '/api/blade-user/equipmentalarmlog/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'equipmentalarmlog_view', '查看', 'view', '/user/equipmentalarmlog/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'equipmentopenlog', '智能公寓管理', 'menu', '/user/equipmentopenlog', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'equipmentopenlog_add', '新增', 'add', '/user/equipmentopenlog/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'equipmentopenlog_edit', '修改', 'edit', '/user/equipmentopenlog/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'equipmentopenlog_delete', '删除', 'delete', '/api/blade-user/equipmentopenlog/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'equipmentopenlog_view', '查看', 'view', '/user/equipmentopenlog/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'equipmentpwd', '智能公寓管理', 'menu', '/user/equipmentpwd', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'equipmentpwd_add', '新增', 'add', '/user/equipmentpwd/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'equipmentpwd_edit', '修改', 'edit', '/user/equipmentpwd/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'equipmentpwd_delete', '删除', 'delete', '/api/blade-user/equipmentpwd/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'equipmentpwd_view', '查看', 'view', '/user/equipmentpwd/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'equipmentrepair', '智能公寓管理', 'menu', '/user/equipmentrepair', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'equipmentrepair_add', '新增', 'add', '/user/equipmentrepair/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'equipmentrepair_edit', '修改', 'edit', '/user/equipmentrepair/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'equipmentrepair_delete', '删除', 'delete', '/api/blade-user/equipmentrepair/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'equipmentrepair_view', '查看', 'view', '/user/equipmentrepair/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'equipmentrepairresource', '智能公寓管理', 'menu', '/apartment/equipmentrepairresource', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'equipmentrepairresource_add', '新增', 'add', '/apartment/equipmentrepairresource/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'equipmentrepairresource_edit', '修改', 'edit', '/apartment/equipmentrepairresource/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'equipmentrepairresource_delete', '删除', 'delete', '/api/blade-apartment/equipmentrepairresource/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'equipmentrepairresource_view', '查看', 'view', '/apartment/equipmentrepairresource/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'equipmentreset', '智能公寓管理', 'menu', '/user/equipmentreset', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'equipmentreset_add', '新增', 'add', '/user/equipmentreset/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'equipmentreset_edit', '修改', 'edit', '/user/equipmentreset/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'equipmentreset_delete', '删除', 'delete', '/api/blade-user/equipmentreset/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'equipmentreset_view', '查看', 'view', '/user/equipmentreset/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'equipmenttype', '智能公寓管理', 'menu', '/user/equipmenttype', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'equipmenttype_add', '新增', 'add', '/user/equipmenttype/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'equipmenttype_edit', '修改', 'edit', '/user/equipmenttype/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'equipmenttype_delete', '删除', 'delete', '/api/blade-user/equipmenttype/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'equipmenttype_view', '查看', 'view', '/user/equipmenttype/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'iaorder', '智能公寓管理', 'menu', '/apartment/iaorder', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'iaorder_add', '新增', 'add', '/apartment/iaorder/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'iaorder_edit', '修改', 'edit', '/apartment/iaorder/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'iaorder_delete', '删除', 'delete', '/api/blade-apartment/iaorder/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'iaorder_view', '查看', 'view', '/apartment/iaorder/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'iaorderlog', '智能公寓管理', 'menu', '/apartment/iaorderlog', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'iaorderlog_add', '新增', 'add', '/apartment/iaorderlog/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'iaorderlog_edit', '修改', 'edit', '/apartment/iaorderlog/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'iaorderlog_delete', '删除', 'delete', '/api/blade-apartment/iaorderlog/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'iaorderlog_view', '查看', 'view', '/apartment/iaorderlog/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'iaordertenant', '智能公寓管理', 'menu', '/apartment/iaordertenant', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'iaordertenant_add', '新增', 'add', '/apartment/iaordertenant/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'iaordertenant_edit', '修改', 'edit', '/apartment/iaordertenant/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'iaordertenant_delete', '删除', 'delete', '/api/blade-apartment/iaordertenant/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'iaordertenant_view', '查看', 'view', '/apartment/iaordertenant/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'lockauth', '智能公寓管理', 'menu', '/user/lockauth', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'lockauth_add', '新增', 'add', '/user/lockauth/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'lockauth_edit', '修改', 'edit', '/user/lockauth/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'lockauth_delete', '删除', 'delete', '/api/blade-user/lockauth/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'lockauth_view', '查看', 'view', '/user/lockauth/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'lockmq', '智能公寓管理', 'menu', '/user/lockmq', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'lockmq_add', '新增', 'add', '/user/lockmq/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'lockmq_edit', '修改', 'edit', '/user/lockmq/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'lockmq_delete', '删除', 'delete', '/api/blade-user/lockmq/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'lockmq_view', '查看', 'view', '/user/lockmq/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'nokeybackmsg', '智能公寓管理', 'menu', '/user/nokeybackmsg', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'nokeybackmsg_add', '新增', 'add', '/user/nokeybackmsg/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'nokeybackmsg_edit', '修改', 'edit', '/user/nokeybackmsg/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'nokeybackmsg_delete', '删除', 'delete', '/api/blade-user/nokeybackmsg/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'nokeybackmsg_view', '查看', 'view', '/user/nokeybackmsg/view', 'file-text', 4, 2, 2, 2, NULL, 0);
1 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
2 VALUES (0, 'noticemessage', '智能公寓管理', 'menu', '/user/noticemessage', NULL, 1, 1, 0, 1, NULL, 0);
3 set @parentid = (SELECT LAST_INSERT_ID());
4 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
5 VALUES (@parentid, 'noticemessage_add', '新增', 'add', '/user/noticemessage/add', 'plus', 1, 2, 1, 1, NULL, 0);
6 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
7 VALUES (@parentid, 'noticemessage_edit', '修改', 'edit', '/user/noticemessage/edit', 'form', 2, 2, 2, 2, NULL, 0);
8 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
9 VALUES (@parentid, 'noticemessage_delete', '删除', 'delete', '/api/blade-user/noticemessage/remove', 'delete', 3, 2, 3, 3, NULL, 0);
10 INSERT INTO `blade_menu`(`parent_id`, `code`, `name`, `alias`, `path`, `source`, `sort`, `category`, `action`, `is_open`, `remark`, `is_deleted`)
11 VALUES (@parentid, 'noticemessage_view', '查看', 'view', '/user/noticemessage/view', 'file-text', 4, 2, 2, 2, NULL, 0);
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!