4
0
Эх сурвалжийг харах

feat(ui): ask for the current password before changing it

Anyone with a signed-in web session could set a new password on the
authentication page, for example with a stolen session cookie or an
unattended browser. Since changing the password now signs out every
other session, this could also lock the owner out of their account.

Ask for the current password whenever a new password is set. Users
created through OAuth2 who have no password yet can still set one
without it, and changing only the username does not require it.
Failed attempts are logged like failed logins.
Frédéric Guillot 1 долоо хоног өмнө
parent
commit
f654f7c767
28 өөрчлөгдсөн 111 нэмэгдсэн , 6 устгасан
  1. 2 0
      internal/locale/translations/ar_SA.json
  2. 2 0
      internal/locale/translations/de_DE.json
  3. 2 0
      internal/locale/translations/el_EL.json
  4. 2 0
      internal/locale/translations/en_US.json
  5. 2 0
      internal/locale/translations/es_ES.json
  6. 2 0
      internal/locale/translations/fi_FI.json
  7. 2 0
      internal/locale/translations/fr_FR.json
  8. 2 0
      internal/locale/translations/gl_ES.json
  9. 2 0
      internal/locale/translations/hi_IN.json
  10. 2 0
      internal/locale/translations/id_ID.json
  11. 2 0
      internal/locale/translations/it_IT.json
  12. 2 0
      internal/locale/translations/ja_JP.json
  13. 2 0
      internal/locale/translations/ko_KR.json
  14. 2 0
      internal/locale/translations/nan_Latn_pehoeji.json
  15. 2 0
      internal/locale/translations/nl_NL.json
  16. 2 0
      internal/locale/translations/pl_PL.json
  17. 2 0
      internal/locale/translations/pt_BR.json
  18. 2 0
      internal/locale/translations/ro_RO.json
  19. 2 0
      internal/locale/translations/ru_RU.json
  20. 2 0
      internal/locale/translations/tr_TR.json
  21. 2 0
      internal/locale/translations/uk_UA.json
  22. 2 0
      internal/locale/translations/zh_CN.json
  23. 2 0
      internal/locale/translations/zh_TW.json
  24. 5 0
      internal/template/templates/views/authentication.html
  25. 7 0
      internal/ui/authentication_show.go
  26. 24 0
      internal/ui/authentication_update.go
  27. 8 6
      internal/ui/form/auth_settings.go
  28. 21 0
      internal/ui/form/auth_settings_test.go

+ 2 - 0
internal/locale/translations/ar_SA.json

@@ -142,6 +142,7 @@
     "error.http_too_many_requests": "أنشأ Miniflux عدداً كبيراً جداً من الطلبات لهذا الموقع. يرجى المحاولة لاحقاً أو تغيير إعدادات التطبيق.",
     "error.http_too_many_requests": "أنشأ Miniflux عدداً كبيراً جداً من الطلبات لهذا الموقع. يرجى المحاولة لاحقاً أو تغيير إعدادات التطبيق.",
     "error.http_unexpected_status_code": "الموقع غير متاح حالياً بسبب رمز حالة HTTP غير متوقع: %d. المشكلة ليست من جانب Miniflux. يرجى المحاولة لاحقاً.",
     "error.http_unexpected_status_code": "الموقع غير متاح حالياً بسبب رمز حالة HTTP غير متوقع: %d. المشكلة ليست من جانب Miniflux. يرجى المحاولة لاحقاً.",
     "error.invalid_categories_sorting_order": "ترتيب فرز الفئات غير صالح.",
     "error.invalid_categories_sorting_order": "ترتيب فرز الفئات غير صالح.",
+    "error.invalid_current_password": "كلمة المرور الحالية غير صحيحة.",
     "error.invalid_default_home_page": "الصفحة الرئيسية الافتراضية غير صالحة!",
     "error.invalid_default_home_page": "الصفحة الرئيسية الافتراضية غير صالحة!",
     "error.invalid_display_mode": "وضع عرض تطبيق الويب غير صالح.",
     "error.invalid_display_mode": "وضع عرض تطبيق الويب غير صالح.",
     "error.invalid_entry_direction": "اتجاه المقال غير صالح.",
     "error.invalid_entry_direction": "اتجاه المقال غير صالح.",
@@ -419,6 +420,7 @@
     "form.submit.saving": "جارٍ الحفظ...",
     "form.submit.saving": "جارٍ الحفظ...",
     "form.user.label.admin": "مدير",
     "form.user.label.admin": "مدير",
     "form.user.label.confirmation": "تأكيد كلمة المرور",
     "form.user.label.confirmation": "تأكيد كلمة المرور",
+    "form.user.label.current_password": "كلمة المرور الحالية",
     "form.user.label.password": "كلمة المرور",
     "form.user.label.password": "كلمة المرور",
     "form.user.label.username": "اسم المستخدم",
     "form.user.label.username": "اسم المستخدم",
     "menu.about": "حول",
     "menu.about": "حول",

+ 2 - 0
internal/locale/translations/de_DE.json

@@ -128,6 +128,7 @@
     "error.http_too_many_requests": "Miniflux hat zu viele Anfragen an diese Webseite gestellt. Bitte versuchen Sie es später erneut oder ändern Sie die Konfiguration der Anwendung.",
     "error.http_too_many_requests": "Miniflux hat zu viele Anfragen an diese Webseite gestellt. Bitte versuchen Sie es später erneut oder ändern Sie die Konfiguration der Anwendung.",
     "error.http_unexpected_status_code": "Die Webseite ist aufgrund eines eines unerwarteten HTTP-Fehlers derzeit nicht verfügbar: %d. Das Problem liegt nicht bei Miniflux. Bitte versuchen Sie es später erneut.",
     "error.http_unexpected_status_code": "Die Webseite ist aufgrund eines eines unerwarteten HTTP-Fehlers derzeit nicht verfügbar: %d. Das Problem liegt nicht bei Miniflux. Bitte versuchen Sie es später erneut.",
     "error.invalid_categories_sorting_order": "Ungültige Kategorie-Sortierreihenfolge.",
     "error.invalid_categories_sorting_order": "Ungültige Kategorie-Sortierreihenfolge.",
+    "error.invalid_current_password": "Das aktuelle Passwort ist falsch.",
     "error.invalid_default_home_page": "Ungültige Standard-Startseite!",
     "error.invalid_default_home_page": "Ungültige Standard-Startseite!",
     "error.invalid_display_mode": "Progressive-Web-App- (PWA-)Anzeigemodus",
     "error.invalid_display_mode": "Progressive-Web-App- (PWA-)Anzeigemodus",
     "error.invalid_entry_direction": "Ungültige Sortierreihenfolge.",
     "error.invalid_entry_direction": "Ungültige Sortierreihenfolge.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Speichern...",
     "form.submit.saving": "Speichern...",
     "form.user.label.admin": "Administrator",
     "form.user.label.admin": "Administrator",
     "form.user.label.confirmation": "Passwortbestätigung",
     "form.user.label.confirmation": "Passwortbestätigung",
+    "form.user.label.current_password": "Aktuelles Passwort",
     "form.user.label.password": "Passwort",
     "form.user.label.password": "Passwort",
     "form.user.label.username": "Benutzername",
     "form.user.label.username": "Benutzername",
     "menu.about": "Über",
     "menu.about": "Über",

+ 2 - 0
internal/locale/translations/el_EL.json

