Commit cce25633 authored by Maxym Borodenko's avatar Maxym Borodenko Committed by Matija Obreza
Browse files

User registration API

- Added Unit tests
parent 9878b545
/*
* Copyright 2018 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.genesys2.server.api.v1;
import javax.servlet.http.HttpServletRequest;
import com.fasterxml.jackson.annotation.JsonView;
import io.swagger.annotations.Api;
import org.apache.commons.validator.routines.EmailValidator;
import org.genesys.blocks.model.JsonViews;
import org.genesys.blocks.security.NotUniqueUserException;
import org.genesys.blocks.security.UserException;
import org.genesys.blocks.security.model.BasicUser;
import org.genesys.blocks.security.service.PasswordPolicy.PasswordPolicyException;
import org.genesys2.server.api.ApiBaseController;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.EMailVerificationService;
import org.genesys2.server.service.TokenVerificationService.NoSuchVerificationTokenException;
import org.genesys2.server.service.TokenVerificationService.TokenExpiredException;
import org.genesys2.server.service.UserService;
import org.genesys2.util.ReCaptchaUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
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.RestController;
/**
* @author Maxym Borodenko
*/
@RestController("userRegistrationApi1")
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = { UserRegistrationController.API_BASE })
@Api(tags = { "user-registration" })
public class UserRegistrationController {
/** The Constant LOG. */
private static final Logger LOG = LoggerFactory.getLogger(UserRegistrationController.class);
/** The Constant API_BASE. */
public static final String API_BASE = ApiBaseController.APIv1_BASE + "/user";
@Value("${captcha.privateKey}")
private String captchaPrivateKey;
@Autowired
private UserService userService;
@Autowired
private EMailVerificationService emailVerificationService;
private EmailValidator emailValidator = EmailValidator.getInstance();
@JsonView(JsonViews.Public.class)
@RequestMapping(value = "/register", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
public User registerUser(@RequestParam(value = "g-recaptcha-response", required = true) final String captchaResponse,
@RequestParam(name = "email", required = true) final String email, @RequestParam(name = "pass", required = true) final String password,
@RequestParam(name = "fullName", required = true) final String fullName, final HttpServletRequest request) throws Exception {
// Validate the reCAPTCHA
if (!ReCaptchaUtil.isValid(captchaResponse, request.getRemoteAddr(), captchaPrivateKey)) {
LOG.warn("Invalid captcha.");
throw new UserException("Captcha check failed.");
}
try {
if (!emailValidator.isValid(email)) {
LOG.warn("Invalid email provided: {}", email);
throw new UserException("Invalid email provided: " + email);
}
final User newUser = userService.createUser(email, fullName, password, BasicUser.AccountType.LOCAL);
emailVerificationService.sendVerificationEmail(newUser);
return newUser;
} catch (final PasswordPolicyException e) {
LOG.error(e.getMessage(), e);
throw new PasswordPolicyException(e.getMessage());
} catch (final DataIntegrityViolationException e) {
LOG.error(e.getMessage(), e);
throw new NotUniqueUserException("E-mail already taken: " + email);
} catch (final Exception e) {
LOG.error(e.getMessage(), e);
throw new Exception(e.getMessage());
}
}
@RequestMapping(value = "/{tokenUuid:.+}/validate", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
public boolean validateEMail(@PathVariable("tokenUuid") String tokenUuid, @RequestParam(value = "key", required = true) String key) throws Exception {
try {
emailVerificationService.validateEMail(tokenUuid, key);
return true;
} catch (final NoSuchVerificationTokenException e) {
throw new Exception("Verification token is not valid");
} catch (final TokenExpiredException e) {
throw new Exception("Verification token has expired");
}
}
}
/*
* Copyright 2018 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.genesys.test.server.api.v1;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.genesys.test.base.AbstractApiTest;
import org.genesys.test.base.WithMockOAuth2Authentication;
import org.genesys2.server.api.v1.UserRegistrationController;
import org.genesys2.server.model.impl.VerificationToken;
import org.genesys2.server.persistence.UserRepository;
import org.genesys2.server.persistence.VerificationTokenRepository;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.restdocs.JUnitRestDocumentation;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.WebApplicationContext;
/**
* The Class UserRegistrationControllerTest.
*
* @author Maxym Borodenko
*/
public class UserRegistrationControllerTest extends AbstractApiTest {
private static final String EMAIL = "test@email.com";
private static final String PASSWORD = "userPass1!";
private static final String FULL_NAME = "test user name";
private static final String RECAPTCHA_RESPONSE = "test-recaptcha-response";
@Rule
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation("target/generated-snippets");
@Autowired
private WebApplicationContext webApplicationContext;
@Autowired
private UserRepository userRepository;
@Autowired
private VerificationTokenRepository verificationTokenRepository;
MockMvc mockMvc;
@After
@Override
@Transactional
public void cleanup() throws Exception {
userRepository.deleteAll();
verificationTokenRepository.deleteAll();
super.cleanup();
}
@Before
@Override
@Transactional
public void beforeTest() throws Exception {
super.beforeTest();
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).apply(documentationConfiguration(this.restDocumentation).uris().withScheme("https").withHost(
"sandbox.genesys-pgr.org").withPort(443)).build();
}
@Test
public void registerUserTest() throws Exception {
/*@formatter:off*/
mockMvc.perform(post(UserRegistrationController.API_BASE.concat("/register"))
.contentType(MediaType.APPLICATION_JSON)
.param("email", EMAIL)
.param("pass", PASSWORD)
.param("fullName", FULL_NAME)
.param("g-recaptcha-response", RECAPTCHA_RESPONSE))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$", not(nullValue())))
.andExpect(jsonPath("$.fullName", is(FULL_NAME)))
.andExpect(jsonPath("$.email", is(EMAIL)));
/*@formatter:on*/
}
/**
* Expect an error because e-mail is already taken
*/
@Test
public void registerUserWithExistingEmailTest() throws Exception {
registerUserTest();
/*@formatter:off*/
mockMvc.perform(post(UserRegistrationController.API_BASE.concat("/register"))
.contentType(MediaType.APPLICATION_JSON)
.param("email", EMAIL)
.param("pass", PASSWORD)
.param("fullName", FULL_NAME)
.param("g-recaptcha-response", RECAPTCHA_RESPONSE))
// .andDo(MockMvcResultHandlers.print())
.andExpect(status().isInternalServerError())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8));
/*@formatter:on*/
}
/**
* Expect an error because e-mail is invalid
*/
@Test
public void registerUserWithInvalidEmailTest() throws Exception {
final String invalidEmail = "invalid@email";
/*@formatter:off*/
mockMvc.perform(post(UserRegistrationController.API_BASE.concat("/register"))
.contentType(MediaType.APPLICATION_JSON)
.param("email", invalidEmail)
.param("pass", PASSWORD)
.param("fullName", FULL_NAME)
.param("g-recaptcha-response", RECAPTCHA_RESPONSE))
// .andDo(MockMvcResultHandlers.print())
.andExpect(status().isInternalServerError())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8));
/*@formatter:on*/
}
@Test
@WithMockOAuth2Authentication
public void validateEMailTest() throws Exception {
registerUserTest();
final VerificationToken token = verificationTokenRepository.findAll().stream().findFirst().orElse(null);
if (token == null) {
throw new Exception("No token");
}
final String tokenUuid = token.getUuid();
final String tokenKey = token.getKey();
/*@formatter:off*/
mockMvc.perform(post(UserRegistrationController.API_BASE.concat("/").concat(tokenUuid).concat("/validate"))
.contentType(MediaType.APPLICATION_JSON)
.param("key", tokenKey))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$", is(true)));
/*@formatter:on*/
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment