Skip to content

Commit ca37dbd

Browse files
committed
Only site admin can add comment to series.
Fix #120
1 parent 355fc40 commit ca37dbd

File tree

22 files changed

+715
-103
lines changed

22 files changed

+715
-103
lines changed

Diff for: src/main/java/ru/mystamps/web/controller/SeriesController.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package ru.mystamps.web.controller;
1919

2020
import javax.inject.Inject;
21+
import javax.servlet.http.HttpServletRequest;
2122
import javax.validation.groups.Default;
2223

2324
import java.util.Calendar;
@@ -46,6 +47,7 @@
4647
import ru.mystamps.web.entity.Series;
4748
import ru.mystamps.web.service.CountryService;
4849
import ru.mystamps.web.service.SeriesService;
50+
import ru.mystamps.web.support.spring.security.SecurityContextUtils;
4951
import ru.mystamps.web.util.CatalogUtils;
5052

5153
@Controller
@@ -105,13 +107,16 @@ public AddSeriesForm showForm() {
105107
public String processInput(
106108
@Validated({Default.class, ImageChecks.class}) AddSeriesForm form,
107109
BindingResult result,
110+
HttpServletRequest request,
108111
User currentUser) {
109112

110113
if (result.hasErrors()) {
111114
return null;
112115
}
113116

114-
Series series = seriesService.add(form, currentUser);
117+
boolean userCanAddComments =
118+
SecurityContextUtils.hasAuthority(request, "ADD_COMMENTS_TO_SERIES");
119+
Series series = seriesService.add(form, currentUser, userCanAddComments);
115120

116121
String dstUrl = UriComponentsBuilder.fromUriString(Url.INFO_SERIES_PAGE)
117122
.buildAndExpand(series.getId())

Diff for: src/main/java/ru/mystamps/web/entity/User.java

+16
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,13 @@
2121

2222
import javax.persistence.Column;
2323
import javax.persistence.Entity;
24+
import javax.persistence.Enumerated;
2425
import javax.persistence.GeneratedValue;
2526
import javax.persistence.Id;
2627
import javax.persistence.Table;
2728

29+
import static javax.persistence.EnumType.STRING;
30+
2831
import lombok.Getter;
2932
import lombok.Setter;
3033

@@ -35,6 +38,7 @@
3538
public class User {
3639

3740
public static final int LOGIN_LENGTH = 15;
41+
public static final int ROLE_LENGTH = 5;
3842
public static final int NAME_LENGTH = 100;
3943
public static final int HASH_LENGTH = 40;
4044
public static final int SALT_LENGTH = 10;
@@ -46,6 +50,10 @@ public class User {
4650
@Column(length = LOGIN_LENGTH, unique = true, nullable = false)
4751
private String login;
4852

53+
@Column(length = ROLE_LENGTH, nullable = false)
54+
@Enumerated(STRING)
55+
private Role role;
56+
4957
@Column(length = NAME_LENGTH, nullable = false)
5058
private String name;
5159

@@ -64,4 +72,12 @@ public class User {
6472
@Column(length = SALT_LENGTH, nullable = false)
6573
private String salt;
6674

75+
public boolean isAdmin() {
76+
return role == Role.ADMIN;
77+
}
78+
79+
public enum Role {
80+
USER, ADMIN
81+
};
82+
6783
}

Diff for: src/main/java/ru/mystamps/web/service/SeriesService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@
2222
import ru.mystamps.web.service.dto.AddSeriesDto;
2323

2424
public interface SeriesService {
25-
Series add(AddSeriesDto dto, User user);
25+
Series add(AddSeriesDto dto, User user, boolean userCanAddComments);
2626
}

Diff for: src/main/java/ru/mystamps/web/service/SeriesServiceImpl.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public SeriesServiceImpl(SeriesDao seriesDao, ImageService imageService) {
6060
@Override
6161
@Transactional
6262
@PreAuthorize("hasAuthority('CREATE_SERIES')")
63-
public Series add(AddSeriesDto dto, User user) {
63+
public Series add(AddSeriesDto dto, User user, boolean userCanAddComments) {
6464
Validate.isTrue(dto != null, "DTO must be non null");
6565
Validate.isTrue(dto.getQuantity() != null, "Stamps quantity must be non null");
6666
Validate.isTrue(
@@ -104,7 +104,7 @@ public Series add(AddSeriesDto dto, User user) {
104104

105105
series.setImageUrl(imageUrl);
106106

107-
if (dto.getComment() != null) {
107+
if (userCanAddComments && dto.getComment() != null) {
108108
Validate.isTrue(
109109
!dto.getComment().trim().isEmpty(),
110110
"Comment must be non empty"

Diff for: src/main/java/ru/mystamps/web/service/UserServiceImpl.java

+3
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import ru.mystamps.web.service.dto.ActivateAccountDto;
4040
import ru.mystamps.web.service.dto.RegisterAccountDto;
4141

42+
import static ru.mystamps.web.entity.User.Role.USER;
43+
4244
public class UserServiceImpl implements UserService {
4345

4446
private static final Logger LOG = LoggerFactory.getLogger(UserService.class);
@@ -117,6 +119,7 @@ public void registerUser(ActivateAccountDto dto) {
117119

118120
User user = new User();
119121
user.setLogin(login);
122+
user.setRole(USER);
120123
user.setName(finalName);
121124
user.setEmail(email);
122125
user.setRegisteredAt(registrationDate);

Diff for: src/main/java/ru/mystamps/web/support/spring/security/CustomUserDetailsService.java

+8-2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.apache.commons.lang3.Validate;
3737

3838
import ru.mystamps.web.entity.User;
39+
import ru.mystamps.web.entity.User.Role;
3940
import ru.mystamps.web.service.UserService;
4041

4142
/**
@@ -67,13 +68,18 @@ public UserDetails loadUserByUsername(String login) {
6768

6869
LOG.debug("User '{}' found", login);
6970

70-
return new CustomUserDetails(user, getAuthorities());
71+
return new CustomUserDetails(user, getAuthorities(user));
7172
}
7273

73-
private static Collection<? extends GrantedAuthority> getAuthorities() {
74+
private static Collection<? extends GrantedAuthority> getAuthorities(User user) {
7475
List<SimpleGrantedAuthority> authorities = new LinkedList<SimpleGrantedAuthority>();
7576
authorities.add(new SimpleGrantedAuthority("CREATE_COUNTRY"));
7677
authorities.add(new SimpleGrantedAuthority("CREATE_SERIES"));
78+
79+
if (user.isAdmin()) {
80+
authorities.add(new SimpleGrantedAuthority("ADD_COMMENTS_TO_SERIES"));
81+
}
82+
7783
return authorities;
7884
}
7985

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package ru.mystamps.web.support.spring.security;
2+
3+
import javax.servlet.http.HttpServletRequest;
4+
5+
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestWrapper;
6+
7+
public final class SecurityContextUtils {
8+
9+
private SecurityContextUtils() {
10+
}
11+
12+
public static boolean hasAuthority(HttpServletRequest request, String authority) {
13+
return new SecurityContextHolderAwareRequestWrapper(request, null).isUserInRole(authority);
14+
}
15+
16+
}

Diff for: src/main/resources/liquibase/initial-state.xml

+7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
<column name="login" type="VARCHAR(15)">
3737
<constraints nullable="false" unique="true" />
3838
</column>
39+
<column name="role" type="VARCHAR(5)">
40+
<constraints nullable="false" />
41+
</column>
3942
<column name="name" type="VARCHAR(100)">
4043
<constraints nullable="false" />
4144
</column>
@@ -413,6 +416,10 @@
413416
<column name="name" value="AuthenticationFailed" />
414417
</insert>
415418
</changeSet>
419+
420+
<changeSet id="create-user-admin" author="php-coder" context="test-data">
421+
<sqlFile path="sql/test-user-admin.sql" relativeToChangelogFile="true" />
422+
</changeSet>
416423

417424
<changeSet id="create-user-coder" author="php-coder" context="test-data">
418425
<sqlFile path="sql/test-user-coder.sql" relativeToChangelogFile="true" />

Diff for: src/main/resources/liquibase/sql/test-country-italy.sql

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
--
44

55
-- Used below as country's owner
6-
INSERT INTO users(id, login, name, registered_at, activated_at, hash, salt, email) VALUES
7-
(2, 'test0', '@valid_country_name@ Country Owner', NOW(), NOW(), '@valid_user_password_hash@', '@valid_user_password_salt@', '[email protected]');
6+
INSERT INTO users(id, login, role, name, registered_at, activated_at, hash, salt, email) VALUES
7+
(3, 'test0', 'USER', '@valid_country_name@ Country Owner', NOW(), NOW(), '@valid_user_password_hash@', '@valid_user_password_salt@', '[email protected]');
88

99
-- Used only in WhenUserAddCountry
1010
INSERT INTO countries(name, created_at, created_by, updated_at, updated_by) VALUES

Diff for: src/main/resources/liquibase/sql/test-user-admin.sql

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
--
2+
-- Auto-generated by Maven, based on values from src/main/resources/test/spring/test-data.properties
3+
--
4+
5+
INSERT INTO users(id, login, role, name, registered_at, activated_at, hash, salt, email) VALUES
6+
(1, '@valid_admin_login@', 'ADMIN', 'Site Admin', NOW(), NOW(), '@valid_admin_password_hash@', '@valid_admin_password_salt@', 'admin@localhost');

Diff for: src/main/resources/liquibase/sql/test-user-coder.sql

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
-- Auto-generated by Maven, based on values from src/main/resources/test/spring/test-data.properties
33
--
44

5-
INSERT INTO users(id, login, name, registered_at, activated_at, hash, salt, email) VALUES
6-
(1, '@valid_user_login@', '@valid_user_name@', NOW(), NOW(), '@valid_user_password_hash@', '@valid_user_password_salt@', '[email protected]');
5+
INSERT INTO users(id, login, role, name, registered_at, activated_at, hash, salt, email) VALUES
6+
(2, '@valid_user_login@', 'USER', '@valid_user_name@', NOW(), NOW(), '@valid_user_password_hash@', '@valid_user_password_salt@', '[email protected]');

Diff for: src/main/resources/test/spring/test-data.properties

+8
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,11 @@ not_activated_user2_act_key = 4444477777
2424
# this country should always exist
2525
# (used only in WhenUserAddCountry)
2626
valid_country_name = Italy
27+
28+
# this privileged user should always exist
29+
valid_admin_login = admin
30+
valid_admin_password = test
31+
32+
# Auto-calculated by SELECT SHA1(CONCAT('${salt}', '{', '${password}', '}'));
33+
valid_admin_password_salt = cEjinQJY3v
34+
valid_admin_password_hash = 27e04fc489395d3167d8dd71fc47e466ee190aee

Diff for: src/main/webapp/WEB-INF/tags/elem/field.tag

+20-17
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,25 @@
55
<%@ attribute name="path" required="true" rtexprvalue="true" %>
66
<%@ attribute name="label" required="true" rtexprvalue="true" %>
77
<%@ attribute name="required" required="false" rtexprvalue="true" type="java.lang.Boolean" %>
8+
<%@ attribute name="render" required="false" rtexprvalue="true" type="java.lang.Boolean" %>
89

9-
<spring:bind path="${path}">
10-
<c:set var="hasError" value="${status.error}" />
11-
12-
<div class="control-group ${hasError ? 'error' : ''}">
13-
<form:label path="${path}" cssClass="control-label">
14-
<span class="field-label">
15-
<spring:message code="${label}" />
16-
</span>
17-
<c:if test="${required}">
18-
<span id="${path}.required" class="required_field">*</span>
19-
</c:if>
20-
</form:label>
21-
<div class="controls">
22-
<jsp:doBody />
23-
<form:errors path="${path}" cssClass="help-inline" />
10+
<c:if test="${empty render or render}">
11+
<spring:bind path="${path}">
12+
<c:set var="hasError" value="${status.error}" />
13+
14+
<div class="control-group ${hasError ? 'error' : ''}">
15+
<form:label path="${path}" cssClass="control-label">
16+
<span class="field-label">
17+
<spring:message code="${label}" />
18+
</span>
19+
<c:if test="${required}">
20+
<span id="${path}.required" class="required_field">*</span>
21+
</c:if>
22+
</form:label>
23+
<div class="controls">
24+
<jsp:doBody />
25+
<form:errors path="${path}" cssClass="help-inline" />
26+
</div>
2427
</div>
25-
</div>
26-
</spring:bind>
28+
</spring:bind>
29+
</c:if>

Diff for: src/main/webapp/WEB-INF/tiles/body/series/add.jsp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
22
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
33
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
4+
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>
45
<%@ taglib tagdir="/WEB-INF/tags/elem" prefix="elem" %>
56
<%@ page import="ru.mystamps.web.validation.ValidationRules" %>
67

@@ -127,7 +128,8 @@
127128
</div>
128129
</div>
129130

130-
<elem:field path="comment" label="t_comment">
131+
<sec:authorize var="userCanAddComments" access="hasAuthority('ADD_COMMENTS_TO_SERIES')" />
132+
<elem:field path="comment" label="t_comment" render="${userCanAddComments}">
131133
<form:textarea path="comment" cssClass="span6" cols="22" rows="3" />
132134
</elem:field>
133135

Diff for: src/main/webapp/WEB-INF/tiles/body/series/info.jsp

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
22
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
33
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
4+
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>
45
<%@ taglib tagdir="/WEB-INF/tags/elem" prefix="elem" %>
56

67
<div class="row-fluid">
@@ -92,7 +93,8 @@
9293
/>
9394
</dd>
9495
</c:if>
95-
<c:if test="${not empty series.comment}">
96+
<sec:authorize var="userCanAddComments" access="hasAuthority('ADD_COMMENTS_TO_SERIES')" />
97+
<c:if test="${userCanAddComments and not empty series.comment}">
9698
<dt>
9799
<spring:message code="t_comment" />
98100
</dt>

0 commit comments

Comments
 (0)