@@ -128,6 +128,7 @@
     "error.http_too_many_requests": "Το Miniflux δημιούργησε πάρα πολλά αιτήματα σε αυτόν τον ιστότοπο. Παρακαλώ δοκιμάστε ξανά αργότερα ή αλλάξτε τη διαμόρφωση της εφαρμογής.",
     "error.http_too_many_requests": "Το Miniflux δημιούργησε πάρα πολλά αιτήματα σε αυτόν τον ιστότοπο. Παρακαλώ δοκιμάστε ξανά αργότερα ή αλλάξτε τη διαμόρφωση της εφαρμογής.",
     "error.http_unexpected_status_code": "Ο ιστότοπος δεν είναι διαθέσιμος αυτήν τη στιγμή λόγω μη αναμενόμενου κωδικού κατάστασης HTTP: %d. Το πρόβλημα δεν είναι στην πλευρά του Miniflux. Παρακαλώ δοκιμάστε ξανά αργότερα.",
     "error.http_unexpected_status_code": "Ο ιστότοπος δεν είναι διαθέσιμος αυτήν τη στιγμή λόγω μη αναμενόμενου κωδικού κατάστασης HTTP: %d. Το πρόβλημα δεν είναι στην πλευρά του Miniflux. Παρακαλώ δοκιμάστε ξανά αργότερα.",
     "error.invalid_categories_sorting_order": "Η κατηγορία δεν μπορεί να είναι κενή.",
     "error.invalid_categories_sorting_order": "Η κατηγορία δεν μπορεί να είναι κενή.",
+    "error.invalid_current_password": "Ο τρέχων κωδικός είναι λανθασμένος.",
     "error.invalid_default_home_page": "Μη έγκυρη προεπιλεγμένη αρχική σελίδα!",
     "error.invalid_default_home_page": "Μη έγκυρη προεπιλεγμένη αρχική σελίδα!",
     "error.invalid_display_mode": "Μη έγκυρη λειτουργία εμφάνισης εφαρμογών ιστού.",
     "error.invalid_display_mode": "Μη έγκυρη λειτουργία εμφάνισης εφαρμογών ιστού.",
     "error.invalid_entry_direction": "Μη έγκυρη κατεύθυνση ταξινόμησης άρθρων.",
     "error.invalid_entry_direction": "Μη έγκυρη κατεύθυνση ταξινόμησης άρθρων.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Αποθήκευση...",
     "form.submit.saving": "Αποθήκευση...",
     "form.user.label.admin": "Διαχειριστής",
     "form.user.label.admin": "Διαχειριστής",
     "form.user.label.confirmation": "Επιβεβαίωση Κωδικού Πρόσβασης",
     "form.user.label.confirmation": "Επιβεβαίωση Κωδικού Πρόσβασης",
+    "form.user.label.current_password": "Τρέχων κωδικός",
     "form.user.label.password": "Κωδικός",
     "form.user.label.password": "Κωδικός",
     "form.user.label.username": "Χρήστης",
     "form.user.label.username": "Χρήστης",
     "menu.about": "Περί",
     "menu.about": "Περί",

+ 2 - 0
internal/locale/translations/en_US.json

@@ -130,6 +130,7 @@
     "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.",
     "error.http_too_many_requests": "Miniflux generated too many requests to this website. Please, try again later or change the application configuration.",
     "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.",
     "error.http_unexpected_status_code": "The website is not available at the moment due to an unexpected HTTP status code: %d. The problem is not on Miniflux side. Please, try again later.",
     "error.invalid_categories_sorting_order": "Invalid categories sorting order.",
     "error.invalid_categories_sorting_order": "Invalid categories sorting order.",
+    "error.invalid_current_password": "The current password is incorrect.",
     "error.invalid_default_home_page": "Invalid default homepage!",
     "error.invalid_default_home_page": "Invalid default homepage!",
     "error.invalid_display_mode": "Invalid web app display mode.",
     "error.invalid_display_mode": "Invalid web app display mode.",
     "error.invalid_entry_direction": "Invalid entry direction.",
     "error.invalid_entry_direction": "Invalid entry direction.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Saving…",
     "form.submit.saving": "Saving…",
     "form.user.label.admin": "Administrator",
     "form.user.label.admin": "Administrator",
     "form.user.label.confirmation": "Password Confirmation",
     "form.user.label.confirmation": "Password Confirmation",
+    "form.user.label.current_password": "Current Password",
     "form.user.label.password": "Password",
     "form.user.label.password": "Password",
     "form.user.label.username": "Username",
     "form.user.label.username": "Username",
     "menu.about": "About",
     "menu.about": "About",

+ 2 - 0
internal/locale/translations/es_ES.json

@@ -128,6 +128,7 @@
     "error.http_too_many_requests": "Miniflux generó demasiadas solicitudes a este sitio web. Por favor, inténtalo de nuevo más tarde o cambia la configuración de la aplicación.",
     "error.http_too_many_requests": "Miniflux generó demasiadas solicitudes a este sitio web. Por favor, inténtalo de nuevo más tarde o cambia la configuración de la aplicación.",
     "error.http_unexpected_status_code": "El sitio web no está disponible en este momento debido a un código de estado HTTP inesperado: %d. El problema no está en el lado de Miniflux. Por favor, inténtalo de nuevo más tarde.",
     "error.http_unexpected_status_code": "El sitio web no está disponible en este momento debido a un código de estado HTTP inesperado: %d. El problema no está en el lado de Miniflux. Por favor, inténtalo de nuevo más tarde.",
     "error.invalid_categories_sorting_order": "Orden de clasificación de categorías no válido.",
     "error.invalid_categories_sorting_order": "Orden de clasificación de categorías no válido.",
+    "error.invalid_current_password": "La contraseña actual es incorrecta.",
     "error.invalid_default_home_page": "¡Página de inicio por defecto no válida!",
     "error.invalid_default_home_page": "¡Página de inicio por defecto no válida!",
     "error.invalid_display_mode": "Modo de visualización de la aplicación web no válido.",
     "error.invalid_display_mode": "Modo de visualización de la aplicación web no válido.",
     "error.invalid_entry_direction": "Dirección de artículo no válida.",
     "error.invalid_entry_direction": "Dirección de artículo no válida.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Guardando...",
     "form.submit.saving": "Guardando...",
     "form.user.label.admin": "Administrador",
     "form.user.label.admin": "Administrador",
     "form.user.label.confirmation": "Confirmación de contraseña",
     "form.user.label.confirmation": "Confirmación de contraseña",
+    "form.user.label.current_password": "Contraseña actual",
     "form.user.label.password": "Contraseña",
     "form.user.label.password": "Contraseña",
     "form.user.label.username": "Nombre de usuario",
     "form.user.label.username": "Nombre de usuario",
     "menu.about": "Acerca de",
     "menu.about": "Acerca de",

+ 2 - 0
internal/locale/translations/fi_FI.json

@@ -128,6 +128,7 @@
     "error.http_too_many_requests": "Miniflux lähetti liikaa pyyntöjä tälle sivustolle. Yritä myöhemmin uudelleen tai muuta sovelluksen asetuksia.",
     "error.http_too_many_requests": "Miniflux lähetti liikaa pyyntöjä tälle sivustolle. Yritä myöhemmin uudelleen tai muuta sovelluksen asetuksia.",
     "error.http_unexpected_status_code": "Sivusto ei ole nyt käytettävissä odottamattoman HTTP-tilakoodin %d vuoksi. Ongelma ei ole Minifluxin puolella. Yritä myöhemmin uudelleen.",
     "error.http_unexpected_status_code": "Sivusto ei ole nyt käytettävissä odottamattoman HTTP-tilakoodin %d vuoksi. Ongelma ei ole Minifluxin puolella. Yritä myöhemmin uudelleen.",
     "error.invalid_categories_sorting_order": "Virheellinen kategorioiden lajittelujärjestys.",
     "error.invalid_categories_sorting_order": "Virheellinen kategorioiden lajittelujärjestys.",
