diff --git a/assets/locales/de/default.mo b/assets/locales/de/default.mo index dbe149848..0051148cc 100644 Binary files a/assets/locales/de/default.mo and b/assets/locales/de/default.mo differ diff --git a/assets/locales/de/default.po b/assets/locales/de/default.po index 5fee9b1ce..c542a2fbd 100644 --- a/assets/locales/de/default.po +++ b/assets/locales/de/default.po @@ -2,265 +2,273 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-07-14 19:44+0000\n" -"PO-Revision-Date: 2020-09-04 13:43+0200\n" +"POT-Creation-Date: 2020-09-21 07:26+0000\n" +"PO-Revision-Date: 2020-09-21 09:29+0200\n" "Last-Translator: \n" "Language-Team: \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.3.1\n" +"X-Generator: Poedit 2.4.1\n" "X-Poedit-Basepath: .\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: messages.go:69 +#: messages.go:71 msgid "Unexpected error, please try again" msgstr "Unerwarteter Fehler, bitte erneut versuchen" -#: messages.go:70 +#: messages.go:72 msgid "Invalid request" msgstr "Ungültige Anfrage" -#: messages.go:71 +#: messages.go:73 msgid "Changes could not be saved" msgstr "Fehler beim Speichern der Daten" -#: messages.go:72 +#: messages.go:74 msgid "Could not be deleted" msgstr "Konnte nicht gelöscht werden" -#: messages.go:73 +#: messages.go:75 #, c-format msgid "%s already exists" msgstr "%s existiert bereits" -#: messages.go:74 messages.go:77 +#: messages.go:76 messages.go:79 msgid "Not found on server, deleted?" msgstr "Nicht auf Server gefunden, gelöscht?" -#: messages.go:75 +#: messages.go:77 msgid "File not found" msgstr "Datei konnte nicht gefunden werden" -#: messages.go:76 +#: messages.go:78 msgid "Selection not found" msgstr "Auswahl nicht gefunden" -#: messages.go:78 +#: messages.go:80 msgid "Account not found" msgstr "Unbekannter Account" -#: messages.go:79 +#: messages.go:81 msgid "User not found" msgstr "Nutzer nicht gefunden" -#: messages.go:80 +#: messages.go:82 msgid "Label not found" msgstr "Kategorie nicht gefunden" -#: messages.go:81 +#: messages.go:83 msgid "Album not found" msgstr "Album nicht gefunden" -#: messages.go:82 +#: messages.go:84 msgid "Not available in public mode" msgstr "Im öffentlichen Modus nicht verfügbar" -#: messages.go:83 +#: messages.go:85 msgid "not available in read-only mode" msgstr "Funktion im ‘read-only’ Modus nicht verfügbar" -#: messages.go:84 +#: messages.go:86 msgid "Please log in and try again" msgstr "Anmeldung erforderlich" -#: messages.go:85 +#: messages.go:87 msgid "Upload might be offensive" msgstr "Inhalt könnte anstößig sein und wurde abgelehnt" -#: messages.go:86 +#: messages.go:88 msgid "No items selected" msgstr "Nichts ausgewählt" -#: messages.go:87 +#: messages.go:89 msgid "Failed creating file, please check permissions" msgstr "Datei konnte nicht angelegt werden" -#: messages.go:88 +#: messages.go:90 msgid "Failed creating folder, please check permissions" msgstr "Verzeichnis konnte nicht angelegt werden" -#: messages.go:89 +#: messages.go:91 msgid "Could not connect, please try again" msgstr "Verbindung fehlgeschlagen" -#: messages.go:90 +#: messages.go:92 msgid "Invalid password, please try again" msgstr "Ungültiges Passwort" -#: messages.go:91 +#: messages.go:93 msgid "Feature disabled" msgstr "Funktion deaktiviert" -#: messages.go:92 +#: messages.go:94 msgid "No labels selected" msgstr "Keine Kategorien ausgewählt" -#: messages.go:93 +#: messages.go:95 msgid "No albums selected" msgstr "Keine Alben ausgewählt" -#: messages.go:94 +#: messages.go:96 msgid "No files available for download" msgstr "Nicht zum Download verfügbar" -#: messages.go:95 +#: messages.go:97 msgid "Failed to create zip file" msgstr "Zip-Datei konnte nicht erstellt werden" #: messages.go:98 +msgid "Invalid credentials" +msgstr "Ungültige Zugangsdaten" + +#: messages.go:99 +msgid "Invalid link" +msgstr "Ungültiger Link" + +#: messages.go:102 msgid "Changes successfully saved" msgstr "Änderungen erfolgreich gespeichert" -#: messages.go:99 +#: messages.go:103 msgid "Album created" msgstr "Album erstellt" -#: messages.go:100 +#: messages.go:104 msgid "Album saved" msgstr "Album gespeichert" -#: messages.go:101 +#: messages.go:105 #, c-format msgid "Album %s deleted" msgstr "Album %s gelöscht" -#: messages.go:102 +#: messages.go:106 msgid "Album contents cloned" msgstr "Album-Einträge kopiert" -#: messages.go:103 +#: messages.go:107 msgid "File removed from stack" msgstr "Datei aus Stapel entfernt" -#: messages.go:104 +#: messages.go:108 #, c-format msgid "Selection added to %s" msgstr "Auswahl zu %s hinzugefügt" -#: messages.go:105 +#: messages.go:109 #, c-format msgid "One entry added to %s" msgstr "Ein Eintrag zu %s hinzugefügt" -#: messages.go:106 +#: messages.go:110 #, c-format msgid "%d entries added to %s" msgstr "%d Einträge zu %s hinzugefügt" -#: messages.go:107 +#: messages.go:111 #, c-format msgid "One entry removed from %s" msgstr "Ein Eintrag aus %s entfernt" -#: messages.go:108 +#: messages.go:112 #, c-format msgid "%d entries removed from %s" msgstr "%d Einträge aus %s entfernt" -#: messages.go:109 +#: messages.go:113 msgid "Account created" msgstr "Server-Konfiguration angelegt" -#: messages.go:110 +#: messages.go:114 msgid "Account saved" msgstr "Server-Konfiguration gespeichert" -#: messages.go:111 +#: messages.go:115 msgid "Account deleted" msgstr "Server-Konfiguration gelöscht" -#: messages.go:112 +#: messages.go:116 msgid "Settings saved" msgstr "Einstellungen gespeichert" -#: messages.go:113 +#: messages.go:117 msgid "Password changed" msgstr "Passwort geändert" -#: messages.go:114 +#: messages.go:118 #, c-format msgid "Import completed in %d s" msgstr "Import in %d s abgeschlossen" -#: messages.go:115 +#: messages.go:119 msgid "Import canceled" msgstr "Import abgebrochen" -#: messages.go:116 +#: messages.go:120 #, c-format msgid "Indexing completed in %d s" msgstr "Indizierung in %d s abgeschlossen" -#: messages.go:117 +#: messages.go:121 msgid "Indexing originals..." msgstr "Indiziere Dateien…" -#: messages.go:118 +#: messages.go:122 #, c-format msgid "Indexing files in %s" msgstr "Indiziere Dateien in %s" -#: messages.go:119 +#: messages.go:123 msgid "Indexing canceled" msgstr "Indizierung abgebrochen" -#: messages.go:120 +#: messages.go:124 #, c-format msgid "Removed %d files and %d photos" msgstr "%d Dateien und %d Fotos wurden entfernt" -#: messages.go:121 +#: messages.go:125 #, c-format msgid "Moving files from %s" msgstr "Verschiebe Dateien von %s" -#: messages.go:122 +#: messages.go:126 #, c-format msgid "Copying files from %s" msgstr "Kopiere Dateien von %s" -#: messages.go:123 +#: messages.go:127 msgid "Labels deleted" msgstr "Kategorien gelöscht”" -#: messages.go:124 +#: messages.go:128 msgid "Label saved" msgstr "Kategorie gespeichert" -#: messages.go:125 +#: messages.go:129 #, c-format msgid "%d files uploaded in %d s" msgstr "%d Dateien hochgeladen in %d s" -#: messages.go:126 +#: messages.go:130 msgid "Selection archived" msgstr "Auswahl archiviert" -#: messages.go:127 +#: messages.go:131 msgid "Selection restored" msgstr "Auswahl wiederhergestellt" -#: messages.go:128 +#: messages.go:132 msgid "Selection marked as private" msgstr "Auswahl als privat markiert" -#: messages.go:129 +#: messages.go:133 msgid "Albums deleted" msgstr "Alben gelöscht" -#: messages.go:130 +#: messages.go:134 #, c-format msgid "Zip created in %d s" msgstr "Zip-Datei erstellt in %d s" diff --git a/assets/locales/en/default.mo b/assets/locales/en/default.mo index bcee7d154..379cc3dd3 100644 Binary files a/assets/locales/en/default.mo and b/assets/locales/en/default.mo differ diff --git a/assets/locales/en/default.po b/assets/locales/en/default.po index 9f8a734ef..5cb57a68c 100644 --- a/assets/locales/en/default.po +++ b/assets/locales/en/default.po @@ -7,264 +7,272 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-07-14 19:44+0000\n" -"PO-Revision-Date: 2020-07-14 22:03+0200\n" +"POT-Creation-Date: 2020-09-21 07:26+0000\n" +"PO-Revision-Date: 2020-09-21 09:29+0200\n" +"Last-Translator: \n" "Language-Team: \n" +"Language: en\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.3.1\n" -"Last-Translator: \n" +"X-Generator: Poedit 2.4.1\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"Language: en\n" -#: messages.go:69 +#: messages.go:71 msgid "Unexpected error, please try again" msgstr "Unexpected error, please try again" -#: messages.go:70 +#: messages.go:72 msgid "Invalid request" msgstr "Invalid request" -#: messages.go:71 +#: messages.go:73 msgid "Changes could not be saved" msgstr "Changes could not be saved" -#: messages.go:72 +#: messages.go:74 msgid "Could not be deleted" msgstr "Could not be deleted" -#: messages.go:73 +#: messages.go:75 #, c-format msgid "%s already exists" msgstr "%s already exists" -#: messages.go:74 messages.go:77 +#: messages.go:76 messages.go:79 msgid "Not found on server, deleted?" msgstr "Not found on server, deleted?" -#: messages.go:75 +#: messages.go:77 msgid "File not found" msgstr "File not found" -#: messages.go:76 +#: messages.go:78 msgid "Selection not found" msgstr "Selection not found" -#: messages.go:78 +#: messages.go:80 msgid "Account not found" msgstr "Account not found" -#: messages.go:79 +#: messages.go:81 msgid "User not found" msgstr "User not found" -#: messages.go:80 +#: messages.go:82 msgid "Label not found" msgstr "Label not found" -#: messages.go:81 +#: messages.go:83 msgid "Album not found" msgstr "Album not found" -#: messages.go:82 +#: messages.go:84 msgid "Not available in public mode" msgstr "Not available in public mode" -#: messages.go:83 +#: messages.go:85 msgid "not available in read-only mode" msgstr "not available in read-only mode" -#: messages.go:84 +#: messages.go:86 msgid "Please log in and try again" msgstr "Please log in and try again" -#: messages.go:85 +#: messages.go:87 msgid "Upload might be offensive" msgstr "Upload might be offensive" -#: messages.go:86 +#: messages.go:88 msgid "No items selected" msgstr "No items selected" -#: messages.go:87 +#: messages.go:89 msgid "Failed creating file, please check permissions" msgstr "Failed creating file, please check permissions" -#: messages.go:88 +#: messages.go:90 msgid "Failed creating folder, please check permissions" msgstr "Failed creating folder, please check permissions" -#: messages.go:89 +#: messages.go:91 msgid "Could not connect, please try again" msgstr "Could not connect, please try again" -#: messages.go:90 +#: messages.go:92 msgid "Invalid password, please try again" msgstr "Invalid password, please try again" -#: messages.go:91 +#: messages.go:93 msgid "Feature disabled" msgstr "Feature disabled" -#: messages.go:92 +#: messages.go:94 msgid "No labels selected" msgstr "No labels selected" -#: messages.go:93 +#: messages.go:95 msgid "No albums selected" msgstr "No albums selected" -#: messages.go:94 +#: messages.go:96 msgid "No files available for download" msgstr "No files available for download" -#: messages.go:95 +#: messages.go:97 msgid "Failed to create zip file" msgstr "Failed to create zip file" #: messages.go:98 +msgid "Invalid credentials" +msgstr "Invalid credentials" + +#: messages.go:99 +msgid "Invalid link" +msgstr "Invalid link" + +#: messages.go:102 msgid "Changes successfully saved" msgstr "Changes successfully saved" -#: messages.go:99 +#: messages.go:103 msgid "Album created" msgstr "Album created" -#: messages.go:100 +#: messages.go:104 msgid "Album saved" msgstr "Album saved" -#: messages.go:101 +#: messages.go:105 #, c-format msgid "Album %s deleted" msgstr "Album %s deleted" -#: messages.go:102 +#: messages.go:106 msgid "Album contents cloned" msgstr "Album contents cloned" -#: messages.go:103 +#: messages.go:107 msgid "File removed from stack" msgstr "File removed from stack" -#: messages.go:104 +#: messages.go:108 #, c-format msgid "Selection added to %s" msgstr "Selection added to %s" -#: messages.go:105 +#: messages.go:109 #, c-format msgid "One entry added to %s" msgstr "One entry added to %s" -#: messages.go:106 +#: messages.go:110 #, c-format msgid "%d entries added to %s" msgstr "%d entries added to %s" -#: messages.go:107 +#: messages.go:111 #, c-format msgid "One entry removed from %s" msgstr "One entry removed from %s" -#: messages.go:108 +#: messages.go:112 #, c-format msgid "%d entries removed from %s" msgstr "%d entries removed from %s" -#: messages.go:109 +#: messages.go:113 msgid "Account created" msgstr "Account created" -#: messages.go:110 +#: messages.go:114 msgid "Account saved" msgstr "Account saved" -#: messages.go:111 +#: messages.go:115 msgid "Account deleted" msgstr "Account deleted" -#: messages.go:112 +#: messages.go:116 msgid "Settings saved" msgstr "Settings saved" -#: messages.go:113 +#: messages.go:117 msgid "Password changed" msgstr "Password changed" -#: messages.go:114 +#: messages.go:118 #, c-format msgid "Import completed in %d s" msgstr "Import completed in %d s" -#: messages.go:115 +#: messages.go:119 msgid "Import canceled" msgstr "Import canceled" -#: messages.go:116 +#: messages.go:120 #, c-format msgid "Indexing completed in %d s" msgstr "Indexing completed in %d s" -#: messages.go:117 +#: messages.go:121 msgid "Indexing originals..." msgstr "Indexing originals..." -#: messages.go:118 +#: messages.go:122 #, c-format msgid "Indexing files in %s" msgstr "Indexing files in %s" -#: messages.go:119 +#: messages.go:123 msgid "Indexing canceled" msgstr "Indexing canceled" -#: messages.go:120 +#: messages.go:124 #, c-format msgid "Removed %d files and %d photos" msgstr "Removed %d files and %d photos" -#: messages.go:121 +#: messages.go:125 #, c-format msgid "Moving files from %s" msgstr "Moving files from %s" -#: messages.go:122 +#: messages.go:126 #, c-format msgid "Copying files from %s" msgstr "Copying files from %s" -#: messages.go:123 +#: messages.go:127 msgid "Labels deleted" msgstr "Labels deleted" -#: messages.go:124 +#: messages.go:128 msgid "Label saved" msgstr "Label saved" -#: messages.go:125 +#: messages.go:129 #, c-format msgid "%d files uploaded in %d s" msgstr "%d files uploaded in %d s" -#: messages.go:126 +#: messages.go:130 msgid "Selection archived" msgstr "Selection archived" -#: messages.go:127 +#: messages.go:131 msgid "Selection restored" msgstr "Selection restored" -#: messages.go:128 +#: messages.go:132 msgid "Selection marked as private" msgstr "Selection marked as private" -#: messages.go:129 +#: messages.go:133 msgid "Albums deleted" msgstr "Albums deleted" -#: messages.go:130 +#: messages.go:134 #, c-format msgid "Zip created in %d s" msgstr "Zip created in %d s" diff --git a/assets/locales/messages.pot b/assets/locales/messages.pot index 7c05b338a..8d95669cc 100644 --- a/assets/locales/messages.pot +++ b/assets/locales/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-09-07 14:15+0000\n" +"POT-Creation-Date: 2020-09-21 07:30+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,253 +17,261 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: messages.go:69 +#: messages.go:71 msgid "Unexpected error, please try again" msgstr "" -#: messages.go:70 +#: messages.go:72 msgid "Invalid request" msgstr "" -#: messages.go:71 +#: messages.go:73 msgid "Changes could not be saved" msgstr "" -#: messages.go:72 +#: messages.go:74 msgid "Could not be deleted" msgstr "" -#: messages.go:73 +#: messages.go:75 #, c-format msgid "%s already exists" msgstr "" -#: messages.go:74 messages.go:77 +#: messages.go:76 messages.go:79 msgid "Not found on server, deleted?" msgstr "" -#: messages.go:75 +#: messages.go:77 msgid "File not found" msgstr "" -#: messages.go:76 +#: messages.go:78 msgid "Selection not found" msgstr "" -#: messages.go:78 +#: messages.go:80 msgid "Account not found" msgstr "" -#: messages.go:79 +#: messages.go:81 msgid "User not found" msgstr "" -#: messages.go:80 +#: messages.go:82 msgid "Label not found" msgstr "" -#: messages.go:81 +#: messages.go:83 msgid "Album not found" msgstr "" -#: messages.go:82 +#: messages.go:84 msgid "Not available in public mode" msgstr "" -#: messages.go:83 +#: messages.go:85 msgid "not available in read-only mode" msgstr "" -#: messages.go:84 +#: messages.go:86 msgid "Please log in and try again" msgstr "" -#: messages.go:85 +#: messages.go:87 msgid "Upload might be offensive" msgstr "" -#: messages.go:86 +#: messages.go:88 msgid "No items selected" msgstr "" -#: messages.go:87 +#: messages.go:89 msgid "Failed creating file, please check permissions" msgstr "" -#: messages.go:88 +#: messages.go:90 msgid "Failed creating folder, please check permissions" msgstr "" -#: messages.go:89 +#: messages.go:91 msgid "Could not connect, please try again" msgstr "" -#: messages.go:90 +#: messages.go:92 msgid "Invalid password, please try again" msgstr "" -#: messages.go:91 +#: messages.go:93 msgid "Feature disabled" msgstr "" -#: messages.go:92 +#: messages.go:94 msgid "No labels selected" msgstr "" -#: messages.go:93 +#: messages.go:95 msgid "No albums selected" msgstr "" -#: messages.go:94 +#: messages.go:96 msgid "No files available for download" msgstr "" -#: messages.go:95 +#: messages.go:97 msgid "Failed to create zip file" msgstr "" #: messages.go:98 -msgid "Changes successfully saved" +msgid "Invalid credentials" msgstr "" #: messages.go:99 -msgid "Album created" -msgstr "" - -#: messages.go:100 -msgid "Album saved" -msgstr "" - -#: messages.go:101 -#, c-format -msgid "Album %s deleted" +msgid "Invalid link" msgstr "" #: messages.go:102 -msgid "Album contents cloned" +msgid "Changes successfully saved" msgstr "" #: messages.go:103 -msgid "File removed from stack" +msgid "Album created" msgstr "" #: messages.go:104 -#, c-format -msgid "Selection added to %s" +msgid "Album saved" msgstr "" #: messages.go:105 #, c-format -msgid "One entry added to %s" +msgid "Album %s deleted" msgstr "" #: messages.go:106 -#, c-format -msgid "%d entries added to %s" +msgid "Album contents cloned" msgstr "" #: messages.go:107 -#, c-format -msgid "One entry removed from %s" +msgid "File removed from stack" msgstr "" #: messages.go:108 #, c-format -msgid "%d entries removed from %s" +msgid "Selection added to %s" msgstr "" #: messages.go:109 -msgid "Account created" +#, c-format +msgid "One entry added to %s" msgstr "" #: messages.go:110 -msgid "Account saved" +#, c-format +msgid "%d entries added to %s" msgstr "" #: messages.go:111 -msgid "Account deleted" +#, c-format +msgid "One entry removed from %s" msgstr "" #: messages.go:112 -msgid "Settings saved" +#, c-format +msgid "%d entries removed from %s" msgstr "" #: messages.go:113 -msgid "Password changed" +msgid "Account created" msgstr "" #: messages.go:114 -#, c-format -msgid "Import completed in %d s" +msgid "Account saved" msgstr "" #: messages.go:115 -msgid "Import canceled" +msgid "Account deleted" msgstr "" #: messages.go:116 -#, c-format -msgid "Indexing completed in %d s" +msgid "Settings saved" msgstr "" #: messages.go:117 -msgid "Indexing originals..." +msgid "Password changed" msgstr "" #: messages.go:118 #, c-format -msgid "Indexing files in %s" +msgid "Import completed in %d s" msgstr "" #: messages.go:119 -msgid "Indexing canceled" +msgid "Import canceled" msgstr "" #: messages.go:120 #, c-format -msgid "Removed %d files and %d photos" +msgid "Indexing completed in %d s" msgstr "" #: messages.go:121 -#, c-format -msgid "Moving files from %s" +msgid "Indexing originals..." msgstr "" #: messages.go:122 #, c-format -msgid "Copying files from %s" +msgid "Indexing files in %s" msgstr "" #: messages.go:123 -msgid "Labels deleted" +msgid "Indexing canceled" msgstr "" #: messages.go:124 -msgid "Label saved" +#, c-format +msgid "Removed %d files and %d photos" msgstr "" #: messages.go:125 #, c-format -msgid "%d files uploaded in %d s" +msgid "Moving files from %s" msgstr "" #: messages.go:126 -msgid "Selection archived" +#, c-format +msgid "Copying files from %s" msgstr "" #: messages.go:127 -msgid "Selection restored" +msgid "Labels deleted" msgstr "" #: messages.go:128 -msgid "Selection marked as private" +msgid "Label saved" msgstr "" #: messages.go:129 -msgid "Albums deleted" +#, c-format +msgid "%d files uploaded in %d s" msgstr "" #: messages.go:130 +msgid "Selection archived" +msgstr "" + +#: messages.go:131 +msgid "Selection restored" +msgstr "" + +#: messages.go:132 +msgid "Selection marked as private" +msgstr "" + +#: messages.go:133 +msgid "Albums deleted" +msgstr "" + +#: messages.go:134 #, c-format msgid "Zip created in %d s" msgstr "" diff --git a/internal/api/session.go b/internal/api/session.go index 79ea47fec..bcff11318 100644 --- a/internal/api/session.go +++ b/internal/api/session.go @@ -7,6 +7,7 @@ import ( "github.com/photoprism/photoprism/internal/acl" "github.com/photoprism/photoprism/internal/entity" "github.com/photoprism/photoprism/internal/form" + "github.com/photoprism/photoprism/internal/i18n" "github.com/photoprism/photoprism/internal/service" "github.com/photoprism/photoprism/internal/session" ) @@ -38,7 +39,7 @@ func CreateSession(router *gin.RouterGroup) { links := entity.FindValidLinks(f.Token, "") if len(links) == 0 { - c.AbortWithStatusJSON(400, gin.H{"error": "Invalid link"}) + c.AbortWithStatusJSON(400, gin.H{"error": i18n.Msg(i18n.ErrInvalidLink)}) } data.Tokens = []string{f.Token} @@ -56,18 +57,18 @@ func CreateSession(router *gin.RouterGroup) { user := entity.FindPersonByUserName(f.UserName) if user == nil { - c.AbortWithStatusJSON(400, gin.H{"error": "Invalid user name or password"}) + c.AbortWithStatusJSON(400, gin.H{"error": i18n.Msg(i18n.ErrInvalidCredentials)}) return } if user.InvalidPassword(f.Password) { - c.AbortWithStatusJSON(400, gin.H{"error": "Invalid user name or password"}) + c.AbortWithStatusJSON(400, gin.H{"error": i18n.Msg(i18n.ErrInvalidCredentials)}) return } data.User = *user } else { - c.AbortWithStatusJSON(400, gin.H{"error": "Password required, please try again"}) + c.AbortWithStatusJSON(400, gin.H{"error": i18n.Msg(i18n.ErrInvalidPassword)}) return } diff --git a/internal/api/session_test.go b/internal/api/session_test.go index e04e62fa9..5f824f388 100644 --- a/internal/api/session_test.go +++ b/internal/api/session_test.go @@ -1,6 +1,7 @@ package api import ( + "github.com/photoprism/photoprism/internal/i18n" "github.com/stretchr/testify/assert" "github.com/tidwall/gjson" "net/http" @@ -39,7 +40,7 @@ func TestCreateSession(t *testing.T) { CreateSession(router) r := PerformRequestWithBody(app, "POST", "/api/v1/session", `{"username": "admin", "password": "xxx"}`) val := gjson.Get(r.Body.String(), "error") - assert.Equal(t, "Invalid user name or password", val.String()) + assert.Equal(t, i18n.Msg(i18n.ErrInvalidCredentials), val.String()) assert.Equal(t, http.StatusBadRequest, r.Code) }) } diff --git a/internal/entity/person.go b/internal/entity/person.go index ce32db349..1e418ac9e 100644 --- a/internal/entity/person.go +++ b/internal/entity/person.go @@ -269,13 +269,27 @@ func (m *Person) InvalidPassword(password string) bool { return true } + time.Sleep(time.Second * 5 * time.Duration(m.LoginAttempts)) + pw := FindPassword(m.PersonUID) if pw == nil { return true } - return pw.InvalidPassword(password) + if pw.InvalidPassword(password) { + if err := Db().Model(m).UpdateColumn("login_attempts", gorm.Expr("login_attempts + ?", 1)).Error; err != nil { + log.Errorf("person: %s (update login attempts)", err) + } + + return true + } + + if err := Db().Model(m).Updates(map[string]interface{}{"login_attempts": 0, "login_at": Timestamp()}).Error; err != nil { + log.Errorf("person: %s (update last login)", err) + } + + return false } // Role returns the user role for ACL permission checks. diff --git a/internal/i18n/messages.go b/internal/i18n/messages.go index 6b8ba409c..bfbc20231 100644 --- a/internal/i18n/messages.go +++ b/internal/i18n/messages.go @@ -28,6 +28,8 @@ const ( ErrNoAlbumsSelected ErrNoFilesForDownload ErrZipFailed + ErrInvalidCredentials + ErrInvalidLink MsgChangesSaved MsgAlbumCreated @@ -93,6 +95,8 @@ var Messages = MessageMap{ ErrNoAlbumsSelected: gettext("No albums selected"), ErrNoFilesForDownload: gettext("No files available for download"), ErrZipFailed: gettext("Failed to create zip file"), + ErrInvalidCredentials: gettext("Invalid credentials"), + ErrInvalidLink: gettext("Invalid link"), // Info and confirmation messages: MsgChangesSaved: gettext("Changes successfully saved"),