Skip to content

Commit 01dca27

Browse files
committed
feat: add preliminary support for hidden images.
Fix #1356
1 parent 97a9322 commit 01dca27

18 files changed

+93
-23
lines changed

NEWS.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
0.x (upcoming release)
22
- (feature) a series can be marked as a similar to another one
33
- (feature) series images can be replaced
4+
- (feature) add preliminary support for hidden images
45

56
0.4.3
67
- (feature) add support for Ukrainian hryvnia

src/main/java/ru/mystamps/web/feature/image/ImageDao.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ public interface ImageDao {
2424
void replace(Integer id, String type, String filename);
2525
void addToSeries(Integer seriesId, Integer imageId);
2626
ImageInfoDto findById(Integer imageId);
27-
List<Integer> findBySeriesId(Integer seriesId);
27+
List<Integer> findBySeriesId(Integer seriesId, boolean hidden);
2828
}

src/main/java/ru/mystamps/web/feature/image/ImageService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ public interface ImageService {
2727
ImageDto get(Integer imageId);
2828
ImageDto getOrCreatePreview(Integer imageId);
2929
void addToSeries(Integer seriesId, Integer imageId);
30-
List<Integer> findBySeriesId(Integer seriesId);
30+
List<Integer> findBySeriesId(Integer seriesId, boolean hidden);
3131
void removeIfPossible(ImageInfoDto imageInfo);
3232
}

