<|start_filename|>ace-modules/ace-generator/src/main/java/com/github/wxiaoqi/security/generator/rest/GeneratorRest.java<|end_filename|>
/*
 *  Copyright (C) 2018  老干爹<<EMAIL>>

 *  Boot-Platform 企业版源码
 *  郑重声明:
 *  如果你从其他途径获取到，请告知老干爹传播人，奖励1000。
 *  老干爹将追究授予人和传播人的法律责任!

 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.

 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package com.github.wxiaoqi.security.generator.rest;

import com.alibaba.druid.pool.DruidDataSource;
import com.github.wxiaoqi.security.common.msg.TableResultResponse;
import com.github.wxiaoqi.security.common.util.Query;
import com.github.wxiaoqi.security.generator.config.SwitchDB;
import com.github.wxiaoqi.security.generator.service.GeneratorService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 老干爹 on 2017/8/25.
 */
@Controller
@RequestMapping("/code/generator")
public class GeneratorRest {

    @Autowired
    private GeneratorService generatorService;

    @Autowired
    private SwitchDB switchDB;

    @Autowired
    private List<DruidDataSource> source;

    /**
     * 列表
     */
    @ResponseBody
    @RequestMapping("/dbs")
    public TableResultResponse<String> getDbList() {
        return new TableResultResponse(new Long(source.size()), source.stream().map(DruidDataSource::getName).collect(Collectors.toList()));
    }

    /**
     * 列表
     */
    @ResponseBody
    @RequestMapping("/page")
    public TableResultResponse<Map<String, Object>> list(@RequestParam Map<String, Object> params) {
        String dbName = String.valueOf(params.get("dbName"));
        switchDB.change(dbName);
        Query query = new Query(params);
        List<Map<String, Object>> result = generatorService.queryList(query);
        int total = generatorService.queryTotal(query);
        return new TableResultResponse(total, result);
    }

    /**
     * 生成代码
     */
    @RequestMapping("/build")
    public void code(String tables, String path, String mainModule, String author, String dbName, String tablePrefix, HttpServletResponse response) throws IOException {
        if (StringUtils.isNoneBlank(tables)) {
            switchDB.change(dbName);
            byte[] data = generatorService.generatorCode(tables.split(","), path, mainModule, author, tablePrefix);
            response.reset();
            response.setHeader("Content-Disposition", "attachment; filename=\"generator-code.zip\"");
            response.addHeader("Content-Length", "" + data.length);
            response.setContentType("application/octet-stream; charset=UTF-8");
            IOUtils.write(data, response.getOutputStream());
        }
    }
}


<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/admin/mapper/GateLogMapper.java<|end_filename|>
package com.github.wxiaoqi.security.modules.admin.mapper;

import com.github.wxiaoqi.security.modules.admin.entity.GateLog;
import tk.mybatis.mapper.common.Mapper;

public interface GateLogMapper extends Mapper<GateLog> {
}

<|start_filename|>ace-dev-base/ace-common/src/main/java/com/github/wxiaoqi/security/common/msg/ObjectRestResponse.java<|end_filename|>
package com.github.wxiaoqi.security.common.msg;

/**
 * Created by Ace on 2017/6/11.
 */
public class ObjectRestResponse<T> extends BaseResponse {

    T data;
    
    public ObjectRestResponse data(T data) {
        this.setData(data);
        return this;
    }
    public T getData() {
        return data;
    }

    public ObjectRestResponse setData(T data) {
        this.data = data;
        return this;
    }


}


<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/admin/vo/FrontUserV2.java<|end_filename|>
package com.github.wxiaoqi.security.modules.admin.vo;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by ace on 2017/8/22.
 */
@Data
public class FrontUserV2 {
    /**
     * 头像地址
     */
    public String avatarUrl;
    /**
     * 昵称
     */
    public String userName;
    /**
     * 角色列表
     */
    public List<String> userRoles;
    /**
     * 用户动作权限编码
     */
    private List<String> userPermissions = new ArrayList<>();
    /**
     * 可访问菜单
     */
    private List<AccessMenuTree> accessMenus = new ArrayList<>();

    private List<AccessMenuTree> accessHeader = new ArrayList<>();
    /**
     * 可访问路由
     */
    private List<AccessRouteTree> accessRoutes = new ArrayList<>();

    /**
     * 可访问接口
     */
    private List<AccessInterface> accessInterfaces = new ArrayList<>();

    private String isAdmin = "0";

}


<|start_filename|>ace-api/src/main/java/com/github/wxiaoqi/security/api/vo/authority/CheckPermissionInfo.java<|end_filename|>
package com.github.wxiaoqi.security.api.vo.authority;

import lombok.Data;

import java.util.function.Consumer;

/**
 * @author <NAME>
 * @create 2020/7/23.
 */
@Data
public class CheckPermissionInfo{
    // 请求权限资源
    private PermissionInfo permissionInfo;
    // 是否有权限
    private Boolean isAuth;
}


<|start_filename|>ace-modules/ace-generator/src/main/java/com/github/wxiaoqi/security/generator/entity/ColumnEntity.java<|end_filename|>
/*
 *  Copyright (C) 2018  老干爹<<EMAIL>>

 *  Boot-Platform 企业版源码
 *  郑重声明:
 *  如果你从其他途径获取到，请告知老干爹传播人，奖励1000。
 *  老干爹将追究授予人和传播人的法律责任!

 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.

 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package com.github.wxiaoqi.security.generator.entity;

/**
 * 列的属性
 *
 * @author 老干爹
 * @email <EMAIL>
 * @version 2017年08月25日
 */
public class ColumnEntity {
	//列名
    private String columnName;
    //列名类型
    private String dataType;
    //列名备注
    private String comments;
    
    //属性名称(第一个字母大写)，如：user_name => UserName
    private String attrName;
    //属性名称(第一个字母小写)，如：user_name => userName
    private String attrname;
    //属性类型
    private String attrType;
    //auto_increment
    private String extra;
    
	public String getColumnName() {
		return columnName;
	}
	public void setColumnName(String columnName) {
		this.columnName = columnName;
	}
	public String getDataType() {
		return dataType;
	}
	public void setDataType(String dataType) {
		this.dataType = dataType;
	}
	public String getComments() {
		return comments;
	}
	public void setComments(String comments) {
		this.comments = comments;
	}
	public String getAttrname() {
		return attrname;
	}
	public void setAttrname(String attrname) {
		this.attrname = attrname;
	}
	public String getAttrName() {
		return attrName;
	}
	public void setAttrName(String attrName) {
		this.attrName = attrName;
	}
	public String getAttrType() {
		return attrType;
	}
	public void setAttrType(String attrType) {
		this.attrType = attrType;
	}
	public String getExtra() {
		return extra;
	}
	public void setExtra(String extra) {
		this.extra = extra;
	}
}


