Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix user application feedback #7769

Merged
merged 5 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,18 @@ See [Configuring Shibboleth](../managing-users-and-groups/authentication-mode.md

Enable the self registration form. See [User Self-Registration](../managing-users-and-groups/user-self-registration.md).

You can configure optionally re-Captcha, to protect you and your users from spam and abuse. And a list of email domains (separated by commas)
You can configure optionally re-Captcha, to protect you and your users from spam and abuse. And a list of email domains (separated by commas)
that can request an account. If not configured any email address is allowed.

## system/userFeedback
## User application feedback

!!! warning "Deprecated"
Enabling the setting, displays in the application footer a link to a page that allows sending comments about the application.

![](img/application-feedback-link.png)

3.0.0
![](img/application-feedback.png)

It requires an email server configured.

## Link in metadata records

Expand Down
135 changes: 98 additions & 37 deletions services/src/main/java/org/fao/geonet/api/site/SiteApi.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2001-2023 Food and Agriculture Organization of the
* Copyright (C) 2001-2024 Food and Agriculture Organization of the
* United Nations (FAO-UN), United Nations World Food Programme (WFP)
* and United Nations Environment Programme (UNEP)
*
Expand Down Expand Up @@ -36,17 +36,16 @@
import jeeves.server.context.ServiceContext;
import jeeves.xlink.Processor;
import org.apache.commons.lang3.StringUtils;
import org.fao.geonet.ApplicationContextHolder;
import org.fao.geonet.GeonetContext;
import org.fao.geonet.NodeInfo;
import org.fao.geonet.SystemInfo;
import org.fao.geonet.*;
import org.fao.geonet.api.ApiParams;
import org.fao.geonet.api.ApiUtils;
import org.fao.geonet.api.OpenApiConfig;
import org.fao.geonet.api.exception.FeatureNotEnabledException;
import org.fao.geonet.api.exception.NotAllowedException;
import org.fao.geonet.api.site.model.SettingSet;
import org.fao.geonet.api.site.model.SettingsListResponse;
import org.fao.geonet.api.tools.i18n.LanguageUtils;
import org.fao.geonet.api.users.recaptcha.RecaptchaChecker;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.doi.client.DoiManager;
import org.fao.geonet.domain.*;
Expand All @@ -69,6 +68,7 @@
import org.fao.geonet.repository.*;
import org.fao.geonet.repository.specification.MetadataSpecs;
import org.fao.geonet.resources.Resources;
import org.fao.geonet.util.MailUtil;
import org.fao.geonet.utils.FilePathChecker;
import org.fao.geonet.utils.Log;
import org.fao.geonet.utils.ProxyInfo;
Expand All @@ -78,15 +78,10 @@
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
Expand All @@ -100,19 +95,12 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Optional;
import java.util.TimeZone;
import java.util.*;

import static org.apache.commons.fileupload.util.Streams.checkFileName;
import static org.fao.geonet.api.ApiParams.API_CLASS_CATALOG_TAG;
import static org.fao.geonet.constants.Geonet.Path.IMPORT_STYLESHEETS_SCHEMA_PREFIX;
import static org.fao.geonet.kernel.setting.Settings.SYSTEM_FEEDBACK_EMAIL;

/**
*
Expand Down Expand Up @@ -201,7 +189,7 @@ public static void reloadServices(ServiceContext context) throws Exception {
@ResponseBody
public SettingsListResponse getSiteOrPortalDescription(
@Parameter(hidden = true)
HttpServletRequest request
HttpServletRequest request
) throws Exception {
SettingsListResponse response = new SettingsListResponse();
response.setSettings(settingManager.getSettings(new String[]{
Expand Down Expand Up @@ -267,19 +255,19 @@ public SettingsListResponse getSettingsSet(
@RequestParam(
required = false
)
SettingSet[] set,
SettingSet[] set,
@Parameter(
description = "Setting key",
required = false
)
@RequestParam(
required = false
)
String[] key,
String[] key,
@Parameter(
hidden = true
)
HttpSession httpSession
HttpSession httpSession
) throws Exception {
ConfigurableApplicationContext appContext = ApplicationContextHolder.get();
UserSession session = ApiUtils.getUserSession(httpSession);
Expand Down Expand Up @@ -353,17 +341,17 @@ public List<Setting> getSettingsDetails(
@RequestParam(
required = false
)
SettingSet[] set,
SettingSet[] set,
@Parameter(
description = "Setting key",
required = false
)
@RequestParam(
required = false
)
String[] key,
String[] key,
@Parameter(hidden = true)
HttpSession httpSession
HttpSession httpSession
) throws Exception {
UserSession session = ApiUtils.getUserSession(httpSession);
Profile profile = session == null ? null : session.getProfile();
Expand Down Expand Up @@ -415,7 +403,7 @@ public List<Setting> getSettingsDetails(
public void saveSettings(
@Parameter(hidden = false)
@RequestParam
Map<String, String> allRequestParams,
Map<String, String> allRequestParams,
HttpServletRequest request
) throws Exception {
ApplicationContext applicationContext = ApplicationContextHolder.get();
Expand Down Expand Up @@ -450,7 +438,7 @@ public void saveSettings(
// Update the system default timezone. If the setting is blank use the timezone user.timezone property from command line or
// TZ environment variable
String zoneId = StringUtils.defaultIfBlank(settingManager.getValue(Settings.SYSTEM_SERVER_TIMEZONE, true),
SettingManager.DEFAULT_SERVER_TIMEZONE.getId());
SettingManager.DEFAULT_SERVER_TIMEZONE.getId());
TimeZone.setDefault(TimeZone.getTimeZone(zoneId));


Expand Down Expand Up @@ -534,7 +522,7 @@ public boolean isCasEnabled(
@PreAuthorize("hasAuthority('Administrator')")
public void updateStagingProfile(
@PathVariable
SystemInfo.Staging profile) {
SystemInfo.Staging profile) {
this.info.setStagingProfile(profile.toString());
}

Expand Down Expand Up @@ -582,22 +570,22 @@ public HttpEntity indexSite(
@Parameter(description = "Drop and recreate index",
required = false)
@RequestParam(required = false, defaultValue = "true")
boolean reset,
boolean reset,
@Parameter(description = "Asynchronous mode (only on all records. ie. no selection bucket)",
required = false)
@RequestParam(required = false, defaultValue = "false")
boolean asynchronous,
boolean asynchronous,
@Parameter(description = "Index. By default only remove record index.",
required = false)
@RequestParam(required = false, defaultValue = "records")
String[] indices,
String[] indices,
@Parameter(
description = ApiParams.API_PARAM_BUCKET_NAME,
required = false)
@RequestParam(
required = false
)
String bucket,
String bucket,
HttpServletRequest request
) throws Exception {
ServiceContext context = ApiUtils.createServiceContext(request);
Expand Down Expand Up @@ -779,7 +767,7 @@ public ProxyConfiguration getProxyConfiguration(
public void setLogo(
@Parameter(description = "Logo to use for the catalog")
@RequestParam("file")
String file,
String file,
@Parameter(
description = "Create favicon too",
required = false
Expand All @@ -788,7 +776,7 @@ public void setLogo(
defaultValue = "false",
required = false
)
boolean asFavicon,
boolean asFavicon,
HttpServletRequest request

) throws Exception {
Expand Down Expand Up @@ -901,4 +889,77 @@ public List<String> getXslTransformations(
return list;
}
}


@io.swagger.v3.oas.annotations.Operation(
summary = "Send an email to catalogue administrator with feedback about the application",
description = "")
@PostMapping(
value = "/userfeedback",
produces = MediaType.APPLICATION_JSON_VALUE
)
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public ResponseEntity<String> sendApplicationUserFeedback(
@Parameter(
description = "Recaptcha validation key."
)
@RequestParam(required = false, defaultValue = "") final String recaptcha,
@Parameter(
description = "User name.",
required = true
)
@RequestParam final String name,
@Parameter(
description = "User organisation.",
required = true
)
@RequestParam final String org,
@Parameter(
description = "User email address.",
required = true
)
@RequestParam final String email,
@Parameter(
description = "A comment or question.",
required = true
)
@RequestParam final String comments,
@Parameter(hidden = true) final HttpServletRequest request
) throws Exception {
Locale locale = languageUtils.parseAcceptLanguage(request.getLocales());
ResourceBundle messages = ResourceBundle.getBundle("org.fao.geonet.api.Messages", locale);

boolean feedbackEnabled = settingManager.getValueAsBool(Settings.SYSTEM_USERFEEDBACK_ENABLE, false);
if (!feedbackEnabled) {
throw new FeatureNotEnabledException(
"Application feedback is not enabled.")
.withMessageKey("exception.resourceNotEnabled.applicationFeedback")
.withDescriptionKey("exception.resourceNotEnabled.applicationFeedback.description");
}

boolean recaptchaEnabled = settingManager.getValueAsBool(Settings.SYSTEM_USERSELFREGISTRATION_RECAPTCHA_ENABLE);

if (recaptchaEnabled) {
boolean validRecaptcha = RecaptchaChecker.verify(recaptcha,
settingManager.getValue(Settings.SYSTEM_USERSELFREGISTRATION_RECAPTCHA_SECRETKEY));
if (!validRecaptcha) {
return new ResponseEntity<>(
messages.getString("recaptcha_not_valid"), HttpStatus.PRECONDITION_FAILED);
}
}

String to = settingManager.getValue(SYSTEM_FEEDBACK_EMAIL);

Set<String> toAddress = new HashSet<>();
toAddress.add(to);

MailUtil.sendMail(new ArrayList<>(toAddress),
messages.getString("site_user_feedback_title"),
String.format(
messages.getString("site_user_feedback_text"),
name, email, org, comments),
settingManager);
return new ResponseEntity<>(HttpStatus.CREATED);
}
}
Loading
Loading