+    "error.invalid_current_password": "Nykyinen salasana on väärä.",
     "error.invalid_default_home_page": "Väärä oletusarvoinen kotisivu!",
     "error.invalid_default_home_page": "Väärä oletusarvoinen kotisivu!",
     "error.invalid_display_mode": "Virheellinen verkkosovelluksen näyttötila.",
     "error.invalid_display_mode": "Virheellinen verkkosovelluksen näyttötila.",
     "error.invalid_entry_direction": "Virheellinen merkintäsuunta.",
     "error.invalid_entry_direction": "Virheellinen merkintäsuunta.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Tallennetaan...",
     "form.submit.saving": "Tallennetaan...",
     "form.user.label.admin": "Ylläpitäjä",
     "form.user.label.admin": "Ylläpitäjä",
     "form.user.label.confirmation": "Salasanan vahvistus",
     "form.user.label.confirmation": "Salasanan vahvistus",
+    "form.user.label.current_password": "Nykyinen salasana",
     "form.user.label.password": "Salasana",
     "form.user.label.password": "Salasana",
     "form.user.label.username": "Käyttäjätunnus",
     "form.user.label.username": "Käyttäjätunnus",
     "menu.about": "Tietoja",
     "menu.about": "Tietoja",

+ 2 - 0
internal/locale/translations/fr_FR.json

@@ -128,6 +128,7 @@
     "error.http_too_many_requests": "Miniflux a généré trop de requêtes vers ce site web. Veuillez réessayer plus tard ou changez la configuration de l'application.",
     "error.http_too_many_requests": "Miniflux a généré trop de requêtes vers ce site web. Veuillez réessayer plus tard ou changez la configuration de l'application.",
     "error.http_unexpected_status_code": "Le site web a répondu avec un code HTTP inattendu : %d. Le problème ne vient pas de Miniflux. Veuillez réessayer plus tard.",
     "error.http_unexpected_status_code": "Le site web a répondu avec un code HTTP inattendu : %d. Le problème ne vient pas de Miniflux. Veuillez réessayer plus tard.",
     "error.invalid_categories_sorting_order": "L'ordre de tri des catégories n'est pas valide.",
     "error.invalid_categories_sorting_order": "L'ordre de tri des catégories n'est pas valide.",
+    "error.invalid_current_password": "Le mot de passe actuel est incorrect.",
     "error.invalid_default_home_page": "Page d'accueil par défaut invalide !",
     "error.invalid_default_home_page": "Page d'accueil par défaut invalide !",
     "error.invalid_display_mode": "Mode d'affichage de l'application web non valide.",
     "error.invalid_display_mode": "Mode d'affichage de l'application web non valide.",
     "error.invalid_entry_direction": "Ordre de trie non valide.",
     "error.invalid_entry_direction": "Ordre de trie non valide.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Sauvegarde en cours...",
     "form.submit.saving": "Sauvegarde en cours...",
     "form.user.label.admin": "Administrateur",
     "form.user.label.admin": "Administrateur",
     "form.user.label.confirmation": "Confirmation du mot de passe",
     "form.user.label.confirmation": "Confirmation du mot de passe",
+    "form.user.label.current_password": "Mot de passe actuel",
     "form.user.label.password": "Mot de passe",
     "form.user.label.password": "Mot de passe",
     "form.user.label.username": "Nom d'utilisateur",
     "form.user.label.username": "Nom d'utilisateur",
     "menu.about": "À propos",
     "menu.about": "À propos",

+ 2 - 0
internal/locale/translations/gl_ES.json

@@ -130,6 +130,7 @@
     "error.http_too_many_requests": "Miniflux xerou demasiadas peticións a este servidor. Inténtao máis tarde ou cambia a configuración da aplicación.",
     "error.http_too_many_requests": "Miniflux xerou demasiadas peticións a este servidor. Inténtao máis tarde ou cambia a configuración da aplicación.",
     "error.http_unexpected_status_code": "O sitio web non está dispoñible neste momento debido a un código de estado HTTP non agardado: %d. O problema non está en Miniflux, inténtao máis tarde.",
     "error.http_unexpected_status_code": "O sitio web non está dispoñible neste momento debido a un código de estado HTTP non agardado: %d. O problema non está en Miniflux, inténtao máis tarde.",
     "error.invalid_categories_sorting_order": "Orde por categorías non válido.",
     "error.invalid_categories_sorting_order": "Orde por categorías non válido.",
+    "error.invalid_current_password": "O contrasinal actual é incorrecto.",
     "error.invalid_default_home_page": "Páxina de inicio predeterminada non válida!",
     "error.invalid_default_home_page": "Páxina de inicio predeterminada non válida!",
     "error.invalid_display_mode": "Modo para mostrar a aplicación web non válido.",
     "error.invalid_display_mode": "Modo para mostrar a aplicación web non válido.",
     "error.invalid_entry_direction": "Dirección da entrada non válida.",
     "error.invalid_entry_direction": "Dirección da entrada non válida.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Gardando…",
     "form.submit.saving": "Gardando…",
     "form.user.label.admin": "Admin",
     "form.user.label.admin": "Admin",
     "form.user.label.confirmation": "Confirmar contrasinal",
     "form.user.label.confirmation": "Confirmar contrasinal",
+    "form.user.label.current_password": "Contrasinal actual",
     "form.user.label.password": "Contrasinal",
     "form.user.label.password": "Contrasinal",
     "form.user.label.username": "Identificador",
     "form.user.label.username": "Identificador",
     "menu.about": "Sobre",
     "menu.about": "Sobre",

+ 2 - 0
internal/locale/translations/hi_IN.json

@@ -128,6 +128,7 @@
     "error.http_too_many_requests": "मिनीफ्लक्स ने इस वेबसाइट पर बहुत अधिक अनुरोध भेजे हैं। कृपया बाद में पुनः प्रयास करें या एप्लिकेशन कॉन्फ़िगरेशन बदलें।",
     "error.http_too_many_requests": "मिनीफ्लक्स ने इस वेबसाइट पर बहुत अधिक अनुरोध भेजे हैं। कृपया बाद में पुनः प्रयास करें या एप्लिकेशन कॉन्फ़िगरेशन बदलें।",
     "error.http_unexpected_status_code": "अप्रत्याशित HTTP स्थिति कोड %d के कारण वेबसाइट उपलब्ध नहीं है। समस्या मिनीफ्लक्स की तरफ नहीं है। कृपया बाद में पुनः प्रयास करें।",
     "error.http_unexpected_status_code": "अप्रत्याशित HTTP स्थिति कोड %d के कारण वेबसाइट उपलब्ध नहीं है। समस्या मिनीफ्लक्स की तरफ नहीं है। कृपया बाद में पुनः प्रयास करें।",
     "error.invalid_categories_sorting_order": "अमान्य श्रेणी क्रम।",
     "error.invalid_categories_sorting_order": "अमान्य श्रेणी क्रम।",
+    "error.invalid_current_password": "वर्तमान पासवर्ड गलत है।",
     "error.invalid_default_home_page": "अमान्य डिफ़ॉल्ट मुखपृष्ठ!",
     "error.invalid_default_home_page": "अमान्य डिफ़ॉल्ट मुखपृष्ठ!",
     "error.invalid_display_mode": "अमान्य वेब ऐप्लिकेशन प्रदर्शन मोड.",
     "error.invalid_display_mode": "अमान्य वेब ऐप्लिकेशन प्रदर्शन मोड.",
     "error.invalid_entry_direction": "अमान्य प्रवेश दिशा।",
     "error.invalid_entry_direction": "अमान्य प्रवेश दिशा।",
@@ -407,6 +408,7 @@
     "form.submit.saving": "सहेजा जा रहा है...",
     "form.submit.saving": "सहेजा जा रहा है...",
     "form.user.label.admin": "प्रशासक",
     "form.user.label.admin": "प्रशासक",
     "form.user.label.confirmation": "पासवर्ड पुष्टि",
     "form.user.label.confirmation": "पासवर्ड पुष्टि",
+    "form.user.label.current_password": "वर्तमान पासवर्ड",
     "form.user.label.password": "पासवर्ड",
     "form.user.label.password": "पासवर्ड",
     "form.user.label.username": "उपयोगकर्ता नाम",
     "form.user.label.username": "उपयोगकर्ता नाम",
     "menu.about": "के बारे में",
     "menu.about": "के बारे में",

