Add HTML login form (fixes #4137) (#8757)

This commit is contained in:
Emil Lundberg
2023-10-06 13:00:58 +02:00
committed by GitHub
parent ac2e444a97
commit 8294870ffc
12 changed files with 683 additions and 244 deletions
+13 -5
View File
@@ -16,13 +16,9 @@ var syncthing = angular.module('syncthing', [
]);
var urlbase = 'rest';
var authUrlbase = urlbase + '/noauth/auth';
syncthing.config(function ($httpProvider, $translateProvider, LocaleServiceProvider) {
var deviceIDShort = metadata.deviceID.substr(0, 5);
$httpProvider.defaults.xsrfHeaderName = 'X-CSRF-Token-' + deviceIDShort;
$httpProvider.defaults.xsrfCookieName = 'CSRF-Token-' + deviceIDShort;
$httpProvider.useApplyAsync(true);
// language and localisation
$translateProvider.useSanitizeValueStrategy('escape');
@@ -33,6 +29,18 @@ syncthing.config(function ($httpProvider, $translateProvider, LocaleServiceProvi
LocaleServiceProvider.setAvailableLocales(validLangs);
LocaleServiceProvider.setDefaultLocale('en');
$httpProvider.useApplyAsync(true);
if (!window.metadata) {
// Most likely we're not authenticated yet, in which case we can't proceed with the rest of the setup.
// Do nothing and wait for the page reload on successful login.
return;
}
var deviceIDShort = metadata.deviceID.substr(0, 5);
$httpProvider.defaults.xsrfHeaderName = 'X-CSRF-Token-' + deviceIDShort;
$httpProvider.defaults.xsrfCookieName = 'CSRF-Token-' + deviceIDShort;
});
// @TODO: extract global level functions into separate service(s)
+10 -3
View File
@@ -2,17 +2,21 @@
<div class="modal-body">
<h1 class="text-center">
<img alt="Syncthing" src="assets/img/logo-horizontal.svg" style="max-width: 366px; vertical-align: -16px" />
<br />
</h1>
<h1 ng-if="version.version" class="text-center">
<small>{{versionString()}}</small>
<br />
<small><i>"{{version.codename}}"</i></small>
</h1>
<p class="text-center">
<p ng-if="version.version" class="text-center">
Build {{version.date | date:"yyyy-MM-dd"}}
<span ng-if="version.tags.length">({{version.tags.join(", ")}})</span>
<br />
Copyright &copy; 2014-{{version.date | date:"yyyy"}} the Syncthing Authors.
</p>
<p ng-if="!version.version" class="text-center" translate>
Log in to see version information.
</p>
<p class="text-center" translate>Syncthing is Free and Open Source Software licensed as MPL v2.0.</p>
<ul class="nav nav-tabs">
@@ -81,7 +85,10 @@ Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Al
</div>
<div id="about-paths" class="tab-pane">
<table class="table table-striped table-auto">
<p ng-if="!authenticated" translate>
Log in to see paths information.
</p>
<table ng-if="authenticated" class="table table-striped table-auto">
<caption><label translate>Internally used paths:</label></caption>
<tbody>
<tr>
+7 -1
View File
@@ -38,7 +38,13 @@ angular.module('syncthing.core')
.error(errorFn);
}
function errorFn(dummy) {
function errorFn(statusString, status) {
if (status === 403) {
// Auth error - reload login page
location.reload();
return;
}
$rootScope.$broadcast(self.OFFLINE);
$timeout(function () {
@@ -14,12 +14,26 @@ angular.module('syncthing.core')
function initController() {
LocaleService.autoConfigLocale();
if (!$scope.authenticated) {
// Can't proceed yet - wait for the page reload after successful login.
return;
}
setInterval($scope.refresh, 10000);
Events.start();
}
// public/scope definitions
// window.metadata is set in /meta.js which requires authentication
$scope.authenticated = window.metadata && window.metadata.authenticated;
$scope.login = {
username: '',
password: '',
errors: {},
};
$scope.completion = {};
$scope.config = {};
$scope.configInSync = true;
@@ -83,6 +97,35 @@ angular.module('syncthing.core')
files: 0
};
$scope.authenticatePassword = function () {
$scope.login.inProgress = true;
$scope.login.errors = {};
$http.post(authUrlbase + '/password', {
username: $scope.login.username,
password: $scope.login.password,
}).then(function () {
location.reload();
}).catch(function (response) {
if (response.status === 403) {
$scope.login.errors.badLogin = true;
} else {
$scope.login.errors.failed = true;
console.log('Password authentication failed:', response);
}
}).finally(function () {
$scope.login.inProgress = false;
});
};
$scope.logout = function() {
$http.post(authUrlbase + '/logout', {})
.then(function () {
location.reload();
}).catch(function (response) {
console.log('Failed to log out:', response);
});
};
$(window).bind('beforeunload', function () {
navigatingAway = true;
});
@@ -183,6 +226,9 @@ angular.module('syncthing.core')
if (arg.status === 0) {
// A network error, not an HTTP error
$scope.$emit(Events.OFFLINE);
} else if (arg.status === 403) {
// Auth error - reload login page
location.reload();
} else if (arg.status >= 400 && arg.status <= 599 && arg.status != 501) {
// A genuine HTTP error. 501/NotImplemented is considered intentional
// and not an error which we need to act upon.
@@ -3119,6 +3165,9 @@ angular.module('syncthing.core')
$scope.docsURL = function (path) {
var url = 'https://docs.syncthing.net';
if (!$scope.versionBase()) {
return url;
}
if (!path) {
// Undefined or null should become a valid string.
path = '';
@@ -128,14 +128,14 @@
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label translate for="User">GUI Authentication User</label>
<input id="User" class="form-control" type="text" ng-model="tmpGUI.user" autocomplete="off" />
<label translate for="user">GUI Authentication User</label>
<input id="user" class="form-control" type="text" name="user" ng-model="tmpGUI.user" autocomplete="username" />
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label translate for="Password">GUI Authentication Password</label>
<input id="Password" class="form-control" type="password" ng-model="tmpGUI.password" ng-trim="false" autocomplete="new-password" />
<label translate for="password">GUI Authentication Password</label>
<input id="password" class="form-control" type="password" name="password" ng-model="tmpGUI.password" ng-trim="false" autocomplete="new-password" />
</div>
</div>
</div>