mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 19:38:23 +00:00 
			
		
		
		
	Merge branch 'master' into feat/approval
This commit is contained in:
		| @@ -43,8 +43,8 @@ func TestUserDeleteAccount(t *testing.T) { | ||||
| 	prepareTestEnv(t) | ||||
|  | ||||
| 	session := loginUser(t, "user8") | ||||
| 	csrf := GetCSRF(t, session, "/user/settings/delete") | ||||
| 	urlStr := fmt.Sprintf("/user/settings/delete?password=%s", userPassword) | ||||
| 	csrf := GetCSRF(t, session, "/user/settings/account") | ||||
| 	urlStr := fmt.Sprintf("/user/settings/account/delete?password=%s", userPassword) | ||||
| 	req := NewRequestWithValues(t, "POST", urlStr, map[string]string{ | ||||
| 		"_csrf": csrf, | ||||
| 	}) | ||||
| @@ -58,8 +58,8 @@ func TestUserDeleteAccountStillOwnRepos(t *testing.T) { | ||||
| 	prepareTestEnv(t) | ||||
|  | ||||
| 	session := loginUser(t, "user2") | ||||
| 	csrf := GetCSRF(t, session, "/user/settings/delete") | ||||
| 	urlStr := fmt.Sprintf("/user/settings/delete?password=%s", userPassword) | ||||
| 	csrf := GetCSRF(t, session, "/user/settings/account") | ||||
| 	urlStr := fmt.Sprintf("/user/settings/account/delete?password=%s", userPassword) | ||||
| 	req := NewRequestWithValues(t, "POST", urlStr, map[string]string{ | ||||
| 		"_csrf": csrf, | ||||
| 	}) | ||||
|   | ||||
| @@ -93,15 +93,12 @@ func testLinksAsUser(userName string, t *testing.T) { | ||||
| 		"/user2?tab=stars", | ||||
| 		"/user2?tab=activity", | ||||
| 		"/user/settings", | ||||
| 		"/user/settings/avatar", | ||||
| 		"/user/settings/account", | ||||
| 		"/user/settings/security", | ||||
| 		"/user/settings/security/two_factor/enroll", | ||||
| 		"/user/settings/email", | ||||
| 		"/user/settings/keys", | ||||
| 		"/user/settings/applications", | ||||
| 		"/user/settings/account_link", | ||||
| 		"/user/settings/organization", | ||||
| 		"/user/settings/delete", | ||||
| 		"/user/settings/repos", | ||||
| 	} | ||||
|  | ||||
| 	session := loginUser(t, userName) | ||||
|   | ||||
| @@ -117,6 +117,7 @@ federated_avatar_lookup=Föderierte Profilbilder einschalten | ||||
| federated_avatar_lookup_popup=Föderierte Profilbilder via Libravatar aktivieren. | ||||
| disable_registration=Registrierung deaktivieren | ||||
| disable_registration_popup=Registrierung neuer Benutzer deaktivieren. Nur Administratoren werden neue Benutzerkonten anlegen können. | ||||
| allow_only_external_registration_popup=Registrierung nur über externe Services aktiveren. | ||||
| openid_signin=OpenID Anmeldung aktivieren | ||||
| openid_signin_popup=Benutzeranmeldung via OpenID aktivieren. | ||||
| openid_signup=OpenID Selbstregistrierung aktivieren | ||||
| @@ -147,6 +148,7 @@ default_allow_create_organization=Erstellen von Organisationen standarmäßig er | ||||
| default_allow_create_organization_popup=Neuen Nutzern das Erstellen von Organisationen standardmäßig erlauben. | ||||
| default_enable_timetracking=Zeiterfassung standardmäßig aktivieren | ||||
| default_enable_timetracking_popup=Zeiterfassung standardmäßig für neue Repositories aktivieren. | ||||
| no_reply_address=Versteckte E-Mail-Domain | ||||
| no_reply_address_helper=Domain-Namen für Benutzer mit einer versteckten Emailadresse. Zum Beispiel wird der Benutzername "Joe" in Git als "joe@noreply.example.org" protokolliert, wenn die versteckte E-Mail-Domäne "noreply.example.org" festgelegt ist. | ||||
|  | ||||
| [home] | ||||
| @@ -330,6 +332,7 @@ change_username=Dein Benutzername wurde geändert. | ||||
| change_username_prompt=Hinweis: Wenn du deinen Benutzernamen änderst, wird auch deine Konto-URL geändert. | ||||
| continue=Weiter | ||||
| cancel=Abbrechen | ||||
| language=Sprache | ||||
|  | ||||
| lookup_avatar_by_mail=Avatar anhand der E-Mail-Addresse suchen | ||||
| federated_avatar_lookup=Suche nach föderierten Profilbildern | ||||
| @@ -500,6 +503,7 @@ form.reach_limit_of_creation=Du hast bereits dein Limit von %d Repositories erre | ||||
| form.name_reserved=Der Repository-Name '%s' ist reserviert. | ||||
| form.name_pattern_not_allowed='%s' ist nicht erlaubt für Repository-Namen. | ||||
|  | ||||
| need_auth=Authentifizierung zum Klonen benötigt | ||||
| migrate_type=Migrationstyp | ||||
| migrate_type_helper=Dieses Repository wird ein <span class="text blue">Mirror</span> sein | ||||
| migrate_repo=Repository migrieren | ||||
| @@ -533,6 +537,7 @@ push_exist_repo=Bestehendes Repository via Kommandozeile pushen | ||||
| bare_message=Dieses Repository hat noch keinen Inhalt. | ||||
|  | ||||
| code=Code | ||||
| code.desc=Zugriff auf Quellcode, Dateien, Commits und Branches. | ||||
| branch=Branch | ||||
| tree=Struktur | ||||
| filter_branch_and_tag=Branch oder Tag filtern | ||||
| @@ -560,11 +565,13 @@ editor.edit_file=Datei bearbeiten | ||||
| editor.preview_changes=Vorschau der Änderungen | ||||
| editor.cannot_edit_non_text_files=Binärdateien können nicht im Webinterface bearbeitet werden. | ||||
| editor.edit_this_file=Datei bearbeiten | ||||
| editor.must_be_on_a_branch=Du musst dich in einer Branch befinden, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen. | ||||
| editor.fork_before_edit=Du musst dieses Repository forken, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen. | ||||
| editor.delete_this_file=Datei löschen | ||||
| editor.must_have_write_access=Du benötigst Schreibzugriff, um Änderungen an dieser Datei vorzuschlagen oder vorzunehmen. | ||||
| editor.file_delete_success=Datei '%s' wurde gelöscht. | ||||
| editor.name_your_file=Dateinamen eingeben… | ||||
| editor.filename_help=Füge einen Ordner hinzu, indem du seinen Namen und anschließend '/' eingibst. Entferne einen Ordner indem du die Zurücktaste am Anfang des Feldes drückst. | ||||
| editor.or=oder | ||||
| editor.cancel_lower=Abbrechen | ||||
| editor.commit_changes=Änderungen committen | ||||
| @@ -723,25 +730,41 @@ issues.tracking_already_started=`Du hast die Zeiterfassung bereits in <a href="% | ||||
| issues.stop_tracking=Stopp | ||||
| issues.stop_tracking_history=hat die Zeiterfassung %s angehalten | ||||
| issues.add_time=Zeit manuell hinzufügen | ||||
| issues.add_time_short=Zeit hinzufügen | ||||
| issues.add_time_cancel=Abbrechen | ||||
| issues.add_time_history=hat %s gearbeitete Zeit hinzugefügt | ||||
| issues.add_time_hours=Stunden | ||||
| issues.add_time_minutes=Minuten | ||||
| issues.add_time_sum_to_small=Es wurde keine Zeit eingegeben. | ||||
| issues.cancel_tracking=Abbrechen | ||||
| issues.cancel_tracking_history=hat die Zeiterfassung %s abgebrochen | ||||
| issues.time_spent_total=Zeitaufwand insgesamt | ||||
| issues.time_spent_from_all_authors=`Aufgewendete Zeit: %s` | ||||
| issues.due_date=Fällig am | ||||
| issues.invalid_due_date_format=Das Fälligkeitsdatum muss das Format 'JJJJ-MM-TT' haben. | ||||
| issues.error_modifying_due_date=Fehler beim Ändern des Fälligkeitsdatums. | ||||
| issues.error_removing_due_date=Fehler beim Entfernen des Fälligkeitsdatums. | ||||
| issues.due_date_form=jjjj-mm-tt | ||||
| issues.due_date_form_add=Fälligkeitsdatum hinzufügen | ||||
| issues.due_date_form_update=Fälligkeitsdatum ändern | ||||
| issues.due_date_form_remove=Fälligkeitsdatum löschen | ||||
| issues.due_date_not_writer=Du musst Schreibrechte in diesem Repository haben, um das Fälligkeitsdatum zu ändern. | ||||
| issues.due_date_not_set=Kein Fälligkeitsdatum gesetzt. | ||||
| issues.due_date_added=hat %s$2 das Fälligkeitsdatum %s$1 hinzugefügt | ||||
| issues.due_date_modified=hat %[3]s das Fälligkeitsdatum von %[2]s zu %[1]s geändert | ||||
| issues.due_date_remove=hat %[2]s das Fälligkeitsdatum %[1]s entfernt | ||||
| issues.due_date_overdue=Überfällig | ||||
|  | ||||
| pulls.desc=Merge-Requests und Code-Reviews aktivieren. | ||||
| pulls.new=Neuer Pull-Request | ||||
| pulls.compare_changes=Neuer Pull-Request | ||||
| pulls.compare_changes_desc=Wähle die Ziel- und Quellbranch aus. | ||||
| pulls.compare_base=Ziel | ||||
| pulls.compare_compare=pull von | ||||
| pulls.filter_branch=Branch filtern | ||||
| pulls.no_results=Keine Ergebnisse verfügbar. | ||||
| pulls.nothing_to_compare=Diese Branches sind identisch. Es muss kein Pull-Request erstellt werden. | ||||
| pulls.has_pull_request=`Es existiert bereits ein Pull-Request zwischen diesen beiden Branches: <a href="%[1]s/pulls/%[3]d">%[2]s#%[3]d</a>` | ||||
| pulls.create=Pull-Request erstellen | ||||
| pulls.title_desc=möchte %[1]d Commits von <code>%[2]s</code> nach <code>%[3]s</code> zusammenführen | ||||
| pulls.merged_title_desc=hat %[1]d Commits von <code>%[2]s</code> nach <code>%[3]s</code> %[4]s zusammengeführt | ||||
| @@ -751,10 +774,18 @@ pulls.tab_files=Geänderte Dateien | ||||
| pulls.reopen_to_merge=Bitte diesen Pull-Request wieder öffnen, um die Merge-Operation auszuführen. | ||||
| pulls.merged=Zusammengeführt | ||||
| pulls.has_merged=Der Pull-Request wurde zusammengeführt. | ||||
| pulls.data_broken=Dieser Pull-Requests ist kaputt, da Fork-Informationen gelöscht wurden. | ||||
| pulls.is_checking=Die Konfliktprüfung läuft noch. Bitte aktualisiere die Seite in wenigen Augenblicken. | ||||
| pulls.can_auto_merge_desc=Dieser Pull-Request kann automatisch zusammengeführt werden. | ||||
| pulls.cannot_auto_merge_desc=Dieser Pull-Request kann nicht automatisch zusammengeführt werden, da es Konflikte gibt. | ||||
| pulls.cannot_auto_merge_helper=Bitte manuell zusammenführen, um die Konflikte zu lösen. | ||||
| pulls.no_merge_desc=Dieser Pull-Request kann nicht gemerged werden, da keine Mergeoptionen aktiviert sind. | ||||
| pulls.no_merge_helper=Aktiviere Mergeoptionen in den Repositoryeinstellungen oder merge den Pull-Request manuell. | ||||
| pulls.merge_pull_request=Pull-Request zusammenführen | ||||
| pulls.rebase_merge_pull_request=Rebase und Mergen | ||||
| pulls.squash_merge_pull_request=Zusammenfassen und Mergen | ||||
| pulls.invalid_merge_option=Du kannst diese Mergeoption auf diesen Pull-Request nicht anwenden. | ||||
| pulls.open_unmerged_pull_exists=`Du kannst diesen Pull-Request nicht erneut öffnen, da noch ein anderer (#%d) mit identischen Eigenschaften offen ist.` | ||||
|  | ||||
| milestones.new=Neuer Meilenstein | ||||
| milestones.open_tab=%d offen | ||||
| @@ -763,6 +794,7 @@ milestones.closed=Geschlossen %s | ||||
| milestones.no_due_date=Kein Fälligkeitsdatum | ||||
| milestones.open=Öffnen | ||||
| milestones.close=Schließen | ||||
| milestones.new_subheader=Benutze Meilensteine, um Issues zu organisieren und den Fortschritt darzustellen. | ||||
| milestones.create=Meilenstein erstellen | ||||
| milestones.title=Titel | ||||
| milestones.desc=Beschreibung | ||||
| @@ -771,6 +803,7 @@ milestones.clear=Feld leeren | ||||
| milestones.invalid_due_date_format=Das Fälligkeitsdatum muss das Format 'JJJJ-MM-TT' haben. | ||||
| milestones.create_success=Der Meilenstein '%s' wurde erstellt. | ||||
| milestones.edit=Meilenstein bearbeiten | ||||
| milestones.edit_subheader=Benutze Meilensteine, um Issues zu organisieren und den Fortschritt darzustellen. | ||||
| milestones.cancel=Abbrechen | ||||
| milestones.modify=Meilenstein bearbeiten | ||||
| milestones.edit_success=Die Änderungen am Meilenstein "%s" wurden gespeichert. | ||||
| @@ -789,6 +822,7 @@ ext_wiki.desc=Verweis auf externes Wiki. | ||||
|  | ||||
| wiki=Wiki | ||||
| wiki.welcome=Willkommen im Wiki. | ||||
| wiki.welcome_desc=Im Wiki kannst Dokumentation schreiben und mit Mitarbeitern teilen. | ||||
| wiki.desc=Schreibe und teile Dokumentation mit Mitarbeitern. | ||||
| wiki.create_first_page=Erstelle die erste Seite | ||||
| wiki.page=Seite | ||||
| @@ -800,6 +834,7 @@ wiki.last_commit_info=%s hat diese Seite bearbeitet %s | ||||
| wiki.edit_page_button=Bearbeiten | ||||
| wiki.new_page_button=Neue Seite | ||||
| wiki.delete_page_button=Seite löschen | ||||
| wiki.delete_page_notice_1=Das Löschen der Wiki-Seite '%s' kann nicht Rückgängig gemacht werden. Fortfahren? | ||||
| wiki.page_already_exists=Eine Wiki-Seite mit dem gleichen Namen existiert bereits. | ||||
| wiki.reserved_page=Der Wiki-Seitenname "%s" ist reserviert. | ||||
| wiki.pages=Seiten | ||||
| @@ -838,6 +873,9 @@ activity.closed_issue_label=Geschlossen | ||||
| activity.new_issues_count_1=Neuer Issue | ||||
| activity.new_issues_count_n=Neue Issues | ||||
| activity.new_issue_label=Geöffnet | ||||
| activity.title.unresolved_conv_1=%d offene Konversation | ||||
| activity.title.unresolved_conv_n=%d offene Konversationen | ||||
| activity.unresolved_conv_desc=Diese kürzlich geänderten Issues und Pull-Requests wurden noch nicht gelöst. | ||||
| activity.unresolved_conv_label=Offen | ||||
| activity.title.releases_1=%d Release | ||||
| activity.title.releases_n=%d Releases | ||||
| @@ -861,6 +899,7 @@ settings.githooks=Git-Hooks | ||||
| settings.basic_settings=Grundeinstellungen | ||||
| settings.mirror_settings=Mirror Einstellungen | ||||
| settings.sync_mirror=Jetzt Synchronisieren | ||||
| settings.mirror_sync_in_progress=Mirror-Synchronisierung wird zurzeit ausgeführt. Komm in ein paar Minuten zurück. | ||||
| settings.site=Webseite | ||||
| settings.update_settings=Einstellungen speichern | ||||
| settings.advanced_settings=Erweiterte Einstellungen | ||||
| @@ -869,16 +908,27 @@ settings.use_internal_wiki=Eingebautes Wiki verwenden | ||||
| settings.use_external_wiki=Externes Wiki verwenden | ||||
| settings.external_wiki_url=Externe Wiki URL | ||||
| settings.external_wiki_url_error=Die externe Wiki-URL ist ungültig. | ||||
| settings.external_wiki_url_desc=Besucher werden auf die externe Wiki-URL weitergeleitet wenn sie auf das Wiki-Tab klicken. | ||||
| settings.issues_desc=Repository Issue-Tracker aktivieren | ||||
| settings.use_internal_issue_tracker=Integrierten Issue-Tracker verwenden | ||||
| settings.use_external_issue_tracker=Externen Issue-Tracker verwenden | ||||
| settings.external_tracker_url=URL eines externen Issue Trackers | ||||
| settings.external_tracker_url_error=Die URL des externen Issue-Trackers ist ungültig. | ||||
| settings.external_tracker_url_desc=Besucher werden auf die externe Issue-Tracker-URL weitergeleitet wenn sie auf das Issues-Tab klicken. | ||||
| settings.tracker_url_format=URL-Format des externen Issue-Systems | ||||
| settings.tracker_issue_style=Namenskonvention des externen Issue-Trackers | ||||
| settings.tracker_issue_style.numeric=Numerisch | ||||
| settings.tracker_issue_style.alphanumeric=Alphanumerisch | ||||
| settings.tracker_url_format_desc=Du kannst die Platzhalter <code>{user}</code>, <code>{repo}</code>, <code>{index}</code> für den Benutzernamen, den Namen des Repositories und die Issue-Nummer verwenden. | ||||
| settings.enable_timetracker=Zeiterfassung aktivieren | ||||
| settings.allow_only_contributors_to_track_time=Nur Mitarbeitern erlauben, die Zeiterfassung zu nutzen | ||||
| settings.pulls_desc=Repository-Pull-Requests aktivieren | ||||
| settings.pulls.ignore_whitespace=Bei Konflikten Leerzeichen ignorieren | ||||
| settings.pulls.allow_merge_commits=Mergecommits aktivieren | ||||
| settings.pulls.allow_rebase_merge=Mergen von Commits durch Rebasen aktivieren | ||||
| settings.pulls.allow_squash_commits=Mergen von Commits durch Squash aktivieren | ||||
| settings.admin_settings=Administratoreinstellungen | ||||
| settings.admin_enable_health_check=Repository-Health-Checks aktivieren (git fsck) | ||||
| settings.danger_zone=Gefahrenzone | ||||
| settings.new_owner_has_same_repo=Der neue Eigentümer hat bereits ein Repository mit dem gleichen Namen. Bitte wähle einen anderen Namen. | ||||
| settings.convert=In ein normales Repository umwandeln | ||||
| @@ -899,6 +949,8 @@ settings.wiki_deletion_success=Repository Wiki-Daten wurden gelöscht. | ||||
| settings.delete=Dieses Repository löschen | ||||
| settings.delete_desc=Wenn dieses Repository gelöscht wurde, gibt es keinen Weg zurück. Bitte sei vorsichtig. | ||||
| settings.delete_notices_1=- Diese Operation kann <strong>NICHT</strong> rückgängig gemacht werden. | ||||
| settings.delete_notices_2=- Die Operation wird das <strong>%s</strong>-Repository dauerhaft löschen, inklusive der Dateien, Issues, Kommentare und Zugriffseinstellungen. | ||||
| settings.delete_notices_fork_1=- Nach dem Löschen werden alle Forks unabhängig. | ||||
| settings.deletion_success=Das Repository wurde gelöscht. | ||||
| settings.update_settings_success=Repository Einstellungen wurden aktualisiert. | ||||
| settings.transfer_owner=Neuer Besitzer | ||||
| @@ -909,30 +961,40 @@ settings.add_collaborator=Mitarbeiter hinzufügen | ||||
| settings.add_collaborator_success=Der Mitarbeiter wurde hinzugefügt. | ||||
| settings.delete_collaborator=Entfernen | ||||
| settings.collaborator_deletion=Mitarbeiter entfernen | ||||
| settings.collaborator_deletion_desc=Nach dem Löschen wird dieser Mitarbeiter keinen Zugriff mehr auf dieses Repository haben. Fortfahren? | ||||
| settings.remove_collaborator_success=Der Mitarbeiter wurde entfernt. | ||||
| settings.search_user_placeholder=Benutzer suchen… | ||||
| settings.org_not_allowed_to_be_collaborator=Organisationen können nicht als Mitarbeiter hinzugefügt werden. | ||||
| settings.user_is_org_member=Der Benutzer ist ein Organisationsmitglied und kann nicht als Mitarbeiter hinzugefügt werden. | ||||
| settings.add_webhook=Webhook hinzufügen | ||||
| settings.hooks_desc=Webhooks senden bei bestimmten Gitea-Events automatisch HTTP POST-Requets an einen Server. Lies mehr in unserer <a target="_blank" rel="noopener" href="%s">Anleitung zu Webhooks (Englisch)</a>. | ||||
| settings.webhook_deletion=Webhook löschen | ||||
| settings.webhook_deletion_desc=Das Entfernen eines Webhooks löscht seine Einstellungen und Zustellungsverlauf. Fortfahren? | ||||
| settings.webhook_deletion_success=Webhook wurde entfernt. | ||||
| settings.webhook.test_delivery=Senden testen | ||||
| settings.webhook.test_delivery_desc=Teste diesen Webhook mit einem Fake-Event. | ||||
| settings.webhook.test_delivery_success=Ein Fake-Event wurde zur Auslieferungswarteschlange hinzugefügt. Es kann einige Sekunden dauern, bevor es im Zustellungsverlauf erscheint. | ||||
| settings.webhook.request=Anfrage | ||||
| settings.webhook.response=Antwort | ||||
| settings.webhook.headers=Kopfzeilen | ||||
| settings.webhook.payload=Inhalt | ||||
| settings.webhook.body=Inhalt | ||||
| settings.githooks_desc=Git-Hooks werden von Git selbst bereitgestellt. Du kannst die Dateien der unterstützten Hooks in der Liste unten bearbeiten, um eigene Operationen einzubinden. | ||||
| settings.githook_edit_desc=Wenn ein Hook nicht aktiv ist, wird der Standardinhalt benutzt. Lasse den Inhalt leer, um den Hook zu deaktivieren. | ||||
| settings.githook_name=Hook-Name | ||||
| settings.githook_content=Hook-Inhalt | ||||
| settings.update_githook=Hook aktualisieren | ||||
| settings.add_webhook_desc=Gitea sendet einen <code>POST</code>-Request mit festgelegtem Content-Type an die Ziel-URL. Mehr Informationen findest du in der <a target="_blank" rel="noopener" href="%s">Anleitung zu Webhooks (Englisch)</a>. | ||||
| settings.payload_url=Ziel-URL | ||||
| settings.content_type=POST-Content-Type | ||||
| settings.secret=Secret | ||||
| settings.slack_username=Benutzername | ||||
| settings.slack_icon_url=Icon-URL | ||||
| settings.discord_username=Benutzername | ||||
| settings.discord_icon_url=Icon-URL | ||||
| settings.slack_color=Farbe | ||||
| settings.event_desc=Auslösen bei: | ||||
| settings.event_push_only=Push-Events | ||||
| settings.event_send_everything=Alle Events | ||||
| settings.event_choose=Benutzerdefinierte Events… | ||||
| settings.event_create=Erstellen | ||||
| @@ -943,20 +1005,34 @@ settings.event_push=Push | ||||
| settings.event_push_desc=Git push in ein Repository. | ||||
| settings.event_repository=Repository | ||||
| settings.event_repository_desc=Repository erstellt oder gelöscht. | ||||
| settings.active=Event-Details mitversenden | ||||
| settings.active_helper=Informationen über das auslösende Event mitversenden. | ||||
| settings.add_hook_success=Webhook wurde hinzugefügt. | ||||
| settings.update_webhook=Webhook aktualisieren | ||||
| settings.update_hook_success=Webhook wurde aktualisiert. | ||||
| settings.delete_webhook=Webhook entfernen | ||||
| settings.recent_deliveries=Letzte Zustellungen | ||||
| settings.hook_type=Hook Typ | ||||
| settings.add_slack_hook_desc=<a href="%s">Slack</a>-Integration zu deinem Repository hinzufügen. | ||||
| settings.slack_token=Token | ||||
| settings.slack_domain=Domain | ||||
| settings.slack_channel=Kanal | ||||
| settings.add_discord_hook_desc=<a href="%s">Discord</a>-Integration zu deinem Repository hinzufügen. | ||||
| settings.add_dingtalk_hook_desc=<a href="%s">Dingtalk</a>-Integration zu deinem Repository hinzufügen. | ||||
| settings.deploy_keys=Deploy-Schlüssel | ||||
| settings.add_deploy_key=Deploy-Schlüssel hinzufügen | ||||
| settings.deploy_key_desc=Deploy-Keys haben nur Lesezugriff auf das Repository. | ||||
| settings.is_writable=Erlaube Schreibzugriff | ||||
| settings.is_writable_info=Erlaube diesem Deploy-Key auf das Repository zu <strong>pushen</strong>. | ||||
| settings.no_deploy_keys=Noch keine Deploy-Keys vorhanden. | ||||
| settings.title=Titel | ||||
| settings.deploy_key_content=Inhalt | ||||
| settings.key_been_used=Ein Deploy-Key mit identischem Inhalt wird bereits verwendet. | ||||
| settings.key_name_used=Ein Deploy-Key mit diesem Namen existiert bereits. | ||||
| settings.add_key_success=Der Deploy-Key '%s' wurde erfolgreich hinzugefügt. | ||||
| settings.deploy_key_deletion=Deploy-Key löschen | ||||
| settings.deploy_key_deletion_desc=Nach dem Löschen wird dieser Deploy-Key keinen Zugriff mehr auf dieses Repository haben. Fortfahren? | ||||
| settings.deploy_key_deletion_success=Der Deploy-Key wurde entfernt. | ||||
| settings.branches=Branches | ||||
| settings.protected_branch=Branch-Protection | ||||
| settings.protected_branch_can_push=Push erlauben? | ||||
| @@ -964,11 +1040,24 @@ settings.protected_branch_can_push_yes=Du kannst pushen | ||||
| settings.protected_branch_can_push_no=Du kannst nicht pushen | ||||
| settings.branch_protection=Branch-Schutz" für Branch '<b>%s</b>' | ||||
| settings.protect_this_branch=Brach-Schutz aktivieren | ||||
| settings.protect_this_branch_desc=Verhindere Löschen und deaktiviere Git force push auf diese Branch. | ||||
| settings.protect_whitelist_committers=Push-Whitelist aktivieren | ||||
| settings.protect_whitelist_committers_desc=Erlaube Nutzern oder Teams auf der Whitelist Push-Beschränkungen zu umgehen. | ||||
| settings.protect_whitelist_users=Nutzer, die pushen dürfen: | ||||
| settings.protect_whitelist_search_users=Benutzer suchen… | ||||
| settings.protect_whitelist_teams=Teams, die pushen dürfen: | ||||
| settings.protect_whitelist_search_teams=Suche nach Teams… | ||||
| settings.protect_merge_whitelist_committers=Merge-Whitelist aktivieren | ||||
| settings.protect_merge_whitelist_committers_desc=Erlaube Nutzern oder Teams auf der Whitelist Pull-Requests in diese Branch zu mergen. | ||||
| settings.protect_merge_whitelist_users=Nutzer, die mergen dürfen: | ||||
| settings.protect_merge_whitelist_teams=Teams, die mergen dürfen: | ||||
| settings.add_protected_branch=Schutz aktivieren | ||||
| settings.delete_protected_branch=Schutz deaktivieren | ||||
| settings.update_protect_branch_success=Branch-protection für die Branch '%s' wurde geändert. | ||||
| settings.remove_protected_branch_success=Branch-protection für die Branch '%s' wurde deaktiviert. | ||||
| settings.protected_branch_deletion=Brach-Schutz deaktivieren | ||||
| settings.protected_branch_deletion_desc=Wenn du die Branch-Protection deaktivierst, können alle Nutzer mit Schreibrechten auf die Branch pushen. Fortfahren? | ||||
| settings.default_branch_desc=Wähle eine Standardbranch für Pull-Requests und Code-Commits: | ||||
| settings.choose_branch=Wähle eine Branch… | ||||
| settings.no_protected_branch=Es gibt keine geschützten Branches. | ||||
|  | ||||
| @@ -985,6 +1074,7 @@ diff.view_file=Datei anzeigen | ||||
| diff.file_suppressed=Datei-Diff unterdrückt, da er zu groß ist | ||||
| diff.too_many_files=Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden. | ||||
|  | ||||
| releases.desc=Behalte den Überblick über Versionen und Downloads. | ||||
| release.releases=Releases | ||||
| release.new_release=Neues Release | ||||
| release.draft=Entwurf | ||||
| @@ -993,8 +1083,11 @@ release.stable=Stabil | ||||
| release.edit=bearbeiten | ||||
| release.ahead=<strong>%d</strong> Commits zu %s seit diesem Release | ||||
| release.source_code=Quelltext | ||||
| release.new_subheader=In Releases werden Projektversionen verwaltet. | ||||
| release.edit_subheader=In Releases werden Projektversionen verwaltet. | ||||
| release.tag_name=Tag-Name | ||||
| release.target=Ziel | ||||
| release.tag_helper=Wähle einen existierenden oder erstelle einen neuen Tag. | ||||
| release.title=Titel | ||||
| release.content=Inhalt | ||||
| release.write=Schreiben | ||||
| @@ -1008,6 +1101,7 @@ release.save_draft=Entwurf speichern | ||||
| release.edit_release=Release aktualisieren | ||||
| release.delete_release=Release löschen | ||||
| release.deletion=Release löschen | ||||
| release.deletion_desc=Wenn du ein Release löschst, wird das den dazugehörigen Git-Tag aus dem Repository löschen. Repository-Inhalte und History bleiben unverändert. Fortfahren? | ||||
| release.deletion_success=Das Release wurde gelöscht. | ||||
| release.tag_name_already_exist=Ein Release mit diesem Tag existiert bereits. | ||||
| release.tag_name_invalid=Der Tag-Name ist ungültig. | ||||
| @@ -1019,12 +1113,16 @@ branch.already_exists=Eine Branch mit dem Namen '%s' existiert bereits. | ||||
| branch.delete_head=Löschen | ||||
| branch.delete=Branch '%s' löschen | ||||
| branch.delete_html=Branch löschen | ||||
| branch.delete_desc=Das Löschen einer Branch ist permanent. Es <strong>KANN NICHT</strong> Rückgängig gemacht werden. Fortfahren? | ||||
| branch.deletion_success=Branch '%s' wurde gelöscht. | ||||
| branch.deletion_failed=Branch '%s' konnte nicht gelöscht werden. | ||||
| branch.delete_branch_has_new_commits=Die Branch '%s' kann nicht gelöscht weden, da seit dem letzten Merge neue Commits hinzugefügt wurden. | ||||
| branch.create_branch=Erstelle Branch <strong>%s</strong> | ||||
| branch.create_from=von '%s' | ||||
| branch.create_success=Branch '%s' wurde erstellt. | ||||
| branch.branch_already_exists=Branch '%s' existiert bereits in diesem Repository. | ||||
| branch.branch_name_conflict=Der Branch-Name '%s' steht in Konflikt mit der bestehendem Branch '%s'. | ||||
| branch.tag_collision=Branch '%s' kann nicht erstellt werden, da in diesem Repository bereits ein Tag mit dem selben Namen existiert. | ||||
| branch.deleted_by=Von %s gelöscht | ||||
| branch.restore_success=Branch '%s' wurde wiederhergestellt. | ||||
| branch.restore_failed=Wiederherstellung der Branch '%s' fehlgeschlagen. | ||||
| @@ -1049,10 +1147,12 @@ org_desc=Beschreibung | ||||
| team_name=Teamname | ||||
| team_desc=Beschreibung | ||||
| team_name_helper=Teamnamen sollten kurz und einprägsam sein. | ||||
| team_desc_helper=Beschreibe den Zweck oder die Rolle des Teams. | ||||
| team_permission_desc=Berechtigungen | ||||
| team_unit_desc=Zugriff auf Repositorybereiche erlauben | ||||
|  | ||||
| form.name_reserved=Der Organisationsname '%s' ist reserviert. | ||||
| form.name_pattern_not_allowed=Das Muster '%s' ist in Organisationsnamen nicht erlaubt. | ||||
| form.create_org_not_allowed=Du bist nicht berechtigt eine Organisation zu erstellen. | ||||
|  | ||||
| settings=Einstellungen | ||||
| @@ -1062,9 +1162,11 @@ settings.website=Webseite | ||||
| settings.location=Standort | ||||
| settings.update_settings=Einstellungen speichern | ||||
| settings.update_setting_success=Organisationseinstellungen wurden aktualisiert. | ||||
| settings.change_orgname_prompt=Hinweis: Die Änderung des Organisationsnamens ändert auch ihre URL. | ||||
| settings.update_avatar_success=Der Organisationsavatar wurde aktualisiert. | ||||
| settings.delete=Organisation löschen | ||||
| settings.delete_account=Diese Organisation löschen | ||||
| settings.delete_prompt=Die Organisation wird dauerhaft gelöscht. Dies <strong>KANN NICHT</strong> rückgängig gemacht werden! | ||||
| settings.confirm_delete_account=Löschen | ||||
| settings.delete_org_title=Organisation löschen | ||||
| settings.delete_org_desc=Diese Organisation wird dauerhaft gelöscht. Fortfahren? | ||||
| @@ -1072,6 +1174,8 @@ settings.hooks_desc=Webhooks hinzufügen, die für <strong>alle</strong> Reposit | ||||
|  | ||||
| members.membership_visibility=Sichtbarkeit der Mitgliedschaft: | ||||
| members.public=Sichtbar | ||||
| members.public_helper=verstecken | ||||
| members.private=Versteckt | ||||
| members.private_helper=sichtbar machen | ||||
| members.member_role=Mitgliedsrolle: | ||||
| members.owner=Besitzer | ||||
| @@ -1086,16 +1190,22 @@ teams.leave=Verlassen | ||||
| teams.read_access=Lesezugriff | ||||
| teams.read_access_helper=Mitglieder können Teamrepositories ansehen und klonen. | ||||
| teams.write_access=Schreibzugriff | ||||
| teams.write_access_helper=Mitglieder können Teamrepositories ansehen und auf sie pushen. | ||||
| teams.admin_access=Administratorzugang | ||||
| teams.admin_access_helper=Mitglieder können auf Team Repositories "pushen", von ihnen "pullen" und Mitarbeiter hinzufügen. | ||||
| teams.no_desc=Dieses Team hat keine Beschreibung | ||||
| teams.settings=Einstellungen | ||||
| teams.owners_permission_desc=Besitzer haben vollen Zugriff auf <strong>alle Repositories</strong> und <strong>Admin-Rechte</strong> für diese Organisation. | ||||
| teams.members=Teammitglieder | ||||
| teams.update_settings=Einstellungen aktualisieren | ||||
| teams.delete_team=Team löschen | ||||
| teams.add_team_member=Teammitglied hinzufügen | ||||
| teams.delete_team_title=Team löschen | ||||
| teams.delete_team_desc=Das Löschen eines Teams wiederruft den Repository-Zugriff für seine Mitglieder. Fortfahren? | ||||
| teams.delete_team_success=Das Team wurde gelöscht. | ||||
| teams.read_permission_desc=Dieses Team hat <strong>Lesezugriff</strong>: Mitglieder können Team-Repositories einsehen und klonen. | ||||
| teams.write_permission_desc=Dieses Team hat <strong>Schreibzugriff</strong>: Mitglieder können Team-Repositories einsehen und darauf pushen. | ||||
| teams.admin_permission_desc=Dieses Team hat <strong>Adminzugriff</strong>: Mitglieder dieses Teams können Team-Repositories ansehen, auf sie pushen und Mitarbeiter hinzufügen. | ||||
| teams.repositories=Team-Repositories | ||||
| teams.search_repo_placeholder=Repository durchsuchen… | ||||
| teams.add_team_repository=Team-Repository hinzufügen | ||||
| @@ -1116,7 +1226,9 @@ last_page=Letzte | ||||
| total=Gesamt: %d | ||||
|  | ||||
| dashboard.statistic=Übersicht | ||||
| dashboard.operations=Wartungsoperationen | ||||
| dashboard.system_status=System-Status | ||||
| dashboard.statistic_info=Gitea's Datenbank hat <b>%d</b> Benutzer, <b>%d</b> Organisationen, <b>%d</b> öffentliche Schlüssel, <b>%d</b> Repositories, <b>%d</b> Beobachtungen, <b>%d</b> Favoriten, <b>%d</b> Aktionen, <b>%d</b> Zugriffe, <b>%d</b> Issues, <b>%d</b> Kommentare, <b>%d</b> Konten sozialer Netzwerke, <b>%d</b> Gefolgte, <b>%d</b> Mirrors, <b>%d</b> Releases, <b>%d</b> Login-Quellen, <b>%d</b> Webhooks, <b>%d</b> Meilensteine, <b>%d</b> Label, <b>%d</b> Hook-Tasks, <b>%d</b> Teams, <b>%d</b> Aktualisierungs-Tasks, <b>%d</b> Anhänge. | ||||
| dashboard.operation_name=Name der Operation | ||||
| dashboard.operation_switch=Wechseln | ||||
| dashboard.operation_run=Ausführen | ||||
| @@ -1130,11 +1242,16 @@ dashboard.delete_missing_repos=Alle Repository-Datensätze mit verlorenen gegang | ||||
| dashboard.delete_missing_repos_success=Alle Repository-Datensätze mit verlorenen Git-Dateien wurden gelöscht. | ||||
| dashboard.git_gc_repos=Garbage Collection auf Repositories ausführen | ||||
| dashboard.git_gc_repos_success=Alle Repositories haben Garbage Collection beendet. | ||||
| dashboard.resync_all_sshkeys='.ssh/authorized_keys'-Datei mit Gitea SSH-Keys neu schreiben. (Wenn Du den eingebauten SSH Server nutzt, musst du das nicht ausführen.) | ||||
| dashboard.resync_all_sshkeys_success=Alle von Gitea verwalteten öffentlichen Schlüssel wurden neu geschrieben. | ||||
| dashboard.resync_all_hooks=Synchronisiere pre-receive, update und post-receive Hooks für alle Repositories. | ||||
| dashboard.resync_all_hooks_success=Alle pre-receive, update und post-receive Repository-Hooks wurden synchronisiert. | ||||
| dashboard.reinit_missing_repos=Alle Git-Repositories mit Einträgen neu einlesen | ||||
| dashboard.reinit_missing_repos_success=Alle verlorenen Git-Repositories mit existierenden Einträgen wurden erfolgreich aktualisiert. | ||||
| dashboard.sync_external_users=Externe Benutzerdaten synchronisieren | ||||
| dashboard.sync_external_users_started=Externe Benutzersynchronisation gestartet. | ||||
| dashboard.git_fsck=Healthchecks auf alle Repositories ausführen | ||||
| dashboard.git_fsck_started=Repository-Healthchecks gestartet. | ||||
| dashboard.server_uptime=Server-Uptime | ||||
| dashboard.current_goroutine=Aktuelle Goroutinen | ||||
| dashboard.current_memory_usage=Aktuelle Speichernutzung | ||||
| @@ -1173,21 +1290,28 @@ users.admin=Administrator | ||||
| users.repos=Repositories | ||||
| users.created=Registriert am | ||||
| users.last_login=Letzte Anmeldung | ||||
| users.never_login=Hat sich noch nie eingeloggt | ||||
| users.send_register_notify=Benutzer-Registrierungsbenachrichtigung senden | ||||
| users.new_success=Der Account '%s' wurde erstellt. | ||||
| users.edit=Bearbeiten | ||||
| users.auth_source=Authentifizierungsquelle | ||||
| users.local=Lokal | ||||
| users.auth_login_name=Anmeldename zur Authentifizierung | ||||
| users.password_helper=Passwort leerlassen, um es nicht zu verändern. | ||||
| users.update_profile_success=Der Account '%s' wurde aktualisiert. | ||||
| users.edit_account=Benutzerkonto bearbeiten | ||||
| users.max_repo_creation=Maximale Anzahl Repositories | ||||
| users.max_repo_creation_desc=(Gib -1 ein, um das globale Standardlimit zu verwenden.) | ||||
| users.is_activated=Account ist aktiviert | ||||
| users.prohibit_login=Anmelden deaktivieren | ||||
| users.is_admin=Ist Administrator | ||||
| users.allow_git_hook=Darf "Git Hooks" erstellen | ||||
| users.allow_import_local=Darf lokale Repositories importieren | ||||
| users.allow_create_organization=Darf Organisationen erstellen | ||||
| users.update_profile=Benutzerkonto aktualisieren | ||||
| users.delete_account=Benutzerkonto löschen | ||||
| users.still_own_repo=Dieser Benutzer besitzt noch mindestens ein Repository. Bitte lösche oder übertrage diese zuerst. | ||||
| users.still_has_org=Dieser Nutzer ist Mitglied einer Organisation. Du musst ihn zuerst aus allen Organisationen entfernen. | ||||
| users.deletion_success=Der Account wurde gelöscht. | ||||
|  | ||||
| orgs.org_manage_panel=Organisationsverwaltung | ||||
| @@ -1220,12 +1344,17 @@ auths.host=Host | ||||
| auths.port=Port | ||||
| auths.bind_dn=DN binden | ||||
| auths.bind_password=Passwort binden | ||||
| auths.bind_password_helper=Achtung: Das Passwort wird im Klartext gespeichert. Benutze wenn möglich einen Account mit nur Lesezugriff. | ||||
| auths.user_base=Basis für Benutzersuche | ||||
| auths.user_dn=Benutzer DN | ||||
| auths.attribute_username=Benutzername Attribut | ||||
| auths.attribute_username_placeholder=Leerlassen, um den in Gitea eingegebenen Benutzernamen zu verwenden. | ||||
| auths.attribute_name=Vornamensattribut | ||||
| auths.attribute_surname=Nachnamensattribut | ||||
| auths.attribute_mail=E-Mail Attribut | ||||
| auths.attributes_in_bind=Hole Attribute im Bind-Kontext | ||||
| auths.use_paged_search=Seitensuche verwenden | ||||
| auths.search_page_size=Seitengröße | ||||
| auths.filter=Benutzerfilter | ||||
| auths.admin_filter=Admin Filter | ||||
| auths.ms_ad_sa=MS AD Suchattribute | ||||
| @@ -1233,6 +1362,7 @@ auths.smtp_auth=SMTP-Authentifizierungstyp | ||||
| auths.smtphost=SMTP-Host | ||||
| auths.smtpport=SMTP-Port | ||||
| auths.allowed_domains=Erlaubte Domains | ||||
| auths.allowed_domains_helper=Leerlassen, um alle Domains zuzulassen. Trenne mehrere Domänen mit einem Komma (','). | ||||
| auths.enable_tls=TLS-Verschlüsselung aktivieren | ||||
| auths.skip_tls_verify=TLS Verifikation überspringen | ||||
| auths.pam_service_name=PAM Dienstname | ||||
| @@ -1240,6 +1370,7 @@ auths.oauth2_provider=OAuth2 Anbieter | ||||
| auths.oauth2_clientID=Client-ID (Schlüssel) | ||||
| auths.oauth2_clientSecret=Client-Secret | ||||
| auths.openIdConnectAutoDiscoveryURL=OpenID Connect Auto Discovery URL | ||||
| auths.oauth2_use_custom_url=Benutzerdefinierte URLs anstelle von Standard-URLs verwenden | ||||
| auths.oauth2_tokenURL=Token-URL | ||||
| auths.oauth2_authURL=Authorisierungs-URL | ||||
| auths.oauth2_profileURL=Profil-URL | ||||
| @@ -1249,11 +1380,14 @@ auths.tips=Tipps | ||||
| auths.tips.oauth2.general=OAuth2 Authentifizierung | ||||
| auths.tips.oauth2.general.tip=Beim Registrieren einer neuen OAuth2 Authentifizierung sollte die Callback/Weiterleitungs-URL <host>/user/oauth2/<Authentication Name>/callback sein. | ||||
| auths.tip.oauth2_provider=OAuth2 Anbieter | ||||
| auths.tip.bitbucket=Registriere einen neuen OAuth-Consumer unter https://bitbucket.org/account/user/<dein-benutzername>/oauth-consumers/new und füge die Berechtigung "Account"-"Read" hinzu. | ||||
| auths.tip.dropbox=Erstelle eine neue App auf https://www.dropbox.com/developers/apps. | ||||
| auths.tip.facebook=Erstelle eine neue Anwendung auf https://developers.facebook.com/apps und füge das Produkt "Facebook Login" hinzu. | ||||
| auths.tip.github=Erstelle unter https://github.com/settings/applications/new eine neue OAuth Anwendung. | ||||
| auths.tip.gitlab=Erstelle unter https://gitlab.com/profile/applications eine neue Anwendung. | ||||
| auths.tip.google_plus=Du erhältst die OAuth2 Client Zugangsdaten in der Google API Console unter https://console.developers.google.com/ | ||||
| auths.tip.openid_connect=Benutze die OpenID Connect Discovery URL (<server>/.well-known/openid-configuration) als Endpunkt. | ||||
| auths.tip.twitter=Gehe auf https://dev.twitter.com/apps, erstelle eine Anwendung und stelle sicher, dass die Option “Allow this application to be used to Sign in with Twitter” aktiviert ist | ||||
| auths.edit=Authentifikationsquelle bearbeiten | ||||
| auths.activated=Diese Authentifikationsquelle ist aktiviert | ||||
| auths.new_success=Die Authentifizierung "%s" wurde hinzugefügt. | ||||
| @@ -1309,6 +1443,7 @@ config.db_path_helper=(für "sqlite3" und "tidb") | ||||
| config.service_config=Service-Konfiguration | ||||
| config.register_email_confirm=E-Mail-Bestätigung benötigt zum Registrieren | ||||
| config.disable_register=Selbstegistrierung deaktivieren | ||||
| config.allow_only_external_registration=Registrierung nur über externe Services aktiveren | ||||
| config.enable_openid_signup=OpenID Selbstregistrierung aktivieren | ||||
| config.enable_openid_signin=OpenID Anmeldung aktivieren | ||||
| config.show_registration_button=Schaltfläche zum Registrieren anzeigen | ||||
| @@ -1319,7 +1454,11 @@ config.enable_captcha=CAPTCHA aktivieren | ||||
| config.active_code_lives=Aktivierungscode Lebensdauer | ||||
| config.reset_password_code_lives=Ablaufdatum des Passworts zurücksetzen | ||||
| config.default_keep_email_private=E-Mail-Adressen standardmäßig verbergen | ||||
| config.default_allow_create_organization=Erstellen von Organisationen standarmäßig erlauben | ||||
| config.enable_timetracking=Zeiterfassung aktivieren | ||||
| config.default_enable_timetracking=Zeiterfassung standardmäßig aktivieren | ||||
| config.default_allow_only_contributors_to_track_time=Nur Mitarbeitern erlauben, die Zeiterfassung zu nutzen | ||||
| config.no_reply_address=Versteckte E-Mail-Domain | ||||
|  | ||||
| config.webhook_config=Webhook-Konfiguration | ||||
| config.queue_length=Warteschlangenlänge | ||||
| @@ -1357,6 +1496,7 @@ config.session_life_time=Session-Lebensdauer | ||||
| config.https_only=Nur HTTPS | ||||
| config.cookie_life_time=Cookie-Lebensdauer | ||||
|  | ||||
| config.picture_config=Avatar-Konfiguration | ||||
| config.picture_service=Bilderservice | ||||
| config.disable_gravatar=Gravatar deaktivieren | ||||
| config.enable_federated_avatar=Föderierte Profilbilder einschalten | ||||
| @@ -1381,6 +1521,7 @@ monitor.name=Name | ||||
| monitor.schedule=Zeitplan | ||||
| monitor.next=Nächste Ausführung | ||||
| monitor.previous=Letzte Ausführung | ||||
| monitor.execute_times=Ausführungen | ||||
| monitor.process=Laufende Prozesse | ||||
| monitor.desc=Beschreibung | ||||
| monitor.start=Startzeit | ||||
| @@ -1460,8 +1601,10 @@ mark_all_as_read=Alle als gelesen markieren | ||||
| [gpg] | ||||
| error.extract_sign=Die Signatur konnte nicht extrahiert werden | ||||
| error.generate_hash=Es konnte kein Hash vom Commit generiert werden | ||||
| error.no_committer_account=Es ist kein Benutzerkonto mit dieser Commiter-Email verbunden | ||||
| error.no_gpg_keys_found=Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden | ||||
| error.not_signed_commit=Kein signierter Commit | ||||
| error.failed_retrieval_gpg_keys=Fehler beim Abrufen eines Keys des Commiter-Kontos | ||||
|  | ||||
| [units] | ||||
| error.no_unit_allowed_repo=Du hast keine Berechtigung auf einen Bereich dieses Repositories zuzugreifen. | ||||
|   | ||||
| @@ -310,12 +310,13 @@ form.name_pattern_not_allowed = The pattern '%s' is not allowed in a username. | ||||
|  | ||||
| [settings] | ||||
| profile = Profile | ||||
| account = Account | ||||
| password = Password | ||||
| security = Security | ||||
| avatar = Avatar | ||||
| ssh_gpg_keys = SSH / GPG Keys | ||||
| social = Social Accounts | ||||
| applications = Access Tokens | ||||
| applications = Applications | ||||
| orgs = Manage Organizations | ||||
| repos = Repositories | ||||
| delete = Delete Account | ||||
|   | ||||
| @@ -117,6 +117,7 @@ federated_avatar_lookup=Habilitar avatares federativos | ||||
| federated_avatar_lookup_popup=Habilitar a busca federativa de avatares a usar o serviço federativo de código aberto baseado no libravatar. | ||||
| disable_registration=Desabilitar auto-cadastro | ||||
| disable_registration_popup=Desabilitar auto-cadastro de usuário. Somente os administradores serão capazes de criar novas contas de usuário. | ||||
| allow_only_external_registration_popup=Habilitar o cadastro apenas por meio de serviços externos. | ||||
| openid_signin=Habilitar acesso via OpenID | ||||
| openid_signin_popup=Habilitar o acesso de usuários via OpenID. | ||||
| openid_signup=Habilitar o auto-cadastro via OpenID | ||||
| @@ -1442,6 +1443,7 @@ config.db_path_helper=(para "sqlite3" e "tidb") | ||||
| config.service_config=Configuração do serviço | ||||
| config.register_email_confirm=Exigir confirmação de e-mail para se cadastrar | ||||
| config.disable_register=Desabilitar auto-cadastro | ||||
| config.allow_only_external_registration=Habilitar o cadastro apenas por meio de serviços externos | ||||
| config.enable_openid_signup=Habilitar o auto-cadastro via OpenID | ||||
| config.enable_openid_signin=Habilitar acesso via OpenID | ||||
| config.show_registration_button=Mostrar botão de cadastro | ||||
|   | ||||
| @@ -150,6 +150,8 @@ organizations=Організації | ||||
| search=Пошук | ||||
| code=Код | ||||
| repo_no_results=Відповідних репозиторіїв не знайдено. | ||||
| user_no_results=Відповідних користувачів не знайдено. | ||||
| org_no_results=Відповідних організацій не знайдено. | ||||
| code_search_results=Результати пошуку '%s' | ||||
|  | ||||
| [auth] | ||||
| @@ -422,7 +424,7 @@ milestones=Етап | ||||
| commits=Коміти | ||||
| commit=Змина | ||||
| releases=Релізи | ||||
| file_raw=Raw | ||||
| file_raw=Неформатований | ||||
| file_history=Історія | ||||
| file_view_raw=Перегляд Raw | ||||
| file_permalink=Постійне посилання | ||||
| @@ -558,8 +560,13 @@ issues.num_participants=%d учасників | ||||
| issues.attachment.open_tab=`Натисніть щоб побачити "%s" у новій вкладці` | ||||
| issues.subscribe=Підписатися | ||||
| issues.unsubscribe=Відписатися | ||||
| issues.tracker=Відстеження часу | ||||
| issues.start_tracking_short=Запустити | ||||
| issues.start_tracking=Почати відстеження часу | ||||
| issues.start_tracking_history=`почав працювати %s` | ||||
| issues.tracking_already_started=`Ви вже почали відстежувати час для цієї <a href="%s"> проблеми</a>!` | ||||
| issues.stop_tracking=Стоп | ||||
| issues.add_time=Вручну додати час | ||||
| issues.add_time_short=Додати час | ||||
| issues.add_time_cancel=Відміна | ||||
| issues.add_time_hours=Години | ||||
| @@ -569,6 +576,7 @@ issues.cancel_tracking=Відміна | ||||
| issues.due_date=Термін дії | ||||
| issues.due_date_form_add=Додати дату завершення | ||||
| issues.due_date_form_remove=Видалити дату завершення | ||||
| issues.due_date_not_set=Термін виконання не встановлений. | ||||
|  | ||||
| pulls.new=Новий запит на злиття | ||||
| pulls.compare_changes=Новий запит на злиття | ||||
| @@ -578,6 +586,7 @@ pulls.filter_branch=Фільтр по гілці | ||||
| pulls.no_results=Результатів не знайдено. | ||||
| pulls.create=Створити запит на злиття | ||||
| pulls.title_desc=хоче злити %[1]d комітів з <code>%[2]s</code> до <code>%[3]s</code> | ||||
| pulls.merged_title_desc=злито %[1]d комітів з <code>%[2]s</code> до <code>%[3]s</code> %[4]s | ||||
| pulls.tab_conversation=Обговорення | ||||
| pulls.tab_commits=Коміти | ||||
| pulls.tab_files=Змінені файли | ||||
| @@ -682,6 +691,7 @@ settings.external_tracker_url=URL зовнішньої системи відст | ||||
| settings.tracker_url_format=Формат URL зовнішнього трекера задач | ||||
| settings.tracker_issue_style.numeric=Цифровий | ||||
| settings.tracker_issue_style.alphanumeric=Буквено-цифровий | ||||
| settings.enable_timetracker=Увімкнути відстеження часу | ||||
| settings.admin_settings=Налаштування адміністратора | ||||
| settings.danger_zone=Небезпечна зона | ||||
| settings.new_owner_has_same_repo=Новий власник вже має репозиторій з такою назвою. Будь ласка, виберіть інше ім'я. | ||||
| @@ -721,6 +731,7 @@ settings.event_pull_request=Запити до злиття | ||||
| settings.event_push=Push | ||||
| settings.event_repository=Репозиторій | ||||
| settings.event_repository_desc=Репозиторій створений або видалено. | ||||
| settings.active=Додавати інформацію про події | ||||
| settings.update_webhook=Оновити веб-хук | ||||
| settings.hook_type=Тип хука | ||||
| settings.slack_token=Токен | ||||
| @@ -833,6 +844,7 @@ teams.settings=Налаштування | ||||
| teams.members=Учасники команди | ||||
| teams.update_settings=Оновити налаштування | ||||
| teams.add_team_member=Додати учасника команди | ||||
| teams.write_permission_desc=Ця команда надає доступ на <strong>запис</strong>: учасники можуть отримувати й виконувати push команди до репозитрію. | ||||
| teams.add_team_repository=Додати репозиторій команди | ||||
| teams.remove_repo=Видалити | ||||
|  | ||||
| @@ -994,6 +1006,7 @@ config.enable_captcha=Увімкнути CAPTCHA | ||||
| config.active_code_lives=Час актуальності кода підтвердження | ||||
| config.default_keep_email_private=Приховати адресу електронної пошти за замовчуванням | ||||
| config.default_allow_create_organization=Дозволити створення організацій за замовчуванням | ||||
| config.enable_timetracking=Увімкнути відстеження часу | ||||
| config.default_enable_timetracking=Увімкнути відстеження часу за замовчуванням | ||||
|  | ||||
| config.webhook_config=Конфігурація web-хуків | ||||
|   | ||||
| @@ -117,6 +117,7 @@ federated_avatar_lookup=启用 Federated 头像 | ||||
| federated_avatar_lookup_popup=启用 Federated Avatars 查找以使用开源的 Libravatar 服务。 | ||||
| disable_registration=禁止用户自助注册 | ||||
| disable_registration_popup=禁用用户自助注册。只有管理员才能创建新的用户帐户。 | ||||
| allow_only_external_registration_popup=仅允许通过外部服务注册。 | ||||
| openid_signin=启用 OpenID 登录 | ||||
| openid_signin_popup=启用通过 OpenID 登录 | ||||
| openid_signup=启用 OpenID 自助注册 | ||||
| @@ -1442,6 +1443,7 @@ config.db_path_helper=(用于 "sqlite3" 和 "tidb") | ||||
| config.service_config=服务配置 | ||||
| config.register_email_confirm=需要电子邮件确认注册 | ||||
| config.disable_register=禁止用户注册 | ||||
| config.allow_only_external_registration=仅允许通过外部服务注册 | ||||
| config.enable_openid_signup=启用 OpenID 自注册 | ||||
| config.enable_openid_signin=启用 OpenID 登录 | ||||
| config.show_registration_button=显示注册按钮 | ||||
|   | ||||
| @@ -37,6 +37,7 @@ import ( | ||||
| 	"github.com/go-macaron/session" | ||||
| 	"github.com/go-macaron/toolbox" | ||||
| 	"gopkg.in/macaron.v1" | ||||
| 	"net/http" | ||||
| ) | ||||
|  | ||||
| // NewMacaron initializes Macaron instance. | ||||
| @@ -217,35 +218,54 @@ func RegisterRoutes(m *macaron.Macaron) { | ||||
| 	m.Group("/user/settings", func() { | ||||
| 		m.Get("", user.Settings) | ||||
| 		m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost) | ||||
| 		m.Combo("/avatar").Get(user.SettingsAvatar). | ||||
| 			Post(binding.MultipartForm(auth.AvatarForm{}), user.SettingsAvatarPost) | ||||
| 		m.Post("/avatar", binding.MultipartForm(auth.AvatarForm{}), user.SettingsAvatarPost) | ||||
| 		m.Post("/avatar/delete", user.SettingsDeleteAvatar) | ||||
| 		m.Combo("/email").Get(user.SettingsEmails). | ||||
| 			Post(bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost) | ||||
| 		m.Post("/email/delete", user.DeleteEmail) | ||||
| 		m.Get("/security", user.SettingsSecurity) | ||||
| 		m.Post("/security", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsSecurityPost) | ||||
| 		m.Group("/openid", func() { | ||||
| 			m.Combo("").Get(user.SettingsOpenID). | ||||
| 				Post(bindIgnErr(auth.AddOpenIDForm{}), user.SettingsOpenIDPost) | ||||
| 			m.Post("/delete", user.DeleteOpenID) | ||||
| 			m.Post("/toggle_visibility", user.ToggleOpenIDVisibility) | ||||
| 		}, openIDSignInEnabled) | ||||
| 		m.Combo("/keys").Get(user.SettingsKeys). | ||||
| 			Post(bindIgnErr(auth.AddKeyForm{}), user.SettingsKeysPost) | ||||
| 		m.Post("/keys/delete", user.DeleteKey) | ||||
| 		m.Group("/account", func() { | ||||
| 			m.Combo("").Get(user.SettingsAccount).Post(bindIgnErr(auth.ChangePasswordForm{}), user.SettingsAccountPost) | ||||
| 			m.Post("/email", bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost) | ||||
| 			m.Post("/email/delete", user.DeleteEmail) | ||||
| 			m.Post("/delete", user.SettingsDelete) | ||||
| 		}) | ||||
| 		m.Group("/security", func() { | ||||
| 			m.Get("", user.SettingsSecurity) | ||||
| 			m.Group("/two_factor", func() { | ||||
| 				m.Post("/regenerate_scratch", user.SettingsTwoFactorRegenerateScratch) | ||||
| 				m.Post("/disable", user.SettingsTwoFactorDisable) | ||||
| 				m.Get("/enroll", user.SettingsTwoFactorEnroll) | ||||
| 				m.Post("/enroll", bindIgnErr(auth.TwoFactorAuthForm{}), user.SettingsTwoFactorEnrollPost) | ||||
| 			}) | ||||
| 			m.Group("/openid", func() { | ||||
| 				m.Post("", bindIgnErr(auth.AddOpenIDForm{}), user.SettingsOpenIDPost) | ||||
| 				m.Post("/delete", user.DeleteOpenID) | ||||
| 				m.Post("/toggle_visibility", user.ToggleOpenIDVisibility) | ||||
| 			}, openIDSignInEnabled) | ||||
| 			m.Post("/account_link", user.SettingsDeleteAccountLink) | ||||
| 		}) | ||||
| 		m.Combo("/applications").Get(user.SettingsApplications). | ||||
| 			Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost) | ||||
| 		m.Post("/applications/delete", user.SettingsDeleteApplication) | ||||
| 		m.Route("/delete", "GET,POST", user.SettingsDelete) | ||||
| 		m.Combo("/account_link").Get(user.SettingsAccountLinks).Post(user.SettingsDeleteAccountLink) | ||||
| 		m.Combo("/keys").Get(user.SettingsKeys). | ||||
| 			Post(bindIgnErr(auth.AddKeyForm{}), user.SettingsKeysPost) | ||||
| 		m.Post("/keys/delete", user.DeleteKey) | ||||
| 		m.Get("/organization", user.SettingsOrganization) | ||||
| 		m.Get("/repos", user.SettingsRepos) | ||||
| 		m.Group("/security/two_factor", func() { | ||||
| 			m.Post("/regenerate_scratch", user.SettingsTwoFactorRegenerateScratch) | ||||
| 			m.Post("/disable", user.SettingsTwoFactorDisable) | ||||
| 			m.Get("/enroll", user.SettingsTwoFactorEnroll) | ||||
| 			m.Post("/enroll", bindIgnErr(auth.TwoFactorAuthForm{}), user.SettingsTwoFactorEnrollPost) | ||||
|  | ||||
| 		// redirects from old settings urls to new ones | ||||
| 		// TODO: can be removed on next major version | ||||
| 		m.Get("/avatar", func(ctx *context.Context) { | ||||
| 			ctx.Redirect(setting.AppSubURL+"/user/settings", http.StatusMovedPermanently) | ||||
| 		}) | ||||
| 		m.Get("/email", func(ctx *context.Context) { | ||||
| 			ctx.Redirect(setting.AppSubURL+"/user/settings/account", http.StatusMovedPermanently) | ||||
| 		}) | ||||
| 		m.Get("/delete", func(ctx *context.Context) { | ||||
| 			ctx.Redirect(setting.AppSubURL+"/user/settings/account", http.StatusMovedPermanently) | ||||
| 		}) | ||||
| 		m.Get("/openid", func(ctx *context.Context) { | ||||
| 			ctx.Redirect(setting.AppSubURL+"/user/settings/security", http.StatusMovedPermanently) | ||||
| 		}) | ||||
| 		m.Get("/account_link", func(ctx *context.Context) { | ||||
| 			ctx.Redirect(setting.AppSubURL+"/user/settings/security", http.StatusMovedPermanently) | ||||
| 		}) | ||||
| 	}, reqSignIn, func(ctx *context.Context) { | ||||
| 		ctx.Data["PageIsUserSettings"] = true | ||||
|   | ||||
| @@ -30,18 +30,13 @@ import ( | ||||
|  | ||||
| const ( | ||||
| 	tplSettingsProfile      base.TplName = "user/settings/profile" | ||||
| 	tplSettingsAvatar       base.TplName = "user/settings/avatar" | ||||
| 	tplSettingsEmails       base.TplName = "user/settings/email" | ||||
| 	tplSettingsKeys         base.TplName = "user/settings/keys" | ||||
| 	tplSettingsSocial       base.TplName = "user/settings/social" | ||||
| 	tplSettingsApplications base.TplName = "user/settings/applications" | ||||
| 	tplSettingsTwofa        base.TplName = "user/settings/twofa" | ||||
| 	tplSettingsAccount      base.TplName = "user/settings/account" | ||||
| 	tplSettingsSecurity     base.TplName = "user/settings/security" | ||||
| 	tplSettingsTwofaEnroll  base.TplName = "user/settings/twofa_enroll" | ||||
| 	tplSettingsAccountLink  base.TplName = "user/settings/account_link" | ||||
| 	tplSettingsApplications base.TplName = "user/settings/applications" | ||||
| 	tplSettingsKeys         base.TplName = "user/settings/keys" | ||||
| 	tplSettingsOrganization base.TplName = "user/settings/organization" | ||||
| 	tplSettingsRepositories base.TplName = "user/settings/repos" | ||||
| 	tplSettingsDelete       base.TplName = "user/settings/delete" | ||||
| 	tplSettingsSecurity     base.TplName = "user/settings/security" | ||||
| ) | ||||
|  | ||||
| // Settings render user's profile page | ||||
| @@ -168,13 +163,6 @@ func UpdateAvatarSetting(ctx *context.Context, form auth.AvatarForm, ctxUser *mo | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // SettingsAvatar render user avatar page | ||||
| func SettingsAvatar(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsAvatar"] = true | ||||
| 	ctx.HTML(200, tplSettingsAvatar) | ||||
| } | ||||
|  | ||||
| // SettingsAvatarPost response for change user's avatar request | ||||
| func SettingsAvatarPost(ctx *context.Context, form auth.AvatarForm) { | ||||
| 	if err := UpdateAvatarSetting(ctx, form, ctx.User); err != nil { | ||||
| @@ -183,7 +171,7 @@ func SettingsAvatarPost(ctx *context.Context, form auth.AvatarForm) { | ||||
| 		ctx.Flash.Success(ctx.Tr("settings.update_avatar_success")) | ||||
| 	} | ||||
|  | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/avatar") | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings") | ||||
| } | ||||
|  | ||||
| // SettingsDeleteAvatar render delete avatar page | ||||
| @@ -192,38 +180,32 @@ func SettingsDeleteAvatar(ctx *context.Context) { | ||||
| 		ctx.Flash.Error(err.Error()) | ||||
| 	} | ||||
|  | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/avatar") | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings") | ||||
| } | ||||
|  | ||||
| // SettingsSecurity render change user's password page and 2FA | ||||
| func SettingsSecurity(ctx *context.Context) { | ||||
| // SettingsAccount renders change user's password, user's email and user suicide page | ||||
| func SettingsAccount(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsSecurity"] = true | ||||
| 	ctx.Data["PageIsSettingsAccount"] = true | ||||
| 	ctx.Data["Email"] = ctx.User.Email | ||||
|  | ||||
| 	enrolled := true | ||||
| 	_, err := models.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	emails, err := models.GetEmailAddresses(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		if models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			enrolled = false | ||||
| 		} else { | ||||
| 			ctx.ServerError("SettingsTwoFactor", err) | ||||
| 			return | ||||
| 		} | ||||
| 		ctx.ServerError("GetEmailAddresses", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Emails"] = emails | ||||
|  | ||||
| 	ctx.Data["TwofaEnrolled"] = enrolled | ||||
| 	ctx.HTML(200, tplSettingsSecurity) | ||||
| 	ctx.HTML(200, tplSettingsAccount) | ||||
| } | ||||
|  | ||||
| // SettingsSecurityPost response for change user's password | ||||
| func SettingsSecurityPost(ctx *context.Context, form auth.ChangePasswordForm) { | ||||
| // SettingsAccountPost response for change user's password | ||||
| func SettingsAccountPost(ctx *context.Context, form auth.ChangePasswordForm) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsSecurity"] = true | ||||
| 	ctx.Data["PageIsSettingsDelete"] = true | ||||
| 	ctx.Data["PageIsSettingsAccount"] = true | ||||
|  | ||||
| 	if ctx.HasError() { | ||||
| 		ctx.HTML(200, tplSettingsSecurity) | ||||
| 		ctx.HTML(200, tplSettingsAccount) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @@ -248,28 +230,13 @@ func SettingsSecurityPost(ctx *context.Context, form auth.ChangePasswordForm) { | ||||
| 		ctx.Flash.Success(ctx.Tr("settings.change_password_success")) | ||||
| 	} | ||||
|  | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/security") | ||||
| } | ||||
|  | ||||
| // SettingsEmails render user's emails page | ||||
| func SettingsEmails(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsEmails"] = true | ||||
|  | ||||
| 	emails, err := models.GetEmailAddresses(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("GetEmailAddresses", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Emails"] = emails | ||||
|  | ||||
| 	ctx.HTML(200, tplSettingsEmails) | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/account") | ||||
| } | ||||
|  | ||||
| // SettingsEmailPost response for change user's email | ||||
| func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsEmails"] = true | ||||
| 	ctx.Data["PageIsSettingsAccount"] = true | ||||
|  | ||||
| 	// Make emailaddress primary. | ||||
| 	if ctx.Query("_method") == "PRIMARY" { | ||||
| @@ -279,7 +246,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) { | ||||
| 		} | ||||
|  | ||||
| 		log.Trace("Email made primary: %s", ctx.User.Name) | ||||
| 		ctx.Redirect(setting.AppSubURL + "/user/settings/email") | ||||
| 		ctx.Redirect(setting.AppSubURL + "/user/settings/account") | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @@ -292,7 +259,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) { | ||||
| 	ctx.Data["Emails"] = emails | ||||
|  | ||||
| 	if ctx.HasError() { | ||||
| 		ctx.HTML(200, tplSettingsEmails) | ||||
| 		ctx.HTML(200, tplSettingsAccount) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @@ -303,7 +270,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) { | ||||
| 	} | ||||
| 	if err := models.AddEmailAddress(email); err != nil { | ||||
| 		if models.IsErrEmailAlreadyUsed(err) { | ||||
| 			ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSettingsEmails, &form) | ||||
| 			ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSettingsAccount, &form) | ||||
| 			return | ||||
| 		} | ||||
| 		ctx.ServerError("AddEmailAddress", err) | ||||
| @@ -323,7 +290,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) { | ||||
| 	} | ||||
|  | ||||
| 	log.Trace("Email address added: %s", email.Email) | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/email") | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/account") | ||||
| } | ||||
|  | ||||
| // DeleteEmail response for delete user's email | ||||
| @@ -336,7 +303,164 @@ func DeleteEmail(ctx *context.Context) { | ||||
|  | ||||
| 	ctx.Flash.Success(ctx.Tr("settings.email_deletion_success")) | ||||
| 	ctx.JSON(200, map[string]interface{}{ | ||||
| 		"redirect": setting.AppSubURL + "/user/settings/email", | ||||
| 		"redirect": setting.AppSubURL + "/user/settings/account", | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // SettingsDelete render user suicide page and response for delete user himself | ||||
| func SettingsDelete(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsAccount"] = true | ||||
|  | ||||
| 	if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil { | ||||
| 		if models.IsErrUserNotExist(err) { | ||||
| 			ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), tplSettingsAccount, nil) | ||||
| 		} else { | ||||
| 			ctx.ServerError("UserSignIn", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if err := models.DeleteUser(ctx.User); err != nil { | ||||
| 		switch { | ||||
| 		case models.IsErrUserOwnRepos(err): | ||||
| 			ctx.Flash.Error(ctx.Tr("form.still_own_repo")) | ||||
| 			ctx.Redirect(setting.AppSubURL + "/user/settings/account") | ||||
| 		case models.IsErrUserHasOrgs(err): | ||||
| 			ctx.Flash.Error(ctx.Tr("form.still_has_org")) | ||||
| 			ctx.Redirect(setting.AppSubURL + "/user/settings/account") | ||||
| 		default: | ||||
| 			ctx.ServerError("DeleteUser", err) | ||||
| 		} | ||||
| 	} else { | ||||
| 		log.Trace("Account deleted: %s", ctx.User.Name) | ||||
| 		ctx.Redirect(setting.AppSubURL + "/") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // SettingsSecurity render change user's password page and 2FA | ||||
| func SettingsSecurity(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsSecurity"] = true | ||||
|  | ||||
| 	enrolled := true | ||||
| 	_, err := models.GetTwoFactorByUID(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		if models.IsErrTwoFactorNotEnrolled(err) { | ||||
| 			enrolled = false | ||||
| 		} else { | ||||
| 			ctx.ServerError("SettingsTwoFactor", err) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 	ctx.Data["TwofaEnrolled"] = enrolled | ||||
|  | ||||
| 	accountLinks, err := models.ListAccountLinks(ctx.User) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("ListAccountLinks", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// map the provider display name with the LoginSource | ||||
| 	sources := make(map[*models.LoginSource]string) | ||||
| 	for _, externalAccount := range accountLinks { | ||||
| 		if loginSource, err := models.GetLoginSourceByID(externalAccount.LoginSourceID); err == nil { | ||||
| 			var providerDisplayName string | ||||
| 			if loginSource.IsOAuth2() { | ||||
| 				providerTechnicalName := loginSource.OAuth2().Provider | ||||
| 				providerDisplayName = models.OAuth2Providers[providerTechnicalName].DisplayName | ||||
| 			} else { | ||||
| 				providerDisplayName = loginSource.Name | ||||
| 			} | ||||
| 			sources[loginSource] = providerDisplayName | ||||
| 		} | ||||
| 	} | ||||
| 	ctx.Data["AccountLinks"] = sources | ||||
|  | ||||
| 	if ctx.Query("openid.return_to") != "" { | ||||
| 		settingsOpenIDVerify(ctx) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	openid, err := models.GetUserOpenIDs(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("GetUserOpenIDs", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["OpenIDs"] = openid | ||||
|  | ||||
| 	ctx.HTML(200, tplSettingsSecurity) | ||||
| } | ||||
|  | ||||
| // SettingsDeleteAccountLink delete a single account link | ||||
| func SettingsDeleteAccountLink(ctx *context.Context) { | ||||
| 	if _, err := models.RemoveAccountLink(ctx.User, ctx.QueryInt64("loginSourceID")); err != nil { | ||||
| 		ctx.Flash.Error("RemoveAccountLink: " + err.Error()) | ||||
| 	} else { | ||||
| 		ctx.Flash.Success(ctx.Tr("settings.remove_account_link_success")) | ||||
| 	} | ||||
|  | ||||
| 	ctx.JSON(200, map[string]interface{}{ | ||||
| 		"redirect": setting.AppSubURL + "/user/settings/security", | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // SettingsApplications render manage access token page | ||||
| func SettingsApplications(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsApplications"] = true | ||||
|  | ||||
| 	tokens, err := models.ListAccessTokens(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("ListAccessTokens", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Tokens"] = tokens | ||||
|  | ||||
| 	ctx.HTML(200, tplSettingsApplications) | ||||
| } | ||||
|  | ||||
| // SettingsApplicationsPost response for add user's access token | ||||
| func SettingsApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsApplications"] = true | ||||
|  | ||||
| 	if ctx.HasError() { | ||||
| 		tokens, err := models.ListAccessTokens(ctx.User.ID) | ||||
| 		if err != nil { | ||||
| 			ctx.ServerError("ListAccessTokens", err) | ||||
| 			return | ||||
| 		} | ||||
| 		ctx.Data["Tokens"] = tokens | ||||
| 		ctx.HTML(200, tplSettingsApplications) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	t := &models.AccessToken{ | ||||
| 		UID:  ctx.User.ID, | ||||
| 		Name: form.Name, | ||||
| 	} | ||||
| 	if err := models.NewAccessToken(t); err != nil { | ||||
| 		ctx.ServerError("NewAccessToken", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ctx.Flash.Success(ctx.Tr("settings.generate_token_success")) | ||||
| 	ctx.Flash.Info(t.Sha1) | ||||
|  | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/applications") | ||||
| } | ||||
|  | ||||
| // SettingsDeleteApplication response for delete user access token | ||||
| func SettingsDeleteApplication(ctx *context.Context) { | ||||
| 	if err := models.DeleteAccessTokenByID(ctx.QueryInt64("id"), ctx.User.ID); err != nil { | ||||
| 		ctx.Flash.Error("DeleteAccessTokenByID: " + err.Error()) | ||||
| 	} else { | ||||
| 		ctx.Flash.Success(ctx.Tr("settings.delete_token_success")) | ||||
| 	} | ||||
|  | ||||
| 	ctx.JSON(200, map[string]interface{}{ | ||||
| 		"redirect": setting.AppSubURL + "/user/settings/applications", | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| @@ -471,65 +595,6 @@ func DeleteKey(ctx *context.Context) { | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // SettingsApplications render user's access tokens page | ||||
| func SettingsApplications(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsApplications"] = true | ||||
|  | ||||
| 	tokens, err := models.ListAccessTokens(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("ListAccessTokens", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Tokens"] = tokens | ||||
|  | ||||
| 	ctx.HTML(200, tplSettingsApplications) | ||||
| } | ||||
|  | ||||
| // SettingsApplicationsPost response for add user's access token | ||||
| func SettingsApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsApplications"] = true | ||||
|  | ||||
| 	if ctx.HasError() { | ||||
| 		tokens, err := models.ListAccessTokens(ctx.User.ID) | ||||
| 		if err != nil { | ||||
| 			ctx.ServerError("ListAccessTokens", err) | ||||
| 			return | ||||
| 		} | ||||
| 		ctx.Data["Tokens"] = tokens | ||||
| 		ctx.HTML(200, tplSettingsApplications) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	t := &models.AccessToken{ | ||||
| 		UID:  ctx.User.ID, | ||||
| 		Name: form.Name, | ||||
| 	} | ||||
| 	if err := models.NewAccessToken(t); err != nil { | ||||
| 		ctx.ServerError("NewAccessToken", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ctx.Flash.Success(ctx.Tr("settings.generate_token_success")) | ||||
| 	ctx.Flash.Info(t.Sha1) | ||||
|  | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/applications") | ||||
| } | ||||
|  | ||||
| // SettingsDeleteApplication response for delete user access token | ||||
| func SettingsDeleteApplication(ctx *context.Context) { | ||||
| 	if err := models.DeleteAccessTokenByID(ctx.QueryInt64("id"), ctx.User.ID); err != nil { | ||||
| 		ctx.Flash.Error("DeleteAccessTokenByID: " + err.Error()) | ||||
| 	} else { | ||||
| 		ctx.Flash.Success(ctx.Tr("settings.delete_token_success")) | ||||
| 	} | ||||
|  | ||||
| 	ctx.JSON(200, map[string]interface{}{ | ||||
| 		"redirect": setting.AppSubURL + "/user/settings/applications", | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // SettingsTwoFactorRegenerateScratch regenerates the user's 2FA scratch code. | ||||
| func SettingsTwoFactorRegenerateScratch(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| @@ -695,86 +760,6 @@ func SettingsTwoFactorEnrollPost(ctx *context.Context, form auth.TwoFactorAuthFo | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/security") | ||||
| } | ||||
|  | ||||
| // SettingsAccountLinks render the account links settings page | ||||
| func SettingsAccountLinks(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsAccountLink"] = true | ||||
|  | ||||
| 	accountLinks, err := models.ListAccountLinks(ctx.User) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("ListAccountLinks", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// map the provider display name with the LoginSource | ||||
| 	sources := make(map[*models.LoginSource]string) | ||||
| 	for _, externalAccount := range accountLinks { | ||||
| 		if loginSource, err := models.GetLoginSourceByID(externalAccount.LoginSourceID); err == nil { | ||||
| 			var providerDisplayName string | ||||
| 			if loginSource.IsOAuth2() { | ||||
| 				providerTechnicalName := loginSource.OAuth2().Provider | ||||
| 				providerDisplayName = models.OAuth2Providers[providerTechnicalName].DisplayName | ||||
| 			} else { | ||||
| 				providerDisplayName = loginSource.Name | ||||
| 			} | ||||
| 			sources[loginSource] = providerDisplayName | ||||
| 		} | ||||
| 	} | ||||
| 	ctx.Data["AccountLinks"] = sources | ||||
|  | ||||
| 	ctx.HTML(200, tplSettingsAccountLink) | ||||
| } | ||||
|  | ||||
| // SettingsDeleteAccountLink delete a single account link | ||||
| func SettingsDeleteAccountLink(ctx *context.Context) { | ||||
| 	if _, err := models.RemoveAccountLink(ctx.User, ctx.QueryInt64("loginSourceID")); err != nil { | ||||
| 		ctx.Flash.Error("RemoveAccountLink: " + err.Error()) | ||||
| 	} else { | ||||
| 		ctx.Flash.Success(ctx.Tr("settings.remove_account_link_success")) | ||||
| 	} | ||||
|  | ||||
| 	ctx.JSON(200, map[string]interface{}{ | ||||
| 		"redirect": setting.AppSubURL + "/user/settings/account_link", | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // SettingsDelete render user suicide page and response for delete user himself | ||||
| func SettingsDelete(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsDelete"] = true | ||||
| 	ctx.Data["Email"] = ctx.User.Email | ||||
|  | ||||
| 	if ctx.Req.Method == "POST" { | ||||
| 		if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil { | ||||
| 			if models.IsErrUserNotExist(err) { | ||||
| 				ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), tplSettingsDelete, nil) | ||||
| 			} else { | ||||
| 				ctx.ServerError("UserSignIn", err) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
|  | ||||
| 		if err := models.DeleteUser(ctx.User); err != nil { | ||||
| 			switch { | ||||
| 			case models.IsErrUserOwnRepos(err): | ||||
| 				ctx.Flash.Error(ctx.Tr("form.still_own_repo")) | ||||
| 				ctx.Redirect(setting.AppSubURL + "/user/settings/delete") | ||||
| 			case models.IsErrUserHasOrgs(err): | ||||
| 				ctx.Flash.Error(ctx.Tr("form.still_has_org")) | ||||
| 				ctx.Redirect(setting.AppSubURL + "/user/settings/delete") | ||||
| 			default: | ||||
| 				ctx.ServerError("DeleteUser", err) | ||||
| 			} | ||||
| 		} else { | ||||
| 			log.Trace("Account deleted: %s", ctx.User.Name) | ||||
| 			ctx.Redirect(setting.AppSubURL + "/") | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ctx.HTML(200, tplSettingsDelete) | ||||
| } | ||||
|  | ||||
| // SettingsOrganization render all the organization of the user | ||||
| func SettingsOrganization(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
|   | ||||
| @@ -8,40 +8,15 @@ import ( | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/modules/auth" | ||||
| 	"code.gitea.io/gitea/modules/auth/openid" | ||||
| 	"code.gitea.io/gitea/modules/base" | ||||
| 	"code.gitea.io/gitea/modules/context" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/setting" | ||||
| ) | ||||
|  | ||||
| const ( | ||||
| 	tplSettingsOpenID base.TplName = "user/settings/openid" | ||||
| ) | ||||
|  | ||||
| // SettingsOpenID renders change user's openid page | ||||
| func SettingsOpenID(ctx *context.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsOpenID"] = true | ||||
|  | ||||
| 	if ctx.Query("openid.return_to") != "" { | ||||
| 		settingsOpenIDVerify(ctx) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	openid, err := models.GetUserOpenIDs(ctx.User.ID) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("GetUserOpenIDs", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["OpenIDs"] = openid | ||||
|  | ||||
| 	ctx.HTML(200, tplSettingsOpenID) | ||||
| } | ||||
|  | ||||
| // SettingsOpenIDPost response for change user's openid | ||||
| func SettingsOpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("settings") | ||||
| 	ctx.Data["PageIsSettingsOpenID"] = true | ||||
| 	ctx.Data["PageIsSettingsSecurity"] = true | ||||
|  | ||||
| 	if ctx.HasError() { | ||||
| 		openid, err := models.GetUserOpenIDs(ctx.User.ID) | ||||
| @@ -50,7 +25,7 @@ func SettingsOpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) { | ||||
| 			return | ||||
| 		} | ||||
| 		ctx.Data["OpenIDs"] = openid | ||||
| 		ctx.HTML(200, tplSettingsOpenID) | ||||
| 		ctx.HTML(200, tplSettingsSecurity) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| @@ -62,7 +37,7 @@ func SettingsOpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) { | ||||
|  | ||||
| 	id, err := openid.Normalize(form.Openid) | ||||
| 	if err != nil { | ||||
| 		ctx.RenderWithErr(err.Error(), tplSettingsOpenID, &form) | ||||
| 		ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &form) | ||||
| 		return | ||||
| 	} | ||||
| 	form.Openid = id | ||||
| @@ -78,15 +53,15 @@ func SettingsOpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) { | ||||
| 	// Check that the OpenID is not already used | ||||
| 	for _, obj := range oids { | ||||
| 		if obj.URI == id { | ||||
| 			ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsOpenID, &form) | ||||
| 			ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsSecurity, &form) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	redirectTo := setting.AppURL + "user/settings/openid" | ||||
| 	redirectTo := setting.AppURL + "user/settings/security" | ||||
| 	url, err := openid.RedirectURL(id, redirectTo, setting.AppURL) | ||||
| 	if err != nil { | ||||
| 		ctx.RenderWithErr(err.Error(), tplSettingsOpenID, &form) | ||||
| 		ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &form) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Redirect(url) | ||||
| @@ -107,7 +82,7 @@ func settingsOpenIDVerify(ctx *context.Context) { | ||||
|  | ||||
| 	id, err := openid.Verify(fullURL) | ||||
| 	if err != nil { | ||||
| 		ctx.RenderWithErr(err.Error(), tplSettingsOpenID, &auth.AddOpenIDForm{ | ||||
| 		ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &auth.AddOpenIDForm{ | ||||
| 			Openid: id, | ||||
| 		}) | ||||
| 		return | ||||
| @@ -118,7 +93,7 @@ func settingsOpenIDVerify(ctx *context.Context) { | ||||
| 	oid := &models.UserOpenID{UID: ctx.User.ID, URI: id} | ||||
| 	if err = models.AddUserOpenID(oid); err != nil { | ||||
| 		if models.IsErrOpenIDAlreadyUsed(err) { | ||||
| 			ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsOpenID, &auth.AddOpenIDForm{Openid: id}) | ||||
| 			ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsSecurity, &auth.AddOpenIDForm{Openid: id}) | ||||
| 			return | ||||
| 		} | ||||
| 		ctx.ServerError("AddUserOpenID", err) | ||||
| @@ -127,7 +102,7 @@ func settingsOpenIDVerify(ctx *context.Context) { | ||||
| 	log.Trace("Associated OpenID %s to user %s", id, ctx.User.Name) | ||||
| 	ctx.Flash.Success(ctx.Tr("settings.add_openid_success")) | ||||
|  | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/openid") | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/security") | ||||
| } | ||||
|  | ||||
| // DeleteOpenID response for delete user's openid | ||||
| @@ -140,7 +115,7 @@ func DeleteOpenID(ctx *context.Context) { | ||||
|  | ||||
| 	ctx.Flash.Success(ctx.Tr("settings.openid_deletion_success")) | ||||
| 	ctx.JSON(200, map[string]interface{}{ | ||||
| 		"redirect": setting.AppSubURL + "/user/settings/openid", | ||||
| 		"redirect": setting.AppSubURL + "/user/settings/security", | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| @@ -151,5 +126,5 @@ func ToggleOpenIDVisibility(ctx *context.Context) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/openid") | ||||
| 	ctx.Redirect(setting.AppSubURL + "/user/settings/security") | ||||
| } | ||||
|   | ||||
| @@ -56,7 +56,7 @@ func TestChangePassword(t *testing.T) { | ||||
| 		test.LoadUser(t, ctx, 2) | ||||
| 		test.LoadRepo(t, ctx, 1) | ||||
|  | ||||
| 		SettingsSecurityPost(ctx, auth.ChangePasswordForm{ | ||||
| 		SettingsAccountPost(ctx, auth.ChangePasswordForm{ | ||||
| 			OldPassword: req.OldPassword, | ||||
| 			Password:    req.NewPassword, | ||||
| 			Retype:      req.Retype, | ||||
|   | ||||
| @@ -5,7 +5,7 @@ | ||||
| 			<div class="ui five wide column"> | ||||
| 				<div class="ui card"> | ||||
| 					{{if eq .SignedUserName .Owner.Name}} | ||||
| 						<a class="image poping up" href="{{AppSubUrl}}/user/settings/avatar" id="profile-avatar" data-content="{{.i18n.Tr "user.change_avatar"}}" data-variation="inverted tiny" data-position="bottom center"> | ||||
| 						<a class="image poping up" href="{{AppSubUrl}}/user/settings" id="profile-avatar" data-content="{{.i18n.Tr "user.change_avatar"}}" data-variation="inverted tiny" data-position="bottom center"> | ||||
| 							<img src="{{.Owner.SizedRelAvatarLink 290}}" title="{{.Owner.Name}}"/> | ||||
| 						</a> | ||||
| 					{{else}} | ||||
|   | ||||
							
								
								
									
										135
									
								
								templates/user/settings/account.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								templates/user/settings/account.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,135 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings account"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.password"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
| 			{{if or (.SignedUser.IsLocal) (.SignedUser.IsOAuth2)}} | ||||
| 			<form class="ui form" action="{{.Link}}?tp=password" method="post"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				{{if .SignedUser.IsPasswordSet}} | ||||
| 				<div class="required field {{if .Err_OldPassword}}error{{end}}"> | ||||
| 					<label for="old_password">{{.i18n.Tr "settings.old_password"}}</label> | ||||
| 					<input id="old_password" name="old_password" type="password" autocomplete="off" autofocus required> | ||||
| 				</div> | ||||
| 				{{end}} | ||||
| 				<div class="required field {{if .Err_Password}}error{{end}}"> | ||||
| 					<label for="password">{{.i18n.Tr "settings.new_password"}}</label> | ||||
| 					<input id="password" name="password" type="password" autocomplete="off" required> | ||||
| 				</div> | ||||
| 				<div class="required field {{if .Err_Password}}error{{end}}"> | ||||
| 					<label for="retype">{{.i18n.Tr "settings.retype_new_password"}}</label> | ||||
| 					<input id="retype" name="retype" type="password" autocomplete="off" required> | ||||
| 				</div> | ||||
|  | ||||
| 				<div class="field"> | ||||
| 					<button class="ui green button">{{$.i18n.Tr "settings.change_password"}}</button> | ||||
| 					<a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.i18n.Tr "auth.forgot_password"}}</a> | ||||
| 				</div> | ||||
| 			</form> | ||||
| 			{{else}} | ||||
| 			<div class="ui info message"> | ||||
| 				<p class="text left">{{$.i18n.Tr "settings.password_change_disabled"}}</p> | ||||
| 			</div> | ||||
| 			{{end}} | ||||
| 		</div> | ||||
|  | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.manage_emails"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
| 			<div class="ui email list"> | ||||
| 				<div class="item"> | ||||
| 					{{.i18n.Tr "settings.email_desc"}} | ||||
| 				</div> | ||||
| 				{{range .Emails}} | ||||
| 					<div class="item"> | ||||
| 						{{if not .IsPrimary}} | ||||
| 							<div class="right floated content"> | ||||
| 								<button class="ui red tiny button delete-button" id="delete-email" data-url="{{$.Link}}/email/delete" data-id="{{.ID}}"> | ||||
| 									{{$.i18n.Tr "settings.delete_email"}} | ||||
| 								</button> | ||||
| 							</div> | ||||
| 							{{if .IsActivated}} | ||||
| 								<div class="right floated content"> | ||||
| 									<form action="{{$.Link}}/email" method="post"> | ||||
| 										{{$.CsrfTokenHtml}} | ||||
| 										<input name="_method" type="hidden" value="PRIMARY"> | ||||
| 										<input name="id" type="hidden" value="{{.ID}}"> | ||||
| 										<button class="ui blue tiny button">{{$.i18n.Tr "settings.primary_email"}}</button> | ||||
| 									</form> | ||||
| 								</div> | ||||
| 							{{end}} | ||||
| 						{{end}} | ||||
| 						<div class="content"> | ||||
| 							<strong>{{.Email}}</strong> | ||||
| 							{{if .IsPrimary}}<span class="text red">{{$.i18n.Tr "settings.primary"}}</span>{{end}} | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				{{end}} | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="ui attached bottom segment"> | ||||
| 			<form class="ui form" action="{{.Link}}/email" method="post"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				<div class="required field {{if .Err_Email}}error{{end}}"> | ||||
| 					<label for="email">{{.i18n.Tr "settings.add_new_email"}}</label> | ||||
| 					<input id="email" name="email" type="email" required> | ||||
| 				</div> | ||||
| 				<button class="ui green button"> | ||||
| 					{{.i18n.Tr "settings.add_email"}} | ||||
| 				</button> | ||||
| 			</form> | ||||
| 		</div> | ||||
|  | ||||
| 		<h4 class="ui top attached warning header"> | ||||
| 			{{.i18n.Tr "settings.delete_account"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached warning segment"> | ||||
| 			<div class="ui red message"> | ||||
| 				<p class="text left"><i class="octicon octicon-alert"></i> {{.i18n.Tr "settings.delete_prompt" | Str2html}}</p> | ||||
| 			</div> | ||||
| 			<form class="ui form ignore-dirty" id="delete-form" action="{{.Link}}/delete" method="post"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				<input class="fake" type="password"> | ||||
| 				<div class="required field {{if .Err_Password}}error{{end}}"> | ||||
| 					<label for="password-confirmation">{{.i18n.Tr "password"}}</label> | ||||
| 					<input id="password-confirmation" name="password" type="password" required> | ||||
| 				</div> | ||||
| 				<div class="field"> | ||||
| 					<div class="ui red button delete-button" id="delete-account" data-type="form" data-form="#delete-form"> | ||||
| 						{{.i18n.Tr "settings.confirm_delete_account"}} | ||||
| 					</div> | ||||
| 					<a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.i18n.Tr "auth.forgot_password"}}</a> | ||||
| 				</div> | ||||
| 			</form> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal" id="delete-email"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.email_deletion"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.email_deletion_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal" id="delete-account"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.delete_account_title"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.delete_account_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
|  | ||||
| {{template "base/footer" .}} | ||||
| @@ -1,44 +0,0 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings account_link"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.manage_account_links"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
| 			<div class="ui key list"> | ||||
| 				<div class="item"> | ||||
| 					{{.i18n.Tr "settings.manage_account_links_desc"}} | ||||
| 				</div> | ||||
| 				{{if .AccountLinks}} | ||||
| 				{{range $loginSource, $provider := .AccountLinks}} | ||||
| 					<div class="item"> | ||||
| 					    <div class="right floated content"> | ||||
| 								<button class="ui red tiny button delete-button" data-url="{{$.Link}}" data-id="{{$loginSource.ID}}"> | ||||
| 									{{$.i18n.Tr "settings.delete_key"}} | ||||
| 								</button> | ||||
| 					    </div> | ||||
| 							<div class="content"> | ||||
| 								<strong>{{$provider}}</strong> | ||||
| 								{{if $loginSource.IsActived}}<span class="text red">{{$.i18n.Tr "settings.active"}}</span>{{end}} | ||||
| 							</div> | ||||
| 					</div> | ||||
| 				{{end}} | ||||
| 				{{end}} | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.remove_account_link"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.remove_account_link_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
| @@ -1,8 +1,7 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings"> | ||||
| <div class="user settings applications"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.manage_access_token"}} | ||||
| 		</h4> | ||||
| @@ -13,26 +12,26 @@ | ||||
| 				</div> | ||||
| 				{{range .Tokens}} | ||||
| 					<div class="item"> | ||||
| 					    <div class="right floated content"> | ||||
| 								<button class="ui red tiny button delete-button" data-url="{{$.Link}}/delete" data-id="{{.ID}}"> | ||||
| 						<div class="right floated content"> | ||||
| 								<button class="ui red tiny button delete-button" id="delete-token" data-url="{{$.Link}}/delete" data-id="{{.ID}}"> | ||||
| 									{{$.i18n.Tr "settings.delete_token"}} | ||||
| 								</button> | ||||
| 					    </div> | ||||
| 							<i class="big send icon {{if .HasRecentActivity}}green{{end}}" {{if .HasRecentActivity}}data-content="{{$.i18n.Tr "settings.token_state_desc"}}" data-variation="inverted tiny"{{end}}></i> | ||||
| 							<div class="content"> | ||||
| 								<strong>{{.Name}}</strong> | ||||
| 								<div class="activity meta"> | ||||
| 									<i>{{$.i18n.Tr "settings.add_on"}} <span>{{.CreatedUnix.FormatShort}}</span> —  <i class="octicon octicon-info"></i> {{if .HasUsed}}{{$.i18n.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}>{{.UpdatedUnix.FormatShort}}</span>{{else}}{{$.i18n.Tr "settings.no_activity"}}{{end}}</i> | ||||
| 								</div> | ||||
| 						</div> | ||||
| 						<i class="big send icon {{if .HasRecentActivity}}green{{end}}" {{if .HasRecentActivity}}data-content="{{$.i18n.Tr "settings.token_state_desc"}}" data-variation="inverted tiny"{{end}}></i> | ||||
| 						<div class="content"> | ||||
| 							<strong>{{.Name}}</strong> | ||||
| 							<div class="activity meta"> | ||||
| 								<i>{{$.i18n.Tr "settings.add_on"}} <span>{{.CreatedUnix.FormatShort}}</span> —  <i class="octicon octicon-info"></i> {{if .HasUsed}}{{$.i18n.Tr "settings.last_used"}} <span {{if .HasRecentActivity}}class="green"{{end}}>{{.UpdatedUnix.FormatShort}}</span>{{else}}{{$.i18n.Tr "settings.no_activity"}}{{end}}</i> | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				{{end}} | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.generate_new_token"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
| 		<div class="ui attached bottom segment"> | ||||
| 			<h5 class="ui top header"> | ||||
| 				{{.i18n.Tr "settings.generate_new_token"}} | ||||
| 			</h5> | ||||
| 			<p>{{.i18n.Tr "settings.new_token_desc"}}</p> | ||||
| 			<form class="ui form ignore-dirty" action="{{.Link}}" method="post"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| @@ -48,7 +47,7 @@ | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal"> | ||||
| <div class="ui small basic delete modal" id="delete-token"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.access_token_deletion"}} | ||||
| @@ -67,4 +66,6 @@ | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
|  | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
| @@ -1,46 +0,0 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings avatar"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.avatar"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
|  | ||||
| 			<form class="ui form" action="{{.Link}}" method="post" enctype="multipart/form-data"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				{{if not DisableGravatar}} | ||||
| 				<div class="inline field"> | ||||
| 					<div class="ui radio checkbox"> | ||||
| 						<input name="source" value="lookup" type="radio" {{if not .SignedUser.UseCustomAvatar}}checked{{end}}> | ||||
| 						<label>{{.i18n.Tr "settings.lookup_avatar_by_mail"}}</label> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<div class="field {{if .Err_Gravatar}}error{{end}}"> | ||||
| 					<label for="gravatar">Avatar {{.i18n.Tr "email"}}</label> | ||||
| 					<input id="gravatar" name="gravatar" value="{{.SignedUser.AvatarEmail}}" /> | ||||
| 				</div> | ||||
| 				{{end}} | ||||
|  | ||||
| 				<div class="inline field"> | ||||
| 					<div class="ui radio checkbox"> | ||||
| 						<input name="source" value="local" type="radio" {{if .SignedUser.UseCustomAvatar}}checked{{end}}> | ||||
| 						<label>{{.i18n.Tr "settings.enable_custom_avatar"}}</label> | ||||
| 					</div> | ||||
| 				</div> | ||||
|  | ||||
| 				<div class="inline field"> | ||||
| 					<label for="avatar">{{.i18n.Tr "settings.choose_new_avatar"}}</label> | ||||
| 					<input name="avatar" type="file" > | ||||
| 				</div> | ||||
|  | ||||
| 				<div class="field"> | ||||
| 					<button class="ui green button">{{$.i18n.Tr "settings.update_avatar"}}</button> | ||||
| 					<a class="ui red button delete-post" data-request-url="{{.Link}}/delete" data-done-url="{{.Link}}">{{$.i18n.Tr "settings.delete_current_avatar"}}</a> | ||||
| 				</div> | ||||
| 			</form> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
| @@ -1,41 +0,0 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings delete"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
| 		<h4 class="ui top attached warning header"> | ||||
| 			{{.i18n.Tr "settings.delete_account"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached warning segment"> | ||||
| 			<div class="ui red message"> | ||||
| 				<p class="text left"><i class="octicon octicon-alert"></i> {{.i18n.Tr "settings.delete_prompt" | Str2html}}</p> | ||||
| 			</div> | ||||
| 			<form class="ui form ignore-dirty" id="delete-form" action="{{.Link}}" method="post"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				<input class="fake" type="password"> | ||||
| 				<div class="required field {{if .Err_Password}}error{{end}}"> | ||||
| 					<label for="password">{{.i18n.Tr "password"}}</label> | ||||
| 					<input id="password" name="password" type="password" autofocus required> | ||||
| 				</div> | ||||
| 				<div class="field"> | ||||
| 					<div class="ui red button delete-button" data-type="form" data-form="#delete-form"> | ||||
| 						{{.i18n.Tr "settings.confirm_delete_account"}} | ||||
| 					</div> | ||||
| 					<a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.i18n.Tr "auth.forgot_password"}}</a> | ||||
| 				</div> | ||||
| 			</form> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.delete_account_title"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.delete_account_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
| @@ -1,66 +0,0 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings emails"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.manage_emails"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
| 			<div class="ui email list"> | ||||
| 				<div class="item"> | ||||
| 					{{.i18n.Tr "settings.email_desc"}} | ||||
| 				</div> | ||||
| 				{{range .Emails}} | ||||
| 					<div class="item"> | ||||
| 						{{if not .IsPrimary}} | ||||
| 							<div class="right floated content"> | ||||
| 								<button class="ui red tiny button delete-button" data-url="{{$.Link}}/delete" data-id="{{.ID}}"> | ||||
| 									{{$.i18n.Tr "settings.delete_email"}} | ||||
| 								</button> | ||||
| 							</div> | ||||
| 							{{if .IsActivated}} | ||||
| 								<div class="right floated content"> | ||||
| 									<form action="{{$.Link}}" method="post"> | ||||
| 										{{$.CsrfTokenHtml}} | ||||
| 										<input name="_method" type="hidden" value="PRIMARY"> | ||||
| 										<input name="id" type="hidden" value="{{.ID}}"> | ||||
| 										<button class="ui blue tiny button">{{$.i18n.Tr "settings.primary_email"}}</button> | ||||
| 									</form> | ||||
| 								</div> | ||||
| 							{{end}} | ||||
| 						{{end}} | ||||
| 						<div class="content"> | ||||
| 							<strong>{{.Email}}</strong> | ||||
| 							{{if .IsPrimary}}<span class="text red">{{$.i18n.Tr "settings.primary"}}</span>{{end}} | ||||
| 						</div> | ||||
| 					</div> | ||||
| 				{{end}} | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="ui attached bottom segment"> | ||||
| 			<form class="ui form" action="{{.Link}}" method="post"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				<div class="required field {{if .Err_Email}}error{{end}}"> | ||||
| 					<label for="email">{{.i18n.Tr "settings.add_new_email"}}</label> | ||||
| 					<input id="email" name="email" type="email" autofocus required> | ||||
| 				</div> | ||||
| 				<button class="ui green button"> | ||||
| 					{{.i18n.Tr "settings.add_email"}} | ||||
| 				</button> | ||||
| 			</form> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.email_deletion"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.email_deletion_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
| @@ -2,28 +2,17 @@ | ||||
| 	<a class="{{if .PageIsSettingsProfile}}active{{end}} item" href="{{AppSubUrl}}/user/settings"> | ||||
| 		{{.i18n.Tr "settings.profile"}} | ||||
| 	</a> | ||||
| 	<a class="{{if .PageIsSettingsAvatar}}active{{end}} item" href="{{AppSubUrl}}/user/settings/avatar"> | ||||
| 		{{.i18n.Tr "settings.avatar"}} | ||||
| 	<a class="{{if .PageIsSettingsAccount}}active{{end}} item" href="{{AppSubUrl}}/user/settings/account"> | ||||
| 		{{.i18n.Tr "settings.account"}} | ||||
| 	</a> | ||||
| 	<a class="{{if .PageIsSettingsSecurity}}active{{end}} item" href="{{AppSubUrl}}/user/settings/security"> | ||||
| 		{{.i18n.Tr "settings.security"}} | ||||
| 	</a> | ||||
| 	<a class="{{if .PageIsSettingsEmails}}active{{end}} item" href="{{AppSubUrl}}/user/settings/email"> | ||||
| 		{{.i18n.Tr "settings.emails"}} | ||||
| 	</a> | ||||
| 	{{if .EnableOpenIDSignIn}} | ||||
| 		<a class="{{if .PageIsSettingsOpenID}}active{{end}} item" href="{{AppSubUrl}}/user/settings/openid"> | ||||
| 			OpenID | ||||
| 		</a> | ||||
| 	{{end}} | ||||
| 	<a class="{{if .PageIsSettingsKeys}}active{{end}} item" href="{{AppSubUrl}}/user/settings/keys"> | ||||
| 		{{.i18n.Tr "settings.ssh_gpg_keys"}} | ||||
| 	</a> | ||||
| 	<a class="{{if .PageIsSettingsApplications}}active{{end}} item" href="{{AppSubUrl}}/user/settings/applications"> | ||||
| 		{{.i18n.Tr "settings.applications"}} | ||||
| 	</a> | ||||
| 	<a class="{{if .PageIsSettingsAccountLink}}active{{end}} item" href="{{AppSubUrl}}/user/settings/account_link"> | ||||
| 		{{.i18n.Tr "settings.account_link"}} | ||||
| 	<a class="{{if .PageIsSettingsKeys}}active{{end}} item" href="{{AppSubUrl}}/user/settings/keys"> | ||||
| 		{{.i18n.Tr "settings.ssh_gpg_keys"}} | ||||
| 	</a> | ||||
| 	<a class="{{if .PageIsSettingsOrganization}}active{{end}} item" href="{{AppSubUrl}}/user/settings/organization"> | ||||
| 		{{.i18n.Tr "settings.organization"}} | ||||
| @@ -31,7 +20,4 @@ | ||||
| 	<a class="{{if .PageIsSettingsRepos}}active{{end}} item" href="{{AppSubUrl}}/user/settings/repos"> | ||||
| 		{{.i18n.Tr "settings.repos"}} | ||||
| 	</a> | ||||
| 	<a class="{{if .PageIsSettingsDelete}}active{{end}} item" href="{{AppSubUrl}}/user/settings/delete"> | ||||
| 		{{.i18n.Tr "settings.delete"}} | ||||
| 	</a> | ||||
| </div> | ||||
|   | ||||
| @@ -1,71 +0,0 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings openid"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.manage_openid"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
| 			<div class="ui openid list"> | ||||
| 				<div class="item"> | ||||
| 					{{.i18n.Tr "settings.openid_desc"}} | ||||
| 				</div> | ||||
| 				{{range .OpenIDs}} | ||||
| 					<div class="item"> | ||||
| 					    <div class="right floated content"> | ||||
| 								<button class="ui red tiny button delete-button" data-url="{{$.Link}}/delete" data-id="{{.ID}}"> | ||||
| 									{{$.i18n.Tr "settings.delete_key"}} | ||||
| 								</button> | ||||
| 					    </div> | ||||
| 							<div class="right floated content"> | ||||
| 								<form action="{{$.Link}}/toggle_visibility" method="post"> | ||||
| 								{{$.CsrfTokenHtml}} | ||||
| 								<input name="id" type="hidden" value="{{.ID}}"> | ||||
| 								{{if .Show}} | ||||
| 									<button class="ui tiny button"> | ||||
| 									<i class="icon fa-eye"></i> | ||||
| 									{{$.i18n.Tr "settings.hide_openid"}} | ||||
| 									</button> | ||||
| 								{{else}} | ||||
| 									<button class="ui tiny button"> | ||||
| 									<i class="icon fa-eye-slash"></i> | ||||
| 									{{$.i18n.Tr "settings.show_openid"}} | ||||
| 									</button> | ||||
| 								{{end}} | ||||
| 								</button> | ||||
| 								</form> | ||||
| 							</div> | ||||
| 							<div class="content"> | ||||
| 								<strong>{{.URI}}</strong> | ||||
| 							</div> | ||||
| 					</div> | ||||
| 				{{end}} | ||||
| 			</div> | ||||
| 		</div> | ||||
| 		<div class="ui attached bottom segment"> | ||||
| 			<form class="ui form" action="{{.Link}}" method="post"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				<div class="required field {{if .Err_OpenID}}error{{end}}"> | ||||
| 					<label for="openid">{{.i18n.Tr "settings.add_new_openid"}}</label> | ||||
| 					<input id="openid" name="openid" type="text" autofocus required> | ||||
| 				</div> | ||||
| 				<button class="ui green button"> | ||||
| 					{{.i18n.Tr "settings.add_openid"}} | ||||
| 				</button> | ||||
| 			</form> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.openid_deletion"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.openid_deletion_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
| @@ -1,5 +1,5 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings account_link"> | ||||
| <div class="user settings organization"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
|   | ||||
| @@ -58,7 +58,44 @@ | ||||
| 					<button class="ui green button">{{$.i18n.Tr "settings.update_profile"}}</button> | ||||
| 				</div> | ||||
| 			</form> | ||||
| 		</div> | ||||
|  | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.avatar"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
| 			<form class="ui form" action="{{.Link}}/avatar" method="post" enctype="multipart/form-data"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				{{if not DisableGravatar}} | ||||
| 				<div class="inline field"> | ||||
| 					<div class="ui radio checkbox"> | ||||
| 						<input name="source" value="lookup" type="radio" {{if not .SignedUser.UseCustomAvatar}}checked{{end}}> | ||||
| 						<label>{{.i18n.Tr "settings.lookup_avatar_by_mail"}}</label> | ||||
| 					</div> | ||||
| 				</div> | ||||
| 				<div class="field {{if .Err_Gravatar}}error{{end}}"> | ||||
| 					<label for="gravatar">Avatar {{.i18n.Tr "email"}}</label> | ||||
| 					<input id="gravatar" name="gravatar" value="{{.SignedUser.AvatarEmail}}" /> | ||||
| 				</div> | ||||
| 				{{end}} | ||||
|  | ||||
| 				<div class="inline field"> | ||||
| 					<div class="ui radio checkbox"> | ||||
| 						<input name="source" value="local" type="radio" {{if .SignedUser.UseCustomAvatar}}checked{{end}}> | ||||
| 						<label>{{.i18n.Tr "settings.enable_custom_avatar"}}</label> | ||||
| 					</div> | ||||
| 				</div> | ||||
|  | ||||
| 				<div class="inline field"> | ||||
| 					<label for="avatar">{{.i18n.Tr "settings.choose_new_avatar"}}</label> | ||||
| 					<input name="avatar" type="file" > | ||||
| 				</div> | ||||
|  | ||||
| 				<div class="field"> | ||||
| 					<button class="ui green button">{{$.i18n.Tr "settings.update_avatar"}}</button> | ||||
| 					<a class="ui red button delete-post" data-request-url="{{.Link}}/avatar/delete" data-done-url="{{.Link}}">{{$.i18n.Tr "settings.delete_current_avatar"}}</a> | ||||
| 				</div> | ||||
| 			</form> | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings"> | ||||
| <div class="user settings repos"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
|   | ||||
| @@ -1,79 +1,14 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings password"> | ||||
| <div class="user settings security"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.password"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
| 			{{if or (.SignedUser.IsLocal) (.SignedUser.IsOAuth2)}} | ||||
| 			<form class="ui form" action="{{.Link}}?tp=password" method="post"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				{{if .SignedUser.IsPasswordSet}} | ||||
| 				<div class="required field {{if .Err_OldPassword}}error{{end}}"> | ||||
| 					<label for="old_password">{{.i18n.Tr "settings.old_password"}}</label> | ||||
| 					<input id="old_password" name="old_password" type="password" autocomplete="off" autofocus required> | ||||
| 				</div> | ||||
| 				{{end}} | ||||
| 				<div class="required field {{if .Err_Password}}error{{end}}"> | ||||
| 					<label for="password">{{.i18n.Tr "settings.new_password"}}</label> | ||||
| 					<input id="password" name="password" type="password" autocomplete="off" required> | ||||
| 				</div> | ||||
| 				<div class="required field {{if .Err_Password}}error{{end}}"> | ||||
| 					<label for="retype">{{.i18n.Tr "settings.retype_new_password"}}</label> | ||||
| 					<input id="retype" name="retype" type="password" autocomplete="off" required> | ||||
| 				</div> | ||||
|  | ||||
| 				<div class="field"> | ||||
| 					<button class="ui green button">{{$.i18n.Tr "settings.change_password"}}</button> | ||||
| 					<a href="{{AppSubUrl}}/user/forgot_password?email={{.Email}}">{{.i18n.Tr "auth.forgot_password"}}</a> | ||||
| 				</div> | ||||
| 			</form> | ||||
| 			{{else}} | ||||
| 			<div class="ui info message"> | ||||
| 				<p class="text left">{{$.i18n.Tr "settings.password_change_disabled"}}</p> | ||||
| 			</div> | ||||
| 			{{end}} | ||||
| 		</div> | ||||
| 		<br/> | ||||
|  | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.twofa"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
| 			<p>{{.i18n.Tr "settings.twofa_desc"}}</p> | ||||
| 			{{if .TwofaEnrolled}} | ||||
| 			<p>{{$.i18n.Tr "settings.twofa_is_enrolled" | Str2html }}</p> | ||||
| 			<form class="ui form" action="{{.Link}}/two_factor/regenerate_scratch" method="post" enctype="multipart/form-data"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				<p>{{.i18n.Tr "settings.regenerate_scratch_token_desc"}}</p> | ||||
| 				<button class="ui blue button">{{$.i18n.Tr "settings.twofa_scratch_token_regenerate"}}</button> | ||||
| 			</form> | ||||
| 			<form class="ui form" action="{{.Link}}/two_factor/disable" method="post" enctype="multipart/form-data" id="disable-form"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				<p>{{.i18n.Tr "settings.twofa_disable_note"}}</p> | ||||
| 				<div class="ui red button delete-button" data-type="form" data-form="#disable-form">{{$.i18n.Tr "settings.twofa_disable"}}</div> | ||||
| 			</form> | ||||
| 			{{else}} | ||||
| 			<p>{{.i18n.Tr "settings.twofa_not_enrolled"}}</p> | ||||
| 			<div class="inline field"> | ||||
| 				<a class="ui green button" href="{{.Link}}/two_factor/enroll">{{$.i18n.Tr "settings.twofa_enroll"}}</a> | ||||
| 			</div> | ||||
| 			{{end}} | ||||
| 		</div> | ||||
| 		{{template "user/settings/security_twofa" .}} | ||||
| 		{{template "user/settings/security_accountlinks" .}} | ||||
| 		{{if .EnableOpenIDSignIn}} | ||||
| 		{{template "user/settings/security_openid" .}} | ||||
| 		{{end}} | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.twofa_disable"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.twofa_disable_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
|  | ||||
| {{template "base/footer" .}} | ||||
|   | ||||
							
								
								
									
										36
									
								
								templates/user/settings/security_accountlinks.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								templates/user/settings/security_accountlinks.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| <h4 class="ui top attached header"> | ||||
| 	{{.i18n.Tr "settings.manage_account_links"}} | ||||
| </h4> | ||||
| <div class="ui attached segment"> | ||||
| 	<div class="ui key list"> | ||||
| 		<div class="item"> | ||||
| 			{{.i18n.Tr "settings.manage_account_links_desc"}} | ||||
| 		</div> | ||||
| 		{{if .AccountLinks}} | ||||
| 		{{range $loginSource, $provider := .AccountLinks}} | ||||
| 			<div class="item"> | ||||
| 				<div class="right floated content"> | ||||
| 						<button class="ui red tiny button delete-button" id="delete-account-link" data-url="{{$.Link}}/account_link" data-id="{{$loginSource.ID}}"> | ||||
| 							{{$.i18n.Tr "settings.delete_key"}} | ||||
| 						</button> | ||||
| 				</div> | ||||
| 					<div class="content"> | ||||
| 						<strong>{{$provider}}</strong> | ||||
| 						{{if $loginSource.IsActived}}<span class="text red">{{$.i18n.Tr "settings.active"}}</span>{{end}} | ||||
| 					</div> | ||||
| 			</div> | ||||
| 		{{end}} | ||||
| 		{{end}} | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal" id="delete-account-link"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.remove_account_link"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.remove_account_link_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
							
								
								
									
										63
									
								
								templates/user/settings/security_openid.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								templates/user/settings/security_openid.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| <h4 class="ui top attached header"> | ||||
| 	{{.i18n.Tr "settings.manage_openid"}} | ||||
| </h4> | ||||
| <div class="ui attached segment"> | ||||
| 	<div class="ui openid list"> | ||||
| 		<div class="item"> | ||||
| 			{{.i18n.Tr "settings.openid_desc"}} | ||||
| 		</div> | ||||
| 		{{range .OpenIDs}} | ||||
| 			<div class="item"> | ||||
| 				<div class="right floated content"> | ||||
| 						<button class="ui red tiny button delete-button" id="delete-openid" data-url="{{$.Link}}/openid/delete" data-id="{{.ID}}"> | ||||
| 							{{$.i18n.Tr "settings.delete_key"}} | ||||
| 						</button> | ||||
| 				</div> | ||||
| 					<div class="right floated content"> | ||||
| 						<form action="{{$.Link}}/openid/toggle_visibility" method="post"> | ||||
| 						{{$.CsrfTokenHtml}} | ||||
| 						<input name="id" type="hidden" value="{{.ID}}"> | ||||
| 						{{if .Show}} | ||||
| 							<button class="ui tiny button"> | ||||
| 							<i class="icon fa-eye"></i> | ||||
| 							{{$.i18n.Tr "settings.hide_openid"}} | ||||
| 							</button> | ||||
| 						{{else}} | ||||
| 							<button class="ui tiny button"> | ||||
| 							<i class="icon fa-eye-slash"></i> | ||||
| 							{{$.i18n.Tr "settings.show_openid"}} | ||||
| 							</button> | ||||
| 						{{end}} | ||||
| 						</button> | ||||
| 						</form> | ||||
| 					</div> | ||||
| 					<div class="content"> | ||||
| 						<strong>{{.URI}}</strong> | ||||
| 					</div> | ||||
| 			</div> | ||||
| 		{{end}} | ||||
| 	</div> | ||||
| </div> | ||||
| <div class="ui attached bottom segment"> | ||||
| 	<form class="ui form" action="{{.Link}}/openid" method="post"> | ||||
| 		{{.CsrfTokenHtml}} | ||||
| 		<div class="required field {{if .Err_OpenID}}error{{end}}"> | ||||
| 			<label for="openid">{{.i18n.Tr "settings.add_new_openid"}}</label> | ||||
| 			<input id="openid" name="openid" type="text" autofocus required> | ||||
| 		</div> | ||||
| 		<button class="ui green button"> | ||||
| 			{{.i18n.Tr "settings.add_openid"}} | ||||
| 		</button> | ||||
| 	</form> | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal" id="delete-openid"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.openid_deletion"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.openid_deletion_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
							
								
								
									
										35
									
								
								templates/user/settings/security_twofa.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								templates/user/settings/security_twofa.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| <h4 class="ui top attached header"> | ||||
| 	{{.i18n.Tr "settings.twofa"}} | ||||
| </h4> | ||||
| <div class="ui attached segment"> | ||||
| 	<p>{{.i18n.Tr "settings.twofa_desc"}}</p> | ||||
| 	{{if .TwofaEnrolled}} | ||||
| 	<p>{{$.i18n.Tr "settings.twofa_is_enrolled" | Str2html }}</p> | ||||
| 	<form class="ui form" action="{{.Link}}/two_factor/regenerate_scratch" method="post" enctype="multipart/form-data"> | ||||
| 		{{.CsrfTokenHtml}} | ||||
| 		<p>{{.i18n.Tr "settings.regenerate_scratch_token_desc"}}</p> | ||||
| 		<button class="ui blue button">{{$.i18n.Tr "settings.twofa_scratch_token_regenerate"}}</button> | ||||
| 	</form> | ||||
| 	<form class="ui form" action="{{.Link}}/two_factor/disable" method="post" enctype="multipart/form-data" id="disable-form"> | ||||
| 		{{.CsrfTokenHtml}} | ||||
| 		<p>{{.i18n.Tr "settings.twofa_disable_note"}}</p> | ||||
| 		<div class="ui red button delete-button" id="disable-twofa" data-type="form" data-form="#disable-form">{{$.i18n.Tr "settings.twofa_disable"}}</div> | ||||
| 	</form> | ||||
| 	{{else}} | ||||
| 	<p>{{.i18n.Tr "settings.twofa_not_enrolled"}}</p> | ||||
| 	<div class="inline field"> | ||||
| 		<a class="ui green button" href="{{.Link}}/two_factor/enroll">{{$.i18n.Tr "settings.twofa_enroll"}}</a> | ||||
| 	</div> | ||||
| 	{{end}} | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal" id="disable-twofa"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.twofa_disable"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.twofa_disable_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
| @@ -1,44 +0,0 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings delete"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{.i18n.Tr "settings.twofa"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached segment"> | ||||
| 			<p>{{.i18n.Tr "settings.twofa_desc"}}</p> | ||||
| 			{{if .TwofaEnrolled}} | ||||
| 			<p>{{$.i18n.Tr "settings.twofa_is_enrolled" | Str2html }}</p> | ||||
| 			<form class="ui form" action="{{.Link}}/regenerate_scratch" method="post" enctype="multipart/form-data"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				<p>{{.i18n.Tr "settings.regenerate_scratch_token_desc"}}</p> | ||||
| 				<button class="ui blue button">{{$.i18n.Tr "settings.twofa_scratch_token_regenerate"}}</button> | ||||
| 			</form> | ||||
| 			<form class="ui form" action="{{.Link}}/disable" method="post" enctype="multipart/form-data" id="disable-form"> | ||||
| 				{{.CsrfTokenHtml}} | ||||
| 				<p>{{.i18n.Tr "settings.twofa_disable_note"}}</p> | ||||
| 				<div class="ui red button delete-button" data-type="form" data-form="#disable-form">{{$.i18n.Tr "settings.twofa_disable"}}</div> | ||||
| 			</form> | ||||
| 			{{else}} | ||||
| 			<p>{{.i18n.Tr "settings.twofa_not_enrolled"}}</p> | ||||
| 			<div class="inline field"> | ||||
| 				<a class="ui green button" href="{{.Link}}/enroll">{{$.i18n.Tr "settings.twofa_enroll"}}</a> | ||||
| 			</div> | ||||
| 			{{end}} | ||||
| 		</div> | ||||
| 	</div> | ||||
| </div> | ||||
|  | ||||
| <div class="ui small basic delete modal"> | ||||
| 	<div class="ui icon header"> | ||||
| 		<i class="trash icon"></i> | ||||
| 		{{.i18n.Tr "settings.twofa_disable"}} | ||||
| 	</div> | ||||
| 	<div class="content"> | ||||
| 		<p>{{.i18n.Tr "settings.twofa_disable_desc"}}</p> | ||||
| 	</div> | ||||
| 	{{template "base/delete_modal_actions" .}} | ||||
| </div> | ||||
|  | ||||
| {{template "base/footer" .}} | ||||
| @@ -1,5 +1,5 @@ | ||||
| {{template "base/head" .}} | ||||
| <div class="user settings delete"> | ||||
| <div class="user settings twofa"> | ||||
| 	{{template "user/settings/navbar" .}} | ||||
| 	<div class="ui container"> | ||||
| 		{{template "base/alert" .}} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user