diff --git a/backend/docker-compose.yml b/backend/docker-compose.yml index f1ac59d8..3777e535 100644 --- a/backend/docker-compose.yml +++ b/backend/docker-compose.yml @@ -21,7 +21,6 @@ services: MAIL_PORT: ${MAIL_PORT} MAIL_USER: ${MAIL_USER} MAIL_PASS: ${MAIL_PASS} - TURNSTILE_SECRET: ${TURNSTILE_SECRET} depends_on: - db diff --git a/backend/src/main/java/com/kurttekin/can/job_track/application/service/TurnstileVerificationService.java b/backend/src/main/java/com/kurttekin/can/job_track/application/service/TurnstileVerificationService.java deleted file mode 100644 index 7a707672..00000000 --- a/backend/src/main/java/com/kurttekin/can/job_track/application/service/TurnstileVerificationService.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.kurttekin.can.job_track.application.service; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -import java.util.HashMap; -import java.util.Map; - -@Service -public class TurnstileVerificationService { - - @Value("${turnstile.secret-key}") - private String turnstileSecretKey; - - private static final String VERIFY_URL = "https://challenges.cloudflare.com/turnstile/v0/siteverify"; - - public boolean verifyToken(String turnstileToken) { - RestTemplate restTemplate = new RestTemplate(); - - Map requestBody = new HashMap<>(); - requestBody.put("secret", turnstileSecretKey); - requestBody.put("response", turnstileToken); - - Map response = restTemplate.postForObject(VERIFY_URL, requestBody, Map.class); - return response != null && Boolean.TRUE.equals(response.get("success")); - } -} diff --git a/backend/src/main/java/com/kurttekin/can/job_track/infrastructure/security/config/MailConfig.java b/backend/src/main/java/com/kurttekin/can/job_track/infrastructure/security/config/MailConfig.java index 0183aefc..d046a18b 100644 --- a/backend/src/main/java/com/kurttekin/can/job_track/infrastructure/security/config/MailConfig.java +++ b/backend/src/main/java/com/kurttekin/can/job_track/infrastructure/security/config/MailConfig.java @@ -42,4 +42,4 @@ public JavaMailSender javaMailSender() { return mailSender; } -} \ No newline at end of file +} diff --git a/backend/src/main/java/com/kurttekin/can/job_track/presentation/rest/AuthController.java b/backend/src/main/java/com/kurttekin/can/job_track/presentation/rest/AuthController.java index 2f258f83..75874e79 100644 --- a/backend/src/main/java/com/kurttekin/can/job_track/presentation/rest/AuthController.java +++ b/backend/src/main/java/com/kurttekin/can/job_track/presentation/rest/AuthController.java @@ -2,7 +2,6 @@ import com.kurttekin.can.job_track.application.dto.ErrorResponse; import com.kurttekin.can.job_track.application.dto.UserRegistrationRequest; -import com.kurttekin.can.job_track.application.service.TurnstileVerificationService; import com.kurttekin.can.job_track.domain.model.user.User; import com.kurttekin.can.job_track.domain.service.UserService; import com.kurttekin.can.job_track.domain.service.VerificationService; @@ -35,19 +34,9 @@ public class AuthController { @Autowired private VerificationService verificationService; - @Autowired - private TurnstileVerificationService turnstileVerificationService; - @PostMapping("/login") - public ResponseEntity login(@RequestBody LoginRequest loginRequest, - @RequestParam String turnstileToken) { + public ResponseEntity login(@RequestBody LoginRequest loginRequest) { try { - // Verify Turnstile token - boolean isTokenValid = turnstileVerificationService.verifyToken(turnstileToken); - if (!isTokenValid) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).body(new ErrorResponse("CAPTCHA failed.")); - } - User user = userService.findUserByUsername(loginRequest.getUsername()) .orElseThrow(() -> new BadCredentialsException("Invalid credentials")); @@ -75,14 +64,8 @@ public ResponseEntity login(@RequestBody LoginRequest loginRequest, } @PostMapping("/register") - public ResponseEntity registerUser(@RequestBody UserRegistrationRequest userRequest, - @RequestParam String turnstileToken) { + public ResponseEntity registerUser(@RequestBody UserRegistrationRequest userRequest) { try { - // Verify Turnstile token - boolean isTokenValid = turnstileVerificationService.verifyToken(turnstileToken); - if (!isTokenValid) { - return ResponseEntity.status(HttpStatus.FORBIDDEN).body("CAPTCHA failed."); - } userService.registerUser(userRequest); return ResponseEntity.ok("User registered successfully! Please verify your email before logging in."); } catch (Exception e) { diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index b4c87495..31213537 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -16,5 +16,3 @@ server.port=${PORT:8080} #server.ssl.key-store-password=${KEY_STORE_PASS} #server.ssl.keyStoreType=PKCS12 #server.ssl.key-alias=${KEY_STORE_ALIAS} - -turnstile.secret-key=${TURNSTILE_SECRET:"0x0000"} diff --git a/backend/src/test/java/com/kurttekin/can/job_track/presentation/rest/AuthControllerTest.java b/backend/src/test/java/com/kurttekin/can/job_track/presentation/rest/AuthControllerTest.java index 92fb5762..408e7a85 100644 --- a/backend/src/test/java/com/kurttekin/can/job_track/presentation/rest/AuthControllerTest.java +++ b/backend/src/test/java/com/kurttekin/can/job_track/presentation/rest/AuthControllerTest.java @@ -4,7 +4,6 @@ import com.kurttekin.can.job_track.application.dto.LoginRequest; import com.kurttekin.can.job_track.application.dto.UserRegistrationRequest; import com.kurttekin.can.job_track.application.service.EmailService; -import com.kurttekin.can.job_track.application.service.TurnstileVerificationService; import com.kurttekin.can.job_track.domain.service.UserService; import com.kurttekin.can.job_track.infrastructure.security.jwt.JwtProvider; import org.junit.jupiter.api.BeforeEach; @@ -49,13 +48,10 @@ class AuthControllerTest { @Mock private EmailService emailService; - @Mock - private TurnstileVerificationService turnstileVerificationService; - private LoginRequest loginRequest; private UserRegistrationRequest userRegistrationRequest; private String token; - private String turnstileToken; + @BeforeEach public void setUp() { @@ -64,19 +60,14 @@ public void setUp() { userRegistrationRequest = new UserRegistrationRequest("testuser", "testuser@test.com", "testpassword"); token = "test.jwt.token"; - turnstileToken= "test.jwt.turnstile"; } @Test public void testLogin_InvalidCredentials() { - // Mock Turnstile verification logic - //when(turnstileVerificationService.verifyToken(anyString())).thenReturn(true); - when(turnstileVerificationService.verifyToken(turnstileToken)).thenReturn(true); - when(authenticationManager.authenticate(any(UsernamePasswordAuthenticationToken.class))) .thenThrow(new BadCredentialsException("Invalid credentials")); - ResponseEntity response = authController.login(loginRequest, turnstileToken); + ResponseEntity response = authController.login(loginRequest); assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); assertEquals("Invalid credentials", response.getBody()); @@ -91,10 +82,8 @@ public void testRegisterUser_Success() { doNothing().when(userService).registerUser(any(UserRegistrationRequest.class)); doNothing().when(emailService).sendVerificationEmail(anyString(),anyString(), anyString()); // Mock email sending - when(turnstileVerificationService.verifyToken(turnstileToken)).thenReturn(true); - // Call the registerUser method in the controller - ResponseEntity response = authController.registerUser(userRegistrationRequest, turnstileToken); + ResponseEntity response = authController.registerUser(userRegistrationRequest); // Check the status and response body assertEquals(HttpStatus.OK, response.getStatusCode()); @@ -105,9 +94,7 @@ public void testRegisterUser_Success() { public void testRegisterUser_Failure() { doThrow(new RuntimeException("Registration failed")).when(userService).registerUser(any(UserRegistrationRequest.class)); - when(turnstileVerificationService.verifyToken(turnstileToken)).thenReturn(true); - - ResponseEntity response = authController.registerUser(userRegistrationRequest, turnstileToken); + ResponseEntity response = authController.registerUser(userRegistrationRequest); assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); assertEquals("Registration failed", response.getBody()); diff --git a/frontend/src/components/Login.js b/frontend/src/components/Login.js index 7373fb9d..4b9bd5ee 100644 --- a/frontend/src/components/Login.js +++ b/frontend/src/components/Login.js @@ -2,8 +2,6 @@ import React, { useContext, useState } from 'react'; import styled from 'styled-components'; import { useNavigate } from 'react-router-dom'; import { AuthContext } from '../contexts/AuthContext'; // Import the context -import Turnstile from "./Turnstile"; -import { REACT_APP_TURNSTILE_SITE_KEY } from '../config.js'; const Container = styled.div` display: flex; @@ -52,7 +50,6 @@ const Login = () => { const [password, setPassword] = useState(""); const [error, setError] = useState(""); // To store and display error messages const { login } = useContext(AuthContext); - const [turnstileToken, setTurnstileToken] = useState(''); const handleSubmit = async (e) => { e.preventDefault(); @@ -64,13 +61,8 @@ const Login = () => { return; } - if (!turnstileToken) { - setError("Please complete the CAPTCHA."); - return; - } - try { - await login(username, password, turnstileToken); // Call the login function + await login(username, password); // Call the login function navigate('/job-applications'); // Redirect after successful login } catch (error) { setError(error.message); // Set the error message @@ -95,10 +87,6 @@ const Login = () => { value={password} onChange={e => setPassword(e.target.value)} /> - setTurnstileToken(token)} - /> {error && {error}} {/* Display error message */} diff --git a/frontend/src/components/Register.js b/frontend/src/components/Register.js index d785339c..3ccb4094 100644 --- a/frontend/src/components/Register.js +++ b/frontend/src/components/Register.js @@ -2,8 +2,6 @@ import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; import { register as registerService } from '../services/authService'; // Import the register function from authService -import Turnstile from "./Turnstile"; -import {REACT_APP_TURNSTILE_SITE_KEY} from "../config"; // Styled components for layout and styling const Container = styled.div` @@ -77,7 +75,7 @@ const Register = () => { specialChar: false, }); const [isPasswordFocused, setIsPasswordFocused] = useState(false); // Track if the password field is focused - const [turnstileToken, setTurnstileToken] = useState(''); + const navigate = useNavigate(); // Password validation function @@ -126,13 +124,8 @@ const Register = () => { return; } - if (!turnstileToken) { - setError("Please complete the CAPTCHA."); - return; - } - try { - await registerService(username, email, password, turnstileToken); // Call the register function + await registerService(username, email, password); // Call the register function setError('Registration successful. Please verify your email before logging in.'); setTimeout(() => navigate('/login'), 1500); // Redirect after 1.5 seconds } catch (err) { @@ -192,10 +185,6 @@ const Register = () => { )} - setTurnstileToken(token)} - /> diff --git a/frontend/src/components/Turnstile.js b/frontend/src/components/Turnstile.js deleted file mode 100644 index 3a4de074..00000000 --- a/frontend/src/components/Turnstile.js +++ /dev/null @@ -1,46 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; - -const Turnstile = ({ siteKey, onVerify }) => { - const [captchaLoaded, setCaptchaLoaded] = useState(false); - const captchaRef = useRef(null); - const turnstileRendered = useRef(false); // Ref to track if Turnstile is already rendered - - useEffect(() => { - // Load the Turnstile script if not already loaded - const handleLoad = () => { - setCaptchaLoaded(true); - }; - - if (window.turnstile && window.turnstile.render) { - handleLoad(); - } else { - const script = document.createElement('script'); - script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js'; - script.async = true; - script.defer = true; - script.onload = handleLoad; - document.body.appendChild(script); - } - - return () => { - // Cleanup: No need to remove the script as it should be loaded only once - }; - }, []); - - useEffect(() => { - if (captchaLoaded && siteKey && !turnstileRendered.current) { - // Render the Turnstile widget only if it hasn't been rendered already - if (captchaRef.current) { - window.turnstile.render(captchaRef.current, { - sitekey: siteKey, - callback: onVerify, - }); - turnstileRendered.current = true; // Mark as rendered - } - } - }, [captchaLoaded, siteKey, onVerify]); - - return
; -}; - -export default Turnstile; diff --git a/frontend/src/config.js b/frontend/src/config.js index 63d92873..8222ed45 100644 --- a/frontend/src/config.js +++ b/frontend/src/config.js @@ -1,2 +1 @@ -export const REACT_APP_BACKEND_URL = process.env.REACT_APP_BACKEND_URL+'/api'; -export const REACT_APP_TURNSTILE_SITE_KEY = process.env.REACT_APP_TURNSTILE_SITE_KEY; \ No newline at end of file +export const REACT_APP_BACKEND_URL = process.env.REACT_APP_BACKEND_URL+'/api'; \ No newline at end of file diff --git a/frontend/src/contexts/AuthContext.js b/frontend/src/contexts/AuthContext.js index 92fb1f71..275e7182 100644 --- a/frontend/src/contexts/AuthContext.js +++ b/frontend/src/contexts/AuthContext.js @@ -18,9 +18,9 @@ export const AuthProvider = ({ children }) => { } }, []); - const login = async (username, password, turnstileToken) => { + const login = async (username, password) => { try { - const response = await loginService(username, password, turnstileToken); + const response = await loginService(username, password); const { token } = response; if (token) { diff --git a/frontend/src/services/authService.js b/frontend/src/services/authService.js index 93bf11c1..f829e40c 100644 --- a/frontend/src/services/authService.js +++ b/frontend/src/services/authService.js @@ -1,11 +1,11 @@ import axios from 'axios'; import { REACT_APP_BACKEND_URL } from '../config'; -export const login = async (username, password, turnstileToken) => { +export const login = async (username, password) => { try { const response = await axios.post( `${REACT_APP_BACKEND_URL}/auth/login`, - { username, password, turnstileToken }, + { username, password }, { headers: { 'Content-Type': 'application/json', @@ -33,8 +33,8 @@ export const login = async (username, password, turnstileToken) => { } }; -export const register = async (username, email, password, turnstileToken) => { - return axios.post(`${REACT_APP_BACKEND_URL}/auth/register`, { username, email, password, turnstileToken }); +export const register = async (username, email, password) => { + return axios.post(`${REACT_APP_BACKEND_URL}/auth/register`, { username, email, password }); }; export const logout = () => {