/user/exists now requires a captcha
All checks were successful
Deploy API / deploy (ubuntu-latest, 2.44.0) (push) Successful in 45s

This commit is contained in:
Braydon 2024-09-19 08:48:04 -04:00
parent 955b035687
commit f3d5ead017
4 changed files with 60 additions and 11 deletions

@ -5,6 +5,7 @@ import cc.pulseapp.api.model.user.User;
import cc.pulseapp.api.model.user.UserDTO;
import cc.pulseapp.api.model.user.input.CompleteOnboardingInput;
import cc.pulseapp.api.model.user.input.EnableTFAInput;
import cc.pulseapp.api.model.user.input.UserExistsInput;
import cc.pulseapp.api.model.user.response.UserSetupTFAResponse;
import cc.pulseapp.api.service.UserService;
import lombok.NonNull;
@ -50,12 +51,12 @@ public final class UserController {
* A GET endpoint to check if a
* user exists with the given email.
*
* @param email the email to check
* @param input the input to check
* @return the response
*/
@GetMapping("/exists") @ResponseBody @NonNull
public ResponseEntity<Map<String, Object>> doesUserExist(@RequestParam @NonNull String email) {
return ResponseEntity.ok(Map.of("exists", userService.doesUserExist(email)));
@PostMapping("/exists") @ResponseBody @NonNull
public ResponseEntity<Map<String, Object>> doesUserExist(UserExistsInput input) {
return ResponseEntity.ok(Map.of("exists", userService.doesUserExist(input)));
}
/**

@ -0,0 +1,35 @@
package cc.pulseapp.api.model.user.input;
import cc.pulseapp.api.model.user.User;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;
/**
* The input to check if
* a {@link User} exists.
*
* @author Braydon
*/
@AllArgsConstructor @Getter @ToString
public final class UserExistsInput {
/**
* The email of the user to check.
*/
private final String email;
/**
* The captcha response token to validate.
*/
private final String captchaResponse;
/**
* Check if this input is valid.
*
* @return whether this input is valid
*/
public boolean isValid() {
return email != null && (!email.isBlank())
&& captchaResponse != null && (!captchaResponse.isBlank());
}
}

@ -34,7 +34,7 @@ public final class CaptchaService {
.header(HttpHeaders.CONTENT_TYPE, "application/json")
.body(body)
.asJson();
if (EnvironmentUtils.isProduction() && !response.getBody().getObject().getBoolean("success")) {
if (/*EnvironmentUtils.isProduction() && */!response.getBody().getObject().getBoolean("success")) {
throw new BadRequestException(Error.CAPTCHA_INVALID);
}
}

@ -11,6 +11,7 @@ import cc.pulseapp.api.model.user.UserDTO;
import cc.pulseapp.api.model.user.UserFlag;
import cc.pulseapp.api.model.user.input.CompleteOnboardingInput;
import cc.pulseapp.api.model.user.input.EnableTFAInput;
import cc.pulseapp.api.model.user.input.UserExistsInput;
import cc.pulseapp.api.model.user.response.UserSetupTFAResponse;
import cc.pulseapp.api.repository.SessionRepository;
import cc.pulseapp.api.repository.UserRepository;
@ -56,6 +57,11 @@ public final class UserService {
*/
@NonNull private final TFAService tfaService;
/**
* The captcha service to use.
*/
@NonNull private final CaptchaService captchaService;
/**
* The user repository to use.
*/
@ -80,13 +86,14 @@ public final class UserService {
@Autowired
public UserService(@NonNull AuthService authService, @NonNull SnowflakeService snowflakeService,
@NonNull OrganizationService orgService, @NonNull StatusPageService statusPageService,
@NonNull TFAService tfaService, @NonNull UserRepository userRepository,
@NonNull SessionRepository sessionRepository) {
@NonNull TFAService tfaService, @NonNull CaptchaService captchaService,
@NonNull UserRepository userRepository, @NonNull SessionRepository sessionRepository) {
this.authService = authService;
this.snowflakeService = snowflakeService;
this.orgService = orgService;
this.statusPageService = statusPageService;
this.tfaService = tfaService;
this.captchaService = captchaService;
this.userRepository = userRepository;
this.sessionRepository = sessionRepository;
}
@ -103,13 +110,18 @@ public final class UserService {
}
/**
* Check if the user with the given email exists.
* Check if a user exists
* with the given email.
*
* @param email the email to check
* @param input the input to check
* @return whether the user exists
*/
public boolean doesUserExist(@NonNull String email) {
return StringUtils.isValidEmail(email) && userRepository.findByEmailIgnoreCase(email) != null;
public boolean doesUserExist(UserExistsInput input) {
if (input == null || (!input.isValid())) { // Ensure the input was provided
throw new BadRequestException(Error.MALFORMED_USER_EXISTS_INPUT);
}
captchaService.validateCaptcha(input.getCaptchaResponse());
return StringUtils.isValidEmail(input.getEmail()) && userRepository.findByEmailIgnoreCase(input.getEmail()) != null;
}
/**
@ -215,6 +227,7 @@ public final class UserService {
* User errors.
*/
private enum Error implements IGenericResponse {
MALFORMED_USER_EXISTS_INPUT,
MALFORMED_ONBOARDING_INPUT,
MALFORMED_ENABLE_TFA_INPUT,
ORGANIZATION_SLUG_INVALID,