From: PhiTux Date: Thu, 11 Sep 2025 15:08:39 +0000 (+0200) Subject: added feature to reauthenticate on pageload X-Git-Url: http://git.99rst.org/?a=commitdiff_plain;h=0cef6c1558a439d8bcf3a1cf77e8f3a4ed3d229e;p=DailyTxT.git added feature to reauthenticate on pageload --- diff --git a/backend/handlers/users.go b/backend/handlers/users.go index 3b98b20..1cd6b61 100644 --- a/backend/handlers/users.go +++ b/backend/handlers/users.go @@ -439,6 +439,7 @@ func GetDefaultSettings() map[string]any { "monochromeBackgroundColor": "#ececec", "checkForUpdates": true, "includeTestVersions": false, + "requirePasswordOnPageLoad": false, } } @@ -1145,3 +1146,33 @@ func ChangeUsername(w http.ResponseWriter, r *http.Request) { "available_backup_codes": availableBackupCodes, }) } + +// ValidatePasswordRequest represents the validate password request body +type ValidatePasswordRequest struct { + Password string `json:"password"` +} + +// ValidatePassword validates the user's password for re-authentication +func ValidatePassword(w http.ResponseWriter, r *http.Request) { + // Get user ID from context + userID, ok := r.Context().Value(utils.UserIDKey).(int) + if !ok { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + // Parse the request body + var req ValidatePasswordRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, "Invalid request body", http.StatusBadRequest) + return + } + + // Validate password using the same method as login + derived_key, available_backup_codes, _ := utils.CheckPasswordForUser(userID, req.Password) + + utils.JSONResponse(w, http.StatusOK, map[string]any{ + "valid": derived_key != "", + "available_backup_codes": available_backup_codes, + }) +} diff --git a/backend/main.go b/backend/main.go index c7aae83..630215e 100644 --- a/backend/main.go +++ b/backend/main.go @@ -76,6 +76,7 @@ func main() { mux.HandleFunc("POST /users/changeUsername", middleware.RequireAuth(handlers.ChangeUsername)) mux.HandleFunc("POST /users/deleteAccount", middleware.RequireAuth(handlers.DeleteAccount)) mux.HandleFunc("POST /users/createBackupCodes", middleware.RequireAuth(handlers.CreateBackupCodes)) + mux.HandleFunc("POST /users/validatePassword", middleware.RequireAuth(handlers.ValidatePassword)) mux.HandleFunc("GET /users/statistics", middleware.RequireAuth(handlers.GetStatistics)) mux.HandleFunc("POST /logs/saveLog", middleware.RequireAuth(handlers.SaveLog)) diff --git a/frontend/src/lib/Datepicker.svelte b/frontend/src/lib/Datepicker.svelte index 0d0e637..96a5c99 100644 --- a/frontend/src/lib/Datepicker.svelte +++ b/frontend/src/lib/Datepicker.svelte @@ -3,7 +3,7 @@ import { onMount } from 'svelte'; import { fly } from 'svelte/transition'; import * as bootstrap from 'bootstrap'; - import { offcanvasIsOpen, sameDate } from '$lib/helpers.js'; + import { offcanvasIsOpen, sameDate, isAuthenticated } from '$lib/helpers.js'; import { getTranslate } from '@tolgee/svelte'; const { t } = getTranslate(); @@ -88,7 +88,7 @@ }; $effect(() => { - if (window.location.href) { + if ($isAuthenticated && window.location.href) { setTimeout(() => { oc = document.querySelector('.offcanvas'); oc.addEventListener('hidden.bs.offcanvas', () => { diff --git a/frontend/src/lib/Sidenav.svelte b/frontend/src/lib/Sidenav.svelte index 2ae549b..7a1649d 100644 --- a/frontend/src/lib/Sidenav.svelte +++ b/frontend/src/lib/Sidenav.svelte @@ -8,7 +8,7 @@ import { onMount } from 'svelte'; import * as bootstrap from 'bootstrap'; import Tag from './Tag.svelte'; - import { offcanvasIsOpen, sameDate } from '$lib/helpers.js'; + import { isAuthenticated, offcanvasIsOpen, sameDate } from '$lib/helpers.js'; import { API_URL } from '$lib/APIurl.js'; import axios from 'axios'; import { cal } from '$lib/calendarStore.js'; @@ -58,7 +58,7 @@ } $effect(() => { - if (window.location.href) { + if ($isAuthenticated && window.location.href) { setTimeout(() => { oc = document.querySelector('.offcanvas'); oc.addEventListener('hidden.bs.offcanvas', () => { diff --git a/frontend/src/lib/assets/GitHub-Logo.png b/frontend/src/lib/assets/GitHub-Logo.png new file mode 100644 index 0000000..84ed908 Binary files /dev/null and b/frontend/src/lib/assets/GitHub-Logo.png differ diff --git a/frontend/src/lib/assets/bmc-button.png b/frontend/src/lib/assets/bmc-button.png new file mode 100644 index 0000000..464bfd9 Binary files /dev/null and b/frontend/src/lib/assets/bmc-button.png differ diff --git a/frontend/src/lib/helpers.js b/frontend/src/lib/helpers.js index 6213608..ad37747 100644 --- a/frontend/src/lib/helpers.js +++ b/frontend/src/lib/helpers.js @@ -21,6 +21,26 @@ function sameDate(date1, date2) { ); } +export const isAuthenticated = writable(false); + +// Function to check if page load authentication is required +function needsReauthentication() { + isAuthenticated.subscribe((value) => { + if (value) return false; + }) + + if (typeof window === 'undefined') return false; + + // Check localStorage for re-auth requirement + const requireReauth = localStorage.getItem('requirePasswordOnPageLoad'); + + if (requireReauth !== 'true') { + isAuthenticated.set(true); + } + + return requireReauth === 'true'; +} + function generateNeonMesh(dark) { /* const baseColors = ['#ff00ff', '#00ffff', '#ffea00', '#ff0080', '#00ff80', '#ff4500']; */ const baseColors = ["#ff00ff", "#00ffff", "#ffea00", "#ff0080", "#00ff80", "#ff4500", @@ -56,7 +76,7 @@ function loadFlagEmoji(language) { return json[language] || ''; } -export { formatBytes, sameDate, loadFlagEmoji, generateNeonMesh }; +export { formatBytes, sameDate, needsReauthentication, generateNeonMesh, loadFlagEmoji }; export let alwaysShowSidenav = writable(true); diff --git a/frontend/src/routes/(authed)/+layout.svelte b/frontend/src/routes/(authed)/+layout.svelte index 5a5e387..b0838f3 100644 --- a/frontend/src/routes/(authed)/+layout.svelte +++ b/frontend/src/routes/(authed)/+layout.svelte @@ -2,7 +2,7 @@ import * as bootstrap from 'bootstrap'; import Fa from 'svelte-fa'; import { goto } from '$app/navigation'; - import { onMount } from 'svelte'; + import { onDestroy, onMount } from 'svelte'; import { readingMode, settings, @@ -12,7 +12,13 @@ import { API_URL } from '$lib/APIurl.js'; import { tags } from '$lib/tagStore.js'; import TagModal from '$lib/TagModal.svelte'; - import { alwaysShowSidenav, generateNeonMesh, loadFlagEmoji } from '$lib/helpers.js'; + import { + alwaysShowSidenav, + generateNeonMesh, + loadFlagEmoji, + needsReauthentication, + isAuthenticated + } from '$lib/helpers.js'; import { templates } from '$lib/templateStore'; import { faRightFromBracket, @@ -112,7 +118,22 @@ } }); + onDestroy(() => { + $isAuthenticated = false; + }); + onMount(() => { + let needsReauth = needsReauthentication(); + + // Check if re-authentication is needed FIRST + if (!$isAuthenticated && needsReauth) { + // Save current route for return after reauth + localStorage.setItem('returnAfterReauth', window.location.pathname); + goto('/reauth'); + return; // Stop further initialization + } + + // Normal initialization only if authenticated getUserSettings(); getTemplates(); getVersionInfo(); @@ -323,6 +344,13 @@ $settings = response.data; $tempSettings = JSON.parse(JSON.stringify($settings)); aLookBackYears = $settings.aLookBackYears.toString(); + + // Save re-auth setting to localStorage for immediate availability + localStorage.setItem( + 'requirePasswordOnPageLoad', + $settings.requirePasswordOnPageLoad.toString() + ); + updateLanguage(); // set background @@ -436,6 +464,12 @@ if (response.data.success) { $settings = $tempSettings; + // Save re-auth setting to localStorage for immediate availability + localStorage.setItem( + 'requirePasswordOnPageLoad', + $tempSettings.requirePasswordOnPageLoad.toString() + ); + // update language updateLanguage(); @@ -1512,11 +1546,25 @@
-
Login bei Reload
- Bla
- blub
- bla
- blub
+ {#if $tempSettings.requirePasswordOnPageLoad !== $settings.requirePasswordOnPageLoad} + {@render unsavedChanges()} + {/if} + +
🔒 {$t('settings.reauth.title')}
+ {$t('settings.reauth.description')} + +
+ + +
diff --git a/frontend/src/routes/(authed)/read/+page.svelte b/frontend/src/routes/(authed)/read/+page.svelte index acf180d..b694ff6 100644 --- a/frontend/src/routes/(authed)/read/+page.svelte +++ b/frontend/src/routes/(authed)/read/+page.svelte @@ -13,7 +13,7 @@ import { faCloudArrowDown } from '@fortawesome/free-solid-svg-icons'; import { Fa } from 'svelte-fa'; import ImageViewer from '$lib/ImageViewer.svelte'; - import { alwaysShowSidenav } from '$lib/helpers.js'; + import { alwaysShowSidenav, needsReauthentication, isAuthenticated } from '$lib/helpers.js'; import { getTranslate } from '@tolgee/svelte'; const { t } = getTranslate(); @@ -34,6 +34,10 @@ let observer; onMount(() => { + /* if (!$isAuthenticated && needsReauthentication()) { + return; + } */ + loadMonthForReading(); // Highlights automatically the day in the calendar, when the log is in the viewport diff --git a/frontend/src/routes/(authed)/write/+page.svelte b/frontend/src/routes/(authed)/write/+page.svelte index c352e1b..0f378d4 100644 --- a/frontend/src/routes/(authed)/write/+page.svelte +++ b/frontend/src/routes/(authed)/write/+page.svelte @@ -32,7 +32,7 @@ import { formatBytes, alwaysShowSidenav, sameDate } from '$lib/helpers.js'; import ImageViewer from '$lib/ImageViewer.svelte'; import TemplateDropdown from '$lib/TemplateDropdown.svelte'; - import { templates, insertTemplate } from '$lib/templateStore'; + import { insertTemplate } from '$lib/templateStore'; import ALookBack from '$lib/ALookBack.svelte'; import { marked } from 'marked'; import { T, getTranslate } from '@tolgee/svelte'; @@ -242,7 +242,8 @@ let aLookBack = $state([]); function getALookBack() { - if (!$settings.useALookBack) { + // Skip if settings not loaded yet + if (!$settings || $settings.useALookBack === undefined || !$settings.useALookBack) { aLookBack = []; return; } @@ -264,6 +265,13 @@ }); } + // Re-trigger aLookBack when settings are loaded/changed + $effect(() => { + if ($settings && $settings.useALookBack !== undefined) { + getALookBack(); + } + }); + const imageExtensions = ['jpeg', 'jpg', 'gif', 'png', 'webp']; //TODO: support svg? -> minsize is necessary... diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte index 406b13c..d7a5490 100644 --- a/frontend/src/routes/login/+page.svelte +++ b/frontend/src/routes/login/+page.svelte @@ -6,7 +6,7 @@ import { goto } from '$app/navigation'; import { API_URL } from '$lib/APIurl.js'; import { getTranslate, getTolgee } from '@tolgee/svelte'; - import { loadFlagEmoji } from '$lib/helpers.js'; + import { isAuthenticated, loadFlagEmoji } from '$lib/helpers.js'; const { t } = getTranslate(); const tolgee = getTolgee(['language']); @@ -166,6 +166,7 @@ handleMigrationProgress(response.data.username); } else { + $isAuthenticated = true; localStorage.setItem('user', response.data.username); goto('/write'); } diff --git a/frontend/src/routes/reauth/+page.svelte b/frontend/src/routes/reauth/+page.svelte new file mode 100644 index 0000000..bc50b75 --- /dev/null +++ b/frontend/src/routes/reauth/+page.svelte @@ -0,0 +1,144 @@ + + +
+
+
+
+ + DailyTxT +
+

{$t('reauth.title')}

+
+
+

+ {$t('reauth.description')} +

+ +
+
+ +
+ + {#if error} +
{error}
+ {/if} + + +
+
+
+
+ +