Compare commits

..

10 Commits

6 changed files with 404 additions and 5516 deletions
+372 -809
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -319,15 +319,15 @@ THUMBNAIL_FOLDER = _get(_conf, ['upload', 'thumbnail_folder'], DEFAULTS['upload'
PREVIEW_FOLDER = _get(_conf, ['upload', 'preview_folder'], DEFAULTS['upload']['preview_folder'])
QR_CODE_FOLDER = _get(_conf, ['upload', 'qrcode_folder'], DEFAULTS['upload']['qrcode_folder'])
# Normalize to absolute paths to avoid cwd issues
# This guarantees exact matching with Docker volume mounts
if not os.path.isabs(UPLOAD_FOLDER):
UPLOAD_FOLDER = os.path.join(BASE_DIR, os.path.relpath(UPLOAD_FOLDER, BASE_DIR))
UPLOAD_FOLDER = os.path.abspath(os.path.join(BASE_DIR, "uploads"))
if not os.path.isabs(THUMBNAIL_FOLDER):
THUMBNAIL_FOLDER = os.path.join(BASE_DIR, os.path.relpath(THUMBNAIL_FOLDER, BASE_DIR))
THUMBNAIL_FOLDER = os.path.abspath(os.path.join(BASE_DIR, "thumbnails"))
if not os.path.isabs(PREVIEW_FOLDER):
PREVIEW_FOLDER = os.path.join(BASE_DIR, os.path.relpath(PREVIEW_FOLDER, BASE_DIR))
PREVIEW_FOLDER = os.path.abspath(os.path.join(BASE_DIR, "previews"))
if not os.path.isabs(QR_CODE_FOLDER):
QR_CODE_FOLDER = os.path.join(BASE_DIR, os.path.relpath(QR_CODE_FOLDER, BASE_DIR))
QR_CODE_FOLDER = os.path.abspath(os.path.join(BASE_DIR, "QRCodes"))
MAX_UPLOAD_MB = _get(_conf, ['upload', 'max_size_mb'], DEFAULTS['upload']['max_size_mb'])
IMAGE_MAX_UPLOAD_MB = _get(_conf, ['upload', 'image_max_size_mb'], DEFAULTS['upload']['image_max_size_mb'])
VIDEO_MAX_UPLOAD_MB = _get(_conf, ['upload', 'video_max_size_mb'], DEFAULTS['upload']['video_max_size_mb'])
+8 -3
View File
@@ -476,8 +476,13 @@ def check_nm_pwd(username, password):
user_record = users.find_one(query)
if user_record is None:
logger.warning("Kein Benutzer für %r in DB %r gefunden.", dp.encrypt_text(username), db_name)
return None
query = {'$or': [{'Username': username}, {'username': username}]}
user_record_fallback = users.find_one(query)
if user_record_fallback is None:
logger.warning("Kein Benutzer für %r in DB %r gefunden.", dp.encrypt_text(username), db_name)
return None
else:
user_record = user_record_fallback
stored_password = user_record.get('Password') or user_record.get('password')
@@ -617,7 +622,7 @@ def get_user(username):
def find_in_db(database_name):
db = client[database_name]
users = db['users']
return users.find_one({'Username': dp.encrypt_text(username)}) or users.find_one({'username': dp.encrypt_text(username)})
return users.find_one({'Username': dp.encrypt_text(username)}) or users.find_one({'username': dp.encrypt_text(username)}) or users.find_one({'username': username}) or users.find_one({'Username': username})
tenant_db, tenant_id = _resolve_request_tenant_db()
if tenant_db:
+14 -3
View File
@@ -7,7 +7,7 @@
<div style="display:flex; justify-content:space-between; align-items:flex-start; gap:12px; flex-wrap:wrap; margin-bottom:16px;">
<div>
<h1 style="margin:0;">Defekte Items</h1>
<p style="margin:6px 0 0; color:#64748b;">Eigenes Verwaltungsfenster fuer gemeldete Defekte mit schneller Reparatur-Funktion.</p>
<p style="margin:6px 0 0; color:#64748b;">Eigenes Verwaltungsfenster für gemeldete Defekte mit schneller Reparatur-Funktion.</p>
</div>
<div style="display:flex; gap:8px; flex-wrap:wrap;">
<a class="btn btn-outline-secondary" href="{{ url_for('admin_borrowings') }}">Ausleihen</a>
@@ -42,7 +42,13 @@
{% if item.isbn %}<div style="font-size:0.82rem; color:#64748b;">ISBN: {{ item.isbn }}</div>{% endif %}
</td>
<td style="padding:11px; border-bottom:1px solid #eef2f7; vertical-align:top;">
<div style="display:inline-block; padding:3px 9px; border-radius:999px; background:#fee2e2; color:#991b1b; font-size:0.75rem; font-weight:700;">Defekt</div>
<!-- HIER IST DIE ÄNDERUNG: Dynamischer Status-Badge -->
<div class="badge bg-{{ item.status_color }} rounded-pill" style="font-size:0.75rem; font-weight:700; padding:4px 10px;">
{{ item.status_text }}
</div>
<!-- ENDE DER ÄNDERUNG -->
<div style="font-size:0.84rem; color:#475569; margin-top:6px;">Meldungen: {{ item.damage_count }}</div>
<div style="font-size:0.84rem; color:#475569;">Condition: {{ item.condition or '-' }}</div>
<div style="font-size:0.84rem; color:#475569;">Verfuegbar: {{ 'Ja' if item.available else 'Nein' }}</div>
@@ -66,7 +72,12 @@
{% endif %}
</td>
<td style="padding:11px; border-bottom:1px solid #eef2f7; vertical-align:top;">
<!-- Button wird ausgeblendet, falls das Item bereits repariert ist -->
{% if item.condition not in ['repaired', 'fixed'] %}
<button class="btn btn-success btn-sm" onclick="repairDamage('{{ item.id }}', this)">Als repariert markieren</button>
{% else %}
<span class="text-success" style="font-size: 0.85rem;"><i class="bi bi-check-circle"></i> Repariert</span>
{% endif %}
</td>
</tr>
{% endfor %}
@@ -118,4 +129,4 @@ function repairDamage(itemId, button) {
});
}
</script>
{% endblock %}
{% endblock %}
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -200,6 +200,7 @@ sys.path.insert(0, "/app")
sys.path.insert(0, "/app/Web")
from Web.modules.database import settings
from pymongo import MongoClient
import Web.modules.inventarsystem.data_protection as dp
tenant_id = sys.argv[1].lower()
mode = sys.argv[2]
@@ -244,14 +245,14 @@ page_permissions = {
"manage_locations": True,
}
if db.users.count_documents({"Username": "admin"}) == 0:
if db.users.count_documents({"Username": dp.encrypt_text("admin")}) == 0:
db.users.insert_one({
"Username": "admin",
"Username": dp.encrypt_text("admin"),
"Password": hashed_pw_string,
"Admin": True,
"active_ausleihung": None,
"name": "Admin",
"last_name": "User",
"name": dp.encrypt_text("Admin"),
"last_name": dp.encrypt_text("User"),
"IsStudent": False,
"PermissionPreset": "full_access",
"ActionPermissions": action_permissions,