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:
+6
-55
@@ -12984,28 +12984,8 @@ type LoginStep = 'login' | 'register-choice' | 'register-private' | 'register-co
|
||||
// Dane firmy z rejestru REGON (GUS) - odpowiedz /api/gus/company.
|
||||
type GusCompany = { name: string | null; nip: string; regon: string | null; address: string | null };
|
||||
|
||||
// Oficjalne logotypy dostawcow logowania spolecznosciowego (SVG w barwach marki).
|
||||
function GoogleIcon() {
|
||||
return (
|
||||
<svg className="social-login-icon" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true">
|
||||
<path fill="#4285F4" d="M17.64 9.205c0-.639-.057-1.252-.164-1.841H9v3.481h4.844a4.14 4.14 0 0 1-1.796 2.716v2.259h2.908c1.702-1.567 2.684-3.875 2.684-6.615z" />
|
||||
<path fill="#34A853" d="M9 18c2.43 0 4.467-.806 5.956-2.18l-2.908-2.259c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.957v2.332A8.997 8.997 0 0 0 9 18z" />
|
||||
<path fill="#FBBC05" d="M3.964 10.71A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.957A8.996 8.996 0 0 0 0 9c0 1.452.348 2.827.957 4.042l3.007-2.332z" />
|
||||
<path fill="#EA4335" d="M9 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.581C13.463.891 11.426 0 9 0A8.997 8.997 0 0 0 .957 4.958L3.964 7.29C4.672 5.163 6.656 3.58 9 3.58z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function FacebookIcon() {
|
||||
return (
|
||||
<svg className="social-login-icon" width="18" height="18" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path fill="#1877F2" d="M24 12.073C24 5.404 18.627 0 12 0S0 5.404 0 12.073c0 6.026 4.388 11.02 10.125 11.926v-8.437H7.078v-3.49h3.047V9.41c0-3.017 1.792-4.686 4.533-4.686 1.312 0 2.686.235 2.686.235v2.97h-1.513c-1.49 0-1.955.93-1.955 1.886v2.259h3.328l-.532 3.489h-2.796v8.437C19.612 23.094 24 18.1 24 12.073z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function LoginPage({ onLogin }: { onLogin: (user: AuthUser) => void }) {
|
||||
const { login, register, socialLogin, forgotPassword, resendActivation } = useAuth();
|
||||
const { login, register, forgotPassword, resendActivation } = useAuth();
|
||||
const [step, setStep] = useState<LoginStep>('login');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
@@ -13181,37 +13161,8 @@ function LoginPage({ onLogin }: { onLogin: (user: AuthUser) => void }) {
|
||||
}
|
||||
};
|
||||
|
||||
const socialButtons = (
|
||||
<>
|
||||
<div className="login-divider">
|
||||
<span>lub kontynuuj z</span>
|
||||
</div>
|
||||
|
||||
<div className="social-login-row">
|
||||
<button
|
||||
className="social-login"
|
||||
type="button"
|
||||
disabled={submitting}
|
||||
onClick={() => runAuth(() => socialLogin('GOOGLE'))}
|
||||
aria-label="Kontynuuj z Google"
|
||||
>
|
||||
<GoogleIcon />
|
||||
<span>Google</span>
|
||||
</button>
|
||||
<button
|
||||
className="social-login"
|
||||
type="button"
|
||||
disabled={submitting}
|
||||
onClick={() => runAuth(() => socialLogin('FACEBOOK'))}
|
||||
aria-label="Kontynuuj z Facebookiem"
|
||||
>
|
||||
<FacebookIcon />
|
||||
<span>Facebook</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="login-security-note"><Icon name="lock" /> Twoje dane są u nas bezpieczne. Stosujemy szyfrowanie SSL.</p>
|
||||
</>
|
||||
const securityNote = (
|
||||
<p className="login-security-note"><Icon name="lock" /> Twoje dane są u nas bezpieczne. Stosujemy szyfrowanie SSL.</p>
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -13326,7 +13277,7 @@ function LoginPage({ onLogin }: { onLogin: (user: AuthUser) => void }) {
|
||||
{submitting ? 'Przetwarzanie…' : 'Zaloguj się'}
|
||||
</button>
|
||||
|
||||
{socialButtons}
|
||||
{securityNote}
|
||||
</form>
|
||||
)}
|
||||
|
||||
@@ -13493,7 +13444,7 @@ function LoginPage({ onLogin }: { onLogin: (user: AuthUser) => void }) {
|
||||
{submitting ? 'Przetwarzanie…' : 'Zarejestruj się'}
|
||||
</button>
|
||||
|
||||
{socialButtons}
|
||||
{securityNote}
|
||||
</form>
|
||||
)}
|
||||
|
||||
@@ -13650,7 +13601,7 @@ function LoginPage({ onLogin }: { onLogin: (user: AuthUser) => void }) {
|
||||
{submitting ? 'Przetwarzanie…' : 'Zarejestruj firmę'}
|
||||
</button>
|
||||
|
||||
{socialButtons}
|
||||
{securityNote}
|
||||
</form>
|
||||
)}
|
||||
|
||||
|
||||
+2
-12
@@ -104,7 +104,6 @@ type AuthContextValue = {
|
||||
loading: boolean;
|
||||
login: (email: string, password: string) => Promise<AuthUser>;
|
||||
register: (email: string, password: string, fullName: string, details?: RegisterDetails) => Promise<RegisterPending>;
|
||||
socialLogin: (provider: Exclude<AuthProviderName, 'LOCAL'>) => Promise<AuthUser>;
|
||||
activateAccount: (token: string) => Promise<void>;
|
||||
resendActivation: (email: string) => Promise<void>;
|
||||
forgotPassword: (email: string) => Promise<void>;
|
||||
@@ -266,15 +265,6 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
[],
|
||||
);
|
||||
|
||||
const socialLogin = useCallback(
|
||||
async (provider: Exclude<AuthProviderName, 'LOCAL'>) =>
|
||||
applyAuth(await apiFetch<AuthResponse>('/auth/social', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ provider }),
|
||||
})),
|
||||
[applyAuth],
|
||||
);
|
||||
|
||||
const activateAccount = useCallback(async (token: string) => {
|
||||
await apiFetch<void>('/auth/activate', { method: 'POST', body: JSON.stringify({ token }) });
|
||||
}, []);
|
||||
@@ -372,11 +362,11 @@ export function AuthProvider({ children }: { children: ReactNode }) {
|
||||
|
||||
const value = useMemo<AuthContextValue>(
|
||||
() => ({
|
||||
user, token, loading, login, register, socialLogin,
|
||||
user, token, loading, login, register,
|
||||
activateAccount, resendActivation, forgotPassword, resetPassword, verifyPhone, resendPhoneOtp,
|
||||
updateProfile, changePassword, verifyPassword, passwordCooldown, deleteAccount, loadSettings, loadSearchPreferences, saveSettings, refreshUser, logout,
|
||||
}),
|
||||
[user, token, loading, login, register, socialLogin,
|
||||
[user, token, loading, login, register,
|
||||
activateAccount, resendActivation, forgotPassword, resetPassword, verifyPhone, resendPhoneOtp,
|
||||
updateProfile, changePassword, verifyPassword, passwordCooldown, deleteAccount, loadSettings, loadSearchPreferences, saveSettings, refreshUser, logout],
|
||||
);
|
||||
|
||||
+1
-65
@@ -13604,67 +13604,6 @@ a.city-card:hover {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.login-divider {
|
||||
align-items: center;
|
||||
color: #6e7d92;
|
||||
display: grid;
|
||||
font-size: 13px;
|
||||
font-weight: 850;
|
||||
grid-template-columns: 1fr auto 1fr;
|
||||
gap: 9px;
|
||||
}
|
||||
|
||||
.login-divider::before,
|
||||
.login-divider::after {
|
||||
background: #dfe5ed;
|
||||
content: "";
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.social-login-row {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.social-login {
|
||||
align-items: center;
|
||||
background: #ffffff;
|
||||
border: 1px solid #dce4ec;
|
||||
border-radius: 10px;
|
||||
color: #24344b;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex: 1 1 0;
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
gap: 9px;
|
||||
height: 46px;
|
||||
justify-content: center;
|
||||
min-width: 0;
|
||||
transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
|
||||
}
|
||||
|
||||
.social-login:hover:not(:disabled) {
|
||||
background: #f7f9fc;
|
||||
border-color: #c4d2e2;
|
||||
box-shadow: 0 2px 10px rgba(20, 34, 58, 0.07);
|
||||
}
|
||||
|
||||
.social-login:disabled {
|
||||
cursor: default;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.social-login-icon {
|
||||
flex: 0 0 auto;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.social-login-row { flex-direction: column; }
|
||||
}
|
||||
|
||||
.login-security-note {
|
||||
align-items: center;
|
||||
color: #7a8798;
|
||||
@@ -14018,8 +13957,6 @@ a.city-card:hover {
|
||||
.remember-me,
|
||||
.forgot-password,
|
||||
.login-submit,
|
||||
.social-login,
|
||||
.login-divider,
|
||||
.login-security-note {
|
||||
font-size: 13px;
|
||||
}
|
||||
@@ -14035,8 +13972,7 @@ a.city-card:hover {
|
||||
}
|
||||
|
||||
.login-field input,
|
||||
.login-submit,
|
||||
.social-login {
|
||||
.login-submit {
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user