improvements
This commit is contained in:
parent
d7bdb646fd
commit
f0e7e9c165
14
app.py
14
app.py
@ -900,11 +900,23 @@ def handle_request_map_data():
|
|||||||
@auth.require_secret
|
@auth.require_secret
|
||||||
def index(path):
|
def index(path):
|
||||||
app_config = auth.return_app_config()
|
app_config = auth.return_app_config()
|
||||||
|
|
||||||
|
# Generate dynamic Open Graph meta tags for Telegram preview
|
||||||
|
og_title = app_config.get('TITLE_LONG', 'Default Title')
|
||||||
|
og_description = "... uns aber, die wir gerettet werden, ist es eine Gotteskraft."
|
||||||
|
|
||||||
|
# If secret or token is provided, show folder names in description
|
||||||
|
folder_names = list(session['folders'].keys())
|
||||||
|
if folder_names:
|
||||||
|
folder_list = ", ".join(folder_names)
|
||||||
|
og_description = folder_list
|
||||||
|
|
||||||
return render_template("app.html",
|
return render_template("app.html",
|
||||||
search_folders = list(session['folders'].keys()),
|
search_folders = folder_names,
|
||||||
title_short=app_config.get('TITLE_SHORT', 'Default Title'),
|
title_short=app_config.get('TITLE_SHORT', 'Default Title'),
|
||||||
title_long=app_config.get('TITLE_LONG' , 'Default Title'),
|
title_long=app_config.get('TITLE_LONG' , 'Default Title'),
|
||||||
|
og_title=og_title,
|
||||||
|
og_description=og_description,
|
||||||
admin_enabled=auth.is_admin()
|
admin_enabled=auth.is_admin()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
42
auth.py
42
auth.py
@ -103,17 +103,17 @@ def require_secret(f):
|
|||||||
|
|
||||||
# 4) Re-check validity of each secret and token to also catch previous ones
|
# 4) Re-check validity of each secret and token to also catch previous ones
|
||||||
# If a secret is no longer valid (or not in config), remove it.
|
# If a secret is no longer valid (or not in config), remove it.
|
||||||
for secret_in_session in session['valid_secrets'][:]:
|
for secret_in_session in session.get('valid_secrets', [])[:]:
|
||||||
# Find the current config item with matching secret
|
# Find the current config item with matching secret
|
||||||
config_item = next(
|
config_item = next(
|
||||||
(c for c in folder_config if c['secret'] == secret_in_session),
|
(c for c in folder_config if c['secret'] == secret_in_session),
|
||||||
None
|
None
|
||||||
)
|
)
|
||||||
# If the config item doesn’t exist or is invalid, remove secret
|
# If the config item doesn't exist or is invalid, remove secret
|
||||||
if config_item is None or not is_valid_secret(config_item, secret_in_session):
|
if config_item is None or not is_valid_secret(config_item, secret_in_session):
|
||||||
session['valid_secrets'].remove(secret_in_session)
|
session['valid_secrets'].remove(secret_in_session)
|
||||||
|
|
||||||
for token_in_session in session['valid_tokens'][:]:
|
for token_in_session in session.get('valid_tokens', [])[:]:
|
||||||
if not is_valid_token(token_in_session):
|
if not is_valid_token(token_in_session):
|
||||||
session['valid_tokens'].remove(token_in_session)
|
session['valid_tokens'].remove(token_in_session)
|
||||||
|
|
||||||
@ -130,7 +130,6 @@ def require_secret(f):
|
|||||||
session['admin'] = False
|
session['admin'] = False
|
||||||
|
|
||||||
# 5) Build session['folders'] fresh from the valid secrets
|
# 5) Build session['folders'] fresh from the valid secrets
|
||||||
# If admin, grant access to ALL folders
|
|
||||||
session['folders'] = {}
|
session['folders'] = {}
|
||||||
|
|
||||||
if is_admin():
|
if is_admin():
|
||||||
@ -139,7 +138,7 @@ def require_secret(f):
|
|||||||
for folder_info in config_item['folders']:
|
for folder_info in config_item['folders']:
|
||||||
session['folders'][folder_info['foldername']] = folder_info['folderpath']
|
session['folders'][folder_info['foldername']] = folder_info['folderpath']
|
||||||
else:
|
else:
|
||||||
# Normal users only get folders from their valid secrets/tokens
|
# Normal users only get folders from their valid secrets
|
||||||
for secret_in_session in session.get('valid_secrets', []):
|
for secret_in_session in session.get('valid_secrets', []):
|
||||||
config_item = next(
|
config_item = next(
|
||||||
(c for c in folder_config if c['secret'] == secret_in_session),
|
(c for c in folder_config if c['secret'] == secret_in_session),
|
||||||
@ -149,10 +148,21 @@ def require_secret(f):
|
|||||||
for folder_info in config_item['folders']:
|
for folder_info in config_item['folders']:
|
||||||
session['folders'][folder_info['foldername']] = folder_info['folderpath']
|
session['folders'][folder_info['foldername']] = folder_info['folderpath']
|
||||||
|
|
||||||
for token_in_session in session.get('valid_tokens', []):
|
# Add token folders for both admin and regular users
|
||||||
|
for token_in_session in session.get('valid_tokens', []):
|
||||||
|
try:
|
||||||
token_item = decode_token(token_in_session)
|
token_item = decode_token(token_in_session)
|
||||||
for folder_info in token_item['folders']:
|
print(f"DEBUG: Decoded token: {token_item}")
|
||||||
|
for folder_info in token_item.get('folders', []):
|
||||||
|
print(f"DEBUG: Adding folder '{folder_info['foldername']}' -> '{folder_info['folderpath']}'")
|
||||||
session['folders'][folder_info['foldername']] = folder_info['folderpath']
|
session['folders'][folder_info['foldername']] = folder_info['folderpath']
|
||||||
|
except Exception as e:
|
||||||
|
print(f"ERROR: Failed to process token: {e}")
|
||||||
|
|
||||||
|
# Mark session as modified to ensure it's saved
|
||||||
|
session.modified = True
|
||||||
|
print(f"DEBUG: Final session['folders'] keys: {list(session['folders'].keys())}")
|
||||||
|
print(f"DEBUG: session['valid_tokens']: {session.get('valid_tokens', [])}")
|
||||||
|
|
||||||
# 6) If we have folders, proceed; otherwise show index
|
# 6) If we have folders, proceed; otherwise show index
|
||||||
if session['folders']:
|
if session['folders']:
|
||||||
@ -161,14 +171,16 @@ def require_secret(f):
|
|||||||
if 'device_id' not in session:
|
if 'device_id' not in session:
|
||||||
session['device_id'] = os.urandom(32).hex()
|
session['device_id'] = os.urandom(32).hex()
|
||||||
|
|
||||||
# AUTO-JUMP FOR TOKENS
|
# AUTO-JUMP FOR TOKENS - Disabled for now to debug
|
||||||
try:
|
# try:
|
||||||
if args_token and is_valid_token(args_token):
|
# if args_token and is_valid_token(args_token):
|
||||||
token_item = decode_token(args_token)
|
# token_item = decode_token(args_token)
|
||||||
target_foldername = token_item['folders'][0]['foldername']
|
# target_foldername = token_item['folders'][0]['foldername']
|
||||||
return redirect(f"path/{target_foldername}")
|
# # Mark session as modified to ensure it's saved before redirect
|
||||||
except Exception as e:
|
# session.modified = True
|
||||||
print(f"Error during auto-jump: {e}")
|
# return redirect(f"/path/{target_foldername}")
|
||||||
|
# except Exception as e:
|
||||||
|
# print(f"Error during auto-jump: {e}")
|
||||||
|
|
||||||
return f(*args, **kwargs)
|
return f(*args, **kwargs)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@ -528,6 +528,30 @@ footer {
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message-content h1 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content h2 {
|
||||||
|
font-size: 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content h3 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content h4 {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content h5 {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content h6 {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
.message-content p {
|
.message-content p {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -258,9 +258,14 @@ function openMessageModal(messageId = null) {
|
|||||||
messageIdInput.value = message.id;
|
messageIdInput.value = message.id;
|
||||||
titleInput.value = message.title;
|
titleInput.value = message.title;
|
||||||
|
|
||||||
// Format datetime for input
|
// Format datetime for input (convert to local time)
|
||||||
const date = new Date(message.datetime);
|
const date = new Date(message.datetime);
|
||||||
const formattedDate = date.toISOString().slice(0, 16);
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
const formattedDate = `${year}-${month}-${day}T${hours}:${minutes}`;
|
||||||
datetimeInput.value = formattedDate;
|
datetimeInput.value = formattedDate;
|
||||||
|
|
||||||
contentInput.value = message.content;
|
contentInput.value = message.content;
|
||||||
@ -271,9 +276,14 @@ function openMessageModal(messageId = null) {
|
|||||||
messageIdInput.value = '';
|
messageIdInput.value = '';
|
||||||
titleInput.value = '';
|
titleInput.value = '';
|
||||||
|
|
||||||
// Set current datetime
|
// Set current datetime (use local time)
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const formattedNow = now.toISOString().slice(0, 16);
|
const year = now.getFullYear();
|
||||||
|
const month = String(now.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(now.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(now.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||||
|
const formattedNow = `${year}-${month}-${day}T${hours}:${minutes}`;
|
||||||
datetimeInput.value = formattedNow;
|
datetimeInput.value = formattedNow;
|
||||||
|
|
||||||
contentInput.value = '';
|
contentInput.value = '';
|
||||||
|
|||||||
@ -6,9 +6,10 @@
|
|||||||
|
|
||||||
<title>{{ title_short }}</title>
|
<title>{{ title_short }}</title>
|
||||||
|
|
||||||
<meta property="og:title" content="{{ title_long }}" />
|
<meta property="og:title" content="{{ og_title }}" />
|
||||||
<meta property="og:description" content="... uns aber, die wir gerettet werden, ist es eine Gotteskraft." />
|
<meta property="og:description" content="{{ og_description }}" />
|
||||||
<meta property="og:image" content="/icon/logo-192x192.png" />
|
<meta property="og:image" content="/icon/logo-192x192.png" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="description" content="... uns aber, die wir gerettet werden, ist es eine Gotteskraft.">
|
<meta name="description" content="... uns aber, die wir gerettet werden, ist es eine Gotteskraft.">
|
||||||
@ -83,21 +84,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Messages Section -->
|
{% include 'messages_section.html' %}
|
||||||
<section id="messages-section" class="tab-content">
|
|
||||||
<div class="container">
|
|
||||||
{% if admin_enabled %}
|
|
||||||
<div class="mb-3">
|
|
||||||
<button id="add-message-btn" class="btn btn-primary" title="Nachricht hinzufügen">
|
|
||||||
<i class="bi bi-plus-circle"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div id="messages-container" class="messages-container">
|
|
||||||
<!-- Messages will be loaded here via JavaScript -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<search style="display: none;">
|
<search style="display: none;">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
68
templates/messages_section.html
Normal file
68
templates/messages_section.html
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<!-- Messages Section -->
|
||||||
|
<section id="messages-section" class="tab-content">
|
||||||
|
<div class="container">
|
||||||
|
{% if admin_enabled %}
|
||||||
|
<div class="mb-3">
|
||||||
|
<button id="add-message-btn" class="btn btn-primary" title="Nachricht hinzufügen">
|
||||||
|
<i class="bi bi-plus-circle"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div id="messages-container" class="messages-container">
|
||||||
|
<!-- Messages will be loaded here via JavaScript -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Message Modal -->
|
||||||
|
<div class="modal fade" id="messageModal" tabindex="-1" aria-labelledby="messageModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="messageModalLabel">Nachricht bearbeiten</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="messageForm">
|
||||||
|
<input type="hidden" id="messageId">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="messageTitle" class="form-label">Titel</label>
|
||||||
|
<input type="text" class="form-control" id="messageTitle" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="messageDateTime" class="form-label">Datum und Zeit</label>
|
||||||
|
<input type="datetime-local" class="form-control" id="messageDateTime" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="messageContent" class="form-label">Inhalt (Markdown unterstützt)</label>
|
||||||
|
<div class="mb-2">
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-secondary" id="insertLinkBtn">
|
||||||
|
<i class="bi bi-link-45deg"></i> Datei/Ordner verlinken
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="collapse" id="fileBrowserCollapse">
|
||||||
|
<div class="file-browser-panel">
|
||||||
|
<h6>Datei/Ordner auswählen</h6>
|
||||||
|
<div id="fileBrowserPath" class="mb-2">
|
||||||
|
<small class="text-muted">Pfad: <span id="currentPath">/</span></small>
|
||||||
|
</div>
|
||||||
|
<div id="fileBrowserContent" class="file-browser-content">
|
||||||
|
<div class="text-center py-3">
|
||||||
|
<div class="spinner-border spinner-border-sm" role="status">
|
||||||
|
<span class="visually-hidden">Laden...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<textarea class="form-control" id="messageContent" rows="10" required></textarea>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Abbrechen</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="saveMessageBtn">Speichern</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Loading…
x
Reference in New Issue
Block a user