Security: verwijder hardcoded wachtwoord, voeg random-wachtwoord-generator toe bij eerste installatie

This commit is contained in:
2026-08-27 08:57:05 +00:00
parent 6485f693dc
commit 74612aefbb
55 changed files with 6019 additions and 876 deletions
+115 -7
View File
@@ -31,6 +31,9 @@
<button type="button" class="btn btn-outline-primary btn-sm" data-bs-toggle="modal" data-bs-target="#newFileModal">
<i class="bi bi-file-earmark-plus"></i> {{ ta.theme_new_file|default('Nieuw bestand') }}
</button>
<button type="button" class="btn btn-outline-secondary btn-sm" id="newDirBtnTop" data-bs-toggle="modal" data-bs-target="#newDirModal" data-in-dir="{{ selectedDir|default('') }}">
<i class="bi bi-folder-plus"></i> {{ ta.new_folder|default('Nieuwe map') }}
</button>
<a href="/admin/theme" class="btn btn-outline-secondary btn-sm">
<i class="bi bi-arrow-left"></i> {{ ta.back|default('Terug') }}
</a>
@@ -64,23 +67,88 @@
'files': files,
'relFile': relFile,
'editableExts': editableExts,
'csrf_token': csrf_token,
'treeIdPrefix': 'theme-tree',
'treeHeader': ta.theme_files|default('Thema bestanden'),
'treeEmptyText': ta.theme_no_files|default('Geen bestanden gevonden.'),
'treeRouteBase': '/admin/theme-edit',
'treeRouteParams': 'theme=' ~ themeName|url_encode ~ '&',
'treeDeleteRoute': '/admin/theme-file-delete',
'treeDeleteName': 'theme',
'treeDeleteValue': themeName,
'treeMoveRoute': '/admin/theme-file-move',
'treeMoveParams': 'theme=' ~ themeName|url_encode ~ '&',
'treeDirActions': false,
'treeDirActions': true,
'treeHideActionsFor': ['theme.json'],
'treeDirSelectRoute': '/admin/theme-edit?theme=' ~ themeName|url_encode,
'treeDirRenameRoute': '/admin/theme-dir-rename-in?theme=' ~ themeName|url_encode,
'treeRootLabel': themeName,
'treeScope': 'theme',
'treeMoveUrl': '/admin/tree-move',
'treeDeleteBase': '/admin/theme-file-delete',
'treeScopeParam': 'theme=' ~ themeName|url_encode ~ '&',
'selectedDir': selectedDir|default(''),
'newFileModalId': '#newFileModal',
'newDirModalId': '#newDirModal',
} %}
{# Editor main panel #}
<div class="editor-main">
{% if showMapPaneel %}
{# Map detail paneel — tonen wanneer een map is geselecteerd #}
<nav aria-label="breadcrumb" class="mb-2">
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="/admin/theme-edit?theme={{ themeName|url_encode }}"><i class="bi bi-folder2-open"></i> {{ themeName }}</a></li>
{% if selectedDir %}
{% set crumbPath = '' %}
{% for part in selectedDir|split('/') %}
{% set crumbPath = crumbPath ? crumbPath ~ '/' ~ part : part %}
{% if loop.last %}
<li class="breadcrumb-item active" aria-current="page">{{ part }}</li>
{% else %}
<li class="breadcrumb-item"><a href="/admin/theme-edit?theme={{ themeName|url_encode }}&dir={{ crumbPath|url_encode }}">{{ part }}</a></li>
{% endif %}
{% endfor %}
{% endif %}
</ol>
</nav>
<div class="card shadow-sm">
<div class="card-header d-flex align-items-center gap-2">
<i class="bi bi-folder-fill text-warning"></i>
<span class="fw-semibold">{{ selectedDirIsRoot ? themeName : selectedDirName }}</span>
{% if not selectedDirIsRoot %}
<span class="badge bg-light text-dark ms-1">{{ themeName }}/{{ selectedDir }}</span>
{% endif %}
</div>
<div class="card-body">
{# Map acties: nieuw bestand / nieuwe map / upload / verwijder #}
<div class="d-flex flex-wrap gap-2 mb-3">
<button type="button" class="btn btn-outline-primary btn-sm" data-bs-toggle="modal" data-bs-target="#newFileModal" data-in-dir="{{ selectedDir }}">
<i class="bi bi-file-earmark-plus"></i> {{ ta.new_file|default('Nieuw bestand') }}
</button>
<button type="button" class="btn btn-outline-secondary btn-sm" data-bs-toggle="modal" data-bs-target="#newDirModal" data-in-dir="{{ selectedDir }}">
<i class="bi bi-folder-plus"></i> {{ ta.new_folder|default('Nieuwe map') }}
</button>
<button type="button" class="btn btn-outline-success btn-sm" data-bs-toggle="collapse" data-bs-target="#themeUploadForm">
<i class="bi bi-cloud-upload"></i> {{ ta.upload|default('Upload') }}
</button>
{% if not selectedDirIsRoot %}
<form method="POST" action="/admin/theme-dir-delete-in" class="d-inline" onsubmit="return confirm('{{ ta.confirm_delete_folder|default('Weet je zeker dat je deze map wilt verwijderen? De map moet leeg zijn.') }}')">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="theme" value="{{ themeName }}">
<input type="hidden" name="dir" value="{{ selectedDir }}">
<button type="submit" class="btn btn-outline-danger btn-sm">
<i class="bi bi-trash"></i> {{ ta.delete|default('Verwijderen') }}
</button>
</form>
{% endif %}
</div>
<div class="text-muted small">
<i class="bi bi-files"></i>
{{ selectedDirCounts.files }} {{ ta.files|default('bestanden') }},
{{ selectedDirCounts.dirs }} {{ ta.subfolders|default('submappen') }}
</div>
</div>
</div>
{% else %}
{% if relFile %}
<nav aria-label="breadcrumb" class="mb-2">
<ol class="breadcrumb mb-0">
@@ -110,13 +178,23 @@
</div>
</div>
</div>
</form>
<div class="d-flex gap-2 mt-3">
<button type="submit" class="btn btn-primary">
<button type="submit" form="editor-form" class="btn btn-primary">
<i class="bi bi-check-lg"></i> {{ ta.save|default('Opslaan') }}
</button>
<a href="/admin/theme" class="btn btn-outline-secondary">{{ ta.cancel|default('Annuleren') }}</a>
{% if relFile != 'theme.json' %}
<form method="POST" action="/admin/theme-file-delete" class="ms-auto" onsubmit="return confirm('{{ ta.confirm_delete_file|default('Weet je zeker dat je dit bestand wilt verwijderen?') }}')">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="theme" value="{{ themeName }}">
<input type="hidden" name="file" value="{{ relFile }}">
<button type="submit" class="btn btn-outline-danger" title="{{ ta.delete|default('Verwijderen') }}">
<i class="bi bi-trash"></i> {{ ta.delete|default('Verwijderen') }}
</button>
</form>
{% endif %}
</div>
</form>
{% else %}
<div class="card shadow-sm">
<div class="card-body text-center py-5 text-muted">
@@ -129,6 +207,7 @@
</div>
</div>
{% endif %}
{% endif %}{# end showMapPaneel #}
</div>
</div>
@@ -139,6 +218,7 @@
<form method="POST" action="/admin/theme-edit?theme={{ themeName|url_encode }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="action" value="new_file">
<input type="hidden" name="in_dir" value="" data-in-dir-field>
<div class="modal-header">
<h5 class="modal-title" id="newFileModalLabel"><i class="bi bi-file-earmark-plus"></i> {{ ta.theme_new_file_title|default('Nieuw bestand aanmaken') }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
@@ -158,6 +238,34 @@
</div>
</div>
</div>
{# New directory modal #}
<div class="modal fade" id="newDirModal" tabindex="-1" aria-labelledby="newDirModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form method="POST" action="/admin/theme-dir-create-in">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="theme" value="{{ themeName }}">
<input type="hidden" name="in_dir" value="" data-in-dir-field>
<div class="modal-header">
<h5 class="modal-title" id="newDirModalLabel"><i class="bi bi-folder-plus"></i> {{ ta.new_folder_title|default('Nieuwe map aanmaken') }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="dirnameInput" class="form-label">{{ ta.folder_name|default('Mapnaam') }}</label>
<input type="text" class="form-control" id="dirnameInput" name="dirname" required autofocus>
<div class="form-text">{{ ta.name_help|default('Alleen letters, cijfers, punten, underscores en streepjes.') }}</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ ta.cancel|default('Annuleren') }}</button>
<button type="submit" class="btn btn-primary"><i class="bi bi-check-lg"></i> {{ ta.create|default('Aanmaken') }}</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}