massive changes and it works
This commit is contained in:
@@ -1,9 +1,39 @@
|
||||
const API_BASE = '/api';
|
||||
|
||||
// Global auth error handler - will be set by useAuth hook
|
||||
let onAuthError = null;
|
||||
|
||||
export const setAuthErrorHandler = (handler) => {
|
||||
onAuthError = handler;
|
||||
};
|
||||
|
||||
const handleAuthError = (response) => {
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
// Trigger auth error handler if set (this will clear user state)
|
||||
if (onAuthError) {
|
||||
onAuthError();
|
||||
}
|
||||
// Force a re-check of auth status to ensure login is shown
|
||||
// This ensures the App component re-renders with user=null
|
||||
if (typeof window !== 'undefined') {
|
||||
// Dispatch a custom event that useAuth can listen to
|
||||
window.dispatchEvent(new CustomEvent('auth-error'));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const api = {
|
||||
async get(endpoint) {
|
||||
const response = await fetch(`${API_BASE}${endpoint}`);
|
||||
const response = await fetch(`${API_BASE}${endpoint}`, {
|
||||
credentials: 'include', // Include cookies for session
|
||||
});
|
||||
if (!response.ok) {
|
||||
// Handle auth errors before parsing response
|
||||
// Don't redirect on /auth/me - that's the auth check itself
|
||||
if ((response.status === 401 || response.status === 403) && !endpoint.startsWith('/auth/')) {
|
||||
handleAuthError(response);
|
||||
// Don't redirect - let React handle UI change through state
|
||||
}
|
||||
const errorData = await response.json().catch(() => null);
|
||||
const errorMessage = errorData?.error || response.statusText;
|
||||
throw new Error(errorMessage);
|
||||
@@ -16,8 +46,15 @@ export const api = {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data),
|
||||
credentials: 'include', // Include cookies for session
|
||||
});
|
||||
if (!response.ok) {
|
||||
// Handle auth errors before parsing response
|
||||
// Don't redirect on /auth/* endpoints - those are login/logout
|
||||
if ((response.status === 401 || response.status === 403) && !endpoint.startsWith('/auth/')) {
|
||||
handleAuthError(response);
|
||||
// Don't redirect - let React handle UI change through state
|
||||
}
|
||||
const errorData = await response.json().catch(() => null);
|
||||
const errorMessage = errorData?.error || response.statusText;
|
||||
throw new Error(errorMessage);
|
||||
@@ -28,8 +65,15 @@ export const api = {
|
||||
async delete(endpoint) {
|
||||
const response = await fetch(`${API_BASE}${endpoint}`, {
|
||||
method: 'DELETE',
|
||||
credentials: 'include', // Include cookies for session
|
||||
});
|
||||
if (!response.ok) {
|
||||
// Handle auth errors before parsing response
|
||||
// Don't redirect on /auth/* endpoints
|
||||
if ((response.status === 401 || response.status === 403) && !endpoint.startsWith('/auth/')) {
|
||||
handleAuthError(response);
|
||||
// Don't redirect - let React handle UI change through state
|
||||
}
|
||||
const errorData = await response.json().catch(() => null);
|
||||
const errorMessage = errorData?.error || response.statusText;
|
||||
throw new Error(errorMessage);
|
||||
@@ -37,19 +81,61 @@ export const api = {
|
||||
return response.json();
|
||||
},
|
||||
|
||||
async uploadFile(endpoint, file) {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
const response = await fetch(`${API_BASE}${endpoint}`, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
async uploadFile(endpoint, file, onProgress, mainBlendFile) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
if (mainBlendFile) {
|
||||
formData.append('main_blend_file', mainBlendFile);
|
||||
}
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
// Track upload progress
|
||||
if (onProgress) {
|
||||
xhr.upload.addEventListener('progress', (e) => {
|
||||
if (e.lengthComputable) {
|
||||
const percentComplete = (e.loaded / e.total) * 100;
|
||||
onProgress(percentComplete);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
xhr.addEventListener('load', () => {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
try {
|
||||
const response = JSON.parse(xhr.responseText);
|
||||
resolve(response);
|
||||
} catch (err) {
|
||||
resolve(xhr.responseText);
|
||||
}
|
||||
} else {
|
||||
// Handle auth errors
|
||||
if (xhr.status === 401 || xhr.status === 403) {
|
||||
handleAuthError({ status: xhr.status });
|
||||
// Don't redirect - let React handle UI change through state
|
||||
}
|
||||
try {
|
||||
const errorData = JSON.parse(xhr.responseText);
|
||||
reject(new Error(errorData.error || xhr.statusText));
|
||||
} catch {
|
||||
reject(new Error(xhr.statusText));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener('error', () => {
|
||||
reject(new Error('Upload failed'));
|
||||
});
|
||||
|
||||
xhr.addEventListener('abort', () => {
|
||||
reject(new Error('Upload aborted'));
|
||||
});
|
||||
|
||||
xhr.open('POST', `${API_BASE}${endpoint}`);
|
||||
xhr.withCredentials = true; // Include cookies for session
|
||||
xhr.send(formData);
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => null);
|
||||
const errorMessage = errorData?.error || response.statusText;
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
return response.json();
|
||||
},
|
||||
};
|
||||
|
||||
@@ -61,6 +147,30 @@ export const auth = {
|
||||
async logout() {
|
||||
return api.post('/auth/logout');
|
||||
},
|
||||
|
||||
async getProviders() {
|
||||
return api.get('/auth/providers');
|
||||
},
|
||||
|
||||
async isLocalLoginAvailable() {
|
||||
return api.get('/auth/local/available');
|
||||
},
|
||||
|
||||
async localRegister(email, name, password) {
|
||||
return api.post('/auth/local/register', { email, name, password });
|
||||
},
|
||||
|
||||
async localLogin(username, password) {
|
||||
return api.post('/auth/local/login', { username, password });
|
||||
},
|
||||
|
||||
async changePassword(oldPassword, newPassword, targetUserId = null) {
|
||||
const body = { old_password: oldPassword, new_password: newPassword };
|
||||
if (targetUserId !== null) {
|
||||
body.target_user_id = targetUserId;
|
||||
}
|
||||
return api.post('/auth/change-password', body);
|
||||
},
|
||||
};
|
||||
|
||||
export const jobs = {
|
||||
@@ -80,19 +190,23 @@ export const jobs = {
|
||||
return api.delete(`/jobs/${id}`);
|
||||
},
|
||||
|
||||
async uploadFile(jobId, file) {
|
||||
return api.uploadFile(`/jobs/${jobId}/upload`, file);
|
||||
async delete(id) {
|
||||
return api.post(`/jobs/${id}/delete`);
|
||||
},
|
||||
|
||||
async uploadFile(jobId, file, onProgress, mainBlendFile) {
|
||||
return api.uploadFile(`/jobs/${jobId}/upload`, file, onProgress, mainBlendFile);
|
||||
},
|
||||
|
||||
async getFiles(jobId) {
|
||||
return api.get(`/jobs/${jobId}/files`);
|
||||
},
|
||||
|
||||
async downloadFile(jobId, fileId) {
|
||||
downloadFile(jobId, fileId) {
|
||||
return `${API_BASE}/jobs/${jobId}/files/${fileId}/download`;
|
||||
},
|
||||
|
||||
async getVideoUrl(jobId) {
|
||||
getVideoUrl(jobId) {
|
||||
return `${API_BASE}/jobs/${jobId}/video`;
|
||||
},
|
||||
|
||||
@@ -131,9 +245,7 @@ export const jobs = {
|
||||
};
|
||||
|
||||
export const runners = {
|
||||
async list() {
|
||||
return api.get('/runners');
|
||||
},
|
||||
// Non-admin runner list removed - use admin.listRunners() instead
|
||||
};
|
||||
|
||||
export const admin = {
|
||||
@@ -160,5 +272,25 @@ export const admin = {
|
||||
async deleteRunner(runnerId) {
|
||||
return api.delete(`/admin/runners/${runnerId}`);
|
||||
},
|
||||
|
||||
async listUsers() {
|
||||
return api.get('/admin/users');
|
||||
},
|
||||
|
||||
async getUserJobs(userId) {
|
||||
return api.get(`/admin/users/${userId}/jobs`);
|
||||
},
|
||||
|
||||
async setUserAdminStatus(userId, isAdmin) {
|
||||
return api.post(`/admin/users/${userId}/admin`, { is_admin: isAdmin });
|
||||
},
|
||||
|
||||
async getRegistrationEnabled() {
|
||||
return api.get('/admin/settings/registration');
|
||||
},
|
||||
|
||||
async setRegistrationEnabled(enabled) {
|
||||
return api.post('/admin/settings/registration', { enabled });
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user