Skip to content

Commit

Permalink
[Backport 4.2.x] Register user / allow to select the group where the …
Browse files Browse the repository at this point in the history
…user wants to register (#8195)

* Register user / allow to select the group where the user wants to register (#8176)

* Register user / allow to select the group that wishes to register

* Register user / API integration tests

* Update web/src/main/webapp/WEB-INF/classes/org/fao/geonet/api/Messages.properties

Co-authored-by: Jody Garnett <[email protected]>

* Update web/src/main/webapp/WEB-INF/classes/org/fao/geonet/api/Messages_fre.properties

Co-authored-by: Jody Garnett <[email protected]>

* Update core/src/test/resources/org/fao/geonet/api/Messages.properties

Co-authored-by: Jody Garnett <[email protected]>

* Update core/src/test/resources/org/fao/geonet/api/Messages_fre.properties

Co-authored-by: Jody Garnett <[email protected]>

* Register user / disable group selection for profile Administrator

* Register user / form improvements

* Register user / surname not required

* Register user / Update new account text

* Update core/src/test/resources/org/fao/geonet/api/Messages_fre.properties

Co-authored-by: François Prunayre <[email protected]>

---------

Co-authored-by: Jody Garnett <[email protected]>
Co-authored-by: François Prunayre <[email protected]>

* Update core/src/test/resources/org/fao/geonet/api/Messages_fre.properties

* Update web/src/main/webapp/WEB-INF/classes/org/fao/geonet/api/Messages_fre.properties

---------

Co-authored-by: Jody Garnett <[email protected]>
Co-authored-by: François Prunayre <[email protected]>
  • Loading branch information
3 people authored Jun 19, 2024
1 parent ab1b5a9 commit 9e5995a
Show file tree
Hide file tree
Showing 13 changed files with 448 additions and 61 deletions.
19 changes: 19 additions & 0 deletions core/src/test/resources/org/fao/geonet/api/Messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ register_email_admin_message=Dear Admin,\n\
Newly registered user %s has requested %s access for %s.\n\
Yours sincerely,\n\
The %s team.
register_email_group_admin_message=Dear Admin,\n\
Newly registered user %s has requested %s access in group %s for %s.\n\
Yours sincerely,\n\
The %s team.
register_email_subject=%s / Your account as %s
register_email_message=Dear User,\n\
Your registration at %s was successful.\n\
Expand All @@ -77,6 +81,21 @@ register_email_message=Dear User,\n\
\n\
Yours sincerely,\n\
The %s team.
register_email_group_message=Dear User,\n\
Your registration at %s was successful.\n\
Your account is: \n\
* username: %s\n\
* password: %s\n\
* profile: %s\n\
\n\
We have sent your request for %s to the group %s administrator. You will be contacted shortly.\n\
To log in and access your account, please click on the link below.\n\
%s\n\
\n\
Thanks for your registration.\n\
\n\
Yours sincerely,\n\
The %s team.
new_user_rating=%s / New user rating on %s
new_user_rating_text=See record %s
user_feedback_title=%s / User feedback on %s / %s
Expand Down
16 changes: 16 additions & 0 deletions core/src/test/resources/org/fao/geonet/api/Messages_fre.properties
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ register_email_admin_message=Cher administrateur,\n\
L'utilisateur %s vient de demander une cr\u00E9ation de compte pour %s.\n\
Salutation,\n\
L'\u00E9quipe %s.
register_email_group_admin_message=Cher administrateur,\n\
L'utilisateur %s vient de demander une cr\u00E9ation de compte pour %s en groupe %s.\n\
Salutation,\n\
L'\u00E9quipe %s.
register_email_subject=%s / Votre compte %s
register_email_message=Cher utilisateur,\n\
Votre compte a \u00E9t\u00E9 cr\u00E9\u00E9 avec succ\u00E9s pour %s.\n\
Expand All @@ -65,6 +69,18 @@ register_email_message=Cher utilisateur,\n\
\n\
Salutations,\n\
L'\u00E9quipe %s.
register_email_group_message=Cher utilisateur,\n\
Votre compte a \u00E9t\u00E9 cr\u00E9\u00E9 avec succ\u00E9s pour %s.\n\
* Nom d'utilisateur : %s\n\
* Mot de passe : %s\n\
* Profil : %s\n\
\n\
Nous avons envoy\u00E9 votre demande de %s \u00E0 l'administrateur du groupe %s. Vous serez contact\u00E9 rapidement.\n\
Vous pouvez d\u00E9s \u00E0 pr\u00E9sent vous connecter.\n\
%s\n\
\n\
Salutations,\n\
L'\u00E9quipe %s.
new_user_rating=%s / Nouvelle \u00E9valuation faite pour %s
new_user_rating_text=Consulter la fiche %s
user_feedback_title=%s / Nouveau commentaire sur %s / %s
Expand Down
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 @@ -11,9 +11,12 @@ Click the `Create an account` button and fill out the registration form:
The fields in this form are self-explanatory except for the following:

- **Email**: The user's email address. This is mandatory and will be used as the username.
- **Profile**: By default, self-registered users are given the `Registered User` profile (see previous section). If any other profile is selected:
- **Requested profile**: By default, self-registered users are given the `Registered User` profile (see previous section). If any other profile is selected:
- the user will still be given the `Registered User` profile
- an email will be sent to the Email address nominated in the Feedback section of the 'System Administration' menu, informing them of the request for a more privileged profile
- **Requested group**: By default, self-registered users are not assigned to any group. If a group is selected:
- the user will still not be assigned to any group
- an email will be sent to the Email address nominated in the Feedback section of the 'System Administration' menu, informing them of the requested group.

## What happens when a user self-registers?

Expand Down
19 changes: 19 additions & 0 deletions services/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@
<scope>test</scope>
</dependency>


<dependency>
<groupId>org.jvnet.mock-javamail</groupId>
<artifactId>mock-javamail</artifactId>
<version>1.9</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
Expand Down Expand Up @@ -386,6 +394,17 @@
</execution>
</executions>
</plugin>

<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<mail.smtp.class>org.jvnet.mock_javamail.MockTransport</mail.smtp.class>
<mail.pop3.class>org.jvnet.mock_javamail.MockStore</mail.pop3.class>
<mail.imap.class>org.jvnet.mock_javamail.MockStore</mail.imap.class>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
Expand Down
151 changes: 106 additions & 45 deletions services/src/main/java/org/fao/geonet/api/users/RegisterApi.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//=============================================================================
//=== Copyright (C) 2001-2021 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 All @@ -26,7 +26,6 @@
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jeeves.server.context.ServiceContext;
import org.fao.geonet.api.API;
import org.fao.geonet.api.ApiUtils;
import org.fao.geonet.api.tools.i18n.LanguageUtils;
import org.fao.geonet.api.users.model.UserRegisterDto;
Expand All @@ -45,17 +44,14 @@
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import javax.servlet.http.HttpServletRequest;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.*;

@EnableWebMvc
@Service
Expand All @@ -72,12 +68,20 @@ public class RegisterApi {
@Autowired(required=false)
SecurityProviderConfiguration securityProviderConfiguration;

@Autowired
GroupRepository groupRepository;

@Autowired
UserGroupRepository userGroupRepository;

@Autowired
SettingManager settingManager;

@io.swagger.v3.oas.annotations.Operation(summary = "Create user account",
description = "User is created with a registered user profile. username field is ignored and the email is used as " +
"username. Password is sent by email. Catalog administrator is also notified.")
@RequestMapping(
@PutMapping(
value = "/actions/register",
method = RequestMethod.PUT,
produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseStatus(value = HttpStatus.CREATED)
@ResponseBody
Expand All @@ -101,19 +105,18 @@ public ResponseEntity<String> registerUser(

ServiceContext context = ApiUtils.createServiceContext(request);

SettingManager sm = context.getBean(SettingManager.class);
boolean selfRegistrationEnabled = sm.getValueAsBool(Settings.SYSTEM_USERSELFREGISTRATION_ENABLE);
boolean selfRegistrationEnabled = settingManager.getValueAsBool(Settings.SYSTEM_USERSELFREGISTRATION_ENABLE);
if (!selfRegistrationEnabled) {
return new ResponseEntity<>(String.format(
messages.getString("self_registration_disabled")
), HttpStatus.PRECONDITION_FAILED);
}

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

if (recaptchaEnabled) {
boolean validRecaptcha = RecaptchaChecker.verify(userRegisterDto.getCaptcha(),
sm.getValue(Settings.SYSTEM_USERSELFREGISTRATION_RECAPTCHA_SECRETKEY));
settingManager.getValue(Settings.SYSTEM_USERSELFREGISTRATION_RECAPTCHA_SECRETKEY));
if (!validRecaptcha) {
return new ResponseEntity<>(
messages.getString("recaptcha_not_valid"), HttpStatus.PRECONDITION_FAILED);
Expand Down Expand Up @@ -144,7 +147,7 @@ public ResponseEntity<String> registerUser(
), HttpStatus.PRECONDITION_FAILED);
}

if (userRepository.findByUsernameIgnoreCase(userRegisterDto.getEmail()).size() != 0) {
if (!userRepository.findByUsernameIgnoreCase(userRegisterDto.getEmail()).isEmpty()) {
// username is ignored and the email is used as username in selfregister
return new ResponseEntity<>(String.format(
messages.getString("user_with_that_username_found"),
Expand All @@ -153,16 +156,13 @@ public ResponseEntity<String> registerUser(
}

User user = new User();

// user.setUsername(userRegisterDto.getUsername());
user.setName(userRegisterDto.getName());
user.setSurname(userRegisterDto.getSurname());
user.setOrganisation(userRegisterDto.getOrganisation());
user.setProfile(Profile.findProfileIgnoreCase(userRegisterDto.getProfile()));
user.getAddresses().add(userRegisterDto.getAddress());
user.getEmailAddresses().add(userRegisterDto.getEmail());


String password = User.getRandomPassword();
user.getSecurity().setPassword(
PasswordUtil.encode(context, password)
Expand All @@ -172,48 +172,78 @@ public ResponseEntity<String> registerUser(
user.setProfile(Profile.RegisteredUser);
user = userRepository.save(user);

Group targetGroup = getGroup(context);
Group targetGroup = getGroup();

if (targetGroup != null) {
UserGroup userGroup = new UserGroup().setUser(user).setGroup(targetGroup).setProfile(Profile.RegisteredUser);
context.getBean(UserGroupRepository.class).save(userGroup);
userGroupRepository.save(userGroup);
}


String catalogAdminEmail = sm.getValue(Settings.SYSTEM_FEEDBACK_EMAIL);
String catalogAdminEmail = settingManager.getValue(Settings.SYSTEM_FEEDBACK_EMAIL);
String subject = String.format(
messages.getString("register_email_admin_subject"),
sm.getSiteName(),
settingManager.getSiteName(),
user.getEmail(),
requestedProfile
);
String message = String.format(
messages.getString("register_email_admin_message"),
user.getEmail(),
requestedProfile,
sm.getNodeURL(),
sm.getSiteName()
);
if (!MailUtil.sendMail(catalogAdminEmail, subject, message, null, sm)) {
Group requestedGroup = getRequestedGroup(userRegisterDto.getGroup());
String message;
if (requestedGroup != null) {
message = String.format(
messages.getString("register_email_group_admin_message"),
user.getEmail(),
requestedProfile,
requestedGroup.getLabelTranslations().get(context.getLanguage()),
settingManager.getNodeURL(),
settingManager.getSiteName()
);
} else {
message = String.format(
messages.getString("register_email_admin_message"),
user.getEmail(),
requestedProfile,
settingManager.getNodeURL(),
settingManager.getSiteName()
);

}

if (Boolean.FALSE.equals(MailUtil.sendMail(catalogAdminEmail, subject, message, null, settingManager))) {
return new ResponseEntity<>(String.format(
messages.getString("mail_error")), HttpStatus.PRECONDITION_FAILED);
}

subject = String.format(
messages.getString("register_email_subject"),
sm.getSiteName(),
settingManager.getSiteName(),
user.getProfile()
);
message = String.format(
messages.getString("register_email_message"),
sm.getSiteName(),
user.getUsername(),
password,
Profile.RegisteredUser,
requestedProfile,
sm.getNodeURL(),
sm.getSiteName()
);
if (!MailUtil.sendMail(user.getEmail(), subject, message, null, sm)) {
if (requestedGroup != null) {
message = String.format(
messages.getString("register_email_group_message"),
settingManager.getSiteName(),
user.getUsername(),
password,
Profile.RegisteredUser,
requestedProfile,
requestedGroup.getLabelTranslations().get(context.getLanguage()),
settingManager.getNodeURL(),
settingManager.getSiteName()
);
} else {
message = String.format(
messages.getString("register_email_message"),
settingManager.getSiteName(),
user.getUsername(),
password,
Profile.RegisteredUser,
requestedProfile,
settingManager.getNodeURL(),
settingManager.getSiteName()
);
}

if (Boolean.FALSE.equals(MailUtil.sendMail(user.getEmail(), subject, message, null, settingManager))) {
return new ResponseEntity<>(String.format(
messages.getString("mail_error")), HttpStatus.PRECONDITION_FAILED);
}
Expand All @@ -224,8 +254,39 @@ public ResponseEntity<String> registerUser(
), HttpStatus.CREATED);
}

Group getGroup(ServiceContext context) throws SQLException {
final GroupRepository bean = context.getBean(GroupRepository.class);
return bean.findById(ReservedGroup.guest.getId()).get();
/**
* Returns the group (GUEST) to assign to the registered user.
*
* @return
*/
private Group getGroup() {
Optional<Group> targetGroupOpt = groupRepository.findById(ReservedGroup.guest.getId());

if (targetGroupOpt.isPresent()) {
return targetGroupOpt.get();
}

return null;
}

/**
* Returns the group requested by the registered user.
*
* @param requestedGroup Requested group identifier for the user.
* @return
*/
private Group getRequestedGroup(String requestedGroup) {
Group targetGroup = null;

if (StringUtils.hasLength(requestedGroup)) {
Optional<Group> targetGroupOpt = groupRepository.findById(Integer.parseInt(requestedGroup));

// Don't allow reserved groups
if (targetGroupOpt.isPresent() && !targetGroupOpt.get().isReserved()) {
targetGroup = targetGroupOpt.get();
}
}

return targetGroup;
}
}
Loading

0 comments on commit 9e5995a

Please sign in to comment.