new file: file_manager.py modified: requirements.txt new file: sessions_db.json modified: templates/base.html new file: templates/file_manager.html new file: templates/file_manager_new.html new file: templates/login.html new file: templates/profile.html new file: templates/users_management.html new file: user_management.py new file: users_db.json
263 lines
13 KiB
HTML
263 lines
13 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Benutzerprofil - App Installer{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container-fluid py-4">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<!-- Breadcrumb -->
|
|
<nav aria-label="breadcrumb" class="mb-4">
|
|
<ol class="breadcrumb">
|
|
<li class="breadcrumb-item"><a href="{{ url_for('index') }}"><i class="fas fa-home"></i> Dashboard</a></li>
|
|
<li class="breadcrumb-item active">Profil</li>
|
|
</ol>
|
|
</nav>
|
|
|
|
<!-- Flash Messages -->
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
{% if messages %}
|
|
{% for category, message in messages %}
|
|
<div class="alert alert-{{ 'danger' if category == 'error' else category }} alert-dismissible fade show" role="alert">
|
|
{{ message }}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
</div>
|
|
{% endfor %}
|
|
{% endif %}
|
|
{% endwith %}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Profil-Info -->
|
|
<div class="col-lg-4 col-md-6 mb-4">
|
|
<div class="card">
|
|
<div class="card-header bg-primary text-white">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-user me-2"></i>
|
|
Benutzer-Informationen
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="text-center mb-3">
|
|
<div class="avatar-circle bg-primary text-white mb-3" style="width: 80px; height: 80px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto; font-size: 2rem;">
|
|
{{ user.first_name[0] if user.first_name else user.username[0] }}{{ user.last_name[0] if user.last_name else '' }}
|
|
</div>
|
|
<h4 class="mb-1">
|
|
{% if user.first_name or user.last_name %}
|
|
{{ user.first_name }} {{ user.last_name }}
|
|
{% else %}
|
|
{{ user.username }}
|
|
{% endif %}
|
|
</h4>
|
|
<span class="badge bg-{% if user.role == 'admin' %}danger{% elif user.role == 'moderator' %}warning{% elif user.role == 'user' %}primary{% else %}secondary{% endif %} fs-6">
|
|
{{ user.role.title() }}
|
|
</span>
|
|
</div>
|
|
|
|
<hr>
|
|
|
|
<div class="info-item mb-2">
|
|
<strong><i class="fas fa-user me-2"></i>Benutzername:</strong>
|
|
<span class="text-muted">{{ user.username }}</span>
|
|
</div>
|
|
|
|
<div class="info-item mb-2">
|
|
<strong><i class="fas fa-envelope me-2"></i>E-Mail:</strong>
|
|
<span class="text-muted">{{ user.email }}</span>
|
|
</div>
|
|
|
|
<div class="info-item mb-2">
|
|
<strong><i class="fas fa-calendar-plus me-2"></i>Erstellt:</strong>
|
|
<span class="text-muted">{{ user.created_at[:10] }}</span>
|
|
</div>
|
|
|
|
{% if user.last_login %}
|
|
<div class="info-item mb-2">
|
|
<strong><i class="fas fa-clock me-2"></i>Letzter Login:</strong>
|
|
<span class="text-muted">{{ user.last_login[:16] }}</span>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="info-item mb-0">
|
|
<strong><i class="fas fa-sign-in-alt me-2"></i>Login-Anzahl:</strong>
|
|
<span class="text-muted">{{ user.login_count or 0 }}x</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Passwort ändern -->
|
|
<div class="col-lg-8 col-md-6 mb-4">
|
|
<div class="card">
|
|
<div class="card-header bg-warning text-dark">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-key me-2"></i>
|
|
Passwort ändern
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<form method="POST" action="{{ url_for('change_password') }}">
|
|
<div class="row">
|
|
<div class="col-md-12 mb-3">
|
|
<label for="old_password" class="form-label">Aktuelles Passwort</label>
|
|
<input type="password"
|
|
class="form-control"
|
|
id="old_password"
|
|
name="old_password"
|
|
required>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="new_password" class="form-label">Neues Passwort</label>
|
|
<input type="password"
|
|
class="form-control"
|
|
id="new_password"
|
|
name="new_password"
|
|
minlength="6"
|
|
required>
|
|
<div class="form-text">Mindestens 6 Zeichen</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="confirm_password" class="form-label">Passwort bestätigen</label>
|
|
<input type="password"
|
|
class="form-control"
|
|
id="confirm_password"
|
|
name="confirm_password"
|
|
minlength="6"
|
|
required>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-warning">
|
|
<i class="fas fa-save me-2"></i>
|
|
Passwort ändern
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Berechtigungen anzeigen -->
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header bg-info text-white">
|
|
<h5 class="card-title mb-0">
|
|
<i class="fas fa-shield-alt me-2"></i>
|
|
Ihre Berechtigungen
|
|
</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="row">
|
|
<!-- Projekt-Berechtigungen -->
|
|
<div class="col-md-6">
|
|
<h6 class="text-primary mb-3"><i class="fas fa-project-diagram me-2"></i>Projekt-Berechtigungen</h6>
|
|
<div class="permissions-list">
|
|
{% set project_permissions = [
|
|
('project.view', 'Projekte anzeigen', 'fas fa-eye'),
|
|
('project.create', 'Projekte erstellen', 'fas fa-plus'),
|
|
('project.update', 'Projekte aktualisieren', 'fas fa-edit'),
|
|
('project.delete', 'Projekte löschen', 'fas fa-trash'),
|
|
('project.start', 'Projekte starten', 'fas fa-play'),
|
|
('project.stop', 'Projekte stoppen', 'fas fa-stop'),
|
|
('project.restart', 'Projekte neustarten', 'fas fa-redo'),
|
|
('project.logs', 'Logs anzeigen', 'fas fa-file-alt'),
|
|
('project.console', 'Konsole nutzen', 'fas fa-terminal'),
|
|
('project.files', 'Dateien verwalten', 'fas fa-folder')
|
|
] %}
|
|
|
|
{% for perm, desc, icon in project_permissions %}
|
|
{% set has_perm = user.role in ['admin'] or (user.role == 'moderator' and perm != 'project.delete') or (user.role == 'user' and perm not in ['project.delete', 'project.console']) or (user.role == 'viewer' and perm in ['project.view', 'project.logs']) %}
|
|
<div class="permission-item d-flex align-items-center mb-2">
|
|
<i class="{{ icon }} me-2 {{ 'text-success' if has_perm else 'text-muted' }}"></i>
|
|
<span class="{{ 'text-dark' if has_perm else 'text-muted' }}">{{ desc }}</span>
|
|
{% if has_perm %}
|
|
<i class="fas fa-check text-success ms-auto"></i>
|
|
{% else %}
|
|
<i class="fas fa-times text-danger ms-auto"></i>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- System-Berechtigungen -->
|
|
<div class="col-md-6">
|
|
<h6 class="text-warning mb-3"><i class="fas fa-cogs me-2"></i>System-Berechtigungen</h6>
|
|
<div class="permissions-list">
|
|
{% set system_permissions = [
|
|
('system.config', 'Konfiguration', 'fas fa-cog'),
|
|
('system.users', 'Benutzerverwaltung', 'fas fa-users'),
|
|
('system.monitoring', 'System-Überwachung', 'fas fa-chart-line'),
|
|
('system.backups', 'Backup-Verwaltung', 'fas fa-download'),
|
|
('system.docker', 'Docker-Verwaltung', 'fab fa-docker')
|
|
] %}
|
|
|
|
{% for perm, desc, icon in system_permissions %}
|
|
{% set has_perm = user.role == 'admin' or (user.role == 'moderator' and perm in ['system.monitoring', 'system.docker']) %}
|
|
<div class="permission-item d-flex align-items-center mb-2">
|
|
<i class="{{ icon }} me-2 {{ 'text-success' if has_perm else 'text-muted' }}"></i>
|
|
<span class="{{ 'text-dark' if has_perm else 'text-muted' }}">{{ desc }}</span>
|
|
{% if has_perm %}
|
|
<i class="fas fa-check text-success ms-auto"></i>
|
|
{% else %}
|
|
<i class="fas fa-times text-danger ms-auto"></i>
|
|
{% endif %}
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.info-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.permission-item {
|
|
padding: 0.25rem 0;
|
|
border-bottom: 1px solid #f8f9fa;
|
|
}
|
|
|
|
.permission-item:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.permissions-list {
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
<script>
|
|
// Passwort-Bestätigung prüfen
|
|
document.getElementById('confirm_password').addEventListener('input', function() {
|
|
const newPassword = document.getElementById('new_password').value;
|
|
const confirmPassword = this.value;
|
|
|
|
if (newPassword !== confirmPassword) {
|
|
this.setCustomValidity('Passwörter stimmen nicht überein');
|
|
} else {
|
|
this.setCustomValidity('');
|
|
}
|
|
});
|
|
|
|
document.getElementById('new_password').addEventListener('input', function() {
|
|
const confirmPassword = document.getElementById('confirm_password');
|
|
confirmPassword.dispatchEvent(new Event('input'));
|
|
});
|
|
</script>
|
|
{% endblock %}
|