+ 2 - 0
internal/locale/translations/id_ID.json

@@ -125,6 +125,7 @@
     "error.http_too_many_requests": "Terlalu banyak koneksi dari Miniflux yang dibuat ke situs ini. Coba lagi nanti atau ubah konfigurasi aplikasi.",
     "error.http_too_many_requests": "Terlalu banyak koneksi dari Miniflux yang dibuat ke situs ini. Coba lagi nanti atau ubah konfigurasi aplikasi.",
     "error.http_unexpected_status_code": "Situs ini tidak dapat dijangkau saat ini dikarenakan kode status HTTP tak diduga: %d Masalah ini bukan pada sisi Miniflux. Coba lagi nanti.",
     "error.http_unexpected_status_code": "Situs ini tidak dapat dijangkau saat ini dikarenakan kode status HTTP tak diduga: %d Masalah ini bukan pada sisi Miniflux. Coba lagi nanti.",
     "error.invalid_categories_sorting_order": "Urutan penyortiran kategori tidak valid.",
     "error.invalid_categories_sorting_order": "Urutan penyortiran kategori tidak valid.",
+    "error.invalid_current_password": "Kata sandi saat ini salah.",
     "error.invalid_default_home_page": "Beranda baku tidak valid!",
     "error.invalid_default_home_page": "Beranda baku tidak valid!",
     "error.invalid_display_mode": "Mode tampilan aplikasi web tidak valid.",
     "error.invalid_display_mode": "Mode tampilan aplikasi web tidak valid.",
     "error.invalid_entry_direction": "Urutan entri tidak valid.",
     "error.invalid_entry_direction": "Urutan entri tidak valid.",
@@ -404,6 +405,7 @@
     "form.submit.saving": "Menyimpan...",
     "form.submit.saving": "Menyimpan...",
     "form.user.label.admin": "Admin",
     "form.user.label.admin": "Admin",
     "form.user.label.confirmation": "Konfirmasi Kata Sandi",
     "form.user.label.confirmation": "Konfirmasi Kata Sandi",
+    "form.user.label.current_password": "Kata Sandi Saat Ini",
     "form.user.label.password": "Kata Sandi",
     "form.user.label.password": "Kata Sandi",
     "form.user.label.username": "Nama Pengguna",
     "form.user.label.username": "Nama Pengguna",
     "menu.about": "Tentang",
     "menu.about": "Tentang",

+ 2 - 0
internal/locale/translations/it_IT.json

@@ -128,6 +128,7 @@
     "error.http_too_many_requests": "Miniflux ha generato troppe richieste verso questo sito. Riprova più tardi o modifica la configurazione dell'applicazione.",
     "error.http_too_many_requests": "Miniflux ha generato troppe richieste verso questo sito. Riprova più tardi o modifica la configurazione dell'applicazione.",
     "error.http_unexpected_status_code": "Il sito web non è disponibile a causa di un codice di stato HTTP inatteso: %d. Il problema non è lato Miniflux. Riprova più tardi.",
     "error.http_unexpected_status_code": "Il sito web non è disponibile a causa di un codice di stato HTTP inatteso: %d. Il problema non è lato Miniflux. Riprova più tardi.",
     "error.invalid_categories_sorting_order": "L'ordinamento delle categorie non è valido.",
     "error.invalid_categories_sorting_order": "L'ordinamento delle categorie non è valido.",
+    "error.invalid_current_password": "La parola d'accesso attuale non è corretta.",
     "error.invalid_default_home_page": "Pagina iniziale predefinita non valida!",
     "error.invalid_default_home_page": "Pagina iniziale predefinita non valida!",
     "error.invalid_display_mode": "Modalità di visualizzazione web app non valida.",
     "error.invalid_display_mode": "Modalità di visualizzazione web app non valida.",
     "error.invalid_entry_direction": "Ordinamento non valido.",
     "error.invalid_entry_direction": "Ordinamento non valido.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Salvataggio in corso...",
     "form.submit.saving": "Salvataggio in corso...",
     "form.user.label.admin": "Amministratore",
     "form.user.label.admin": "Amministratore",
     "form.user.label.confirmation": "Conferma password",
     "form.user.label.confirmation": "Conferma password",
+    "form.user.label.current_password": "Parola d'accesso attuale",
     "form.user.label.password": "Parola d'accesso",
     "form.user.label.password": "Parola d'accesso",
     "form.user.label.username": "Nome utente",
     "form.user.label.username": "Nome utente",
     "menu.about": "Informazioni",
     "menu.about": "Informazioni",

+ 2 - 0
internal/locale/translations/ja_JP.json

@@ -125,6 +125,7 @@
     "error.http_too_many_requests": "Miniflux がこのウェブサイトに対してリクエストを送りすぎました。しばらく待つか、アプリケーション設定を変更してください。",
     "error.http_too_many_requests": "Miniflux がこのウェブサイトに対してリクエストを送りすぎました。しばらく待つか、アプリケーション設定を変更してください。",
     "error.http_unexpected_status_code": "予期しない HTTP ステータスコード (%d) により現在このウェブサイトは利用できません。問題は Miniflux 側にはありません。しばらくしてから再度お試しください。",
     "error.http_unexpected_status_code": "予期しない HTTP ステータスコード (%d) により現在このウェブサイトは利用できません。問題は Miniflux 側にはありません。しばらくしてから再度お試しください。",
     "error.invalid_categories_sorting_order": "カテゴリの表示順が無効です。",
     "error.invalid_categories_sorting_order": "カテゴリの表示順が無効です。",
+    "error.invalid_current_password": "現在のパスワードが正しくありません。",
     "error.invalid_default_home_page": "デフォルトのトップページが無効です",
     "error.invalid_default_home_page": "デフォルトのトップページが無効です",
     "error.invalid_display_mode": "Web アプリの表示モードが無効です。",
     "error.invalid_display_mode": "Web アプリの表示モードが無効です。",
     "error.invalid_entry_direction": "記事の表示順が無効です。",
     "error.invalid_entry_direction": "記事の表示順が無効です。",
@@ -404,6 +405,7 @@
     "form.submit.saving": "保存中…",
     "form.submit.saving": "保存中…",
     "form.user.label.admin": "管理者",
     "form.user.label.admin": "管理者",
     "form.user.label.confirmation": "パスワード確認",
     "form.user.label.confirmation": "パスワード確認",
+    "form.user.label.current_password": "現在のパスワード",
     "form.user.label.password": "パスワード",
     "form.user.label.password": "パスワード",
     "form.user.label.username": "ユーザー名",
     "form.user.label.username": "ユーザー名",
     "menu.about": "ソフトウェア情報",
     "menu.about": "ソフトウェア情報",

+ 2 - 0
internal/locale/translations/ko_KR.json

@@ -125,6 +125,7 @@
     "error.http_too_many_requests": "Miniflux가 이 웹사이트에 너무 많은 요청을 보냈습니다. 잠시 기다리거나 애플리케이션 설정을 변경해 주세요.",
     "error.http_too_many_requests": "Miniflux가 이 웹사이트에 너무 많은 요청을 보냈습니다. 잠시 기다리거나 애플리케이션 설정을 변경해 주세요.",
     "error.http_unexpected_status_code": "예상치 못한 HTTP 상태 코드(%d)로 인해 현재 이 웹사이트를 사용할 수 없습니다. Miniflux 측의 문제가 아닙니다. 잠시 후 다시 시도해 주세요.",
     "error.http_unexpected_status_code": "예상치 못한 HTTP 상태 코드(%d)로 인해 현재 이 웹사이트를 사용할 수 없습니다. Miniflux 측의 문제가 아닙니다. 잠시 후 다시 시도해 주세요.",
     "error.invalid_categories_sorting_order": "카테고리 표시 순서가 유효하지 않습니다.",
     "error.invalid_categories_sorting_order": "카테고리 표시 순서가 유효하지 않습니다.",
