feat: Enhance favorites management by binding session favorites to authenticated users and updating cache handling
This commit is contained in:
+27
-1
@@ -3733,6 +3733,13 @@ def login():
|
|||||||
is_admin_user = bool(user.get('Admin', False))
|
is_admin_user = bool(user.get('Admin', False))
|
||||||
session['admin'] = is_admin_user
|
session['admin'] = is_admin_user
|
||||||
session['is_admin'] = is_admin_user
|
session['is_admin'] = is_admin_user
|
||||||
|
# Bind session favorites to the authenticated user to avoid cross-user leakage.
|
||||||
|
try:
|
||||||
|
session['favorites_owner'] = username
|
||||||
|
session['favorites'] = list(dict.fromkeys([str(f) for f in us.get_favorites(username)]))
|
||||||
|
except Exception:
|
||||||
|
session['favorites_owner'] = username
|
||||||
|
session['favorites'] = []
|
||||||
if is_admin_user:
|
if is_admin_user:
|
||||||
permissions = us.get_effective_permissions(username)
|
permissions = us.get_effective_permissions(username)
|
||||||
if _page_access_allowed(permissions, 'home_admin') and _action_access_allowed(permissions, 'can_manage_settings'):
|
if _page_access_allowed(permissions, 'home_admin') and _action_access_allowed(permissions, 'can_manage_settings'):
|
||||||
@@ -3827,6 +3834,8 @@ def logout():
|
|||||||
session.pop('username', None)
|
session.pop('username', None)
|
||||||
session.pop('admin', None)
|
session.pop('admin', None)
|
||||||
session.pop('is_admin', None)
|
session.pop('is_admin', None)
|
||||||
|
session.pop('favorites', None)
|
||||||
|
session.pop('favorites_owner', None)
|
||||||
return redirect(url_for('login'))
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
|
|
||||||
@@ -3835,6 +3844,7 @@ def get_items():
|
|||||||
"""Return items plus merged favorites (session + DB) and per-item favorite flag."""
|
"""Return items plus merged favorites (session + DB) and per-item favorite flag."""
|
||||||
client = None
|
client = None
|
||||||
try:
|
try:
|
||||||
|
_ensure_session_favs()
|
||||||
username = session.get('username')
|
username = session.get('username')
|
||||||
# Merge DB favorites into session if logged in
|
# Merge DB favorites into session if logged in
|
||||||
if username:
|
if username:
|
||||||
@@ -4081,8 +4091,23 @@ def api_booking_conflicts():
|
|||||||
|
|
||||||
"""Favorites management endpoints (persistent + session cache)."""
|
"""Favorites management endpoints (persistent + session cache)."""
|
||||||
def _ensure_session_favs():
|
def _ensure_session_favs():
|
||||||
if 'favorites' not in session:
|
username = session.get('username')
|
||||||
|
owner = session.get('favorites_owner')
|
||||||
|
|
||||||
|
if not username:
|
||||||
|
if 'favorites' not in session or not isinstance(session.get('favorites'), list):
|
||||||
session['favorites'] = []
|
session['favorites'] = []
|
||||||
|
return
|
||||||
|
|
||||||
|
if owner != username:
|
||||||
|
session['favorites_owner'] = username
|
||||||
|
session['favorites'] = []
|
||||||
|
session.modified = True
|
||||||
|
return
|
||||||
|
|
||||||
|
if 'favorites' not in session or not isinstance(session.get('favorites'), list):
|
||||||
|
session['favorites'] = []
|
||||||
|
session.modified = True
|
||||||
|
|
||||||
@app.route('/favorites', methods=['GET'])
|
@app.route('/favorites', methods=['GET'])
|
||||||
def list_favorites():
|
def list_favorites():
|
||||||
@@ -4169,6 +4194,7 @@ def toggle_fav(item_id):
|
|||||||
@app.route('/debug/favorites')
|
@app.route('/debug/favorites')
|
||||||
def debug_favorites():
|
def debug_favorites():
|
||||||
"""Diagnostic endpoint: shows session favorites, DB favorites and merged output."""
|
"""Diagnostic endpoint: shows session favorites, DB favorites and merged output."""
|
||||||
|
_ensure_session_favs()
|
||||||
username = session.get('username')
|
username = session.get('username')
|
||||||
session_favs = list(session.get('favorites', []))
|
session_favs = list(session.get('favorites', []))
|
||||||
db_favs = []
|
db_favs = []
|
||||||
|
|||||||
@@ -843,7 +843,7 @@
|
|||||||
|
|
||||||
const favoriteIds = new Set(data.favorites || []);
|
const favoriteIds = new Set(data.favorites || []);
|
||||||
window.currentFavorites = favoriteIds;
|
window.currentFavorites = favoriteIds;
|
||||||
try { sessionStorage.setItem('favoritesCache', JSON.stringify(Array.from(favoriteIds))); } catch(e){}
|
try { sessionStorage.setItem('favoritesCache:' + ({{ session.get('username', '') | tojson }} || 'anon'), JSON.stringify(Array.from(favoriteIds))); } catch(e){}
|
||||||
pageItems.forEach(item => {
|
pageItems.forEach(item => {
|
||||||
try {
|
try {
|
||||||
const card = document.createElement('div');
|
const card = document.createElement('div');
|
||||||
@@ -4233,6 +4233,7 @@
|
|||||||
<script>
|
<script>
|
||||||
let favoritesOnly = false;
|
let favoritesOnly = false;
|
||||||
let tableViewMode = false;
|
let tableViewMode = false;
|
||||||
|
const favoritesCacheKey = 'favoritesCache:' + ({{ session.get('username', '') | tojson }} || 'anon');
|
||||||
|
|
||||||
function setViewModeState() {
|
function setViewModeState() {
|
||||||
document.body.classList.toggle('table-view', tableViewMode);
|
document.body.classList.toggle('table-view', tableViewMode);
|
||||||
@@ -4263,7 +4264,7 @@ function toggleFavorite(id, btn, card){
|
|||||||
}
|
}
|
||||||
if(!window.currentFavorites) window.currentFavorites = new Set();
|
if(!window.currentFavorites) window.currentFavorites = new Set();
|
||||||
if(isFav) window.currentFavorites.add(id); else window.currentFavorites.delete(id);
|
if(isFav) window.currentFavorites.add(id); else window.currentFavorites.delete(id);
|
||||||
try { sessionStorage.setItem('favoritesCache', JSON.stringify(Array.from(window.currentFavorites))); } catch(e){}
|
try { sessionStorage.setItem(favoritesCacheKey, JSON.stringify(Array.from(window.currentFavorites))); } catch(e){}
|
||||||
})
|
})
|
||||||
.catch(err=>console.error('Netzwerkfehler Favoriten', err));
|
.catch(err=>console.error('Netzwerkfehler Favoriten', err));
|
||||||
}
|
}
|
||||||
@@ -4271,7 +4272,7 @@ document.addEventListener('DOMContentLoaded', ()=>{
|
|||||||
// Initialize favorites cache set if stored
|
// Initialize favorites cache set if stored
|
||||||
try {
|
try {
|
||||||
if(!window.currentFavorites){
|
if(!window.currentFavorites){
|
||||||
const cached = sessionStorage.getItem('favoritesCache');
|
const cached = sessionStorage.getItem(favoritesCacheKey);
|
||||||
if(cached){ window.currentFavorites = new Set(JSON.parse(cached)); }
|
if(cached){ window.currentFavorites = new Set(JSON.parse(cached)); }
|
||||||
}
|
}
|
||||||
} catch(e){}
|
} catch(e){}
|
||||||
@@ -4310,7 +4311,7 @@ function openItemQuick(id){
|
|||||||
if(item && !item.error){
|
if(item && !item.error){
|
||||||
// ensure favorites set available
|
// ensure favorites set available
|
||||||
if(!window.currentFavorites){
|
if(!window.currentFavorites){
|
||||||
window.currentFavorites = new Set(JSON.parse(sessionStorage.getItem('favoritesCache')||'[]'));
|
window.currentFavorites = new Set(JSON.parse(sessionStorage.getItem(favoritesCacheKey)||'[]'));
|
||||||
}
|
}
|
||||||
openItemModal(item);
|
openItemModal(item);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user