fix: login in works in subdomain
All checks were successful
Update changelog / changelog (push) Successful in 28s

This commit is contained in:
Pc
2026-01-04 13:33:15 +01:00
parent 4fa55b4caf
commit 549da339e4
2 changed files with 39 additions and 44 deletions

View File

@@ -3,26 +3,17 @@ import { AuthContext } from './AuthContext';
import { sha512 } from '../utils/crypto'; import { sha512 } from '../utils/crypto';
import type { AuthResponse } from '../types/auth'; import type { AuthResponse } from '../types/auth';
// Bazowy URL z .env (np. "https://api.moja-aplikacja.pl")
const API_BASE_URL = (import.meta.env.VITE_API_TARGET || '').replace(/\/$/, '');
/** /**
* Funkcja pomocnicza do pobierania subdomeny. * Funkcja pomocnicza do pobierania subdomeny.
* Przykład: 'klient1.aplikacja.pl' -> 'klient1'
*/ */
const getSubdomain = () => { const getSubdomain = (): string | null => {
const hostname = window.location.hostname; const hostname = window.location.hostname;
const parts = hostname.split('.'); const parts = hostname.split('.');
// Obsługa localhost i prostych domen (np. localhost lub moja-strona.pl)
if (parts.length <= 2) return null; if (parts.length <= 2) return null;
// Zwraca pierwszy człon (subdomenę)
return parts[0]; return parts[0];
}; };
export function AuthProvider({ children }: { children: ReactNode }) { export function AuthProvider({ children }: { children: ReactNode }) {
// Klucz tokena może być specyficzny dla subdomeny, aby sesje się nie mieszały
const subdomain = getSubdomain(); const subdomain = getSubdomain();
const storageKey = subdomain ? `ktty_token_${subdomain}` : 'ktty_token'; const storageKey = subdomain ? `ktty_token_${subdomain}` : 'ktty_token';
@@ -31,57 +22,51 @@ export function AuthProvider({ children }: { children: ReactNode }) {
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const authRequest = useCallback(async (endpoint: 'signUp' | 'signIn', name: string, pass: string) => { const authRequest = useCallback(async (endpoint: 'signUp' | 'signIn', name: string, pass: string) => {
if (!API_BASE_URL) {
const msg = "Błąd konfiguracji: VITE_API_TARGET jest pusty.";
setError(msg);
return null;
}
setLoading(true); setLoading(true);
setError(null); setError(null);
try { try {
const hashedPassword = await sha512(pass); const hashedPassword = await sha512(pass);
// DYNAMICZNY URL: // Korzystamy z relatywnej ścieżki /api, którą Vite Proxy przekaże dalej.
// Możesz wstawić subdomenę jako część ścieżki lub jako subdomenę API // Usuwamy API_BASE_URL, aby uniknąć błędów o nieużywanej zmiennej.
// Opcja A (ścieżka): `${API_BASE_URL}/${subdomain}/api/v1/...` const pathPrefix = subdomain ? `/api/${subdomain}` : '/api';
// Opcja B (subdomena): `https://${subdomain}.api.twoja-domena.pl/...` const fullUrl = `${pathPrefix}/v1/user/${endpoint}`;
const urlPrefix = subdomain ? `${API_BASE_URL}/${subdomain}` : API_BASE_URL;
const fullUrl = `${urlPrefix}/api/v1/user/${endpoint}`;
const response = await fetch(fullUrl, { const response = await fetch(fullUrl, {
method: 'POST', method: 'POST',
headers: { headers: {
'accept': 'application/json', 'accept': 'application/json',
'Content-Type': 'application/json', 'Content-Type': 'application/json',
// Opcjonalnie: przesyłanie subdomeny w nagłówku, jeśli API tego wymaga
'X-Subdomain': subdomain || '', 'X-Subdomain': subdomain || '',
}, },
body: JSON.stringify({ name, password: hashedPassword, ttl: 86400 }), body: JSON.stringify({ name, password: hashedPassword, ttl: 86400 }),
}); });
const contentType = response.headers.get("content-type"); // Rozwiązanie błędu "Unexpected any": definiujemy typ danych przed użyciem
let data: AuthResponse | null = null; const data: AuthResponse = await response.json();
if (contentType && contentType.includes("application/json")) {
data = await response.json();
}
if (!response.ok) { if (!response.ok) {
const errorMsg = data?.error || data?.message || `Błąd serwera: ${response.status}`; const errorMsg = data?.error || data?.message || `Błąd serwera: ${response.status}`;
throw new Error(errorMsg); throw new Error(errorMsg);
} }
if (data && data.token) { if (data?.token) {
sessionStorage.setItem(storageKey, data.token); sessionStorage.setItem(storageKey, data.token);
setToken(data.token); setToken(data.token);
} }
return data; return data;
} catch (err: unknown) { } catch (err: unknown) {
const message = err instanceof Error ? err.message : 'Unknown error'; // Rozwiązanie błędu "Unexpected any" w bloku catch:
setError(message); let errorMessage = 'Wystąpił nieoczekiwany błąd';
if (err instanceof Error) {
errorMessage = err.message;
} else if (typeof err === 'string') {
errorMessage = err;
}
setError(errorMessage);
return null; return null;
} finally { } finally {
setLoading(false); setLoading(false);

View File

@@ -1,29 +1,39 @@
import { defineConfig, loadEnv } from 'vite' import { defineConfig, loadEnv, type PluginOption } from 'vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
import tailwindcss from '@tailwindcss/vite' import tailwindcss from '@tailwindcss/vite'
import path from 'path' import path from 'path'
import { fileURLToPath } from 'url'
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default defineConfig(({ mode }) => { export default defineConfig(({ mode }) => {
// Ścieżka do folderu nadrzędnego
const envDirectory = path.resolve(__dirname, '..'); const envDirectory = path.resolve(__dirname, '..');
// Wczytujemy zmienne do użytku
const env = loadEnv(mode, envDirectory, ''); const env = loadEnv(mode, envDirectory, '');
const backendTarget = env.VITE_API_TARGET;
return { return {
envDir: envDirectory,
envDir: envDirectory,
plugins: [ plugins: [
react(), react() as PluginOption,
tailwindcss(), tailwindcss() as PluginOption,
], ],
server: { server: {
port: 6568, port: 6568,
host: true,
proxy: {
'/api': {
target: backendTarget,
changeOrigin: true,
secure: false,
},
},
}, },
preview: { preview: {
port: 6568, port: 6568,
allowedHosts: [env.VITE_ALLOWED_HOST], allowedHosts: true,
}, },
} }
}) })