+    "error.invalid_current_password": "현재 비밀번호가 올바르지 않습니다.",
     "error.invalid_default_home_page": "기본 시작 페이지가 유효하지 않습니다",
     "error.invalid_default_home_page": "기본 시작 페이지가 유효하지 않습니다",
     "error.invalid_display_mode": "웹 앱 표시 모드가 유효하지 않습니다.",
     "error.invalid_display_mode": "웹 앱 표시 모드가 유효하지 않습니다.",
     "error.invalid_entry_direction": "게시물 표시 방향이 유효하지 않습니다.",
     "error.invalid_entry_direction": "게시물 표시 방향이 유효하지 않습니다.",
@@ -404,6 +405,7 @@
     "form.submit.saving": "저장 중…",
     "form.submit.saving": "저장 중…",
     "form.user.label.admin": "관리자",
     "form.user.label.admin": "관리자",
     "form.user.label.confirmation": "비밀번호 확인",
     "form.user.label.confirmation": "비밀번호 확인",
+    "form.user.label.current_password": "현재 비밀번호",
     "form.user.label.password": "비밀번호",
     "form.user.label.password": "비밀번호",
     "form.user.label.username": "사용자명",
     "form.user.label.username": "사용자명",
     "menu.about": "소프트웨어 정보",
     "menu.about": "소프트웨어 정보",

+ 2 - 0
internal/locale/translations/nan_Latn_pehoeji.json

@@ -125,6 +125,7 @@
     "error.http_too_many_requests": "Miniflux tùi chit ê bāng-chām ê chhéng-kiû siuⁿ kè chōe, chhiáⁿ têng chhì-khòaⁿ-māi ah-sī tiâu-chéng thêng-sek siat-tēng.",
     "error.http_too_many_requests": "Miniflux tùi chit ê bāng-chām ê chhéng-kiû siuⁿ kè chōe, chhiáⁿ têng chhì-khòaⁿ-māi ah-sī tiâu-chéng thêng-sek siat-tēng.",
     "error.http_unexpected_status_code": "Chit ê bāng-chām chòe liáu chi̍t ê liāu-bōe-tio̍h ê HTTP chōng-thài bé: %d, chhiáⁿ tán--chi̍t-ē chiah koh chhì-khòaⁿ-māi.",
     "error.http_unexpected_status_code": "Chit ê bāng-chām chòe liáu chi̍t ê liāu-bōe-tio̍h ê HTTP chōng-thài bé: %d, chhiáⁿ tán--chi̍t-ē chiah koh chhì-khòaⁿ-māi.",
     "error.invalid_categories_sorting_order": "Lūi-pia̍t ê chōe pái bô-hāu, chhiáⁿ tán-hāu %d hun-cheng āu koh chhì-khòaⁿ-māi.",
     "error.invalid_categories_sorting_order": "Lūi-pia̍t ê chōe pái bô-hāu, chhiáⁿ tán-hāu %d hun-cheng āu koh chhì-khòaⁿ-māi.",
+    "error.invalid_current_password": "Hiān-chāi ê bi̍t-bé m̄ tio̍h.",
     "error.invalid_default_home_page": "Ū-siat chú-ia̍h ū būn-tôe!",
     "error.invalid_default_home_page": "Ū-siat chú-ia̍h ū būn-tôe!",
     "error.invalid_display_mode": "Ū būn-tôe ê su-li̍p bô͘-sek.",
     "error.invalid_display_mode": "Ū būn-tôe ê su-li̍p bô͘-sek.",
     "error.invalid_entry_direction": "Ū būn-tôe ê su-li̍p hong-hiòng.",
     "error.invalid_entry_direction": "Ū būn-tôe ê su-li̍p hong-hiòng.",
@@ -404,6 +405,7 @@
     "form.submit.saving": "Tng leh pó-chûn…",
     "form.submit.saving": "Tng leh pó-chûn…",
     "form.user.label.admin": "Koán-lí-lâng",
     "form.user.label.admin": "Koán-lí-lâng",
     "form.user.label.confirmation": "Koh su-li̍p chi̍t pái bi̍t-bé",
     "form.user.label.confirmation": "Koh su-li̍p chi̍t pái bi̍t-bé",
+    "form.user.label.current_password": "Hiān-chāi ê bi̍t-bé",
     "form.user.label.password": "Bi̍t-bé",
     "form.user.label.password": "Bi̍t-bé",
     "form.user.label.username": "Kháu-chō miâ",
     "form.user.label.username": "Kháu-chō miâ",
     "menu.about": "Iú-koan",
     "menu.about": "Iú-koan",

+ 2 - 0
internal/locale/translations/nl_NL.json

@@ -128,6 +128,7 @@
     "error.http_too_many_requests": "Miniflux heeft te veel aanvragen gegenereerd voor deze website. Probeer het later nog eens of wijzig de applicatieconfiguratie.",
     "error.http_too_many_requests": "Miniflux heeft te veel aanvragen gegenereerd voor deze website. Probeer het later nog eens of wijzig de applicatieconfiguratie.",
     "error.http_unexpected_status_code": "De website is momenteel niet beschikbaar vanwege een onverwachte HTTP-statuscode: %d. De oorzaak hiervan ligt niet bij Miniflux. Probeer het later nogmaals aub.",
     "error.http_unexpected_status_code": "De website is momenteel niet beschikbaar vanwege een onverwachte HTTP-statuscode: %d. De oorzaak hiervan ligt niet bij Miniflux. Probeer het later nogmaals aub.",
     "error.invalid_categories_sorting_order": "Ongeldige volgorde van categorieën.",
     "error.invalid_categories_sorting_order": "Ongeldige volgorde van categorieën.",
+    "error.invalid_current_password": "Het huidige wachtwoord is onjuist.",
     "error.invalid_default_home_page": "Ongeldige startpagina!",
     "error.invalid_default_home_page": "Ongeldige startpagina!",
     "error.invalid_display_mode": "Ongeldige weergavemodus voor de webapp.",
     "error.invalid_display_mode": "Ongeldige weergavemodus voor de webapp.",
     "error.invalid_entry_direction": "Ongeldige sorteervolgorde.",
     "error.invalid_entry_direction": "Ongeldige sorteervolgorde.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Opslaan...",
     "form.submit.saving": "Opslaan...",
     "form.user.label.admin": "Beheerder",
     "form.user.label.admin": "Beheerder",
     "form.user.label.confirmation": "Bevestig wachtwoord",
     "form.user.label.confirmation": "Bevestig wachtwoord",
+    "form.user.label.current_password": "Huidig wachtwoord",
     "form.user.label.password": "Wachtwoord",
     "form.user.label.password": "Wachtwoord",
     "form.user.label.username": "Gebruikersnaam",
     "form.user.label.username": "Gebruikersnaam",
     "menu.about": "Over",
     "menu.about": "Over",

+ 2 - 0
internal/locale/translations/pl_PL.json

@@ -131,6 +131,7 @@
     "error.http_too_many_requests": "Miniflux wygenerował zbyt wiele żądań do tej witryny. Spróbuj ponownie później lub zmień konfigurację aplikacji.",
     "error.http_too_many_requests": "Miniflux wygenerował zbyt wiele żądań do tej witryny. Spróbuj ponownie później lub zmień konfigurację aplikacji.",
     "error.http_unexpected_status_code": "Strona jest w tej chwili niedostępna z powodu nieoczekiwanego kodu stanu HTTP: %d. Problem nie leży po stronie Miniflux. Spróbuj ponownie później.",
     "error.http_unexpected_status_code": "Strona jest w tej chwili niedostępna z powodu nieoczekiwanego kodu stanu HTTP: %d. Problem nie leży po stronie Miniflux. Spróbuj ponownie później.",
     "error.invalid_categories_sorting_order": "Nieprawidłowa kolejność sortowania kategorii.",
     "error.invalid_categories_sorting_order": "Nieprawidłowa kolejność sortowania kategorii.",
