SEBWIN-220: Corrected configuration algorithm to also verify the current administrator password when reconfiguring during application startup.
This commit is contained in:
parent
5641dc3e4b
commit
7173109d05
10 changed files with 304 additions and 176 deletions
|
@ -129,7 +129,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication
|
|||
public void MustHandlePasswordRequestCorrectly()
|
||||
{
|
||||
var passwordRequested = false;
|
||||
var purpose = PasswordRequestPurpose.Administrator;
|
||||
var purpose = PasswordRequestPurpose.LocalAdministrator;
|
||||
var requestId = Guid.NewGuid();
|
||||
var resetEvent = new AutoResetEvent(false);
|
||||
|
||||
|
|
|
@ -285,13 +285,28 @@ namespace SafeExamBrowser.Client
|
|||
|
||||
private void ClientHost_PasswordRequested(PasswordRequestEventArgs args)
|
||||
{
|
||||
var isAdmin = args.Purpose == PasswordRequestPurpose.Administrator;
|
||||
var message = isAdmin ? TextKey.PasswordDialog_AdminPasswordRequired : TextKey.PasswordDialog_SettingsPasswordRequired;
|
||||
var title = isAdmin ? TextKey.PasswordDialog_AdminPasswordRequiredTitle : TextKey.PasswordDialog_SettingsPasswordRequiredTitle;
|
||||
var dialog = uiFactory.CreatePasswordDialog(text.Get(message), text.Get(title));
|
||||
var message = default(TextKey);
|
||||
var title = default(TextKey);
|
||||
|
||||
logger.Info($"Received input request with id '{args.RequestId}' for the {args.Purpose.ToString().ToLower()} password.");
|
||||
|
||||
switch (args.Purpose)
|
||||
{
|
||||
case PasswordRequestPurpose.LocalAdministrator:
|
||||
message = TextKey.PasswordDialog_LocalAdminPasswordRequired;
|
||||
title = TextKey.PasswordDialog_LocalAdminPasswordRequiredTitle;
|
||||
break;
|
||||
case PasswordRequestPurpose.LocalSettings:
|
||||
message = TextKey.PasswordDialog_LocalSettingsPasswordRequired;
|
||||
title = TextKey.PasswordDialog_LocalSettingsPasswordRequiredTitle;
|
||||
break;
|
||||
case PasswordRequestPurpose.Settings:
|
||||
message = TextKey.PasswordDialog_SettingsPasswordRequired;
|
||||
title = TextKey.PasswordDialog_SettingsPasswordRequiredTitle;
|
||||
break;
|
||||
}
|
||||
|
||||
var dialog = uiFactory.CreatePasswordDialog(text.Get(message), text.Get(title));
|
||||
var result = dialog.Show();
|
||||
|
||||
runtime.SubmitPassword(args.RequestId, result.Success, result.Password);
|
||||
|
|
|
@ -252,7 +252,7 @@ namespace SafeExamBrowser.Configuration.DataFormats
|
|||
|
||||
if (status != LoadStatus.Success)
|
||||
{
|
||||
logger.Error($"Element '{element}' is not supported!");
|
||||
logger.Error($"Element '{element}' is not a supported value type!");
|
||||
}
|
||||
|
||||
return status;
|
||||
|
|
|
@ -14,9 +14,14 @@ namespace SafeExamBrowser.Contracts.Communication.Data
|
|||
public enum PasswordRequestPurpose
|
||||
{
|
||||
/// <summary>
|
||||
/// The password is to be used as administrator password for an application configuration.
|
||||
/// The password is to be used as administrator password for the local client configuration.
|
||||
/// </summary>
|
||||
Administrator,
|
||||
LocalAdministrator,
|
||||
|
||||
/// <summary>
|
||||
/// The password is to be used as settings password for the local client configuration.
|
||||
/// </summary>
|
||||
LocalSettings,
|
||||
|
||||
/// <summary>
|
||||
/// The password is to be used as settings password for an application configuration.
|
||||
|
|
|
@ -85,10 +85,12 @@ namespace SafeExamBrowser.Contracts.I18n
|
|||
OperationStatus_WaitExplorerStartup,
|
||||
OperationStatus_WaitExplorerTermination,
|
||||
OperationStatus_WaitRuntimeDisconnection,
|
||||
PasswordDialog_AdminPasswordRequired,
|
||||
PasswordDialog_AdminPasswordRequiredTitle,
|
||||
PasswordDialog_Cancel,
|
||||
PasswordDialog_Confirm,
|
||||
PasswordDialog_LocalAdminPasswordRequired,
|
||||
PasswordDialog_LocalAdminPasswordRequiredTitle,
|
||||
PasswordDialog_LocalSettingsPasswordRequired,
|
||||
PasswordDialog_LocalSettingsPasswordRequiredTitle,
|
||||
PasswordDialog_QuitPasswordRequired,
|
||||
PasswordDialog_QuitPasswordRequiredTitle,
|
||||
PasswordDialog_SettingsPasswordRequired,
|
||||
|
|
|
@ -213,18 +213,24 @@
|
|||
<Entry key="OperationStatus_WaitRuntimeDisconnection">
|
||||
Waiting for the runtime to disconnect
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_AdminPasswordRequired">
|
||||
Please enter the administrator password for the application configuration:
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_AdminPasswordRequiredTitle">
|
||||
Administrator Password Required
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_Cancel">
|
||||
Cancel
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_Confirm">
|
||||
Confirm
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_LocalAdminPasswordRequired">
|
||||
Please enter the administrator password for the local client configuration:
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_LocalAdminPasswordRequiredTitle">
|
||||
Administrator Password Required
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_LocalSettingsPasswordRequired">
|
||||
Please enter the settings password for the local client configuration:
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_LocalSettingsPasswordRequiredTitle">
|
||||
Settings Password Required
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_QuitPasswordRequired">
|
||||
Please enter the quit password in order to terminate the application:
|
||||
</Entry>
|
||||
|
@ -232,7 +238,7 @@
|
|||
Quit Password Required
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_SettingsPasswordRequired">
|
||||
Please enter the settings password for the application configuration:
|
||||
Please enter the settings password for the selected application configuration:
|
||||
</Entry>
|
||||
<Entry key="PasswordDialog_SettingsPasswordRequiredTitle">
|
||||
Settings Password Required
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
|
||||
var clientExecutable = Context.Next.AppConfig.ClientExecutablePath;
|
||||
var clientLogFile = $"{'"' + Context.Next.AppConfig.ClientLogFile + '"'}";
|
||||
var clientLogLevel = logger.LogLevel.ToString();
|
||||
var clientLogLevel = Context.Next.Settings.LogLevel.ToString();
|
||||
var runtimeHostUri = Context.Next.AppConfig.RuntimeAddress;
|
||||
var startupToken = Context.Next.StartupToken.ToString("D");
|
||||
|
||||
|
|
|
@ -59,11 +59,11 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
||||
|
||||
var result = OperationResult.Failed;
|
||||
var isValidUri = TryInitializeSettingsUri(out Uri uri);
|
||||
var isValidUri = TryInitializeSettingsUri(out var uri, out var source);
|
||||
|
||||
if (isValidUri)
|
||||
{
|
||||
result = LoadSettings(uri);
|
||||
result = LoadSettingsForStartup(uri, source);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -81,11 +81,11 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeConfiguration);
|
||||
|
||||
var result = OperationResult.Failed;
|
||||
var isValidUri = TryValidateSettingsUri(Context.ReconfigurationFilePath, out Uri uri);
|
||||
var isValidUri = TryValidateSettingsUri(Context.ReconfigurationFilePath, out var uri);
|
||||
|
||||
if (isValidUri)
|
||||
{
|
||||
result = LoadSettings(uri);
|
||||
result = LoadSettingsForReconfiguration(uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -104,66 +104,88 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
|
||||
private OperationResult LoadDefaultSettings()
|
||||
{
|
||||
logger.Info("No valid configuration resource specified nor found in PROGRAMDATA or APPDATA - loading default settings...");
|
||||
logger.Info("No valid configuration resource specified and no local client configuration found - loading default settings...");
|
||||
Context.Next.Settings = configuration.LoadDefaultSettings();
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
private OperationResult LoadSettings(Uri uri)
|
||||
private OperationResult LoadSettingsForStartup(Uri uri, UriSource source)
|
||||
{
|
||||
var passwordParams = new PasswordParameters { Password = string.Empty, IsHash = true };
|
||||
var status = configuration.TryLoadSettings(uri, out var settings, passwordParams);
|
||||
var currentPassword = default(string);
|
||||
var passwordParams = default(PasswordParameters);
|
||||
var settings = default(Settings);
|
||||
var status = default(LoadStatus?);
|
||||
|
||||
if (status == LoadStatus.PasswordNeeded && Context.Current?.Settings.AdminPasswordHash != null)
|
||||
if (source == UriSource.CommandLine)
|
||||
{
|
||||
passwordParams.Password = Context.Current.Settings.AdminPasswordHash;
|
||||
passwordParams.IsHash = true;
|
||||
var hasAppDataFile = File.Exists(AppDataFile);
|
||||
var hasProgramDataFile = File.Exists(ProgramDataFile);
|
||||
|
||||
status = configuration.TryLoadSettings(uri, out settings, passwordParams);
|
||||
}
|
||||
|
||||
for (int attempts = 0; attempts < 5 && status == LoadStatus.PasswordNeeded; attempts++)
|
||||
{
|
||||
var success = TryGetPassword(PasswordRequestPurpose.Settings, out var password);
|
||||
|
||||
if (success)
|
||||
if (hasProgramDataFile)
|
||||
{
|
||||
passwordParams.Password = password;
|
||||
passwordParams.IsHash = false;
|
||||
status = TryLoadSettings(new Uri(ProgramDataFile, UriKind.Absolute), UriSource.ProgramData, out _, out settings);
|
||||
}
|
||||
else
|
||||
else if (hasAppDataFile)
|
||||
{
|
||||
return OperationResult.Aborted;
|
||||
status = TryLoadSettings(new Uri(AppDataFile, UriKind.Absolute), UriSource.AppData, out _, out settings);
|
||||
}
|
||||
|
||||
status = configuration.TryLoadSettings(uri, out settings, passwordParams);
|
||||
if ((!hasProgramDataFile && !hasAppDataFile) || status == LoadStatus.Success)
|
||||
{
|
||||
currentPassword = settings?.AdminPasswordHash;
|
||||
status = TryLoadSettings(uri, source, out passwordParams, out settings, currentPassword);
|
||||
}
|
||||
}
|
||||
|
||||
Context.Next.Settings = settings;
|
||||
|
||||
if (settings != null)
|
||||
else
|
||||
{
|
||||
logger.LogLevel = settings.LogLevel;
|
||||
status = TryLoadSettings(uri, source, out passwordParams, out settings);
|
||||
}
|
||||
|
||||
return HandleLoadResult(uri, settings, status, passwordParams);
|
||||
if (status.HasValue)
|
||||
{
|
||||
return DetermineLoadResult(uri, source, settings, status.Value, passwordParams, currentPassword);
|
||||
}
|
||||
else
|
||||
{
|
||||
return OperationResult.Aborted;
|
||||
}
|
||||
}
|
||||
|
||||
private OperationResult HandleLoadResult(Uri uri, Settings settings, LoadStatus status, PasswordParameters password)
|
||||
private OperationResult LoadSettingsForReconfiguration(Uri uri)
|
||||
{
|
||||
if (status == LoadStatus.LoadWithBrowser)
|
||||
{
|
||||
return HandleBrowserResource(uri);
|
||||
}
|
||||
var currentPassword = Context.Current.Settings.AdminPasswordHash;
|
||||
var source = UriSource.Reconfiguration;
|
||||
var status = TryLoadSettings(uri, source, out var passwordParams, out var settings, currentPassword);
|
||||
|
||||
if (status == LoadStatus.Success && settings.ConfigurationMode == ConfigurationMode.ConfigureClient)
|
||||
if (status.HasValue)
|
||||
{
|
||||
return HandleClientConfiguration(uri, password);
|
||||
return DetermineLoadResult(uri, source, settings, status.Value, passwordParams, currentPassword);
|
||||
}
|
||||
|
||||
if (status == LoadStatus.Success)
|
||||
else
|
||||
{
|
||||
return OperationResult.Aborted;
|
||||
}
|
||||
}
|
||||
|
||||
private OperationResult DetermineLoadResult(Uri uri, UriSource source, Settings settings, LoadStatus status, PasswordParameters passwordParams, string currentPassword = default(string))
|
||||
{
|
||||
if (status == LoadStatus.LoadWithBrowser || status == LoadStatus.Success)
|
||||
{
|
||||
var isNewConfiguration = source == UriSource.CommandLine || source == UriSource.Reconfiguration;
|
||||
|
||||
Context.Next.Settings = settings;
|
||||
|
||||
if (status == LoadStatus.LoadWithBrowser)
|
||||
{
|
||||
return HandleBrowserResource(uri);
|
||||
}
|
||||
|
||||
if (isNewConfiguration && settings.ConfigurationMode == ConfigurationMode.ConfigureClient)
|
||||
{
|
||||
return HandleClientConfiguration(uri, passwordParams, currentPassword);
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
|
@ -180,132 +202,171 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
private OperationResult HandleClientConfiguration(Uri resource, PasswordParameters password)
|
||||
private OperationResult HandleClientConfiguration(Uri uri, PasswordParameters passwordParams, string currentPassword = default(string))
|
||||
{
|
||||
var isAppDataFile = Path.GetFullPath(resource.AbsolutePath).Equals(AppDataFile, StringComparison.OrdinalIgnoreCase);
|
||||
var isProgramDataFile = Path.GetFullPath(resource.AbsolutePath).Equals(ProgramDataFile, StringComparison.OrdinalIgnoreCase);
|
||||
var isFirstSession = Context.Current == null;
|
||||
var success = TryConfigureClient(uri, passwordParams, currentPassword);
|
||||
|
||||
if (!isAppDataFile && !isProgramDataFile)
|
||||
if (success == true)
|
||||
{
|
||||
var requiresAuthentication = IsAuthenticationRequiredForClientConfiguration(password);
|
||||
|
||||
logger.Info("Starting client configuration...");
|
||||
|
||||
if (requiresAuthentication)
|
||||
if (isFirstSession && AbortAfterClientConfiguration())
|
||||
{
|
||||
var result = HandleClientConfigurationAuthentication();
|
||||
|
||||
if (result != OperationResult.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Info("Authentication is not required.");
|
||||
}
|
||||
|
||||
var status = configuration.ConfigureClientWith(resource, password);
|
||||
|
||||
if (status == SaveStatus.Success)
|
||||
{
|
||||
logger.Info("Client configuration was successful.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error($"Client configuration failed with status '{status}'!");
|
||||
ActionRequired?.Invoke(new ClientConfigurationErrorMessageArgs());
|
||||
|
||||
return OperationResult.Failed;
|
||||
}
|
||||
|
||||
if (isFirstSession)
|
||||
{
|
||||
var result = HandleClientConfigurationOnStartup();
|
||||
|
||||
if (result != OperationResult.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
private bool IsAuthenticationRequiredForClientConfiguration(PasswordParameters password)
|
||||
{
|
||||
var requiresAuthentication = Context.Current?.Settings.AdminPasswordHash != null;
|
||||
|
||||
if (requiresAuthentication)
|
||||
{
|
||||
var currentPassword = Context.Current.Settings.AdminPasswordHash;
|
||||
var nextPassword = Context.Next.Settings.AdminPasswordHash;
|
||||
var hasSettingsPassword = password.Password != null;
|
||||
var sameAdminPassword = currentPassword.Equals(nextPassword, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
requiresAuthentication = !sameAdminPassword;
|
||||
|
||||
if (requiresAuthentication && hasSettingsPassword)
|
||||
{
|
||||
var settingsPassword = password.IsHash ? password.Password : hashAlgorithm.GenerateHashFor(password.Password);
|
||||
var knowsAdminPassword = currentPassword.Equals(settingsPassword, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
requiresAuthentication = !knowsAdminPassword;
|
||||
}
|
||||
}
|
||||
|
||||
return requiresAuthentication;
|
||||
}
|
||||
|
||||
private OperationResult HandleClientConfigurationAuthentication()
|
||||
{
|
||||
var currentPassword = Context.Current.Settings.AdminPasswordHash;
|
||||
var isSamePassword = false;
|
||||
|
||||
for (int attempts = 0; attempts < 5 && !isSamePassword; attempts++)
|
||||
{
|
||||
var success = TryGetPassword(PasswordRequestPurpose.Administrator, out var password);
|
||||
|
||||
if (success)
|
||||
{
|
||||
isSamePassword = currentPassword.Equals(hashAlgorithm.GenerateHashFor(password), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Info("Authentication was aborted.");
|
||||
|
||||
return OperationResult.Aborted;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSamePassword)
|
||||
{
|
||||
logger.Info("Authentication was successful.");
|
||||
|
||||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
logger.Info("Authentication has failed!");
|
||||
ActionRequired?.Invoke(new InvalidPasswordMessageArgs());
|
||||
if (!success.HasValue)
|
||||
{
|
||||
return OperationResult.Aborted;
|
||||
}
|
||||
|
||||
return OperationResult.Failed;
|
||||
}
|
||||
|
||||
private OperationResult HandleClientConfigurationOnStartup()
|
||||
private LoadStatus? TryLoadSettings(Uri uri, UriSource source, out PasswordParameters passwordParams, out Settings settings, string currentPassword = default(string))
|
||||
{
|
||||
passwordParams = new PasswordParameters { Password = string.Empty, IsHash = true };
|
||||
|
||||
var status = configuration.TryLoadSettings(uri, out settings, passwordParams);
|
||||
|
||||
if (status == LoadStatus.PasswordNeeded && currentPassword != default(string))
|
||||
{
|
||||
passwordParams.Password = currentPassword;
|
||||
passwordParams.IsHash = true;
|
||||
|
||||
status = configuration.TryLoadSettings(uri, out settings, passwordParams);
|
||||
}
|
||||
|
||||
for (int attempts = 0; attempts < 5 && status == LoadStatus.PasswordNeeded; attempts++)
|
||||
{
|
||||
var isLocalConfig = source == UriSource.AppData || source == UriSource.ProgramData;
|
||||
var purpose = isLocalConfig ? PasswordRequestPurpose.LocalSettings : PasswordRequestPurpose.Settings;
|
||||
var success = TryGetPassword(purpose, out var password);
|
||||
|
||||
if (success)
|
||||
{
|
||||
passwordParams.Password = password;
|
||||
passwordParams.IsHash = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
status = configuration.TryLoadSettings(uri, out settings, passwordParams);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
private bool? TryConfigureClient(Uri uri, PasswordParameters passwordParams, string currentPassword = default(string))
|
||||
{
|
||||
var mustAuthenticate = IsRequiredToAuthenticateForClientConfiguration(passwordParams, currentPassword);
|
||||
|
||||
logger.Info("Starting client configuration...");
|
||||
|
||||
if (mustAuthenticate)
|
||||
{
|
||||
var authenticated = AuthenticateForClientConfiguration(currentPassword);
|
||||
|
||||
if (authenticated == true)
|
||||
{
|
||||
logger.Info("Authentication was successful.");
|
||||
}
|
||||
|
||||
if (authenticated == false)
|
||||
{
|
||||
logger.Info("Authentication has failed!");
|
||||
ActionRequired?.Invoke(new InvalidPasswordMessageArgs());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!authenticated.HasValue)
|
||||
{
|
||||
logger.Info("Authentication was aborted.");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Info("Authentication is not required.");
|
||||
}
|
||||
|
||||
var status = configuration.ConfigureClientWith(uri, passwordParams);
|
||||
var success = status == SaveStatus.Success;
|
||||
|
||||
if (success)
|
||||
{
|
||||
logger.Info("Client configuration was successful.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error($"Client configuration failed with status '{status}'!");
|
||||
ActionRequired?.Invoke(new ClientConfigurationErrorMessageArgs());
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
private bool IsRequiredToAuthenticateForClientConfiguration(PasswordParameters passwordParams, string currentPassword = default(string))
|
||||
{
|
||||
var mustAuthenticate = currentPassword != default(string);
|
||||
|
||||
if (mustAuthenticate)
|
||||
{
|
||||
var nextPassword = Context.Next.Settings.AdminPasswordHash;
|
||||
var hasSettingsPassword = passwordParams.Password != null;
|
||||
var sameAdminPassword = currentPassword.Equals(nextPassword, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (sameAdminPassword)
|
||||
{
|
||||
mustAuthenticate = false;
|
||||
}
|
||||
else if (hasSettingsPassword)
|
||||
{
|
||||
var settingsPassword = passwordParams.IsHash ? passwordParams.Password : hashAlgorithm.GenerateHashFor(passwordParams.Password);
|
||||
var knowsAdminPassword = currentPassword.Equals(settingsPassword, StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
mustAuthenticate = !knowsAdminPassword;
|
||||
}
|
||||
}
|
||||
|
||||
return mustAuthenticate;
|
||||
}
|
||||
|
||||
private bool? AuthenticateForClientConfiguration(string currentPassword)
|
||||
{
|
||||
var authenticated = false;
|
||||
|
||||
for (int attempts = 0; attempts < 5 && !authenticated; attempts++)
|
||||
{
|
||||
var success = TryGetPassword(PasswordRequestPurpose.LocalAdministrator, out var password);
|
||||
|
||||
if (success)
|
||||
{
|
||||
authenticated = currentPassword.Equals(hashAlgorithm.GenerateHashFor(password), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return authenticated;
|
||||
}
|
||||
|
||||
private bool AbortAfterClientConfiguration()
|
||||
{
|
||||
var args = new ConfigurationCompletedEventArgs();
|
||||
|
||||
ActionRequired?.Invoke(args);
|
||||
logger.Info($"The user chose to {(args.AbortStartup ? "abort" : "continue")} startup after successful client configuration.");
|
||||
|
||||
if (args.AbortStartup)
|
||||
{
|
||||
return OperationResult.Aborted;
|
||||
}
|
||||
|
||||
return OperationResult.Success;
|
||||
return args.AbortStartup;
|
||||
}
|
||||
|
||||
private void ShowFailureMessage(LoadStatus status, Uri uri)
|
||||
|
@ -337,32 +398,32 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
return args.Success;
|
||||
}
|
||||
|
||||
private bool TryInitializeSettingsUri(out Uri uri)
|
||||
private bool TryInitializeSettingsUri(out Uri uri, out UriSource source)
|
||||
{
|
||||
var path = default(string);
|
||||
var isValidUri = false;
|
||||
|
||||
uri = null;
|
||||
source = default(UriSource);
|
||||
|
||||
if (commandLineArgs?.Length > 1)
|
||||
{
|
||||
path = commandLineArgs[1];
|
||||
isValidUri = Uri.TryCreate(path, UriKind.Absolute, out uri);
|
||||
logger.Info($"Found command-line argument for configuration resource: '{path}', the URI is {(isValidUri ? "valid" : "invalid")}.");
|
||||
isValidUri = Uri.TryCreate(commandLineArgs[1], UriKind.Absolute, out uri);
|
||||
source = UriSource.CommandLine;
|
||||
logger.Info($"Found command-line argument for configuration resource: '{uri}', the URI is {(isValidUri ? "valid" : "invalid")}.");
|
||||
}
|
||||
|
||||
if (!isValidUri && File.Exists(ProgramDataFile))
|
||||
{
|
||||
path = ProgramDataFile;
|
||||
isValidUri = Uri.TryCreate(path, UriKind.Absolute, out uri);
|
||||
logger.Info($"Found configuration file in PROGRAMDATA: '{path}', the URI is {(isValidUri ? "valid" : "invalid")}.");
|
||||
isValidUri = Uri.TryCreate(ProgramDataFile, UriKind.Absolute, out uri);
|
||||
source = UriSource.ProgramData;
|
||||
logger.Info($"Found configuration file in PROGRAMDATA directory: '{uri}'.");
|
||||
}
|
||||
|
||||
if (!isValidUri && File.Exists(AppDataFile))
|
||||
{
|
||||
path = AppDataFile;
|
||||
isValidUri = Uri.TryCreate(path, UriKind.Absolute, out uri);
|
||||
logger.Info($"Found configuration file in APPDATA: '{path}', the URI is {(isValidUri ? "valid" : "invalid")}.");
|
||||
isValidUri = Uri.TryCreate(AppDataFile, UriKind.Absolute, out uri);
|
||||
source = UriSource.AppData;
|
||||
logger.Info($"Found configuration file in APPDATA directory: '{uri}'.");
|
||||
}
|
||||
|
||||
return isValidUri;
|
||||
|
@ -393,5 +454,14 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private enum UriSource
|
||||
{
|
||||
Undefined,
|
||||
AppData,
|
||||
CommandLine,
|
||||
ProgramData,
|
||||
Reconfiguration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
|
||||
public override OperationResult Perform()
|
||||
{
|
||||
SwitchLogSeverity();
|
||||
ActivateNewSession();
|
||||
|
||||
return OperationResult.Success;
|
||||
|
@ -33,6 +34,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
|
||||
public override OperationResult Repeat()
|
||||
{
|
||||
SwitchLogSeverity();
|
||||
ActivateNewSession();
|
||||
|
||||
return OperationResult.Success;
|
||||
|
@ -43,6 +45,18 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
return OperationResult.Success;
|
||||
}
|
||||
|
||||
private void SwitchLogSeverity()
|
||||
{
|
||||
if (logger.LogLevel != Context.Next.Settings.LogLevel)
|
||||
{
|
||||
var current = logger.LogLevel.ToString().ToUpper();
|
||||
var next = Context.Next.Settings.LogLevel.ToString().ToUpper();
|
||||
|
||||
logger.Info($"Switching from log severity '{current}' to '{next}' for new session.");
|
||||
logger.LogLevel = Context.Next.Settings.LogLevel;
|
||||
}
|
||||
}
|
||||
|
||||
private void ActivateNewSession()
|
||||
{
|
||||
var isFirstSession = Context.Current == null;
|
||||
|
|
|
@ -452,9 +452,25 @@ namespace SafeExamBrowser.Runtime
|
|||
|
||||
private void TryGetPasswordViaDialog(PasswordRequiredEventArgs args)
|
||||
{
|
||||
var isAdmin = args.Purpose == PasswordRequestPurpose.Administrator;
|
||||
var message = isAdmin ? TextKey.PasswordDialog_AdminPasswordRequired : TextKey.PasswordDialog_SettingsPasswordRequired;
|
||||
var title = isAdmin ? TextKey.PasswordDialog_AdminPasswordRequiredTitle : TextKey.PasswordDialog_SettingsPasswordRequiredTitle;
|
||||
var message = default(TextKey);
|
||||
var title = default(TextKey);
|
||||
|
||||
switch (args.Purpose)
|
||||
{
|
||||
case PasswordRequestPurpose.LocalAdministrator:
|
||||
message = TextKey.PasswordDialog_LocalAdminPasswordRequired;
|
||||
title = TextKey.PasswordDialog_LocalAdminPasswordRequiredTitle;
|
||||
break;
|
||||
case PasswordRequestPurpose.LocalSettings:
|
||||
message = TextKey.PasswordDialog_LocalSettingsPasswordRequired;
|
||||
title = TextKey.PasswordDialog_LocalSettingsPasswordRequiredTitle;
|
||||
break;
|
||||
case PasswordRequestPurpose.Settings:
|
||||
message = TextKey.PasswordDialog_SettingsPasswordRequired;
|
||||
title = TextKey.PasswordDialog_SettingsPasswordRequiredTitle;
|
||||
break;
|
||||
}
|
||||
|
||||
var dialog = uiFactory.CreatePasswordDialog(text.Get(message), text.Get(title));
|
||||
var result = dialog.Show(runtimeWindow);
|
||||
|
||||
|
|
Loading…
Reference in a new issue