Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
I
ioc_sixiang_license
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zengtianlai3
ioc_sixiang_license
Commits
8746029d
Commit
8746029d
authored
Sep 08, 2022
by
AfirSraftGarrier
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/for-yx' into for-yx
parents
5a2db264
67ae1d61
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
226 additions
and
86 deletions
+226
-86
pom.xml
license/pom.xml
+7
-0
LoginController.java
.../java/iot/sixiang/license/controller/LoginController.java
+49
-37
SysOperLogController.java
.../iot/sixiang/license/controller/SysOperLogController.java
+5
-5
UserController.java
...n/java/iot/sixiang/license/controller/UserController.java
+55
-19
SysOperLog.java
.../src/main/java/iot/sixiang/license/entity/SysOperLog.java
+1
-3
JwtFilter.java
license/src/main/java/iot/sixiang/license/jwt/JwtFilter.java
+9
-4
SysOperLogMapper.java
...ain/java/iot/sixiang/license/mapper/SysOperLogMapper.java
+2
-1
UserMapper.java
.../src/main/java/iot/sixiang/license/mapper/UserMapper.java
+2
-0
LoginVo.java
...e/src/main/java/iot/sixiang/license/model/vo/LoginVo.java
+8
-0
SysOperLogVo.java
.../main/java/iot/sixiang/license/model/vo/SysOperLogVo.java
+37
-0
UserUpdatePwdVo.java
...in/java/iot/sixiang/license/model/vo/UserUpdatePwdVo.java
+18
-0
SysOperLogService.java
...n/java/iot/sixiang/license/service/SysOperLogService.java
+2
-1
UserService.java
...rc/main/java/iot/sixiang/license/service/UserService.java
+4
-1
SysOperLogServiceImpl.java
...t/sixiang/license/service/impl/SysOperLogServiceImpl.java
+5
-6
UserServiceImpl.java
...ava/iot/sixiang/license/service/impl/UserServiceImpl.java
+7
-5
application.yml
license/src/main/resources/application.yml
+8
-1
SysOperLogMapper.xml
license/src/main/resources/mapper/SysOperLogMapper.xml
+2
-2
UserMapper.xml
license/src/main/resources/mapper/UserMapper.xml
+5
-1
No files found.
license/pom.xml
View file @
8746029d
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
<description>
Demo project for Spring Boot
</description>
<description>
Demo project for Spring Boot
</description>
<properties>
<properties>
<java.version>
1.8
</java.version>
<java.version>
1.8
</java.version>
<acc.secret.version>
1.0.4
</acc.secret.version>
</properties>
</properties>
<dependencies>
<dependencies>
...
@@ -144,6 +145,12 @@
...
@@ -144,6 +145,12 @@
<version>
1.9
</version>
<version>
1.9
</version>
</dependency>
</dependency>
<dependency>
<groupId>
com.acc
</groupId>
<artifactId>
secret
</artifactId>
<version>
${acc.secret.version}
</version>
</dependency>
<!--邮件-->
<!--邮件-->
<dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<groupId>
org.springframework.boot
</groupId>
...
...
license/src/main/java/iot/sixiang/license/controller/LoginController.java
View file @
8746029d
package
iot
.
sixiang
.
license
.
controller
;
package
iot
.
sixiang
.
license
.
controller
;
import
com.acc.secret.util.RSAUtil
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiImplicitParams
;
import
io.swagger.annotations.ApiImplicitParams
;
import
io.swagger.annotations.ApiOperation
;
import
io.swagger.annotations.ApiOperation
;
import
iot.sixiang.license.consts.ResultCode
;
import
iot.sixiang.license.entity.User
;
import
iot.sixiang.license.jwt.JwtUtil
;
import
iot.sixiang.license.jwt.JwtUtil
;
import
iot.sixiang.license.jwt.LoginUser
;
import
iot.sixiang.license.jwt.LoginUser
;
import
iot.sixiang.license.jwt.UserUtils
;
import
iot.sixiang.license.jwt.UserUtils
;
import
iot.sixiang.license.log.BusinessType
;
import
iot.sixiang.license.log.BusinessType
;
import
iot.sixiang.license.log.MyLog
;
import
iot.sixiang.license.log.MyLog
;
import
iot.sixiang.license.mapper.UserMapper
;
import
iot.sixiang.license.model.BaseResult
;
import
iot.sixiang.license.model.BaseResult
;
import
iot.sixiang.license.model.ResResult
;
import
iot.sixiang.license.model.ResResult
;
import
iot.sixiang.license.model.vo.LoginVo
;
import
iot.sixiang.license.model.vo.LoginVo
;
...
@@ -22,6 +26,8 @@ import org.springframework.web.bind.annotation.*;
...
@@ -22,6 +26,8 @@ import org.springframework.web.bind.annotation.*;
import
springfox.documentation.annotations.ApiIgnore
;
import
springfox.documentation.annotations.ApiIgnore
;
import
javax.annotation.Resource
;
import
javax.annotation.Resource
;
import
javax.servlet.ServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.util.Date
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -37,18 +43,17 @@ public class LoginController {
...
@@ -37,18 +43,17 @@ public class LoginController {
@Resource
@Resource
EmailUtils
emailUtils
;
EmailUtils
emailUtils
;
@Resource
UserMapper
userMapper
;
@Value
(
"${spring.mail.to}"
)
@Value
(
"${spring.mail.to}"
)
private
String
account
;
private
String
account
;
@Value
(
"${rsa.private_key}"
)
private
String
PRIVATE_KRY
;
@Value
(
"${rsa.public_key}"
)
private
String
PUBLIC_KEY
;
//模拟数据库
private
static
final
String
USER_NAME
=
"root"
;
static
Map
<
String
,
LoginUser
>
userMap
=
new
HashMap
<>();
static
{
LoginUser
user1
=
new
LoginUser
(
"2147483647"
,
"root"
,
"123456"
);
userMap
.
put
(
"2147483647"
,
user1
);
}
/**
/**
* 模拟用户登录
* 模拟用户登录
*/
*/
...
@@ -64,10 +69,11 @@ public class LoginController {
...
@@ -64,10 +69,11 @@ public class LoginController {
if
(
StringUtils
.
isEmpty
(
userName
)
||
StringUtils
.
isEmpty
(
password
)
||
StringUtils
.
isEmpty
(
code
))
{
if
(
StringUtils
.
isEmpty
(
userName
)
||
StringUtils
.
isEmpty
(
password
)
||
StringUtils
.
isEmpty
(
code
))
{
return
ResResult
.
validate_failed
().
setMsgValue
(
"参数不能为空"
);
return
ResResult
.
validate_failed
().
setMsgValue
(
"参数不能为空"
);
}
}
for
(
LoginUser
dbUser
:
userMap
.
values
())
{
User
user
=
userMapper
.
getUserByUserName
(
USER_NAME
);
String
name
=
dbUser
.
getUserName
();
String
name
=
USER_NAME
;
String
psw
=
name
+
dbUser
.
getPassword
();
String
pwd
=
user
.
getPassword
();
if
(
DigestUtils
.
md5DigestAsHex
(
name
.
getBytes
()).
equals
(
userName
)
&&
DigestUtils
.
md5DigestAsHex
(
psw
.
getBytes
()).
equals
(
password
))
{
LoginUser
dbUser
=
new
LoginUser
(
String
.
valueOf
(
user
.
getUserId
()),
user
.
getUserName
(),
user
.
getPassword
());
if
(
name
.
equals
(
userName
)
&&
RSAUtil
.
getDecryptString
(
password
,
PRIVATE_KRY
).
equals
(
pwd
))
{
// 登录错误次数
// 登录错误次数
Integer
errCnt
=
UserUtils
.
getErrCnt
(
userName
);
Integer
errCnt
=
UserUtils
.
getErrCnt
(
userName
);
Date
countFreezeDate
=
UserUtils
.
getCountFreezeDate
(
userName
);
Date
countFreezeDate
=
UserUtils
.
getCountFreezeDate
(
userName
);
...
@@ -80,7 +86,9 @@ public class LoginController {
...
@@ -80,7 +86,9 @@ public class LoginController {
String
token
=
JwtUtil
.
createToken
(
dbUser
);
String
token
=
JwtUtil
.
createToken
(
dbUser
);
LoginVo
loginVo
=
new
LoginVo
();
LoginVo
loginVo
=
new
LoginVo
();
loginVo
.
setAuthorization
(
token
);
loginVo
.
setAuthorization
(
token
);
UserUtils
.
setToken
(
dbUser
.
getUserId
(),
token
);
loginVo
.
setUpdateTime
(
user
.
getUpdateTime
());
loginVo
.
setPubKey
(
PUBLIC_KEY
);
UserUtils
.
setToken
(
dbUser
.
getUserId
(),
token
);
UserUtils
.
setTokenExp
(
dbUser
.
getUserId
(),
JwtUtil
.
getTokenExp
());
UserUtils
.
setTokenExp
(
dbUser
.
getUserId
(),
JwtUtil
.
getTokenExp
());
UserUtils
.
removeErrCnt
(
userName
);
UserUtils
.
removeErrCnt
(
userName
);
UserUtils
.
removeCountFreezeDate
(
userName
);
UserUtils
.
removeCountFreezeDate
(
userName
);
...
@@ -93,7 +101,6 @@ public class LoginController {
...
@@ -93,7 +101,6 @@ public class LoginController {
}
}
}
}
}
}
}
Integer
errCnt
=
UserUtils
.
getErrCnt
(
userName
);
Integer
errCnt
=
UserUtils
.
getErrCnt
(
userName
);
if
(
errCnt
==
null
)
{
if
(
errCnt
==
null
)
{
UserUtils
.
setErrCnt
(
userName
,
1
);
UserUtils
.
setErrCnt
(
userName
,
1
);
...
@@ -119,6 +126,11 @@ public class LoginController {
...
@@ -119,6 +126,11 @@ public class LoginController {
return
ResResult
.
failed
().
setMsgValue
(
"用户名或密码错误"
);
return
ResResult
.
failed
().
setMsgValue
(
"用户名或密码错误"
);
}
}
//public static void main(String[] args) {
// System.out.println(DigestUtils.md5DigestAsHex("PI7dBYlEfeP8IZ6vogqFL1U5pVnyCuNAGja3lsREx4M9r0SX123456PI7dBYlEfeP8IZ6vogqFL1U5pVnyCuNAGja3lsREx4M9r0SX".getBytes()));
// System.out.println(DigestUtils.md5DigestAsHex("PI7dBYlEfeP8IZ6vogqFL1U5pVnyCuNAGja3lsREx4M9r0SXrootPI7dBYlEfeP8IZ6vogqFL1U5pVnyCuNAGja3lsREx4M9r0SX".getBytes()));
//}
@ApiOperation
(
value
=
"注销接口"
,
notes
=
"注销接口"
)
@ApiOperation
(
value
=
"注销接口"
,
notes
=
"注销接口"
)
@GetMapping
(
"logout"
)
@GetMapping
(
"logout"
)
@MyLog
(
title
=
"注销"
,
businessType
=
BusinessType
.
OTHER
)
@MyLog
(
title
=
"注销"
,
businessType
=
BusinessType
.
OTHER
)
...
@@ -131,9 +143,9 @@ public class LoginController {
...
@@ -131,9 +143,9 @@ public class LoginController {
@RequestMapping
(
value
=
"fail"
,
method
=
{
RequestMethod
.
GET
,
RequestMethod
.
POST
})
@RequestMapping
(
value
=
"fail"
,
method
=
{
RequestMethod
.
GET
,
RequestMethod
.
POST
})
@ApiIgnore
@ApiIgnore
public
BaseResult
fail
()
{
public
BaseResult
fail
(
ServletRequest
servletRequest
)
{
String
msg
=
servletRequest
.
getAttribute
(
"msg"
).
toString
();
return
BaseResult
.
unauthorized
(
);
return
BaseResult
.
failed
().
setCodeValue
(
ResultCode
.
UNAUTHORIZED
.
getCode
()).
setMsgValue
(
msg
);
}
}
@ApiOperation
(
value
=
"发送验证码"
,
notes
=
"发送验证码到邮箱"
)
@ApiOperation
(
value
=
"发送验证码"
,
notes
=
"发送验证码到邮箱"
)
...
...
license/src/main/java/iot/sixiang/license/controller/SysOperLogController.java
View file @
8746029d
...
@@ -4,11 +4,11 @@ import io.swagger.annotations.Api;
...
@@ -4,11 +4,11 @@ import io.swagger.annotations.Api;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiImplicitParams
;
import
io.swagger.annotations.ApiImplicitParams
;
import
io.swagger.annotations.ApiOperation
;
import
io.swagger.annotations.ApiOperation
;
import
iot.sixiang.license.entity.SysOperLog
;
import
iot.sixiang.license.log.BusinessType
;
import
iot.sixiang.license.log.BusinessType
;
import
iot.sixiang.license.log.MyLog
;
import
iot.sixiang.license.log.MyLog
;
import
iot.sixiang.license.model.PageInfoModel
;
import
iot.sixiang.license.model.PageInfoModel
;
import
iot.sixiang.license.model.PageResult
;
import
iot.sixiang.license.model.PageResult
;
import
iot.sixiang.license.model.vo.SysOperLogVo
;
import
iot.sixiang.license.service.SysOperLogService
;
import
iot.sixiang.license.service.SysOperLogService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.GetMapping
;
...
@@ -42,16 +42,16 @@ public class SysOperLogController {
...
@@ -42,16 +42,16 @@ public class SysOperLogController {
@ApiImplicitParam
(
name
=
"pageNo"
,
value
=
"当前在第几页"
,
required
=
true
,
dataType
=
"int"
),
@ApiImplicitParam
(
name
=
"pageNo"
,
value
=
"当前在第几页"
,
required
=
true
,
dataType
=
"int"
),
@ApiImplicitParam
(
name
=
"pageSize"
,
value
=
"每页显示多少条"
,
required
=
true
,
dataType
=
"int"
)
@ApiImplicitParam
(
name
=
"pageSize"
,
value
=
"每页显示多少条"
,
required
=
true
,
dataType
=
"int"
)
})
})
public
PageResult
<
SysOperLog
>
getOperLogList
(
@RequestParam
(
value
=
"pageNo"
,
defaultValue
=
"0"
)
int
pageNo
,
public
PageResult
<
SysOperLog
Vo
>
getOperLogList
(
@RequestParam
(
value
=
"pageNo"
,
defaultValue
=
"0"
)
int
pageNo
,
@RequestParam
(
value
=
"pageSize"
,
defaultValue
=
"0"
)
int
pageSize
)
{
@RequestParam
(
value
=
"pageSize"
,
defaultValue
=
"0"
)
int
pageSize
)
{
PageInfoModel
<
SysOperLog
>
records
=
sysOperLogService
.
getOperLogList
(
pageNo
,
pageSize
);
PageInfoModel
<
SysOperLog
Vo
>
records
=
sysOperLogService
.
getOperLogList
(
pageNo
,
pageSize
);
int
total
=
records
.
getTotal
();
int
total
=
records
.
getTotal
();
int
pages
=
total
/
pageSize
;
//pages为总页数
int
pages
=
total
/
pageSize
;
//pages为总页数
int
mod
=
total
%
pageSize
;
int
mod
=
total
%
pageSize
;
if
(
mod
!=
0
){
if
(
mod
!=
0
){
pages
=
pages
+
1
;
pages
=
pages
+
1
;
}
}
List
<
SysOperLog
>
result
=
records
.
getResult
();
List
<
SysOperLog
Vo
>
result
=
records
.
getResult
();
return
new
PageResult
(
200
,
"查找成功"
,
pageNo
,
pages
,
total
,
result
);
return
new
PageResult
(
200
,
"查找成功"
,
pageNo
,
pages
,
total
,
result
);
}
}
}
}
license/src/main/java/iot/sixiang/license/controller/UserController.java
View file @
8746029d
package
iot
.
sixiang
.
license
.
controller
;
package
iot
.
sixiang
.
license
.
controller
;
import
com.acc.secret.util.RSAUtil
;
import
com.alibaba.fastjson.JSONObject
;
import
com.alibaba.fastjson.JSONObject
;
import
com.github.xiaoymin.knife4j.annotations.ApiOperationSupport
;
import
com.github.xiaoymin.knife4j.annotations.ApiOperationSupport
;
import
com.github.xiaoymin.knife4j.annotations.DynamicParameter
;
import
com.github.xiaoymin.knife4j.annotations.DynamicParameter
;
...
@@ -9,16 +10,21 @@ import io.swagger.annotations.Api;
...
@@ -9,16 +10,21 @@ import io.swagger.annotations.Api;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiImplicitParam
;
import
io.swagger.annotations.ApiImplicitParams
;
import
io.swagger.annotations.ApiImplicitParams
;
import
io.swagger.annotations.ApiOperation
;
import
io.swagger.annotations.ApiOperation
;
import
iot.sixiang.license.entity.User
;
import
iot.sixiang.license.jwt.UserUtils
;
import
iot.sixiang.license.log.BusinessType
;
import
iot.sixiang.license.log.BusinessType
;
import
iot.sixiang.license.log.MyLog
;
import
iot.sixiang.license.log.MyLog
;
import
iot.sixiang.license.model.BaseResult
;
import
iot.sixiang.license.model.BaseResult
;
import
iot.sixiang.license.model.PageInfoModel
;
import
iot.sixiang.license.model.PageInfoModel
;
import
iot.sixiang.license.model.PageResult
;
import
iot.sixiang.license.model.PageResult
;
import
iot.sixiang.license.model.vo.UserUpdatePwdVo
;
import
iot.sixiang.license.model.vo.UserVo
;
import
iot.sixiang.license.model.vo.UserVo
;
import
iot.sixiang.license.service.UserService
;
import
iot.sixiang.license.service.UserService
;
import
iot.sixiang.license.util.CommonUtil
;
import
iot.sixiang.license.util.CommonUtil
;
import
iot.sixiang.license.xss.XssUtil
;
import
iot.sixiang.license.xss.XssUtil
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.util.DigestUtils
;
import
org.springframework.util.DigestUtils
;
import
org.springframework.web.bind.WebDataBinder
;
import
org.springframework.web.bind.WebDataBinder
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.*
;
...
@@ -40,6 +46,8 @@ public class UserController {
...
@@ -40,6 +46,8 @@ public class UserController {
@Autowired
@Autowired
private
UserService
userService
;
private
UserService
userService
;
@Value
(
"${rsa.private_key}"
)
private
String
PRIVATE_KRY
;
@InitBinder
@InitBinder
public
void
initBinder
(
WebDataBinder
binder
)
{
public
void
initBinder
(
WebDataBinder
binder
)
{
...
@@ -91,28 +99,56 @@ public class UserController {
...
@@ -91,28 +99,56 @@ public class UserController {
}
}
}
}
/**
///**
* 修改user
// * 修改user
*
// *
* @param jsonObject
// * @param jsonObject
* @return
// * @return
*/
// */
@ApiOperation
(
value
=
"用户修改接口"
,
notes
=
"修改用户"
)
//@ApiOperation(value = "用户修改接口", notes = "修改用户")
@PostMapping
(
"update"
)
//@PostMapping("update")
@MyLog
(
title
=
"修改用户"
,
optParam
=
"#{userId},#{password}"
,
businessType
=
BusinessType
.
UPDATE
)
//@MyLog(title = "修改用户", optParam = "#{userId},#{password}", businessType = BusinessType.UPDATE)
@ApiOperationSupport
(
params
=
@DynamicParameters
(
name
=
"jsonObject"
,
properties
=
{
//@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {
@DynamicParameter
(
name
=
"userId"
,
value
=
"用户Id"
,
required
=
true
,
dataTypeClass
=
Integer
.
class
),
// @DynamicParameter(name = "userId", value = "用户Id", required = true, dataTypeClass = Integer.class),
@DynamicParameter
(
name
=
"password"
,
value
=
"密码"
,
required
=
true
,
dataTypeClass
=
String
.
class
)
// @DynamicParameter(name = "password", value = "密码", required = true, dataTypeClass = String.class)
}))
//}))
public
BaseResult
updateUser
(
@RequestBody
JSONObject
jsonObject
)
{
//public BaseResult updateUser(@RequestBody JSONObject jsonObject) {
int
userId
=
jsonObject
.
getInteger
(
"userId"
);
// int userId = jsonObject.getInteger("userId");
String
password
=
jsonObject
.
getString
(
"password"
);
// String password = jsonObject.getString("password");
boolean
res
=
userService
.
updateUser
(
userId
,
password
);
// boolean res = userService.updateUser(userId, password);
if
(
res
)
{
// if (res) {
return
BaseResult
.
success
();
// return BaseResult.success();
// } else {
// return BaseResult.failed();
// }
//}
@ApiOperation
(
value
=
"用户修改密码"
,
notes
=
"修改密码"
)
@PostMapping
(
"update_pwd"
)
@MyLog
(
title
=
"修改密码"
,
businessType
=
BusinessType
.
UPDATE
)
public
BaseResult
updatePwd
(
@RequestBody
UserUpdatePwdVo
userUpdatePwdVo
)
{
String
oldPassWord
=
userUpdatePwdVo
.
getOldPassWord
();
String
newPassWord
=
userUpdatePwdVo
.
getNewPassWord
();
String
userId
=
UserUtils
.
getLoginUserId
();
User
user
;
if
(!
StringUtils
.
isEmpty
(
userId
))
{
user
=
userService
.
getUserById
(
Integer
.
parseInt
(
userId
));
}
else
{
}
else
{
return
BaseResult
.
failed
();
return
BaseResult
.
failed
();
}
}
oldPassWord
=
RSAUtil
.
getDecryptString
(
oldPassWord
,
PRIVATE_KRY
);
newPassWord
=
RSAUtil
.
getDecryptString
(
newPassWord
,
PRIVATE_KRY
);
if
(
oldPassWord
.
equals
(
user
.
getPassword
()))
{
user
.
setPassword
(
newPassWord
);
boolean
b
=
userService
.
updateUser
(
user
);
if
(
b
)
{
return
BaseResult
.
success
().
setMsgValue
(
"密码修改成功"
);
}
else
{
return
BaseResult
.
failed
().
setMsgValue
(
"密码修改失败"
);
}
}
else
{
return
BaseResult
.
failed
().
setMsgValue
(
"原密码出错"
);
}
}
}
...
...
license/src/main/java/iot/sixiang/license/entity/SysOperLog.java
View file @
8746029d
...
@@ -35,7 +35,7 @@ public class SysOperLog implements Serializable {
...
@@ -35,7 +35,7 @@ public class SysOperLog implements Serializable {
@ApiModelProperty
(
"参数"
)
@ApiModelProperty
(
"参数"
)
private
String
optParam
;
private
String
optParam
;
@ApiModelProperty
(
"业务类型(0其它 1
新增 2修改 3
删除)"
)
@ApiModelProperty
(
"业务类型(0其它 1
查找 2新增 3修改 4
删除)"
)
private
Integer
businessType
;
private
Integer
businessType
;
@ApiModelProperty
(
"路径名称"
)
@ApiModelProperty
(
"路径名称"
)
...
@@ -49,6 +49,4 @@ public class SysOperLog implements Serializable {
...
@@ -49,6 +49,4 @@ public class SysOperLog implements Serializable {
@ApiModelProperty
(
"操作时间"
)
@ApiModelProperty
(
"操作时间"
)
private
Date
operTime
;
private
Date
operTime
;
}
}
license/src/main/java/iot/sixiang/license/jwt/JwtFilter.java
View file @
8746029d
...
@@ -62,23 +62,28 @@ public class JwtFilter implements Filter {
...
@@ -62,23 +62,28 @@ public class JwtFilter implements Filter {
}
}
if
(
StringUtils
.
isEmpty
(
token
))
{
if
(
StringUtils
.
isEmpty
(
token
))
{
request
.
setAttribute
(
"msg"
,
"
认证信息
不能为空"
);
request
.
setAttribute
(
"msg"
,
"
token
不能为空"
);
request
.
getRequestDispatcher
(
"/iot_license/fail"
).
forward
(
request
,
response
);
request
.
getRequestDispatcher
(
"/iot_license/fail"
).
forward
(
request
,
response
);
}
else
{
}
else
{
DecodedJWT
jwt
=
JwtUtil
.
verifyToken
(
token
);
DecodedJWT
jwt
=
JwtUtil
.
verifyToken
(
token
);
if
(
jwt
==
null
)
{
if
(
jwt
==
null
)
{
request
.
setAttribute
(
"msg"
,
"
认证信息非法
"
);
request
.
setAttribute
(
"msg"
,
"
非法token
"
);
request
.
getRequestDispatcher
(
"/iot_license/fail"
).
forward
(
request
,
response
);
request
.
getRequestDispatcher
(
"/iot_license/fail"
).
forward
(
request
,
response
);
}
else
{
}
else
{
Map
<
String
,
Claim
>
userData
=
jwt
.
getClaims
();
Map
<
String
,
Claim
>
userData
=
jwt
.
getClaims
();
if
(
userData
==
null
)
{
if
(
userData
==
null
)
{
request
.
setAttribute
(
"msg"
,
"
认证信息非法
"
);
request
.
setAttribute
(
"msg"
,
"
非法token
"
);
request
.
getRequestDispatcher
(
"/iot_license/fail"
).
forward
(
request
,
response
);
request
.
getRequestDispatcher
(
"/iot_license/fail"
).
forward
(
request
,
response
);
return
;
return
;
}
}
String
userId
=
userData
.
get
(
"userId"
).
asString
();
String
userId
=
userData
.
get
(
"userId"
).
asString
();
String
userName
=
userData
.
get
(
"userName"
).
asString
();
String
userName
=
userData
.
get
(
"userName"
).
asString
();
String
password
=
""
;
String
password
=
""
;
if
(!
token
.
equals
(
UserUtils
.
getToken
(
userId
)))
{
request
.
setAttribute
(
"msg"
,
"账户已在别处登录,请重新登录"
);
request
.
getRequestDispatcher
(
"/iot_license/fail"
).
forward
(
request
,
response
);
return
;
}
LoginUser
loginUser
=
new
LoginUser
(
userId
,
userName
,
password
);
LoginUser
loginUser
=
new
LoginUser
(
userId
,
userName
,
password
);
Date
curDate
=
new
Date
();
Date
curDate
=
new
Date
();
Date
tokenExp
=
UserUtils
.
getTokenExp
(
userId
);
Date
tokenExp
=
UserUtils
.
getTokenExp
(
userId
);
...
@@ -89,7 +94,7 @@ public class JwtFilter implements Filter {
...
@@ -89,7 +94,7 @@ public class JwtFilter implements Filter {
}
else
{
}
else
{
UserUtils
.
removeToken
(
userId
);
UserUtils
.
removeToken
(
userId
);
UserUtils
.
removeTokenExp
(
userId
);
UserUtils
.
removeTokenExp
(
userId
);
request
.
setAttribute
(
"msg"
,
"token已
失效
"
);
request
.
setAttribute
(
"msg"
,
"token已
过期
"
);
request
.
getRequestDispatcher
(
"/iot_license/fail"
).
forward
(
request
,
response
);
request
.
getRequestDispatcher
(
"/iot_license/fail"
).
forward
(
request
,
response
);
}
}
}
}
...
...
license/src/main/java/iot/sixiang/license/mapper/SysOperLogMapper.java
View file @
8746029d
...
@@ -2,6 +2,7 @@ package iot.sixiang.license.mapper;
...
@@ -2,6 +2,7 @@ package iot.sixiang.license.mapper;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
com.baomidou.mybatisplus.core.mapper.BaseMapper
;
import
iot.sixiang.license.entity.SysOperLog
;
import
iot.sixiang.license.entity.SysOperLog
;
import
iot.sixiang.license.model.vo.SysOperLogVo
;
import
java.util.Date
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.List
;
...
@@ -18,5 +19,5 @@ public interface SysOperLogMapper extends BaseMapper<SysOperLog> {
...
@@ -18,5 +19,5 @@ public interface SysOperLogMapper extends BaseMapper<SysOperLog> {
boolean
addOperlog
(
String
title
,
Integer
businessType
,
String
uri
,
Integer
status
,
String
optParam
,
String
errorMsg
,
Date
operTime
);
boolean
addOperlog
(
String
title
,
Integer
businessType
,
String
uri
,
Integer
status
,
String
optParam
,
String
errorMsg
,
Date
operTime
);
List
<
SysOperLog
>
getOperLogList
();
List
<
SysOperLog
Vo
>
getOperLogList
();
}
}
license/src/main/java/iot/sixiang/license/mapper/UserMapper.java
View file @
8746029d
...
@@ -26,4 +26,6 @@ public interface UserMapper extends BaseMapper<User> {
...
@@ -26,4 +26,6 @@ public interface UserMapper extends BaseMapper<User> {
List
<
UserVo
>
getUserList
(
String
userName
,
String
company
);
List
<
UserVo
>
getUserList
(
String
userName
,
String
company
);
User
getUserByUserName
(
String
userName
);
User
getUserByUserName
(
String
userName
);
User
getUserById
(
int
userId
);
}
}
license/src/main/java/iot/sixiang/license/model/vo/LoginVo.java
View file @
8746029d
...
@@ -3,6 +3,8 @@ package iot.sixiang.license.model.vo;
...
@@ -3,6 +3,8 @@ package iot.sixiang.license.model.vo;
import
io.swagger.annotations.ApiModelProperty
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
lombok.Data
;
import
java.util.Date
;
/**
/**
* Created by m33 on 2022/6/14 18:51
* Created by m33 on 2022/6/14 18:51
*/
*/
...
@@ -11,4 +13,10 @@ public class LoginVo {
...
@@ -11,4 +13,10 @@ public class LoginVo {
@ApiModelProperty
(
"token"
)
@ApiModelProperty
(
"token"
)
private
String
authorization
;
private
String
authorization
;
@ApiModelProperty
(
"pubKey"
)
private
String
pubKey
;
@ApiModelProperty
(
"更新时间"
)
private
Date
updateTime
;
}
}
license/src/main/java/iot/sixiang/license/model/vo/SysOperLogVo.java
0 → 100644
View file @
8746029d
package
iot
.
sixiang
.
license
.
model
.
vo
;
import
com.baomidou.mybatisplus.annotation.IdType
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
java.util.Date
;
/**
* Created by m33
* Date 2022/9/7 14:52
* Description
*/
@Data
public
class
SysOperLogVo
{
@ApiModelProperty
(
"主键Id"
)
private
Integer
id
;
@ApiModelProperty
(
"模块标题"
)
private
String
title
;
@ApiModelProperty
(
"业务类型(0其它 1查找 2新增 3修改 4删除)"
)
private
Integer
businessType
;
@ApiModelProperty
(
"路径名称"
)
private
String
uri
;
@ApiModelProperty
(
"操作状态(0正常 1异常)"
)
private
Integer
status
;
@ApiModelProperty
(
"错误消息"
)
private
String
errorMsg
;
@ApiModelProperty
(
"操作时间"
)
private
Date
operTime
;
}
license/src/main/java/iot/sixiang/license/model/vo/UserUpdatePwdVo.java
0 → 100644
View file @
8746029d
package
iot
.
sixiang
.
license
.
model
.
vo
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
/**
* Created by m33
* Date 2022/9/7 15:06
* Description
*/
@Data
public
class
UserUpdatePwdVo
{
@ApiModelProperty
(
value
=
"旧密码"
)
private
String
oldPassWord
;
@ApiModelProperty
(
value
=
"新密码"
)
private
String
newPassWord
;
}
license/src/main/java/iot/sixiang/license/service/SysOperLogService.java
View file @
8746029d
...
@@ -3,6 +3,7 @@ package iot.sixiang.license.service;
...
@@ -3,6 +3,7 @@ package iot.sixiang.license.service;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
com.baomidou.mybatisplus.extension.service.IService
;
import
iot.sixiang.license.entity.SysOperLog
;
import
iot.sixiang.license.entity.SysOperLog
;
import
iot.sixiang.license.model.PageInfoModel
;
import
iot.sixiang.license.model.PageInfoModel
;
import
iot.sixiang.license.model.vo.SysOperLogVo
;
import
java.util.Date
;
import
java.util.Date
;
...
@@ -17,5 +18,5 @@ import java.util.Date;
...
@@ -17,5 +18,5 @@ import java.util.Date;
public
interface
SysOperLogService
extends
IService
<
SysOperLog
>
{
public
interface
SysOperLogService
extends
IService
<
SysOperLog
>
{
boolean
addOperlog
(
String
title
,
Integer
businessType
,
String
uri
,
Integer
status
,
String
optParam
,
String
errorMsg
,
Date
operTime
);
boolean
addOperlog
(
String
title
,
Integer
businessType
,
String
uri
,
Integer
status
,
String
optParam
,
String
errorMsg
,
Date
operTime
);
PageInfoModel
<
SysOperLog
>
getOperLogList
(
int
pageNo
,
int
pageSize
);
PageInfoModel
<
SysOperLog
Vo
>
getOperLogList
(
int
pageNo
,
int
pageSize
);
}
}
license/src/main/java/iot/sixiang/license/service/UserService.java
View file @
8746029d
package
iot
.
sixiang
.
license
.
service
;
package
iot
.
sixiang
.
license
.
service
;
import
iot.sixiang.license.entity.User
;
import
iot.sixiang.license.model.PageInfoModel
;
import
iot.sixiang.license.model.PageInfoModel
;
import
iot.sixiang.license.model.vo.UserVo
;
import
iot.sixiang.license.model.vo.UserVo
;
...
@@ -17,7 +18,9 @@ public interface UserService{
...
@@ -17,7 +18,9 @@ public interface UserService{
boolean
addUser
(
String
userName
,
String
company
,
String
password
);
boolean
addUser
(
String
userName
,
String
company
,
String
password
);
boolean
updateUser
(
int
userId
,
String
password
);
boolean
updateUser
(
User
user
);
PageInfoModel
<
UserVo
>
getUserList
(
int
pageNo
,
int
pageSize
,
String
userName
,
String
company
);
PageInfoModel
<
UserVo
>
getUserList
(
int
pageNo
,
int
pageSize
,
String
userName
,
String
company
);
User
getUserById
(
int
userId
);
}
}
license/src/main/java/iot/sixiang/license/service/impl/SysOperLogServiceImpl.java
View file @
8746029d
...
@@ -6,13 +6,13 @@ import iot.sixiang.license.entity.SysOperLog;
...
@@ -6,13 +6,13 @@ import iot.sixiang.license.entity.SysOperLog;
import
iot.sixiang.license.handler.IotLicenseException
;
import
iot.sixiang.license.handler.IotLicenseException
;
import
iot.sixiang.license.mapper.SysOperLogMapper
;
import
iot.sixiang.license.mapper.SysOperLogMapper
;
import
iot.sixiang.license.model.PageInfoModel
;
import
iot.sixiang.license.model.PageInfoModel
;
import
iot.sixiang.license.model.vo.SysOperLogVo
;
import
iot.sixiang.license.service.SysOperLogService
;
import
iot.sixiang.license.service.SysOperLogService
;
import
iot.sixiang.license.xss.XssUtil
;
import
iot.sixiang.license.xss.XssUtil
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
javax.annotation.Resource
;
import
javax.annotation.Resource
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Comparator
;
import
java.util.Date
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.List
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
...
@@ -45,18 +45,17 @@ public class SysOperLogServiceImpl extends ServiceImpl<SysOperLogMapper, SysOper
...
@@ -45,18 +45,17 @@ public class SysOperLogServiceImpl extends ServiceImpl<SysOperLogMapper, SysOper
}
}
@Override
@Override
public
PageInfoModel
<
SysOperLog
>
getOperLogList
(
int
pageNo
,
int
pageSize
)
{
public
PageInfoModel
<
SysOperLog
Vo
>
getOperLogList
(
int
pageNo
,
int
pageSize
)
{
if
(
pageNo
==
0
||
pageSize
==
0
)
{
if
(
pageNo
==
0
||
pageSize
==
0
)
{
throw
new
IotLicenseException
(
ResultCode
.
VALIDATE_FAILED
.
getCode
(),
ResultCode
.
VALIDATE_FAILED
.
getMsg
());
throw
new
IotLicenseException
(
ResultCode
.
VALIDATE_FAILED
.
getCode
(),
ResultCode
.
VALIDATE_FAILED
.
getMsg
());
}
}
List
<
SysOperLog
>
records
=
sysOperLogMapper
.
getOperLogList
();
List
<
SysOperLogVo
>
records
=
sysOperLogMapper
.
getOperLogList
();
records
=
records
.
stream
().
sorted
(
Comparator
.
comparing
(
SysOperLog:
:
getOperTime
,
Comparator
.
reverseOrder
())).
collect
(
Collectors
.
toList
());
List
<
SysOperLogVo
>
result
=
new
ArrayList
<>();
List
<
SysOperLog
>
result
=
new
ArrayList
<>();
int
begin
=
(
pageNo
-
1
)
*
pageSize
;
int
begin
=
(
pageNo
-
1
)
*
pageSize
;
if
(
begin
>=
0
&&
records
.
size
()
>
0
)
{
if
(
begin
>=
0
&&
records
.
size
()
>
0
)
{
result
=
records
.
stream
().
skip
(
begin
).
limit
(
pageSize
).
collect
(
Collectors
.
toList
());
result
=
records
.
stream
().
skip
(
begin
).
limit
(
pageSize
).
collect
(
Collectors
.
toList
());
}
}
PageInfoModel
<
SysOperLog
>
objectPageInfoModel
=
new
PageInfoModel
<>();
PageInfoModel
<
SysOperLog
Vo
>
objectPageInfoModel
=
new
PageInfoModel
<>();
objectPageInfoModel
.
setTotal
(
records
.
size
());
objectPageInfoModel
.
setTotal
(
records
.
size
());
objectPageInfoModel
.
setResult
(
result
);
objectPageInfoModel
.
setResult
(
result
);
return
objectPageInfoModel
;
return
objectPageInfoModel
;
...
...
license/src/main/java/iot/sixiang/license/service/impl/UserServiceImpl.java
View file @
8746029d
...
@@ -51,6 +51,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
...
@@ -51,6 +51,11 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
return
objectPageInfoModel
;
return
objectPageInfoModel
;
}
}
@Override
public
User
getUserById
(
int
userId
)
{
return
userMapper
.
getUserById
(
userId
);
}
@Override
@Override
public
boolean
deleteUser
(
int
userId
)
{
public
boolean
deleteUser
(
int
userId
)
{
if
(
userId
==
0
)
{
if
(
userId
==
0
)
{
...
@@ -72,10 +77,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
...
@@ -72,10 +77,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
}
}
@Override
@Override
public
boolean
updateUser
(
int
userId
,
String
password
)
{
public
boolean
updateUser
(
User
user
)
{
if
(
userId
==
0
||
StringUtils
.
isEmpty
(
password
))
{
return
userMapper
.
updateUser
(
user
.
getUserId
(),
user
.
getPassword
());
throw
new
IotLicenseException
(
ResultCode
.
VALIDATE_FAILED
.
getCode
(),
ResultCode
.
VALIDATE_FAILED
.
getMsg
());
}
return
userMapper
.
updateUser
(
userId
,
password
);
}
}
}
}
license/src/main/resources/application.yml
View file @
8746029d
...
@@ -32,5 +32,12 @@ server:
...
@@ -32,5 +32,12 @@ server:
cros
:
cros
:
# 需要设置访问白名单
# 需要设置访问白名单
cros_allowed_origins
:
http://192.168.1.88:8080, http://localhost:8868
cros_allowed_origins
:
http://192.168.1.88:8080, http://localhost:8868
, http://localhost:8080
cros_allowed_method
:
GET,POST
cros_allowed_method
:
GET,POST
other
:
md5
:
salt
:
PI7dBYlEfeP8IZ6vogqFL1U5pVnyCuNAGja3lsREx4M9r0SX
rsa
:
public_key
:
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA18W2H1hO98dUWf1PNKNWTWmxCyvvy0NOR7iSvp76J0LdzyMJxs8WHVAmRfSGOb9SvpDZhBVx11bhTBqkl1qMzJWzn+F2ZtTCH2nXZcJHwSfLuGqin5FRBYW1WrFkqwg+R80aOuRSrbo0k1bZg3JPkkCxISHieEZPjSV5a4r7+Xopj0a9Dnh3rh4nDmH2p/wvotkx1oMKdhFglYcAITlk9ucEUf+CDuSdTAFFeKg9+fPqwKqWZRJZPQXqV3pGZ1/JS7gPnBFGZojW44eJufkBeiW3pbBvm/cKOkTnb8o4oltYUJsirYSQCCG+sDtxUAuGxuDCv8p+r8dWE1z5+xKclQIDAQAB
private_key
:
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXxbYfWE73x1RZ/U80o1ZNabELK+/LQ05HuJK+nvonQt3PIwnGzxYdUCZF9IY5v1K+kNmEFXHXVuFMGqSXWozMlbOf4XZm1MIfaddlwkfBJ8u4aqKfkVEFhbVasWSrCD5HzRo65FKtujSTVtmDck+SQLEhIeJ4Rk+NJXlrivv5eimPRr0OeHeuHicOYfan/C+i2THWgwp2EWCVhwAhOWT25wRR/4IO5J1MAUV4qD358+rAqpZlElk9BepXekZnX8lLuA+cEUZmiNbjh4m5+QF6JbelsG+b9wo6ROdvyjiiW1hQmyKthJAIIb6wO3FQC4bG4MK/yn6vx1YTXPn7EpyVAgMBAAECggEAR7YQ+kfqLtVThnj2mwLyCtZmndTjZEWhPZrtQmcpsmS5vT7i3+0xZ1qc7cD/3y9j+6u+bvSFmlDondd4/kh85P2X7joLlM9/GNufV9WC7YIhZdAi7i9ooxI2HMc6MtGRiWF0J0B87folwRYrQlF6epv/goh1cQ3FIJ7kxMYzSk0gF0JcmOZn3KH8tMt3t/GK+uVUIycuEQQKsaTTq45nIM7oqhlAwD/M+IO2pGFkLXJ23FzFACI10qBdpn+xL2xFGRO6EE8EAeDslT4OvvN3/vtnSnRNn8CJqfoEG40XO0xrZzH1noI35iPWX1WrN7qFLAhl2oLhu1ZSIA1tz0+I/QKBgQD3X/islXfVmV2XeuHvaf4qcMAdrgLQwtmLlHhFxfFURPh6au8uatDgUA8HWcRACmhtTruytlFRGKKFwZxuQE/LOZh67Uts3GTs5eHN8xvZTL+en+n7B/cCRYrrg3+yAM/k0eezIlk65iW700o+icEHxkwTXhhVBmIROBzpXsVCwwKBgQDfS6kVhgZxLMQePbXUQ1NBr2KbfhXLzceINhsoyWLa1rIk8+9HLSxw8q0zma12Jqkd22OAgkbeLDy+niYPi3pUrWAm8O59Ot1aaOarxMTvEv7+eS+urKId57sli/hQTWsS+xghA4+VfW2+EY++pYyZIp+j+1/Q2ciXWVJy4iv9xwKBgFzW8+kxn2vWxz1WrPzBdtZOwothB0V6G1M7QXhONag+ylKHV4TAKexFn55Onky6mz6K0f7cVeBtsnEonKD0Gf5Xe1aHQEt225ndHMXCe60uFKxfr9y6vIVpvB1vmLkhfOSPsrmUJpDoVzkKr06RPJTCY0LRiag/YQa9XHxpSPcpAoGAKbsiJnudyJjtLhmqWbkbXjNA4n515FjY6YPzH3RDnVJyiKVuGoc+vv0bkYEvAd3HzWSq++FdDTiHQbictFsEyb59McnlSFIv/C2Orptfkq6iKTzMxIBO6/fa6fF2vss5L5rtr33S38VJNTRjAOY/mH74BtV72rRY4LA40G+keRECgYEAiGg0DYxcSGf2bEP1WESYPTTdgS5ke1niIwZ00SgtkIjPSVgTCmf4Tciys6lGSe/Oqnvk24VR6pz07wzcbH92AURVaeqiEvVuVonzA6Yl0jxeOIM31S1BSBJRT8kDijuvwoJu2tPoZG0306KF9L8pyy1Z6cTTmIfGR0NpZCHWPSg=
\ No newline at end of file
license/src/main/resources/mapper/SysOperLogMapper.xml
View file @
8746029d
...
@@ -5,7 +5,7 @@
...
@@ -5,7 +5,7 @@
insert into sys_oper_log(title, business_type, uri, status, opt_param, error_msg, oper_time) values (#{title},#{businessType},#{uri},#{status},#{optParam},#{errorMsg},#{operTime})
insert into sys_oper_log(title, business_type, uri, status, opt_param, error_msg, oper_time) values (#{title},#{businessType},#{uri},#{status},#{optParam},#{errorMsg},#{operTime})
</insert>
</insert>
<select
id=
"getOperLogList"
resultType=
"iot.sixiang.license.
entity.SysOperLog
"
>
<select
id=
"getOperLogList"
resultType=
"iot.sixiang.license.
model.vo.SysOperLogVo
"
>
select id, title, business_type, uri, status,
opt_param, error_msg, oper_time from sys_oper_log
select id, title, business_type, uri, status,
error_msg, oper_time from sys_oper_log order by oper_time desc
</select>
</select>
</mapper>
</mapper>
license/src/main/resources/mapper/UserMapper.xml
View file @
8746029d
...
@@ -27,7 +27,11 @@
...
@@ -27,7 +27,11 @@
</select>
</select>
<select
id=
"getUserByUserName"
resultType=
"iot.sixiang.license.entity.User"
>
<select
id=
"getUserByUserName"
resultType=
"iot.sixiang.license.entity.User"
>
select user_id from user where user_name = #{userName}
select * from user where user_name = #{userName}
</select>
<select
id=
"getUserById"
resultType=
"iot.sixiang.license.entity.User"
>
select * from user where user_id = #{userId}
</select>
</select>
</mapper>
</mapper>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment