Commit cadb5207 by 宋珺琪

记录日志功能

parent a88f200b
package com.founder.commonutils.model.newPublicEntity.CodeYymc;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* code_yymc(字典表)
*/
@Data
@ApiModel("code_yymc")
public class CodeYymc implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.INPUT)
/**
* 编码
*/
@ApiModelProperty("编码")
private String code;
/**
* 名称
*/
@ApiModelProperty("名称")
private String name;
/**
* 是否有子节点(1有0无)
*/
@ApiModelProperty("是否有子节点(1有0无)")
private String isparent;
/**
* 操作类型代码,code_czlx
*/
@ApiModelProperty("操作类型代码,code_czlx")
private String czlxdm;
/**
* 操作类型
*/
@ApiModelProperty("操作类型")
private String czlx;
/**
* 级别
*/
@ApiModelProperty("级别")
private String lev;
/**
* 一级代码
*/
@ApiModelProperty("一级代码")
private String codeLev1;
/**
* 一级名称
*/
@ApiModelProperty("一级名称")
private String dscLev1;
/**
* 二级代码
*/
@ApiModelProperty("二级代码")
private String codeLev2;
/**
* 二级名称
*/
@ApiModelProperty("二级名称")
private String dscLev2;
/**
* 三级代码
*/
@ApiModelProperty("三级代码")
private String codeLev3;
/**
* 三级名称
*/
@ApiModelProperty("三级名称")
private String dscLev3;
/**
* 四级代码
*/
@ApiModelProperty("四级代码")
private String codeLev4;
/**
* 四级名称
*/
@ApiModelProperty("四级名称")
private String dscLev4;
/**
* 五级代码
*/
@ApiModelProperty("五级代码")
private String codeLev5;
/**
* 五级名称
*/
@ApiModelProperty("五级名称")
private String dscLev5;
@ApiModelProperty(value = "当前第几页")
@TableField(exist = false)
private int page;
@ApiModelProperty(value = "每页多少行")
@TableField(exist = false)
private int limit;
}
\ No newline at end of file
package com.founder.commonutils.model.newPublicEntity.CodeYymc;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* sys_yhczrz(记录日志实体)
*/
@Data
public class SysYhczrz implements Serializable {
@ApiModelProperty("用户身份证号")
private String yhGmsfhm;
@ApiModelProperty("用户单位代码")
private String yhdwGajgjgdm;
@ApiModelProperty("用户单位名称")
private String yhdwGajgmc;
@ApiModelProperty("用户姓名")
private String yhXm;
@ApiModelProperty("用户ip")
private String yhIp;
@ApiModelProperty("应用名称")
private String yymcJyqk;
@ApiModelProperty("应用类型代码")
private String yymcdm;
@ApiModelProperty("操作类型代码")
private String czlxdm;
@ApiModelProperty("操作参数")
private String czxxParam;
@ApiModelProperty("操作类型")
private String czlx;
@ApiModelProperty("登记人姓名")
private String xxdjryXm;
@ApiModelProperty("信息操作人员_公民身份号码")
private String xxczryGmsfhm;
@ApiModelProperty("信息登记人员_公民身份号码")
private String xxdjryGmsfhm;
@ApiModelProperty("信息操作人员_姓名")
private String xxczryXm;
@ApiModelProperty("信息操作单位_公安机关机构代码")
private String xxczdwGajgjgdm;
@ApiModelProperty("信息操作单位_公安机关名称")
private String xxczdwGajgmc;
@ApiModelProperty("信息登记人员_联系电话")
private String xxdjryLxdh;
@ApiModelProperty("信息登记单位_公安机关名称")
private String xxdjdwGajgmc;
@ApiModelProperty("信息登记单位_公安机关机构代码")
private String xxdjdwGajgjgdm;
}
......@@ -130,7 +130,7 @@ public class TbAsjJwdinfo {
@ApiModelProperty(value = "信息登记单位_公安机关名称")
private String xxdjdwGajgmc;
@ApiModelProperty(value = "受理时间")
private Date slsj;
private String slsj;
@ApiModelProperty(value = "受理开始时间")
private String slsjKssj;
@ApiModelProperty(value = "受理结束时间")
......
......@@ -507,6 +507,33 @@ public class HttpUtil {
return result;
}
public static String doPostJson(String url, String json,String token) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
httpPost.setHeader("founder.authorization", token);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return resultString;
}
}
package com.founder.servicebase.controller.CodeYymcController;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.founder.commonutils.model.newPublicEntity.CodeYymc.CodeYymc;
import com.founder.commonutils.model.newPublicEntity.MapRestResult;
import com.founder.servicebase.logs.OperLog;
import com.founder.servicebase.logs.OperationType;
import com.founder.servicebase.mapper.mysqlMapper.CodeYymcMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/code")
@Api(tags = "页面按钮编码")
public class CodeYymcController {
@Autowired
CodeYymcMapper codeYymcMapper;
@PostMapping("yymcAdd")
@ApiOperation(value = "添加名称编码")
@OperLog(message = "添加名称编码", operation = OperationType.ADD)
public MapRestResult yymcAdd(@RequestBody CodeYymc codeYymc){
int insert = codeYymcMapper.insert(codeYymc);
if (insert > 0){
return new MapRestResult(200,"新增成功",codeYymc);
} else {
return new MapRestResult().error("保存失败");
}
}
@PostMapping("yymcDelete")
@ApiOperation(value = "删除名称编码")
@OperLog(message = "删除名称编码", operation = OperationType.DELETE)
public MapRestResult yymcDelete(@RequestBody CodeYymc codeYymc){
int i = codeYymcMapper.deleteById(codeYymc.getCode());
if (i > 0){
return new MapRestResult(200,"删除成功",codeYymc);
} else {
return new MapRestResult().error("删除失败");
}
}
@PostMapping("yymcUpdate")
@ApiOperation(value = "修改名称编码")
@OperLog(message = "修改名称编码", operation = OperationType.UPDATE)
public MapRestResult yymcUpdate(@RequestBody CodeYymc codeYymc){
UpdateWrapper<CodeYymc> wrapper = new UpdateWrapper<>();
wrapper.eq("code",codeYymc.getCode());
int update = codeYymcMapper.update(codeYymc, wrapper);
if (update > 0){
return new MapRestResult(200,"修改成功",codeYymc);
} else {
return new MapRestResult().error("修改失败");
}
}
@PostMapping("yymcSelect")
@ApiOperation(value = "查询code编码")
@OperLog(message = "查询code编码", operation = OperationType.QUERY)
public MapRestResult yymcSelect(@RequestBody CodeYymc codeYymc){
QueryWrapper<CodeYymc> wrapper = new QueryWrapper<>();
//根据name模糊
wrapper.like(StringUtils.isNotEmpty(codeYymc.getName()),"name",codeYymc.getName());
//一级名称
wrapper.like(StringUtils.isNotEmpty(codeYymc.getDscLev1()),"dsc_lev1",codeYymc.getDscLev1());
//二级名称
wrapper.like(StringUtils.isNotEmpty(codeYymc.getDscLev2()),"dsc_lev2",codeYymc.getDscLev2());
//三级名称
wrapper.like(StringUtils.isNotEmpty(codeYymc.getDscLev3()),"dsc_lev3",codeYymc.getDscLev3());
//四级名称
wrapper.like(StringUtils.isNotEmpty(codeYymc.getDscLev4()),"dsc_lev4",codeYymc.getDscLev4());
//五级名称
wrapper.like(StringUtils.isNotEmpty(codeYymc.getDscLev5()),"dsc_lev5",codeYymc.getDscLev5());
//是否是父级
wrapper.eq(StringUtils.isNotEmpty(codeYymc.getIsparent()),"isparent",codeYymc.getIsparent());
//操作类型代码
wrapper.eq(StringUtils.isNotEmpty(codeYymc.getCzlxdm()),"czlxdm",codeYymc.getCzlxdm());
//级别
wrapper.eq(StringUtils.isNotEmpty(codeYymc.getLev()),"lev",codeYymc.getLev());
IPage iPage = codeYymcMapper.selectPage(new Page(codeYymc.getPage(), codeYymc.getLimit()), wrapper);
return new MapRestResult(200,"ok",iPage.getTotal(),iPage.getRecords());
}
@PostMapping("yymcList")
@ApiOperation(value = "所有名称的集合")
@OperLog(message = "所有名称的集合", operation = OperationType.QUERY)
public MapRestResult yymcList(){
QueryWrapper<CodeYymc> wrapper = new QueryWrapper<>();
wrapper.select("name");
List<String> collect = codeYymcMapper.selectList(wrapper).stream()
.map(o -> o.getName()).distinct()
.collect(Collectors.toList());
System.out.println(collect);
return new MapRestResult(200,"ok",collect.size(),collect);
}
}
package com.founder.servicebase.interceptor;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* 解决拦截器 I/O error while reading input message; nested exception is java.io.IOException: Stream closed 问题
*/
@Component
public class AntiSqlInjectionfilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
//取Body数据
RepeatedlyReadRequestWrapper requestWrapper = new RepeatedlyReadRequestWrapper(request);
//TODO something
filterChain.doFilter(requestWrapper != null ? requestWrapper : request, servletResponse);
}
}
\ No newline at end of file
package com.founder.servicebase.interceptor;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
/**
* 解决拦截器 getReader() has already been called for this request
* HttpServletRequest只能被读取一次 重写getInputStream和getReader
*/
public class RepeatedlyReadRequestWrapper extends HttpServletRequestWrapper {
private final String body;
public RepeatedlyReadRequestWrapper(HttpServletRequest request) throws IOException{
super(request);
StringBuilder sb = new StringBuilder();
InputStream ins = request.getInputStream();
BufferedReader isr = null;
try{
if(ins != null){
isr = new BufferedReader(new InputStreamReader(ins));
char[] charBuffer = new char[128];
int readCount;
while((readCount = isr.read(charBuffer)) != -1){
sb.append(charBuffer,0,readCount);
}
}
}catch (IOException e){
throw e;
}finally {
if(isr != null) {
isr.close();
}
}
sb.toString();
body = sb.toString();
}
public String getBody() {
System.out.println(body);
return this.body;
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletIns = new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() {
return byteArrayIns.read();
}
};
return servletIns;
}
}
\ No newline at end of file
......@@ -3,26 +3,29 @@ package com.founder.servicebase.interceptor;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.founder.commonutils.Exception.TokenException;
import com.founder.commonutils.model.newPublicEntity.*;
import com.founder.commonutils.util.JwtUser;
import com.founder.commonutils.util.NetworkUtil;
import com.founder.commonutils.util.ResultUtil;
import com.founder.commonutils.model.newPublicEntity.CodeYymc.CodeYymc;
import com.founder.commonutils.model.newPublicEntity.CodeYymc.SysYhczrz;
import com.founder.commonutils.util.*;
import com.founder.servicebase.mapper.mysqlMapper.CodeYymcMapper;
import com.founder.servicebase.service.SkServiceApplyService;
import com.founder.servicebase.service.SkServiceService;
import com.founder.servicebase.service.SysUserService;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.*;
/**
* @author jlt
......@@ -38,6 +41,18 @@ public class TokenInterceptor implements HandlerInterceptor {
@Autowired
private SkServiceService service;
@Value("${logUrl}")
private String URL ;
@Value("${logtoken}")
private String token ;
@Value("${xzxtlog}")
private String xzxtlog ;
@Autowired
CodeYymcMapper codeYymcMapper;
private JwtUser jwtUser = new JwtUser();
private boolean flag = true;//true代表用户登录,false代表第三方登录
......@@ -116,6 +131,14 @@ public class TokenInterceptor implements HandlerInterceptor {
System.out.println(token);
str = verifyToken(request,token);
if (str.equals("")) {
Enumeration<String> headerNames = request.getHeaderNames();
while(headerNames.hasMoreElements()){//如果请求头中还有key
if(headerNames.nextElement().equals("logcode")){
if (xzxtlog.equals("true") && !request.getHeader("logcode").equals("") && request.getHeader("logcode")!=null){
savaYhczrz(request);
}
}
}
return true;
} else {//账号、密码不匹配
Map<String, Object> map = getMap(401, str);
......@@ -210,4 +233,81 @@ public class TokenInterceptor implements HandlerInterceptor {
map.put("msg", msg);
return map;
}
/**
* 记录日志接口 http://10.142.16.177:9026/yhczrz/savaYhczrz
*/
public void savaYhczrz(HttpServletRequest request){
String logcode = request.getHeader("logcode");
System.out.println(logcode);
// 根据code去查询对应名称;
QueryWrapper wrapper = new QueryWrapper<>();
wrapper.eq("code",logcode);
CodeYymc codeYymc = codeYymcMapper.selectOne(wrapper);
SysUser user = (SysUser)request.getAttribute("user");
SysYhczrz sysYhczrz = new SysYhczrz();
sysYhczrz.setYhGmsfhm(user.getIdentitycard());
sysYhczrz.setYhdwGajgjgdm(user.getUnitcode());
sysYhczrz.setYhdwGajgmc(user.getUnitname());
sysYhczrz.setYhXm(user.getTrueName());
sysYhczrz.setYhIp(user.getIp());
sysYhczrz.setYymcJyqk(codeYymc.getName());
sysYhczrz.setYymcdm(logcode);
sysYhczrz.setCzlxdm(codeYymc.getCzlxdm());
try {
if (codeYymc.getCzlxdm().equals("05")){
sysYhczrz.setCzxxParam(null);
}
//get 或者 post multipart/form-data格式
else if (request.getMethod().equals("POST") && request.getContentType().contains("form-data") ){
//获得提交的参数,将提交的参数的名称和对应的值存入到一个Map集合中
Map<String, String[]> parameterMap = request.getParameterMap();
String jsonStr = com.alibaba.fastjson.JSONObject.toJSONString(parameterMap);
com.alibaba.fastjson.JSONObject obj = com.alibaba.fastjson.JSONObject.parseObject(jsonStr);
System.out.println(obj.toJSONString());
sysYhczrz.setCzxxParam(obj.toJSONString());
} //post application/json 格式
else if (request.getMethod().equals("POST") &&request.getContentType().contains("application/json")){
RepeatedlyReadRequestWrapper repeatedlyReadRequestWrapper = new RepeatedlyReadRequestWrapper(request);
String s = repeatedlyReadRequestWrapper.getBody();
sysYhczrz.setCzxxParam(s);
System.out.println(s);
} //get
else if(request.getMethod().equals("GET")){
Map<String, String[]> parameterMap = request.getParameterMap();
String jsonStr = com.alibaba.fastjson.JSONObject.toJSONString(parameterMap);
com.alibaba.fastjson.JSONObject obj = com.alibaba.fastjson.JSONObject.parseObject(jsonStr);
System.out.println(obj.toJSONString());
sysYhczrz.setCzxxParam(obj.toJSONString());
}
} catch (IOException e) {
System.out.println("获取body失败");
throw new RuntimeException(e);
}
sysYhczrz.setCzlx(codeYymc.getCzlx());
sysYhczrz.setXxdjryXm(user.getLrr());
sysYhczrz.setXxczryGmsfhm(user.getIdentitycard());
sysYhczrz.setXxdjryGmsfhm(user.getIdentitycard());
sysYhczrz.setXxczryXm(user.getTrueName());
sysYhczrz.setXxczdwGajgjgdm(user.getUnitcode());
sysYhczrz.setXxczdwGajgmc(user.getUnitname());
sysYhczrz.setXxdjryLxdh(user.getTelephone());
sysYhczrz.setXxdjdwGajgmc(user.getUnitname());
sysYhczrz.setXxdjdwGajgjgdm(user.getUnitcode());
ObjectMapper mapper = new ObjectMapper();
try {
String json = mapper.writeValueAsString(sysYhczrz);
String s = HttpUtil.doPostJson(URL, json, token);
System.out.println(s);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
package com.founder.servicebase.mapper.mysqlMapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.founder.commonutils.model.newPublicEntity.CodeYymc.CodeYymc;
public interface CodeYymcMapper extends BaseMapper<CodeYymc> {
}
......@@ -235,8 +235,8 @@
)
</if>
<if test="startLng!=null and startLng!='' and endLng!=null and endLng!='' and startLat!=null and startLat!='' and endLat!=null and endLat!=''">
and cast(T.ASJFSDD_DQJD as signed) BETWEEN cast(#{startLng,jdbcType=VARCHAR} as signed) AND cast(#{endLng,jdbcType=VARCHAR} as signed)
AND cast(T.ASJFSDD_DQWD as signed) BETWEEN cast(#{startLat,jdbcType=VARCHAR} as signed) AND cast(#{endLat,jdbcType=VARCHAR} as signed)
and cast(T.ASJFSDD_DQJD as CHAR) BETWEEN cast(#{startLng,jdbcType=VARCHAR} as CHAR) AND cast(#{endLng,jdbcType=VARCHAR} as CHAR)
AND cast(T.ASJFSDD_DQWD as CHAR) BETWEEN cast(#{startLat,jdbcType=VARCHAR} as CHAR) AND cast(#{endLat,jdbcType=VARCHAR} as CHAR)
</if>
<if test="pabj_pdbz != null and pabj_pdbz == '0'">
and ZCJDDM not in ('0600','0700','0800')
......@@ -380,8 +380,8 @@
WHERE
1=1
<if test="startLng != null and startLng != '' and endLng != null and endLng != '' and startLat != null and startLat != ''and endLat != null and endLat != ''">
AND cast(X as signed) BETWEEN cast(#{startLng} as signed) AND cast(#{endLng} as signed)
AND cast(Y as signed) BETWEEN cast(#{startLat} as signed) AND cast(#{endLat} as signed)
AND cast(X as CHAR) BETWEEN cast(#{startLng} as signed) AND cast(#{endLng} as CHAR)
AND cast(Y as CHAR) BETWEEN cast(#{startLat} as signed) AND cast(#{endLat} as CHAR)
</if>
<if test="xm != null and xm != ''">
AND BZ.XM LIKE concat('%', #{xm , jdbcType=VARCHAR }, '%')
......
......@@ -156,6 +156,13 @@ public class TbStAsjServiceImpl extends ServiceImpl<TbStAsjMapper, TbStAsj> impl
if (params.getEndLng() != null && !params.getEndLng().equals("")) {
queryWrapper.le("CAST(x AS decimal(16,8))", Double.parseDouble(params.getEndLng()));
}
//时间
if (params.getKssj() != null) {
queryWrapper.ge("str_to_date(date,'%Y-%m-%d %H:%i:%s')", params.getKssj());
}
if (params.getJssj() != null) {
queryWrapper.le("str_to_date(date,'%Y-%m-%d %H:%i:%s')", params.getJssj());
}
List<SkPointlocation> list = skPointlocationService.list(queryWrapper);
Map<String,List<SkPointlocation>> listMap = list.stream().collect(Collectors.groupingBy(SkPointlocation::getObjectname));
......
......@@ -79,6 +79,10 @@ basePath=/data/images
imagesUrl=http://47.92.48.137:1008/images/
logUrl=http://39.99.155.173:8764/yhczrz/savaYhczrz
logtoken=Basic 9b6c45cfcf3a4a629e3ed90fa3e5d058
#xzxtlog=true /false ture \u8868\u793A\u5F00\u542F\u65E5\u5FD7\uFF0Cfalse\u8868\u793A\u5173\u95ED\u65E5\u5FD7\uFF0C\u9ED8\u8BA4\u662Fture
xzxtlog =true
#admin\u670D\u52A1\u76D1\u63A7\u6DFB\u52A0\u63CF\u8FF0\uFF08\u9875\u9762\u7EC6\u8282\u91CC\u7684\u4FE1\u606F \u63CF\u8FF0\u3001\u4F5C\u8005\u3001\u7248\u672C\uFF09
info.describe=SpringBoot_Founder_publicapi
......
......@@ -72,7 +72,10 @@ password=ENC(z+abBc/QcZelKfpAFXXeSwRBOcUjidsu)
basePath=/data/images
imagesUrl=http://47.92.48.137:1008/images/
logUrl=http://10.142.16.177:9026/yhczrz/savaYhczrz
logtoken=Basic 9b6c45cfcf3a4a629e3ed90fa3e5d058
#xzxtlog=true /false ture \u8868\u793A\u5F00\u542F\u65E5\u5FD7\uFF0Cfalse\u8868\u793A\u5173\u95ED\u65E5\u5FD7\uFF0C\u9ED8\u8BA4\u662Fture
xzxtlog =true
#admin\u670D\u52A1\u76D1\u63A7\u6DFB\u52A0\u63CF\u8FF0\uFF08\u9875\u9762\u7EC6\u8282\u91CC\u7684\u4FE1\u606F \u63CF\u8FF0\u3001\u4F5C\u8005\u3001\u7248\u672C\uFF09
info.describe=SpringBootAdmin_Founder_skyp!
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment