Files
Oxicloud/static/sw.js
T
Dionisio 05135529ce fix(security): scope root folder listing to authenticated user
Non-admin users were seeing all users' root folders, including the
admin's. Three root causes fixed:

1. Backend: list_root_folders now extracts AuthUser and filters
   results so each user only sees their own home folder at the
   root level (folders matching 'My Folder - {username}' or
   'Mi Carpeta - {username}').

2. Frontend: findUserHomeFolder() searched only for the Spanish
   pattern 'Mi Carpeta - {username}' but the backend creates
   folders with the English pattern 'My Folder - {username}'.
   Now checks both naming conventions.

3. Frontend: when the home folder was not found, the code fell
   back to folderList[0] — which was usually the admin's folder.
   Removed that dangerous fallback; now shows empty root instead.

Fixes #94
2026-02-13 22:31:05 +01:00

100 lines
3.0 KiB
JavaScript

// OxiCloud Service Worker
const CACHE_NAME = 'oxicloud-cache-v5';
const ASSETS_TO_CACHE = [
'/',
'/index.html',
'/js/i18n.js',
'/js/languageSelector.js',
'/locales/en.json',
'/locales/es.json',
'/locales/fa.json',
'/locales/de.json',
'/favicon.ico',
'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css',
'https://cdn.jsdelivr.net/npm/alpinejs@3.12.3/dist/cdn.min.js'
];
// Install event - cache assets
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log('Cache opened');
return cache.addAll(ASSETS_TO_CACHE);
})
.then(() => self.skipWaiting()) // Activate immediately
);
});
// Activate event - clean old caches
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.filter(cacheName => {
return cacheName !== CACHE_NAME;
}).map(cacheName => {
return caches.delete(cacheName);
})
);
}).then(() => self.clients.claim()) // Take control of clients
);
});
// Fetch event - serve from cache, update cache from network
self.addEventListener('fetch', event => {
// Don't intercept API requests - let them go straight to the network
if (event.request.url.includes('/api/')) {
return;
}
event.respondWith(
caches.match(event.request)
.then(response => {
// Cache hit - return the response from the cached version
if (response) {
// For non-core assets, still fetch from network for updates
if (!ASSETS_TO_CACHE.includes(new URL(event.request.url).pathname)) {
fetch(event.request).then(networkResponse => {
if (networkResponse && networkResponse.status === 200) {
const clonedResponse = networkResponse.clone();
caches.open(CACHE_NAME).then(cache => {
cache.put(event.request, clonedResponse);
});
}
}).catch(() => {
// Ignore network fetch errors - we already have a cached version
});
}
return response;
}
// Not in cache - get from network and add to cache
return fetch(event.request).then(response => {
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
// Clone the response as it's a stream and can only be consumed once
const responseToCache = response.clone();
caches.open(CACHE_NAME).then(cache => {
cache.put(event.request, responseToCache);
});
return response;
});
})
);
});
// Background sync for failed requests
self.addEventListener('sync', event => {
if (event.tag === 'oxicloud-sync') {
event.waitUntil(
// Implement background sync for pending file operations
Promise.resolve() // Placeholder for actual implementation
);
}
});