+    "error.invalid_current_password": "Obecne hasło jest nieprawidłowe.",
     "error.invalid_default_home_page": "Nieprawidłowa domyślna strona główna!",
     "error.invalid_default_home_page": "Nieprawidłowa domyślna strona główna!",
     "error.invalid_display_mode": "Nieprawidłowy tryb wyświetlania aplikacji sieciowej.",
     "error.invalid_display_mode": "Nieprawidłowy tryb wyświetlania aplikacji sieciowej.",
     "error.invalid_entry_direction": "Nieprawidłowa kolejność sortowania.",
     "error.invalid_entry_direction": "Nieprawidłowa kolejność sortowania.",
@@ -410,6 +411,7 @@
     "form.submit.saving": "Zapisywanie…",
     "form.submit.saving": "Zapisywanie…",
     "form.user.label.admin": "Administrator",
     "form.user.label.admin": "Administrator",
     "form.user.label.confirmation": "Potwierdzenie hasła",
     "form.user.label.confirmation": "Potwierdzenie hasła",
+    "form.user.label.current_password": "Obecne hasło",
     "form.user.label.password": "Hasło",
     "form.user.label.password": "Hasło",
     "form.user.label.username": "Nazwa użytkownika",
     "form.user.label.username": "Nazwa użytkownika",
     "menu.about": "O czytniku",
     "menu.about": "O czytniku",

+ 2 - 0
internal/locale/translations/pt_BR.json

@@ -128,6 +128,7 @@
     "error.http_too_many_requests": "O Miniflux gerou muitas solicitações para este site. Por favor, tente novamente mais tarde ou altere a configuração do aplicativo.",
     "error.http_too_many_requests": "O Miniflux gerou muitas solicitações para este site. Por favor, tente novamente mais tarde ou altere a configuração do aplicativo.",
     "error.http_unexpected_status_code": "O site não está disponível no momento devido a um código de status HTTP inesperado: %d. O problema não está no Miniflux. Por favor, tente novamente mais tarde.",
     "error.http_unexpected_status_code": "O site não está disponível no momento devido a um código de status HTTP inesperado: %d. O problema não está no Miniflux. Por favor, tente novamente mais tarde.",
     "error.invalid_categories_sorting_order": "A ordem de classificação das categorias não é válida.",
     "error.invalid_categories_sorting_order": "A ordem de classificação das categorias não é válida.",
+    "error.invalid_current_password": "A senha atual está incorreta.",
     "error.invalid_default_home_page": "Página inicial por defeito inválida!",
     "error.invalid_default_home_page": "Página inicial por defeito inválida!",
     "error.invalid_display_mode": "Modo de exibição de aplicativo inválido da web.",
     "error.invalid_display_mode": "Modo de exibição de aplicativo inválido da web.",
     "error.invalid_entry_direction": "Direção de entrada inválida.",
     "error.invalid_entry_direction": "Direção de entrada inválida.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Salvando...",
     "form.submit.saving": "Salvando...",
     "form.user.label.admin": "Administrador",
     "form.user.label.admin": "Administrador",
     "form.user.label.confirmation": "Confirmação de senha",
     "form.user.label.confirmation": "Confirmação de senha",
+    "form.user.label.current_password": "Senha atual",
     "form.user.label.password": "Senha",
     "form.user.label.password": "Senha",
     "form.user.label.username": "Nome de usuário",
     "form.user.label.username": "Nome de usuário",
     "menu.about": "Sobre",
     "menu.about": "Sobre",

+ 2 - 0
internal/locale/translations/ro_RO.json

@@ -131,6 +131,7 @@
     "error.http_too_many_requests": "Miniflux a generat prea multe solicitări pe acest site web. Vă rog, încercați mai tîrziu sau modificați configurațiile aplicației.",
     "error.http_too_many_requests": "Miniflux a generat prea multe solicitări pe acest site web. Vă rog, încercați mai tîrziu sau modificați configurațiile aplicației.",
     "error.http_unexpected_status_code": "Acest site web nu este disponibil momentan din cauza unei erori HTTP: %d. Problema nu este de la Miniflux. Vă rugăm să reîncercați mai târziu.",
     "error.http_unexpected_status_code": "Acest site web nu este disponibil momentan din cauza unei erori HTTP: %d. Problema nu este de la Miniflux. Vă rugăm să reîncercați mai târziu.",
     "error.invalid_categories_sorting_order": "Ordinea de sortare a categoriilor nu este validă.",
     "error.invalid_categories_sorting_order": "Ordinea de sortare a categoriilor nu este validă.",
+    "error.invalid_current_password": "Parola curentă este incorectă.",
     "error.invalid_default_home_page": "Pagină de start invalidă!",
     "error.invalid_default_home_page": "Pagină de start invalidă!",
     "error.invalid_display_mode": "Mod invalid de afișare în aplicația web.",
     "error.invalid_display_mode": "Mod invalid de afișare în aplicația web.",
     "error.invalid_entry_direction": "Direcție invalidă ăn intrare.",
     "error.invalid_entry_direction": "Direcție invalidă ăn intrare.",
@@ -410,6 +411,7 @@
     "form.submit.saving": "Salvez…",
     "form.submit.saving": "Salvez…",
     "form.user.label.admin": "Administrator",
     "form.user.label.admin": "Administrator",
     "form.user.label.confirmation": "Confirmare Parolă",
     "form.user.label.confirmation": "Confirmare Parolă",
+    "form.user.label.current_password": "Parola curentă",
     "form.user.label.password": "Parolă",
     "form.user.label.password": "Parolă",
     "form.user.label.username": "Nume utilizator",
     "form.user.label.username": "Nume utilizator",
     "menu.about": "Despre",
     "menu.about": "Despre",

+ 2 - 0
internal/locale/translations/ru_RU.json

@@ -131,6 +131,7 @@
     "error.http_too_many_requests": "Miniflux отправил слишком много запросов к этому сайту. Пожалуйста, попробуйте позже или измените настройки приложения.",
     "error.http_too_many_requests": "Miniflux отправил слишком много запросов к этому сайту. Пожалуйста, попробуйте позже или измените настройки приложения.",
     "error.http_unexpected_status_code": "В данный момент сайт недоступен из-за непредвиденного кода HTTP-ответа: %d. Проблема не связана с Miniflux. Пожалуйста, попробуйте позже.",
     "error.http_unexpected_status_code": "В данный момент сайт недоступен из-за непредвиденного кода HTTP-ответа: %d. Проблема не связана с Miniflux. Пожалуйста, попробуйте позже.",
     "error.invalid_categories_sorting_order": "Недопустимый порядок сортировки категорий.",
     "error.invalid_categories_sorting_order": "Недопустимый порядок сортировки категорий.",
+    "error.invalid_current_password": "Текущий пароль неверен.",
     "error.invalid_default_home_page": "Недопустимая домашняя страница по умолчанию!",
     "error.invalid_default_home_page": "Недопустимая домашняя страница по умолчанию!",
     "error.invalid_display_mode": "Недопустимый режим отображения веб-приложения.",
     "error.invalid_display_mode": "Недопустимый режим отображения веб-приложения.",
     "error.invalid_entry_direction": "Недопустимая сортировка записей.",
     "error.invalid_entry_direction": "Недопустимая сортировка записей.",
@@ -410,6 +411,7 @@
     "form.submit.saving": "Сохранение…",
     "form.submit.saving": "Сохранение…",
     "form.user.label.admin": "Администратор",
     "form.user.label.admin": "Администратор",
     "form.user.label.confirmation": "Подтверждение пароля",
     "form.user.label.confirmation": "Подтверждение пароля",
+    "form.user.label.current_password": "Текущий пароль",
     "form.user.label.password": "Пароль",
     "form.user.label.password": "Пароль",
     "form.user.label.username": "Имя пользователя",
     "form.user.label.username": "Имя пользователя",
     "menu.about": "О приложении",
     "menu.about": "О приложении",

