forked from rongchao/epmet-cloud-rizhao
				
			
				 16 changed files with 581 additions and 25 deletions
			
			
		@ -0,0 +1,37 @@ | 
				
			|||
package com.epmet.dto.form; | 
				
			|||
 | 
				
			|||
import lombok.AllArgsConstructor; | 
				
			|||
import lombok.Data; | 
				
			|||
import lombok.NoArgsConstructor; | 
				
			|||
 | 
				
			|||
import javax.validation.constraints.NotBlank; | 
				
			|||
 | 
				
			|||
@Data | 
				
			|||
@AllArgsConstructor | 
				
			|||
@NoArgsConstructor | 
				
			|||
public class CorsConfigFormDTO { | 
				
			|||
 | 
				
			|||
    public interface Add {} | 
				
			|||
    public interface Update {} | 
				
			|||
 | 
				
			|||
    @NotBlank(message = "ID不能为空", groups = { Update.class }) | 
				
			|||
    private String id; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 首部type | 
				
			|||
     */ | 
				
			|||
    @NotBlank(message = "首部类型不能为空", groups = { Add.class, Update.class }) | 
				
			|||
    private String headerType; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 首部value | 
				
			|||
     */ | 
				
			|||
    @NotBlank(message = "首部值不能为空", groups = { Add.class, Update.class }) | 
				
			|||
    private String headerValue; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 备注 | 
				
			|||
     */ | 
				
			|||
    private String comment; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,27 @@ | 
				
			|||
package com.epmet.dto.result; | 
				
			|||
 | 
				
			|||
import lombok.AllArgsConstructor; | 
				
			|||
import lombok.Data; | 
				
			|||
import lombok.NoArgsConstructor; | 
				
			|||
 | 
				
			|||
@Data | 
				
			|||
@AllArgsConstructor | 
				
			|||
@NoArgsConstructor | 
				
			|||
public class CorsConfigResultDTO { | 
				
			|||
 | 
				
			|||
    private String id; | 
				
			|||
    /** | 
				
			|||
     * 首部类型 | 
				
			|||
     */ | 
				
			|||
    private String headerType; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 首部值 | 
				
			|||
     */ | 
				
			|||
    private String headerValue; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 首部备注 | 
				
			|||
     */ | 
				
			|||
    private String comment; | 
				
			|||
} | 
				
			|||
@ -0,0 +1,24 @@ | 
				
			|||
package com.epmet.feign; | 
				
			|||
 | 
				
			|||
import com.epmet.commons.tools.constant.ServiceConstant; | 
				
			|||
import com.epmet.commons.tools.utils.Result; | 
				
			|||
import com.epmet.dto.result.CorsConfigResultDTO; | 
				
			|||
import com.epmet.feign.fallback.EpmetAdminOpenFeignClientFallback; | 
				
			|||
import org.springframework.cloud.openfeign.FeignClient; | 
				
			|||
import org.springframework.web.bind.annotation.PostMapping; | 
				
			|||
 | 
				
			|||
import java.util.List; | 
				
			|||
 | 
				
			|||
@FeignClient(name = ServiceConstant.EPMET_ADMIN_SERVER, fallback = EpmetAdminOpenFeignClientFallback.class) | 
				
			|||
//@FeignClient(name = ServiceConstant.EPMET_ADMIN_SERVER, fallback = EpmetAdminOpenFeignClientFallback.class, url = "localhost:8082")
 | 
				
			|||
public interface EpmetAdminOpenFeignClient { | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Description 查询跨域配置列表 | 
				
			|||
     * @return | 
				
			|||
     * @author wxz | 
				
			|||
     * @date 2021.06.25 10:00 | 
				
			|||
     */ | 
				
			|||
    @PostMapping("/sys/cors-config/list") | 
				
			|||
    Result<List<CorsConfigResultDTO>> list(); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,18 @@ | 
				
			|||
package com.epmet.feign.fallback; | 
				
			|||
 | 
				
			|||
import com.epmet.commons.tools.constant.ServiceConstant; | 
				
			|||
import com.epmet.commons.tools.utils.ModuleUtils; | 
				
			|||
import com.epmet.commons.tools.utils.Result; | 
				
			|||
import com.epmet.dto.result.CorsConfigResultDTO; | 
				
			|||
import com.epmet.feign.EpmetAdminOpenFeignClient; | 
				