<|start_filename|>ace-gate/src/main/java/com/github/wxiaoqi/security/gate/handler/RequestBodyRoutePredicateFactory.java<|end_filename|>
/*
 * Copyright 2013-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.github.wxiaoqi.security.gate.handler;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.gateway.handler.AsyncPredicate;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * This predicate is BETA and may be subject to change in a future release.
 */
@Slf4j
@Component
@Order(1)
public class RequestBodyRoutePredicateFactory
        extends AbstractRoutePredicateFactory<RequestBodyRoutePredicateFactory.Config> {
    protected static final Log LOGGER = LogFactory.getLog(RequestBodyRoutePredicateFactory.class);
    private final List<HttpMessageReader<?>> messageReaders;

    public RequestBodyRoutePredicateFactory() {
        super(RequestBodyRoutePredicateFactory.Config.class);
        this.messageReaders = HandlerStrategies.withDefaults().messageReaders();
    }

    public RequestBodyRoutePredicateFactory(List<HttpMessageReader<?>> messageReaders) {
        super(RequestBodyRoutePredicateFactory.Config.class);
        this.messageReaders = messageReaders;
    }
    public static final String REQUEST_BODY_ATTR = "requestBodyAttr";


    @Override
    public AsyncPredicate<ServerWebExchange> applyAsync(Config config) {
        return exchange -> {
            if (!"POST".equals(exchange.getRequest().getMethodValue())&&!"PUT".equals(exchange.getRequest().getMethodValue())) {
                return Mono.just(true);
            }
            Object cachedBody = exchange.getAttribute(REQUEST_BODY_ATTR);
            if (cachedBody != null) {
                try {
                    return Mono.just(true);
                } catch (ClassCastException e) {
                    if (LOGGER.isDebugEnabled()) {
                        LOGGER.debug("Predicate test failed because class in predicate does not match the cached body object",
                                e);
                    }
                }
                return Mono.just(true);
            } else {
                return ServerWebExchangeUtils.cacheRequestBodyAndRequest(exchange, (serverHttpRequest) -> ServerRequest.create(exchange.mutate().request(serverHttpRequest).build(), this.messageReaders).bodyToMono(String.class).defaultIfEmpty("").doOnNext((objectValue) -> {
                    if(StringUtils.isBlank(objectValue)){
                        exchange.getAttributes().put(REQUEST_BODY_ATTR, JSON.toJSONString(exchange.getRequest().getQueryParams()));
                    }else {
                        exchange.getAttributes().put(REQUEST_BODY_ATTR, objectValue);
                    }
                }).map((objectValue) -> true));

            }
        };
    }

    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        throw new UnsupportedOperationException(
                "ReadBodyPredicateFactory is only async.");
    }

    public static class Config {
        private List<String> sources = new ArrayList<>();

        public List<String> getSources() {
            return sources;
        }

        public RequestBodyRoutePredicateFactory.Config setSources(List<String> sources) {
            this.sources = sources;
            return this;
        }

        public RequestBodyRoutePredicateFactory.Config setSources(String... sources) {
            this.sources = Arrays.asList(sources);
            return this;
        }
    }
}


<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/admin/mapper/UserMapper.java<|end_filename|>
package com.github.wxiaoqi.security.modules.admin.mapper;

import com.github.wxiaoqi.security.modules.admin.entity.User;
import org.apache.ibatis.annotations.Param;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

public interface UserMapper extends Mapper<User> {
    public List<User> selectMemberByGroupId(@Param("groupId") int groupId);
    public List<User> selectLeaderByGroupId(@Param("groupId") int groupId);
}

<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/admin/mapper/GroupTypeMapper.java<|end_filename|>
package com.github.wxiaoqi.security.modules.admin.mapper;

import com.github.wxiaoqi.security.modules.admin.entity.GroupType;
import tk.mybatis.mapper.common.Mapper;

public interface GroupTypeMapper extends Mapper<GroupType> {
}

<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/auth/util/user/JwtAuthenticationRequest.java<|end_filename|>
package com.github.wxiaoqi.security.modules.auth.util.user;

import java.io.Serializable;

public class JwtAuthenticationRequest implements Serializable {

    private static final long serialVersionUID = -8445943548965154778L;

    private String username;
    private String password;
    private String verCode;
    private String uuid;

    public JwtAuthenticationRequest(String username, String password, String verCode, String uuid) {
        this.username = username;
        this.password = password;
        this.verCode = verCode;
        this.uuid = uuid;
    }

    public JwtAuthenticationRequest() {
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getVerCode() {
        return verCode;
    }

    public void setVerCode(String verCode) {
        this.verCode = verCode;
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }
}


<|start_filename|>ace-modules/ace-sample/src/main/java/com/github/wxiaoqi/security/sample/rest/SampleDataTestController.java<|end_filename|>
package com.github.wxiaoqi.security.sample.rest;

import com.github.wxiaoqi.security.common.context.BaseContextHandler;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.rest.BaseController;
import com.github.wxiaoqi.security.sample.biz.SampleDataTestBiz;
import com.github.wxiaoqi.security.sample.entity.SampleDataTest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("sampleDataTest")
public class SampleDataTestController extends BaseController<SampleDataTestBiz,SampleDataTest> {
    @GetMapping("/who")
    public ObjectRestResponse<String> whoAmI(){
        return new ObjectRestResponse<>().data(BaseContextHandler.getName());
    }
}

<|start_filename|>ace-modules/ace-generator/src/main/java/com/github/wxiaoqi/security/generator/config/DynamicDatasourceConfig.java<|end_filename|>
package com.github.wxiaoqi.security.generator.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author laogandie
 * @create 2020/1/28.
 */
@Configuration
@AutoConfigureAfter(DataSourceConfigurer.class)
public class DynamicDatasourceConfig {
    @Autowired
    private List<DruidDataSource> source;

    /**
     * spring boot 启动后将自定义创建好的数据源对象放到TargetDataSources中用于后续的切换数据源用
     *             (比如：DynamicDataSourceContextHolder.setDataSourceKey("dbMall")，手动切换到dbMall数据源
     * 同时指定默认数据源连接
     * @return 动态数据源对象
     */
    @Bean
    @Primary
    public DynamicDataSource dynamicDataSource() {
        //获取动态数据库的实例（单例方式）
        DynamicDataSource dynamicDataSource = DynamicDataSource.getInstance();
//        //创建默认数据库连接对象
        DruidDataSource defaultDataSource = source.get(0);

        Map<Object,Object> map = new HashMap<>();
        //自定义数据源key值，将创建好的数据源对象，赋值到targetDataSources中,用于切换数据源时指定对应key即可切换
        for(DruidDataSource dataSource:source) {
            map.put(dataSource.getName(), dataSource);
        }
        dynamicDataSource.setTargetDataSources(map);
        //设置默认数据源
        dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);

