test: subdomaind api
All checks were successful
Update changelog / changelog (push) Successful in 26s
All checks were successful
Update changelog / changelog (push) Successful in 26s
This commit is contained in:
@@ -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={{
|
||||||
|
|||||||
@@ -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'],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Reference in New Issue
Block a user