Commit 5f289395 authored by Matija Obreza's avatar Matija Obreza

Merge branch...

Merge branch 'ui-442-page-for-cancellation-of-the-password-reset-request-is-opened-if-user-wants-canceled-request-of-validate-email' into 'master'

Added "type" to smtp cancellation links

See merge request genesys-pgr/genesys-server!442
parents f7335444 1057827e
...@@ -211,7 +211,7 @@ public class MeController extends ApiBaseController { ...@@ -211,7 +211,7 @@ public class MeController extends ApiBaseController {
@PreAuthorize("hasRole('TRUSTED_CLIENT') || hasRole('USER')") @PreAuthorize("hasRole('TRUSTED_CLIENT') || hasRole('USER')")
@PostMapping(value = "/{tokenUuid:.+}/cancel") @PostMapping(value = "/{tokenUuid:.+}/cancel")
public boolean cancelValidation(@PathVariable("tokenUuid") String tokenUuid, HttpServletRequest req, @RequestParam(value = "g-recaptcha-response", required = false) String response) throws IOException, UserException { public boolean cancelValidation(@PathVariable("tokenUuid") String tokenUuid, HttpServletRequest req, @RequestParam(value = "g-recaptcha-response", required = false) String response) throws IOException, UserException, TokenVerificationService.NoSuchVerificationTokenException {
// Validate the reCAPTCHA // Validate the reCAPTCHA
if (!ReCaptchaUtil.isValid(response, req.getRemoteAddr(), captchaPrivateKey)) { if (!ReCaptchaUtil.isValid(response, req.getRemoteAddr(), captchaPrivateKey)) {
...@@ -219,7 +219,7 @@ public class MeController extends ApiBaseController { ...@@ -219,7 +219,7 @@ public class MeController extends ApiBaseController {
throw new UserException("Captcha check failed."); throw new UserException("Captcha check failed.");
} }
emailVerificationService.cancelValidation(tokenUuid); emailVerificationService.cancelPasswordReset(tokenUuid);
return true; return true;
} }
......
...@@ -41,6 +41,7 @@ import org.springframework.dao.DataIntegrityViolationException; ...@@ -41,6 +41,7 @@ import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
...@@ -116,4 +117,17 @@ public class UserRegistrationController { ...@@ -116,4 +117,17 @@ public class UserRegistrationController {
throw new Exception("Verification token has expired"); throw new Exception("Verification token has expired");
} }
} }
@PostMapping(value = "/{tokenUuid:.+}/cancel")
public boolean cancelValidation(@PathVariable("tokenUuid") String tokenUuid, HttpServletRequest req, @RequestParam(value = "g-recaptcha-response", required = false) String response) throws Exception {
// Validate the reCAPTCHA
if (!ReCaptchaUtil.isValid(response, req.getRemoteAddr(), captchaPrivateKey)) {
LOG.warn("Invalid captcha.");
throw new UserException("Captcha check failed.");
}
emailVerificationService.cancelValidation(tokenUuid);
return true;
}
} }
...@@ -160,11 +160,16 @@ public class UserProfileController extends BaseController { ...@@ -160,11 +160,16 @@ public class UserProfileController extends BaseController {
} }
@RequestMapping(value = "/{tokenUuid:.+}/cancel", method = RequestMethod.GET) @RequestMapping(value = "/{tokenUuid:.+}/cancel", method = RequestMethod.GET)
public String cancelValidation(ModelMap model, @PathVariable("tokenUuid") String tokenUuid) { public String cancelValidation(ModelMap model, @PathVariable("tokenUuid") String tokenUuid) throws Exception {
emailVerificationService.cancelValidation(tokenUuid); emailVerificationService.cancelValidation(tokenUuid);
return "redirect:/"; return "redirect:/content/user-registration-canceled";
} }
@RequestMapping(value = "/{tokenUuid:.+}/cancel", method = RequestMethod.GET, params = { "type=pass" })
public String cancelPasswordReset(ModelMap model, @PathVariable("tokenUuid") String tokenUuid) throws NoSuchVerificationTokenException {
emailVerificationService.cancelPasswordReset(tokenUuid);
return "redirect:/content/user-password-reset-canceled";
}
@RequestMapping(value = "/{tokenUuid:.+}/validate", method = RequestMethod.GET) @RequestMapping(value = "/{tokenUuid:.+}/validate", method = RequestMethod.GET)
public String validateEmail(ModelMap model, @PathVariable("tokenUuid") String tokenUuid) { public String validateEmail(ModelMap model, @PathVariable("tokenUuid") String tokenUuid) {
model.addAttribute("tokenUuid", tokenUuid); model.addAttribute("tokenUuid", tokenUuid);
......
...@@ -104,7 +104,7 @@ public class UserProfileController extends BaseController { ...@@ -104,7 +104,7 @@ public class UserProfileController extends BaseController {
} }
@RequestMapping(value = "/{tokenUuid:.+}/cancel", method = RequestMethod.GET) @RequestMapping(value = "/{tokenUuid:.+}/cancel", method = RequestMethod.GET)
public String cancelValidation(ModelMap model, @PathVariable("tokenUuid") String tokenUuid) { public String cancelValidation(ModelMap model, @PathVariable("tokenUuid") String tokenUuid) throws Exception {
emailVerificationService.cancelValidation(tokenUuid); emailVerificationService.cancelValidation(tokenUuid);
return "redirect:" + URLBASE; return "redirect:" + URLBASE;
} }
......
...@@ -28,7 +28,9 @@ public interface EMailVerificationService { ...@@ -28,7 +28,9 @@ public interface EMailVerificationService {
void sendPasswordResetEmail(User user); void sendPasswordResetEmail(User user);
void cancelValidation(String tokenUuid); void cancelPasswordReset(String tokenUuid) throws NoSuchVerificationTokenException;
void cancelValidation(String tokenUuid) throws Exception;
void validateEMail(String tokenUuid, String key) throws NoSuchVerificationTokenException, TokenExpiredException; void validateEMail(String tokenUuid, String key) throws NoSuchVerificationTokenException, TokenExpiredException;
......
...@@ -37,6 +37,17 @@ public interface TokenVerificationService { ...@@ -37,6 +37,17 @@ public interface TokenVerificationService {
*/ */
void cancel(String tokenUuid) throws NoSuchVerificationTokenException; void cancel(String tokenUuid) throws NoSuchVerificationTokenException;
/**
* Fetch the token
*
* @param purpose
* @param tokenUuid
* @throws NoSuchVerificationTokenException
*
* @return
*/
VerificationToken fetchToken(String purpose, String tokenUuid) throws NoSuchVerificationTokenException;
/** /**
* Check token validity, remove it from persistence * Check token validity, remove it from persistence
* *
......
...@@ -23,6 +23,9 @@ import java.util.UUID; ...@@ -23,6 +23,9 @@ import java.util.UUID;
import org.genesys.blocks.security.SecurityContextUtil; import org.genesys.blocks.security.SecurityContextUtil;
import org.genesys.blocks.security.UserException; import org.genesys.blocks.security.UserException;
import org.genesys.blocks.security.service.PasswordPolicy.PasswordPolicyException; import org.genesys.blocks.security.service.PasswordPolicy.PasswordPolicyException;
import org.genesys2.server.component.security.AsAdminInvoker;
import org.genesys2.server.exception.InvalidApiUsageException;
import org.genesys2.server.model.UserRole;
import org.genesys2.server.model.impl.Article; import org.genesys2.server.model.impl.Article;
import org.genesys2.server.model.impl.User; import org.genesys2.server.model.impl.User;
import org.genesys2.server.model.impl.VerificationToken; import org.genesys2.server.model.impl.VerificationToken;
...@@ -60,6 +63,9 @@ public class EMailVerificationServiceImpl implements EMailVerificationService { ...@@ -60,6 +63,9 @@ public class EMailVerificationServiceImpl implements EMailVerificationService {
@Autowired @Autowired
private ContentService contentService; private ContentService contentService;
@Autowired
private AsAdminInvoker asAdminInvoker;
@Value("${frontend.url}") @Value("${frontend.url}")
private String frontendUrl; private String frontendUrl;
...@@ -100,11 +106,40 @@ public class EMailVerificationServiceImpl implements EMailVerificationService { ...@@ -100,11 +106,40 @@ public class EMailVerificationServiceImpl implements EMailVerificationService {
@Override @Override
@Transactional @Transactional
public void cancelValidation(String tokenUuid) { public void cancelPasswordReset(String tokenUuid) throws InvalidApiUsageException {
try {
tokenVerificationService.cancel(tokenUuid);
} catch (NoSuchVerificationTokenException e) {
LOG.warn("No such token. Error message {}", e.getMessage());
throw new InvalidApiUsageException("No such verification token");
}
}
/**
* User registration has been canceled. Remove user data if user not yet validated.
*/
@Override
@Transactional
public void cancelValidation(String tokenUuid) throws Exception {
try { try {
VerificationToken verificationToken = tokenVerificationService.fetchToken("email-verification", tokenUuid);
final User user = userService.getUser(UUID.fromString(verificationToken.getData()));
if (user.hasRole(UserRole.VALIDATEDUSER.getName())) {
throw new InvalidApiUsageException("User already validated");
}
asAdminInvoker.invoke(() -> {
userService.deleteUser(user);
return true;
});
tokenVerificationService.cancel(tokenUuid); tokenVerificationService.cancel(tokenUuid);
} catch (final NoSuchVerificationTokenException e) { } catch (final NoSuchVerificationTokenException e) {
// Silently cancel exception LOG.warn("No such token. Error message {}", e.getMessage());
throw new InvalidApiUsageException("No such verification token");
} }
} }
...@@ -124,7 +159,7 @@ public class EMailVerificationServiceImpl implements EMailVerificationService { ...@@ -124,7 +159,7 @@ public class EMailVerificationServiceImpl implements EMailVerificationService {
public void changePassword(final String tokenUuid, final String key, final String password) throws NoSuchVerificationTokenException, PasswordPolicyException, public void changePassword(final String tokenUuid, final String key, final String password) throws NoSuchVerificationTokenException, PasswordPolicyException,
TokenExpiredException { TokenExpiredException {
final VerificationToken consumedToken = tokenVerificationService.consumeToken("email-password", tokenUuid, key); final VerificationToken consumedToken = tokenVerificationService.consumeToken("email-password", tokenUuid, key);
final User user = userService.getUserByUuid(consumedToken.getData()); final User user = userService.getUser(UUID.fromString(consumedToken.getData()));
Authentication prevAuth = SecurityContextHolder.getContext().getAuthentication(); Authentication prevAuth = SecurityContextHolder.getContext().getAuthentication();
try { try {
......
...@@ -73,6 +73,18 @@ public class TokenVerificationServiceImpl implements TokenVerificationService, J ...@@ -73,6 +73,18 @@ public class TokenVerificationServiceImpl implements TokenVerificationService, J
} }
} }
@Override
public VerificationToken fetchToken(String purpose, String tokenUuid) throws NoSuchVerificationTokenException {
final VerificationToken verificationToken = verificationTokenRepository.findByPurposeAndUuid(purpose, tokenUuid);
if (verificationToken == null) {
LOG.warn("No such verification token {}", tokenUuid);
throw new NoSuchVerificationTokenException();
}
return verificationToken;
}
@Override @Override
@Transactional @Transactional
public VerificationToken consumeToken(String purpose, String tokenUuid, String key) throws NoSuchVerificationTokenException, TokenExpiredException { public VerificationToken consumeToken(String purpose, String tokenUuid, String key) throws NoSuchVerificationTokenException, TokenExpiredException {
......
{ {
"en": { "en": {
"title": "Reset password", "title": "Reset password",
"body": "<h2><small>Genesys account</small><br/>Reset password</h2><p>Click <a href=\"{0}/profile/{1}/pwdreset\">this link</a> to reset your password.</p><h2>Validation key: {3}</h2><p>If you didn't make this request, <a href=\"{0}/profile/{1}/cancel\">click here to cancel</a>.</p><p>Thanks,<br/ >Genesys team</p>" "body": "<h2><small>Genesys account</small><br/>Reset password</h2><p>Click <a href=\"{0}/profile/{1}/pwdreset\">this link</a> to reset your password.</p><h2>Validation key: {3}</h2><p>If you didn't make this request, <a href=\"{0}/profile/{1}/cancel?type=pass\">click here to cancel</a>.</p><p>Thanks,<br/ >Genesys team</p>"
} }
} }
\ No newline at end of file
{ {
"en": { "en": {
"title": "Verify your email address", "title": "Verify your email address",
"body": "<h2><small>Genesys account</small><br/>Verify your email address</h2><p>You can already use your Genesys account. We need to confirm your email account before granting you access to all Genesys features.</p><p><a href=\"{0}/profile/{1}/validate\">Verify {2}</a></p><h2>Validation key: {3}</h2><p>If you didn't make this request, <a href=\"{0}/profile/{1}/cancel\">click here to cancel</a>.</p><p>Thanks,<br/ >Genesys team</p>" "body": "<h2><small>Genesys account</small><br/>Verify your email address</h2><p>You can already use your Genesys account. We need to confirm your email account before granting you access to all Genesys features.</p><p><a href=\"{0}/profile/{1}/validate\">Verify {2}</a></p><h2>Validation key: {3}</h2><p>If you didn't make this request, <a href=\"{0}/profile/{1}/cancel?type=email\">click here to cancel</a>.</p><p>Thanks,<br/ >Genesys team</p>"
} }
} }
\ No newline at end of file
{
"en": {
"title": "Password reset request canceled",
"body": "<p>The request to reset the account password is canceled.</p>"
}
}
{
"en": {
"title": "User account registration canceled",
"body": "<p>The registration of the user account was canceled. Any personal information associated with the account was removed from Genesys.</p>"
}
}
...@@ -130,7 +130,7 @@ public class EmailVerificationServiceTest extends AbstractServicesTest { ...@@ -130,7 +130,7 @@ public class EmailVerificationServiceTest extends AbstractServicesTest {
// FIXME Does not consider existing data // FIXME Does not consider existing data
@Ignore @Ignore
@Test @Test
public void cancelValidationTest() throws TokenVerificationService.NoSuchVerificationTokenException { public void cancelValidationTest() throws TokenVerificationService.NoSuchVerificationTokenException, Exception {
LOG.info("Start test-method cancelValidationTest"); LOG.info("Start test-method cancelValidationTest");
assertTrue(!verificationTokenRepository.findAll().isEmpty()); assertTrue(!verificationTokenRepository.findAll().isEmpty());
......
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