Compare commits

..

17 Commits

Author SHA1 Message Date
Aiirondev_dev 4943aff944 changes to the email processing 2026-09-17 20:13:26 +02:00
Aiirondev_dev ee1683abe1 fix of faulty spelling 2026-09-17 19:59:35 +02:00
Aiirondev_dev 320acb5256 changes to the email sending 2026-09-17 19:36:48 +02:00
Aiirondev_dev 7b2a6d7bc1 test mail sender 2026-09-17 19:28:24 +02:00
Aiirondev_dev 027cef257d changes to the client building for the email requests 2026-09-17 17:42:00 +02:00
Aiirondev_dev cbacda34ca temporary removal of the tutorial Page 2026-09-17 16:46:31 +02:00
Aiirondev_dev cbc805919a changes to the Email behaivior 2026-09-16 17:45:16 +02:00
Aiirondev 31e8b7ccb4 revert 92c86334e9
revert Refactor email configuration handling and improve logging for email delivery
2026-09-16 15:37:25 +00:00
Aiirondev 5d908b6142 revert 92c86334e9
revert Refactor email configuration handling and improve logging for email delivery
2026-09-16 15:37:12 +00:00
Aiirondev aa9eb4996a revert eba20b7e2e
revert Fixes for the Secret deployment
2026-09-16 15:36:35 +00:00
Aiirondev 43f963d0d3 revert 7ab2899e92
revert changes to the Secret changes
2026-09-16 15:36:10 +00:00
Aiirondev 6589b8d275 revert 8673c0f05c
revert secrets processibg chanbged
2026-09-16 15:35:55 +00:00
Aiirondev 612ce2e6e6 revert d49ec9fd34
revert changes to the env processing
2026-09-16 15:35:36 +00:00
Aiirondev 210483d250 revert 6b3c35f895
revert changes tp implement the env file
2026-09-16 15:35:21 +00:00
Aiirondev 943b48ce16 revert 1dbe5709f5
revert changes to some settings
2026-09-16 15:35:12 +00:00
Aiirondev 476dfee0ff revert d002c5f9da
revert changes
2026-09-16 15:35:04 +00:00
Aiirondev_dev d002c5f9da changes 2026-09-16 17:14:37 +02:00
7 changed files with 160 additions and 195 deletions
+91 -100
View File
@@ -230,106 +230,97 @@ jobs:
tags: | tags: |
${{ steps.meta.outputs.image }} ${{ steps.meta.outputs.image }}
- name: Create release-only docker bundle - name: Create release-only docker bundle
run: | run: |
mkdir -p release-bundle mkdir -p release-bundle
cat > release-bundle/docker-compose.yml <<EOF
# 1. .env Datei aus Gitea Secrets erzeugen services:
cat > release-bundle/.env <<EOF app:
INVENTAR_SECRET_KEY=${{ secrets.INVENTAR_SECRET_KEY }} image: \${INVENTAR_APP_IMAGE:-${{ steps.meta.outputs.image }}}
INVENTAR_DATA_ENCRYPTION_KEY=${{ secrets.INVENTAR_DATA_ENCRYPTION_KEY }} container_name: inventarsystem-app
INVENTAR_MONGODB_PASSWORD=${{ secrets.INVENTAR_MONGODB_PASSWORD }} restart: unless-stopped
EMAIL_ENABLED=${{ secrets.EMAIL_ENABLED }} ports:
EMAIL_SMTP_HOST=${{ secrets.EMAIL_SMTP_HOST }} - "\${INVENTAR_HTTP_PORT:-10000}:8000"
EMAIL_SMTP_PORT=${{ secrets.EMAIL_SMTP_PORT }} depends_on:
EMAIL_USERNAME=${{ secrets.EMAIL_USERNAME }} - mongodb
EMAIL_PASSWORD=${{ secrets.EMAIL_PASSWORD }} - redis
EMAIL_FROM_ADDRESS=${{ secrets.EMAIL_FROM_ADDRESS }} environment:
EOF INVENTAR_MONGODB_HOST: mongodb
INVENTAR_MONGODB_PORT: "27017"
# 2. docker-compose.yml nutzt env_file INVENTAR_MONGODB_DB: Inventarsystem
cat > release-bundle/docker-compose.yml <<EOF INVENTAR_BACKUP_FOLDER: /data/backups
services: INVENTAR_LOGS_FOLDER: /data/logs
app: INVENTAR_SECRET_KEY: ${{secrets.INVENTAR_SECRET_KEY}}
image: \${INVENTAR_APP_IMAGE:-${{ steps.meta.outputs.image }}} INVENTAR_DATA_ENCRYPTION_KEY: ${{secrets.INVENTAR_DATA_ENCRYPTION_KEY}}
container_name: inventarsystem-app INVENTAR_MONGODB_PASSWORD: ${{secrets.INVENTAR_MONGODB_PASSWORD}}
restart: unless-stopped EMAIL_ENABLED: ${{secrets.EMAIL_ENABLED}}
env_file: EMAIL_SMTP_HOST: ${{secrets.EMAIL_SMTP_HOST}}
- .env EMAIL_SMTP_PORT: ${{secrets.EMAIL_SMTP_PORT}}
ports: EMAIL_USERNAME: ${{secrets.EMAIL_USERNAME}}
- "\${INVENTAR_HTTP_PORT:-10000}:8000" EMAIL_PASSWORD: ${{secrets.EMAIL_PASSWORD}}
depends_on: expose:
- mongodb - "8000"
- redis volumes:
environment: - ./config.json:/app/config.json:ro
INVENTAR_MONGODB_HOST: mongodb - app_uploads:/app/Web/uploads
INVENTAR_MONGODB_PORT: "27017" - app_thumbnails:/app/Web/thumbnails
INVENTAR_MONGODB_DB: Inventarsystem - app_previews:/app/Web/previews
INVENTAR_BACKUP_FOLDER: /data/backups - app_qrcodes:/app/Web/QRCodes
INVENTAR_LOGS_FOLDER: /data/logs - app_backups:/data/backups
expose: - app_logs:/data/logs
- "8000"
volumes: mongodb:
- ./config.json:/app/config.json:ro image: mongo:7.0
- app_uploads:/app/Web/uploads container_name: inventarsystem-mongodb
- app_thumbnails:/app/Web/thumbnails restart: unless-stopped
- app_previews:/app/Web/previews volumes:
- app_qrcodes:/app/Web/QRCodes - mongodb_data:/data/db
- app_backups:/data/backups healthcheck:
- app_logs:/data/logs test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"]
interval: 10s
mongodb: timeout: 5s
image: mongo:7.0 retries: 10
container_name: inventarsystem-mongodb
restart: unless-stopped redis:
volumes: image: redis:7-alpine
- mongodb_data:/data/db container_name: inventarsystem-redis
healthcheck: restart: unless-stopped
test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand('ping').ok"] command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru
interval: 10s ports:
timeout: 5s - "6379:6379"
retries: 10 volumes:
- redis_data:/data
redis: healthcheck:
image: redis:7-alpine test: ["CMD", "redis-cli", "ping"]
container_name: inventarsystem-redis interval: 10s
restart: unless-stopped timeout: 5s
command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru retries: 5
ports:
- "6379:6379" volumes:
volumes: mongodb_data:
- redis_data:/data app_uploads:
healthcheck: app_thumbnails:
test: ["CMD", "redis-cli", "ping"] app_previews:
interval: 10s app_qrcodes:
timeout: 5s app_backups:
retries: 5 app_logs:
redis_data:
volumes: EOF
mongodb_data:
app_uploads: for f in start.sh stop.sh restart.sh backup.sh restore.sh config.json update.sh; do
app_thumbnails: if [ -f "$f" ]; then
app_previews: cp "$f" "release-bundle/$(basename "$f")"
app_qrcodes: fi
app_backups: done
app_logs:
redis_data: for f in docker-compose-multitenant.yml manage-tenant.sh run-tenant-cmd.sh MULTITENANT_DEPLOYMENT.md MULTITENANT_PYTHON_API.md; do
EOF if [ -f "$f" ]; then
cp "$f" "release-bundle/$(basename "$f")"
for f in start.sh stop.sh restart.sh backup.sh restore.sh config.json update.sh; do fi
if [ -f "$f" ]; then done
cp "$f" "release-bundle/$(basename "$f")"
fi find release-bundle -maxdepth 1 -type f -name '*.sh' -exec chmod +x {} \; || true
done tar -czf inventarsystem-docker-bundle.tar.gz -C release-bundle .
for f in docker-compose-multitenant.yml manage-tenant.sh run-tenant-cmd.sh MULTITENANT_DEPLOYMENT.md MULTITENANT_PYTHON_API.md; do
if [ -f "$f" ]; then
cp "$f" "release-bundle/$(basename "$f")"
fi
done
find release-bundle -maxdepth 1 -type f -name '*.sh' -exec chmod +x {} \; || true
tar -czf inventarsystem-docker-bundle.tar.gz -C release-bundle .
- name: Create or update Gitea Release - name: Create or update Gitea Release
uses: https://gitea.com/actions/gitea-release-action@v1 uses: https://gitea.com/actions/gitea-release-action@v1
+13 -1
View File
@@ -13755,4 +13755,16 @@ def upload_csv_batch():
"images_processed": processed_count, "images_processed": processed_count,
"images_deduplicated": dedup_count, "images_deduplicated": dedup_count,
"images_failed": error_count "images_failed": error_count
}), 200 }), 200
@app.route('/test_email')
def test_email():
#Test endpoint to send a sample email.
#This is for development purposes only.
try:
send(to_email="maximiliangruendinger@gmail.com", subject="Test Email from Inventarsystem", body="This is a test email sent from the Inventarsystem application.")
return "Test email sent successfully."
except Exception as e:
return f"Failed to send test email: {str(e)}", 500
+5 -17
View File
@@ -220,25 +220,13 @@ SSL_CERT = _get(_conf, ['ssl', 'cert'], DEFAULTS['ssl']['cert'])
SSL_KEY = _get(_conf, ['ssl', 'key'], DEFAULTS['ssl']['key']) SSL_KEY = _get(_conf, ['ssl', 'key'], DEFAULTS['ssl']['key'])
# Email settings # Email settings
def _get_email_env(name, default=''): EMAIL_ENABLED = bool(os.getenv('EMAIL_ENABLED', False))
value = os.getenv(name) EMAIL_SMTP_HOST = str(os.getenv('EMAIL_SMTP_HOST', False))
if value is None:
return default
value = value.strip()
return '' if value.lower() in {'', 'false', 'none', 'null'} else value
EMAIL_ENABLED = _get_email_env('EMAIL_ENABLED').lower() in {'1', 'true', 'yes', 'on'}
EMAIL_SMTP_HOST = "mail.invario-software.de"
EMAIL_SMTP_PORT = int(os.getenv('EMAIL_SMTP_PORT', 587)) EMAIL_SMTP_PORT = int(os.getenv('EMAIL_SMTP_PORT', 587))
EMAIL_USE_TLS = True EMAIL_USE_TLS = True
EMAIL_USERNAME = "no-reply@invario-software.de" EMAIL_USERNAME = str(os.getenv('EMAIL_USERNAME', False))
EMAIL_PASSWORD = "#,EATwIn,68" EMAIL_PASSWORD = str(os.getenv('EMAIL_PASSWORD', False))
EMAIL_FROM_ADDRESS = ( EMAIL_FROM_ADDRESS = _get(_conf, ['email', 'from_address'], EMAIL_USERNAME)
_get_email_env('EMAIL_FROM_ADDRESS')
or _get(_conf, ['email', 'from_address'], '')
or EMAIL_USERNAME
)
EMAIL_DEFAULT_SENDER_NAME = "Invario Inventarsystem Sender" EMAIL_DEFAULT_SENDER_NAME = "Invario Inventarsystem Sender"
EMAIL_TIMEOUT_SECONDS = 20 EMAIL_TIMEOUT_SECONDS = 20
+9 -17
View File
@@ -3,32 +3,25 @@ from email.mime.text import MIMEText
from email.mime.application import MIMEApplication from email.mime.application import MIMEApplication
import smtplib import smtplib
import time import time
import logging
import Web.modules.database.settings as cfg import Web.modules.database.settings as cfg
logger = logging.getLogger(__name__)
def _build_smtp_client(): def _build_smtp_client():
if not cfg.EMAIL_SMTP_HOST:
raise RuntimeError('EMAIL_SMTP_HOST ist nicht konfiguriert')
smtp = smtplib.SMTP( smtp = smtplib.SMTP(
cfg.EMAIL_SMTP_HOST, "mail.invario-software.de",
cfg.EMAIL_SMTP_PORT, 587,
timeout=cfg.EMAIL_TIMEOUT_SECONDS, timeout=10,
) )
smtp.ehlo() smtp.ehlo()
if cfg.EMAIL_USE_TLS: if True:
smtp.starttls() smtp.starttls()
smtp.ehlo() smtp.ehlo()
if cfg.EMAIL_USERNAME: smtp.login("no-reply@invario-software.de", "eSpage,65,{")
smtp.login(cfg.EMAIL_USERNAME, cfg.EMAIL_PASSWORD or "")
return smtp return smtp
def _normalize_recipients(email: list | str) -> list[str]: def _normalize_recipients(email: list | str) -> list[str]:
if isinstance(email, str): if isinstance(email, str):
email = email.replace(';', ',').split(',') email = email.replace(';', ',').split(',')
@@ -38,12 +31,11 @@ def _normalize_recipients(email: list | str) -> list[str]:
def _send_message(email: list | str, subject: str, note: str, sender: str, attachment=None) -> bool: def _send_message(email: list | str, subject: str, note: str, sender: str, attachment=None) -> bool:
"""Send a plain/HTML message, optionally with one PDF attachment.""" """Send a plain/HTML message, optionally with one PDF attachment."""
if not cfg.MODULES.is_enabled("mail"): if not cfg.MODULES.is_enabled("mail"):
logger.info("Email delivery skipped because the mail module is disabled") print("Debug: Module not enabled")
return False return False
recipients = _normalize_recipients(email) recipients = _normalize_recipients(email)
if not recipients: if not recipients:
logger.warning("Email delivery skipped because no recipients were provided")
return False return False
body_message = note body_message = note
@@ -84,7 +76,7 @@ def _send_message(email: list | str, subject: str, note: str, sender: str, attac
msg = MIMEMultipart("mixed" if attachment else "alternative") msg = MIMEMultipart("mixed" if attachment else "alternative")
msg["Subject"] = str(subject) msg["Subject"] = str(subject)
from_address = cfg.EMAIL_FROM_ADDRESS or cfg.EMAIL_USERNAME or "no-reply@invario-software.de" from_address = "no-reply@invario-software.de"
msg["From"] = f"{sender} <{from_address}>" msg["From"] = f"{sender} <{from_address}>"
msg["To"] = str(recipient) msg["To"] = str(recipient)
@@ -112,7 +104,7 @@ def _send_message(email: list | str, subject: str, note: str, sender: str, attac
return True return True
except Exception as e: except Exception as e:
logger.exception("Email delivery failed: %s", e) print(f"Debug: Fehler beim Senden der E-Mail: {e}")
return False return False
finally: finally:
if smtp: if smtp:
+1 -1
View File
@@ -3,7 +3,7 @@ import Web.modules.terminplaner.backend_server as appointment_service
import Web.modules.database.settings as cfg import Web.modules.database.settings as cfg
import Web.modules.database.termine as termin import Web.modules.database.termine as termin
import Web.modules.database.user as us import Web.modules.database.user as us
from Web.modules.emailservice.email import send_pdf from Web.modules.emailservice.email import send, send_pdf
from Web.modules.terminplaner.backend_server import _resolve_public_base_url from Web.modules.terminplaner.backend_server import _resolve_public_base_url
import csv import csv
import io import io
+41 -36
View File
@@ -1346,11 +1346,13 @@
</li> </li>
{% endif %} {% endif %}
{% if 'username' in session %} {% if 'username' in session %}
<!--
{% if current_permissions.pages.get('tutorial_page', False) %} {% if current_permissions.pages.get('tutorial_page', False) %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link quick-link-pill {% if current_path == url_for('tutorial_page') %}nav-active{% endif %}" href="{{ url_for('tutorial_page') }}" data-tutorial-tip="Nutzen Sie das Tutorial, um die Bibliotheksfunktionen kennenzulernen.">Tutorial</a> <a class="nav-link quick-link-pill {% if current_path == url_for('tutorial_page') %}nav-active{% endif %}" href="{{ url_for('tutorial_page') }}" data-tutorial-tip="Nutzen Sie das Tutorial, um die Bibliotheksfunktionen kennenzulernen.">Tutorial</a>
</li> </li>
{% endif %} {% endif %}
-->
{% endif %} {% endif %}
{% if 'username' in session and current_permissions.actions.get('can_insert', False) and current_permissions.pages.get('library_admin', False) %} {% if 'username' in session and current_permissions.actions.get('can_insert', False) and current_permissions.pages.get('library_admin', False) %}
<li class="nav-item"> <li class="nav-item">
@@ -1630,6 +1632,8 @@
</div> </div>
</div> </div>
<!--
<div id="onboarding-overlay" role="dialog" aria-modal="true" aria-label="Tutorial Vorschlag"> <div id="onboarding-overlay" role="dialog" aria-modal="true" aria-label="Tutorial Vorschlag">
<div id="onboarding-modal"> <div id="onboarding-modal">
<h3>Wollen Sie eine Vorstellung des Produkts?</h3> <h3>Wollen Sie eine Vorstellung des Produkts?</h3>
@@ -1643,6 +1647,7 @@
</div> </div>
</div> </div>
</div> </div>
-->
<div id="notification-toast" class="notification-toast" role="status" aria-live="polite"> <div id="notification-toast" class="notification-toast" role="status" aria-live="polite">
<strong id="notification-toast-title">Neue Benachrichtigung</strong> <strong id="notification-toast-title">Neue Benachrichtigung</strong>
@@ -1662,7 +1667,7 @@
<option value="Benachrichtigungen"></option> <option value="Benachrichtigungen"></option>
{% endif %} {% endif %}
{% if current_permissions.pages.get('tutorial_page', False) %} {% if current_permissions.pages.get('tutorial_page', False) %}
<option value="Tutorial"></option> <!--<option value="Tutorial"></option>-->
{% endif %} {% endif %}
{% endif %} {% endif %}
@@ -1765,10 +1770,10 @@
}); });
const username = {{ (session['username'] if 'username' in session else '')|tojson }}; const username = {{ (session['username'] if 'username' in session else '')|tojson }};
const isTutorialPage = window.location.pathname === {{ url_for('tutorial_page')|tojson }}; //const isTutorialPage = window.location.pathname === {{ url_for('tutorial_page')|tojson }};
const isLoginPage = window.location.pathname === {{ url_for('login')|tojson }}; const isLoginPage = window.location.pathname === {{ url_for('login')|tojson }};
const notificationsPagePath = {{ url_for('notifications_view')|tojson }}; const notificationsPagePath = {{ url_for('notifications_view')|tojson }};
const onboardingKey = username ? ('inventarsystem_tutorial_prompt_v1_' + username) : null; //const onboardingKey = username ? ('inventarsystem_tutorial_prompt_v1_' + username) : null;
const onboardingOverlay = document.getElementById('onboarding-overlay'); const onboardingOverlay = document.getElementById('onboarding-overlay');
const notificationButtons = Array.from(document.querySelectorAll('[data-notification-button="true"]')); const notificationButtons = Array.from(document.querySelectorAll('[data-notification-button="true"]'));
const notificationToast = document.getElementById('notification-toast'); const notificationToast = document.getElementById('notification-toast');
@@ -1789,9 +1794,9 @@
{% if current_permissions.pages.get('notifications_view', False) %} {% if current_permissions.pages.get('notifications_view', False) %}
{ label: 'Benachrichtigungen', keywords: ['benachrichtigungen', 'nachrichten', 'notifications'], url: {{ url_for('notifications_view')|tojson }} }, { label: 'Benachrichtigungen', keywords: ['benachrichtigungen', 'nachrichten', 'notifications'], url: {{ url_for('notifications_view')|tojson }} },
{% endif %} {% endif %}
{% if current_permissions.pages.get('tutorial_page', False) %} //{% if current_permissions.pages.get('tutorial_page', False) %}
{ label: 'Tutorial', keywords: ['tutorial', 'hilfe', 'anleitung'], url: {{ url_for('tutorial_page')|tojson }} }, //{ label: 'Tutorial', keywords: ['tutorial', 'hilfe', 'anleitung'], url: {{ url_for('tutorial_page')|tojson }} },
{% endif %} //{% endif %}
{% endif %} {% endif %}
{ label: 'Impressum', keywords: ['impressum'], url: {{ url_for('impressum')|tojson }} }, { label: 'Impressum', keywords: ['impressum'], url: {{ url_for('impressum')|tojson }} },
@@ -2042,11 +2047,11 @@
window.setInterval(pollNotificationStatus, 30000); window.setInterval(pollNotificationStatus, 30000);
} }
function showOnboarding(){ //function showOnboarding(){
if (onboardingOverlay) { // if (onboardingOverlay) {
onboardingOverlay.style.display = 'flex'; // onboardingOverlay.style.display = 'flex';
} // }
} //}
function hideOnboarding(){ function hideOnboarding(){
if (onboardingOverlay) { if (onboardingOverlay) {
@@ -2054,19 +2059,19 @@
} }
} }
if (onboardingKey && !isTutorialPage && !isLoginPage) { //if (onboardingKey && !isTutorialPage && !isLoginPage) {
const decision = localStorage.getItem(onboardingKey); // const decision = localStorage.getItem(onboardingKey);
if (!decision || decision === 'later') { // if (!decision || decision === 'later') {
showOnboarding(); // showOnboarding();
} // }
} //}
document.getElementById('onboarding-start')?.addEventListener('click', function(){ //document.getElementById('onboarding-start')?.addEventListener('click', function(){
if (onboardingKey) { // if (onboardingKey) {
localStorage.setItem(onboardingKey, 'started'); // localStorage.setItem(onboardingKey, 'started');
} // }
window.location.href = {{ url_for('tutorial_page')|tojson }}; // window.location.href = {{ url_for('tutorial_page')|tojson }};
}); //});
document.getElementById('onboarding-later')?.addEventListener('click', function(){ document.getElementById('onboarding-later')?.addEventListener('click', function(){
if (onboardingKey) { if (onboardingKey) {
@@ -2399,21 +2404,21 @@
<script> <script>
(function () { (function () {
const username = {{ (session['username'] if 'username' in session else '')|tojson }}; const username = {{ (session['username'] if 'username' in session else '')|tojson }};
const tooltipModeKey = username ? ('inventarsystem_tutorial_tooltips_enabled_' + username) : 'inventarsystem_tutorial_tooltips_enabled'; //const tooltipModeKey = username ? ('inventarsystem_tutorial_tooltips_enabled_' + username) : 'inventarsystem_tutorial_tooltips_enabled';
const enabled = localStorage.getItem(tooltipModeKey) === '1'; const enabled = localStorage.getItem(tooltipModeKey) === '1';
function applyTooltipMode(active) { //function applyTooltipMode(active) {
document.body.classList.toggle('tutorial-tooltips-active', active); // document.body.classList.toggle('tutorial-tooltips-active', active);
let indicator = document.getElementById('tutorialTooltipIndicator'); // let indicator = document.getElementById('tutorialTooltipIndicator');
if (!indicator) { // if (!indicator) {
indicator = document.createElement('div'); // indicator = document.createElement('div');
indicator.id = 'tutorialTooltipIndicator'; // indicator.id = 'tutorialTooltipIndicator';
indicator.className = 'tutorial-tooltip-indicator'; // indicator.className = 'tutorial-tooltip-indicator';
indicator.textContent = 'Tutorial-Modus aktiv: Tooltips sind eingeschaltet'; // indicator.textContent = 'Tutorial-Modus aktiv: Tooltips sind eingeschaltet';
document.body.appendChild(indicator); // document.body.appendChild(indicator);
} // }
indicator.style.display = active ? 'inline-flex' : 'none'; // indicator.style.display = active ? 'inline-flex' : 'none';
} //}
applyTooltipMode(enabled); applyTooltipMode(enabled);
})(); })();
-23
View File
@@ -518,12 +518,6 @@ detect_server_capacity() {
} }
write_env_file() { write_env_file() {
if [ -f "$SCRIPT_DIR/.env" ]; then
set -o allexport
source "$SCRIPT_DIR/.env"
set +o allexport
fi
cat > "$ENV_FILE" <<EOF cat > "$ENV_FILE" <<EOF
NUITKA_BUILD=$NUITKA_BUILD_VALUE NUITKA_BUILD=$NUITKA_BUILD_VALUE
INVENTAR_HTTP_PORT=$HTTP_PORT_VALUE INVENTAR_HTTP_PORT=$HTTP_PORT_VALUE
@@ -536,17 +530,6 @@ INVENTAR_WORKERS=$INVENTAR_WORKERS
INVENTAR_THREADS=$INVENTAR_THREADS INVENTAR_THREADS=$INVENTAR_THREADS
INVENTAR_WORKER_TIMEOUT=${INVENTAR_WORKER_TIMEOUT:-30} INVENTAR_WORKER_TIMEOUT=${INVENTAR_WORKER_TIMEOUT:-30}
INVENTAR_WORKER_CONNECTIONS=${INVENTAR_WORKER_CONNECTIONS:-100} INVENTAR_WORKER_CONNECTIONS=${INVENTAR_WORKER_CONNECTIONS:-100}
# Secrets & E-Mail Konfiguration weiterreichen
INVENTAR_SECRET_KEY=${INVENTAR_SECRET_KEY:-}
INVENTAR_DATA_ENCRYPTION_KEY=${INVENTAR_DATA_ENCRYPTION_KEY:-}
INVENTAR_MONGODB_PASSWORD=${INVENTAR_MONGODB_PASSWORD:-}
EMAIL_ENABLED=${EMAIL_ENABLED:-true}
EMAIL_SMTP_HOST=${EMAIL_SMTP_HOST:-}
EMAIL_SMTP_PORT=${EMAIL_SMTP_PORT:-587}
EMAIL_USERNAME=${EMAIL_USERNAME:-}
EMAIL_PASSWORD=${EMAIL_PASSWORD:-}
EMAIL_FROM_ADDRESS=${EMAIL_FROM_ADDRESS:-}
EOF EOF
} }
@@ -554,8 +537,6 @@ write_runtime_compose_override() {
cat > "$RUNTIME_COMPOSE_OVERRIDE_FILE" <<EOF cat > "$RUNTIME_COMPOSE_OVERRIDE_FILE" <<EOF
services: services:
app: app:
env_file:
- ${ENV_FILE}
working_dir: /app/Web working_dir: /app/Web
command: ["gunicorn", "app:app", "--bind", "0.0.0.0:8000", "--workers", "${INVENTAR_WORKERS:-2}", "--threads", "${INVENTAR_THREADS:-2}", "--timeout", "${INVENTAR_WORKER_TIMEOUT:-30}", "--graceful-timeout", "20", "--worker-connections", "${INVENTAR_WORKER_CONNECTIONS:-100}", "--max-requests", "1000", "--max-requests-jitter", "100", "--log-level", "info", "--access-logfile", "-", "--error-logfile", "-"] command: ["gunicorn", "app:app", "--bind", "0.0.0.0:8000", "--workers", "${INVENTAR_WORKERS:-2}", "--threads", "${INVENTAR_THREADS:-2}", "--timeout", "${INVENTAR_WORKER_TIMEOUT:-30}", "--graceful-timeout", "20", "--worker-connections", "${INVENTAR_WORKER_CONNECTIONS:-100}", "--max-requests", "1000", "--max-requests-jitter", "100", "--log-level", "info", "--access-logfile", "-", "--error-logfile", "-"]
image: ${APP_IMAGE_VALUE} image: ${APP_IMAGE_VALUE}
@@ -588,10 +569,6 @@ verify_stack_health() {
if [ -f "$RUNTIME_COMPOSE_OVERRIDE_FILE" ]; then if [ -f "$RUNTIME_COMPOSE_OVERRIDE_FILE" ]; then
compose_args+=(-f "$RUNTIME_COMPOSE_OVERRIDE_FILE") compose_args+=(-f "$RUNTIME_COMPOSE_OVERRIDE_FILE")
fi fi
if [ -f "$SCRIPT_DIR/.env" ]; then
compose_args+=(--env-file "$SCRIPT_DIR/.env")
fi
compose_args+=(--env-file "$ENV_FILE") compose_args+=(--env-file "$ENV_FILE")
while [[ $retry_count -lt 2 ]]; do while [[ $retry_count -lt 2 ]]; do