			|||
import org.springframework.stereotype.Component; | 
				
			|||
 | 
				
			|||
import java.util.List; | 
				
			|||
 | 
				
			|||
@Component | 
				
			|||
public class EpmetAdminOpenFeignClientFallback implements EpmetAdminOpenFeignClient { | 
				
			|||
    @Override | 
				
			|||
    public Result<List<CorsConfigResultDTO>> list() { | 
				
			|||
        return ModuleUtils.feignConError(ServiceConstant.EPMET_USER_SERVER, "list", null); | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,70 @@ | 
				
			|||
package com.epmet.controller; | 
				
			|||
 | 
				
			|||
import com.epmet.commons.tools.utils.Result; | 
				
			|||
import com.epmet.commons.tools.validator.ValidatorUtils; | 
				
			|||
import com.epmet.dto.form.CorsConfigFormDTO; | 
				
			|||
import com.epmet.dto.result.CorsConfigResultDTO; | 
				
			|||
import com.epmet.service.CorsConfigService; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.web.bind.annotation.*; | 
				
			|||
 | 
				
			|||
import java.util.List; | 
				
			|||
 | 
				
			|||
@RestController | 
				
			|||
@RequestMapping("cors-config") | 
				
			|||
public class CorsConfigController { | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    private CorsConfigService corsConfigService; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Description 查询跨域配置列表 | 
				
			|||
     * @return | 
				
			|||
     * @author wxz | 
				
			|||
     * @date 2021.06.25 10:00 | 
				
			|||
    */ | 
				
			|||
    @PostMapping("/list") | 
				
			|||
    public Result<List<CorsConfigResultDTO>> list() { | 
				
			|||
        List<CorsConfigResultDTO> list = corsConfigService.list(); | 
				
			|||
        return new Result<List<CorsConfigResultDTO>>().ok(list); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Description 添加跨域配置 | 
				
			|||
     * @return | 
				
			|||
     * @author wxz | 
				
			|||
     * @date 2021.06.25 13:51 | 
				
			|||
    */ | 
				
			|||
    @PostMapping("/add") | 
				
			|||
    public Result<CorsConfigResultDTO> addConfig(@RequestBody CorsConfigFormDTO input) { | 
				
			|||
        ValidatorUtils.validateEntity(input, CorsConfigFormDTO.Add.class); | 
				
			|||
        CorsConfigResultDTO data = corsConfigService.addConfig(input.getHeaderType(), input.getHeaderValue(), input.getComment()); | 
				
			|||
        return new Result<CorsConfigResultDTO>().ok(data); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Description 通过id删除配置 | 
				
			|||
     * @return | 
				
			|||
     * @author wxz | 
				
			|||
     * @date 2021.06.25 14:18 | 
				
			|||
    */ | 
				
			|||
    @PostMapping("/delete/{id}") | 
				
			|||
    public Result deleteConfigById(@PathVariable("id") String configId) { | 
				
			|||
        corsConfigService.deleteById(configId); | 
				
			|||
        return new Result<>(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Description 根据id更新 | 
				
			|||
     * @return | 
				
			|||
     * @author wxz | 
				
			|||
     * @date 2021.06.25 14:23 | 
				
			|||
    */ | 
				
			|||
    @PostMapping("/update") | 
				
			|||
    public Result updateById(@RequestBody CorsConfigFormDTO input) { | 
				
			|||
        ValidatorUtils.validateEntity(input, CorsConfigFormDTO.Update.class); | 
				
			|||
        corsConfigService.updateById(input.getId(), input.getHeaderType(), input.getHeaderValue(), input.getComment()); | 
				
			|||
        return new Result<>(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,33 @@ | 
				
			|||
/** | 
				
			|||
 * Copyright 2018 人人开源 https://www.renren.io
 | 
				
			|||
 * <p> | 
				
			|||
 * 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 3 of the License, or | 
				
			|||
 * (at your option) any later version. | 
				
			|||
 * <p> | 
				
			|||
 * 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. | 
				
			|||
 * <p> | 
				
			|||
 * You should have received a copy of the GNU General Public License | 
				
			|||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			|||
 */ | 
				
			|||
 | 
				
			|||
package com.epmet.dao; | 
				
			|||
 | 
				
			|||
import com.epmet.commons.mybatis.dao.BaseDao; | 
				
			|||
import com.epmet.entity.CorsConfigEntity; | 
				
			|||
import org.apache.ibatis.annotations.Mapper; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * 跨域配置表 | 
				
			|||
 * | 
				
			|||
 * @author generator generator@elink-cn.com | 
				
			|||
 * @since v1.0.0 2021-06-25 | 
				
			|||
 */ | 
				
			|||
@Mapper | 
				
			|||
public interface CorsConfigDao extends BaseDao<CorsConfigEntity> { | 
				
			|||
	 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,56 @@ | 
				
			|||
/** | 
				
			|||
 * Copyright 2018 人人开源 https://www.renren.io
 | 
				
			|||
 * <p> | 
				
			|||
 * 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 3 of the License, or | 
				
			|||
 * (at your option) any later version. | 
				
			|||
 * <p> | 
				
			|||
 * 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. | 
				
			|||
 * <p> | 
				
			|||
 * You should have received a copy of the GNU General Public License | 
				
			|||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			|||
 */ | 
				
			|||
 | 
				
			|||
package com.epmet.entity; | 
				
			|||
 | 
				
			|||
import com.baomidou.mybatisplus.annotation.TableName; | 
				
			|||
 | 
				
			|||
import com.epmet.commons.mybatis.entity.BaseEpmetEntity; | 
				
			|||
import lombok.Data; | 
				
			|||
import lombok.EqualsAndHashCode; | 
				
			|||
 | 
				
			|||
import java.util.Date; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * 跨域配置表 | 
				
			|||
 * | 
				
			|||
 * @author generator generator@elink-cn.com | 
				
			|||
 * @since v1.0.0 2021-06-25 | 
				
			|||
 */ | 
				
			|||
@Data | 
				
			|||
@EqualsAndHashCode(callSuper=false) | 
				
			|||
@TableName("cors_config") | 
				
			|||
public class CorsConfigEntity extends BaseEpmetEntity { | 
				
			|||
 | 
				
			|||
	private static final long serialVersionUID = 1L; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 首部类型 | 
				
			|||
     */ | 
				
			|||
	private String headerType; | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * 首部值 | 
				
			|||
     */ | 
				
			|||
	private String headerValue; | 
				
			|||
 | 
				
			|||
	/** | 
				
			|||
	 * 说明 | 
				
			|||
	 */ | 
				
			|||
	private String comment; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
@ -0,0 +1,20 @@ | 
				
			|||
package com.epmet.service; | 
				
			|||
 | 
				
			|||
import com.epmet.dto.result.CorsConfigResultDTO; | 
				
			|||
 | 
				
			|||
import java.util.List; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * @Description 跨域配置service接口 | 
				
			|||
 * @author wxz | 
				
			|||
 * @date 2021-06-44 09:52:44 | 
				
			|||
*/ | 
				
			|||
public interface CorsConfigService { | 
				
			|||
    List<CorsConfigResultDTO> list(); | 
				
			|||
 | 
				
			|||
    CorsConfigResultDTO addConfig(String headerType, String headerValue, String comment); | 
				
			|||
 | 
				
			|||
    void deleteById(String configId); | 
				
			|||
 | 
				
			|||
    void updateById(String configId, String headerType, String headerValue, String comment); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,110 @@ | 
				
			|||
package com.epmet.service.impl; | 
				
			|||
 | 
				
			|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
				
			|||
import com.epmet.commons.tools.exception.EpmetErrorCode; | 
				
			|||
import com.epmet.commons.tools.exception.ExceptionUtils; | 
				
			|||
import com.epmet.commons.tools.exception.RenException; | 
				
			|||
import com.epmet.commons.tools.redis.RedisKeys; | 
				
			|||
import com.epmet.commons.tools.utils.ConvertUtils; | 
				
			|||
import com.epmet.dao.CorsConfigDao; | 
				
			|||
import com.epmet.dto.result.CorsConfigResultDTO; | 
				
			|||
import com.epmet.entity.CorsConfigEntity; | 
				
			|||
import com.epmet.service.CorsConfigService; | 
				
			|||
import org.slf4j.Logger; | 
				
			|||
import org.slf4j.LoggerFactory; | 
				
			|||
import org.springframework.beans.factory.annotation.Autowired; | 
				
			|||
import org.springframework.data.redis.core.HashOperations; | 
				
			|||
import org.springframework.data.redis.core.RedisTemplate; | 
				
			|||
import org.springframework.stereotype.Service; | 
				
			|||
 | 
				
			|||
import java.util.List; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * @Description 跨域配置 | 
				
			|||
 * @author wxz | 
				
			|||
 * @date 2021.06.25 09:53:57 | 
				
			|||
*/ | 
				
			|||
@Service | 
				
			|||
public class CorsConfigServiceImpl implements CorsConfigService { | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    private CorsConfigDao corsConfigDao; | 
				
			|||
 | 
				
			|||
    @Autowired | 
				
			|||
    private RedisTemplate redisTemplate; | 
				
			|||
 | 
				
			|||
    private Logger logger = LoggerFactory.getLogger(getClass()); | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Description 查询配置列表 | 
				
			|||
     * @return | 
				
			|||
     * @author wxz | 
				
			|||
     * @date 2021.06.25 09:58 | 
				
			|||
    */ | 
				
			|||
    @Override | 
				
			|||
    public List<CorsConfigResultDTO> list() { | 
				
			|||
        LambdaQueryWrapper<CorsConfigEntity> conditions = new LambdaQueryWrapper<>(); | 
				
			|||
        return ConvertUtils.sourceToTarget(corsConfigDao.selectList(conditions), CorsConfigResultDTO.class); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Override | 
				
			|||
    public CorsConfigResultDTO addConfig(String headerType, String headerValue, String comment) { | 
				
			|||
        LambdaQueryWrapper<CorsConfigEntity> w = new LambdaQueryWrapper<>(); | 
				
			|||
        w.eq(CorsConfigEntity::getHeaderType, headerType.trim()); | 
				
			|||
        w.eq(CorsConfigEntity::getHeaderValue, headerValue.trim()); | 
				
			|||
        if (corsConfigDao.selectCount(w) > 0) { | 
				
			|||
            throw new RenException(EpmetErrorCode.OPER_CORS_CONFIG_ERROR.getCode(), "已存在该跨域配置,请勿重复添加"); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        CorsConfigEntity insert = new CorsConfigEntity(); | 
				
			|||
        insert.setHeaderType(headerType); | 
				
			|||
        insert.setHeaderValue(headerValue); | 
				
			|||
        insert.setComment(comment); | 
				
			|||
        if (corsConfigDao.insert(insert) == 0) { | 
				
			|||
            throw new RenException(EpmetErrorCode.OPER_CORS_CONFIG_ERROR.getCode(), "插入跨域配置出错"); | 
				
			|||
        } | 
				
			|||
 | 
				
			|||
        deleteFromRedis(); | 
				
			|||
        return new CorsConfigResultDTO(insert.getId(), headerType, headerValue, comment); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Override | 
				
			|||
    public void deleteById(String configId) { | 
				
			|||
        if (corsConfigDao.deleteById(configId) == 0) { | 
				
			|||
            String msg = "删除出错,不存在该项数据"; | 
				
			|||
            throw new RenException(EpmetErrorCode.OPER_CORS_CONFIG_ERROR.getCode(), msg, msg, RenException.MessageMode.CODE_INTERNAL_EXTERNAL); | 
				
			|||
        } | 
				
			|||
        deleteFromRedis(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    @Override | 
				
			|||
    public void updateById(String configId, String headerType, String headerValue, String comment) { | 
				
			|||
        CorsConfigEntity exists = corsConfigDao.selectById(configId); | 
				
			|||
        if (exists == null) { | 
				
			|||
            String msg = "该项数据不存在"; | 
				
			|||
            throw new RenException(EpmetErrorCode.OPER_CORS_CONFIG_ERROR.getCode(), msg, msg, RenException.MessageMode.CODE_INTERNAL_EXTERNAL); | 
				
			|||
        } | 
				
			|||
        exists.setHeaderType(headerType); | 
				
			|||
        exists.setHeaderValue(headerValue); | 
				
			|||
        exists.setComment(comment); | 
				
			|||
        if (corsConfigDao.updateById(exists) == 0) { | 
				
			|||
            throw new RenException(EpmetErrorCode.OPER_CORS_CONFIG_ERROR.getCode(), "更新出错,影响条数为0"); | 
				
			|||
        } | 
				
			|||
        deleteFromRedis(); | 
				
			|||
    } | 
				
			|||
 | 
				
			|||
    /** | 
				
			|||
     * @Description 从缓存中删除 | 
				
			|||
     * @return | 
				
			|||
     * @author wxz | 
				
			|||
     * @date 2021.06.25 14:26 | 
				
			|||
    */ | 
				
			|||
    private void deleteFromRedis() { | 
				
			|||
        try { | 
				
			|||
            redisTemplate.delete(RedisKeys.getCorsConfigKey()); | 
				
			|||
        } catch (Exception e) { | 
				
			|||
            String errorMsg = ExceptionUtils.getErrorStackTrace(e); | 
				
			|||
            logger.error(String.format("从Redis中删除Cors跨域信息失败,程序继续执行。错误信息:%s", errorMsg)); | 
				
			|||
        } | 
				
			|||
    } | 
				
			|||
} | 
				
			|||
@ -0,0 +1,13 @@ | 
				
			|||
CREATE TABLE `cors_config` ( | 
				
			|||
  `ID` varchar(64) NOT NULL, | 
				
			|||
  `HEADER_TYPE` varchar(32) NOT NULL COMMENT '首部类型', | 
				
			|||
  `HEADER_VALUE` varchar(128) NOT NULL COMMENT '首部值', | 
				
			|||
  `COMMENT` varchar(512) DEFAULT NULL COMMENT '说明', | 
				
			|||
  `DEL_FLAG` int(11) NOT NULL DEFAULT '0' COMMENT '删除标识 0.未删除 1.已删除', | 
				
			|||
  `REVISION` int(11) NOT NULL COMMENT '乐观锁', | 
				
			|||
  `CREATED_BY` varchar(32) NOT NULL COMMENT '创建人', | 
				
			|||
  `CREATED_TIME` datetime NOT NULL COMMENT '创建时间', | 
				
			|||
  `UPDATED_BY` varchar(32) NOT NULL COMMENT '更新人', | 
				
			|||
  `UPDATED_TIME` datetime NOT NULL COMMENT '更新时间', | 
				
			|||
  PRIMARY KEY (`ID`) | 
				
			|||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='跨域配置表' | 
				
			|||
@ -0,0 +1,20 @@ | 
				
			|||
<?xml version="1.0" encoding="UTF-8"?> | 
				
			|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | 
				
			|||
 | 
				
			|||
<mapper namespace="com.epmet.dao.CorsConfigDao"> | 
				
			|||
 | 
				
			|||
    <resultMap type="com.epmet.entity.CorsConfigEntity" id="corsConfigMap"> | 
				
			|||
        <result property="id" column="ID"/> | 
				
			|||
        <result property="headerType" column="HEADER_TYPE"/> | 
				
			|||
        <result property="headerValue" column="HEADER_VALUE"/> | 
				
			|||
        <result property="comment" column="COMMENT"/> | 
				
			|||
        <result property="delFlag" column="DEL_FLAG"/> | 
				
			|||
        <result property="revision" column="REVISION"/> | 
				
			|||
        <result property="createdBy" column="CREATED_BY"/> | 
				
			|||
        <result property="createdTime" column="CREATED_TIME"/> | 
				
			|||
        <result property="updatedBy" column="UPDATED_BY"/> | 
				
			|||
        <result property="updatedTime" column="UPDATED_TIME"/> | 
				
			|||
    </resultMap> | 
				
			|||
 | 
				
			|||
 | 
				
			|||
</mapper> | 
				
			|||
@ -0,0 +1,21 @@ | 
				
			|||
package com.epmet.bean; | 
				
			|||
 | 
				
			|||
import lombok.AllArgsConstructor; | 
				
			|||
import lombok.Data; | 
				
			|||
import lombok.NoArgsConstructor; | 
				
			|||
 | 
				
			|||
import java.util.List; | 
				
			|||
 | 
				
			|||
/** | 
				
			|||
 * @Description 跨域配置缓存 | 
				
			|||
 * @author wxz | 
				
			|||
 * @date 2021.06.25 10:59:44 | 
				
			|||
*/ | 
				
			|||
@Data | 
				
			|||
@AllArgsConstructor | 
				
			|||
@NoArgsConstructor | 
				
			|||
public class CorsConfigCache { | 
				
			|||
 | 
				
			|||
    private List<String> accessControlAllowOrigins; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
					Loading…
					
					
				
		Reference in new issue