+ 2 - 0
internal/locale/translations/tr_TR.json

@@ -128,6 +128,7 @@
     "error.http_too_many_requests": "Miniflux bu web sitesine çok fazla istek oluşturdu. Lütfen daha sonra tekrar deneyin veya uygulama yapılandırmasını değiştirin.",
     "error.http_too_many_requests": "Miniflux bu web sitesine çok fazla istek oluşturdu. Lütfen daha sonra tekrar deneyin veya uygulama yapılandırmasını değiştirin.",
     "error.http_unexpected_status_code": "Beklenmeyen bir HTTP durum kodu nedeniyle bu websitesi şu anda kullanılamıyor: %d. Sorun Miniflux tarafında değil. Lütfen daha sonra tekrar deneyiniz.",
     "error.http_unexpected_status_code": "Beklenmeyen bir HTTP durum kodu nedeniyle bu websitesi şu anda kullanılamıyor: %d. Sorun Miniflux tarafında değil. Lütfen daha sonra tekrar deneyiniz.",
     "error.invalid_categories_sorting_order": "Geçersiz kategori sıralama düzeni.",
     "error.invalid_categories_sorting_order": "Geçersiz kategori sıralama düzeni.",
+    "error.invalid_current_password": "Mevcut parola yanlış.",
     "error.invalid_default_home_page": "Geçersiz varsayılan ana sayfa!",
     "error.invalid_default_home_page": "Geçersiz varsayılan ana sayfa!",
     "error.invalid_display_mode": "Geçersiz web uygulaması görüntüleme modu.",
     "error.invalid_display_mode": "Geçersiz web uygulaması görüntüleme modu.",
     "error.invalid_entry_direction": "Geçersiz makele sıralaması.",
     "error.invalid_entry_direction": "Geçersiz makele sıralaması.",
@@ -407,6 +408,7 @@
     "form.submit.saving": "Kaydediliyor...",
     "form.submit.saving": "Kaydediliyor...",
     "form.user.label.admin": "Yönetici",
     "form.user.label.admin": "Yönetici",
     "form.user.label.confirmation": "Parola Doğrulama",
     "form.user.label.confirmation": "Parola Doğrulama",
+    "form.user.label.current_password": "Mevcut Parola",
     "form.user.label.password": "Parola",
     "form.user.label.password": "Parola",
     "form.user.label.username": "Kullanıcı Adı",
     "form.user.label.username": "Kullanıcı Adı",
     "menu.about": "Hakkında",
     "menu.about": "Hakkında",

+ 2 - 0
internal/locale/translations/uk_UA.json

@@ -131,6 +131,7 @@
     "error.http_too_many_requests": "Miniflux згенерував надто багато запитів до цього сайту. Будь ласка, спробуйте пізніше або змініть налаштування програми.",
     "error.http_too_many_requests": "Miniflux згенерував надто багато запитів до цього сайту. Будь ласка, спробуйте пізніше або змініть налаштування програми.",
     "error.http_unexpected_status_code": "Сайт наразі недоступний через неочікуваний HTTP-код: %d. Проблема не на стороні Miniflux. Будь ласка, спробуйте пізніше.",
     "error.http_unexpected_status_code": "Сайт наразі недоступний через неочікуваний HTTP-код: %d. Проблема не на стороні Miniflux. Будь ласка, спробуйте пізніше.",
     "error.invalid_categories_sorting_order": "Недійсний порядок сортування категорій.",
     "error.invalid_categories_sorting_order": "Недійсний порядок сортування категорій.",
+    "error.invalid_current_password": "Поточний пароль неправильний.",
     "error.invalid_default_home_page": "Недійсна домашня сторінка за замовчуванням!",
     "error.invalid_default_home_page": "Недійсна домашня сторінка за замовчуванням!",
     "error.invalid_display_mode": "Недійсний режим відображення.",
     "error.invalid_display_mode": "Недійсний режим відображення.",
     "error.invalid_entry_direction": "Недійсний напрямок запису.",
     "error.invalid_entry_direction": "Недійсний напрямок запису.",
@@ -410,6 +411,7 @@
     "form.submit.saving": "Зберігаю...",
     "form.submit.saving": "Зберігаю...",
     "form.user.label.admin": "Адміністратор",
     "form.user.label.admin": "Адміністратор",
     "form.user.label.confirmation": "Підтверждення паролю",
     "form.user.label.confirmation": "Підтверждення паролю",
+    "form.user.label.current_password": "Поточний пароль",
     "form.user.label.password": "Пароль",
     "form.user.label.password": "Пароль",
     "form.user.label.username": "Ім’я користувача",
     "form.user.label.username": "Ім’я користувача",
     "menu.about": "Про додаток",
     "menu.about": "Про додаток",

+ 2 - 0
internal/locale/translations/zh_CN.json

@@ -125,6 +125,7 @@
     "error.http_too_many_requests": "Miniflux 向此网站生成了过多请求。请稍后重试或更改应用程序配置。",
     "error.http_too_many_requests": "Miniflux 向此网站生成了过多请求。请稍后重试或更改应用程序配置。",
     "error.http_unexpected_status_code": "由于意外的 HTTP 状态码 %d,网站暂不可用。这不是 Miniflux 的问题,请稍后重试。",
     "error.http_unexpected_status_code": "由于意外的 HTTP 状态码 %d,网站暂不可用。这不是 Miniflux 的问题,请稍后重试。",
     "error.invalid_categories_sorting_order": "无效的分类排序顺序。",
     "error.invalid_categories_sorting_order": "无效的分类排序顺序。",
+    "error.invalid_current_password": "当前密码不正确。",
     "error.invalid_default_home_page": "无效的默认主页!",
     "error.invalid_default_home_page": "无效的默认主页!",
     "error.invalid_display_mode": "无效的网页应用显示模式。",
     "error.invalid_display_mode": "无效的网页应用显示模式。",
     "error.invalid_entry_direction": "无效的条目方向。",
     "error.invalid_entry_direction": "无效的条目方向。",
@@ -404,6 +405,7 @@
     "form.submit.saving": "保存中…",
     "form.submit.saving": "保存中…",
     "form.user.label.admin": "管理员",
     "form.user.label.admin": "管理员",
     "form.user.label.confirmation": "确认密码",
     "form.user.label.confirmation": "确认密码",
+    "form.user.label.current_password": "当前密码",
     "form.user.label.password": "密码",
     "form.user.label.password": "密码",
     "form.user.label.username": "用户名",
     "form.user.label.username": "用户名",
     "menu.about": "关于",
     "menu.about": "关于",

+ 2 - 0
internal/locale/translations/zh_TW.json

@@ -125,6 +125,7 @@
     "error.http_too_many_requests": "Miniflux 對此網站的請求過多,請稍後重試或調整程式設定。",
     "error.http_too_many_requests": "Miniflux 對此網站的請求過多,請稍後重試或調整程式設定。",
     "error.http_unexpected_status_code": "此網站回應了意外的 HTTP 狀態碼:%d,請稍後重試。",
     "error.http_unexpected_status_code": "此網站回應了意外的 HTTP 狀態碼:%d,請稍後重試。",
     "error.invalid_categories_sorting_order": "無效的分類排序",
     "error.invalid_categories_sorting_order": "無效的分類排序",
+    "error.invalid_current_password": "目前密碼不正確。",
     "error.invalid_default_home_page": "預設主頁無效!",
     "error.invalid_default_home_page": "預設主頁無效!",
     "error.invalid_display_mode": "無效的顯示模式。",
     "error.invalid_display_mode": "無效的顯示模式。",
     "error.invalid_entry_direction": "無效的輸入方向。",
     "error.invalid_entry_direction": "無效的輸入方向。",