        return dynamicDataSource;
    }

    /**
     * 将动态数据源添加到事务管理器中，并生成新的bean
     * @return the platform transaction manager
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}


<|start_filename|>ace-modules/ace-generator/src/main/java/com/github/wxiaoqi/security/generator/entity/TableEntity.java<|end_filename|>
/*
 *  Copyright (C) 2018  老干爹<<EMAIL>>

 *  Boot-Platform 企业版源码
 *  郑重声明:
 *  如果你从其他途径获取到，请告知老干爹传播人，奖励1000。
 *  老干爹将追究授予人和传播人的法律责任!

 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.

 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package com.github.wxiaoqi.security.generator.entity;

import java.util.List;

/**
 * 表数据
 *
 * @author 老干爹
 * @email <EMAIL>
 * @version 2017年08月25日
 */
public class TableEntity {
	//表的名称
	private String tableName;
	//表的备注
	private String comments;
	//表的主键
	private ColumnEntity pk;
	//表的列名(不包含主键)
	private List<ColumnEntity> columns;
	
	//类名(第一个字母大写)，如：sys_user => SysUser
	private String className;
	//类名(第一个字母小写)，如：sys_user => sysUser
	private String classname;
	
	public String getTableName() {
		return tableName;
	}
	public void setTableName(String tableName) {
		this.tableName = tableName;
	}
	public String getComments() {
		return comments;
	}
	public void setComments(String comments) {
		this.comments = comments;
	}
	public ColumnEntity getPk() {
		return pk;
	}
	public void setPk(ColumnEntity pk) {
		this.pk = pk;
	}
	public List<ColumnEntity> getColumns() {
		return columns;
	}
	public void setColumns(List<ColumnEntity> columns) {
		this.columns = columns;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	public String getClassname() {
		return classname;
	}
	public void setClassname(String classname) {
		this.classname = classname;
	}
}


<|start_filename|>ace-modules/ace-generator/src/main/java/com/github/wxiaoqi/security/generator/config/DynamicDataSource.java<|end_filename|>
package com.github.wxiaoqi.security.generator.config;

/**
 * @author laogandie
 * @create 2020/1/28.
 */
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import java.util.HashMap;
import java.util.Map;

/**
 * 动态数据设置以及获取，本类属于单例
 * @author lxf 2018-09-29
 */
//@Component
public class DynamicDataSource extends AbstractRoutingDataSource {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    //单例句柄
    private static DynamicDataSource instance;
    private static byte[] lock=new byte[0];
    //用于存储已实例的数据源map
    private static Map<Object,Object> dataSourceMap=new HashMap<Object, Object>();

    /**
     * 获取当前数据源
     * @return
     */
    @Override
    protected Object determineCurrentLookupKey() {
        logger.info("Current DataSource is [{}]", DynamicDataSourceContextHolder.getDataSourceKey());
        return DynamicDataSourceContextHolder.getDataSourceKey();
    }

    /**
     * 设置数据源
     * @param targetDataSources
     */
    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        super.setTargetDataSources(targetDataSources);
        dataSourceMap.putAll(targetDataSources);
        super.afterPropertiesSet();// 必须添加该句，否则新添加数据源无法识别到
    }

    /**
     * 获取存储已实例的数据源map
     * @return
     */
    public Map<Object, Object> getDataSourceMap() {
        return dataSourceMap;
    }

    /**
     * 单例方法
     * @return
     */
    public static synchronized DynamicDataSource getInstance(){
        if(instance==null){
            synchronized (lock){
                if(instance==null){
                    instance=new DynamicDataSource();
                }
            }
        }
        return instance;
    }

    /**
     * 是否存在当前key的 DataSource
     * @param key
     * @return 存在返回 true, 不存在返回 false
     */
    public static boolean isExistDataSource(String key) {
        return dataSourceMap.containsKey(key);
    }
}

<|start_filename|>ace-modules/ace-generator/src/main/java/com/github/wxiaoqi/security/generator/utils/DateUtils.java<|end_filename|>
/*
 *  Copyright (C) 2018  老干爹<<EMAIL>>

 *  Boot-Platform 企业版源码
 *  郑重声明:
 *  如果你从其他途径获取到，请告知老干爹传播人，奖励1000。
 *  老干爹将追究授予人和传播人的法律责任!

 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.

 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.

 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package com.github.wxiaoqi.security.generator.utils;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtils {
	/** 时间格式(yyyy-MM-dd) */
	public final static String DATE_PATTERN = "yyyy-MM-dd";
	/** 时间格式(yyyy-MM-dd HH:mm:ss) */
	public final static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
	
	public static String format(Date date) {
        return format(date, DATE_PATTERN);
    }

    public static String format(Date date, String pattern) {
        if(date != null){
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }
}


<|start_filename|>ace-modules/ace-sample/src/main/java/com/github/wxiaoqi/security/sample/entity/SampleDataTest.java<|end_filename|>
package com.github.wxiaoqi.security.sample.entity;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.util.Date;


/**
 * 
 * 
 * @author 老干爹
 * @email <EMAIL>
 * @version 2020-09-05 10:33:41
 */
@Table(name = "sample_data_test")
public class SampleDataTest implements Serializable {
	private static final long serialVersionUID = 1L;
	
	    //
    @Id
    private Integer id;
	
	    //
    @Column(name = "name")
    private String name;
	
	    //
    @Column(name = "depart_id")
    private String departId;
	
	    //创建人
    @Column(name = "crt_user_name")
    private String crtUserName;
	
	    //创建人ID
    @Column(name = "crt_user_id")
    private String crtUserId;
	
	    //创建时间
    @Column(name = "crt_time")
    private Date crtTime;
	
	    //最后更新人
    @Column(name = "upd_user_name")
    private String updUserName;
	
	    //最后更新人ID
    @Column(name = "upd_user_id")
    private String updUserId;
	
	    //最后更新时间
    @Column(name = "upd_time")
    private Date updTime;
	
	    //租户ID
    @Column(name = "tenant_id")
    private String tenantId;
	

