package ru.mcs.diary.auth;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import ru.mcs.diary.auth.dto.ForgotPasswordRequest;
import ru.mcs.diary.auth.dto.ParentRegisterRequest;
import ru.mcs.diary.auth.dto.RegisterRequest;
import ru.mcs.diary.auth.dto.ResetPasswordRequest;
@Slf4j
@Controller
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {
private final AuthService authService;
// ==================== Логин ====================
@GetMapping("/login")
public String loginPage(@RequestParam(value = "error", required = false) String error,
@RequestParam(value = "logout", required = false) String logout,
Model model) {
if (error != null) {
model.addAttribute("error", "Неверный email или пароль");
}
if (logout != null) {
model.addAttribute("message", "Вы успешно вышли из системы");
}
return "auth/login";
}
// ==================== Регистрация преподавателя ====================
@GetMapping("/register")
public String registerPage(Model model) {
model.addAttribute("request", new RegisterRequest());
return "auth/register";
}
@PostMapping("/register")
public String register(@Valid @ModelAttribute("request") RegisterRequest request,
BindingResult bindingResult,
RedirectAttributes redirectAttributes,
Model model) {
if (bindingResult.hasErrors()) {
return "auth/register";
}
try {
authService.registerTeacher(request);
redirectAttributes.addFlashAttribute("message",
"Регистрация успешна! Теперь вы можете войти в систему.");
return "redirect:/auth/login";
} catch (IllegalArgumentException e) {
model.addAttribute("error", e.getMessage());
return "auth/register";
}
}
// ==================== Восстановление пароля ====================
@GetMapping("/forgot-password")
public String forgotPasswordPage(Model model) {
model.addAttribute("request", new ForgotPasswordRequest());
return "auth/forgot-password";
}
@PostMapping("/forgot-password")
public String forgotPassword(@Valid @ModelAttribute("request") ForgotPasswordRequest request,
BindingResult bindingResult,
RedirectAttributes redirectAttributes,
Model model) {
if (bindingResult.hasErrors()) {
return "auth/forgot-password";
}
try {
authService.initiatePasswordReset(request.getEmail());
// Всегда показываем успех (не раскрываем существование пользователя)
redirectAttributes.addFlashAttribute("message",
"Если указанный email зарегистрирован, на него отправлена ссылка для восстановления пароля.");
return "redirect:/auth/login";
} catch (Exception e) {
log.error("Error during password reset", e);
redirectAttributes.addFlashAttribute("message",
"Если указанный email зарегистрирован, на него отправлена ссылка для восстановления пароля.");
return "redirect:/auth/login";
}
}
@GetMapping("/reset-password")
public String resetPasswordPage(@RequestParam("token") String token, Model model) {
var validToken = authService.validatePasswordResetToken(token);
if (validToken.isEmpty()) {
model.addAttribute("error", "Недействительная или просроченная ссылка");
return "auth/reset-password-error";
}
ResetPasswordRequest request = new ResetPasswordRequest();
request.setToken(token);
model.addAttribute("request", request);
return "auth/reset-password";
}
@PostMapping("/reset-password")
public String resetPassword(@Valid @ModelAttribute("request") ResetPasswordRequest request,
BindingResult bindingResult,
RedirectAttributes redirectAttributes,
Model model) {
if (bindingResult.hasErrors()) {
return "auth/reset-password";
}
try {
authService.resetPassword(request);
redirectAttributes.addFlashAttribute("message",
"Пароль успешно изменён. Теперь вы можете войти с новым паролем.");
return "redirect:/auth/login";
} catch (IllegalArgumentException e) {
model.addAttribute("error", e.getMessage());
return "auth/reset-password";
}
}
// ==================== Регистрация родителя по приглашению ====================
@GetMapping("/parent/invite")
public String parentInvitePage(@RequestParam("token") String token, Model model) {
var validToken = authService.validateParentInviteToken(token);
if (validToken.isEmpty()) {
model.addAttribute("error", "Недействительная или просроченная ссылка приглашения");
return "auth/parent-invite-error";
}
var parent = validToken.get().getParent();
model.addAttribute("parentName", parent.getFullName());
model.addAttribute("parentEmail", parent.getEmail());
ParentRegisterRequest request = new ParentRegisterRequest();
request.setToken(token);
model.addAttribute("request", request);
return "auth/parent-invite";
}
@PostMapping("/parent/invite")
public String activateParent(@Valid @ModelAttribute("request") ParentRegisterRequest request,
BindingResult bindingResult,
RedirectAttributes redirectAttributes,
Model model) {
if (bindingResult.hasErrors()) {
// Восстанавливаем данные для отображения
var validToken = authService.validateParentInviteToken(request.getToken());
if (validToken.isPresent()) {
var parent = validToken.get().getParent();
model.addAttribute("parentName", parent.getFullName());
model.addAttribute("parentEmail", parent.getEmail());
}
return "auth/parent-invite";
}
try {
authService.activateParent(request);
redirectAttributes.addFlashAttribute("message",
"Регистрация успешна! Теперь вы можете войти в систему.");
return "redirect:/auth/login";
} catch (IllegalArgumentException e) {
model.addAttribute("error", e.getMessage());
return "auth/parent-invite";
}
}
}