Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
X
xyqb-user2
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
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
head_group
xyqb-user2
Commits
ef595f7e
Commit
ef595f7e
authored
May 03, 2017
by
minminyan
Browse files
Options
Browse Files
Download
Plain Diff
合并代码
parents
8f6896b9
4c3b3444
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
840 additions
and
695 deletions
+840
-695
AppController.java
...antgroup/xyqb/controller/external/user/AppController.java
+6
-0
InnerController.java
...tgroup/xyqb/controller/external/user/InnerController.java
+29
-3
UserController.java
...ntgroup/xyqb/controller/internal/user/UserController.java
+416
-413
IUserRepository.java
...n/java/cn/quantgroup/xyqb/repository/IUserRepository.java
+2
-1
ISessionService.java
...a/cn/quantgroup/xyqb/service/session/ISessionService.java
+11
-8
SessionServiceImpl.java
...ntgroup/xyqb/service/session/impl/SessionServiceImpl.java
+121
-111
IUserDetailService.java
...a/cn/quantgroup/xyqb/service/user/IUserDetailService.java
+6
-5
UserDetailServiceImpl.java
...ntgroup/xyqb/service/user/impl/UserDetailServiceImpl.java
+75
-41
UserServiceImpl.java
...cn/quantgroup/xyqb/service/user/impl/UserServiceImpl.java
+115
-113
UserDetailVO.java
...java/cn/quantgroup/xyqb/service/user/vo/UserDetailVO.java
+59
-0
No files found.
src/main/java/cn/quantgroup/xyqb/controller/external/user/AppController.java
View file @
ef595f7e
...
...
@@ -86,6 +86,9 @@ public class AppController implements IBaseController {
if
(
user
==
null
)
{
return
JsonResult
.
buildErrorStateResult
(
USER_ERROR_OR_PASSWORD_ERROR
,
null
);
}
if
(!
user
.
getEnable
())
{
return
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
);
}
Merchant
merchant
=
merchantService
.
findMerchantByName
(
key
);
if
(
merchant
==
null
)
{
return
JsonResult
.
buildErrorStateResult
(
"无效的商户"
,
null
);
...
...
@@ -126,6 +129,9 @@ public class AppController implements IBaseController {
if
(
user
==
null
)
{
return
JsonResult
.
buildErrorStateResult
(
USER_ERROR_OR_PASSWORD_ERROR
,
null
);
}
if
(!
user
.
getEnable
())
{
return
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
);
}
Merchant
merchant
=
merchantService
.
findMerchantByName
(
key
);
if
(
merchant
==
null
)
{
return
JsonResult
.
buildErrorStateResult
(
"无效的商户"
,
null
);
...
...
src/main/java/cn/quantgroup/xyqb/controller/external/user/InnerController.java
View file @
ef595f7e
...
...
@@ -4,15 +4,17 @@ import cn.quantgroup.xyqb.entity.*;
import
cn.quantgroup.xyqb.entity.enumerate.*
;
import
cn.quantgroup.xyqb.model.*
;
import
cn.quantgroup.xyqb.service.auth.IIdCardService
;
import
cn.quantgroup.xyqb.service.session.ISessionService
;
import
cn.quantgroup.xyqb.service.user.*
;
import
cn.quantgroup.xyqb.service.user.vo.UserDetailVO
;
import
cn.quantgroup.xyqb.service.wechat.IWechatService
;
import
cn.quantgroup.xyqb.util.ValidationUtil
;
import
com.alibaba.fastjson.JSONObject
;
import
com.alibaba.fastjson.TypeReference
;
import
org.apache.commons.collections.CollectionUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.bind.annotation.RestController
;
...
...
@@ -47,7 +49,8 @@ public class InnerController {
private
IWechatService
wechatService
;
@Autowired
private
IUserSpouseService
userSpouseService
;
@Autowired
private
ISessionService
sessionService
;
@RequestMapping
(
"/user/search/phoneNo"
)
public
JsonResult
findByPhoneNo
(
String
phoneNo
)
{
...
...
@@ -102,6 +105,7 @@ public class InnerController {
user
.
setUpdatedAt
(
new
Timestamp
(
updatedAt
));
user
.
setEnable
(
true
);
user
.
setRegisteredFrom
(
registeredFrom
);
user
.
setUuid
(
uuid
);
user
.
setPassword
(
password
);
user
=
userService
.
saveUser
(
user
);
UserRet
userRet
=
null
;
...
...
@@ -333,7 +337,10 @@ public class InnerController {
@RequestMapping
(
"/user_detail/search_list"
)
public
JsonResult
searchUserDetailList
(
String
name
,
String
phoneNo
,
String
idNo
)
{
List
<
UserDetail
>
userDetails
=
userDetailService
.
searchUserDetailList
(
name
,
phoneNo
,
idNo
);
if
(
StringUtils
.
isBlank
(
name
)
&&
StringUtils
.
isBlank
(
phoneNo
)
&&
StringUtils
.
isBlank
(
idNo
))
{
return
JsonResult
.
buildErrorStateResult
(
"至少必须满足一个条件不为空"
,
null
);
}
List
<
UserDetailVO
>
userDetails
=
userDetailService
.
searchUserDetailList
(
name
,
phoneNo
,
idNo
);
return
JsonResult
.
buildSuccessResult
(
"success"
,
userDetails
);
}
...
...
@@ -373,6 +380,25 @@ public class InnerController {
return
JsonResult
.
buildSuccessResult
(
null
,
null
==
wechatUserInfo
?
null
:
wechatUserInfo
.
getOpenId
());
}
@RequestMapping
(
"/user/disable"
)
public
JsonResult
disableUser
(
Long
userId
)
{
if
(
null
==
userId
||
0L
==
userId
)
{
return
JsonResult
.
buildErrorStateResult
(
"userId不能为空"
,
null
);
}
User
user
=
userService
.
findById
(
userId
);
if
(
null
==
user
)
{
return
JsonResult
.
buildErrorStateResult
(
"未查询到该用户,用户id:"
+
userId
,
null
);
}
user
.
setEnable
(
false
);
user
.
setUpdatedAt
(
new
Timestamp
(
System
.
currentTimeMillis
()));
LOGGER
.
info
(
"注销用户的信息,userId={}"
,
userId
);
user
=
userService
.
saveUser
(
user
);
if
(!
user
.
getEnable
())
{
sessionService
.
deleteByUserId
(
userId
);
}
return
JsonResult
.
buildSuccessResult
(
"用户已禁用."
,
user
.
getEnable
()
==
false
);
}
@RequestMapping
(
"/user/spouse/save"
)
public
JsonResult
saveSpouse
(
Long
userId
,
MaritalStatus
status
,
String
spousePhone
,
String
spouseName
)
{
if
(
userId
==
null
||
userId
==
0
)
{
...
...
src/main/java/cn/quantgroup/xyqb/controller/internal/user/UserController.java
View file @
ef595f7e
...
...
@@ -106,6 +106,9 @@ public class UserController implements IBaseController {
JsonResult
successResult
=
validMap
.
get
(
"success"
);
String
phoneNo
=
successResult
.
getData
().
toString
();
User
user
=
userService
.
findByPhoneWithCache
(
phoneNo
);
if
(
user
!=
null
&&
!
user
.
getEnable
())
{
return
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
);
}
if
(
user
==
null
)
{
user
=
registerFastWhenLogin
(
phoneNo
,
channelId
,
createdFrom
,
appChannel
);
if
(
user
==
null
)
{
...
...
@@ -403,7 +406,7 @@ public class UserController implements IBaseController {
String
userName
=
credentialArr
[
0
];
String
pass
=
credentialArr
[
1
];
User
user
=
userService
.
findByPhoneWithCache
(
userName
);
if
(
user
==
null
)
{
if
(
user
==
null
||
!
user
.
getEnable
()
)
{
return
null
;
}
//验证密码
...
...
@@ -421,7 +424,7 @@ public class UserController implements IBaseController {
//查询用户,存在则保存用户session信息,userId为uuid
User
user
=
userService
.
findByUuidInDb
(
userId
);
//用户信息存在,更新session中的最后访问时间,重新写入缓存.
if
(
null
!=
user
)
{
if
(
null
!=
user
||
!
user
.
getEnable
()
)
{
return
new
JsonResult
(
sessionService
.
createSession
(
channelId
,
createdFrom
,
appChannel
,
user
,
merchant
));
}
else
{
return
JsonResult
.
buildErrorStateResult
(
"登录失败"
,
null
);
...
...
src/main/java/cn/quantgroup/xyqb/repository/IUserRepository.java
View file @
ef595f7e
...
...
@@ -2,11 +2,12 @@ package cn.quantgroup.xyqb.repository;
import
cn.quantgroup.xyqb.entity.User
;
import
org.springframework.data.jpa.repository.JpaRepository
;
import
org.springframework.data.jpa.repository.JpaSpecificationExecutor
;
/**
* Created by Miraculous on 15/7/4.
*/
public
interface
IUserRepository
extends
JpaRepository
<
User
,
Long
>
{
public
interface
IUserRepository
extends
JpaRepository
<
User
,
Long
>
,
JpaSpecificationExecutor
<
User
>
{
User
findByPhoneNo
(
String
phoneNo
);
...
...
src/main/java/cn/quantgroup/xyqb/service/session/ISessionService.java
View file @
ef595f7e
...
...
@@ -2,7 +2,6 @@ package cn.quantgroup.xyqb.service.session;
import
cn.quantgroup.xyqb.entity.Merchant
;
import
cn.quantgroup.xyqb.entity.User
;
import
cn.quantgroup.xyqb.function.OneArgFunction
;
import
cn.quantgroup.xyqb.model.AuthBean
;
import
cn.quantgroup.xyqb.model.LoginProperties
;
import
cn.quantgroup.xyqb.model.session.SessionStruct
;
...
...
@@ -21,8 +20,12 @@ public interface ISessionService {
String
findSessionIdByUserIdLoginProperties
(
Long
userId
,
LoginProperties
properties
);
String
findSessionValueBySessionId
(
String
sessionId
);
SessionStruct
newSession
(
User
user
,
LoginProperties
properties
);
void
persistSession
(
String
token
,
SessionValue
sessionValue
);
SessionStruct
findSessionBySessionId
(
String
sessionId
);
void
deleteByUserId
(
long
userId
);
}
src/main/java/cn/quantgroup/xyqb/service/session/impl/SessionServiceImpl.java
View file @
ef595f7e
...
...
@@ -3,34 +3,34 @@ package cn.quantgroup.xyqb.service.session.impl;
import
cn.quantgroup.xyqb.Constants
;
import
cn.quantgroup.xyqb.entity.Merchant
;
import
cn.quantgroup.xyqb.entity.User
;
import
cn.quantgroup.xyqb.function.OneArgFunction
;
import
cn.quantgroup.xyqb.model.AuthBean
;
import
cn.quantgroup.xyqb.model.JsonResult
;
import
cn.quantgroup.xyqb.model.LoginProperties
;
import
cn.quantgroup.xyqb.model.session.SessionStruct
;
import
cn.quantgroup.xyqb.model.session.SessionValue
;
import
cn.quantgroup.xyqb.service.session.ISessionService
;
import
com.alibaba.fastjson.JSON
;
import
com.google.common.base.Joiner
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Qualifier
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.CollectionUtils
;
import
java.sql.Timestamp
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.UUID
;
import
java.util.concurrent.TimeUnit
;
/**
*
* Created by 11 on 2016/12/28.
*/
@Slf4j
@Service
public
class
SessionServiceImpl
implements
ISessionService
{
public
class
SessionServiceImpl
implements
ISessionService
{
@Autowired
@Qualifier
(
"stringRedisTemplate"
)
...
...
@@ -47,7 +47,7 @@ public class SessionServiceImpl implements ISessionService{
//找到用户
String
sessionId
=
findSessionIdByUserIdLoginProperties
(
user
.
getId
(),
properties
);
// String sessionId = sessionService.findSessionIdByUserIdAndMerchant(user.getId(), merchant);
if
(
org
.
apache
.
commons
.
lang
.
StringUtils
.
isNotEmpty
(
sessionId
))
{
if
(
org
.
apache
.
commons
.
lang
.
StringUtils
.
isNotEmpty
(
sessionId
))
{
SessionStruct
sessionStruct
=
findSessionBySessionId
(
sessionId
);
sessionStruct
.
setAttribute
(
"channelId"
,
String
.
valueOf
(
channelId
));
sessionStruct
.
setAttribute
(
"createdFrom"
,
String
.
valueOf
(
createdFrom
));
...
...
@@ -99,13 +99,13 @@ public class SessionServiceImpl implements ISessionService{
}
@Override
public
String
findSessionValueBySessionId
(
String
sessionId
)
{
public
String
findSessionValueBySessionId
(
String
sessionId
)
{
String
result
=
stringRedisTemplate
.
opsForValue
().
get
(
Constants
.
Session
.
USER_SESSION_CACHE
+
sessionId
);
return
StringUtils
.
defaultString
(
result
,
""
);
}
@Override
public
SessionStruct
newSession
(
User
user
,
LoginProperties
loginProperties
)
{
public
SessionStruct
newSession
(
User
user
,
LoginProperties
loginProperties
)
{
Timestamp
now
=
new
Timestamp
(
System
.
currentTimeMillis
());
SessionStruct
sessionStruct
=
new
SessionStruct
();
SessionValue
sessionValue
=
new
SessionValue
();
...
...
@@ -134,7 +134,7 @@ public class SessionServiceImpl implements ISessionService{
@Override
public
SessionStruct
findSessionBySessionId
(
String
sessionId
)
{
String
sessionValue
=
findSessionValueBySessionId
(
sessionId
);
if
(
StringUtils
.
isEmpty
(
sessionValue
))
{
if
(
StringUtils
.
isEmpty
(
sessionValue
))
{
return
null
;
}
try
{
...
...
@@ -152,5 +152,15 @@ public class SessionServiceImpl implements ISessionService{
}
@Override
public
void
deleteByUserId
(
long
userId
)
{
String
pattern
=
Constants
.
Session
.
USER_SESSION_ID_CACHE
+
":"
+
String
.
valueOf
(
userId
)
+
":*"
;
Set
<
String
>
keys
=
stringRedisTemplate
.
keys
(
pattern
);
if
(!
CollectionUtils
.
isEmpty
(
keys
))
{
log
.
info
(
"删除用户userId={}的缓存信息,个数:{},keys={}"
,
userId
,
keys
.
size
(),
Joiner
.
on
(
","
).
join
(
keys
));
}
stringRedisTemplate
.
delete
(
keys
);
}
}
src/main/java/cn/quantgroup/xyqb/service/user/IUserDetailService.java
View file @
ef595f7e
package
cn
.
quantgroup
.
xyqb
.
service
.
user
;
import
cn.quantgroup.xyqb.entity.UserDetail
;
import
cn.quantgroup.xyqb.service.user.vo.UserDetailVO
;
import
org.springframework.dao.DataIntegrityViolationException
;
import
java.util.List
;
...
...
@@ -17,5 +18,5 @@ public interface IUserDetailService {
void
updateUserQQ
(
Long
userId
,
String
qq
);
List
<
UserDetail
>
searchUserDetailList
(
String
name
,
String
phoneNo
,
String
idNo
);
List
<
UserDetailVO
>
searchUserDetailList
(
String
name
,
String
phoneNo
,
String
idNo
);
}
src/main/java/cn/quantgroup/xyqb/service/user/impl/UserDetailServiceImpl.java
View file @
ef595f7e
package
cn
.
quantgroup
.
xyqb
.
service
.
user
.
impl
;
import
cn.quantgroup.xyqb.entity.User
;
import
cn.quantgroup.xyqb.entity.UserDetail
;
import
cn.quantgroup.xyqb.repository.IUserDetailRepository
;
import
cn.quantgroup.xyqb.repository.IUserRepository
;
import
cn.quantgroup.xyqb.service.user.IUserDetailService
;
import
cn.quantgroup.xyqb.service.user.vo.UserDetailVO
;
import
com.google.common.collect.Maps
;
import
org.apache.commons.lang.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.dao.DataIntegrityViolationException
;
import
org.springframework.data.jpa.domain.Specification
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.CollectionUtils
;
import
javax.persistence.criteria.*
;
import
javax.persistence.criteria.CriteriaBuilder
;
import
javax.persistence.criteria.CriteriaQuery
;
import
javax.persistence.criteria.Predicate
;
import
javax.persistence.criteria.Root
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
/**
* Created by 11 on 2016/12/29.
...
...
@@ -21,6 +31,8 @@ public class UserDetailServiceImpl implements IUserDetailService {
@Autowired
private
IUserDetailRepository
userDetailRepository
;
@Autowired
private
IUserRepository
userRepository
;
@Override
public
UserDetail
findByUserId
(
Long
userId
)
{
...
...
@@ -43,8 +55,21 @@ public class UserDetailServiceImpl implements IUserDetailService {
}
@Override
public
List
<
UserDetail
>
searchUserDetailList
(
String
name
,
String
phoneNo
,
String
idNo
)
{
return
userDetailRepository
.
findAll
(
getSpecification
(
name
,
phoneNo
,
idNo
));
public
List
<
UserDetailVO
>
searchUserDetailList
(
String
name
,
String
phoneNo
,
String
idNo
)
{
// return
List
<
UserDetail
>
details
=
userDetailRepository
.
findAll
(
getSpecification
(
name
,
phoneNo
,
idNo
));
Map
<
Long
,
User
>
userMap
=
Maps
.
newHashMap
();
if
(!
CollectionUtils
.
isEmpty
(
details
))
{
List
<
Long
>
userIds
=
details
.
stream
().
map
(
d
->
d
.
getUserId
()).
collect
(
Collectors
.
toList
());
List
<
User
>
users
=
userRepository
.
findAll
((
root
,
query
,
cb
)
->
{
query
.
where
(
root
.
get
(
"id"
).
in
(
userIds
));
return
query
.
getRestriction
();
});
userMap
=
users
.
stream
().
collect
(
Collectors
.
toMap
(
User:
:
getId
,
o
->
o
));
}
Map
<
Long
,
User
>
finalUserMap
=
userMap
;
List
<
UserDetailVO
>
userDetailVOS
=
details
.
stream
().
map
(
o
->
fromUserDetailAndUserMap
(
o
,
finalUserMap
)).
collect
(
Collectors
.
toList
());
return
userDetailVOS
;
}
private
Specification
<
UserDetail
>
getSpecification
(
String
name
,
String
phoneNo
,
String
idNo
)
{
...
...
@@ -67,4 +92,13 @@ public class UserDetailServiceImpl implements IUserDetailService {
};
return
specification
;
}
private
UserDetailVO
fromUserDetailAndUserMap
(
UserDetail
userDetail
,
Map
<
Long
,
User
>
userMap
)
{
UserDetailVO
userDetailVO
=
UserDetailVO
.
fromUserDetail
(
userDetail
);
User
user
=
userMap
.
get
(
userDetail
.
getUserId
());
if
(
user
!=
null
)
{
userDetailVO
.
setEnable
(
user
.
getEnable
());
}
return
userDetailVO
;
}
}
src/main/java/cn/quantgroup/xyqb/service/user/impl/UserServiceImpl.java
View file @
ef595f7e
...
...
@@ -47,6 +47,7 @@ public class UserServiceImpl implements IUserService {
}
@Override
@CacheEvict
(
value
=
"usercache"
,
key
=
"'xyqbuser' + #user.phoneNo"
,
cacheManager
=
"cacheManager"
)
public
User
saveUser
(
User
user
)
{
return
userRepository
.
save
(
user
);
}
...
...
@@ -101,7 +102,7 @@ public class UserServiceImpl implements IUserService {
user
.
setUuid
(
uuid
);
user
.
setPassword
(
PasswordUtil
.
MD5
(
password
.
toLowerCase
()
+
Constants
.
PASSWORD_SALT
));
//解决线上白条registerFrom为1的问题
if
(
channelId
==
222L
)
{
if
(
channelId
==
222L
)
{
user
.
setRegisteredFrom
(
channelId
);
}
else
{
user
.
setRegisteredFrom
(
registerFrom
);
...
...
@@ -120,10 +121,11 @@ public class UserServiceImpl implements IUserService {
/**
* 修改用户密码
* @date 2017-02-15 修改用户修改密码时,更新updatedAt时间
*
* @param phoneNo
* @param password
* @return
* @date 2017-02-15 修改用户修改密码时,更新updatedAt时间
*/
@Override
@CacheEvict
(
value
=
"usercache"
,
key
=
"'xyqbuser' + #phone"
,
cacheManager
=
"cacheManager"
)
...
...
src/main/java/cn/quantgroup/xyqb/service/user/vo/UserDetailVO.java
0 → 100644
View file @
ef595f7e
package
cn
.
quantgroup
.
xyqb
.
service
.
user
.
vo
;
import
cn.quantgroup.xyqb.entity.UserDetail
;
import
cn.quantgroup.xyqb.model.Gender
;
import
cn.quantgroup.xyqb.model.IdType
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
@Data
@NoArgsConstructor
public
class
UserDetailVO
{
private
Long
id
;
private
Long
userId
;
private
String
phoneNo
;
private
String
name
;
private
String
idNo
;
private
IdType
idType
;
private
Boolean
isAuthenticated
=
false
;
private
Gender
gender
;
private
String
email
;
private
String
qq
;
private
Boolean
enable
;
private
Long
createdAt
;
private
Long
updatedAt
;
public
static
UserDetailVO
fromUserDetail
(
UserDetail
userDetail
)
{
UserDetailVO
userDetailVO
=
new
UserDetailVO
();
userDetailVO
.
id
=
userDetail
.
getId
();
userDetailVO
.
userId
=
userDetail
.
getUserId
();
userDetailVO
.
phoneNo
=
userDetail
.
getPhoneNo
();
userDetailVO
.
name
=
userDetail
.
getName
();
userDetailVO
.
idNo
=
userDetail
.
getIdNo
();
userDetailVO
.
idType
=
userDetail
.
getIdType
();
userDetailVO
.
isAuthenticated
=
userDetail
.
getIsAuthenticated
();
userDetailVO
.
gender
=
userDetail
.
getGender
();
userDetailVO
.
email
=
userDetail
.
getEmail
();
userDetailVO
.
qq
=
userDetail
.
getQq
();
if
(
userDetail
.
getCreatedAt
()
!=
null
)
{
userDetailVO
.
createdAt
=
userDetail
.
getCreatedAt
().
getTime
();
}
if
(
userDetail
.
getUpdatedAt
()
!=
null
)
{
userDetailVO
.
updatedAt
=
userDetail
.
getUpdatedAt
().
getTime
();
}
return
userDetailVO
;
}
}
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