	/**
	 * 设置：
	 */
	public void setId(Integer id) {
		this.id = id;
	}
	/**
	 * 获取：
	 */
	public Integer getId() {
		return id;
	}
	/**
	 * 设置：
	 */
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * 获取：
	 */
	public String getName() {
		return name;
	}
	/**
	 * 设置：
	 */
	public void setDepartId(String departId) {
		this.departId = departId;
	}
	/**
	 * 获取：
	 */
	public String getDepartId() {
		return departId;
	}
	/**
	 * 设置：创建人
	 */
	public void setCrtUserName(String crtUserName) {
		this.crtUserName = crtUserName;
	}
	/**
	 * 获取：创建人
	 */
	public String getCrtUserName() {
		return crtUserName;
	}
	/**
	 * 设置：创建人ID
	 */
	public void setCrtUserId(String crtUserId) {
		this.crtUserId = crtUserId;
	}
	/**
	 * 获取：创建人ID
	 */
	public String getCrtUserId() {
		return crtUserId;
	}
	/**
	 * 设置：创建时间
	 */
	public void setCrtTime(Date crtTime) {
		this.crtTime = crtTime;
	}
	/**
	 * 获取：创建时间
	 */
	public Date getCrtTime() {
		return crtTime;
	}
	/**
	 * 设置：最后更新人
	 */
	public void setUpdUserName(String updUserName) {
		this.updUserName = updUserName;
	}
	/**
	 * 获取：最后更新人
	 */
	public String getUpdUserName() {
		return updUserName;
	}
	/**
	 * 设置：最后更新人ID
	 */
	public void setUpdUserId(String updUserId) {
		this.updUserId = updUserId;
	}
	/**
	 * 获取：最后更新人ID
	 */
	public String getUpdUserId() {
		return updUserId;
	}
	/**
	 * 设置：最后更新时间
	 */
	public void setUpdTime(Date updTime) {
		this.updTime = updTime;
	}
	/**
	 * 获取：最后更新时间
	 */
	public Date getUpdTime() {
		return updTime;
	}
	/**
	 * 设置：租户ID
	 */
	public void setTenantId(String tenantId) {
		this.tenantId = tenantId;
	}
	/**
	 * 获取：租户ID
	 */
	public String getTenantId() {
		return tenantId;
	}
}


<|start_filename|>ace-gate/src/main/docker/Dockerfile<|end_filename|>
FROM livingobjects/jre8
VOLUME /tmp
# 将jar包添加到容器中并更名为app.jar
ADD ace-gate.jar app.jar
# 运行jar包
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/auth/controller/ServiceController.java<|end_filename|>
package com.github.wxiaoqi.security.modules.auth.controller;

import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.rest.BaseController;
import com.github.wxiaoqi.security.modules.auth.biz.ClientBiz;
import com.github.wxiaoqi.security.modules.auth.entity.Client;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * @author ace
 * @create 2017/12/26.
 */
@RestController
@RequestMapping("service")
public class ServiceController extends BaseController<ClientBiz,Client>{

    @RequestMapping(value = "/{id}/client", method = RequestMethod.PUT)
    @ResponseBody
    public ObjectRestResponse modifyUsers(@PathVariable int id, String clients){
        baseBiz.modifyClientServices(id, clients);
        return new ObjectRestResponse();
    }

    @RequestMapping(value = "/{id}/client", method = RequestMethod.GET)
    @ResponseBody
    public ObjectRestResponse<List<Client>> getUsers(@PathVariable int id){
        return new ObjectRestResponse<List<Client>>().data(baseBiz.getClientServices(id));
    }
}


<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/admin/rpc/service/PermissionService.java<|end_filename|>
package com.github.wxiaoqi.security.modules.admin.rpc.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.api.vo.authority.CheckPermissionInfo;
import com.github.wxiaoqi.security.api.vo.authority.PermissionInfo;
import com.github.wxiaoqi.security.api.vo.user.UserInfo;
import com.github.wxiaoqi.security.common.constant.CommonConstants;
import com.github.wxiaoqi.security.common.context.BaseContextHandler;
import com.github.wxiaoqi.security.common.util.TreeUtil;
import com.github.wxiaoqi.security.modules.admin.biz.ElementBiz;
import com.github.wxiaoqi.security.modules.admin.biz.MenuBiz;
import com.github.wxiaoqi.security.modules.admin.biz.UserBiz;
import com.github.wxiaoqi.security.modules.admin.constant.AdminCommonConstant;
import com.github.wxiaoqi.security.common.constant.RedisKeyConstant;
import com.github.wxiaoqi.security.modules.admin.entity.Element;
import com.github.wxiaoqi.security.modules.admin.entity.Menu;
import com.github.wxiaoqi.security.modules.admin.entity.User;
import com.github.wxiaoqi.security.modules.admin.util.Sha256PasswordEncoder;
import com.github.wxiaoqi.security.modules.admin.vo.*;
import com.github.wxiaoqi.security.modules.auth.util.user.JwtTokenUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Created by ace on 2017/9/12.
 */
@Service
public class PermissionService {
    @Autowired
    private UserBiz userBiz;
    @Autowired
    private MenuBiz menuBiz;
    @Autowired
    private ElementBiz elementBiz;
    @Autowired
    private JwtTokenUtil userAuthUtil;
    private Sha256PasswordEncoder encoder = new Sha256PasswordEncoder();

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public UserInfo getUserByUsername(String username) {
        UserInfo info = new UserInfo();
        User user = userBiz.getUserByUsername(username);
        BeanUtils.copyProperties(user, info);
        info.setId(user.getId().toString());
        return info;
    }

    public UserInfo validate(String username, String password) {
        UserInfo info = new UserInfo();
        User user = userBiz.getUserByUsername(username);
        if (encoder.matches(password, user.getPassword())) {
            BeanUtils.copyProperties(user, info);
            info.setId(user.getId().toString());
        }
        return info;
    }

    public List<PermissionInfo> getAllPermission() {
        String key = RedisKeyConstant.REDIS_KEY_ALL_PERMISISON;
        String s = stringRedisTemplate.opsForValue().get(key);
        if (s == null || org.apache.commons.lang.StringUtils.isBlank(s)) {
            List<Menu> menus = menuBiz.selectListAll();
            List<PermissionInfo> result = new ArrayList<PermissionInfo>();
            menu2permission(menus, result);
            List<Element> elements = elementBiz.getAllElementPermissions();
            element2permission(result, elements);
            s = JSON.toJSONString(result);
            stringRedisTemplate.opsForValue().set(key, s, 12, TimeUnit.HOURS);
        }
        List<PermissionInfo> permissionInfos = JSON.parseArray(s, PermissionInfo.class);
        return permissionInfos;
    }

    private void menu2permission(List<Menu> menus, List<PermissionInfo> result) {
        PermissionInfo info;
        for (Menu menu : menus) {
            if (StringUtils.isBlank(menu.getHref())) {
                menu.setHref("/" + menu.getCode());
            }
            info = new PermissionInfo();
            info.setCode(menu.getCode());
            info.setType(AdminCommonConstant.RESOURCE_TYPE_MENU);
            info.setName(AdminCommonConstant.RESOURCE_ACTION_VISIT);
            String uri = menu.getHref();
            if (!uri.startsWith("/")) {
                uri = "/" + uri;
            }
            info.setUri(uri);
            info.setMethod(AdminCommonConstant.RESOURCE_REQUEST_METHOD_GET);
            result.add(info
            );
            info.setMenu(menu.getTitle());
        }
    }

