refacto : review auth part 1
This commit is contained in:
@@ -136,7 +136,7 @@ export default function SettingsPage() {
|
|||||||
password,
|
password,
|
||||||
};
|
};
|
||||||
|
|
||||||
storageService.setCredentials(
|
storageService.setKomgaConfig(
|
||||||
{
|
{
|
||||||
serverUrl: newConfig.serverUrl,
|
serverUrl: newConfig.serverUrl,
|
||||||
credentials: { username: newConfig.username, password: newConfig.password },
|
credentials: { username: newConfig.username, password: newConfig.password },
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { AuthError } from "@/types/auth";
|
import { AuthError } from "@/types/auth";
|
||||||
import { storageService } from "./storage.service";
|
import { storageService } from "./storage.service";
|
||||||
import { KomgaUser } from "@/types/komga";
|
|
||||||
|
|
||||||
interface AuthUser {
|
interface AuthUser {
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
import { KomgaUser, KomgaLibrary, KomgaSeries, KomgaBook, ReadProgress } from "@/types/komga";
|
|
||||||
import { AuthConfig } from "@/types/auth";
|
|
||||||
import { storageService } from "./storage.service";
|
|
||||||
|
|
||||||
class KomgaService {
|
|
||||||
private static instance: KomgaService;
|
|
||||||
|
|
||||||
private constructor() {}
|
|
||||||
|
|
||||||
public static getInstance(): KomgaService {
|
|
||||||
if (!KomgaService.instance) {
|
|
||||||
KomgaService.instance = new KomgaService();
|
|
||||||
}
|
|
||||||
return KomgaService.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Crée les headers d'authentification
|
|
||||||
*/
|
|
||||||
private getAuthHeaders(config?: AuthConfig): Headers {
|
|
||||||
const headers = new Headers();
|
|
||||||
const credentials = config || storageService.getCredentials();
|
|
||||||
|
|
||||||
if (credentials?.credentials) {
|
|
||||||
const { username, password } = credentials.credentials;
|
|
||||||
headers.set("Authorization", `Basic ${btoa(`${username}:${password}`)}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vérifie les credentials en récupérant l'utilisateur courant
|
|
||||||
*/
|
|
||||||
async checkCredentials(config: AuthConfig): Promise<KomgaUser> {
|
|
||||||
const response = await fetch(`${config.serverUrl}/api/v1/libraries`, {
|
|
||||||
headers: this.getAuthHeaders(config),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Invalid credentials");
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Récupère les bibliothèques
|
|
||||||
*/
|
|
||||||
async getLibraries(): Promise<KomgaLibrary[]> {
|
|
||||||
const credentials = storageService.getCredentials();
|
|
||||||
if (!credentials) throw new Error("Not authenticated");
|
|
||||||
|
|
||||||
const response = await fetch(`${credentials.serverUrl}/api/v1/libraries`, {
|
|
||||||
headers: this.getAuthHeaders(),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Failed to fetch libraries");
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Récupère l'URL de la couverture d'une bibliothèque
|
|
||||||
*/
|
|
||||||
getLibraryThumbnailUrl(libraryId: string): string {
|
|
||||||
const credentials = storageService.getCredentials();
|
|
||||||
if (!credentials) throw new Error("Not authenticated");
|
|
||||||
|
|
||||||
return `${credentials.serverUrl}/api/v1/libraries/${libraryId}/thumbnail`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Récupère les séries d'une bibliothèque
|
|
||||||
*/
|
|
||||||
async getLibrarySeries(libraryId: string): Promise<KomgaSeries[]> {
|
|
||||||
const credentials = storageService.getCredentials();
|
|
||||||
if (!credentials) throw new Error("Not authenticated");
|
|
||||||
|
|
||||||
const response = await fetch(`${credentials.serverUrl}/api/v1/libraries/${libraryId}/series`, {
|
|
||||||
headers: this.getAuthHeaders(),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Failed to fetch series");
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Récupère les livres d'une série
|
|
||||||
*/
|
|
||||||
async getSeriesBooks(seriesId: string): Promise<KomgaBook[]> {
|
|
||||||
const credentials = storageService.getCredentials();
|
|
||||||
if (!credentials) throw new Error("Not authenticated");
|
|
||||||
|
|
||||||
const response = await fetch(`${credentials.serverUrl}/api/v1/series/${seriesId}/books`, {
|
|
||||||
headers: this.getAuthHeaders(),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Failed to fetch books");
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Récupère l'URL de la couverture d'un livre
|
|
||||||
*/
|
|
||||||
getBookThumbnailUrl(bookId: string): string {
|
|
||||||
const credentials = storageService.getCredentials();
|
|
||||||
if (!credentials) throw new Error("Not authenticated");
|
|
||||||
|
|
||||||
return `${credentials.serverUrl}/api/v1/books/${bookId}/thumbnail`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Récupère l'URL de lecture d'un livre
|
|
||||||
*/
|
|
||||||
getBookReadingUrl(bookId: string): string {
|
|
||||||
const credentials = storageService.getCredentials();
|
|
||||||
if (!credentials) throw new Error("Not authenticated");
|
|
||||||
|
|
||||||
return `${credentials.serverUrl}/api/v1/books/${bookId}/pages/1`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Récupère la progression de lecture d'une série
|
|
||||||
*/
|
|
||||||
async getSeriesReadProgress(seriesId: string): Promise<ReadProgress> {
|
|
||||||
const credentials = storageService.getCredentials();
|
|
||||||
if (!credentials) throw new Error("Not authenticated");
|
|
||||||
|
|
||||||
const response = await fetch(
|
|
||||||
`${credentials.serverUrl}/api/v1/series/${seriesId}/read-progress`,
|
|
||||||
{
|
|
||||||
headers: this.getAuthHeaders(),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Failed to fetch series read progress");
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.json();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const komgaService = KomgaService.getInstance();
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { AuthConfig } from "@/types/auth";
|
import { AuthConfig } from "@/types/auth";
|
||||||
|
|
||||||
const CREDENTIALS_KEY = "komgaCredentials";
|
const KOMGACREDENTIALS_KEY = "komgaCredentials";
|
||||||
const USER_KEY = "komgaUser";
|
const USER_KEY = "stripUser";
|
||||||
const TTL_CONFIG_KEY = "ttlConfig";
|
const TTL_CONFIG_KEY = "ttlConfig";
|
||||||
|
|
||||||
interface TTLConfig {
|
interface TTLConfig {
|
||||||
@@ -28,7 +28,7 @@ class StorageService {
|
|||||||
/**
|
/**
|
||||||
* Stocke les credentials de manière sécurisée
|
* Stocke les credentials de manière sécurisée
|
||||||
*/
|
*/
|
||||||
setCredentials(config: AuthConfig, remember: boolean = false): void {
|
setKomgaConfig(config: AuthConfig, remember: boolean = false): void {
|
||||||
const storage = remember ? localStorage : sessionStorage;
|
const storage = remember ? localStorage : sessionStorage;
|
||||||
|
|
||||||
// Encodage basique des credentials en base64
|
// Encodage basique des credentials en base64
|
||||||
@@ -41,10 +41,10 @@ class StorageService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
storage.setItem(CREDENTIALS_KEY, encoded);
|
storage.setItem(KOMGACREDENTIALS_KEY, encoded);
|
||||||
|
|
||||||
// Définir aussi un cookie pour le middleware
|
// Définir aussi un cookie pour le middleware
|
||||||
const cookieValue = `${CREDENTIALS_KEY}=${encoded}; path=/; samesite=strict`;
|
const cookieValue = `${KOMGACREDENTIALS_KEY}=${encoded}; path=/; samesite=strict`;
|
||||||
const maxAge = remember ? `; max-age=${30 * 24 * 60 * 60}` : "";
|
const maxAge = remember ? `; max-age=${30 * 24 * 60 * 60}` : "";
|
||||||
document.cookie = cookieValue + maxAge;
|
document.cookie = cookieValue + maxAge;
|
||||||
|
|
||||||
@@ -58,10 +58,10 @@ class StorageService {
|
|||||||
if (typeof window === "undefined") return null;
|
if (typeof window === "undefined") return null;
|
||||||
|
|
||||||
const storage =
|
const storage =
|
||||||
localStorage.getItem(CREDENTIALS_KEY) || sessionStorage.getItem(CREDENTIALS_KEY);
|
localStorage.getItem(KOMGACREDENTIALS_KEY) || sessionStorage.getItem(KOMGACREDENTIALS_KEY);
|
||||||
console.log("StorageService - Lecture des credentials:", {
|
console.log("StorageService - Lecture des credentials:", {
|
||||||
fromLocalStorage: !!localStorage.getItem(CREDENTIALS_KEY),
|
fromLocalStorage: !!localStorage.getItem(KOMGACREDENTIALS_KEY),
|
||||||
fromSessionStorage: !!sessionStorage.getItem(CREDENTIALS_KEY),
|
fromSessionStorage: !!sessionStorage.getItem(KOMGACREDENTIALS_KEY),
|
||||||
value: storage,
|
value: storage,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -135,17 +135,17 @@ class StorageService {
|
|||||||
* Efface toutes les données stockées
|
* Efface toutes les données stockées
|
||||||
*/
|
*/
|
||||||
clear(): void {
|
clear(): void {
|
||||||
localStorage.removeItem(CREDENTIALS_KEY);
|
localStorage.removeItem(KOMGACREDENTIALS_KEY);
|
||||||
localStorage.removeItem(USER_KEY);
|
localStorage.removeItem(USER_KEY);
|
||||||
sessionStorage.removeItem(CREDENTIALS_KEY);
|
sessionStorage.removeItem(KOMGACREDENTIALS_KEY);
|
||||||
sessionStorage.removeItem(USER_KEY);
|
sessionStorage.removeItem(USER_KEY);
|
||||||
document.cookie = `${CREDENTIALS_KEY}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
document.cookie = `${KOMGACREDENTIALS_KEY}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
||||||
document.cookie = `${USER_KEY}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
document.cookie = `${USER_KEY}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
||||||
}
|
}
|
||||||
|
|
||||||
getUser() {
|
getUser() {
|
||||||
try {
|
try {
|
||||||
const userStr = localStorage.getItem("komgaUser");
|
const userStr = localStorage.getItem(USER_KEY);
|
||||||
if (!userStr) return null;
|
if (!userStr) return null;
|
||||||
return JSON.parse(atob(userStr));
|
return JSON.parse(atob(userStr));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -155,9 +155,17 @@ class StorageService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearAll() {
|
clearAll() {
|
||||||
localStorage.removeItem("komgaUser");
|
localStorage.removeItem(USER_KEY);
|
||||||
localStorage.removeItem("komgaCredentials");
|
localStorage.removeItem(KOMGACREDENTIALS_KEY);
|
||||||
localStorage.removeItem("ttlConfig");
|
localStorage.removeItem(TTL_CONFIG_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
getKeys() {
|
||||||
|
return {
|
||||||
|
credentials: KOMGACREDENTIALS_KEY,
|
||||||
|
user: USER_KEY,
|
||||||
|
ttlConfig: TTL_CONFIG_KEY,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export function middleware(request: NextRequest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pour les routes protégées, vérifier la présence de l'utilisateur
|
// Pour les routes protégées, vérifier la présence de l'utilisateur
|
||||||
const user = request.cookies.get("komgaUser");
|
const user = request.cookies.get("stripUser");
|
||||||
if (!user) {
|
if (!user) {
|
||||||
const loginUrl = new URL("/login", request.url);
|
const loginUrl = new URL("/login", request.url);
|
||||||
loginUrl.searchParams.set("from", pathname);
|
loginUrl.searchParams.set("from", pathname);
|
||||||
|
|||||||
Reference in New Issue
Block a user