test: subdomaind api
All checks were successful
Update changelog / changelog (push) Successful in 26s

This commit is contained in:
Pc
2026-01-03 19:00:48 +01:00
parent fc0ee5a4d6
commit 4fa55b4caf
2 changed files with 43 additions and 57 deletions

View File

@@ -3,37 +3,61 @@ 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';
// Pobieramy bazowy adres i usuwamy ewentualny ukośnik na końcu // Bazowy URL z .env (np. "https://api.moja-aplikacja.pl")
// Używamy import.meta.env, który jest dostępny wewnątrz kodu React
const API_BASE_URL = (import.meta.env.VITE_API_TARGET || '').replace(/\/$/, ''); const API_BASE_URL = (import.meta.env.VITE_API_TARGET || '').replace(/\/$/, '');
/**
* Funkcja pomocnicza do pobierania subdomeny.
* Przykład: 'klient1.aplikacja.pl' -> 'klient1'
*/
const getSubdomain = () => {
const hostname = window.location.hostname;
const parts = hostname.split('.');
// Obsługa localhost i prostych domen (np. localhost lub moja-strona.pl)
if (parts.length <= 2) return null;
// Zwraca pierwszy człon (subdomenę)
return parts[0];
};
export function AuthProvider({ children }: { children: ReactNode }) { export function AuthProvider({ children }: { children: ReactNode }) {
const [token, setToken] = useState<string | null>(sessionStorage.getItem('ktty_token')); // Klucz tokena może być specyficzny dla subdomeny, aby sesje się nie mieszały
const subdomain = getSubdomain();
const storageKey = subdomain ? `ktty_token_${subdomain}` : 'ktty_token';
const [token, setToken] = useState<string | null>(sessionStorage.getItem(storageKey));
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
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) { if (!API_BASE_URL) {
const msg = "Błąd konfiguracji: VITE_API_TARGET jest pusty. Sprawdź plik .env i restartuj serwer."; const msg = "Błąd konfiguracji: VITE_API_TARGET jest pusty.";
setError(msg); setError(msg);
return null; return null;
} }
setLoading(true); setLoading(true);
setError(null); setError(null);
try { try {
const hashedPassword = await sha512(pass); const hashedPassword = await sha512(pass);
const fullUrl = `${API_BASE_URL}/api/v1/user/${endpoint}`;
// DYNAMICZNY URL:
// Możesz wstawić subdomenę jako część ścieżki lub jako subdomenę API
// Opcja A (ścieżka): `${API_BASE_URL}/${subdomain}/api/v1/...`
// Opcja B (subdomena): `https://${subdomain}.api.twoja-domena.pl/...`
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 || '',
}, },
body: JSON.stringify({ name, password: hashedPassword, ttl: 86400 }), body: JSON.stringify({ name, password: hashedPassword, ttl: 86400 }),
}); });
@@ -51,7 +75,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
} }
if (data && data.token) { if (data && data.token) {
sessionStorage.setItem('ktty_token', data.token); sessionStorage.setItem(storageKey, data.token);
setToken(data.token); setToken(data.token);
} }
return data; return data;
@@ -62,12 +86,12 @@ export function AuthProvider({ children }: { children: ReactNode }) {
} finally { } finally {
setLoading(false); setLoading(false);
} }
}, []); }, [subdomain, storageKey]);
const logout = useCallback(() => { const logout = useCallback(() => {
sessionStorage.removeItem('ktty_token'); sessionStorage.removeItem(storageKey);
setToken(null); setToken(null);
}, []); }, [storageKey]);
return ( return (
<AuthContext.Provider value={{ <AuthContext.Provider value={{

View File

@@ -1,67 +1,29 @@
import { defineConfig, loadEnv, type Plugin } from 'vite' // Zmieniono na 'type Plugin' import { defineConfig, loadEnv } 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'
// Plugin obsługujący logikę przekierowań
const domainRedirectPlugin = (targetUrl: string, useSubdomains: boolean, debug: boolean): Plugin => ({
name: 'domain-redirect',
configureServer(server) {
server.middlewares.use((req, res, next) => {
const host = req.headers.host; // np. "ssss.localhost:6568"
if (!host) return next();
const hostname = host.split(':')[0]; // usuwamy port, zostaje "ssss.localhost"
const targetHost = new URL(targetUrl).hostname;
// LOGIKA TESTOWA DLA LOCALHOST:
// Jeśli host to np. ssss.localhost, a nie czysty localhost:
const isSubdomainOfLocalhost = hostname.endsWith('.localhost');
const isPureLocalhost = hostname === 'localhost' || hostname === '127.0.0.1';
if (debug) {
console.log(`[Debug] Host: ${hostname}, SubOfLocal: ${isSubdomainOfLocalhost}, Pure: ${isPureLocalhost}`);
}
// Przekieruj jeśli:
// 1. To subdomena localhosta (do testów)
// 2. LUB to subdomena ktty.is, a subdomeny są wyłączone
if ((isSubdomainOfLocalhost && hostname !== 'localhost') || (useSubdomains && hostname !== targetHost && !isPureLocalhost)) {
if (debug) console.log(`[Redirect] Z ${hostname} na ${targetUrl}`);
res.writeHead(301, { Location: `${targetUrl}${req.url}` });
return res.end();
}
next();
});
}
});
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, '');
// Twoje zmienne z .env
const publicUrl = env.PUBLIC_URL;
const useSubdomains = env.USE_SUBDOMAINS === 'true';
const isDebug = env.DEBUG === 'true';
return { return {
envDir: envDirectory, envDir: envDirectory,
plugins: [ plugins: [
react(), react(),
tailwindcss(), tailwindcss(),
domainRedirectPlugin(publicUrl, useSubdomains, isDebug)
], ],
server: { server: {
port: 6568, port: 6568,
host: true,
}, },
preview: { preview: {
port: 6568, port: 6568,
allowedHosts: [env.VITE_ALLOWED_HOST],
allowedHosts: [env.VITE_ALLOWED_HOST , 'localhost'],
}, },
} }
}) })