    public List<PermissionInfo> getPermissionByUsername(String username) {
        String key = String.format(RedisKeyConstant.REDIS_KEY_USER_PERMISISON, username);
        String s = stringRedisTemplate.opsForValue().get(key);
        if (s == null || org.apache.commons.lang.StringUtils.isBlank(s)) {
            User user = userBiz.getUserByUsername(username);
            List<Menu> menus = menuBiz.getUserAuthorityMenuByUserId(user.getId());
            List<PermissionInfo> result = new ArrayList<PermissionInfo>();
            menu2permission(menus, result);
            List<Element> elements = elementBiz.getAuthorityElementByUserId(user.getId() + "");
            element2permission(result, elements);
            stringRedisTemplate.opsForValue().set(key, JSON.toJSONString(result), 12, TimeUnit.HOURS);

            return result;
        }
        List<PermissionInfo> permissionInfos = JSON.parseArray(s, PermissionInfo.class);
        return permissionInfos;
    }

    private void element2permission(List<PermissionInfo> result, List<Element> elements) {
        PermissionInfo info;
        for (Element element : elements) {
            info = new PermissionInfo();
            info.setCode(element.getCode());
            info.setType(element.getType());
            info.setUri(element.getUri());
            info.setMethod(element.getMethod());
            info.setName(element.getName());
            info.setMenu(element.getMenuId());
            result.add(info);
        }
    }


    private List<MenuTree> getMenuTree(List<Menu> menus, int root) {
        List<MenuTree> trees = new ArrayList<MenuTree>();
        MenuTree node = null;
        for (Menu menu : menus) {
            node = new MenuTree();
            BeanUtils.copyProperties(menu, node);
            trees.add(node);
        }
        return TreeUtil.bulid(trees, root);
    }

    public FrontUserV2 getUserInfoV2() {
        String username = BaseContextHandler.getUsername();
        if (username == null) {
            return null;
        }
        User user = userBiz.getUserByUsername(username);
        FrontUserV2 frontUser = new FrontUserV2();
        List<Menu> menus = menuBiz.getUserAuthorityMenuByUserId(user.getId());
        List<AccessMenuTree> menuTrees = new ArrayList<AccessMenuTree>();
        List<AccessRouteTree> routeTrees = new ArrayList<>();
        AccessMenuTree node = null;
        AccessRouteTree routeNode = null;
        List<Integer> menuIds = new ArrayList<>();
        List<AccessMenuTree> header = new ArrayList<>();
        // 设置菜单树
        for (Menu menu : menus) {
            node = new AccessMenuTree();
            node.setIcon(menu.getIcon());
            node.setPath(menu.getHref());
            node.setTitle(menu.getTitle());
            node.setId(menu.getId());
            node.setParentId(menu.getParentId());
            menuTrees.add(node);
            // 设置系统头部菜单
            if (menu.getParentId().equals(AdminCommonConstant.ROOT)) {
                menuIds.add(menu.getId());
                node = new AccessMenuTree();
                node.setIcon(menu.getIcon());
                node.setPath(menu.getHref());
                node.setTitle(menu.getTitle());
                node.setId(menu.getId());
                node.setParentId(menu.getParentId());
                header.add(node);
                continue;
            }
            routeNode = new AccessRouteTree();
            routeNode.setIcon(menu.getIcon());
            routeNode.setId(menu.getId());
            routeNode.setPath(menu.getHref());
            routeNode.setParentId(menu.getParentId());
            routeNode.setName(menu.getCode());
            routeNode.setComponent(menu.getAttr3());
            routeNode.setComponentPath(menu.getAttr1());
            JSONObject jsonObject = JSONObject.parseObject(menu.getAttr2());
            jsonObject.put("title", menu.getTitle());
            routeNode.setMeta(jsonObject);
            routeTrees.add(routeNode);
        }
        // 配置页面资源权限
        List<Element> elements = elementBiz.getAuthorityElementByUserId(user.getId() + "");
        List<String> permissions = new ArrayList<>();
        List<AccessInterface> interfaces = new ArrayList<>();
        AccessInterface accessInterface = null;
        for (Element element : elements) {
            accessInterface = new AccessInterface();
            permissions.add(element.getCode());
            accessInterface.setMethod(element.getMethod());
            accessInterface.setPath(element.getUri());
            interfaces.add(accessInterface);
        }
        // 配置路由权限
        List<AccessRouteTree> accessRoutes = new ArrayList<>();
        for (Integer menuId : menuIds) {
            accessRoutes.addAll(TreeUtil.bulid(routeTrees, menuId));
        }
        frontUser.setAccessMenus(TreeUtil.bulid(menuTrees, AdminCommonConstant.ROOT));
        frontUser.setAccessHeader(header);
        frontUser.setAccessRoutes(accessRoutes);
        frontUser.setUserPermissions(permissions);
        frontUser.setUserName(user.getName());
        frontUser.setAccessInterfaces(interfaces);
        //TODO 待接入头像附件上传服务
        frontUser.setAvatarUrl("https://api.adorable.io/avatars/85/abott@adorable.png");
        return frontUser;
    }

    public FrontUser getUserInfo(String token) throws Exception {
        String username = userAuthUtil.getInfoFromToken(token).getUniqueName();
        if (username == null) {
            return null;
        }
        UserInfo user = this.getUserByUsername(username);
        FrontUser frontUser = new FrontUser();
        BeanUtils.copyProperties(user, frontUser);
        List<PermissionInfo> permissionInfos = this.getPermissionByUsername(username);
        Stream<PermissionInfo> menus = permissionInfos.parallelStream().filter((permission) -> {
            return permission.getType().equals(CommonConstants.RESOURCE_TYPE_MENU);
        });
        frontUser.setMenus(menus.collect(Collectors.toList()));
        Stream<PermissionInfo> elements = permissionInfos.parallelStream().filter((permission) -> {
            return !permission.getType().equals(CommonConstants.RESOURCE_TYPE_MENU);
        });
        frontUser.setElements(elements.collect(Collectors.toList()));
        return frontUser;
    }

    public List<MenuTree> getMenusByUsername(String token) throws Exception {
        String username = userAuthUtil.getInfoFromToken(token).getUniqueName();
        if (username == null) {
            return null;
        }
        User user = userBiz.getUserByUsername(username);
        List<Menu> menus = menuBiz.getUserAuthorityMenuByUserId(user.getId());
        return getMenuTree(menus, AdminCommonConstant.ROOT);
    }

