diff --git a/SafeExamBrowser.Client.UnitTests/Communication/ClientHostTests.cs b/SafeExamBrowser.Client.UnitTests/Communication/ClientHostTests.cs
index 939b2b39..a2cfe768 100644
--- a/SafeExamBrowser.Client.UnitTests/Communication/ClientHostTests.cs
+++ b/SafeExamBrowser.Client.UnitTests/Communication/ClientHostTests.cs
@@ -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);
diff --git a/SafeExamBrowser.Client/ClientController.cs b/SafeExamBrowser.Client/ClientController.cs
index 624c2c37..161b95a2 100644
--- a/SafeExamBrowser.Client/ClientController.cs
+++ b/SafeExamBrowser.Client/ClientController.cs
@@ -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);
diff --git a/SafeExamBrowser.Configuration/DataFormats/XmlParser.cs b/SafeExamBrowser.Configuration/DataFormats/XmlParser.cs
index eaa567e3..434c96c5 100644
--- a/SafeExamBrowser.Configuration/DataFormats/XmlParser.cs
+++ b/SafeExamBrowser.Configuration/DataFormats/XmlParser.cs
@@ -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;
diff --git a/SafeExamBrowser.Contracts/Communication/Data/PasswordRequestPurpose.cs b/SafeExamBrowser.Contracts/Communication/Data/PasswordRequestPurpose.cs
index 20a79136..d4a98763 100644
--- a/SafeExamBrowser.Contracts/Communication/Data/PasswordRequestPurpose.cs
+++ b/SafeExamBrowser.Contracts/Communication/Data/PasswordRequestPurpose.cs
@@ -14,9 +14,14 @@ namespace SafeExamBrowser.Contracts.Communication.Data
public enum PasswordRequestPurpose
{
///
- /// 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.
///
- Administrator,
+ LocalAdministrator,
+
+ ///
+ /// The password is to be used as settings password for the local client configuration.
+ ///
+ LocalSettings,
///
/// The password is to be used as settings password for an application configuration.
diff --git a/SafeExamBrowser.Contracts/I18n/TextKey.cs b/SafeExamBrowser.Contracts/I18n/TextKey.cs
index 0fbf4262..2e2bd662 100644
--- a/SafeExamBrowser.Contracts/I18n/TextKey.cs
+++ b/SafeExamBrowser.Contracts/I18n/TextKey.cs
@@ -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,
diff --git a/SafeExamBrowser.I18n/Text.xml b/SafeExamBrowser.I18n/Text.xml
index 9d10002c..adf381fe 100644
--- a/SafeExamBrowser.I18n/Text.xml
+++ b/SafeExamBrowser.I18n/Text.xml
@@ -213,18 +213,24 @@
Waiting for the runtime to disconnect
-
- Please enter the administrator password for the application configuration:
-
-
- Administrator Password Required
-
Cancel
Confirm
+
+ Please enter the administrator password for the local client configuration:
+
+
+ Administrator Password Required
+
+
+ Please enter the settings password for the local client configuration:
+
+
+ Settings Password Required
+
Please enter the quit password in order to terminate the application:
@@ -232,7 +238,7 @@
Quit Password Required
- Please enter the settings password for the application configuration:
+ Please enter the settings password for the selected application configuration:
Settings Password Required
diff --git a/SafeExamBrowser.Runtime/Operations/ClientOperation.cs b/SafeExamBrowser.Runtime/Operations/ClientOperation.cs
index c140e5ea..ff46d4d0 100644
--- a/SafeExamBrowser.Runtime/Operations/ClientOperation.cs
+++ b/SafeExamBrowser.Runtime/Operations/ClientOperation.cs
@@ -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");
diff --git a/SafeExamBrowser.Runtime/Operations/ConfigurationOperation.cs b/SafeExamBrowser.Runtime/Operations/ConfigurationOperation.cs
index 14b8cebd..07a75cb9 100644
--- a/SafeExamBrowser.Runtime/Operations/ConfigurationOperation.cs
+++ b/SafeExamBrowser.Runtime/Operations/ConfigurationOperation.cs
@@ -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
+ }
}
}
diff --git a/SafeExamBrowser.Runtime/Operations/SessionActivationOperation.cs b/SafeExamBrowser.Runtime/Operations/SessionActivationOperation.cs
index c7aa8dfb..71548669 100644
--- a/SafeExamBrowser.Runtime/Operations/SessionActivationOperation.cs
+++ b/SafeExamBrowser.Runtime/Operations/SessionActivationOperation.cs
@@ -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;
diff --git a/SafeExamBrowser.Runtime/RuntimeController.cs b/SafeExamBrowser.Runtime/RuntimeController.cs
index 531bf694..08fd1573 100644
--- a/SafeExamBrowser.Runtime/RuntimeController.cs
+++ b/SafeExamBrowser.Runtime/RuntimeController.cs
@@ -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);