@@ -404,6 +405,7 @@
     "form.submit.saving": "儲存中…",
     "form.submit.saving": "儲存中…",
     "form.user.label.admin": "管理員",
     "form.user.label.admin": "管理員",
     "form.user.label.confirmation": "再次輸入密碼",
     "form.user.label.confirmation": "再次輸入密碼",
+    "form.user.label.current_password": "目前密碼",
     "form.user.label.password": "密碼",
     "form.user.label.password": "密碼",
     "form.user.label.username": "使用者名稱",
     "form.user.label.username": "使用者名稱",
     "menu.about": "關於",
     "menu.about": "關於",

+ 5 - 0
internal/template/templates/views/authentication.html

@@ -22,6 +22,11 @@
         <label for="form-username">{{ t "form.user.label.username" }}</label>
         <label for="form-username">{{ t "form.user.label.username" }}</label>
         <input type="text" name="username" id="form-username" value="{{ .form.Username }}" autocomplete="username" required>
         <input type="text" name="username" id="form-username" value="{{ .form.Username }}" autocomplete="username" required>
 
 
+        {{ if .hasPassword }}
+        <label for="form-current-password">{{ t "form.user.label.current_password" }}</label>
+        <input type="password" name="current_password" id="form-current-password" autocomplete="current-password">
+        {{ end }}
+
         <label for="form-password">{{ t "form.user.label.password" }}</label>
         <label for="form-password">{{ t "form.user.label.password" }}</label>
         <input type="password" name="password" id="form-password" value="{{ .form.Password }}" autocomplete="new-password">
         <input type="password" name="password" id="form-password" value="{{ .form.Password }}" autocomplete="new-password">
 
 

+ 7 - 0
internal/ui/authentication_show.go

@@ -25,8 +25,15 @@ func (h *handler) showAuthenticationPage(w http.ResponseWriter, r *http.Request)
 		return
 		return
 	}
 	}
 
 
+	hasPassword, err := h.store.HasPassword(user.ID)
+	if err != nil {
+		response.HTMLServerError(w, r, err)
+		return
+	}
+
 	view := view.New(h.tpl, r)
 	view := view.New(h.tpl, r)
 	view.Set("form", form.AuthSettingsForm{Username: user.Username})
 	view.Set("form", form.AuthSettingsForm{Username: user.Username})
+	view.Set("hasPassword", hasPassword)
 	view.Set("menu", "settings")
 	view.Set("menu", "settings")
 	view.Set("user", user)
 	view.Set("user", user)
 	navMetadata, _ := h.store.GetNavMetadata(user.ID)
 	navMetadata, _ := h.store.GetNavMetadata(user.ID)

+ 24 - 0
internal/ui/authentication_update.go

@@ -4,6 +4,7 @@
 package ui // import "miniflux.app/v2/internal/ui"
 package ui // import "miniflux.app/v2/internal/ui"
 
 
 import (
 import (
+	"log/slog"
 	"net/http"
 	"net/http"
 
 
 	"miniflux.app/v2/internal/config"
 	"miniflux.app/v2/internal/config"
@@ -34,10 +35,17 @@ func (h *handler) updateAuthentication(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 
 
+	hasPassword, err := h.store.HasPassword(user.ID)
+	if err != nil {
+		response.HTMLServerError(w, r, err)
+		return
+	}
+
 	authSettingsForm := form.NewAuthSettingsForm(r)
 	authSettingsForm := form.NewAuthSettingsForm(r)
 
 
 	view := view.New(h.tpl, r)
 	view := view.New(h.tpl, r)
 	view.Set("form", authSettingsForm)
 	view.Set("form", authSettingsForm)
+	view.Set("hasPassword", hasPassword)
 	view.Set("menu", "settings")
 	view.Set("menu", "settings")
 	view.Set("user", user)
 	view.Set("user", user)
 	navMetadata, _ := h.store.GetNavMetadata(user.ID)
 	navMetadata, _ := h.store.GetNavMetadata(user.ID)
@@ -52,6 +60,22 @@ func (h *handler) updateAuthentication(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 
 
+	// Users created through OAuth2 have no password yet, so there is nothing to confirm.
+	if authSettingsForm.Password != "" && hasPassword {
+		if err := h.store.CheckPassword(user.Username, authSettingsForm.CurrentPassword); err != nil {
+			slog.Warn("Incorrect current password on password change",
+				slog.Bool("authentication_failed", true),
+				slog.String("client_ip", request.ClientIP(r)),
+				slog.String("user_agent", r.UserAgent()),
+				slog.String("username", user.Username),
+				slog.Any("error", err),
+			)
+			view.Set("errorMessage", locale.NewLocalizedError("error.invalid_current_password").Translate(user.Language))
+			response.HTML(w, r, view.Render("authentication"))
+			return
+		}
+	}
+
 	userModificationRequest := &model.UserModificationRequest{
 	userModificationRequest := &model.UserModificationRequest{
 		Username: model.OptionalString(authSettingsForm.Username),
 		Username: model.OptionalString(authSettingsForm.Username),
 		Password: model.OptionalString(authSettingsForm.Password),
 		Password: model.OptionalString(authSettingsForm.Password),

+ 8 - 6
internal/ui/form/auth_settings.go

@@ -12,9 +12,10 @@ import (
 
 
 // AuthSettingsForm represents the authentication settings form.
 // AuthSettingsForm represents the authentication settings form.
 type AuthSettingsForm struct {
 type AuthSettingsForm struct {
-	Username     string
-	Password     string
-	Confirmation string
+	Username        string
+	CurrentPassword string
+	Password        string
+	Confirmation    string
 }
 }
 
 
 // Merge updates the fields of the given user.
 // Merge updates the fields of the given user.
@@ -51,8 +52,9 @@ func (a *AuthSettingsForm) Validate() *locale.LocalizedError {
 // NewAuthSettingsForm returns a new AuthSettingsForm.
 // NewAuthSettingsForm returns a new AuthSettingsForm.
 func NewAuthSettingsForm(r *http.Request) *AuthSettingsForm {
 func NewAuthSettingsForm(r *http.Request) *AuthSettingsForm {
 	return &AuthSettingsForm{
 	return &AuthSettingsForm{
-		Username:     r.FormValue("username"),
-		Password:     r.FormValue("password"),
-		Confirmation: r.FormValue("confirmation"),
+		Username:        r.FormValue("username"),
+		CurrentPassword: r.FormValue("current_password"),
+		Password:        r.FormValue("password"),
+		Confirmation:    r.FormValue("confirmation"),
 	}
 	}
 }
 }

+ 21 - 0
internal/ui/form/auth_settings_test.go

@@ -4,6 +4,10 @@
 package form // import "miniflux.app/v2/internal/ui/form"
 package form // import "miniflux.app/v2/internal/ui/form"
 
 
 import (
 import (
+	"net/http"
+	"net/http/httptest"
+	"net/url"
+	"strings"
 	"testing"
 	"testing"
 
 
 	"miniflux.app/v2/internal/model"
 	"miniflux.app/v2/internal/model"
@@ -73,3 +77,20 @@ func TestAuthSettingsMergeKeepsPasswordWhenEmpty(t *testing.T) {
 		t.Errorf("Expected password to be unchanged, got %q", user.Password)
 		t.Errorf("Expected password to be unchanged, got %q", user.Password)
 	}
 	}
 }
 }
+
+func TestNewAuthSettingsFormReadsCurrentPassword(t *testing.T) {
+	values := url.Values{
+		"username":         {"user"},
+		"current_password": {"old-secret"},
+		"password":         {"new-secret"},
+		"confirmation":     {"new-secret"},
+	}
+	request := httptest.NewRequest(http.MethodPost, "/authentication", strings.NewReader(values.Encode()))
+	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+
+	form := NewAuthSettingsForm(request)
+
+	if form.CurrentPassword != "old-secret" {
+		t.Errorf("Expected current password to be read from the request, got %q", form.CurrentPassword)
+	}
+}