Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c77c52271c | |||
| 7e00ed3151 | |||
| 39c9666c0f | |||
| 8eb240440b | |||
| 9dc6fe6eeb | |||
| acfa24d742 | |||
| 88f6b77455 | |||
| bc5e08142a |
@@ -54,10 +54,34 @@ def _clean_name_fragment(value):
|
|||||||
return cleaned
|
return cleaned
|
||||||
|
|
||||||
|
|
||||||
def _get_tenant_db(client):
|
def _get_tenant_db(client, tenant_id=None):
|
||||||
"""Return the current tenant database for the request, or fall back to default."""
|
"""Return the current tenant database for the request, or fall back to default."""
|
||||||
try:
|
try:
|
||||||
from tenant import get_tenant_db
|
from tenant import get_tenant_db
|
||||||
|
if tenant_id is None:
|
||||||
|
return get_tenant_db(client)
|
||||||
|
|
||||||
|
tenant_id = str(tenant_id).strip()
|
||||||
|
if tenant_id:
|
||||||
|
try:
|
||||||
|
from tenant import get_tenant_config
|
||||||
|
|
||||||
|
config = get_tenant_config(tenant_id)
|
||||||
|
if isinstance(config, dict):
|
||||||
|
explicit_db = config.get('db') or config.get('db_name')
|
||||||
|
if explicit_db:
|
||||||
|
db_name = str(explicit_db).strip()
|
||||||
|
if db_name and not db_name.startswith('inventar_'):
|
||||||
|
db_name = f'inventar_{db_name}'
|
||||||
|
if db_name:
|
||||||
|
return client[db_name]
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
sanitized = ''.join(c for c in tenant_id.lower() if c.isalnum() or c == '_')
|
||||||
|
if sanitized:
|
||||||
|
return client[f'inventar_{sanitized}']
|
||||||
|
|
||||||
return get_tenant_db(client)
|
return get_tenant_db(client)
|
||||||
except Exception:
|
except Exception:
|
||||||
return client[cfg.MONGODB_DB]
|
return client[cfg.MONGODB_DB]
|
||||||
@@ -479,8 +503,45 @@ def check_nm_pwd(username, password):
|
|||||||
query = {'$or': [{'Username': username}, {'username': username}]}
|
query = {'$or': [{'Username': username}, {'username': username}]}
|
||||||
user_record_fallback = users.find_one(query)
|
user_record_fallback = users.find_one(query)
|
||||||
if user_record_fallback is None:
|
if user_record_fallback is None:
|
||||||
logger.warning("Kein Benutzer für %r in DB %r gefunden.", dp.encrypt_text(username), db_name)
|
if db_name != cfg.MONGODB_DB:
|
||||||
return None
|
default_users = client[cfg.MONGODB_DB]['users']
|
||||||
|
user_record_fallback = default_users.find_one(
|
||||||
|
{'$or': [
|
||||||
|
{'Username': dp.encrypt_text(username)},
|
||||||
|
{'username': dp.encrypt_text(username)},
|
||||||
|
{'Username': username},
|
||||||
|
{'username': username},
|
||||||
|
]}
|
||||||
|
)
|
||||||
|
if user_record_fallback is not None:
|
||||||
|
migrated_record = dict(user_record_fallback)
|
||||||
|
migrated_record.pop('_id', None)
|
||||||
|
users.replace_one(
|
||||||
|
{'$or': [
|
||||||
|
{'Username': migrated_record.get('Username')},
|
||||||
|
{'username': migrated_record.get('username')},
|
||||||
|
]},
|
||||||
|
migrated_record,
|
||||||
|
upsert=True,
|
||||||
|
)
|
||||||
|
logger.warning(
|
||||||
|
"Tenant user %r migrated from default DB %r to tenant DB %r.",
|
||||||
|
dp.encrypt_text(username),
|
||||||
|
cfg.MONGODB_DB,
|
||||||
|
db_name,
|
||||||
|
)
|
||||||
|
user_record = users.find_one(
|
||||||
|
{'$or': [
|
||||||
|
{'Username': migrated_record.get('Username')},
|
||||||
|
{'username': migrated_record.get('username')},
|
||||||
|
]}
|
||||||
|
) or migrated_record
|
||||||
|
else:
|
||||||
|
logger.warning("Kein Benutzer für %r in DB %r gefunden.", dp.encrypt_text(username), db_name)
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
logger.warning("Kein Benutzer für %r in DB %r gefunden.", dp.encrypt_text(username), db_name)
|
||||||
|
return None
|
||||||
else:
|
else:
|
||||||
user_record = user_record_fallback
|
user_record = user_record_fallback
|
||||||
|
|
||||||
@@ -497,6 +558,59 @@ def check_nm_pwd(username, password):
|
|||||||
finally:
|
finally:
|
||||||
client.close()
|
client.close()
|
||||||
|
|
||||||
|
def add_admin(
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
name='',
|
||||||
|
last_name='',
|
||||||
|
is_student=False,
|
||||||
|
permission_preset='full_access',
|
||||||
|
action_permissions=None,
|
||||||
|
page_permissions=None,
|
||||||
|
tenant_id=None,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Add a new user to the database.
|
||||||
|
"""
|
||||||
|
if not check_password_strength(password):
|
||||||
|
return False
|
||||||
|
|
||||||
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
|
try:
|
||||||
|
db = _get_tenant_db(client, tenant_id)
|
||||||
|
users = db['users']
|
||||||
|
|
||||||
|
permission_defaults = build_default_permission_payload(permission_preset)
|
||||||
|
|
||||||
|
if isinstance(action_permissions, dict):
|
||||||
|
for key, value in action_permissions.items():
|
||||||
|
permission_defaults['actions'][str(key)] = bool(value)
|
||||||
|
|
||||||
|
if isinstance(page_permissions, dict):
|
||||||
|
for key, value in page_permissions.items():
|
||||||
|
permission_defaults['pages'][str(key)] = bool(value)
|
||||||
|
|
||||||
|
safe_name = name.strip() if name else ''
|
||||||
|
safe_last_name = last_name.strip() if last_name else ''
|
||||||
|
|
||||||
|
user_doc = {
|
||||||
|
'Username': username,
|
||||||
|
'Password': hashing(password),
|
||||||
|
'Admin': True,
|
||||||
|
'active_ausleihung': None,
|
||||||
|
'name': dp.encrypt_text(safe_name) if safe_name else '',
|
||||||
|
'last_name': dp.encrypt_text(safe_last_name) if safe_last_name else '',
|
||||||
|
'IsStudent': bool(is_student),
|
||||||
|
'PermissionPreset': permission_defaults['preset'],
|
||||||
|
'ActionPermissions': permission_defaults['actions'],
|
||||||
|
'PagePermissions': permission_defaults['pages'],
|
||||||
|
}
|
||||||
|
|
||||||
|
users.insert_one(user_doc)
|
||||||
|
return True
|
||||||
|
finally:
|
||||||
|
client.close()
|
||||||
|
|
||||||
|
|
||||||
def add_user(
|
def add_user(
|
||||||
username,
|
username,
|
||||||
@@ -509,6 +623,7 @@ def add_user(
|
|||||||
permission_preset='standard_user',
|
permission_preset='standard_user',
|
||||||
action_permissions=None,
|
action_permissions=None,
|
||||||
page_permissions=None,
|
page_permissions=None,
|
||||||
|
tenant_id=None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Add a new user to the database.
|
Add a new user to the database.
|
||||||
@@ -518,7 +633,7 @@ def add_user(
|
|||||||
|
|
||||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||||
try:
|
try:
|
||||||
db = _get_tenant_db(client)
|
db = _get_tenant_db(client, tenant_id)
|
||||||
users = db['users']
|
users = db['users']
|
||||||
|
|
||||||
permission_defaults = build_default_permission_payload(permission_preset)
|
permission_defaults = build_default_permission_payload(permission_preset)
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ document.getElementById('batchUploadForm').addEventListener('submit', async func
|
|||||||
imageMap.set(file.name.toLowerCase(), file);
|
imageMap.set(file.name.toLowerCase(), file);
|
||||||
});
|
});
|
||||||
|
|
||||||
const BATCH_SIZE = 50;
|
const BATCH_SIZE = 20;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const csvText = await csvFile.text();
|
const csvText = await csvFile.text();
|
||||||
|
|||||||
+45
-82
@@ -201,65 +201,35 @@ sys.path.insert(0, "/app/Web")
|
|||||||
from Web.modules.database import settings
|
from Web.modules.database import settings
|
||||||
from pymongo import MongoClient
|
from pymongo import MongoClient
|
||||||
import Web.modules.inventarsystem.data_protection as dp
|
import Web.modules.inventarsystem.data_protection as dp
|
||||||
|
import Web.modules.database.user as us
|
||||||
|
|
||||||
tenant_id = sys.argv[1].lower()
|
tenant_id = sys.argv[1].lower()
|
||||||
mode = sys.argv[2]
|
mode = sys.argv[2]
|
||||||
sanitized = "".join(c for c in tenant_id if c.isalnum() or c == "_")
|
sanitized = "".join(c for c in tenant_id if c.isalnum() or c == "_")
|
||||||
db_name = f"inventar_{sanitized}"
|
db_name = f"inventar_{sanitized}" if sanitized else settings.MONGODB_DB
|
||||||
client = MongoClient(settings.MONGODB_HOST, int(settings.MONGODB_PORT))
|
|
||||||
|
client = MongoClient(settings.MONGODB_HOST, settings.MONGODB_PORT)
|
||||||
db = client[db_name]
|
db = client[db_name]
|
||||||
|
users = db["users"]
|
||||||
pw_bytes = "admin123".encode("utf-8")
|
permission_defaults = us.build_default_permission_payload("full_access")
|
||||||
random_salt = os.urandom(16)
|
admin_doc = {
|
||||||
hashed = hashlib.scrypt(pw_bytes, salt=random_salt, n=16384, r=8, p=1)
|
"Username": "admin",
|
||||||
hashed_pw_string = f"v1${random_salt.hex()}${hashed.hex()}"
|
"Password": us.hashing("admin123"),
|
||||||
|
"Admin": True,
|
||||||
action_permissions = {
|
"active_ausleihung": None,
|
||||||
"can_borrow": True,
|
"name": dp.encrypt_text("admin"),
|
||||||
"can_insert": True,
|
"last_name": dp.encrypt_text("admin"),
|
||||||
"can_edit": True,
|
"IsStudent": False,
|
||||||
"can_delete": True,
|
"PermissionPreset": permission_defaults["preset"],
|
||||||
"can_manage_users": True,
|
"ActionPermissions": permission_defaults["actions"],
|
||||||
"can_manage_settings": True,
|
"PagePermissions": permission_defaults["pages"],
|
||||||
"can_view_logs": True,
|
|
||||||
}
|
}
|
||||||
|
users.replace_one({"Username": "admin"}, admin_doc, upsert=True)
|
||||||
page_permissions = {
|
print("Fallback successfully applied")
|
||||||
"home": True,
|
|
||||||
"tutorial_page": True,
|
|
||||||
"my_borrowed_items": True,
|
|
||||||
"notifications_view": True,
|
|
||||||
"impressum": True,
|
|
||||||
"license": True,
|
|
||||||
"library_view": True,
|
|
||||||
"terminplan": True,
|
|
||||||
"home_admin": True,
|
|
||||||
"upload_admin": True,
|
|
||||||
"library_admin": True,
|
|
||||||
"admin_borrowings": True,
|
|
||||||
"library_loans_admin": True,
|
|
||||||
"admin_damaged_items": True,
|
|
||||||
"admin_audit_dashboard": True,
|
|
||||||
"logs": True,
|
|
||||||
"manage_filters": True,
|
|
||||||
"manage_locations": True,
|
|
||||||
}
|
|
||||||
|
|
||||||
if db.users.count_documents({"Username": dp.encrypt_text("admin")}) == 0:
|
|
||||||
db.users.insert_one({
|
|
||||||
"Username": dp.encrypt_text("admin"),
|
|
||||||
"Password": hashed_pw_string,
|
|
||||||
"Admin": True,
|
|
||||||
"active_ausleihung": None,
|
|
||||||
"name": dp.encrypt_text("Admin"),
|
|
||||||
"last_name": dp.encrypt_text("User"),
|
|
||||||
"IsStudent": False,
|
|
||||||
"PermissionPreset": "full_access",
|
|
||||||
"ActionPermissions": action_permissions,
|
|
||||||
"PagePermissions": page_permissions,
|
|
||||||
})
|
|
||||||
|
|
||||||
if mode == "trial":
|
if mode == "trial":
|
||||||
|
client = MongoClient(settings.MONGODB_HOST, settings.MONGODB_PORT)
|
||||||
|
db = client[db_name]
|
||||||
db.settings.update_one(
|
db.settings.update_one(
|
||||||
{"setting_type": "tenant_trial"},
|
{"setting_type": "tenant_trial"},
|
||||||
{"$set": {
|
{"$set": {
|
||||||
@@ -272,6 +242,8 @@ if mode == "trial":
|
|||||||
upsert=True,
|
upsert=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
client.close()
|
||||||
|
|
||||||
print(f"Tenant {sys.argv[1]} database initialized. Default admin: admin / admin123")
|
print(f"Tenant {sys.argv[1]} database initialized. Default admin: admin / admin123")
|
||||||
PY
|
PY
|
||||||
}
|
}
|
||||||
@@ -674,38 +646,29 @@ case "$COMMAND" in
|
|||||||
port_to_remove=""
|
port_to_remove=""
|
||||||
|
|
||||||
if [ -n "$APP_CONTAINER" ]; then
|
if [ -n "$APP_CONTAINER" ]; then
|
||||||
# Zuerst die Datenbank via PyMongo hart droppen (Erzwungenes Löschen)
|
# MongoDB-Datenbank via PyMongo direkt im Container droppen
|
||||||
port_to_remove="$(docker exec "$APP_CONTAINER" python3 - "$TENANT_ID" <<'PY'
|
docker exec -i "$APP_CONTAINER" python3 -c '
|
||||||
import sys, re
|
import sys, os
|
||||||
sys.path.insert(0, '/app')
|
try:
|
||||||
sys.path.insert(0, '/app/Web')
|
import pymongo
|
||||||
from tenant import delete_tenant, get_tenant_config
|
tenant_id = sys.argv[1]
|
||||||
from Web.modules.database import settings
|
mongo_uri = os.environ.get("MONGO_URI", "mongodb://localhost:27017/")
|
||||||
from pymongo import MongoClient
|
client = pymongo.MongoClient(mongo_uri, serverSelectionTimeoutMS=2000)
|
||||||
|
db_name = f"inventar_{tenant_id}"
|
||||||
|
if db_name in client.list_database_names():
|
||||||
|
client.drop_database(db_name)
|
||||||
|
print(f"Dropped database: {db_name}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error dropping database: {e}", file=sys.stderr)
|
||||||
|
' "$TENANT_ID" > /dev/null 2>&1
|
||||||
|
|
||||||
tenant_id = sys.argv[1]
|
# Konfiguration und Port via Host-Funktion bereinigen und Port ermitteln
|
||||||
tenant_cfg = get_tenant_config(tenant_id)
|
if port_to_remove="$(remove_tenant_port "$TENANT_ID" 2>/dev/null)"; then
|
||||||
port = tenant_cfg.get('port')
|
:
|
||||||
|
else
|
||||||
|
port_to_remove=""
|
||||||
|
fi
|
||||||
|
|
||||||
# Datenbanknamen exakt rekonstruieren
|
|
||||||
sanitized = "".join(c for c in tenant_id if c.isalnum() or c == "_")
|
|
||||||
db_name = f"inventar_{sanitized}"
|
|
||||||
|
|
||||||
try:
|
|
||||||
client = MongoClient(settings.MONGODB_HOST, int(settings.MONGODB_PORT))
|
|
||||||
client.drop_database(db_name)
|
|
||||||
print(f"MongoDB database '{db_name}' dropped successfully.", file=sys.stderr)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Warning: Could not drop database '{db_name}': {e}", file=sys.stderr)
|
|
||||||
|
|
||||||
if not delete_tenant(tenant_id):
|
|
||||||
print(f'Error: failed to delete tenant {tenant_id}', file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if port is not None:
|
|
||||||
print(port)
|
|
||||||
PY
|
|
||||||
)"
|
|
||||||
echo "Tenant '$TENANT_ID' database and config removed."
|
echo "Tenant '$TENANT_ID' database and config removed."
|
||||||
else
|
else
|
||||||
echo "Warning: Application container not running. Tenant database may still exist in MongoDB."
|
echo "Warning: Application container not running. Tenant database may still exist in MongoDB."
|
||||||
@@ -728,7 +691,7 @@ PY
|
|||||||
else
|
else
|
||||||
echo "Removed tenant '$TENANT_ID'. No port mapping was present."
|
echo "Removed tenant '$TENANT_ID'. No port mapping was present."
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
restart-tenant)
|
restart-tenant)
|
||||||
TENANT_ID="${2:-}"
|
TENANT_ID="${2:-}"
|
||||||
|
|||||||
Reference in New Issue
Block a user