Skip to content

Commit 2fe2821

Browse files
authored
Validate language parameter in API services (geonetwork#6673)
* Validate formatters language parameter * Add LanguageUtils tests * Update Pages API to validate the language * Formatters API - accept value 'all' for language parameter
1 parent 67d7831 commit 2fe2821

File tree

4 files changed

+131
-5
lines changed

4 files changed

+131
-5
lines changed

services/src/main/java/org/fao/geonet/api/pages/PagesAPI.java

+22
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.fao.geonet.api.exception.ResourceAlreadyExistException;
3737
import org.fao.geonet.api.exception.ResourceNotFoundException;
3838
import org.fao.geonet.api.exception.WebApplicationException;
39+
import org.fao.geonet.api.tools.i18n.LanguageUtils;
3940
import org.fao.geonet.domain.Profile;
4041
import org.fao.geonet.domain.page.Page;
4142
import org.fao.geonet.domain.page.PageIdentity;
@@ -56,6 +57,7 @@
5657
import java.io.UnsupportedEncodingException;
5758
import java.nio.charset.StandardCharsets;
5859
import java.util.ArrayList;
60+
import java.util.Arrays;
5961
import java.util.List;
6062

6163
@RequestMapping(value = {"/{portal}/api/pages"})
@@ -75,6 +77,9 @@ public class PagesAPI {
7577
@Autowired
7678
private PageRepository pageRepository;
7779

80+
@Autowired
81+
private LanguageUtils languageUtils;
82+
7883
@io.swagger.v3.oas.annotations.Operation(
7984
summary = "Add a new Page object in DRAFT section in status HIDDEN",
8085
description = "<p>Is not possible to load a link and a file at the same time.</p> <a href='http://geonetwork-opensource.org/manuals/4.0.x/eng/users/user-guide/define-static-pages/define-pages.html'>More info</a>")
@@ -98,6 +103,7 @@ public void addPage(
98103
@RequestParam(value = "format", required = true) final Page.PageFormat format,
99104
@Parameter(hidden = true) final HttpServletResponse response) throws ResourceAlreadyExistException {
100105

106+
checkValidLanguage(language);
101107

102108
checkMandatoryContent(data, link);
103109

@@ -141,6 +147,9 @@ public ResponseEntity editPage(
141147
@RequestParam(value = "link", required = false) final String link,
142148
@RequestParam(value = "format", required = true) final Page.PageFormat format
143149
) throws ResourceNotFoundException {
150+
151+
checkValidLanguage(language);
152+
144153
checkUniqueContent(data, link);
145154

146155
checkCorrectFormat(data, link, format);
@@ -174,6 +183,10 @@ public void editPageName(
174183
@RequestParam(value = "newPageId", required = false) final String newPageId,
175184
@Parameter(hidden = true) final HttpServletResponse response) throws ResourceNotFoundException, ResourceAlreadyExistException {
176185

186+
checkValidLanguage(language);
187+
188+
checkValidLanguage(newLanguage);
189+
177190
final Page page = pageRepository.findById(new PageIdentity(language, pageId)).get();
178191

179192
if (page == null) {
@@ -501,6 +514,15 @@ private void checkFileType(final MultipartFile data) {
501514
}
502515
}
503516

517+
private void checkValidLanguage(String language) {
518+
if (!languageUtils.getUiLanguages().contains(language)) {
519+
throw new IllegalArgumentException(
520+
String.format("Language value is not valid: %s. A valid application language is mandatory: %s.",
521+
language,
522+
String.join(",", languageUtils.getUiLanguages())));
523+
}
524+
}
525+
504526
/**
505527
* Check permissions on single page and return.
506528
*

services/src/main/java/org/fao/geonet/api/records/formatters/FormatterApi.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@
108108
public class FormatterApi extends AbstractFormatService implements ApplicationListener {
109109
private static final Set<String> ALLOWED_PARAMETERS = Sets.newHashSet("id", "uuid", "xsl", "skippopularity", "hide_withheld");
110110

111+
private static final String PARAM_LANGUAGE_ALL_VALUES = "all";
112+
111113
@Autowired
112114
LanguageUtils languageUtils;
113115

@@ -243,9 +245,17 @@ public void getRecordFormattedBy(
243245
formatType = FormatType.xml;
244246
}
245247

246-
String language = isoLanguagesMapper.iso639_2T_to_iso639_2B(locale.getISO3Language());
248+
String language;
247249
if (StringUtils.isNotEmpty(iso3lang)) {
248-
language = isoLanguagesMapper.iso639_2T_to_iso639_2B(iso3lang);
250+
if (PARAM_LANGUAGE_ALL_VALUES.equalsIgnoreCase(iso3lang)) {
251+
language = iso3lang;
252+
} else if (languageUtils.getUiLanguages().contains(iso3lang)) {
253+
language = isoLanguagesMapper.iso639_2T_to_iso639_2B(iso3lang);
254+
} else {
255+
language = languageUtils.getDefaultUiLanguage();
256+
}
257+
} else {
258+
language = isoLanguagesMapper.iso639_2T_to_iso639_2B(locale.getISO3Language());
249259
}
250260

251261
AbstractMetadata metadata = ApiUtils.canViewRecord(metadataUuid, servletRequest);

services/src/main/java/org/fao/geonet/api/tools/i18n/LanguageUtils.java

+23-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
* Created by francois on 05/02/16.
3232
*/
3333
public class LanguageUtils {
34+
/* The languages in the UI */
3435
private final Set<String> iso3code;
36+
/* The default application language */
3537
private final String defaultLanguage;
3638
Collection<Locale> locales = new ArrayList<>();
3739

@@ -70,9 +72,27 @@ public String getIso3langCode(Enumeration<Locale> locales) {
7072
}
7173

7274
public Locale parseAcceptLanguage(final Locale locale) {
73-
Vector<Locale> locales = new Vector<>();
74-
locales.add(locale);
75+
List<Locale> localesToParse = Collections.singletonList(locale);
7576

76-
return parseAcceptLanguage(locales.elements());
77+
return parseAcceptLanguage(Collections.enumeration(localesToParse));
78+
}
79+
80+
81+
/**
82+
* Get the default application iso3 code language.
83+
*
84+
* @return
85+
*/
86+
public String getDefaultUiLanguage() {
87+
return defaultLanguage;
88+
}
89+
90+
/**
91+
* Get the UI iso3 code languages.
92+
*
93+
* @return
94+
*/
95+
public Set<String> getUiLanguages() {
96+
return iso3code;
7797
}
7898
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright (C) 2001-2022 Food and Agriculture Organization of the
3+
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
4+
* and United Nations Environment Programme (UNEP)
5+
*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation; either version 2 of the License, or (at
9+
* your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful, but
12+
* WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program; if not, write to the Free Software
18+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19+
*
20+
* Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
21+
* Rome - Italy. email: [email protected]
22+
*/
23+
package org.fao.geonet.api.tools.i18n;
24+
25+
import org.fao.geonet.languages.IsoLanguagesMapper;
26+
import org.junit.Assert;
27+
import org.junit.Before;
28+
import org.junit.Test;
29+
import org.springframework.beans.factory.annotation.Autowired;
30+
31+
import java.util.HashSet;
32+
import java.util.Locale;
33+
import java.util.Set;
34+
import java.util.stream.Collectors;
35+
import java.util.stream.Stream;
36+
37+
public class LanguageUtilsTest {
38+
LanguageUtils languageUtils;
39+
40+
@Before
41+
public void setUp() throws Exception {
42+
Set<String> localesToLoad = Stream.of("dut", "ger", "eng", "fre")
43+
.collect(Collectors.toCollection(HashSet::new));
44+
45+
languageUtils = new LanguageUtils(localesToLoad, "eng");
46+
}
47+
48+
@Test
49+
public void getDefaultLanguage() throws Exception {
50+
Assert.assertEquals("eng", languageUtils.getDefaultUiLanguage());
51+
}
52+
53+
@Test
54+
public void getUiLanguages() throws Exception {
55+
Assert.assertEquals(4, languageUtils.getUiLanguages().size());
56+
}
57+
58+
@Test
59+
public void parseAcceptLanguage() throws Exception {
60+
Set<String> localesToLoad = Stream.of("dut", "ger", "eng", "fre")
61+
.collect(Collectors.toCollection(HashSet::new));
62+
63+
LanguageUtils languageUtils = new LanguageUtils(localesToLoad, "eng");
64+
65+
Locale gerLocale = new Locale("de");
66+
String iso3lang = languageUtils.parseAcceptLanguage(gerLocale).getISO3Language();
67+
Assert.assertEquals("ger", IsoLanguagesMapper.iso639_2T_to_iso639_2B(iso3lang));
68+
69+
// Get default language as not in the list of supported locales
70+
Locale spaLocale = new Locale("es");
71+
iso3lang = languageUtils.parseAcceptLanguage(spaLocale).getISO3Language();
72+
Assert.assertEquals("eng", IsoLanguagesMapper.iso639_2T_to_iso639_2B(iso3lang));
73+
}
74+
}

0 commit comments

Comments
 (0)