src/main/java/ru/mystamps/web/feature/image/ImageServiceImpl.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -184,10 +184,10 @@ public void addToSeries(Integer seriesId, Integer imageId) {
184184

185185
@Override
186186
@Transactional(readOnly = true)
187-
public List<Integer> findBySeriesId(Integer seriesId) {
187+
public List<Integer> findBySeriesId(Integer seriesId, boolean hidden) {
188188
Validate.isTrue(seriesId != null, "Series id must be non null");
189189

190-
return imageDao.findBySeriesId(seriesId);
190+
return imageDao.findBySeriesId(seriesId, hidden);
191191
}
192192

193193
@Override

src/main/java/ru/mystamps/web/feature/image/JdbcImageDao.java

+6-2
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,14 @@ public ImageInfoDto findById(Integer imageId) {
115115
}
116116

117117
@Override
118-
public List<Integer> findBySeriesId(Integer seriesId) {
118+
public List<Integer> findBySeriesId(Integer seriesId, boolean hidden) {
119+
Map<String, Object> params = new HashMap<>();
120+
params.put("series_id", seriesId);
121+
params.put("hidden", hidden);
122+
119123
return jdbcTemplate.queryForList(
120124
findBySeriesIdSql,
121-
Collections.singletonMap("series_id", seriesId),
125+
params,
122126
Integer.class
123127
);
124128
}

src/main/java/ru/mystamps/web/feature/series/SeriesController.java

+20-4
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,10 @@ public String showInfo(
214214
}
215215

216216
String lang = LocaleUtils.getLanguageOrNull(userLocale);
217-
SeriesDto series = seriesService.findFullInfoById(seriesId, lang);
217+
boolean userCanSeeHiddenImages = SecurityContextUtils.hasAuthority(
218+
Authority.VIEW_HIDDEN_IMAGES
219+
);
220+
SeriesDto series = seriesService.findFullInfoById(seriesId, lang, userCanSeeHiddenImages);
218221
if (series == null) {
219222
response.sendError(HttpServletResponse.SC_NOT_FOUND);
220223
return null;
@@ -363,7 +366,10 @@ public String processImage(
363366
}
364367

365368
String lang = LocaleUtils.getLanguageOrNull(userLocale);
366-
SeriesDto series = seriesService.findFullInfoById(seriesId, lang);
369+
boolean userCanSeeHiddenImages = SecurityContextUtils.hasAuthority(
370+
Authority.VIEW_HIDDEN_IMAGES
371+
);
372+
SeriesDto series = seriesService.findFullInfoById(seriesId, lang, userCanSeeHiddenImages);
367373
if (series == null) {
368374
response.sendError(HttpServletResponse.SC_NOT_FOUND);
369375
return null;
@@ -434,7 +440,14 @@ public String addToCollection(
434440

435441
if (result.hasErrors()) {
436442
String lang = LocaleUtils.getLanguageOrNull(userLocale);
437-
SeriesDto series = seriesService.findFullInfoById(seriesId, lang);
443+
boolean userCanSeeHiddenImages = SecurityContextUtils.hasAuthority(
444+
Authority.VIEW_HIDDEN_IMAGES
445+
);
446+
SeriesDto series = seriesService.findFullInfoById(
447+
seriesId,
448+
lang,
449+
userCanSeeHiddenImages
450+
);
438451
if (series == null) {
439452
response.sendError(HttpServletResponse.SC_NOT_FOUND);
440453
return null;
@@ -511,7 +524,10 @@ public String processAskForm(
511524
}
512525

513526
String lang = LocaleUtils.getLanguageOrNull(userLocale);
514-
SeriesDto series = seriesService.findFullInfoById(seriesId, lang);
527+
boolean userCanSeeHiddenImages = SecurityContextUtils.hasAuthority(
528+
Authority.VIEW_HIDDEN_IMAGES
529+
);
530+
SeriesDto series = seriesService.findFullInfoById(seriesId, lang, userCanSeeHiddenImages);
515531
if (series == null) {
516532
response.sendError(HttpServletResponse.SC_NOT_FOUND);
517533
return null;

src/main/java/ru/mystamps/web/feature/series/SeriesDto.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public class SeriesDto {
4646
@Getter
4747
private final List<Integer> imageIds;
4848

49+
@Getter
50+
private final List<Integer> hiddenImageIds;
51+
4952
@SuppressWarnings({ "checkstyle:parameternumber", "PMD.ExcessiveParameterList" })
5053
public SeriesDto(
5154
SeriesFullInfoDto info,
@@ -55,7 +58,8 @@ public SeriesDto(
5558
List<String> gibbonsNumbers,
5659
List<String> solovyovNumbers,
5760
List<String> zagorskiNumbers,
58-
List<Integer> imageIds) {
61+
List<Integer> imageIds,
62+
List<Integer> hiddenImageIds) {
5963

6064
this.info = info;
6165
this.michel = new CatalogInfoDto(michelNumbers, info.getMichelPrice());
@@ -65,6 +69,7 @@ public SeriesDto(
6569
this.solovyov = new CatalogInfoDto(solovyovNumbers, info.getSolovyovPrice());
6670
this.zagorski = new CatalogInfoDto(zagorskiNumbers, info.getZagorskiPrice());
6771
this.imageIds = imageIds;
72+
this.hiddenImageIds = hiddenImageIds;
6873
}
6974

7075
public Integer getId() {

src/main/java/ru/mystamps/web/feature/series/SeriesService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public interface SeriesService {
3333
boolean isSeriesExist(Integer seriesId);
3434
Integer findQuantityById(Integer seriesId);
3535

36-
SeriesDto findFullInfoById(Integer seriesId, String lang);
36+
SeriesDto findFullInfoById(Integer seriesId, String lang, boolean userCanSeeHiddenImages);
3737

3838
List<SeriesInfoDto> findByMichelNumber(String michelNumberCode, String lang);
3939
List<SeriesInfoDto> findByScottNumber(String scottNumberCode, String lang);

src/main/java/ru/mystamps/web/feature/series/SeriesServiceImpl.java

+14-3
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,11 @@ public Integer findQuantityById(Integer seriesId) {
200200

201201
@Override
202202
@Transactional(readOnly = true)
203-
public SeriesDto findFullInfoById(Integer seriesId, String lang) {
203+
public SeriesDto findFullInfoById(
204+
Integer seriesId,
205+
String lang,
206+
boolean userCanSeeHiddenImages) {
207+
204208
Validate.isTrue(seriesId != null, "Series id must be non null");
205209

206210
SeriesFullInfoDto seriesBaseInfo = seriesDao.findByIdAsSeriesFullInfo(seriesId, lang);
@@ -215,7 +219,13 @@ public SeriesDto findFullInfoById(Integer seriesId, String lang) {
215219
List<String> solovyovNumbers = solovyovCatalogService.findBySeriesId(seriesId);
216220
List<String> zagorskiNumbers = zagorskiCatalogService.findBySeriesId(seriesId);
217221

218-
List<Integer> imageIds = imageService.findBySeriesId(seriesId);
222+
List<Integer> imageIds = imageService.findBySeriesId(seriesId, false);
223+
224+
// @todo #1356 SeriesServiceImpl.findFullInfoById(): add unit test for hidden images
225+
List<Integer> hiddenImageIds = Collections.emptyList();
226+
if (userCanSeeHiddenImages) {
227+
hiddenImageIds = imageService.findBySeriesId(seriesId, true);
228+
}
219229

220230
return new SeriesDto(
221231
seriesBaseInfo,
@@ -225,7 +235,8 @@ public SeriesDto findFullInfoById(Integer seriesId, String lang) {
225235
gibbonsNumbers,
226236
solovyovNumbers,
227237
zagorskiNumbers,
228-
imageIds
238+
imageIds,
239+
hiddenImageIds
229240
);
230241
}
231242

src/main/java/ru/mystamps/web/support/spring/security/Authority.java

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ public final class Authority {
4040
public static final GrantedAuthority UPDATE_COLLECTION = new SimpleGrantedAuthority(StringAuthority.UPDATE_COLLECTION);
4141
public static final GrantedAuthority VIEW_ANY_ESTIMATION = new SimpleGrantedAuthority(StringAuthority.VIEW_ANY_ESTIMATION);
4242
public static final GrantedAuthority VIEW_DAILY_STATS = new SimpleGrantedAuthority(StringAuthority.VIEW_DAILY_STATS);
43+
public static final GrantedAuthority VIEW_HIDDEN_IMAGES = new SimpleGrantedAuthority(StringAuthority.VIEW_HIDDEN_IMAGES);
4344
public static final GrantedAuthority VIEW_SERIES_SALES = new SimpleGrantedAuthority(StringAuthority.VIEW_SERIES_SALES);
4445
public static final GrantedAuthority VIEW_SITE_EVENTS = new SimpleGrantedAuthority(StringAuthority.VIEW_SITE_EVENTS);
4546

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

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ private static Collection<? extends GrantedAuthority> getAuthorities(UserDetails
8484
authorities.add(Authority.REPLACE_IMAGE);
8585
authorities.add(Authority.VIEW_ANY_ESTIMATION);
8686
authorities.add(Authority.VIEW_DAILY_STATS);
87+
authorities.add(Authority.VIEW_HIDDEN_IMAGES);
8788
authorities.add(Authority.VIEW_SERIES_SALES);
8889
authorities.add(Authority.VIEW_SITE_EVENTS);
8990

src/main/java/ru/mystamps/web/support/spring/security/StringAuthority.java

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public final class StringAuthority {
3636
public static final String UPDATE_COLLECTION = "UPDATE_COLLECTION";
3737
public static final String VIEW_ANY_ESTIMATION = "VIEW_ANY_ESTIMATION";
3838
public static final String VIEW_DAILY_STATS = "VIEW_DAILY_STATS";
39+
public static final String VIEW_HIDDEN_IMAGES = "VIEW_HIDDEN_IMAGES";
3940
public static final String VIEW_SERIES_SALES = "VIEW_SERIES_SALES";
4041
public static final String VIEW_SITE_EVENTS = "VIEW_SITE_EVENTS";
4142

src/main/resources/ru/mystamps/i18n/Messages.properties

+1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ t_add_to_collection = Add to collection
143143
t_remove_from_collection = Remove from collection
144144
t_need_authentication_to_add_series_to_collection = \
145145
In order to add this series to your collection you should <a href="{0}">register</a> or <a href="{1}">pass authentication</a>.
146+
t_hidden_images = Hidden images
146147
t_image_id = Image ID
147148
t_add_image = Add image
148149
t_replace_image = Replace image

src/main/resources/ru/mystamps/i18n/Messages_ru.properties

+1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ t_add_to_collection = Добавить в коллекцию
142142
t_remove_from_collection = Убрать из коллекции
143143
t_need_authentication_to_add_series_to_collection = \
144144
Для того, чтобы добавить эту серию в свою коллекцию вы должны <a href="{0}">зарегистрироваться</a> или <a href="{1}">пройти идентификацию</a>.
145+
t_hidden_images = Скрытые изображения
145146
t_image_id = ID изображения
146147
t_add_image = Добавить изображение
147148
t_replace_image = Заменить изображение

src/main/resources/sql/image_dao_queries.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ series_image.find_by_series_id = \
1515
SELECT image_id \
1616
FROM series_images \
1717
WHERE series_id = :series_id \
18-
AND hidden = FALSE
18+
AND hidden = :hidden
1919

2020
image_data.find_by_image_id = \
2121
SELECT d.content AS data \

src/main/webapp/WEB-INF/views/series/info.html

+23-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,29 @@
167167
</form>
168168
</div>
169169
</div>
170-
170+
171+
<!--/* @todo #1356 Hidden images: add integration tests */-->
172+
<!--/* @todo #1356 Hidden images: allow to replace a hidden image */-->
173+
<!--/* @todo #1356 Hidden images: admin can hide an image */-->
174+
<!--/* @todo #1356 Hidden images: protect hidden images from direct access */-->
175+
<div class="row" th:if="${not #lists.isEmpty(series.hiddenImageIds)}" th:each="imageId,iter : ${series.hiddenImageIds}">
176+
<div class="col-sm-12">
177+
<h5 th:text="#{t_hidden_images}">Hidden images</h5>
178+
<a id="series-hidden-image-link-1"
179+
target="_blank"
180+
href="../../../../resources/test/test.png"
181+
th:id="|series-hidden-image-link-${iter.count}|"
182+
th:href="@{${GET_IMAGE_PAGE}(id=${imageId})}">
183+
184+
<img class="img-responsive series-images"
185+
id="series-hidden-image-1"
186+
src="../../../../resources/test/test.png"
187+
th:id="|series-hidden-image-${iter.count}|"
188+
th:src="@{${GET_IMAGE_PREVIEW_PAGE}(id=${imageId})}" />
189+
</a>
190+
</div>
191+
</div>
192+
171193
</div>
172194

173195
<div class="col-sm-4">

src/test/groovy/ru/mystamps/web/feature/image/ImageServiceImplTest.groovy

+8-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*/
1818
package ru.mystamps.web.feature.image
1919

20+
import static io.qala.datagen.RandomShortApi.bool
21+
2022
import org.slf4j.helpers.NOPLogger
2123
import org.springframework.web.multipart.MultipartFile
2224
import ru.mystamps.web.feature.image.ImageDb.Images
@@ -370,7 +372,7 @@ class ImageServiceImplTest extends Specification {
370372

371373
def "findBySeriesId() should throw exception when series id is null"() {
372374
when:
373-
service.findBySeriesId(null)
375+
service.findBySeriesId(null, bool())
374376
then:
375377
IllegalArgumentException ex = thrown()
376378
ex.message == 'Series id must be non null'
@@ -380,14 +382,18 @@ class ImageServiceImplTest extends Specification {
380382
def "findBySeriesId() should invoke dao, pass argument and return result from dao"() {
381383
given:
382384
Integer expectedSeriesId = 14
385+
boolean expectedHidden = bool()
383386
and:
384387
List<Integer> expectedResult = [ 1, 2 ]
385388
when:
386-
List<Integer> result = service.findBySeriesId(expectedSeriesId)
389+
List<Integer> result = service.findBySeriesId(expectedSeriesId, expectedHidden)
387390
then:
388391
1 * imageDao.findBySeriesId({ Integer seriesId ->
389392
assert seriesId == expectedSeriesId
390393
return true
394+
}, { boolean hidden ->
395+
assert hidden == expectedHidden
396+
return true
391397
}) >> expectedResult
392398
and:
393399
result == expectedResult

src/test/groovy/ru/mystamps/web/feature/series/SeriesServiceImplTest.groovy

+4-4
Original file line numberDiff line numberDiff line change
@@ -691,14 +691,14 @@ class SeriesServiceImplTest extends Specification {
691691

692692
def "findFullInfoById() should throw exception when series id is null"() {
693693
when:
694-
service.findFullInfoById(null, null)
694+
service.findFullInfoById(null, null, bool())
695695
then:
696696
thrown(IllegalArgumentException)
697697
}
698698

699699
def "findFullInfoById() should return null when series not found"() {
700700
when:
701-
SeriesDto result = service.findFullInfoById(Random.id(), Random.lang())
701+
SeriesDto result = service.findFullInfoById(Random.id(), Random.lang(), bool())
702702
then:
703703
1 * seriesDao.findByIdAsSeriesFullInfo(_ as Integer, _ as String)
704704
and:
@@ -725,7 +725,7 @@ class SeriesServiceImplTest extends Specification {
725725
List<String> expectedSolovyovNumbers = Random.solovyovNumbers().toList()
726726
List<Integer> expectedImageIds = Random.listOfIntegers()
727727
when:
728-
SeriesDto result = service.findFullInfoById(expectedSeriesId, expectedLang)
728+
SeriesDto result = service.findFullInfoById(expectedSeriesId, expectedLang, false)
729729
then:
730730
1 * seriesDao.findByIdAsSeriesFullInfo(expectedSeriesId, expectedLang) >> expectedInfo
731731
and:
@@ -741,7 +741,7 @@ class SeriesServiceImplTest extends Specification {
741741
and:
742742
1 * zagorskiCatalogService.findBySeriesId(expectedSeriesId) >> expectedZagorskiNumbers
743743
and:
744-
1 * imageService.findBySeriesId(expectedSeriesId) >> expectedImageIds
744+
1 * imageService.findBySeriesId(expectedSeriesId, false) >> expectedImageIds
745745
and:
746746
result != null
747747
result.id == expectedInfo.id

0 commit comments

Comments
 (0)