Compare commits

...

8 Commits

Author SHA1 Message Date
Aiirondev_dev 2d7cec075c workaround for existing misused users
Release Inventarsystem / release-docker (push) Successful in 2m15s
2026-08-14 12:08:31 +02:00
Aiirondev_dev fc0fdf8472 change to the authentification system to allow the user acces o the main page
Release Inventarsystem / release-docker (push) Successful in 2m16s
2026-08-14 12:05:23 +02:00
Aiirondev_dev 237c79be58 changes to the user authentication
Release Inventarsystem / release-docker (push) Successful in 2m17s
2026-08-14 11:58:44 +02:00
Aiirondev_dev 821636908f changes to the user authentification
Release Inventarsystem / release-docker (push) Successful in 2m17s
2026-08-14 11:51:10 +02:00
Aiirondev_dev 1506406adc Merge remote-tracking branch 'refs/remotes/origin/main'
Release Inventarsystem / release-docker (push) Successful in 3m18s
2026-08-14 11:24:51 +02:00
Aiirondev_dev 567edc43a7 Slight changes to make the username appear correctly 2026-08-14 11:15:12 +02:00
Aiirondev_dev 28f5991fa0 slight fixes to fix the image displayment
Release Inventarsystem / release-docker (push) Successful in 2m17s
2026-08-13 00:23:54 +02:00
Aiirondev_dev e9b4cf0c25 slight fixes to fix the image processing
Release Inventarsystem / release-docker (push) Successful in 2m15s
2026-08-12 23:47:38 +02:00
3 changed files with 29 additions and 30 deletions
+8 -9
View File
@@ -453,7 +453,7 @@ PERMISSION_ACTION_ENDPOINTS = {
'admin_reset_user_password': 'can_manage_users',
'admin_update_user_permissions': 'can_manage_users',
'admin_anonymize_names': 'can_manage_users',
'home_admin': 'can_manage_settings',
'home_admin': 'can_borrow',
'upload_admin': 'can_insert',
'library_admin': 'can_insert',
'admin_borrowings': 'can_manage_settings',
@@ -811,6 +811,8 @@ def _page_access_allowed(permissions, endpoint):
if not permissions or not endpoint:
return True
page_permissions = permissions.get('pages', {})
if endpoint == "home_admin":
return True
return bool(page_permissions.get(endpoint, True))
@@ -824,13 +826,10 @@ def _action_access_allowed(permissions, action_key):
def _permission_denied_fallback_endpoint(permissions, current_endpoint=None):
username = session.get('username')
is_admin_user = bool(username and us.check_admin(username))
admin_home_allowed = _page_access_allowed(permissions, 'home_admin') and _action_access_allowed(permissions, 'can_manage_settings')
for candidate in ('my_borrowed_items', 'tutorial_page', 'notifications_view', 'impressum', 'home_admin'):
if current_endpoint and candidate == current_endpoint:
continue
if candidate == 'home_admin' and is_admin_user and not admin_home_allowed:
continue
if _page_access_allowed(permissions, candidate):
return candidate
return 'logout'
@@ -5555,10 +5554,10 @@ def upload_item():
app.logger.info(f"Starting image upload session {upload_session_id} - Files: {len(images)}, User: {encrypt_text(username)}")
for index, image in enumerate(images):
if upload_mode == 'library':
app.logger.info(f"[Upload {upload_session_id}] Skipping manual upload (Library Mode)")
skipped_count += 1
continue
#if upload_mode == 'library':
# app.logger.info(f"[Upload {upload_session_id}] Skipping manual upload (Library Mode)")
# skipped_count += 1
# continue
if not image or not image.filename:
skipped_count += 1
@@ -8011,7 +8010,7 @@ def user_del():
fullname = None
users_list.append({
'username': username, # Username ist plain in DB, kein decrypt_text() notwendig
'username': decrypt_text(username),
'admin': user.get('Admin', False),
'fullname': fullname,
'name': name,
+1
View File
@@ -211,6 +211,7 @@ PERMISSION_PRESETS = {
},
'pages': {
'home': True,
'home_admin': True,
'tutorial_page': True,
'my_borrowed_items': True,
'notifications_view': True,
+20 -21
View File
@@ -1252,24 +1252,26 @@
return div.innerHTML;
}
// Opens the modal and fetches the data
function showItemDetail(itemId) {
const detailContent = document.getElementById('detailContent');
const detailModal = document.getElementById('detailModal');
// 1. Show the loading state immediately
detailContent.innerHTML = '<p>Lade Details...</p>';
detailModal.style.display = 'flex';
// 2. Generate Image/Video Gallery Client-Side
const item = libraryItems.find(i => i._id === itemId);
let mediaHtml = '';
if (item && item.Images && item.Images.length > 0) {
const imagesHtml = item.Images.map((image, index) => {
// Robuste Prüfung: Wir testen gängige Benennungen aus deinem Backend
const imageArray = item.Images || item.Bilder || item.images;
if (item && Array.isArray(imageArray) && imageArray.length > 0) {
const imagesHtml = imageArray.map((image, index) => {
// Dein neuer Code für die exakte Routen-Generierung
const imageSrc = image.startsWith('/uploads/') || image.startsWith('http') ?
image :
`{{ url_for('uploaded_file', filename='') }}${image}`;
image :
`{{ url_for('uploaded_file', filename='') }}${image}`;
const thumbnailInfo = item.ThumbnailInfo && item.ThumbnailInfo[index];
const isVideo = isVideoFile(image);
@@ -1280,42 +1282,39 @@
: imageSrc;
if (thumbnailInfo && thumbnailInfo.has_thumbnail) {
return `<div class="video-container" style="position: relative; width: 120px; height: 120px; display: inline-block; margin-right: 15px; margin-bottom: 15px;">
<img src="${videoSrc}" alt="${escapeHtml(item.Name || '')}" class="item-image" style="width: 100%; height: 100%; object-fit: cover; border-radius: 8px; border: 1px solid #ddd;">
<div class="video-preview-overlay" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; background: rgba(0,0,0,0.6); border-radius: 50%; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; font-size: 16px;">
</div>
</div>`;
return `
<div class="video-container" style="position: relative; width: 120px; height: 120px; display: inline-block; margin-right: 15px; margin-bottom: 15px;">
<img src="${videoSrc}" alt="${escapeHtml(item.Name || 'Medium')}" class="item-image" style="width: 100%; height: 100%; object-fit: cover; border-radius: 8px; border: 1px solid #ddd;">
<div class="video-preview-overlay" style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; background: rgba(0,0,0,0.6); border-radius: 50%; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; font-size: 16px;">
</div>
</div>`;
} else {
return `<div style="width: 120px; height: 120px; background: #333; color: #fff; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; margin-right: 15px; margin-bottom: 15px;">VIDEO</div>`;
return `<div style="width: 120px; height: 120px; background: #333; color: #fff; display: inline-flex; align-items: center; justify-content: center; border-radius: 8px; margin-right: 15px; margin-bottom: 15px;">VIDEO</div>`;
}
} else {
const imageSrcFinal = thumbnailInfo && thumbnailInfo.has_thumbnail
? thumbnailInfo.thumbnail_url
: imageSrc;
return `<img src="${imageSrcFinal}" alt="${escapeHtml(item.Name || '')}" class="item-image" style="width: 120px; height: 120px; object-fit: cover; border-radius: 8px; border: 1px solid #ddd; margin-right: 15px; margin-bottom: 15px;">`;
return `<img src="${imageSrcFinal}" alt="${escapeHtml(item.Name || 'Medium')}" class="item-image" style="width: 120px; height: 120px; object-fit: cover; border-radius: 8px; border: 1px solid #ddd; margin-right: 15px; margin-bottom: 15px;">`;
}
}).join('');
mediaHtml = `<div class="detail-gallery-container" style="margin-bottom: 20px; padding-bottom: 15px; border-bottom: 1px solid #eee; display: flex; flex-wrap: wrap;">${imagesHtml}</div>`;
}
// 3. Fetch the data
fetch(`/api/item_detail/${itemId}`)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
return response.text();
})
.then(html => {
// 4. Clean the HTML and display it, injecting the media gallery before the fetched content
detailContent.innerHTML = mediaHtml + DOMPurify.sanitize(html);
})
.catch(err => {
console.error('Error loading detail:', err);
detailContent.innerHTML = '<p>Sorry, we could not load the item details. Please try again later.</p>';
detailContent.innerHTML = '<p style="color: red;">Entschuldigung, die Details konnten nicht geladen werden.</p>';
});
}