mirror of
https://gitlab.com/etc404/software-engineering-project.git
synced 2026-05-10 20:52:58 +00:00
more checks and stuff for verification
This commit is contained in:
@@ -25,6 +25,11 @@ public class EmailController {
|
||||
if (emailService.isValidEmail(email) == false) {
|
||||
return ResponseEntity.status(429).body("Invalid Email Detected.");
|
||||
}
|
||||
|
||||
if (emailService.isEmailTaken(email)) {
|
||||
return ResponseEntity.status(409).body("An account with this email already exists.");
|
||||
}
|
||||
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,15 @@ public class UserController {
|
||||
return new ResponseEntity<>(users, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@PostMapping("/check")
|
||||
public ResponseEntity<?> isTaken(@RequestParam String name) {
|
||||
|
||||
if (userService.isUsernameTaken(name)) {
|
||||
return ResponseEntity.status(409).body("An account with this username already exists.");
|
||||
}
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
// build get current user REST API
|
||||
@GetMapping("/me")
|
||||
public UserDto getLoggedInUser(Principal principal) {
|
||||
|
||||
@@ -11,6 +11,8 @@ public interface UserRepo extends JpaRepository<User, Integer> {
|
||||
|
||||
Optional<User> findByUsername(String username);
|
||||
|
||||
Optional<User> findByEmail(String Email);
|
||||
|
||||
List<User> findByUsernameContainingIgnoreCase(String name);
|
||||
|
||||
}
|
||||
@@ -7,6 +7,9 @@ import org.springframework.mail.MailException;
|
||||
import org.springframework.mail.SimpleMailMessage;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.example.demo.repository.UserRepo;
|
||||
|
||||
import javax.naming.directory.Attributes;
|
||||
import javax.naming.directory.DirContext;
|
||||
import javax.naming.directory.InitialDirContext;
|
||||
@@ -23,6 +26,9 @@ public class EmailService {
|
||||
@Autowired
|
||||
private OtpStore otpStore;
|
||||
|
||||
@Autowired
|
||||
private UserRepo userRepository;
|
||||
|
||||
public void sendOtpEmail(String toEmail) {
|
||||
String otp = OtpUtil.generateOtp(6);
|
||||
otpStore.save(toEmail, otp);
|
||||
@@ -46,12 +52,17 @@ public class EmailService {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmailTaken(String email) {
|
||||
return userRepository.findByEmail(email.toLowerCase().trim()).isPresent();
|
||||
}
|
||||
|
||||
public boolean isValidEmail(String email) {
|
||||
if (email == null || email.isBlank()) return false;
|
||||
|
||||
String emailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
|
||||
if (!email.matches(emailRegex)) return false;
|
||||
|
||||
|
||||
try {
|
||||
InternetAddress emailAddr = new InternetAddress(email, true);
|
||||
emailAddr.validate();
|
||||
|
||||
@@ -255,4 +255,9 @@ public class UserServiceImpl implements UserService {
|
||||
|
||||
return favoriteRepository.existsById(new FavoriteId(user.getId(), recipeId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isUsernameTaken(String username) {
|
||||
return userRepository.findByUsername(username.toLowerCase().trim()).isPresent();
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ import com.example.demo.entity.User;
|
||||
public interface UserService {
|
||||
UserDto convertToDto(User user);
|
||||
|
||||
Boolean isUsernameTaken(String username);
|
||||
|
||||
User saveUser(User user);
|
||||
|
||||
List<UserDto> getAllUsers();
|
||||
|
||||
@@ -87,108 +87,142 @@ function isProfane(str) {
|
||||
error.textContent = message;
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
|
||||
const form = document.getElementById("createUserForm");
|
||||
const passwordField = document.getElementById("password");
|
||||
const confirmPasswordField = document.getElementById("confirmPassword");
|
||||
const passwordError = document.getElementById("passwordError");
|
||||
const form = document.getElementById("createUserForm");
|
||||
const passwordField = document.getElementById("password");
|
||||
const confirmPasswordField = document.getElementById("confirmPassword");
|
||||
const usernameField = document.getElementById("username");
|
||||
const emailField = document.getElementById("email");
|
||||
const passwordError = document.getElementById("passwordError");
|
||||
|
||||
function checkPasswords() {
|
||||
if (confirmPasswordField.value === "") {
|
||||
confirmPasswordField.classList.remove("invalid");
|
||||
passwordError.textContent = "Password cannot be blank";
|
||||
return;
|
||||
}
|
||||
function checkPasswords() {
|
||||
if (confirmPasswordField.value === "") {
|
||||
confirmPasswordField.classList.remove("invalid");
|
||||
passwordError.textContent = "";
|
||||
return;
|
||||
}
|
||||
if (passwordField.value !== confirmPasswordField.value) {
|
||||
confirmPasswordField.classList.add("invalid");
|
||||
passwordError.textContent = "Passwords do not match.";
|
||||
} else {
|
||||
confirmPasswordField.classList.remove("invalid");
|
||||
passwordError.textContent = "";
|
||||
}
|
||||
}
|
||||
|
||||
passwordField.addEventListener("input", checkPasswords);
|
||||
confirmPasswordField.addEventListener("input", checkPasswords);
|
||||
|
||||
const csrfToken = () => document.querySelector('meta[name="_csrf"]').getAttribute("content");
|
||||
const csrfHeader = () => document.querySelector('meta[name="_csrf_header"]').getAttribute("content");
|
||||
|
||||
emailField.addEventListener("blur", async () => {
|
||||
if (!emailField.value) return;
|
||||
const res = await fetch(`/api/email/check?email=${encodeURIComponent(emailField.value)}`,
|
||||
{ method: "POST", headers: { [csrfHeader()]: csrfToken() } });
|
||||
if (!res.ok) showError(emailField, await res.text() || "Email already in use.");
|
||||
else clearError(emailField);
|
||||
});
|
||||
|
||||
usernameField.addEventListener("blur", async () => {
|
||||
if (!usernameField.value) {
|
||||
clearError(usernameField);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isProfane(usernameField.value)) {
|
||||
showError(usernameField, "Username contains inappropriate language.");
|
||||
return;
|
||||
}
|
||||
|
||||
clearError(usernameField);
|
||||
|
||||
const res = await fetch(`/api/users/check?name=${encodeURIComponent(usernameField.value)}`,
|
||||
{ method: "POST", headers: { [csrfHeader()]: csrfToken() } });
|
||||
|
||||
if (!res.ok) showError(usernameField, await res.text() || "Username already taken.");
|
||||
else clearError(usernameField);
|
||||
})
|
||||
|
||||
form.addEventListener("submit", async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
[usernameField, emailField, passwordField, confirmPasswordField].forEach(clearError);
|
||||
passwordError.textContent = "";
|
||||
|
||||
const password = passwordField.value;
|
||||
const confirmPassword = confirmPasswordField.value;
|
||||
const name = usernameField.value;
|
||||
const email = emailField.value;
|
||||
|
||||
if (password !== confirmPassword) {
|
||||
confirmPasswordField.classList.add("invalid");
|
||||
passwordError.textContent = "Passwords do not match.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (isProfane(name)) {
|
||||
showError(usernameField, "Username contains inappropriate language.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const headers = { [csrfHeader()]: csrfToken() };
|
||||
|
||||
const emailRes = await fetch(`/api/email/check?email=${encodeURIComponent(email)}`,
|
||||
{ method: "POST", headers });
|
||||
if (!emailRes.ok) {
|
||||
passwordError.style.color = "red";
|
||||
passwordError.textContent = await emailRes.text() || "Invalid email detected.";
|
||||
return;
|
||||
}
|
||||
|
||||
const userRes = await fetch(`/api/users/check?name=${encodeURIComponent(name)}`,
|
||||
{ method: "POST", headers });
|
||||
if (!userRes.ok) {
|
||||
passwordError.style.color = "red";
|
||||
passwordError.textContent = await userRes.text() || "Username already taken.";
|
||||
return;
|
||||
}
|
||||
|
||||
sessionStorage.setItem("pendingEmail", email);
|
||||
sessionStorage.setItem("pendingUser", JSON.stringify({
|
||||
username: name, email, hashedpassword: password, role: "ROLE_USER"
|
||||
}));
|
||||
|
||||
|
||||
if (passwordField.value !== confirmPasswordField.value) {
|
||||
confirmPasswordField.classList.add("invalid");
|
||||
passwordError.textContent = "Passwords do not match.";
|
||||
} else {
|
||||
confirmPasswordField.classList.remove("invalid");
|
||||
passwordError.textContent = "";
|
||||
}
|
||||
}
|
||||
const sendRes = await fetch(`/api/email/send?email=${encodeURIComponent(email)}`,
|
||||
{ method: "POST", headers });
|
||||
if (!sendRes.ok) {
|
||||
passwordError.style.color = "red";
|
||||
passwordError.textContent = "Failed to send verification email. Please check your address.";
|
||||
return;
|
||||
}
|
||||
|
||||
passwordField.addEventListener("input", checkPasswords);
|
||||
confirmPasswordField.addEventListener("input", checkPasswords);
|
||||
passwordError.style.color = "green";
|
||||
passwordError.textContent = "Check your email for a verification code...";
|
||||
setTimeout(() => { window.location.href = "/verify"; }, 1500);
|
||||
|
||||
form.addEventListener("submit", async function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const password = passwordField.value;
|
||||
const confirmPassword = confirmPasswordField.value;
|
||||
const name = document.getElementById("username").value;
|
||||
const email = document.getElementById("email").value;
|
||||
|
||||
if (password !== confirmPassword) {
|
||||
confirmPasswordField.classList.add("invalid");
|
||||
passwordError.textContent = "Passwords do not match.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (isProfane(document.getElementById("username").value)) {
|
||||
showError(username, 'Username contains inappropriate language');
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
passwordError.style.color = "red";
|
||||
passwordError.textContent = "Could not connect to the server.";
|
||||
console.error("Request error:", error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
const userData = {
|
||||
username: document.getElementById("username").value,
|
||||
email: document.getElementById("email").value,
|
||||
hashedpassword: password,
|
||||
role: "ROLE_USER"
|
||||
};
|
||||
function showError(input, message) {
|
||||
input.classList.add("invalid");
|
||||
passwordError.style.color = "red";
|
||||
passwordError.textContent = message;
|
||||
}
|
||||
|
||||
const csrfToken = document.querySelector('meta[name="_csrf"]').getAttribute('content');
|
||||
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').getAttribute('content');
|
||||
|
||||
try {
|
||||
const checkResponse = await fetch(`/api/email/check?email=${encodeURIComponent(email)}`, {
|
||||
method: "POST",
|
||||
headers: { [csrfHeader]: csrfToken }
|
||||
});
|
||||
|
||||
if (!checkResponse.ok) {
|
||||
const errorText = await checkResponse.text();
|
||||
passwordError.style.color = "red";
|
||||
passwordError.textContent = errorText || "Invalid Email Detected.";
|
||||
return;
|
||||
}
|
||||
|
||||
sessionStorage.setItem("pendingEmail", email);
|
||||
sessionStorage.setItem("pendingUser", JSON.stringify({
|
||||
username: name,
|
||||
email: email,
|
||||
hashedpassword: password,
|
||||
role: "ROLE_USER"
|
||||
}));
|
||||
|
||||
const sendResponse = await fetch(`/api/email/send?email=${encodeURIComponent(email)}`, {
|
||||
method: "POST",
|
||||
headers: { [csrfHeader]: csrfToken }
|
||||
});
|
||||
|
||||
if (!sendResponse.ok) {
|
||||
passwordError.style.color = "red";
|
||||
passwordError.textContent = "Failed to send verification email. Please check your address.";
|
||||
return;
|
||||
}
|
||||
|
||||
passwordError.style.color = "green";
|
||||
passwordError.textContent = "Check your email for a verification code...";
|
||||
setTimeout(function () {
|
||||
window.location.href = "/verify";
|
||||
}, 1500);
|
||||
|
||||
} catch (error) {
|
||||
passwordError.style.color = "red";
|
||||
passwordError.textContent = "Could not connect to the server.";
|
||||
console.error("Request error:", error);
|
||||
}
|
||||
});
|
||||
});
|
||||
function clearError(input) {
|
||||
input.classList.remove("invalid");
|
||||
passwordError.textContent = "";
|
||||
}
|
||||
|
||||
</script>
|
||||
Reference in New Issue
Block a user