Files
digiserver-v2/app/templates/admin/https_config.html
root 2ea24a98cd feat: add real-time HTTPS status detection on admin config page
- Detect actual HTTPS status from current request (scheme + X-Forwarded-Proto)
- Auto-sync database when HTTPS status mismatch is detected
- Show real-time connection info (protocol, host, port)
- Display helpful message when accessing via HTTPS but config shows disabled
- Add CSS styling for detection status display
- Users now see accurate HTTPS status even if database wasn't in sync
2026-01-14 21:22:22 +02:00

527 lines
15 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}HTTPS Configuration - DigiServer v2{% endblock %}
{% block content %}
<div class="container">
<div class="page-header">
<a href="{{ url_for('admin.admin_panel') }}" class="back-link">← Back to Admin Panel</a>
<h1>🔒 HTTPS Configuration</h1>
</div>
<div class="https-config-container">
<!-- Status Display -->
<div class="card status-card">
<h2>Current Status</h2>
<!-- Real-time HTTPS detection -->
<div class="status-detection">
<p class="detection-info">
<strong>🔍 Detected Connection:</strong>
{% if is_https_active %}
<span class="badge badge-success">🔒 HTTPS ({{ request.scheme.upper() }})</span>
{% else %}
<span class="badge badge-warning">🔓 HTTP</span>
{% endif %}
<br>
<small>Current host: <code>{{ current_host }}</code> via {{ request.host }}</small>
</p>
</div>
{% if config and config.https_enabled %}
<div class="status-enabled">
<span class="status-badge">✅ HTTPS ENABLED</span>
<div class="status-details">
<p><strong>Domain:</strong> {{ config.domain }}</p>
<p><strong>Hostname:</strong> {{ config.hostname }}</p>
<p><strong>Email:</strong> {{ config.email }}</p>
<p><strong>IP Address:</strong> {{ config.ip_address }}</p>
<p><strong>Port:</strong> {{ config.port }}</p>
<p><strong>Access URL:</strong> <code>https://{{ config.domain }}</code></p>
<p><strong>Last Updated:</strong> {{ config.updated_at.strftime('%Y-%m-%d %H:%M:%S') }} by {{ config.updated_by }}</p>
</div>
</div>
{% else %}
<div class="status-disabled">
<span class="status-badge-inactive">⚠️ HTTPS DISABLED</span>
{% if is_https_active %}
<p style="color: #156b2e; background: #d1f0e0; padding: 10px; border-radius: 4px; margin: 10px 0;">
<strong>Note:</strong> You are currently accessing this page via HTTPS, but the configuration shows as disabled.
This configuration will be automatically updated. Please refresh the page.
</p>
{% else %}
<p>The application is currently running on HTTP only (port 80)</p>
<p>Enable HTTPS below to secure your application.</p>
{% endif %}
</div>
{% endif %}
</div>
<!-- Configuration Form -->
<div class="card config-card">
<h2>Configure HTTPS Settings</h2>
<p class="info-text">
💡 <strong>Workflow:</strong> First, the app runs on HTTP (port 80). After you configure the HTTPS settings below,
the application will be available over HTTPS (port 443) using the domain and hostname you specify.
</p>
<form method="POST" action="{{ url_for('admin.update_https_config') }}" class="https-form">
<!-- Enable HTTPS Toggle -->
<div class="form-group">
<label class="toggle-label">
<input type="checkbox" name="https_enabled" id="https_enabled"
{% if config and config.https_enabled %}checked{% endif %}
class="toggle-input">
<span class="toggle-slider"></span>
<span class="toggle-text">Enable HTTPS</span>
</label>
<p class="form-hint">Check this box to enable HTTPS/SSL for your application</p>
</div>
<!-- Hostname Field -->
<div class="form-group">
<label for="hostname">Hostname <span class="required">*</span></label>
<input type="text" id="hostname" name="hostname"
value="{{ config.hostname or 'digiserver' }}"
placeholder="e.g., digiserver"
class="form-input"
required>
<p class="form-hint">Short name for your server (e.g., 'digiserver')</p>
</div>
<!-- Domain Field -->
<div class="form-group">
<label for="domain">Full Domain Name <span class="required">*</span></label>
<input type="text" id="domain" name="domain"
value="{{ config.domain or 'digiserver.sibiusb.harting.intra' }}"
placeholder="e.g., digiserver.sibiusb.harting.intra"
class="form-input"
required>
<p class="form-hint">Complete domain name (e.g., digiserver.sibiusb.harting.intra)</p>
</div>
<!-- IP Address Field -->
<div class="form-group">
<label for="ip_address">IP Address <span class="required">*</span></label>
<input type="text" id="ip_address" name="ip_address"
value="{{ config.ip_address or '10.76.152.164' }}"
placeholder="e.g., 10.76.152.164"
class="form-input"
required>
<p class="form-hint">Server's IP address for direct access (e.g., 10.76.152.164)</p>
</div>
<!-- Email Field -->
<div class="form-group">
<label for="email">Email Address <span class="required">*</span></label>
<input type="email" id="email" name="email"
value="{{ config.email or '' }}"
placeholder="e.g., admin@example.com"
class="form-input"
required>
<p class="form-hint">Email address for SSL certificate notifications and Let's Encrypt communications</p>
</div>
<!-- Port Field -->
<div class="form-group">
<label for="port">HTTPS Port</label>
<input type="number" id="port" name="port"
value="{{ config.port or 443 }}"
placeholder="443"
min="1" max="65535"
class="form-input">
<p class="form-hint">Port for HTTPS connections (default: 443)</p>
</div>
<!-- Preview Section -->
<div class="preview-section">
<h3>Access Points After Configuration:</h3>
<ul class="access-points">
<li>
<strong>HTTPS (Recommended):</strong>
<code>https://<span id="preview-domain">digiserver.sibiusb.harting.intra</span></code>
</li>
<li>
<strong>HTTP (Fallback):</strong>
<code>http://<span id="preview-ip">10.76.152.164</span></code>
</li>
</ul>
</div>
<!-- Form Actions -->
<div class="form-actions">
<button type="submit" class="btn btn-primary btn-lg">
💾 Save HTTPS Configuration
</button>
<a href="{{ url_for('admin.admin_panel') }}" class="btn btn-secondary">
Cancel
</a>
</div>
</form>
</div>
<!-- Information Section -->
<div class="card info-card">
<h2> Important Information</h2>
<div class="info-sections">
<div class="info-section">
<h3>📝 Before You Start</h3>
<ul>
<li>Ensure your DNS is configured to resolve the domain to your server</li>
<li>Verify the IP address matches your server's actual network interface</li>
<li>Check that ports 80, 443, and 443/UDP are open for traffic</li>
</ul>
</div>
<div class="info-section">
<h3>🔐 HTTPS Setup</h3>
<ul>
<li>SSL certificates are automatically managed by Caddy</li>
<li>Certificates are obtained from Let's Encrypt</li>
<li>Automatic renewal is handled by the system</li>
</ul>
</div>
<div class="info-section">
<h3>✅ After Configuration</h3>
<ul>
<li>Your app will restart with the new settings</li>
<li>Both HTTP and HTTPS access points will be available</li>
<li>HTTP requests will be redirected to HTTPS</li>
<li>Check the status above for current configuration</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<style>
.https-config-container {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
.page-header {
margin-bottom: 30px;
}
.back-link {
display: inline-block;
margin-bottom: 15px;
color: #0066cc;
text-decoration: none;
font-weight: 500;
}
.back-link:hover {
text-decoration: underline;
}
.status-detection {
background: #f0f7ff;
border-left: 4px solid #0066cc;
padding: 15px;
margin-bottom: 20px;
border-radius: 4px;
}
.detection-info {
margin: 0;
font-size: 14px;
line-height: 1.6;
}
.badge {
display: inline-block;
padding: 4px 12px;
border-radius: 4px;
font-size: 12px;
font-weight: 600;
margin-left: 8px;
}
.badge-success {
background: #d1f0e0;
color: #156b2e;
}
.badge-warning {
background: #fff3cd;
color: #856404;
}
.status-card {
margin-bottom: 30px;
border-left: 5px solid #ddd;
}
.status-enabled {
background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%);
border-radius: 8px;
padding: 20px;
border-left: 5px solid #28a745;
}
.status-disabled {
background: linear-gradient(135deg, #fff3cd 0%, #ffeaa7 100%);
border-radius: 8px;
padding: 20px;
border-left: 5px solid #ffc107;
}
.status-badge {
display: inline-block;
background: #28a745;
color: white;
padding: 8px 16px;
border-radius: 20px;
font-weight: bold;
margin-bottom: 15px;
font-size: 14px;
}
.status-badge-inactive {
display: inline-block;
background: #ffc107;
color: #333;
padding: 8px 16px;
border-radius: 20px;
font-weight: bold;
margin-bottom: 15px;
font-size: 14px;
}
.status-details {
margin-top: 15px;
}
.status-details p {
margin: 8px 0;
font-size: 14px;
}
.status-details code {
background: rgba(0,0,0,0.1);
padding: 4px 8px;
border-radius: 4px;
font-family: 'Courier New', monospace;
}
.config-card {
margin-bottom: 30px;
}
.info-text {
background: #e7f3ff;
border-left: 4px solid #0066cc;
padding: 12px 16px;
border-radius: 4px;
margin-bottom: 25px;
font-size: 14px;
}
.https-form {
padding: 20px 0;
}
.form-group {
margin-bottom: 25px;
}
.form-group label {
display: block;
font-weight: 600;
margin-bottom: 8px;
color: #333;
}
.required {
color: #dc3545;
}
.form-input {
width: 100%;
padding: 12px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 14px;
font-family: inherit;
transition: all 0.2s;
}
.form-input:focus {
outline: none;
border-color: #0066cc;
box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);
}
.form-hint {
font-size: 13px;
color: #666;
margin-top: 6px;
}
/* Toggle Switch Styling */
.toggle-label {
display: flex;
align-items: center;
gap: 12px;
cursor: pointer;
user-select: none;
}
.toggle-input {
display: none;
}
.toggle-slider {
display: inline-block;
width: 50px;
height: 28px;
background: #ccc;
border-radius: 14px;
position: relative;
transition: all 0.3s;
}
.toggle-slider::after {
content: '';
position: absolute;
width: 24px;
height: 24px;
background: white;
border-radius: 50%;
top: 2px;
left: 2px;
transition: all 0.3s;
}
.toggle-input:checked + .toggle-slider {
background: #28a745;
}
.toggle-input:checked + .toggle-slider::after {
left: 24px;
}
.toggle-text {
font-weight: 600;
color: #333;
}
.preview-section {
background: #f8f9fa;
border: 2px dashed #0066cc;
border-radius: 8px;
padding: 20px;
margin: 25px 0;
}
.preview-section h3 {
margin-top: 0;
color: #0066cc;
}
.access-points {
list-style: none;
padding: 0;
margin: 0;
}
.access-points li {
padding: 10px;
background: white;
border-radius: 4px;
margin-bottom: 8px;
border-left: 4px solid #0066cc;
}
.access-points code {
background: #e7f3ff;
padding: 6px 10px;
border-radius: 4px;
font-family: 'Courier New', monospace;
color: #0066cc;
}
.form-actions {
display: flex;
gap: 10px;
margin-top: 30px;
padding-top: 25px;
border-top: 1px solid #ddd;
}
.btn-lg {
padding: 12px 30px;
font-size: 16px;
font-weight: 600;
}
.info-card {
background: linear-gradient(135deg, #e7f3ff 0%, #f0f7ff 100%);
}
.info-card h2 {
color: #0066cc;
}
.info-sections {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-top: 20px;
}
.info-section h3 {
color: #0066cc;
margin-top: 0;
font-size: 16px;
}
.info-section ul {
padding-left: 20px;
margin: 0;
}
.info-section li {
margin-bottom: 8px;
font-size: 14px;
color: #555;
}
@media (max-width: 768px) {
.https-config-container {
padding: 10px;
}
.info-sections {
grid-template-columns: 1fr;
}
.form-actions {
flex-direction: column;
}
.btn-lg {
width: 100%;
}
}
</style>
<script>
// Update preview in real-time
document.getElementById('domain').addEventListener('input', function() {
document.getElementById('preview-domain').textContent = this.value || 'digiserver.sibiusb.harting.intra';
});
document.getElementById('ip_address').addEventListener('input', function() {
document.getElementById('preview-ip').textContent = this.value || '10.76.152.164';
});
// Load initial preview
document.getElementById('preview-domain').textContent = document.getElementById('domain').value || 'digiserver.sibiusb.harting.intra';
document.getElementById('preview-ip').textContent = document.getElementById('ip_address').value || '10.76.152.164';
</script>
{% endblock %}