Implementierung Wissensmanagement
Dieser Commit ist enthalten in:
@ -14,19 +14,23 @@ class ApiClient {
|
||||
|
||||
// Token Management
|
||||
setToken(token) {
|
||||
console.log('[API] setToken:', token ? token.substring(0, 20) + '...' : 'NULL');
|
||||
this.token = token;
|
||||
if (token) {
|
||||
localStorage.setItem('auth_token', token);
|
||||
} else {
|
||||
this.token = null;
|
||||
localStorage.removeItem('auth_token');
|
||||
localStorage.removeItem('current_user');
|
||||
}
|
||||
}
|
||||
|
||||
getToken() {
|
||||
if (!this.token) {
|
||||
this.token = localStorage.getItem('auth_token');
|
||||
}
|
||||
return this.token;
|
||||
// IMMER aus localStorage lesen um Synchronisationsprobleme zu vermeiden
|
||||
// (z.B. wenn Token nach Login gesetzt wird während andere Requests laufen)
|
||||
const token = localStorage.getItem('auth_token');
|
||||
this.token = token; // Cache aktualisieren
|
||||
return token;
|
||||
}
|
||||
|
||||
setCsrfToken(token) {
|
||||
@ -39,10 +43,10 @@ class ApiClient {
|
||||
}
|
||||
|
||||
getCsrfToken() {
|
||||
if (!this.csrfToken) {
|
||||
this.csrfToken = sessionStorage.getItem('csrf_token');
|
||||
}
|
||||
return this.csrfToken;
|
||||
// IMMER aus sessionStorage lesen um Synchronisationsprobleme zu vermeiden
|
||||
const token = sessionStorage.getItem('csrf_token');
|
||||
this.csrfToken = token; // Cache aktualisieren
|
||||
return token;
|
||||
}
|
||||
|
||||
// Base Request Method
|
||||
@ -56,6 +60,7 @@ class ApiClient {
|
||||
|
||||
// Add auth token
|
||||
const token = this.getToken();
|
||||
console.log('[API] Request:', endpoint, 'Token:', token ? token.substring(0, 20) + '...' : 'NULL');
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
@ -98,8 +103,22 @@ class ApiClient {
|
||||
|
||||
// Handle 401 Unauthorized
|
||||
if (response.status === 401) {
|
||||
this.setToken(null);
|
||||
window.dispatchEvent(new CustomEvent('auth:logout'));
|
||||
// Token der für diesen Request verwendet wurde
|
||||
const requestToken = token;
|
||||
const currentToken = localStorage.getItem('auth_token');
|
||||
|
||||
console.log('[API] 401 received for:', endpoint);
|
||||
console.log('[API] Request token:', requestToken ? requestToken.substring(0, 20) + '...' : 'NULL');
|
||||
console.log('[API] Current token:', currentToken ? currentToken.substring(0, 20) + '...' : 'NULL');
|
||||
|
||||
// Nur ausloggen wenn der Token der gleiche ist (kein neuer Login in der Zwischenzeit)
|
||||
if (!currentToken || currentToken === requestToken) {
|
||||
console.log('[API] Token invalid, triggering logout');
|
||||
this.setToken(null);
|
||||
window.dispatchEvent(new CustomEvent('auth:logout'));
|
||||
} else {
|
||||
console.log('[API] 401 ignored - new login occurred while request was in flight');
|
||||
}
|
||||
throw new ApiError('Sitzung abgelaufen', 401);
|
||||
}
|
||||
|
||||
@ -274,7 +293,9 @@ class ApiClient {
|
||||
// =====================
|
||||
|
||||
async login(username, password) {
|
||||
console.log('[API] login() called');
|
||||
const response = await this.post('/auth/login', { username, password });
|
||||
console.log('[API] login() response:', response ? 'OK' : 'NULL', 'token:', response?.token ? 'EXISTS' : 'MISSING');
|
||||
this.setToken(response.token);
|
||||
// Store CSRF token from login response
|
||||
if (response.csrfToken) {
|
||||
@ -977,6 +998,79 @@ class ApiClient {
|
||||
xhr.send(formData);
|
||||
});
|
||||
}
|
||||
|
||||
// =====================
|
||||
// KNOWLEDGE ENDPOINTS (Wissensmanagement)
|
||||
// =====================
|
||||
|
||||
// Kategorien
|
||||
async getKnowledgeCategories() {
|
||||
return this.get('/knowledge/categories');
|
||||
}
|
||||
|
||||
async createKnowledgeCategory(data) {
|
||||
return this.post('/knowledge/categories', data);
|
||||
}
|
||||
|
||||
async updateKnowledgeCategory(id, data) {
|
||||
return this.put(`/knowledge/categories/${id}`, data);
|
||||
}
|
||||
|
||||
async deleteKnowledgeCategory(id) {
|
||||
return this.delete(`/knowledge/categories/${id}`);
|
||||
}
|
||||
|
||||
async updateKnowledgeCategoryPosition(id, newPosition) {
|
||||
return this.put(`/knowledge/categories/${id}/position`, { newPosition });
|
||||
}
|
||||
|
||||
// Einträge
|
||||
async getKnowledgeEntries(categoryId = null) {
|
||||
const params = categoryId ? `?categoryId=${categoryId}` : '';
|
||||
return this.get(`/knowledge/entries${params}`);
|
||||
}
|
||||
|
||||
async getKnowledgeEntry(id) {
|
||||
return this.get(`/knowledge/entries/${id}`);
|
||||
}
|
||||
|
||||
async createKnowledgeEntry(data) {
|
||||
return this.post('/knowledge/entries', data);
|
||||
}
|
||||
|
||||
async updateKnowledgeEntry(id, data) {
|
||||
return this.put(`/knowledge/entries/${id}`, data);
|
||||
}
|
||||
|
||||
async deleteKnowledgeEntry(id) {
|
||||
return this.delete(`/knowledge/entries/${id}`);
|
||||
}
|
||||
|
||||
async updateKnowledgeEntryPosition(id, newPosition, newCategoryId = null) {
|
||||
return this.put(`/knowledge/entries/${id}/position`, { newPosition, newCategoryId });
|
||||
}
|
||||
|
||||
// Anhänge
|
||||
async getKnowledgeAttachments(entryId) {
|
||||
return this.get(`/knowledge/attachments/${entryId}`);
|
||||
}
|
||||
|
||||
async uploadKnowledgeAttachment(entryId, file, onProgress) {
|
||||
return this.uploadFile(`/knowledge/attachments/${entryId}`, file, onProgress);
|
||||
}
|
||||
|
||||
async deleteKnowledgeAttachment(id) {
|
||||
return this.delete(`/knowledge/attachments/${id}`);
|
||||
}
|
||||
|
||||
getKnowledgeAttachmentDownloadUrl(id) {
|
||||
return `${this.baseUrl}/knowledge/attachments/download/${id}`;
|
||||
}
|
||||
|
||||
// Suche
|
||||
async searchKnowledge(query) {
|
||||
return this.get(`/knowledge/search?q=${encodeURIComponent(query)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Custom API Error Class
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren