refacto : review auth part 1
This commit is contained in:
@@ -136,7 +136,7 @@ export default function SettingsPage() {
|
||||
password,
|
||||
};
|
||||
|
||||
storageService.setCredentials(
|
||||
storageService.setKomgaConfig(
|
||||
{
|
||||
serverUrl: newConfig.serverUrl,
|
||||
credentials: { username: newConfig.username, password: newConfig.password },
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { AuthError } from "@/types/auth";
|
||||
import { storageService } from "./storage.service";
|
||||
import { KomgaUser } from "@/types/komga";
|
||||
|
||||
interface AuthUser {
|
||||
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";
|
||||
|
||||
const CREDENTIALS_KEY = "komgaCredentials";
|
||||
const USER_KEY = "komgaUser";
|
||||
const KOMGACREDENTIALS_KEY = "komgaCredentials";
|
||||
const USER_KEY = "stripUser";
|
||||
const TTL_CONFIG_KEY = "ttlConfig";
|
||||
|
||||
interface TTLConfig {
|
||||
@@ -28,7 +28,7 @@ class StorageService {
|
||||
/**
|
||||
* 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;
|
||||
|
||||
// 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
|
||||
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}` : "";
|
||||
document.cookie = cookieValue + maxAge;
|
||||
|
||||
@@ -58,10 +58,10 @@ class StorageService {
|
||||
if (typeof window === "undefined") return null;
|
||||
|
||||
const storage =
|
||||
localStorage.getItem(CREDENTIALS_KEY) || sessionStorage.getItem(CREDENTIALS_KEY);
|
||||
localStorage.getItem(KOMGACREDENTIALS_KEY) || sessionStorage.getItem(KOMGACREDENTIALS_KEY);
|
||||
console.log("StorageService - Lecture des credentials:", {
|
||||
fromLocalStorage: !!localStorage.getItem(CREDENTIALS_KEY),
|
||||
fromSessionStorage: !!sessionStorage.getItem(CREDENTIALS_KEY),
|
||||
fromLocalStorage: !!localStorage.getItem(KOMGACREDENTIALS_KEY),
|
||||
fromSessionStorage: !!sessionStorage.getItem(KOMGACREDENTIALS_KEY),
|
||||
value: storage,
|
||||
});
|
||||
|
||||
@@ -135,17 +135,17 @@ class StorageService {
|
||||
* Efface toutes les données stockées
|
||||
*/
|
||||
clear(): void {
|
||||
localStorage.removeItem(CREDENTIALS_KEY);
|
||||
localStorage.removeItem(KOMGACREDENTIALS_KEY);
|
||||
localStorage.removeItem(USER_KEY);
|
||||
sessionStorage.removeItem(CREDENTIALS_KEY);
|
||||
sessionStorage.removeItem(KOMGACREDENTIALS_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`;
|
||||
}
|
||||
|
||||
getUser() {
|
||||
try {
|
||||
const userStr = localStorage.getItem("komgaUser");
|
||||
const userStr = localStorage.getItem(USER_KEY);
|
||||
if (!userStr) return null;
|
||||
return JSON.parse(atob(userStr));
|
||||
} catch (error) {
|
||||
@@ -155,9 +155,17 @@ class StorageService {
|
||||
}
|
||||
|
||||
clearAll() {
|
||||
localStorage.removeItem("komgaUser");
|
||||
localStorage.removeItem("komgaCredentials");
|
||||
localStorage.removeItem("ttlConfig");
|
||||
localStorage.removeItem(USER_KEY);
|
||||
localStorage.removeItem(KOMGACREDENTIALS_KEY);
|
||||
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
|
||||
const user = request.cookies.get("komgaUser");
|
||||
const user = request.cookies.get("stripUser");
|
||||
if (!user) {
|
||||
const loginUrl = new URL("/login", request.url);
|
||||
loginUrl.searchParams.set("from", pathname);
|
||||
|
||||
Reference in New Issue
Block a user