- 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
527 lines
15 KiB
HTML
527 lines
15 KiB
HTML
{% 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 %}
|