diff --git a/backend/src/main/java/io/papermc/hangar/components/auth/controller/AuthController.java b/backend/src/main/java/io/papermc/hangar/components/auth/controller/AuthController.java index b723e417..e2d8252c 100644 --- a/backend/src/main/java/io/papermc/hangar/components/auth/controller/AuthController.java +++ b/backend/src/main/java/io/papermc/hangar/components/auth/controller/AuthController.java @@ -48,22 +48,18 @@ public class AuthController extends HangarComponent { private final VerificationService verificationService; private final CredentialsService credentialsService; private final UserService userService; - private final TurnstileService turnstileService; - public AuthController(final AuthService authService, final TokenService tokenService, final VerificationService verificationService, final CredentialsService credentialsService, final UserService userService, final TurnstileService turnstileService) { + public AuthController(final AuthService authService, final TokenService tokenService, final VerificationService verificationService, final CredentialsService credentialsService, final UserService userService) { this.authService = authService; this.tokenService = tokenService; this.verificationService = verificationService; this.credentialsService = credentialsService; this.userService = userService; - this.turnstileService = turnstileService; } @Anyone @PostMapping("/signup") public ResponseEntity signup(@RequestBody final SignupForm signupForm) { - this.turnstileService.validate(signupForm.captcha()); - final UserTable userTable = this.authService.registerUser(signupForm); if (userTable == null) { return ResponseEntity.badRequest().build(); diff --git a/backend/src/main/java/io/papermc/hangar/components/auth/service/AuthService.java b/backend/src/main/java/io/papermc/hangar/components/auth/service/AuthService.java index 3fdeebcd..23320d2c 100644 --- a/backend/src/main/java/io/papermc/hangar/components/auth/service/AuthService.java +++ b/backend/src/main/java/io/papermc/hangar/components/auth/service/AuthService.java @@ -49,8 +49,9 @@ public class AuthService extends HangarComponent implements UserDetailsService { private final TokenService tokenService; private final UsersApiService usersApiService; private final BucketService bucketService; + private final TurnstileService turnstileService; - public AuthService(final UserDAO userDAO, final UserCredentialDAO userCredentialDAO, final PasswordEncoder passwordEncoder, final ValidationService validationService, final VerificationService verificationService, final CredentialsService credentialsService, final HibpService hibpService, final MailService mailService, final TokenService tokenService, final UsersApiService usersApiService, final BucketService bucketService) { + public AuthService(final UserDAO userDAO, final UserCredentialDAO userCredentialDAO, final PasswordEncoder passwordEncoder, final ValidationService validationService, final VerificationService verificationService, final CredentialsService credentialsService, final HibpService hibpService, final MailService mailService, final TokenService tokenService, final UsersApiService usersApiService, final BucketService bucketService, final TurnstileService turnstileService) { this.userDAO = userDAO; this.userCredentialDAO = userCredentialDAO; this.passwordEncoder = passwordEncoder; @@ -62,6 +63,7 @@ public class AuthService extends HangarComponent implements UserDetailsService { this.tokenService = tokenService; this.usersApiService = usersApiService; this.bucketService = bucketService; + this.turnstileService = turnstileService; } @Transactional @@ -71,6 +73,8 @@ public class AuthService extends HangarComponent implements UserDetailsService { } this.validateNewUser(form.username(), form.email(), form.tos()); + this.turnstileService.validate(form.captcha()); + if (!this.config.isDisableRateLimiting()) { Bucket bucket = this.bucketService.bucket("register-user", new RateLimit.Model(1, 1, 60 * 5, false, "register-user")); if (bucket != null && !bucket.tryConsume(1)) { diff --git a/backend/src/main/java/io/papermc/hangar/components/auth/service/TurnstileService.java b/backend/src/main/java/io/papermc/hangar/components/auth/service/TurnstileService.java index d8844004..430436cb 100644 --- a/backend/src/main/java/io/papermc/hangar/components/auth/service/TurnstileService.java +++ b/backend/src/main/java/io/papermc/hangar/components/auth/service/TurnstileService.java @@ -1,9 +1,10 @@ package io.papermc.hangar.components.auth.service; +import com.fasterxml.jackson.annotation.JsonProperty; import io.papermc.hangar.HangarComponent; import io.papermc.hangar.exceptions.HangarApiException; import io.papermc.hangar.util.RequestUtil; -import java.util.Arrays; +import java.util.List; import org.springframework.http.HttpEntity; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; @@ -34,10 +35,10 @@ public class TurnstileService extends HangarComponent { var response = this.restTemplate.postForEntity(url, entity, TurnstileResponse.class); if (response.getBody() != null && !response.getBody().success()) { - throw new HangarApiException("error.captcha", Arrays.toString(response.getBody().errorCodes())); + throw new HangarApiException("error.captcha", response.getBody().errorCodes()); } } } - record TurnstileResponse(boolean success, String[] errorCodes){} + record TurnstileResponse(boolean success, @JsonProperty("error-codes") List errorCodes){} } diff --git a/frontend/src/i18n/locales/en.json b/frontend/src/i18n/locales/en.json index 15974fa0..2ab559e5 100644 --- a/frontend/src/i18n/locales/en.json +++ b/frontend/src/i18n/locales/en.json @@ -1214,6 +1214,7 @@ "unknown": "An error occurred", "aal1": "You need to verify your email first", "aal2": "You need to setup 2fa first", - "privileged": "You need to be in a privileged session to do this" + "privileged": "You need to be in a privileged session to do this", + "captcha": "Error while verifying the security challenge: {0}. Please try again." } } diff --git a/frontend/src/pages/auth/signup.vue b/frontend/src/pages/auth/signup.vue index d7975758..f048784c 100644 --- a/frontend/src/pages/auth/signup.vue +++ b/frontend/src/pages/auth/signup.vue @@ -19,6 +19,7 @@ const notification = useNotificationStore(); const i18n = useI18n(); const form = reactive({}); const loading = ref(false); +const turnstile = useTemplateRef("turnstile"); const errorMessage = ref(); @@ -31,6 +32,9 @@ async function submit() { done.value = true; } catch (e) { notification.fromError(i18n, e); + if (e?.response?.data?.message === "error.captcha") { + turnstile.value?.reset(); + } } loading.value = false; } @@ -93,7 +97,7 @@ useSeo(computed(() => ({ title: "Sign up", route }))); - +
{{ errorMessage }}
diff --git a/frontend/src/store/notification.ts b/frontend/src/store/notification.ts index f02ca236..884bf4dd 100644 --- a/frontend/src/store/notification.ts +++ b/frontend/src/store/notification.ts @@ -37,7 +37,7 @@ export const useNotificationStore = defineStore("notification", () => { message = i18n.t(error.response.data.detail); } if (error.response?.data?.message) { - message = i18n.t(error.response.data.message); + message = i18n.t(error.response.data.message, ...error.response.data.messageArgs); } await show({ message, color: "red", clearable, timeout, addedAt: Date.now() }); }