    public Mono<CheckPermissionInfo> checkUserPermission(String username, String requestUri, String requestMethod) {
        CheckPermissionInfo checkPermissionInfo = new CheckPermissionInfo();
        List<PermissionInfo> allPermission = this.getAllPermission();
        // 判断当前访问资源是否有权限控制
        List<PermissionInfo> matchPermission = allPermission.parallelStream().filter(permissionInfo -> {
            String uri = permissionInfo.getUri();
            if (uri.indexOf("{") > 0) {
                uri = uri.replaceAll("\\{\\*\\}", "[a-zA-Z\\\\d]+");
            }
            String regEx = "^" + uri + "$";
            return (Pattern.compile(regEx).matcher(requestUri).find())
                    && requestMethod.equals(permissionInfo.getMethod());
        }).collect(Collectors.toList());
        // 说明当前访问资源不做权限控制
        if (matchPermission.size() == 0) {
            checkPermissionInfo.setIsAuth(true);
            return Mono.just(checkPermissionInfo);
        }
        // 判断当前用户是否拥有该访问资源的权限
        List<PermissionInfo> permissions = this.getPermissionByUsername(username);
        PermissionInfo current = null;
        for (PermissionInfo info : permissions) {
            boolean anyMatch = matchPermission.parallelStream().anyMatch(permissionInfo -> permissionInfo.getCode().equals(info.getCode()));
            if (anyMatch) {
                current = info;
                break;
            }
        }
        if (current == null) {
            // 当前用户不拥有该权限
            checkPermissionInfo.setIsAuth(false);
        } else {
            // 当前用户拥有该资源的访问权限
            checkPermissionInfo.setIsAuth(true);
            checkPermissionInfo.setPermissionInfo(current);
        }
        return Mono.just(checkPermissionInfo);
    }
}


<|start_filename|>ace-modules/ace-sample/src/main/java/com/github/wxiaoqi/security/sample/SampleBootstrap.java<|end_filename|>
package com.github.wxiaoqi.security.sample;

import com.github.wxiaoqi.security.auth.client.EnableAceAuthClient;
import com.spring4all.swagger.EnableSwagger2Doc;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * @author laogandie
 * @create 2020/9/5.
 */
@EnableDiscoveryClient
@EnableCircuitBreaker
@SpringBootApplication
@EnableTransactionManagement
@MapperScan("com.github.wxiaoqi.security.sample.mapper")
@EnableSwagger2Doc
@EnableAceAuthClient
@EnableFeignClients({"com.github.wxiaoqi.security.auth.client.feign"})
public class SampleBootstrap {
    public static void main(String[] args) {
        new SpringApplicationBuilder(SampleBootstrap.class).run(args);    }
}


<|start_filename|>ace-dev-base/ace-common/src/main/java/com/github/wxiaoqi/security/common/util/http/HttpHelper.java<|end_filename|>
package com.github.wxiaoqi.security.common.util.http;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.ServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;

/**
 * 通用http工具封装
 *
 * @author <NAME>
 */
@Slf4j
public class HttpHelper {

    public static String getBodyString(ServletRequest request) {
        StringBuilder sb = new StringBuilder();
        BufferedReader reader = null;
        try (InputStream inputStream = request.getInputStream()) {
            reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8")));
            String line = "";
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            log.warn("getBodyString出现问题！");
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return sb.toString();
    }
}


<|start_filename|>ace-gate/src/main/java/com/github/wxiaoqi/security/gate/service/LogService.java<|end_filename|>
package com.github.wxiaoqi.security.gate.service;

import com.github.wxiaoqi.security.api.vo.log.LogInfo;

/**
 * @author <NAME>
 * @create 2020/7/23.
 */
public interface LogService {
    void saveLog(LogInfo info);
}


<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/admin/vo/AccessMenuTree.java<|end_filename|>
package com.github.wxiaoqi.security.modules.admin.vo;

import com.github.wxiaoqi.security.common.vo.TreeNode;
import lombok.Data;
import org.springframework.beans.BeanUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * ${DESCRIPTION}
 *
 * @author the sun
 * @create 2017-06-19 13:03
 */
@Data
public class AccessMenuTree extends TreeNode implements Serializable{
    String title;
    String icon;
    String path;
    List<AccessMenuTree> nodes = new ArrayList<AccessMenuTree>();


    @Override
    public void setChildren(List<TreeNode> children) {
        super.setChildren(children);
        nodes = new ArrayList<AccessMenuTree>();
    }

    @Override
    public void add(TreeNode node) {
        super.add(node);
        AccessMenuTree n = new AccessMenuTree();
        BeanUtils.copyProperties(node,n);
        nodes.add(n);
    }
}


<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/admin/vo/AccessRouteTree.java<|end_filename|>
package com.github.wxiaoqi.security.modules.admin.vo;

import com.alibaba.fastjson.JSONObject;
import com.github.wxiaoqi.security.common.vo.TreeNode;
import lombok.Data;
import org.springframework.beans.BeanUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * ${DESCRIPTION}
 *
 * @author the sun
 * @create 2017-06-19 13:03
 */
@Data
public class AccessRouteTree extends TreeNode implements Serializable {
    String name;
    String icon;
    String path;
    String component;
    String componentPath;
    /**
     * "meta": {
     * "title": "系统设置",
     * "cache": true
     * }
     */
    JSONObject meta;

    List<AccessRouteTree> nodes = new ArrayList<AccessRouteTree>();


    @Override
    public void setChildren(List<TreeNode> children) {
        super.setChildren(children);
        nodes = new ArrayList<AccessRouteTree>();
    }

