Usun symulowane logowanie przez Google i Facebook
Deploy Polska Lokalnie / deploy (push) Successful in 30s
Deploy Polska Lokalnie / deploy (push) Successful in 30s
Endpoint /api/auth/social byl atrapa bez prawdziwego OAuth: wydawal token sesji dla dowolnego adresu e-mail podanego w zadaniu, bez hasla. Podanie adresu administratora dawalo pelna sesje z rola ADMIN. Na tym etapie logowanie ma byc wylacznie dla uzytkownikow systemu (e-mail i haslo), wiec usuwam je w calosci: - backend: endpoint, wpis permitAll w SecurityConfig, AuthService.socialLogin z pomocnikami i DTO SocialLoginRequest. Enum AuthProvider zostaje, bo istniejace konta moga miec GOOGLE/FACEBOOK. - frontend: przyciski Google/Facebook w formularzach logowania i rejestracji, socialLogin w AuthContext oraz osierocone style. Test regresyjny AuthControllerTest nie uruchomi sie jeszcze na H2 - start kontekstu wywraca sie na split_part w SQL naprawiajacym nicki (ten sam blad dotyczy istniejacego contextLoads). Zweryfikowane recznie na stacku z PostgreSQL: /api/auth/social -> 403, logowanie e-mailem -> 200. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -23,7 +23,6 @@ import pl.polskalokalnie.auth.dto.AuthResponse;
|
||||
import pl.polskalokalnie.auth.dto.LoginRequest;
|
||||
import pl.polskalokalnie.auth.dto.RegisterRequest;
|
||||
import pl.polskalokalnie.auth.dto.RegisterResponse;
|
||||
import pl.polskalokalnie.auth.dto.SocialLoginRequest;
|
||||
import pl.polskalokalnie.auth.dto.UpdateProfileRequest;
|
||||
import pl.polskalokalnie.auth.dto.UserResponse;
|
||||
|
||||
@@ -47,11 +46,6 @@ public class AuthController {
|
||||
return authService.login(request);
|
||||
}
|
||||
|
||||
@PostMapping("/social")
|
||||
public AuthResponse social(@Valid @RequestBody SocialLoginRequest request) {
|
||||
return authService.socialLogin(request);
|
||||
}
|
||||
|
||||
// --- Aktywacja konta ---
|
||||
|
||||
@PostMapping("/activate")
|
||||
|
||||
@@ -19,7 +19,6 @@ import pl.polskalokalnie.auth.dto.AuthResponse;
|
||||
import pl.polskalokalnie.auth.dto.LoginRequest;
|
||||
import pl.polskalokalnie.auth.dto.RegisterRequest;
|
||||
import pl.polskalokalnie.auth.dto.RegisterResponse;
|
||||
import pl.polskalokalnie.auth.dto.SocialLoginRequest;
|
||||
import pl.polskalokalnie.auth.dto.UpdateProfileRequest;
|
||||
import pl.polskalokalnie.auth.dto.UserResponse;
|
||||
import pl.polskalokalnie.user.AccountType;
|
||||
@@ -261,45 +260,6 @@ public class AuthService {
|
||||
return authToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Symulowane logowanie spoleczne: znajduje lub tworzy konto powiazane z dostawca.
|
||||
* Nie ma tu prawdziwego OAuth - dane przychodza z frontendu jako demo.
|
||||
*/
|
||||
public AuthResponse socialLogin(SocialLoginRequest request) {
|
||||
AuthProvider provider = request.provider();
|
||||
String email = normalizeEmail(
|
||||
request.email() != null && !request.email().isBlank()
|
||||
? request.email()
|
||||
: defaultSocialEmail(provider));
|
||||
String name = request.fullName() != null && !request.fullName().isBlank()
|
||||
? request.fullName().trim()
|
||||
: defaultSocialName(provider);
|
||||
|
||||
textModerationService.validateOrThrow(name);
|
||||
|
||||
AppUser user = userRepository.findByEmailIgnoreCase(email).orElseGet(() -> {
|
||||
if (blockedEmailRepository.existsByEmailIgnoreCase(email)) {
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Ten adres e-mail został zablokowany i nie można go już użyć do rejestracji");
|
||||
}
|
||||
AppUser created = new AppUser();
|
||||
created.setEmail(email);
|
||||
created.setFullName(name);
|
||||
created.setNick(nickService.generateFromName(name, email, null));
|
||||
created.setRole(Role.USER);
|
||||
created.setProvider(provider);
|
||||
// Logowanie spoleczne nie wymaga rekopisania danych, wiec konto jest od razu zweryfikowane.
|
||||
created.setVerified(true);
|
||||
return userRepository.save(created);
|
||||
});
|
||||
|
||||
if (user.isBlocked()) {
|
||||
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Konto zostało zablokowane");
|
||||
}
|
||||
|
||||
leadSyncService.syncUser(user);
|
||||
return buildAuthResponse(user);
|
||||
}
|
||||
|
||||
// Odstep, po ktorym wejscie do aplikacji (odswiezenie /auth/me) na nowo odnotowuje aktywnosc.
|
||||
// Bez tego zapisywalibysmy do bazy przy kazdym zadaniu profilu - a wystarczy zgrubna dokladnosc.
|
||||
private static final Duration LAST_ACTIVE_REFRESH = Duration.ofMinutes(2);
|
||||
@@ -491,20 +451,4 @@ public class AuthService {
|
||||
String source = fullName != null && !fullName.isBlank() ? fullName : user.getFullName();
|
||||
return nickService.generateFromName(source, user.getEmail(), user);
|
||||
}
|
||||
|
||||
private String defaultSocialEmail(AuthProvider provider) {
|
||||
return switch (provider) {
|
||||
case GOOGLE -> "demo.google@gmail.com";
|
||||
case FACEBOOK -> "demo.facebook@facebook.com";
|
||||
case LOCAL -> "demo.local@polskalokalnie.pl";
|
||||
};
|
||||
}
|
||||
|
||||
private String defaultSocialName(AuthProvider provider) {
|
||||
return switch (provider) {
|
||||
case GOOGLE -> "Użytkownik Google";
|
||||
case FACEBOOK -> "Użytkownik Facebook";
|
||||
case LOCAL -> "Użytkownik";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public class SecurityConfig {
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
||||
.requestMatchers("/error").permitAll()
|
||||
.requestMatchers("/api/auth/register", "/api/auth/login", "/api/auth/social").permitAll()
|
||||
.requestMatchers("/api/auth/register", "/api/auth/login").permitAll()
|
||||
.requestMatchers("/api/auth/activate", "/api/auth/resend-activation",
|
||||
"/api/auth/forgot-password", "/api/auth/reset-password",
|
||||
"/api/auth/verify-phone", "/api/auth/resend-phone-otp").permitAll()
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package pl.polskalokalnie.auth.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import pl.polskalokalnie.user.AuthProvider;
|
||||
|
||||
/**
|
||||
* Symulowane logowanie spoleczne. W wersji produkcyjnej email/name pochodzilyby
|
||||
* z tokenu dostawcy OAuth (Google/Facebook); tutaj przychodza z frontendu jako dane demo.
|
||||
*/
|
||||
public record SocialLoginRequest(
|
||||
@NotNull AuthProvider provider,
|
||||
String email,
|
||||
String fullName
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package pl.polskalokalnie.auth;
|
||||
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
class AuthControllerTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
// Regresja: symulowane logowanie spoleczne wydawalo token dla dowolnego adresu e-mail
|
||||
// bez hasla - wystarczylo podac adres administratora, zeby dostac jego sesje.
|
||||
@Test
|
||||
void socialLoginEndpointDoesNotIssueToken() throws Exception {
|
||||
mockMvc.perform(post("/api/auth/social")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"provider\":\"GOOGLE\",\"email\":\"admin@softspm.com\"}"))
|
||||
.andExpect(status().is4xxClientError())
|
||||
.andExpect(content().string(not(containsString("token"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void adminCanLogInWithEmailAndPassword() throws Exception {
|
||||
mockMvc.perform(post("/api/auth/login")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"email\":\"admin@softspm.com\",\"password\":\"Admin123!\"}"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.token").isNotEmpty())
|
||||
.andExpect(jsonPath("$.user.role").value("ADMIN"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user