fix: login in works in subdomain
All checks were successful
Update changelog / changelog (push) Successful in 28s
All checks were successful
Update changelog / changelog (push) Successful in 28s
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Reference in New Issue
Block a user