    @Override
    public void add(TreeNode node) {
        super.add(node);
        AccessRouteTree n = new AccessRouteTree();
        BeanUtils.copyProperties(node, n);
        nodes.add(n);
    }
}


<|start_filename|>ace-gate/src/main/java/com/github/wxiaoqi/security/gate/GatewayServerBootstrap.java<|end_filename|>
package com.github.wxiaoqi.security.gate;

import com.github.wxiaoqi.security.auth.client.EnableAceAuthClient;
import com.github.wxiaoqi.security.gate.utils.DBLog;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * @author ace
 * @create 2018/3/12.
 */
@SpringCloudApplication
@EnableAceAuthClient
//TODO 切换为webclient
@EnableFeignClients({"com.github.wxiaoqi.security.auth.client.feign"})
public class GatewayServerBootstrap {
    public static void main(String[] args) {
        DBLog.getInstance().start();
        SpringApplication.run(GatewayServerBootstrap.class, args);
    }
}


<|start_filename|>ace-modules/ace-sample/src/main/java/com/github/wxiaoqi/security/sample/mapper/SampleDataTestMapper.java<|end_filename|>
package com.github.wxiaoqi.security.sample.mapper;

import com.github.wxiaoqi.security.sample.entity.SampleDataTest;
import tk.mybatis.mapper.common.Mapper;

/**
 * 
 * 
 * @author 老干爹
 * @email <EMAIL>
 * @version 2020-09-05 10:33:41
 */
public interface SampleDataTestMapper extends Mapper<SampleDataTest> {
	
}


<|start_filename|>ace-api/src/main/java/com/github/wxiaoqi/security/api/vo/search/IndexObject.java<|end_filename|>
/*
 *
 *  *  Copyright (C) 2018  the sun<<EMAIL>>
 *
 *  *  AG-Enterprise 企业版源码
 *  *  郑重声明:
 *  *  如果你从其他途径获取到，请告知老A传播人，奖励1000。
 *  *  老A将追究授予人和传播人的法律责任!
 *
 *  *  This program is free software; you can redistribute it and/or modify
 *  *  it under the terms of the GNU General Public License as published by
 *  *  the Free Software Foundation; either version 2 of the License, or
 *  *  (at your option) any later version.
 *
 *  *  This program is distributed in the hope that it will be useful,
 *  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  *  GNU General Public License for more details.
 *
 *  *  You should have received a copy of the GNU General Public License along
 *  *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

package com.github.wxiaoqi.security.api.vo.search;


import java.io.Serializable;

/**
 * Description:索引对象
 *
 * @author ace
 **/
public class IndexObject implements Comparable<IndexObject>,Serializable{
	
	private Long id;

	private String title;

	private String keywords;

	private String descripton;

	private String postDate;

	public String getPostDate() {
		return postDate;
	}

	public void setPostDate(String postDate) {
		this.postDate = postDate;
	}

	public String getDescripton() {
		return descripton;
	}

	public void setDescripton(String descripton) {
		this.descripton = descripton;
	}

	private String url;

	/*相似度*/
	private float score;


	public String getKeywords() {
		return keywords;
	}

	public void setKeywords(String keywords) {
		this.keywords = keywords;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}



	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public float getScore() {
		return score;
	}

	public  void setScore(float score) {
		this.score = score;
	}


	
	public IndexObject() {
		super();
	}

	public IndexObject(Long _id, String _keywords, String _descripton, String _postDate, float _score) {
		super();
		this.id = _id;
		this.keywords = _keywords;
		this.score = _score;
		this.descripton=_descripton;
		this.postDate=_postDate;
	}
	@Override
	public int compareTo(IndexObject o) {
		if(this.score < o.getScore()){
			return 1;
		}else if(this.score > o.getScore()){
			return -1;
		}
		return 0;
	}
	
	
}


<|start_filename|>ace-modules/ace-sample/src/main/java/com/github/wxiaoqi/security/sample/biz/SampleDataTestBiz.java<|end_filename|>
package com.github.wxiaoqi.security.sample.biz;

import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.sample.entity.SampleDataTest;
import com.github.wxiaoqi.security.sample.mapper.SampleDataTestMapper;
import org.springframework.stereotype.Service;

/**
 * 
 *
 * @author 老干爹
 * @email <EMAIL>
 * @version 2020-09-05 10:33:41
 */
@Service
public class SampleDataTestBiz extends BaseBiz<SampleDataTestMapper,SampleDataTest> {
}

<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/admin/mapper/ResourceAuthorityMapper.java<|end_filename|>
package com.github.wxiaoqi.security.modules.admin.mapper;

import com.github.wxiaoqi.security.modules.admin.entity.ResourceAuthority;
import org.apache.ibatis.annotations.Param;
import tk.mybatis.mapper.common.Mapper;

public interface ResourceAuthorityMapper extends Mapper<ResourceAuthority> {
    public void deleteByAuthorityIdAndResourceType(@Param("authorityId")String authorityId,@Param("resourceType") String resourceType);
}

<|start_filename|>ace-modules/ace-generator/src/main/java/com/github/wxiaoqi/security/generator/config/SwitchDB.java<|end_filename|>
package com.github.wxiaoqi.security.generator.config;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

/**
 * 切换数据库类
 *
 * @author lxf 2018-09-28
 */
@Configuration
@Slf4j
public class SwitchDB {
    @Autowired
    private Environment evn;
    //私有库数据源key
    private static String ljyunDataSourceKey = "ljyun_";

    @Autowired
    DynamicDataSource dynamicDataSource;

    /**
     * 切换数据库对外方法,如果私有库id参数非0,则首先连接私有库，否则连接其他已存在的数据源
     *
     * @param dbName 已存在的数据库源对象
     * @return 返回当前数据库连接对象对应的key
     */
    public String change(String dbName) {
        toDB(dbName);
        //获取当前连接的数据源对象的key
        String currentKey = DynamicDataSourceContextHolder.getDataSourceKey();
        log.info("＝＝＝＝＝当前连接的数据库是:" + currentKey);
        return currentKey;
    }

    /**
     * 切换已存在的数据源
     *
     * @param dbName
     */
    private void toDB(String dbName) {
        //如果不指定数据库，则直接连接默认数据库
        String dbSourceKey = dbName.trim().isEmpty() ? "default" : dbName.trim();
        //获取当前连接的数据源对象的key
        String currentKey = DynamicDataSourceContextHolder.getDataSourceKey();
        //如果当前数据库连接已经是想要的连接，则直接返回
        if (currentKey == dbSourceKey) {
            return;
        }
        //判断储存动态数据源实例的map中key值是否存在
        if (DynamicDataSource.isExistDataSource(dbSourceKey)) {
            DynamicDataSourceContextHolder.setDataSourceKey(dbSourceKey);
            log.info("＝＝＝＝＝普通库: " + dbName + ",切换完毕");
        } else {
            log.info("切换普通数据库时，数据源key=" + dbName + "不存在");
        }
    }

}


<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/auth/controller/OnlineController.java<|end_filename|>
package com.github.wxiaoqi.security.modules.auth.controller;

import com.alibaba.fastjson.JSON;
import com.github.wxiaoqi.security.common.msg.ObjectRestResponse;
import com.github.wxiaoqi.security.common.msg.TableResultResponse;
import com.github.wxiaoqi.security.common.constant.RedisKeyConstant;
import com.github.wxiaoqi.security.modules.admin.entity.OnlineLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author <NAME>
 * @create 2020/7/29.
 */
@RestController
@RequestMapping("online")
public class OnlineController {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping("/page")
    public TableResultResponse<OnlineLog> getOnlineInfo(@RequestParam(defaultValue = "10") int limit, @RequestParam(defaultValue = "1") int offset) {
        stringRedisTemplate.opsForValue();
        //倒序查询分页的ids
        Set<String> ids = stringRedisTemplate.opsForZSet().reverseRange(RedisKeyConstant.REDIS_KEY_TOKEN, (offset - 1) * limit, (offset - 1) * limit + limit - 1);
        List<OnlineLog> logs = new ArrayList<>(ids.size());
        for (String id : ids) {
            String s = stringRedisTemplate.opsForValue().get(RedisKeyConstant.REDIS_KEY_TOKEN + ":" + id);
            if (s == null) {
                stringRedisTemplate.opsForZSet().remove(RedisKeyConstant.REDIS_KEY_TOKEN, id);
            } else {
                logs.add(JSON.parseObject(s, OnlineLog.class));
            }
        }
        return new TableResultResponse<>(stringRedisTemplate.opsForZSet().size(RedisKeyConstant.REDIS_KEY_TOKEN), logs);
    }


