Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
solo-1
Project overview
Project overview
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
Administrator
solo-1
Commits
f271af1b
Commit
f271af1b
authored
Apr 02, 2013
by
Liang Ding
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
注册用户加入 URL 字段
暂时没有加入升级程序,所以需要重新初始化开发库。
parent
dcc31bcc
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1097 additions
and
1032 deletions
+1097
-1032
core/src/main/java/org/b3log/solo/processor/UpgradeProcessor.java
.../main/java/org/b3log/solo/processor/UpgradeProcessor.java
+1
-0
core/src/main/java/org/b3log/solo/processor/console/UserConsole.java
...in/java/org/b3log/solo/processor/console/UserConsole.java
+429
-426
core/src/main/java/org/b3log/solo/service/InitService.java
core/src/main/java/org/b3log/solo/service/InitService.java
+1
-0
core/src/main/java/org/b3log/solo/service/UserMgmtService.java
...src/main/java/org/b3log/solo/service/UserMgmtService.java
+35
-5
core/src/main/java/org/b3log/solo/util/Comments.java
core/src/main/java/org/b3log/solo/util/Comments.java
+355
-362
core/src/main/resources/repository.json
core/src/main/resources/repository.json
+6
-1
core/src/test/java/org/b3log/solo/repository/impl/UserRepositoryImplTestCase.java
...3log/solo/repository/impl/UserRepositoryImplTestCase.java
+101
-99
war/src/main/resources/lang_en_US.properties
war/src/main/resources/lang_en_US.properties
+3
-1
war/src/main/resources/lang_zh_CN.properties
war/src/main/resources/lang_zh_CN.properties
+3
-1
war/src/main/webapp/admin-user-list.ftl
war/src/main/webapp/admin-user-list.ftl
+102
-86
war/src/main/webapp/js/admin/userList.js
war/src/main/webapp/js/admin/userList.js
+5
-0
war/src/main/webapp/register.ftl
war/src/main/webapp/register.ftl
+56
-51
No files found.
core/src/main/java/org/b3log/solo/processor/UpgradeProcessor.java
View file @
f271af1b
...
...
@@ -60,6 +60,7 @@ import org.json.JSONObject;
@RequestProcessor
// TODO: 060
// 1. Add column Preference.feedOutputCnt
// 2. Add column User.userURL
public
final
class
UpgradeProcessor
{
/**
...
...
core/src/main/java/org/b3log/solo/processor/console/UserConsole.java
View file @
f271af1b
/*
* Copyright (c) 2009, 2010, 2011, 2012, 2013, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
b3log
.
solo
.
processor
.
console
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.b3log.latke.Keys
;
import
org.b3log.latke.Latkes
;
import
org.b3log.latke.model.Role
;
import
org.b3log.latke.model.User
;
import
org.b3log.latke.service.LangPropsService
;
import
org.b3log.latke.service.ServiceException
;
import
org.b3log.latke.servlet.HTTPRequestContext
;
import
org.b3log.latke.servlet.HTTPRequestMethod
;
import
org.b3log.latke.servlet.annotation.RequestProcessing
;
import
org.b3log.latke.servlet.annotation.RequestProcessor
;
import
org.b3log.latke.servlet.renderer.JSONRenderer
;
import
org.b3log.latke.util.Requests
;
import
org.b3log.solo.service.UserMgmtService
;
import
org.b3log.solo.service.UserQueryService
;
import
org.b3log.solo.util.QueryResults
;
import
org.b3log.solo.util.Users
;
import
org.json.JSONObject
;
/**
* User console request processing.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @author <a href="mailto:385321165@qq.com">DASHU</a>
* @version 1.0.0.3, Mar 30, 2013
* @since 0.4.0
*/
@RequestProcessor
public
final
class
UserConsole
{
/**
* Logger.
*/
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
UserConsole
.
class
.
getName
());
/**
* User query service.
*/
private
UserQueryService
userQueryService
=
UserQueryService
.
getInstance
();
/**
* User management service.
*/
private
UserMgmtService
userMgmtService
=
UserMgmtService
.
getInstance
();
/**
* User utilities.
*/
private
Users
userUtils
=
Users
.
getInstance
();
/**
* Language service.
*/
private
LangPropsService
langPropsService
=
LangPropsService
.
getInstance
();
/**
* Updates a user by the specified request.
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "msg": ""
* }
* </pre>
* </p>
*
* @param request the specified http servlet request, for example,
* <pre>
* {
* "oId": "",
* "userName": "",
* "userEmail": "",
* "userPassword": "",
* "userRole": ""
* }
* </pre>
* @param context the specified http request context
* @param response the specified http servlet response
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/user/"
,
method
=
HTTPRequestMethod
.
PUT
)
public
void
updateUser
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
if
(!
userUtils
.
isAdminLoggedIn
(
request
))
{
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
);
return
;
}
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
final
JSONObject
ret
=
new
JSONObject
();
try
{
final
JSONObject
requestJSONObject
=
Requests
.
parseRequestJSONObject
(
request
,
response
);
userMgmtService
.
updateUser
(
requestJSONObject
);
ret
.
put
(
Keys
.
STATUS_CODE
,
true
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"updateSuccLabel"
));
renderer
.
setJSONObject
(
ret
);
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
final
JSONObject
jsonObject
=
QueryResults
.
defaultResult
();
renderer
.
setJSONObject
(
jsonObject
);
jsonObject
.
put
(
Keys
.
MSG
,
e
.
getMessage
());
}
}
/**
* Adds a user with the specified request.
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "oId": "", // Generated user id
* "msg": ""
* }
* </pre>
* </p>
*
* @param request the specified http servlet request, for example,
* <pre>
* {
* "userName": "",
* "userEmail": "",
* "userPassword": "",
* "userRole": "" // optional, uses {@value org.b3log.latke.model.Role#DEFAULT_ROLE} instead,
* if not speciffied
* }
* </pre>
* @param response the specified http servlet response
* @param context the specified http request context
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/user/"
,
method
=
HTTPRequestMethod
.
POST
)
public
void
addUser
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
final
JSONObject
ret
=
new
JSONObject
();
try
{
final
JSONObject
requestJSONObject
=
Requests
.
parseRequestJSONObject
(
request
,
response
);
if
(
userUtils
.
isAdminLoggedIn
(
request
))
{
requestJSONObject
.
put
(
User
.
USER_ROLE
,
Role
.
DEFAULT_ROLE
);
}
else
{
requestJSONObject
.
put
(
User
.
USER_ROLE
,
Role
.
VISITOR_ROLE
);
}
final
String
userId
=
userMgmtService
.
addUser
(
requestJSONObject
);
ret
.
put
(
Keys
.
OBJECT_ID
,
userId
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"addSuccLabel"
));
ret
.
put
(
Keys
.
STATUS_CODE
,
true
);
renderer
.
setJSONObject
(
ret
);
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
final
JSONObject
jsonObject
=
QueryResults
.
defaultResult
();
renderer
.
setJSONObject
(
jsonObject
);
jsonObject
.
put
(
Keys
.
MSG
,
e
.
getMessage
());
}
}
/**
* Removes a user by the specified request.
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "msg": ""
* }
* </pre>
* </p>
*
* @param request the specified http servlet request
* @param response the specified http servlet response
* @param context the specified http request context
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/user/*"
,
method
=
HTTPRequestMethod
.
DELETE
)
public
void
removeUser
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
if
(!
userUtils
.
isAdminLoggedIn
(
request
))
{
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
);
return
;
}
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
final
JSONObject
jsonObject
=
new
JSONObject
();
renderer
.
setJSONObject
(
jsonObject
);
try
{
final
String
userId
=
request
.
getRequestURI
().
substring
((
Latkes
.
getContextPath
()
+
"/console/user/"
).
length
());
userMgmtService
.
removeUser
(
userId
);
jsonObject
.
put
(
Keys
.
STATUS_CODE
,
true
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"removeSuccLabel"
));
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
jsonObject
.
put
(
Keys
.
STATUS_CODE
,
false
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"removeFailLabel"
));
}
}
/**
* Gets users by the specified request json object.
* <p>
* The request URI contains the pagination arguments. For example, the
* request URI is /console/users/1/10/20, means the current page is 1, the
* page size is 10, and the window size is 20.
* </p>
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "pagination": {
* "paginationPageCount": 100,
* "paginationPageNums": [1, 2, 3, 4, 5]
* },
* "users": [{
* "oId": "",
* "userName": "",
* "userEmail": "",
* "userPassword": "",
* "roleName": ""
* }, ....]
* "sc": "GET_USERS_SUCC"
* }
* </pre>
* </p>
*
* @param request the specified http servlet request
* @param response the specified http servlet response
* @param context the specified http request context
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/users/*/*/*"
/* Requests.PAGINATION_PATH_PATTERN */
,
method
=
HTTPRequestMethod
.
GET
)
public
void
getUsers
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
if
(!
userUtils
.
isAdminLoggedIn
(
request
))
{
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
);
return
;
}
try
{
final
String
requestURI
=
request
.
getRequestURI
();
final
String
path
=
requestURI
.
substring
((
Latkes
.
getContextPath
()
+
"/console/users/"
).
length
());
final
JSONObject
requestJSONObject
=
Requests
.
buildPaginationRequest
(
path
);
final
JSONObject
result
=
userQueryService
.
getUsers
(
requestJSONObject
);
result
.
put
(
Keys
.
STATUS_CODE
,
true
);
renderer
.
setJSONObject
(
result
);
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
final
JSONObject
jsonObject
=
QueryResults
.
defaultResult
();
renderer
.
setJSONObject
(
jsonObject
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"getFailLabel"
));
}
}
/**
* Gets a user by the specified request.
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "user": {
* "oId": "",
* "userName": "",
* "userEmail": "",
* "userPassword": ""
* }
* }
* </pre>
* </p>
*
* @param request the specified http servlet request
* @param response the specified http servlet response
* @param context the specified http request context
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/user/*"
,
method
=
HTTPRequestMethod
.
GET
)
public
void
getUser
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
if
(!
userUtils
.
isAdminLoggedIn
(
request
))
{
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
);
return
;
}
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
try
{
final
String
requestURI
=
request
.
getRequestURI
();
final
String
userId
=
requestURI
.
substring
((
Latkes
.
getContextPath
()
+
"/console/user/"
).
length
());
final
JSONObject
result
=
userQueryService
.
getUser
(
userId
);
if
(
null
==
result
)
{
renderer
.
setJSONObject
(
QueryResults
.
defaultResult
());
return
;
}
renderer
.
setJSONObject
(
result
);
result
.
put
(
Keys
.
STATUS_CODE
,
true
);
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
final
JSONObject
jsonObject
=
QueryResults
.
defaultResult
();
renderer
.
setJSONObject
(
jsonObject
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"getFailLabel"
));
}
}
/**
* Change a user role.
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "msg": ""
* }
* </pre>
* </p>
*
* @param request the specified http servlet request
* @param response the specified http servlet response
* @param context the specified http request context
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/changeRole/*"
,
method
=
HTTPRequestMethod
.
GET
)
public
void
changeUserRole
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
if
(!
userUtils
.
isAdminLoggedIn
(
request
))
{
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
);
return
;
}
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
final
JSONObject
jsonObject
=
new
JSONObject
();
renderer
.
setJSONObject
(
jsonObject
);
try
{
final
String
userId
=
request
.
getRequestURI
().
substring
((
Latkes
.
getContextPath
()
+
"/console/changeRole/"
).
length
());
userMgmtService
.
changeRole
(
userId
);
jsonObject
.
put
(
Keys
.
STATUS_CODE
,
true
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"updateSuccLabel"
));
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
jsonObject
.
put
(
Keys
.
STATUS_CODE
,
false
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"removeFailLabel"
));
}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, 2013, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
b3log
.
solo
.
processor
.
console
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
org.b3log.latke.Keys
;
import
org.b3log.latke.Latkes
;
import
org.b3log.latke.model.Role
;
import
org.b3log.latke.model.User
;
import
org.b3log.latke.service.LangPropsService
;
import
org.b3log.latke.service.ServiceException
;
import
org.b3log.latke.servlet.HTTPRequestContext
;
import
org.b3log.latke.servlet.HTTPRequestMethod
;
import
org.b3log.latke.servlet.annotation.RequestProcessing
;
import
org.b3log.latke.servlet.annotation.RequestProcessor
;
import
org.b3log.latke.servlet.renderer.JSONRenderer
;
import
org.b3log.latke.util.Requests
;
import
org.b3log.solo.service.UserMgmtService
;
import
org.b3log.solo.service.UserQueryService
;
import
org.b3log.solo.util.QueryResults
;
import
org.b3log.solo.util.Users
;
import
org.json.JSONObject
;
/**
* User console request processing.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @author <a href="mailto:385321165@qq.com">DASHU</a>
* @version 1.0.0.4, Apr 2, 2013
* @since 0.4.0
*/
@RequestProcessor
public
final
class
UserConsole
{
/**
* Logger.
*/
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
UserConsole
.
class
.
getName
());
/**
* User query service.
*/
private
UserQueryService
userQueryService
=
UserQueryService
.
getInstance
();
/**
* User management service.
*/
private
UserMgmtService
userMgmtService
=
UserMgmtService
.
getInstance
();
/**
* User utilities.
*/
private
Users
userUtils
=
Users
.
getInstance
();
/**
* Language service.
*/
private
LangPropsService
langPropsService
=
LangPropsService
.
getInstance
();
/**
* Updates a user by the specified request.
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "msg": ""
* }
* </pre>
* </p>
*
* @param request the specified http servlet request, for example,
* <pre>
* {
* "oId": "",
* "userName": "",
* "userEmail": "",
* "userPassword": "", // Unhashed
* "userRole": "", // optional
* "userURL": "", // optional
* }
* </pre>
* @param context the specified http request context
* @param response the specified http servlet response
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/user/"
,
method
=
HTTPRequestMethod
.
PUT
)
public
void
updateUser
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
if
(!
userUtils
.
isAdminLoggedIn
(
request
))
{
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
);
return
;
}
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
final
JSONObject
ret
=
new
JSONObject
();
try
{
final
JSONObject
requestJSONObject
=
Requests
.
parseRequestJSONObject
(
request
,
response
);
userMgmtService
.
updateUser
(
requestJSONObject
);
ret
.
put
(
Keys
.
STATUS_CODE
,
true
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"updateSuccLabel"
));
renderer
.
setJSONObject
(
ret
);
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
final
JSONObject
jsonObject
=
QueryResults
.
defaultResult
();
renderer
.
setJSONObject
(
jsonObject
);
jsonObject
.
put
(
Keys
.
MSG
,
e
.
getMessage
());
}
}
/**
* Adds a user with the specified request.
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "oId": "", // Generated user id
* "msg": ""
* }
* </pre>
* </p>
*
* @param request the specified http servlet request, for example,
* <pre>
* {
* "userName": "",
* "userEmail": "",
* "userPassword": "",
* "userURL": "", // optional, uses 'servePath' instead if not specified
* "userRole": "" // optional, uses {@value org.b3log.latke.model.Role#DEFAULT_ROLE} instead if not speciffied
* }
* </pre>
* @param response the specified http servlet response
* @param context the specified http request context
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/user/"
,
method
=
HTTPRequestMethod
.
POST
)
public
void
addUser
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
final
JSONObject
ret
=
new
JSONObject
();
try
{
final
JSONObject
requestJSONObject
=
Requests
.
parseRequestJSONObject
(
request
,
response
);
if
(
userUtils
.
isAdminLoggedIn
(
request
))
{
// if the administrator register a new user, treats the new user as a normal user
// (defaultRole) who could post article
requestJSONObject
.
put
(
User
.
USER_ROLE
,
Role
.
DEFAULT_ROLE
);
}
else
{
// if a normal user or a visitor register a new user, treates the new user as a visitor (visitorRole) who couldn't
// post article
requestJSONObject
.
put
(
User
.
USER_ROLE
,
Role
.
VISITOR_ROLE
);
}
final
String
userId
=
userMgmtService
.
addUser
(
requestJSONObject
);
ret
.
put
(
Keys
.
OBJECT_ID
,
userId
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"addSuccLabel"
));
ret
.
put
(
Keys
.
STATUS_CODE
,
true
);
renderer
.
setJSONObject
(
ret
);
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
final
JSONObject
jsonObject
=
QueryResults
.
defaultResult
();
renderer
.
setJSONObject
(
jsonObject
);
jsonObject
.
put
(
Keys
.
MSG
,
e
.
getMessage
());
}
}
/**
* Removes a user by the specified request.
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "msg": ""
* }
* </pre>
* </p>
*
* @param request the specified http servlet request
* @param response the specified http servlet response
* @param context the specified http request context
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/user/*"
,
method
=
HTTPRequestMethod
.
DELETE
)
public
void
removeUser
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
if
(!
userUtils
.
isAdminLoggedIn
(
request
))
{
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
);
return
;
}
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
final
JSONObject
jsonObject
=
new
JSONObject
();
renderer
.
setJSONObject
(
jsonObject
);
try
{
final
String
userId
=
request
.
getRequestURI
().
substring
((
Latkes
.
getContextPath
()
+
"/console/user/"
).
length
());
userMgmtService
.
removeUser
(
userId
);
jsonObject
.
put
(
Keys
.
STATUS_CODE
,
true
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"removeSuccLabel"
));
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
jsonObject
.
put
(
Keys
.
STATUS_CODE
,
false
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"removeFailLabel"
));
}
}
/**
* Gets users by the specified request json object.
* <p>
* The request URI contains the pagination arguments. For example, the
* request URI is /console/users/1/10/20, means the current page is 1, the
* page size is 10, and the window size is 20.
* </p>
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "pagination": {
* "paginationPageCount": 100,
* "paginationPageNums": [1, 2, 3, 4, 5]
* },
* "users": [{
* "oId": "",
* "userName": "",
* "userEmail": "",
* "userPassword": "",
* "roleName": ""
* }, ....]
* "sc": "GET_USERS_SUCC"
* }
* </pre>
* </p>
*
* @param request the specified http servlet request
* @param response the specified http servlet response
* @param context the specified http request context
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/users/*/*/*"
/* Requests.PAGINATION_PATH_PATTERN */
,
method
=
HTTPRequestMethod
.
GET
)
public
void
getUsers
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
if
(!
userUtils
.
isAdminLoggedIn
(
request
))
{
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
);
return
;
}
try
{
final
String
requestURI
=
request
.
getRequestURI
();
final
String
path
=
requestURI
.
substring
((
Latkes
.
getContextPath
()
+
"/console/users/"
).
length
());
final
JSONObject
requestJSONObject
=
Requests
.
buildPaginationRequest
(
path
);
final
JSONObject
result
=
userQueryService
.
getUsers
(
requestJSONObject
);
result
.
put
(
Keys
.
STATUS_CODE
,
true
);
renderer
.
setJSONObject
(
result
);
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
final
JSONObject
jsonObject
=
QueryResults
.
defaultResult
();
renderer
.
setJSONObject
(
jsonObject
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"getFailLabel"
));
}
}
/**
* Gets a user by the specified request.
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "user": {
* "oId": "",
* "userName": "",
* "userEmail": "",
* "userPassword": ""
* }
* }
* </pre>
* </p>
*
* @param request the specified http servlet request
* @param response the specified http servlet response
* @param context the specified http request context
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/user/*"
,
method
=
HTTPRequestMethod
.
GET
)
public
void
getUser
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
if
(!
userUtils
.
isAdminLoggedIn
(
request
))
{
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
);
return
;
}
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
try
{
final
String
requestURI
=
request
.
getRequestURI
();
final
String
userId
=
requestURI
.
substring
((
Latkes
.
getContextPath
()
+
"/console/user/"
).
length
());
final
JSONObject
result
=
userQueryService
.
getUser
(
userId
);
if
(
null
==
result
)
{
renderer
.
setJSONObject
(
QueryResults
.
defaultResult
());
return
;
}
renderer
.
setJSONObject
(
result
);
result
.
put
(
Keys
.
STATUS_CODE
,
true
);
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
final
JSONObject
jsonObject
=
QueryResults
.
defaultResult
();
renderer
.
setJSONObject
(
jsonObject
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"getFailLabel"
));
}
}
/**
* Change a user role.
*
* <p>
* Renders the response with a json object, for example,
* <pre>
* {
* "sc": boolean,
* "msg": ""
* }
* </pre>
* </p>
*
* @param request the specified http servlet request
* @param response the specified http servlet response
* @param context the specified http request context
* @throws Exception exception
*/
@RequestProcessing
(
value
=
"/console/changeRole/*"
,
method
=
HTTPRequestMethod
.
GET
)
public
void
changeUserRole
(
final
HttpServletRequest
request
,
final
HttpServletResponse
response
,
final
HTTPRequestContext
context
)
throws
Exception
{
if
(!
userUtils
.
isAdminLoggedIn
(
request
))
{
response
.
sendError
(
HttpServletResponse
.
SC_FORBIDDEN
);
return
;
}
final
JSONRenderer
renderer
=
new
JSONRenderer
();
context
.
setRenderer
(
renderer
);
final
JSONObject
jsonObject
=
new
JSONObject
();
renderer
.
setJSONObject
(
jsonObject
);
try
{
final
String
userId
=
request
.
getRequestURI
().
substring
((
Latkes
.
getContextPath
()
+
"/console/changeRole/"
).
length
());
userMgmtService
.
changeRole
(
userId
);
jsonObject
.
put
(
Keys
.
STATUS_CODE
,
true
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"updateSuccLabel"
));
}
catch
(
final
ServiceException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
e
.
getMessage
(),
e
);
jsonObject
.
put
(
Keys
.
STATUS_CODE
,
false
);
jsonObject
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"removeFailLabel"
));
}
}
}
core/src/main/java/org/b3log/solo/service/InitService.java
View file @
f271af1b
...
...
@@ -437,6 +437,7 @@ public final class InitService {
admin
.
put
(
User
.
USER_NAME
,
requestJSONObject
.
getString
(
User
.
USER_NAME
));
admin
.
put
(
User
.
USER_EMAIL
,
requestJSONObject
.
getString
(
User
.
USER_EMAIL
));
admin
.
put
(
User
.
USER_URL
,
Latkes
.
getServePath
());
admin
.
put
(
User
.
USER_ROLE
,
Role
.
ADMIN_ROLE
);
admin
.
put
(
User
.
USER_PASSWORD
,
MD5
.
hash
(
requestJSONObject
.
getString
(
User
.
USER_PASSWORD
)));
admin
.
put
(
UserExt
.
USER_ARTICLE_COUNT
,
0
);
...
...
core/src/main/java/org/b3log/solo/service/UserMgmtService.java
View file @
f271af1b
...
...
@@ -19,6 +19,7 @@ package org.b3log.solo.service;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
org.b3log.latke.Keys
;
import
org.b3log.latke.Latkes
;
import
org.b3log.latke.model.Role
;
import
org.b3log.latke.model.User
;
import
org.b3log.latke.repository.RepositoryException
;
...
...
@@ -26,6 +27,7 @@ import org.b3log.latke.repository.Transaction;
import
org.b3log.latke.service.LangPropsService
;
import
org.b3log.latke.service.ServiceException
;
import
org.b3log.latke.util.MD5
;
import
org.b3log.latke.util.Strings
;
import
org.b3log.solo.model.UserExt
;
import
org.b3log.solo.repository.UserRepository
;
import
org.b3log.solo.repository.impl.UserRepositoryImpl
;
...
...
@@ -67,7 +69,8 @@ public final class UserMgmtService {
* "userName": "",
* "userEmail": "",
* "userPassword": "", // Unhashed
* "userRole": ""
* "userRole": "", // optional
* "userURL": "", // optional
* }
* </pre>
* @throws ServiceException service exception
...
...
@@ -99,8 +102,19 @@ public final class UserMgmtService {
oldUser
.
put
(
User
.
USER_EMAIL
,
userNewEmail
);
oldUser
.
put
(
User
.
USER_NAME
,
userName
);
oldUser
.
put
(
User
.
USER_PASSWORD
,
MD5
.
hash
(
userPassword
));
// Unchanges the default role
final
String
userRole
=
requestJSONObject
.
optString
(
User
.
USER_ROLE
);
if
(!
Strings
.
isEmptyOrNull
(
userRole
))
{
oldUser
.
put
(
User
.
USER_ROLE
,
userRole
);
}
final
String
userURL
=
requestJSONObject
.
optString
(
User
.
USER_URL
);
if
(!
Strings
.
isEmptyOrNull
(
userURL
))
{
oldUser
.
put
(
User
.
USER_URL
,
userURL
);
}
userRepository
.
update
(
oldUserId
,
oldUser
);
transaction
.
commit
();
}
catch
(
final
RepositoryException
e
)
{
...
...
@@ -159,8 +173,8 @@ public final class UserMgmtService {
* "userName": "",
* "userEmail": "",
* "userPassword": "", // Unhashed
* "user
Role": "" // optional, uses {@value Role#DEFAULT_ROLE} instead,
*
if not speciffied
* "user
URL": "", // optional, uses 'servePath' instead if not specified
*
"userRole": "" // optional, uses {@value Role#DEFAULT_ROLE} instead,
if not speciffied
* }
* </pre>,see {@link User} for more details
* @return generated user id
...
...
@@ -182,16 +196,32 @@ public final class UserMgmtService {
throw
new
ServiceException
(
langPropsService
.
get
(
"duplicatedEmailLabel"
));
}
user
.
put
(
User
.
USER_EMAIL
,
userEmail
);
final
String
userName
=
requestJSONObject
.
optString
(
User
.
USER_NAME
);
user
.
put
(
User
.
USER_EMAIL
,
userEmail
);
user
.
put
(
User
.
USER_NAME
,
userName
);
final
String
userPassword
=
requestJSONObject
.
optString
(
User
.
USER_PASSWORD
);
user
.
put
(
User
.
USER_PASSWORD
,
MD5
.
hash
(
userPassword
));
String
userURL
=
requestJSONObject
.
optString
(
User
.
USER_URL
);
if
(
Strings
.
isEmptyOrNull
(
userURL
))
{
userURL
=
Latkes
.
getServePath
();
}
if
(!
Strings
.
isURL
(
userURL
))
{
throw
new
ServiceException
(
langPropsService
.
get
(
"urlInvalidLabel"
));
}
user
.
put
(
User
.
USER_URL
,
userURL
);
final
String
roleName
=
requestJSONObject
.
optString
(
User
.
USER_ROLE
,
Role
.
DEFAULT_ROLE
);
user
.
put
(
User
.
USER_ROLE
,
roleName
);
user
.
put
(
UserExt
.
USER_ARTICLE_COUNT
,
0
);
user
.
put
(
UserExt
.
USER_PUBLISHED_ARTICLE_COUNT
,
0
);
...
...
core/src/main/java/org/b3log/solo/util/Comments.java
View file @
f271af1b
/*
* Copyright (c) 2009, 2010, 2011, 2012, 2013, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
b3log
.
solo
.
util
;
import
java.io.IOException
;
import
java.net.URL
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
org.b3log.latke.Keys
;
import
org.b3log.latke.mail.MailService
;
import
org.b3log.latke.mail.MailService.Message
;
import
org.b3log.latke.mail.MailServiceFactory
;
import
org.b3log.latke.service.LangPropsService
;
import
org.b3log.latke.util.Strings
;
import
org.b3log.solo.SoloServletListener
;
import
org.b3log.solo.model.*
;
import
org.b3log.solo.repository.ArticleRepository
;
import
org.b3log.solo.repository.PageRepository
;
import
org.b3log.solo.repository.impl.ArticleRepositoryImpl
;
import
org.b3log.solo.repository.impl.PageRepositoryImpl
;
import
org.b3log.solo.service.PreferenceQueryService
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
/**
* Comment utilities.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.9, Mar 28, 2012
* @since 0.3.1
*/
public
final
class
Comments
{
/**
* Logger.
*/
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
Comments
.
class
.
getName
());
/**
* Language service.
*/
private
static
LangPropsService
langPropsService
=
LangPropsService
.
getInstance
();
/**
* Preference query service.
*/
private
static
PreferenceQueryService
preferenceQueryService
=
PreferenceQueryService
.
getInstance
();
/**
* Article repository.
*/
private
static
ArticleRepository
articleRepository
=
ArticleRepositoryImpl
.
getInstance
();
/**
* Page repository.
*/
private
static
PageRepository
pageRepository
=
PageRepositoryImpl
.
getInstance
();
/**
* Mail service.
*/
private
static
final
MailService
MAIL_SVC
=
MailServiceFactory
.
getMailService
();
/**
* Minimum length of comment name.
*/
private
static
final
int
MIN_COMMENT_NAME_LENGTH
=
2
;
/**
* Maximum length of comment name.
*/
private
static
final
int
MAX_COMMENT_NAME_LENGTH
=
20
;
/**
* Minimum length of comment content.
*/
private
static
final
int
MIN_COMMENT_CONTENT_LENGTH
=
2
;
/**
* Maximum length of comment content.
*/
private
static
final
int
MAX_COMMENT_CONTENT_LENGTH
=
500
;
/**
* Comment mail HTML body.
*/
public
static
final
String
COMMENT_MAIL_HTML_BODY
=
"<p>{articleOrPage} [<a href=\""
+
"{articleOrPageURL}\">"
+
"{title}</a>]"
+
" received a new comment:</p>"
+
"{commenter}: <span><a href=\"http://{commentSharpURL}\">"
+
"{commentContent}</a></span>"
;
/**
* Gets comment sharp URL with the specified page and comment id.
*
* @param page the specified page
* @param commentId the specified comment id
* @return comment sharp URL
* @throws JSONException json exception
*/
public
static
String
getCommentSharpURLForPage
(
final
JSONObject
page
,
final
String
commentId
)
throws
JSONException
{
return
page
.
getString
(
Page
.
PAGE_PERMALINK
)
+
"#"
+
commentId
;
}
/**
* Gets comment sharp URL with the specified article and comment id.
*
* @param article the specified article
* @param commentId the specified comment id
* @return comment sharp URL
* @throws JSONException json exception
*/
public
static
String
getCommentSharpURLForArticle
(
final
JSONObject
article
,
final
String
commentId
)
throws
JSONException
{
final
String
articleLink
=
article
.
getString
(
Article
.
ARTICLE_PERMALINK
);
return
articleLink
+
"#"
+
commentId
;
}
/**
* Checks the specified comment adding request.
*
* @param requestJSONObject the specified comment adding request, for example,
* <pre>
* {
* "type": "", // "article"/"page"
* "oId": "",
* "commentName": "",
* "commentEmail": "",
* "commentURL": "",
* "commentContent": "",
* }
* </pre>
* @return check result, for example,
* <pre>
* {
* "sc": boolean,
* "msg": "" // Exists if "sc" equals to false
* }
* </pre>
*/
public
static
JSONObject
checkAddCommentRequest
(
final
JSONObject
requestJSONObject
)
{
final
JSONObject
ret
=
new
JSONObject
();
try
{
ret
.
put
(
Keys
.
STATUS_CODE
,
false
);
final
JSONObject
preference
=
preferenceQueryService
.
getPreference
();
if
(
null
==
preference
||
!
preference
.
optBoolean
(
Preference
.
COMMENTABLE
))
{
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"notAllowCommentLabel"
));
return
ret
;
}
final
String
id
=
requestJSONObject
.
optString
(
Keys
.
OBJECT_ID
);
final
String
type
=
requestJSONObject
.
optString
(
Common
.
TYPE
);
if
(
Article
.
ARTICLE
.
equals
(
type
))
{
final
JSONObject
article
=
articleRepository
.
get
(
id
);
if
(
null
==
article
||
!
article
.
optBoolean
(
Article
.
ARTICLE_COMMENTABLE
))
{
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"notAllowCommentLabel"
));
return
ret
;
}
}
else
{
final
JSONObject
page
=
pageRepository
.
get
(
id
);
if
(
null
==
page
||
!
page
.
optBoolean
(
Page
.
PAGE_COMMENTABLE
))
{
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"notAllowCommentLabel"
));
return
ret
;
}
}
final
String
commentName
=
requestJSONObject
.
getString
(
Comment
.
COMMENT_NAME
);
if
(
MAX_COMMENT_NAME_LENGTH
<
commentName
.
length
()
||
MIN_COMMENT_NAME_LENGTH
>
commentName
.
length
())
{
LOGGER
.
log
(
Level
.
WARNING
,
"Comment name is too long[{0}]"
,
commentName
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"nameTooLongLabel"
));
return
ret
;
}
final
String
commentEmail
=
requestJSONObject
.
getString
(
Comment
.
COMMENT_EMAIL
).
trim
().
toLowerCase
();
if
(!
Strings
.
isEmail
(
commentEmail
))
{
LOGGER
.
log
(
Level
.
WARNING
,
"Comment email is invalid[{0}]"
,
commentEmail
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"mailInvalidLabel"
));
return
ret
;
}
final
String
commentURL
=
requestJSONObject
.
optString
(
Comment
.
COMMENT_URL
);
try
{
new
URL
(
commentURL
);
if
(
commentURL
.
contains
(
"<"
)
||
commentURL
.
contains
(
">"
))
{
throw
new
IllegalArgumentException
();
}
}
catch
(
final
Exception
e
)
{
LOGGER
.
log
(
Level
.
WARNING
,
"Comment URL is invalid[{0}]"
,
commentURL
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"urlInvalidLabel"
));
return
ret
;
}
final
String
commentContent
=
requestJSONObject
.
optString
(
Comment
.
COMMENT_CONTENT
).
replaceAll
(
"\\n"
,
SoloServletListener
.
ENTER_ESC
);
if
(
MAX_COMMENT_CONTENT_LENGTH
<
commentContent
.
length
()
||
MIN_COMMENT_CONTENT_LENGTH
>
commentContent
.
length
())
{
LOGGER
.
log
(
Level
.
WARNING
,
"Comment conent length is invalid[{0}]"
,
commentContent
.
length
());
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"commentContentCannotEmptyLabel"
));
return
ret
;
}
ret
.
put
(
Keys
.
STATUS_CODE
,
true
);
return
ret
;
}
catch
(
final
Exception
e
)
{
LOGGER
.
log
(
Level
.
WARNING
,
"Checks add comment request["
+
requestJSONObject
.
toString
()
+
"] failed"
,
e
);
ret
.
put
(
Keys
.
STATUS_CODE
,
false
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"addFailLabel"
));
return
ret
;
}
}
/**
* Sends a notification mail to administrator for notifying the specified
* article or page received the specified comment and original comment.
*
* @param articleOrPage the specified article or page
* @param comment the specified comment
* @param originalComment original comment, if not exists, set it as
* {@code null}
* @param preference the specified preference
* @throws IOException io exception
* @throws JSONException json exception
*/
public
static
void
sendNotificationMail
(
final
JSONObject
articleOrPage
,
final
JSONObject
comment
,
final
JSONObject
originalComment
,
final
JSONObject
preference
)
throws
IOException
,
JSONException
{
final
String
commentEmail
=
comment
.
getString
(
Comment
.
COMMENT_EMAIL
);
final
String
commentId
=
comment
.
getString
(
Keys
.
OBJECT_ID
);
final
String
commentContent
=
comment
.
getString
(
Comment
.
COMMENT_CONTENT
).
replaceAll
(
SoloServletListener
.
ENTER_ESC
,
"<br/>"
);
final
String
adminEmail
=
preference
.
getString
(
Preference
.
ADMIN_EMAIL
);
if
(
adminEmail
.
equalsIgnoreCase
(
commentEmail
))
{
LOGGER
.
log
(
Level
.
FINER
,
"Do not send comment notification mail to admin itself[{0}]"
,
adminEmail
);
return
;
}
if
(
null
!=
originalComment
&&
comment
.
has
(
Comment
.
COMMENT_ORIGINAL_COMMENT_ID
))
{
final
String
originalEmail
=
originalComment
.
getString
(
Comment
.
COMMENT_EMAIL
);
if
(
originalEmail
.
equalsIgnoreCase
(
adminEmail
))
{
LOGGER
.
log
(
Level
.
FINER
,
"Do not send comment notification mail to admin while the specified comment[{0}] is an reply"
,
commentId
);
return
;
}
}
final
String
blogTitle
=
preference
.
getString
(
Preference
.
BLOG_TITLE
);
final
String
blogHost
=
preference
.
getString
(
Preference
.
BLOG_HOST
);
boolean
isArticle
=
true
;
String
title
=
articleOrPage
.
optString
(
Article
.
ARTICLE_TITLE
);
if
(
Strings
.
isEmptyOrNull
(
title
))
{
title
=
articleOrPage
.
getString
(
Page
.
PAGE_TITLE
);
isArticle
=
false
;
}
final
String
commentSharpURL
=
comment
.
getString
(
Comment
.
COMMENT_SHARP_URL
);
final
Message
message
=
new
Message
();
message
.
setFrom
(
adminEmail
);
message
.
addRecipient
(
adminEmail
);
String
mailSubject
=
null
;
String
articleOrPageURL
=
null
;
String
mailBody
=
null
;
if
(
isArticle
)
{
mailSubject
=
blogTitle
+
": New comment on article ["
+
title
+
"]"
;
articleOrPageURL
=
"http://"
+
blogHost
+
articleOrPage
.
getString
(
Article
.
ARTICLE_PERMALINK
);
mailBody
=
COMMENT_MAIL_HTML_BODY
.
replace
(
"{articleOrPage}"
,
"Article"
);
}
else
{
mailSubject
=
blogTitle
+
": New comment on page ["
+
title
+
"]"
;
articleOrPageURL
=
"http://"
+
blogHost
+
articleOrPage
.
getString
(
Page
.
PAGE_PERMALINK
);
mailBody
=
COMMENT_MAIL_HTML_BODY
.
replace
(
"{articleOrPage}"
,
"Page"
);
}
message
.
setSubject
(
mailSubject
);
final
String
commentName
=
comment
.
getString
(
Comment
.
COMMENT_NAME
);
final
String
commentURL
=
comment
.
getString
(
Comment
.
COMMENT_URL
);
String
commenter
=
null
;
if
(!
"http://"
.
equals
(
commentURL
))
{
commenter
=
"<a target=\"_blank\" "
+
"href=\""
+
commentURL
+
"\">"
+
commentName
+
"</a>"
;
}
else
{
commenter
=
commentName
;
}
mailBody
=
mailBody
.
replace
(
"{articleOrPageURL}"
,
articleOrPageURL
).
replace
(
"{title}"
,
title
).
replace
(
"{commentContent}"
,
commentContent
).
replace
(
"{commentSharpURL}"
,
blogHost
+
commentSharpURL
).
replace
(
"{commenter}"
,
commenter
);
message
.
setHtmlBody
(
mailBody
);
LOGGER
.
log
(
Level
.
FINER
,
"Sending a mail[mailSubject={0}, mailBody=[{1}] to admin[email={2}]"
,
new
Object
[]
{
mailSubject
,
mailBody
,
adminEmail
});
MAIL_SVC
.
send
(
message
);
}
/**
* Gets the {@link Comments} singleton.
*
* @return the singleton
*/
public
static
Comments
getInstance
()
{
return
SingletonHolder
.
SINGLETON
;
}
/**
* Private default constructor.
*/
private
Comments
()
{}
/**
* Singleton holder.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.0, Jan 12, 2011
*/
private
static
final
class
SingletonHolder
{
/**
* Singleton.
*/
private
static
final
Comments
SINGLETON
=
new
Comments
();
/**
* Private default constructor.
*/
private
SingletonHolder
()
{}
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, 2013, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
b3log
.
solo
.
util
;
import
java.io.IOException
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
org.b3log.latke.Keys
;
import
org.b3log.latke.mail.MailService
;
import
org.b3log.latke.mail.MailService.Message
;
import
org.b3log.latke.mail.MailServiceFactory
;
import
org.b3log.latke.service.LangPropsService
;
import
org.b3log.latke.util.Strings
;
import
org.b3log.solo.SoloServletListener
;
import
org.b3log.solo.model.*
;
import
org.b3log.solo.repository.ArticleRepository
;
import
org.b3log.solo.repository.PageRepository
;
import
org.b3log.solo.repository.impl.ArticleRepositoryImpl
;
import
org.b3log.solo.repository.impl.PageRepositoryImpl
;
import
org.b3log.solo.service.PreferenceQueryService
;
import
org.json.JSONException
;
import
org.json.JSONObject
;
/**
* Comment utilities.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.10, Apr 2, 2013
* @since 0.3.1
*/
public
final
class
Comments
{
/**
* Logger.
*/
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
Comments
.
class
.
getName
());
/**
* Language service.
*/
private
static
LangPropsService
langPropsService
=
LangPropsService
.
getInstance
();
/**
* Preference query service.
*/
private
static
PreferenceQueryService
preferenceQueryService
=
PreferenceQueryService
.
getInstance
();
/**
* Article repository.
*/
private
static
ArticleRepository
articleRepository
=
ArticleRepositoryImpl
.
getInstance
();
/**
* Page repository.
*/
private
static
PageRepository
pageRepository
=
PageRepositoryImpl
.
getInstance
();
/**
* Mail service.
*/
private
static
final
MailService
MAIL_SVC
=
MailServiceFactory
.
getMailService
();
/**
* Minimum length of comment name.
*/
private
static
final
int
MIN_COMMENT_NAME_LENGTH
=
2
;
/**
* Maximum length of comment name.
*/
private
static
final
int
MAX_COMMENT_NAME_LENGTH
=
20
;
/**
* Minimum length of comment content.
*/
private
static
final
int
MIN_COMMENT_CONTENT_LENGTH
=
2
;
/**
* Maximum length of comment content.
*/
private
static
final
int
MAX_COMMENT_CONTENT_LENGTH
=
500
;
/**
* Comment mail HTML body.
*/
public
static
final
String
COMMENT_MAIL_HTML_BODY
=
"<p>{articleOrPage} [<a href=\""
+
"{articleOrPageURL}\">"
+
"{title}</a>]"
+
" received a new comment:</p>"
+
"{commenter}: <span><a href=\"http://{commentSharpURL}\">"
+
"{commentContent}</a></span>"
;
/**
* Gets comment sharp URL with the specified page and comment id.
*
* @param page the specified page
* @param commentId the specified comment id
* @return comment sharp URL
* @throws JSONException json exception
*/
public
static
String
getCommentSharpURLForPage
(
final
JSONObject
page
,
final
String
commentId
)
throws
JSONException
{
return
page
.
getString
(
Page
.
PAGE_PERMALINK
)
+
"#"
+
commentId
;
}
/**
* Gets comment sharp URL with the specified article and comment id.
*
* @param article the specified article
* @param commentId the specified comment id
* @return comment sharp URL
* @throws JSONException json exception
*/
public
static
String
getCommentSharpURLForArticle
(
final
JSONObject
article
,
final
String
commentId
)
throws
JSONException
{
final
String
articleLink
=
article
.
getString
(
Article
.
ARTICLE_PERMALINK
);
return
articleLink
+
"#"
+
commentId
;
}
/**
* Checks the specified comment adding request.
*
* @param requestJSONObject the specified comment adding request, for example,
* <pre>
* {
* "type": "", // "article"/"page"
* "oId": "",
* "commentName": "",
* "commentEmail": "",
* "commentURL": "",
* "commentContent": "",
* }
* </pre>
* @return check result, for example,
* <pre>
* {
* "sc": boolean,
* "msg": "" // Exists if "sc" equals to false
* }
* </pre>
*/
public
static
JSONObject
checkAddCommentRequest
(
final
JSONObject
requestJSONObject
)
{
final
JSONObject
ret
=
new
JSONObject
();
try
{
ret
.
put
(
Keys
.
STATUS_CODE
,
false
);
final
JSONObject
preference
=
preferenceQueryService
.
getPreference
();
if
(
null
==
preference
||
!
preference
.
optBoolean
(
Preference
.
COMMENTABLE
))
{
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"notAllowCommentLabel"
));
return
ret
;
}
final
String
id
=
requestJSONObject
.
optString
(
Keys
.
OBJECT_ID
);
final
String
type
=
requestJSONObject
.
optString
(
Common
.
TYPE
);
if
(
Article
.
ARTICLE
.
equals
(
type
))
{
final
JSONObject
article
=
articleRepository
.
get
(
id
);
if
(
null
==
article
||
!
article
.
optBoolean
(
Article
.
ARTICLE_COMMENTABLE
))
{
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"notAllowCommentLabel"
));
return
ret
;
}
}
else
{
final
JSONObject
page
=
pageRepository
.
get
(
id
);
if
(
null
==
page
||
!
page
.
optBoolean
(
Page
.
PAGE_COMMENTABLE
))
{
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"notAllowCommentLabel"
));
return
ret
;
}
}
final
String
commentName
=
requestJSONObject
.
getString
(
Comment
.
COMMENT_NAME
);
if
(
MAX_COMMENT_NAME_LENGTH
<
commentName
.
length
()
||
MIN_COMMENT_NAME_LENGTH
>
commentName
.
length
())
{
LOGGER
.
log
(
Level
.
WARNING
,
"Comment name is too long[{0}]"
,
commentName
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"nameTooLongLabel"
));
return
ret
;
}
final
String
commentEmail
=
requestJSONObject
.
getString
(
Comment
.
COMMENT_EMAIL
).
trim
().
toLowerCase
();
if
(!
Strings
.
isEmail
(
commentEmail
))
{
LOGGER
.
log
(
Level
.
WARNING
,
"Comment email is invalid[{0}]"
,
commentEmail
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"mailInvalidLabel"
));
return
ret
;
}
final
String
commentURL
=
requestJSONObject
.
optString
(
Comment
.
COMMENT_URL
);
if
(!
Strings
.
isURL
(
commentURL
))
{
LOGGER
.
log
(
Level
.
WARNING
,
"Comment URL is invalid[{0}]"
,
commentURL
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"urlInvalidLabel"
));
return
ret
;
}
final
String
commentContent
=
requestJSONObject
.
optString
(
Comment
.
COMMENT_CONTENT
).
replaceAll
(
"\\n"
,
SoloServletListener
.
ENTER_ESC
);
if
(
MAX_COMMENT_CONTENT_LENGTH
<
commentContent
.
length
()
||
MIN_COMMENT_CONTENT_LENGTH
>
commentContent
.
length
())
{
LOGGER
.
log
(
Level
.
WARNING
,
"Comment conent length is invalid[{0}]"
,
commentContent
.
length
());
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"commentContentCannotEmptyLabel"
));
return
ret
;
}
ret
.
put
(
Keys
.
STATUS_CODE
,
true
);
return
ret
;
}
catch
(
final
Exception
e
)
{
LOGGER
.
log
(
Level
.
WARNING
,
"Checks add comment request["
+
requestJSONObject
.
toString
()
+
"] failed"
,
e
);
ret
.
put
(
Keys
.
STATUS_CODE
,
false
);
ret
.
put
(
Keys
.
MSG
,
langPropsService
.
get
(
"addFailLabel"
));
return
ret
;
}
}
/**
* Sends a notification mail to administrator for notifying the specified
* article or page received the specified comment and original comment.
*
* @param articleOrPage the specified article or page
* @param comment the specified comment
* @param originalComment original comment, if not exists, set it as
* {@code null}
* @param preference the specified preference
* @throws IOException io exception
* @throws JSONException json exception
*/
public
static
void
sendNotificationMail
(
final
JSONObject
articleOrPage
,
final
JSONObject
comment
,
final
JSONObject
originalComment
,
final
JSONObject
preference
)
throws
IOException
,
JSONException
{
final
String
commentEmail
=
comment
.
getString
(
Comment
.
COMMENT_EMAIL
);
final
String
commentId
=
comment
.
getString
(
Keys
.
OBJECT_ID
);
final
String
commentContent
=
comment
.
getString
(
Comment
.
COMMENT_CONTENT
).
replaceAll
(
SoloServletListener
.
ENTER_ESC
,
"<br/>"
);
final
String
adminEmail
=
preference
.
getString
(
Preference
.
ADMIN_EMAIL
);
if
(
adminEmail
.
equalsIgnoreCase
(
commentEmail
))
{
LOGGER
.
log
(
Level
.
FINER
,
"Do not send comment notification mail to admin itself[{0}]"
,
adminEmail
);
return
;
}
if
(
null
!=
originalComment
&&
comment
.
has
(
Comment
.
COMMENT_ORIGINAL_COMMENT_ID
))
{
final
String
originalEmail
=
originalComment
.
getString
(
Comment
.
COMMENT_EMAIL
);
if
(
originalEmail
.
equalsIgnoreCase
(
adminEmail
))
{
LOGGER
.
log
(
Level
.
FINER
,
"Do not send comment notification mail to admin while the specified comment[{0}] is an reply"
,
commentId
);
return
;
}
}
final
String
blogTitle
=
preference
.
getString
(
Preference
.
BLOG_TITLE
);
final
String
blogHost
=
preference
.
getString
(
Preference
.
BLOG_HOST
);
boolean
isArticle
=
true
;
String
title
=
articleOrPage
.
optString
(
Article
.
ARTICLE_TITLE
);
if
(
Strings
.
isEmptyOrNull
(
title
))
{
title
=
articleOrPage
.
getString
(
Page
.
PAGE_TITLE
);
isArticle
=
false
;
}
final
String
commentSharpURL
=
comment
.
getString
(
Comment
.
COMMENT_SHARP_URL
);
final
Message
message
=
new
Message
();
message
.
setFrom
(
adminEmail
);
message
.
addRecipient
(
adminEmail
);
String
mailSubject
=
null
;
String
articleOrPageURL
=
null
;
String
mailBody
=
null
;
if
(
isArticle
)
{
mailSubject
=
blogTitle
+
": New comment on article ["
+
title
+
"]"
;
articleOrPageURL
=
"http://"
+
blogHost
+
articleOrPage
.
getString
(
Article
.
ARTICLE_PERMALINK
);
mailBody
=
COMMENT_MAIL_HTML_BODY
.
replace
(
"{articleOrPage}"
,
"Article"
);
}
else
{
mailSubject
=
blogTitle
+
": New comment on page ["
+
title
+
"]"
;
articleOrPageURL
=
"http://"
+
blogHost
+
articleOrPage
.
getString
(
Page
.
PAGE_PERMALINK
);
mailBody
=
COMMENT_MAIL_HTML_BODY
.
replace
(
"{articleOrPage}"
,
"Page"
);
}
message
.
setSubject
(
mailSubject
);
final
String
commentName
=
comment
.
getString
(
Comment
.
COMMENT_NAME
);
final
String
commentURL
=
comment
.
getString
(
Comment
.
COMMENT_URL
);
String
commenter
=
null
;
if
(!
"http://"
.
equals
(
commentURL
))
{
commenter
=
"<a target=\"_blank\" "
+
"href=\""
+
commentURL
+
"\">"
+
commentName
+
"</a>"
;
}
else
{
commenter
=
commentName
;
}
mailBody
=
mailBody
.
replace
(
"{articleOrPageURL}"
,
articleOrPageURL
).
replace
(
"{title}"
,
title
).
replace
(
"{commentContent}"
,
commentContent
).
replace
(
"{commentSharpURL}"
,
blogHost
+
commentSharpURL
).
replace
(
"{commenter}"
,
commenter
);
message
.
setHtmlBody
(
mailBody
);
LOGGER
.
log
(
Level
.
FINER
,
"Sending a mail[mailSubject={0}, mailBody=[{1}] to admin[email={2}]"
,
new
Object
[]
{
mailSubject
,
mailBody
,
adminEmail
});
MAIL_SVC
.
send
(
message
);
}
/**
* Gets the {@link Comments} singleton.
*
* @return the singleton
*/
public
static
Comments
getInstance
()
{
return
SingletonHolder
.
SINGLETON
;
}
/**
* Private default constructor.
*/
private
Comments
()
{}
/**
* Singleton holder.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.0, Jan 12, 2011
*/
private
static
final
class
SingletonHolder
{
/**
* Singleton.
*/
private
static
final
Comments
SINGLETON
=
new
Comments
();
/**
* Private default constructor.
*/
private
SingletonHolder
()
{}
}
}
core/src/main/resources/repository.json
View file @
f271af1b
{
"description"
:
"Description of repository structures, for generation (DDL: http://en.wikipedia.org/wiki/Data_Definition_Language) of the relational database table and persistence validation."
,
"version"
:
"1.0.
0.9, Mar 5
, 2013"
,
"version"
:
"1.0.
1.0, Apr 2
, 2013"
,
"authors"
:
[
"Liang Ding"
],
"since"
:
"0.4.0"
,
...
...
@@ -538,6 +538,11 @@
"type"
:
"String"
,
"length"
:
255
},
{
"name"
:
"userURL"
,
"type"
:
"String"
,
"length"
:
255
},
{
"name"
:
"userPassword"
,
"type"
:
"String"
,
...
...
core/src/test/java/org/b3log/solo/repository/impl/UserRepositoryImplTestCase.java
View file @
f271af1b
/*
* Copyright (c) 2009, 2010, 2011, 2012, 2013, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
b3log
.
solo
.
repository
.
impl
;
import
org.b3log.latke.Keys
;
import
org.b3log.latke.model.Role
;
import
org.b3log.latke.model.User
;
import
org.b3log.latke.repository.FilterOperator
;
import
org.b3log.latke.repository.PropertyFilter
;
import
org.b3log.latke.repository.Query
;
import
org.b3log.latke.repository.Transaction
;
import
org.b3log.solo.AbstractTestCase
;
import
org.b3log.solo.model.UserExt
;
import
org.b3log.solo.repository.UserRepository
;
import
org.json.JSONArray
;
import
org.json.JSONObject
;
import
org.testng.Assert
;
import
org.testng.annotations.Test
;
/**
* {@link UserRepositoryImpl} test case.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.1, Feb 21, 2012
*/
@Test
(
suiteName
=
"repository"
)
public
final
class
UserRepositoryImplTestCase
extends
AbstractTestCase
{
/**
* Tests.
*
* @throws Exception exception
*/
@Test
public
void
test
()
throws
Exception
{
final
UserRepository
userRepository
=
getUserRepository
();
final
JSONObject
another
=
new
JSONObject
();
another
.
put
(
User
.
USER_NAME
,
"test1"
);
another
.
put
(
User
.
USER_EMAIL
,
"test1@gmail.com"
);
another
.
put
(
User
.
USER_PASSWORD
,
"pass1"
);
another
.
put
(
User
.
USER_ROLE
,
Role
.
DEFAULT_ROLE
);
another
.
put
(
UserExt
.
USER_ARTICLE_COUNT
,
0
);
another
.
put
(
UserExt
.
USER_PUBLISHED_ARTICLE_COUNT
,
0
);
Transaction
transaction
=
userRepository
.
beginTransaction
();
userRepository
.
add
(
another
);
transaction
.
commit
();
Assert
.
assertNull
(
userRepository
.
getAdmin
());
JSONObject
admin
=
new
JSONObject
();
admin
.
put
(
User
.
USER_NAME
,
"test"
);
admin
.
put
(
User
.
USER_EMAIL
,
"test@gmail.com"
);
admin
.
put
(
User
.
USER_PASSWORD
,
"pass"
);
admin
.
put
(
User
.
USER_ROLE
,
Role
.
ADMIN_ROLE
);
admin
.
put
(
UserExt
.
USER_ARTICLE_COUNT
,
0
);
admin
.
put
(
UserExt
.
USER_PUBLISHED_ARTICLE_COUNT
,
0
);
transaction
=
userRepository
.
beginTransaction
();
userRepository
.
add
(
admin
);
transaction
.
commit
();
Assert
.
assertTrue
(
userRepository
.
isAdminEmail
(
"test@gmail.com"
));
Assert
.
assertFalse
(
userRepository
.
isAdminEmail
(
"notFound@gmail.com"
));
admin
=
userRepository
.
getAdmin
();
Assert
.
assertNotNull
(
admin
);
Assert
.
assertEquals
(
"test"
,
admin
.
optString
(
User
.
USER_NAME
));
final
JSONObject
result
=
userRepository
.
get
(
new
Query
().
setFilter
(
new
PropertyFilter
(
User
.
USER_NAME
,
FilterOperator
.
EQUAL
,
"test1"
)));
final
JSONArray
users
=
result
.
getJSONArray
(
Keys
.
RESULTS
);
Assert
.
assertEquals
(
users
.
length
(),
1
);
Assert
.
assertEquals
(
users
.
getJSONObject
(
0
).
getString
(
User
.
USER_EMAIL
),
"test1@gmail.com"
);
final
JSONObject
notFound
=
userRepository
.
getByEmail
(
"not.found@gmail.com"
);
Assert
.
assertNull
(
notFound
);
final
JSONObject
found
=
userRepository
.
getByEmail
(
"test1@gmail.com"
);
Assert
.
assertNotNull
(
found
);
Assert
.
assertEquals
(
found
.
getString
(
User
.
USER_PASSWORD
),
"pass1"
);
}
}
/*
* Copyright (c) 2009, 2010, 2011, 2012, 2013, B3log Team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
b3log
.
solo
.
repository
.
impl
;
import
org.b3log.latke.Keys
;
import
org.b3log.latke.model.Role
;
import
org.b3log.latke.model.User
;
import
org.b3log.latke.repository.FilterOperator
;
import
org.b3log.latke.repository.PropertyFilter
;
import
org.b3log.latke.repository.Query
;
import
org.b3log.latke.repository.Transaction
;
import
org.b3log.solo.AbstractTestCase
;
import
org.b3log.solo.model.UserExt
;
import
org.b3log.solo.repository.UserRepository
;
import
org.json.JSONArray
;
import
org.json.JSONObject
;
import
org.testng.Assert
;
import
org.testng.annotations.Test
;
/**
* {@link UserRepositoryImpl} test case.
*
* @author <a href="mailto:DL88250@gmail.com">Liang Ding</a>
* @version 1.0.0.2, Apr 2, 2013
*/
@Test
(
suiteName
=
"repository"
)
public
final
class
UserRepositoryImplTestCase
extends
AbstractTestCase
{
/**
* Tests.
*
* @throws Exception exception
*/
@Test
public
void
test
()
throws
Exception
{
final
UserRepository
userRepository
=
getUserRepository
();
final
JSONObject
another
=
new
JSONObject
();
another
.
put
(
User
.
USER_NAME
,
"test1"
);
another
.
put
(
User
.
USER_EMAIL
,
"test1@gmail.com"
);
another
.
put
(
User
.
USER_PASSWORD
,
"pass1"
);
another
.
put
(
User
.
USER_URL
,
"http://b3log.org"
);
another
.
put
(
User
.
USER_ROLE
,
Role
.
DEFAULT_ROLE
);
another
.
put
(
UserExt
.
USER_ARTICLE_COUNT
,
0
);
another
.
put
(
UserExt
.
USER_PUBLISHED_ARTICLE_COUNT
,
0
);
Transaction
transaction
=
userRepository
.
beginTransaction
();
userRepository
.
add
(
another
);
transaction
.
commit
();
Assert
.
assertNull
(
userRepository
.
getAdmin
());
JSONObject
admin
=
new
JSONObject
();
admin
.
put
(
User
.
USER_NAME
,
"test"
);
admin
.
put
(
User
.
USER_EMAIL
,
"test@gmail.com"
);
admin
.
put
(
User
.
USER_PASSWORD
,
"pass"
);
admin
.
put
(
User
.
USER_URL
,
"http://b3log.org"
);
admin
.
put
(
User
.
USER_ROLE
,
Role
.
ADMIN_ROLE
);
admin
.
put
(
UserExt
.
USER_ARTICLE_COUNT
,
0
);
admin
.
put
(
UserExt
.
USER_PUBLISHED_ARTICLE_COUNT
,
0
);
transaction
=
userRepository
.
beginTransaction
();
userRepository
.
add
(
admin
);
transaction
.
commit
();
Assert
.
assertTrue
(
userRepository
.
isAdminEmail
(
"test@gmail.com"
));
Assert
.
assertFalse
(
userRepository
.
isAdminEmail
(
"notFound@gmail.com"
));
admin
=
userRepository
.
getAdmin
();
Assert
.
assertNotNull
(
admin
);
Assert
.
assertEquals
(
"test"
,
admin
.
optString
(
User
.
USER_NAME
));
final
JSONObject
result
=
userRepository
.
get
(
new
Query
().
setFilter
(
new
PropertyFilter
(
User
.
USER_NAME
,
FilterOperator
.
EQUAL
,
"test1"
)));
final
JSONArray
users
=
result
.
getJSONArray
(
Keys
.
RESULTS
);
Assert
.
assertEquals
(
users
.
length
(),
1
);
Assert
.
assertEquals
(
users
.
getJSONObject
(
0
).
getString
(
User
.
USER_EMAIL
),
"test1@gmail.com"
);
final
JSONObject
notFound
=
userRepository
.
getByEmail
(
"not.found@gmail.com"
);
Assert
.
assertNull
(
notFound
);
final
JSONObject
found
=
userRepository
.
getByEmail
(
"test1@gmail.com"
);
Assert
.
assertNotNull
(
found
);
Assert
.
assertEquals
(
found
.
getString
(
User
.
USER_PASSWORD
),
"pass1"
);
}
}
war/src/main/resources/lang_en_US.properties
View file @
f271af1b
...
...
@@ -16,7 +16,7 @@
#
# Description: B3log Solo language configurations(en_US).
# Version: 2.1.0.
6, Apr 1
, 2013
# Version: 2.1.0.
7, Apr 2
, 2013
# Author: Liang Ding
# Author: Liyuan Li
# Author: Dongxu Wang
...
...
@@ -193,6 +193,8 @@ userName1Label=Username:
userLabel
=
User
userPassword1Label
=
Password:
userPasswordLabel
=
Password
userURL1Label
=
Link:
userURLLabel
=
Link
categoryLabel
=
Category
noticeBoard1Label
=
Notice Board:
noticeBoardLabel
=
Notice Board
...
...
war/src/main/resources/lang_zh_CN.properties
View file @
f271af1b
...
...
@@ -16,7 +16,7 @@
#
# Description: B3log Solo default language configurations(zh_CN).
# Version: 2.1.1.
3, Apr 1
, 2013
# Version: 2.1.1.
4, Apr 2
, 2013
# Author: Liang Ding
# Author: Liyuan Li
# Author: Dongxu Wang
...
...
@@ -193,6 +193,8 @@ userName1Label=\u7528\u6237\u540d\uff1a
userLabel
=
\u7528\u6237
userPassword1Label
=
\u
5bc6
\u7801\u
ff1a
userPasswordLabel
=
\u
5bc6
\u7801
userURL1Label
=
\u
94fe
\u
63a5
\u
ff1a
userURLLabel
=
\u
94fe
\u
63a5
categoryLabel
=
\u5206\u
7c7b
noticeBoard1Label
=
\u
516c
\u
544a
\u
ff1a
noticeBoardLabel
=
\u
516c
\u
544a
...
...
war/src/main/webapp/admin-user-list.ftl
View file @
f271af1b
<div id="userTable"></div>
<div id="userPagination" class="margin12 right"></div>
<div class="clear"></div>
<table class="form" width="100%" cellpadding="0px" cellspacing="9px">
<thead>
<tr>
<th style="text-align: left" colspan="2">
${addUserLabel}
</th>
</tr>
</thead>
<tbody>
<tr>
<th width="48px">
<label for="userName">${commentName1Label}</label>
</th>
<td>
<input id="userName" type="text"/>
</td>
</tr>
<tr>
<th>
<label for="userEmail">${commentEmail1Label}</label>
</th>
<td>
<input id="userEmail" type="text"/>
</td>
</tr>
<tr>
<th>
<label for="userPassword">${userPassword1Label}</label>
</th>
<td>
<input id="userPassword" type="password"/>
</td>
</tr>
<tr>
<td colspan="2" align="right">
<button onclick="admin.userList.add();">${saveLabel}</button>
</td>
</tr>
</tbody>
</table>
<div id="userUpdate" class="none">
<table class="form" width="100%" cellpadding="0px" cellspacing="9px">
<thead>
<tr>
<th style="text-align: left" colspan="2">
${updateUserLabel}
</th>
</tr>
</thead>
<tbody>
<tr>
<th width="48px">
<label for="userNameUpdate">${commentName1Label}</label>
</th>
<td>
<input id="userNameUpdate" type="text"/>
</td>
</tr>
<tr>
<th>
<label for="userEmailUpdate">${commentEmail1Label}</label>
</th>
<td>
<input id="userEmailUpdate" type="text"/>
</td>
</tr>
<tr>
<th>
<label for="userPasswordUpdate">${userPassword1Label}</label>
</th>
<td>
<input id="userPasswordUpdate" type="password"/>
</td>
</tr>
<tr>
<td colspan="2" align="right">
<button onclick="admin.userList.update();">${updateLabel}</button>
</td>
</tr>
</tbody>
</table>
</div>
${plugins}
<div id="userTable"></div>
<div id="userPagination" class="margin12 right"></div>
<div class="clear"></div>
<table class="form" width="100%" cellpadding="0px" cellspacing="9px">
<thead>
<tr>
<th style="text-align: left" colspan="2">
${addUserLabel}
</th>
</tr>
</thead>
<tbody>
<tr>
<th width="48px">
<label for="userName">${commentName1Label}</label>
</th>
<td>
<input id="userName" type="text"/>
</td>
</tr>
<tr>
<th>
<label for="userEmail">${commentEmail1Label}</label>
</th>
<td>
<input id="userEmail" type="text"/>
</td>
</tr>
<tr>
<th>
<label for="userURL">${userURL1Label}</label>
</th>
<td>
<input id="userURL" type="text"/>
</td>
</tr>
<tr>
<th>
<label for="userPassword">${userPassword1Label}</label>
</th>
<td>
<input id="userPassword" type="password"/>
</td>
</tr>
<tr>
<td colspan="2" align="right">
<button onclick="admin.userList.add();">${saveLabel}</button>
</td>
</tr>
</tbody>
</table>
<div id="userUpdate" class="none">
<table class="form" width="100%" cellpadding="0px" cellspacing="9px">
<thead>
<tr>
<th style="text-align: left" colspan="2">
${updateUserLabel}
</th>
</tr>
</thead>
<tbody>
<tr>
<th width="48px">
<label for="userNameUpdate">${commentName1Label}</label>
</th>
<td>
<input id="userNameUpdate" type="text"/>
</td>
</tr>
<tr>
<th>
<label for="userEmailUpdate">${commentEmail1Label}</label>
</th>
<td>
<input id="userEmailUpdate" type="text"/>
</td>
</tr>
<tr>
<th>
<label for="userURLUpdate">${userURL1Label}</label>
</th>
<td>
<input id="userURLUpdate" type="text"/>
</td>
</tr>
<tr>
<th>
<label for="userPasswordUpdate">${userPassword1Label}</label>
</th>
<td>
<input id="userPasswordUpdate" type="password"/>
</td>
</tr>
<tr>
<td colspan="2" align="right">
<button onclick="admin.userList.update();">${updateLabel}</button>
</td>
</tr>
</tbody>
</table>
</div>
${plugins}
war/src/main/webapp/js/admin/userList.js
View file @
f271af1b
...
...
@@ -134,6 +134,7 @@ admin.userList = {
var
requestJSONObject
=
{
"
userName
"
:
$
(
"
#userName
"
).
val
(),
"
userEmail
"
:
$
(
"
#userEmail
"
).
val
(),
"
userURL
"
:
$
(
"
#userURL
"
).
val
(),
"
userPassword
"
:
$
(
"
#userPassword
"
).
val
()
};
...
...
@@ -151,6 +152,7 @@ admin.userList = {
$
(
"
#userName
"
).
val
(
""
);
$
(
"
#userEmail
"
).
val
(
""
);
$
(
"
#userURL
"
).
val
(
""
);
$
(
"
#userPassword
"
).
val
(
""
);
if
(
admin
.
userList
.
pageInfo
.
currentCount
===
Label
.
PAGE_SIZE
&&
admin
.
userList
.
pageInfo
.
currentPage
===
admin
.
userList
.
pageInfo
.
pageCount
)
{
...
...
@@ -198,6 +200,8 @@ admin.userList = {
}
else
{
$userEmailUpdate
.
removeAttr
(
"
disabled
"
);
}
$
(
"
#userURLUpdate
"
).
val
(
result
.
user
.
userURL
);
$
(
"
#userPasswordUpdate
"
).
val
(
result
.
user
.
userPassword
);
$
(
"
#loadMsg
"
).
text
(
""
);
...
...
@@ -217,6 +221,7 @@ admin.userList = {
"
userName
"
:
$
(
"
#userNameUpdate
"
).
val
(),
"
oId
"
:
userInfo
.
oId
,
"
userEmail
"
:
$
(
"
#userEmailUpdate
"
).
val
(),
"
userURL
"
:
$
(
"
#userURLUpdate
"
).
val
(),
"
userRole
"
:
userInfo
.
userRole
,
"
userPassword
"
:
$
(
"
#userPasswordUpdate
"
).
val
()
};
...
...
war/src/main/webapp/register.ftl
View file @
f271af1b
...
...
@@ -4,7 +4,7 @@
<meta
charset=
"utf-8"
/>
<title>
${blogTitle}
</title>
<meta
name=
"keywords"
content=
"GAE 博客,blog,b3log,kill IE6"
/>
<meta
name=
"description"
content=
"An open source blog based on GAE Java,GAE Java 开源博客,
Let's kill IE6
"
/>
<meta
name=
"description"
content=
"An open source blog based on GAE Java,GAE Java 开源博客,
用户注册
"
/>
<meta
name=
"owner"
content=
"B3log Team"
/>
<meta
name=
"author"
content=
"B3log Team"
/>
<meta
name=
"generator"
content=
"B3log Solo"
/>
...
...
@@ -34,6 +34,10 @@
${userName1Label}
</label>
<input
id=
"userName"
/>
<label
for=
"userURL"
>
${userURL1Label}
</label>
<input
id=
"userURL"
/>
<label
for=
"userPassword"
>
${userPassword1Label}
</label>
...
...
@@ -63,59 +67,60 @@
</div>
<script
type=
"text/javascript"
src=
"${staticServePath}/js/lib/jquery/jquery.min.js"
charset=
"utf-8"
></script>
<script
type=
"text/javascript"
>
var
validate
=
function
()
{
var
userName
=
$
(
"
#userName
"
).
val
().
replace
(
/
(
^
\s
*
)
|
(\s
*$
)
/g
,
""
);
if
(
!
/^
((([
a-z
]
|
\d
|
[
!#
\$
%&'
\*\+\-\/
=
\?\^
_`{
\|
}~
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
+
(\.([
a-z
]
|
\d
|
[
!#
\$
%&'
\*\+\-\/
=
\?\^
_`{
\|
}~
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
+
)
*
)
|
((\x
22
)((((\x
20|
\x
09
)
*
(\x
0d
\x
0a
))?(\x
20|
\x
09
)
+
)?(([\x
01-
\x
08
\x
0b
\x
0c
\x
0e-
\x
1f
\x
7f
]
|
\x
21|
[\x
23-
\x
5b
]
|
[\x
5d-
\x
7e
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
|
(\\([\x
01-
\x
09
\x
0b
\x
0c
\x
0d-
\x
7f
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
]))))
*
(((\x
20|
\x
09
)
*
(\x
0d
\x
0a
))?(\x
20|
\x
09
)
+
)?(\x
22
)))
@
((([
a-z
]
|
\d
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
|
(([
a-z
]
|
\d
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])([
a-z
]
|
\d
|-|
\.
|_|~|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
*
([
a-z
]
|
\d
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])))\.)
+
(([
a-z
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
|
(([
a-z
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])([
a-z
]
|
\d
|-|
\.
|_|~|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
*
([
a-z
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])))\.?
$/i
.
test
(
$
(
"
#userEmail
"
).
val
()))
{
$
(
"
#tip
"
).
text
(
"
${mailInvalidLabel}
"
);
$
(
"
#userEmail
"
).
focus
();
}
else
if
(
2
>
userName
.
length
||
userName
.
length
>
20
)
{
$
(
"
#tip
"
).
text
(
"
${nameTooLongLabel}
"
);
$
(
"
#userName
"
).
focus
();
}
else
if
(
$
(
"
#userPassword
"
).
val
().
replace
(
/
\s
/g
,
""
)
===
""
)
{
$
(
"
#tip
"
).
text
(
"
${passwordEmptyLabel}
"
);
$
(
"
#userPassword
"
).
focus
();
}
else
if
(
$
(
"
#userPassword
"
).
val
()
!==
$
(
"
#userPasswordConfirm
"
).
val
())
{
$
(
"
#tip
"
).
text
(
"
${passwordNotMatchLabel}
"
);
$
(
"
#userPasswordConfirm
"
).
focus
();
}
else
{
$
(
"
#tip
"
).
text
(
""
);
return
true
;
}
return
false
;
};
var
validate
=
function
()
{
var
userName
=
$
(
"
#userName
"
).
val
().
replace
(
/
(
^
\s
*
)
|
(\s
*$
)
/g
,
""
);
if
(
!
/^
((([
a-z
]
|
\d
|
[
!#
\$
%&'
\*\+\-\/
=
\?\^
_`{
\|
}~
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
+
(\.([
a-z
]
|
\d
|
[
!#
\$
%&'
\*\+\-\/
=
\?\^
_`{
\|
}~
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
+
)
*
)
|
((\x
22
)((((\x
20|
\x
09
)
*
(\x
0d
\x
0a
))?(\x
20|
\x
09
)
+
)?(([\x
01-
\x
08
\x
0b
\x
0c
\x
0e-
\x
1f
\x
7f
]
|
\x
21|
[\x
23-
\x
5b
]
|
[\x
5d-
\x
7e
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
|
(\\([\x
01-
\x
09
\x
0b
\x
0c
\x
0d-
\x
7f
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
]))))
*
(((\x
20|
\x
09
)
*
(\x
0d
\x
0a
))?(\x
20|
\x
09
)
+
)?(\x
22
)))
@
((([
a-z
]
|
\d
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
|
(([
a-z
]
|
\d
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])([
a-z
]
|
\d
|-|
\.
|_|~|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
*
([
a-z
]
|
\d
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])))\.)
+
(([
a-z
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
|
(([
a-z
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])([
a-z
]
|
\d
|-|
\.
|_|~|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])
*
([
a-z
]
|
[\u
00A0-
\u
D7FF
\u
F900-
\u
FDCF
\u
FDF0-
\u
FFEF
])))\.?
$/i
.
test
(
$
(
"
#userEmail
"
).
val
()))
{
$
(
"
#tip
"
).
text
(
"
${mailInvalidLabel}
"
);
$
(
"
#userEmail
"
).
focus
();
}
else
if
(
2
>
userName
.
length
||
userName
.
length
>
20
)
{
$
(
"
#tip
"
).
text
(
"
${nameTooLongLabel}
"
);
$
(
"
#userName
"
).
focus
();
}
else
if
(
$
(
"
#userPassword
"
).
val
().
replace
(
/
\s
/g
,
""
)
===
""
)
{
$
(
"
#tip
"
).
text
(
"
${passwordEmptyLabel}
"
);
$
(
"
#userPassword
"
).
focus
();
}
else
if
(
$
(
"
#userPassword
"
).
val
()
!==
$
(
"
#userPasswordConfirm
"
).
val
())
{
$
(
"
#tip
"
).
text
(
"
${passwordNotMatchLabel}
"
);
$
(
"
#userPasswordConfirm
"
).
focus
();
}
else
{
$
(
"
#tip
"
).
text
(
""
);
return
true
;
}
return
false
;
};
var
getUserInfo
=
function
()
{
if
(
validate
())
{
var
requestJSONObject
=
{
"
userName
"
:
$
(
"
#userName
"
).
val
(),
"
userEmail
"
:
$
(
"
#userEmail
"
).
val
(),
"
userPassword
"
:
$
(
"
#userPassword
"
).
val
()
};
$
.
ajax
({
url
:
"
${contextPath}
"
+
"
/console/user/
"
,
type
:
"
POST
"
,
cache
:
false
,
data
:
JSON
.
stringify
(
requestJSONObject
),
success
:
function
(
result
,
textStatus
)
{
$
(
"
#tip
"
).
text
(
result
.
msg
);
if
(
!
result
.
sc
)
{
return
;
}
setTimeout
(
function
()
{
window
.
location
.
href
=
"
${servePath}
"
;
},
1000
);
}
})
var
getUserInfo
=
function
()
{
if
(
validate
())
{
var
requestJSONObject
=
{
"
userName
"
:
$
(
"
#userName
"
).
val
(),
"
userEmail
"
:
$
(
"
#userEmail
"
).
val
(),
"
userURL
"
:
$
(
"
#userURL
"
).
val
(),
"
userPassword
"
:
$
(
"
#userPassword
"
).
val
()
};
$
.
ajax
({
url
:
"
${contextPath}
"
+
"
/console/user/
"
,
type
:
"
POST
"
,
cache
:
false
,
data
:
JSON
.
stringify
(
requestJSONObject
),
success
:
function
(
result
,
textStatus
)
{
$
(
"
#tip
"
).
text
(
result
.
msg
);
if
(
!
result
.
sc
)
{
return
;
}
setTimeout
(
function
()
{
window
.
location
.
href
=
"
${servePath}
"
;
},
1000
);
}
}
})
}
}
$
(
function
()
{
$
(
"
#userPasswordConfirm
"
).
keypress
(
function
(
event
)
{
if
(
event
.
keyCode
===
13
)
{
getUserInfo
();
}
});
});
$
(
function
()
{
$
(
"
#userPasswordConfirm
"
).
keypress
(
function
(
event
)
{
if
(
event
.
keyCode
===
13
)
{
getUserInfo
();
}
});
});
</script>
</body>
...
...
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