Files
sogo/UI/WebServerResources/js/Main/Main.app.js

420 lines
16 KiB
JavaScript

/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* JavaScript for MainUI (SOGoRootPage) */
(function () {
'use strict';
angular.module('SOGo.MainUI', ['SOGo.Common', 'SOGo.Authentication']);
const PASSWORD_RECOVERY_TIMER_MS = 2000;
/**
* @ngInject
*/
LoginController.$inject = ['$scope', '$window', '$timeout', 'Dialog', '$mdDialog', 'Authentication', 'sgFocus', 'sgRippleClick', 'sgConstant', '$mdToast'];
function LoginController($scope, $window, $timeout, Dialog, $mdDialog, Authentication, focus, rippleDo, sgConstant, $mdToast) {
var vm = this;
this.$onInit = function () {
this.creds = {
username: $window.cookieUsername,
password: null,
domain: null,
rememberLogin: angular.isDefined($window.cookieUsername) && $window.cookieUsername.length > 0
};
if($window.loginHint)
this.creds.username = $window.loginHint;
// Send selected language only if user has changed it
if (/\blanguage=/.test($window.location.search))
this.creds.language = $window.language;
this.loginState = false;
// Code pattern for TOTP verification code
this.verificationCodePattern = '\\d{6}';
// Password policy - change expired password
this.passwords = { newPassword: null, newPasswordConfirmation: null, oldPassword: null, visible: false };
// Password recovery
this.passwordRecovery = {
passwordRecoveryEnabled: false,
passwordRecoveryQuestionKey: null,
passwordRecoveryQuestion: null,
passwordRecoveryMode: null,
passwordRecoveryQuestionAnswer: null,
passwordRecoveryToken: null,
passwordRecoveryLinkTimer: null,
passwordRecoverySecondaryEmailText: null,
passwordRecoveryMailDomain: null,
showLoader: false
};
// Show login once everything is initialized
this.showLogin = false;
$timeout(function () {
vm.showLogin = true;
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
let token = urlParams.get('token');
if (0 < window.location.pathname.indexOf("passwordRecoveryEmail") && token) {
token = token.replace(/\//g, ''); // remove trailing '/'
const tokenArray = token.split(".");
// Retrieve info from token
if (3 === tokenArray.length) {
vm.passwordRecovery.passwordRecoveryToken = token;
const info = JSON.parse(atob(tokenArray[1]));
vm.creds.username = info.username;
vm.creds.domain = info.domain;
vm.passwordRecovery.passwordRecoveryToken = token;
vm.passwordRecovery.passwordRecoveryMode = "SecondaryEmail";
vm.passwordRecovery.passwordRecoveryEnabled = true;
vm.loginState = 'passwordchange';
rippleDo('loginContent');
}
} else {
vm.retrievePasswordRecoveryEnabled();
}
// Manage autofill
if (document.querySelectorAll('*:autofill').length > 0) {
document.querySelectorAll('*:autofill').forEach((el) => {
el.parentElement.classList.add("md-input-has-value");
});
}
}, 100);
};
this.login = function () {
vm.loginState = 'authenticating';
Authentication.login(vm.creds)
.then(function (data) {
if (data.totpmissingkey) {
vm.loginState = 'totpcode';
focus('totpcode');
}
else if (data.totpdisabled) {
vm.loginState = 'totpdisabled';
vm.cn = data.cn;
vm.url = data.url;
}
else {
vm.loginState = 'logged';
vm.cn = data.cn;
vm.url = data.url;
// Let the user see the succesfull message before reloading the page
$timeout(function () {
vm.continueLogin();
}, 1000);
}
}, function (msg) {
vm.loginState = 'error';
if (msg.error) {
vm.errorMessage = msg.error;
}
else if (msg.grace > 0) {
// Password is expired, grace logins limit is not yet reached
vm.loginState = 'passwordwillexpire';
vm.cn = msg.cn;
vm.url = msg.url;
vm.passwordPolicy = msg.userPolicies ? msg.userPolicies : [];
vm.errorMessage = l('You have %{0} logins remaining before your account is locked. Please change your password in the preference dialog.', msg.grace);
}
else if (msg.expire > 0) {
// Password will soon expire
var value, string;
if (msg.expire > 86400) {
value = Math.round(msg.expire / 86400);
string = l("days");
}
else if (msg.expire > 3600) {
value = Math.round(msg.expire / 3600);
string = l("hours");
}
else if (msg.expire > 60) {
value = Math.round(msg.expire / 60);
string = l("minutes");
}
else {
value = msg.expire;
string = l("seconds");
}
vm.loginState = 'passwordwillexpire';
vm.cn = msg.cn;
vm.url = msg.url;
vm.errorMessage = l('Your password is going to expire in %{0} %{1}.', value, string);
}
else if (msg.passwordexpired && msg.passwordexpired == 2) {
vm.loginState = 'passwordchange';
vm.passwordPolicy = msg.userPolicies ? msg.userPolicies : [];
vm.url = msg.url;
vm.passwordexpired = msg.passwordexpired;
} else if (msg.passwordexpired) {
vm.loginState = 'passwordchange';
vm.passwordPolicy = msg.userPolicies ? msg.userPolicies : [];
vm.url = msg.url;
vm.passwordexpired = msg.passwordexpired;
}
});
return false;
};
this.loginName = function() {
vm.loginState = 'authenticating';
Authentication.loginName(vm.creds)
.then(function(data) {
vm.loginState = 'logged';
vm.cn = data.cn;
vm.url = data.url;
// Let the user see the succesfull message before reloading the page
$timeout(function() {
vm.continueLogin();
}, 1000);
}, function(msg) {
vm.loginState = 'error';
if (msg.error) {
vm.errorMessage = msg.error;
}
else if (msg.grace > 0) {
// Password is expired, grace logins limit is not yet reached
vm.loginState = 'passwordwillexpire';
vm.cn = msg.cn;
vm.url = msg.url;
vm.errorMessage = l('You have %{0} logins remaining before your account is locked. Please change your password in the preference dialog.', msg.grace);
}
else if (msg.expire > 0) {
// Password will soon expire
var value, string;
if (msg.expire > 86400) {
value = Math.round(msg.expire/86400);
string = l("days");
}
else if (msg.expire > 3600) {
value = Math.round(msg.expire/3600);
string = l("hours");
}
else if (msg.expire > 60) {
value = Math.round(msg.expire/60);
string = l("minutes");
}
else {
value = msg.expire;
string = l("seconds");
}
vm.loginState = 'passwordwillexpire';
vm.cn = msg.cn;
vm.url = msg.url;
vm.errorMessage = l('Your password is going to expire in %{0} %{1}.', value, string);
}
else if (msg.passwordexpired) {
vm.loginState = 'passwordchange';
vm.url = msg.url;
}
});
return false;
};
this.restoreLogin = function () {
if ('SecretQuestion' === vm.passwordRecovery.passwordRecoveryMode) {
rippleDo('loginContent');
vm.passwordRecoveryAbort();
} else {
delete vm.creds.verificationCode;
vm.passwordRecoveryAbort();
}
};
this.continueLogin = function () {
if ($window.location.href === vm.url)
$window.location.reload(true);
else
$window.location.href = vm.url;
};
this.showAbout = function ($event) {
$mdDialog.show({
targetEvent: $event,
templateUrl: 'aboutBox.html',
controller: AboutDialogController,
controllerAs: 'about'
});
AboutDialogController.$inject = ['$mdDialog'];
function AboutDialogController($mdDialog) {
this.closeDialog = function () {
$mdDialog.hide();
};
}
};
this.changeLanguage = function ($event) {
// Reload page
$window.location.href = ApplicationBaseURL + 'changeLanguage?language=' + this.creds.language;
};
this.canChangePassword = function (form) {
if (this.passwords.newPasswordConfirmation && this.passwords.newPasswordConfirmation.length &&
this.passwords.newPassword != this.passwords.newPasswordConfirmation) {
form.newPasswordConfirmation.$setValidity('newPasswordMismatch', false);
return false;
}
else {
form.newPasswordConfirmation.$setValidity('newPasswordMismatch', true);
}
if (this.passwords.newPassword && this.passwords.newPassword.length > 0 &&
this.passwords.newPasswordConfirmation && this.passwords.newPasswordConfirmation.length &&
this.passwords.newPassword == this.passwords.newPasswordConfirmation &&
((this.isInPasswordRecoveryMode()) ||
(!this.loginState && this.passwords.oldPassword && this.passwords.oldPassword.length > 0) ||
('passwordchange' == this.loginState && this.passwords.oldPassword && this.passwords.oldPassword.length > 0)
))
return true;
return false;
};
this.changePassword = function () {
Authentication.changePassword(this.creds.username, this.creds.domain, this.passwords.newPassword, this.passwords.oldPassword, this.passwordRecovery.passwordRecoveryToken).then(function (data) {
vm.loginState = 'message';
vm.url = data.url;
vm.errorMessage = l('The password was changed successfully.');
}, function (msg) {
$mdToast.show(
$mdToast.simple()
.textContent(msg)
.position(sgConstant.toastPosition)
.hideDelay(2000)
);
});
};
this.passwordRecoveryInfo = function () {
vm.loginState = 'passwordrecovery';
vm.passwordRecovery.showLoader = true;
Authentication.passwordRecovery(this.creds.username, this.creds.domain).then(function (data) {
vm.passwordRecovery.passwordRecoveryMode = data.mode;
if ('SecretQuestion' === data.mode) {
vm.passwordRecovery.passwordRecoveryQuestion = data.secretQuestionLabel;
vm.passwordRecovery.passwordRecoveryQuestionKey = data.secretQuestion;
} else if ('SecondaryEmail' === data.mode) {
vm.passwordRecovery.passwordRecoverySecondaryEmailText = l("A link will be sent to %{0}", data.obfuscatedRecoveryEmail);
} else if ('Disabled' === data.mode) {
vm.loginState = 'error';
vm.errorMessage = l('No password recovery method has been defined for this user');
}
vm.passwordRecovery.showLoader = false;
}, function (msg) {
vm.loginState = 'error';
vm.errorMessage = msg;
vm.passwordRecovery.showLoader = false;
});
};
this.passwordRecoveryEmail = function () {
vm.passwordRecovery.showLoader = true;
Authentication.passwordRecoveryEmail(this.creds.username, this.creds.domain
, this.passwordRecovery.passwordRecoveryMode
, this.passwordRecovery.passwordRecoveryMailDomain).then(function () {
vm.loginState = 'sendrecoverymail';
vm.passwordRecovery.showLoader = false;
}, function (msg) {
vm.loginState = 'error';
vm.errorMessage = msg;
vm.passwordRecovery.showLoader = false;
});
};
this.passwordRecoveryCheck = function () {
vm.passwordRecovery.showLoader = true;
Authentication.passwordRecoveryCheck(this.creds.username, this.creds.domain
, this.passwordRecovery.passwordRecoveryMode
, this.passwordRecovery.passwordRecoveryQuestionKey
, this.passwordRecovery.passwordRecoveryQuestionAnswer
, this.passwordRecovery.passwordRecoveryMailDomain).then(function (token) {
if ("SecretQuestion" == vm.passwordRecovery.passwordRecoveryMode) {
vm.passwordRecovery.passwordRecoveryToken = token;
vm.loginState = 'passwordchange';
} else if ("SecondaryEmail" == vm.passwordRecovery.passwordRecoveryMode) {
vm.loginState = 'sendrecoverymail';
}
vm.passwordRecovery.showLoader = false;
}, function (msg) {
vm.loginState = 'error';
vm.errorMessage = msg;
vm.passwordRecovery.showLoader = false;
});
};
this.isPasswordExpiredSecurity = function () {
return (this.passwordexpired && 2 === this.passwordexpired);
};
this.isInPasswordRecoveryMode = function () {
return (("SecretQuestion" == this.passwordRecovery.passwordRecoveryMode) ||
("SecondaryEmail" == this.passwordRecovery.passwordRecoveryMode &&
this.passwordRecovery.passwordRecoveryToken)) ? true : false;
};
this.passwordRecoveryAbort = function () {
this.passwords = { newPassword: null, newPasswordConfirmation: null, oldPassword: null };
this.loginState = false;
this.passwordRecovery.passwordRecoveryEnabled = false;
this.passwordRecovery.passwordRecoveryQuestion = null;
this.passwordRecovery.passwordRecoveryMode = null;
this.passwordRecovery.passwordRecoveryQuestionAnswer = null;
this.passwordRecovery.passwordRecoveryToken = null;
this.passwordRecovery.passwordRecoverySecondaryEmailText = null;
this.passwordRecovery.passwordRecoveryMailDomain = null;
this.passwordRecovery.showLoader = false;
$window.location.reload(true);
};
this.usernameChanged = function () {
if (this.passwordRecovery.passwordRecoveryLinkTimer) {
clearTimeout(this.passwordRecovery.passwordRecoveryLinkTimer);
}
this.passwordRecovery.passwordRecoveryLinkTimer = setTimeout(() => {
vm.retrievePasswordRecoveryEnabled();
this.passwordRecovery.passwordRecoveryLinkTimer = null;
}, PASSWORD_RECOVERY_TIMER_MS);
};
this.retrievePasswordRecoveryEnabled = function () {
if (this.creds.username || this.creds.domain) {
Authentication.passwordRecoveryEnabled(this.creds.username, this.creds.domain).then(function (mailDomain) {
vm.passwordRecovery.passwordRecoveryMailDomain = mailDomain;
vm.passwordRecovery.passwordRecoveryEnabled = true;
}, function () {
vm.passwordRecovery.passwordRecoveryEnabled = false;
});
}
};
this.changePasswordVisibility = function () {
this.passwords.visible = !this.passwords.visible;
var field = document.getElementById("passwordField");
if (this.passwords.visible) {
field.type = "text";
document.getElementById("password-visibility-icon").innerHTML = 'visibility_off';
} else {
field.type = "password";
document.getElementById("password-visibility-icon").innerHTML = 'visibility';
}
}
}
angular
.module('SOGo.MainUI')
.controller('LoginController', LoginController);
})();