    @RequestMapping("/{id}")
    public ObjectRestResponse forceLogout(@PathVariable("id") String tokenId) {
        stringRedisTemplate.delete(RedisKeyConstant.REDIS_KEY_TOKEN + ":" + tokenId);
        stringRedisTemplate.opsForZSet().remove(RedisKeyConstant.REDIS_KEY_TOKEN, tokenId);
        return new ObjectRestResponse<>();
    }

}


<|start_filename|>ace-gate/src/main/java/com/github/wxiaoqi/security/gate/service/LogServiceImpl.java<|end_filename|>
package com.github.wxiaoqi.security.gate.service;

import com.github.wxiaoqi.security.api.vo.log.LogInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

/**
 * @author <NAME>
 * @create 2020/7/23.
 */
@Component
@Slf4j
public class LogServiceImpl implements LogService {

    @Autowired
    private WebClient.Builder webClientBuilder;

    @Override
    public void saveLog(LogInfo info) {
        Mono<Void> mono = webClientBuilder.build().
                post().uri("http://ace-admin/api/log/save").body(BodyInserters.fromValue(info)).retrieve().bodyToMono(Void.class);
        // 输出结果
        log.debug(String.valueOf(mono.block()));
    }
}


<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/admin/vo/AccessInterface.java<|end_filename|>
package com.github.wxiaoqi.security.modules.admin.vo;

import lombok.Data;

/**
 * @author <NAME>
 * @create 2020/7/17.
 */
@Data
public class AccessInterface {
    String path;
    String method;
}


<|start_filename|>ace-modules/ace-generator/src/main/java/com/github/wxiaoqi/security/generator/config/DataSourceConfigurer.java<|end_filename|>
package com.github.wxiaoqi.security.generator.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 数据源配置类,在tomcat启动时触发，在该类中生成多个数据源实例并将其注入到 ApplicationContext 中
 * @author lxf 2018-09-27
 */

@Configuration
public class DataSourceConfigurer {

    @Bean("Sample数据库")
    @ConfigurationProperties(prefix = "spring.sample-datasource")
    public DruidDataSource sampleDatasource() {
        return DataSourceBuilder.create().type(DruidDataSource.class).build();
    }


    @Bean("Admin数据库")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidDataSource adminDatasource() {
        return DataSourceBuilder.create().type(DruidDataSource.class).build();
    }

}

<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/admin/entity/OnlineLog.java<|end_filename|>
package com.github.wxiaoqi.security.modules.admin.entity;

import lombok.Data;

/**
 * 当前在线会话
 * 
 * @author <NAME>
 */
@Data
public class OnlineLog
{
    /** 会话编号 */
    private String tokenId;

    /** 用户名称 */
    private String userName;

    /** 登录IP地址 */
    private String ipaddr;

    /** 登录地址 */
    private String loginLocation;

    /** 浏览器类型 */
    private String browser;

    /** 操作系统 */
    private String os;

    /** 登录时间 */
    private Long loginTime;

    /**
     * 用户id
     */
    private String userId;

}


<|start_filename|>ace-modules/ace-generator/src/main/java/com/github/wxiaoqi/security/generator/GeneratorServerBootstrap.java<|end_filename|>
package com.github.wxiaoqi.security.generator;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.context.annotation.ComponentScan;

/**
 * @author ace
 * @create 2018/3/12.
 */
@SpringCloudApplication
@ComponentScan({"com.github.wxiaoqi.security.common","com.github.wxiaoqi.security.generator"})
@MapperScan("com.github.wxiaoqi.security.generator.mapper")
public class GeneratorServerBootstrap {
    public static void main(String[] args) {
        SpringApplication.run(GeneratorServerBootstrap.class, args);
    }
}


<|start_filename|>ace-api/src/main/java/com/github/wxiaoqi/security/api/vo/log/LogInfo.java<|end_filename|>
package com.github.wxiaoqi.security.api.vo.log;

import java.io.Serializable;
import java.util.Date;

/**
 * ${DESCRIPTION}
 *
 * @author the sun
 * @create 2017-07-01 11:18
 */
public class LogInfo implements Serializable{
    private String menu;

    private String opt;

    private String uri;

    private Long crtTime;

    private String crtUser;

    private String crtName;

    private String crtHost;

    private String body;

    public LogInfo(String menu, String option, String uri,  Date crtTime, String crtUser, String crtName, String crtHost,String body) {
        this.menu = menu;
        this.opt = option;
        this.uri = uri;
        this.crtTime = crtTime.getTime();
        this.crtUser = crtUser;
        this.crtName = crtName;
        this.crtHost = crtHost;
        this.body = body;
    }

    public LogInfo() {
    }

    public String getMenu() {
        return menu;
    }

    public void setMenu(String menu) {
        this.menu = menu;
    }

    public String getOpt() {
        return opt;
    }

    public void setOpt(String option) {
        this.opt = option;
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public Long getCrtTime() {
        return crtTime;
    }

    public void setCrtTime(Date crtTime) {
        this.crtTime = crtTime.getTime();
    }

    public String getCrtUser() {
        return crtUser;
    }

    public void setCrtUser(String crtUser) {
        this.crtUser = crtUser;
    }

    public String getCrtName() {
        return crtName;
    }

    public void setCrtName(String crtName) {
        this.crtName = crtName;
    }

    public String getCrtHost() {
        return crtHost;
    }

    public void setCrtHost(String crtHost) {
        this.crtHost = crtHost;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
}


<|start_filename|>ace-modules/ace-admin/src/main/java/com/github/wxiaoqi/security/modules/auth/biz/ClientServiceBiz.java<|end_filename|>
package com.github.wxiaoqi.security.modules.auth.biz;

import com.github.wxiaoqi.security.modules.auth.entity.ClientService;
import com.github.wxiaoqi.security.modules.auth.mapper.ClientServiceMapper;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import org.springframework.stereotype.Service;

/**
 * @author ace
 * @create 2017/12/30.
 */
@Service
public class ClientServiceBiz extends BaseBiz<ClientServiceMapper,ClientService> {
}
