diff --git a/SafeExamBrowser.Client.UnitTests/Communication/ClientHostTests.cs b/SafeExamBrowser.Client.UnitTests/Communication/ClientHostTests.cs index 7ebfbaf1..4d374bc0 100644 --- a/SafeExamBrowser.Client.UnitTests/Communication/ClientHostTests.cs +++ b/SafeExamBrowser.Client.UnitTests/Communication/ClientHostTests.cs @@ -49,7 +49,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication { var token = Guid.NewGuid(); - sut.StartupToken = token; + sut.AuthenticationToken = token; var response = sut.Connect(token); @@ -64,7 +64,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication { var token = Guid.NewGuid(); - sut.StartupToken = token; + sut.AuthenticationToken = token; var response = sut.Connect(Guid.NewGuid()); @@ -78,7 +78,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication { var token = Guid.NewGuid(); - sut.StartupToken = token; + sut.AuthenticationToken = token; var response1 = sut.Connect(token); var response2 = sut.Connect(token); @@ -102,7 +102,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication var token = Guid.NewGuid(); sut.RuntimeDisconnected += () => eventFired = true; - sut.StartupToken = token; + sut.AuthenticationToken = token; var connectionResponse = sut.Connect(token); var response = sut.Disconnect(new DisconnectionMessage { CommunicationToken = connectionResponse.CommunicationToken.Value }); @@ -116,11 +116,11 @@ namespace SafeExamBrowser.Client.UnitTests.Communication [TestMethod] public void MustNotAllowReconnectionAfterDisconnection() { - var token = sut.StartupToken = Guid.NewGuid(); + var token = sut.AuthenticationToken = Guid.NewGuid(); var response = sut.Connect(token); sut.Disconnect(new DisconnectionMessage { CommunicationToken = response.CommunicationToken.Value }); - sut.StartupToken = token = Guid.NewGuid(); + sut.AuthenticationToken = token = Guid.NewGuid(); response = sut.Connect(token); @@ -130,7 +130,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication [TestMethod] public void MustHandleAuthenticationRequestCorrectly() { - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new SimpleMessage(SimpleMessagePurport.Authenticate) { CommunicationToken = token }; @@ -157,7 +157,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication messageBoxRequested = args.Action == action && args.Icon == icon && args.Message == message && args.RequestId == requestId && args.Title == title; resetEvent.Set(); }; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var request = new MessageBoxRequestMessage(action, icon, message, requestId, title) { CommunicationToken = token }; @@ -184,7 +184,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication passwordRequested = args.Purpose == purpose && args.RequestId == requestId; resetEvent.Set(); }; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new PasswordRequestMessage(purpose, requestId) { CommunicationToken = token }; @@ -210,7 +210,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication reconfigurationDenied = new Uri(args.ConfigurationPath).Equals(new Uri(filePath)); resetEvent.Set(); }; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new ReconfigurationDeniedMessage(filePath) { CommunicationToken = token }; @@ -230,7 +230,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication var shutdownRequested = false; sut.Shutdown += () => shutdownRequested = true; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new SimpleMessage(SimpleMessagePurport.Shutdown) { CommunicationToken = token }; @@ -245,7 +245,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication [TestMethod] public void MustReturnUnknownMessageAsDefault() { - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new TestMessage { CommunicationToken = token } as Message; @@ -266,7 +266,7 @@ namespace SafeExamBrowser.Client.UnitTests.Communication [TestMethod] public void MustNotFailIfNoEventHandlersSubscribed() { - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; diff --git a/SafeExamBrowser.Client/Communication/ClientHost.cs b/SafeExamBrowser.Client/Communication/ClientHost.cs index 89d60461..3f3c9b35 100644 --- a/SafeExamBrowser.Client/Communication/ClientHost.cs +++ b/SafeExamBrowser.Client/Communication/ClientHost.cs @@ -20,7 +20,7 @@ namespace SafeExamBrowser.Client.Communication private bool allowConnection = true; private int processId; - public Guid StartupToken { private get; set; } + public Guid AuthenticationToken { private get; set; } public bool IsConnected { get; private set; } public event CommunicationEventHandler MessageBoxRequested; @@ -41,7 +41,7 @@ namespace SafeExamBrowser.Client.Communication protected override bool OnConnect(Guid? token) { - var authenticated = StartupToken == token; + var authenticated = AuthenticationToken == token; var accepted = allowConnection && authenticated; if (accepted) diff --git a/SafeExamBrowser.Client/CompositionRoot.cs b/SafeExamBrowser.Client/CompositionRoot.cs index 68b94b36..cfc0e21d 100644 --- a/SafeExamBrowser.Client/CompositionRoot.cs +++ b/SafeExamBrowser.Client/CompositionRoot.cs @@ -51,11 +51,11 @@ namespace SafeExamBrowser.Client { internal class CompositionRoot { + private Guid authenticationToken; private ClientConfiguration configuration; private string logFilePath; private LogLevel logLevel; private string runtimeHostUri; - private Guid startupToken; private UserInterfaceMode uiMode; private IActionCenter actionCenter; @@ -110,7 +110,7 @@ namespace SafeExamBrowser.Client var operations = new Queue(); operations.Enqueue(new I18nOperation(logger, text, textResource)); - operations.Enqueue(new RuntimeConnectionOperation(logger, runtimeProxy, startupToken)); + operations.Enqueue(new RuntimeConnectionOperation(logger, runtimeProxy, authenticationToken)); operations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeProxy)); operations.Enqueue(new DelegateOperation(UpdateAppConfig)); operations.Enqueue(new LazyInitializationOperation(BuildClientHostOperation)); @@ -166,14 +166,14 @@ namespace SafeExamBrowser.Client var hasLogfilePath = Uri.TryCreate(args[1], UriKind.Absolute, out Uri filePath) && filePath.IsFile; var hasLogLevel = Enum.TryParse(args[2], out LogLevel level); var hasHostUri = Uri.TryCreate(args[3], UriKind.Absolute, out Uri hostUri) && hostUri.IsWellFormedOriginalString(); - var hasToken = Guid.TryParse(args[4], out Guid token); + var hasAuthenticationToken = Guid.TryParse(args[4], out Guid token); - if (hasLogfilePath && hasLogLevel && hasHostUri && hasToken) + if (hasLogfilePath && hasLogLevel && hasHostUri && hasAuthenticationToken) { logFilePath = args[1]; logLevel = level; runtimeHostUri = args[3]; - startupToken = token; + authenticationToken = token; uiMode = args.Length == 6 && Enum.TryParse(args[5], out uiMode) ? uiMode : UserInterfaceMode.Desktop; return; @@ -222,7 +222,7 @@ namespace SafeExamBrowser.Client var operation = new CommunicationHostOperation(host, logger); clientHost = host; - clientHost.StartupToken = startupToken; + clientHost.AuthenticationToken = authenticationToken; return operation; } diff --git a/SafeExamBrowser.Communication.UnitTests/Proxies/ServiceProxyTests.cs b/SafeExamBrowser.Communication.UnitTests/Proxies/ServiceProxyTests.cs index 7b9308e5..e8ade396 100644 --- a/SafeExamBrowser.Communication.UnitTests/Proxies/ServiceProxyTests.cs +++ b/SafeExamBrowser.Communication.UnitTests/Proxies/ServiceProxyTests.cs @@ -68,7 +68,7 @@ namespace SafeExamBrowser.Communication.UnitTests.Proxies { sut.Ignore = true; - var communication = sut.StartSession(Guid.Empty, null); + var communication = sut.StartSession(null); Assert.IsTrue(communication.Success); proxy.Verify(p => p.Send(It.IsAny()), Times.Never); diff --git a/SafeExamBrowser.Communication/Proxies/ServiceProxy.cs b/SafeExamBrowser.Communication/Proxies/ServiceProxy.cs index bdc8c432..88caff61 100644 --- a/SafeExamBrowser.Communication/Proxies/ServiceProxy.cs +++ b/SafeExamBrowser.Communication/Proxies/ServiceProxy.cs @@ -8,7 +8,7 @@ using System; using SafeExamBrowser.Contracts.Communication.Proxies; -using SafeExamBrowser.Contracts.Configuration.Settings; +using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Logging; namespace SafeExamBrowser.Communication.Proxies @@ -45,7 +45,7 @@ namespace SafeExamBrowser.Communication.Proxies return base.Disconnect(); } - public CommunicationResult StartSession(Guid sessionId, Settings settings) + public CommunicationResult StartSession(ServiceConfiguration configuration) { if (IgnoreOperation(nameof(StartSession))) { diff --git a/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs b/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs index b951b151..b8f91349 100644 --- a/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs +++ b/SafeExamBrowser.Configuration.UnitTests/ConfigurationRepositoryTests.cs @@ -275,10 +275,11 @@ namespace SafeExamBrowser.Configuration.UnitTests var appConfig = sut.InitializeAppConfig(); var configuration = sut.InitializeSessionConfiguration(); - Assert.IsInstanceOfType(configuration.AppConfig, typeof(AppConfig)); - Assert.IsInstanceOfType(configuration.Id, typeof(Guid)); Assert.IsNull(configuration.Settings); - Assert.IsInstanceOfType(configuration.StartupToken, typeof(Guid)); + Assert.IsInstanceOfType(configuration.AppConfig, typeof(AppConfig)); + Assert.IsInstanceOfType(configuration.ClientAuthenticationToken, typeof(Guid)); + Assert.IsInstanceOfType(configuration.ServiceAuthenticationToken, typeof(Guid)); + Assert.IsInstanceOfType(configuration.SessionId, typeof(Guid)); } [TestMethod] @@ -309,10 +310,12 @@ namespace SafeExamBrowser.Configuration.UnitTests var secondSession = sut.InitializeSessionConfiguration(); var thirdSession = sut.InitializeSessionConfiguration(); - Assert.AreNotEqual(firstSession.Id, secondSession.Id); - Assert.AreNotEqual(firstSession.StartupToken, secondSession.StartupToken); - Assert.AreNotEqual(secondSession.Id, thirdSession.Id); - Assert.AreNotEqual(secondSession.StartupToken, thirdSession.StartupToken); + Assert.AreNotEqual(firstSession.SessionId, secondSession.SessionId); + Assert.AreNotEqual(firstSession.ClientAuthenticationToken, secondSession.ClientAuthenticationToken); + Assert.AreNotEqual(firstSession.ServiceAuthenticationToken, secondSession.ServiceAuthenticationToken); + Assert.AreNotEqual(secondSession.SessionId, thirdSession.SessionId); + Assert.AreNotEqual(secondSession.ClientAuthenticationToken, thirdSession.ClientAuthenticationToken); + Assert.AreNotEqual(secondSession.ServiceAuthenticationToken, thirdSession.ServiceAuthenticationToken); } private void RegisterModules() diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Security.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Security.cs index 0ad00558..5e119543 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Security.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.Security.cs @@ -33,5 +33,16 @@ namespace SafeExamBrowser.Configuration.ConfigurationData settings.KioskMode = KioskMode.None; } } + + private void MapServicePolicy(Settings settings, object value) + { + const int WARN = 1; + const int FORCE = 2; + + if (value is int policy) + { + settings.ServicePolicy = policy == FORCE ? ServicePolicy.Mandatory : (policy == WARN ? ServicePolicy.Warn : ServicePolicy.Optional); + } + } } } diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs index ee9fb9fd..5918021a 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataMapper.cs @@ -21,6 +21,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData MapConfigurationFileSettings(item.Key, item.Value, settings); MapGeneralSettings(item.Key, item.Value, settings); MapInputSettings(item.Key, item.Value, settings); + MapSecuritySettings(item.Key, item.Value, settings); MapUserInterfaceSettings(item.Key, item.Value, settings); } @@ -174,6 +175,16 @@ namespace SafeExamBrowser.Configuration.ConfigurationData } } + private void MapSecuritySettings(string key, object value, Settings settings) + { + switch (key) + { + case Keys.Security.ServicePolicy: + MapServicePolicy(settings, value); + break; + } + } + private void MapUserInterfaceSettings(string key, object value, Settings settings) { switch (key) diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs index 4ba33965..e7f9213f 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs @@ -72,7 +72,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData return appConfig; } - internal ISessionConfiguration InitializeSessionConfiguration() + internal SessionConfiguration InitializeSessionConfiguration() { var configuration = new SessionConfiguration(); @@ -80,8 +80,9 @@ namespace SafeExamBrowser.Configuration.ConfigurationData appConfig.ClientAddress = $"{BASE_ADDRESS}/client/{Guid.NewGuid()}"; configuration.AppConfig = appConfig.Clone(); - configuration.Id = Guid.NewGuid(); - configuration.StartupToken = Guid.NewGuid(); + configuration.ClientAuthenticationToken = Guid.NewGuid(); + configuration.ServiceAuthenticationToken = Guid.NewGuid(); + configuration.SessionId = Guid.NewGuid(); return configuration; } diff --git a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs index 4e3c3192..bc6953f3 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/Keys.cs @@ -116,6 +116,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData { internal const string KioskModeCreateNewDesktop = "createNewDesktop"; internal const string KioskModeDisableExplorerShell = "killExplorerShell"; + internal const string ServicePolicy = "sebServicePolicy"; } internal static class UserInterface diff --git a/SafeExamBrowser.Configuration/ConfigurationRepository.cs b/SafeExamBrowser.Configuration/ConfigurationRepository.cs index 137cc933..4630f67f 100644 --- a/SafeExamBrowser.Configuration/ConfigurationRepository.cs +++ b/SafeExamBrowser.Configuration/ConfigurationRepository.cs @@ -94,7 +94,7 @@ namespace SafeExamBrowser.Configuration return dataValues.InitializeAppConfig(); } - public ISessionConfiguration InitializeSessionConfiguration() + public SessionConfiguration InitializeSessionConfiguration() { return dataValues.InitializeSessionConfiguration(); } diff --git a/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj b/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj index ef04b34c..b266185d 100644 --- a/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj +++ b/SafeExamBrowser.Configuration/SafeExamBrowser.Configuration.csproj @@ -94,7 +94,6 @@ - diff --git a/SafeExamBrowser.Configuration/SessionConfiguration.cs b/SafeExamBrowser.Configuration/SessionConfiguration.cs deleted file mode 100644 index ef15e800..00000000 --- a/SafeExamBrowser.Configuration/SessionConfiguration.cs +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -using System; -using SafeExamBrowser.Contracts.Configuration; -using SafeExamBrowser.Contracts.Configuration.Settings; - -namespace SafeExamBrowser.Configuration -{ - internal class SessionConfiguration : ISessionConfiguration - { - public AppConfig AppConfig { get; set; } - public Guid Id { get; set; } - public Settings Settings { get; set; } - public Guid StartupToken { get; set; } - } -} diff --git a/SafeExamBrowser.Contracts/Communication/Hosts/IClientHost.cs b/SafeExamBrowser.Contracts/Communication/Hosts/IClientHost.cs index 1c112b35..807c66ce 100644 --- a/SafeExamBrowser.Contracts/Communication/Hosts/IClientHost.cs +++ b/SafeExamBrowser.Contracts/Communication/Hosts/IClientHost.cs @@ -16,16 +16,16 @@ namespace SafeExamBrowser.Contracts.Communication.Hosts /// public interface IClientHost : ICommunicationHost { + /// + /// The token used for initial authentication with the runtime. + /// + Guid AuthenticationToken { set; } + /// /// Indicates whether the runtime has established a connection to this host. /// bool IsConnected { get; } - /// - /// The startup token used for initial authentication. - /// - Guid StartupToken { set; } - /// /// Event fired when the runtime requests a message box input from the user. /// diff --git a/SafeExamBrowser.Contracts/Communication/Hosts/IRuntimeHost.cs b/SafeExamBrowser.Contracts/Communication/Hosts/IRuntimeHost.cs index 261d76a6..61e69428 100644 --- a/SafeExamBrowser.Contracts/Communication/Hosts/IRuntimeHost.cs +++ b/SafeExamBrowser.Contracts/Communication/Hosts/IRuntimeHost.cs @@ -22,9 +22,9 @@ namespace SafeExamBrowser.Contracts.Communication.Hosts bool AllowConnection { get; set; } /// - /// The startup token used for initial authentication. + /// The token used for initial authentication. /// - Guid StartupToken { set; } + Guid AuthenticationToken { set; } /// /// Event fired when the client disconnected from the runtime. diff --git a/SafeExamBrowser.Contracts/Communication/ICommunication.cs b/SafeExamBrowser.Contracts/Communication/ICommunication.cs index f9bf388d..15c76975 100644 --- a/SafeExamBrowser.Contracts/Communication/ICommunication.cs +++ b/SafeExamBrowser.Contracts/Communication/ICommunication.cs @@ -10,6 +10,7 @@ using System; using System.ServiceModel; using SafeExamBrowser.Contracts.Communication.Data; using SafeExamBrowser.Contracts.Configuration; +using ServiceConfiguration = SafeExamBrowser.Contracts.Configuration.ServiceConfiguration; namespace SafeExamBrowser.Contracts.Communication { @@ -26,6 +27,7 @@ namespace SafeExamBrowser.Contracts.Communication [ServiceKnownType(typeof(PasswordRequestMessage))] [ServiceKnownType(typeof(ReconfigurationMessage))] [ServiceKnownType(typeof(ReconfigurationDeniedMessage))] + [ServiceKnownType(typeof(ServiceConfiguration))] [ServiceKnownType(typeof(SimpleMessage))] [ServiceKnownType(typeof(SimpleResponse))] public interface ICommunication diff --git a/SafeExamBrowser.Contracts/Communication/Proxies/IServiceProxy.cs b/SafeExamBrowser.Contracts/Communication/Proxies/IServiceProxy.cs index b4e85d80..9f819e58 100644 --- a/SafeExamBrowser.Contracts/Communication/Proxies/IServiceProxy.cs +++ b/SafeExamBrowser.Contracts/Communication/Proxies/IServiceProxy.cs @@ -7,7 +7,7 @@ */ using System; -using SafeExamBrowser.Contracts.Configuration.Settings; +using SafeExamBrowser.Contracts.Configuration; namespace SafeExamBrowser.Contracts.Communication.Proxies { @@ -28,9 +28,9 @@ namespace SafeExamBrowser.Contracts.Communication.Proxies bool IsConnected { get; } /// - /// Instructs the service to start a new session according to the given parameters. + /// Instructs the service to start a new session according to the given configuration. /// - CommunicationResult StartSession(Guid sessionId, Settings settings); + CommunicationResult StartSession(ServiceConfiguration configuration); /// /// Instructs the service to stop the specified session. diff --git a/SafeExamBrowser.Contracts/Configuration/ClientConfiguration.cs b/SafeExamBrowser.Contracts/Configuration/ClientConfiguration.cs index d707c2b0..d67da0f7 100644 --- a/SafeExamBrowser.Contracts/Configuration/ClientConfiguration.cs +++ b/SafeExamBrowser.Contracts/Configuration/ClientConfiguration.cs @@ -11,7 +11,7 @@ using System; namespace SafeExamBrowser.Contracts.Configuration { /// - /// Container for the configuration of the client application component. + /// The configuration for a session of the client application component. /// [Serializable] public class ClientConfiguration diff --git a/SafeExamBrowser.Contracts/Configuration/IConfigurationRepository.cs b/SafeExamBrowser.Contracts/Configuration/IConfigurationRepository.cs index b037df49..0e85442a 100644 --- a/SafeExamBrowser.Contracts/Configuration/IConfigurationRepository.cs +++ b/SafeExamBrowser.Contracts/Configuration/IConfigurationRepository.cs @@ -31,7 +31,7 @@ namespace SafeExamBrowser.Contracts.Configuration /// /// Initializes all relevant configuration data for a new session. /// - ISessionConfiguration InitializeSessionConfiguration(); + SessionConfiguration InitializeSessionConfiguration(); /// /// Loads the default settings. diff --git a/SafeExamBrowser.Contracts/Configuration/ServiceConfiguration.cs b/SafeExamBrowser.Contracts/Configuration/ServiceConfiguration.cs new file mode 100644 index 00000000..1dc3eeb1 --- /dev/null +++ b/SafeExamBrowser.Contracts/Configuration/ServiceConfiguration.cs @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +using System; + +namespace SafeExamBrowser.Contracts.Configuration +{ + /// + /// The configuration for a session of the service application component. + /// + [Serializable] + public class ServiceConfiguration + { + /// + /// The global application configuration. + /// + public AppConfig AppConfig { get; set; } + + /// + /// The token used for initial authentication with the runtime. + /// + public Guid AuthenticationToken { get; set; } + + /// + /// The unique identifier for the current session. + /// + public Guid SessionId { get; set; } + + /// + /// The application settings to be used by the service. + /// + public Settings.Settings Settings { get; set; } + } +} diff --git a/SafeExamBrowser.Contracts/Configuration/ISessionConfiguration.cs b/SafeExamBrowser.Contracts/Configuration/SessionConfiguration.cs similarity index 56% rename from SafeExamBrowser.Contracts/Configuration/ISessionConfiguration.cs rename to SafeExamBrowser.Contracts/Configuration/SessionConfiguration.cs index e3cf8787..3ba11124 100644 --- a/SafeExamBrowser.Contracts/Configuration/ISessionConfiguration.cs +++ b/SafeExamBrowser.Contracts/Configuration/SessionConfiguration.cs @@ -11,28 +11,33 @@ using System; namespace SafeExamBrowser.Contracts.Configuration { /// - /// Holds all session-related configuration data. + /// Container holding all session-related configuration data. /// - public interface ISessionConfiguration + public class SessionConfiguration { /// /// The active application configuration for this session. /// - AppConfig AppConfig { get; } + public AppConfig AppConfig { get; set; } + + /// + /// The token used for initial communication authentication with the client. + /// + public Guid ClientAuthenticationToken { get; set; } + + /// + /// The token used for initial communication authentication with the service. + /// + public Guid ServiceAuthenticationToken { get; set; } /// /// The unique session identifier. /// - Guid Id { get; } + public Guid SessionId { get; set; } /// /// The settings used for this session. /// - Settings.Settings Settings { get; set; } - - /// - /// The startup token used by the client and runtime components for initial authentication. - /// - Guid StartupToken { get; } + public Settings.Settings Settings { get; set; } } } diff --git a/SafeExamBrowser.Contracts/Configuration/Settings/ServicePolicy.cs b/SafeExamBrowser.Contracts/Configuration/Settings/ServicePolicy.cs index d6a29b49..f697d12c 100644 --- a/SafeExamBrowser.Contracts/Configuration/Settings/ServicePolicy.cs +++ b/SafeExamBrowser.Contracts/Configuration/Settings/ServicePolicy.cs @@ -21,6 +21,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings /// /// The service component is optional. If it is not running, all service-related actions are simply skipped. /// - Optional + Optional, + + /// + /// The service component should be running. If it is not running, the user will be warned that all service-related actions are skipped. + /// + Warn } } diff --git a/SafeExamBrowser.Contracts/I18n/TextKey.cs b/SafeExamBrowser.Contracts/I18n/TextKey.cs index 9f9aee4f..0c1cacdc 100644 --- a/SafeExamBrowser.Contracts/I18n/TextKey.cs +++ b/SafeExamBrowser.Contracts/I18n/TextKey.cs @@ -48,6 +48,10 @@ namespace SafeExamBrowser.Contracts.I18n MessageBox_ReconfigurationQuestionTitle, MessageBox_ReloadConfirmation, MessageBox_ReloadConfirmationTitle, + MessageBox_ServiceUnavailableError, + MessageBox_ServiceUnavailableErrorTitle, + MessageBox_ServiceUnavailableWarning, + MessageBox_ServiceUnavailableWarningTitle, MessageBox_SessionStartError, MessageBox_SessionStartErrorTitle, MessageBox_ShutdownError, diff --git a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj index 24cd39b1..37feb0ae 100644 --- a/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj +++ b/SafeExamBrowser.Contracts/SafeExamBrowser.Contracts.csproj @@ -60,6 +60,7 @@ + @@ -76,6 +77,7 @@ + @@ -133,10 +135,9 @@ - - + diff --git a/SafeExamBrowser.I18n/Text.xml b/SafeExamBrowser.I18n/Text.xml index 14ee3f73..bc473526 100644 --- a/SafeExamBrowser.I18n/Text.xml +++ b/SafeExamBrowser.I18n/Text.xml @@ -102,6 +102,18 @@ Reload? + + Failed to initialize the Safe Exam Browser service! The application is not allowed to start since the current configuration requires the service to be running. + + + Service Unavailable + + + Failed to initialize the Safe Exam Browser service. The application is allowed to start, but it should be ensured that the service is installed and running. + + + Service Unavailable + The application failed to start a new session! Please consult the application log for more information... diff --git a/SafeExamBrowser.Runtime.UnitTests/Communication/RuntimeHostTests.cs b/SafeExamBrowser.Runtime.UnitTests/Communication/RuntimeHostTests.cs index 392f4fa3..667cdd96 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Communication/RuntimeHostTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Communication/RuntimeHostTests.cs @@ -48,7 +48,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication var token = Guid.NewGuid(); sut.AllowConnection = true; - sut.StartupToken = token; + sut.AuthenticationToken = token; var response = sut.Connect(token); @@ -62,7 +62,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication var token = Guid.NewGuid(); sut.AllowConnection = true; - sut.StartupToken = token; + sut.AuthenticationToken = token; var response = sut.Connect(Guid.NewGuid()); @@ -76,7 +76,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication var token = Guid.NewGuid(); sut.AllowConnection = true; - sut.StartupToken = token; + sut.AuthenticationToken = token; var response1 = sut.Connect(token); var response2 = sut.Connect(token); @@ -100,7 +100,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication var token = Guid.NewGuid(); sut.AllowConnection = true; - sut.StartupToken = token; + sut.AuthenticationToken = token; sut.ClientDisconnected += () => disconnected = true; var connectionResponse = sut.Connect(token); @@ -117,13 +117,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication var token = Guid.NewGuid(); sut.AllowConnection = true; - sut.StartupToken = token; + sut.AuthenticationToken = token; var response = sut.Connect(token); sut.Disconnect(new DisconnectionMessage { CommunicationToken = response.CommunicationToken.Value }); sut.AllowConnection = true; - sut.StartupToken = token = Guid.NewGuid(); + sut.AuthenticationToken = token = Guid.NewGuid(); response = sut.Connect(token); @@ -137,7 +137,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication sut.AllowConnection = true; sut.ClientReady += () => clientReady = true; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new SimpleMessage(SimpleMessagePurport.ClientIsReady) { CommunicationToken = token }; @@ -157,7 +157,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication sut.AllowConnection = true; sut.ClientConfigurationNeeded += (a) => { args = a; args.ClientConfiguration = configuration; }; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new SimpleMessage(SimpleMessagePurport.ConfigurationNeeded) { CommunicationToken = token }; @@ -176,7 +176,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication sut.AllowConnection = true; sut.ShutdownRequested += () => shutdownRequested = true; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new SimpleMessage(SimpleMessagePurport.RequestShutdown) { CommunicationToken = token }; @@ -198,7 +198,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication sut.AllowConnection = true; sut.MessageBoxReplyReceived += (a) => { args = a; sync.Set(); }; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new MessageBoxReplyMessage(requestId, result) { CommunicationToken = token }; @@ -225,7 +225,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication sut.AllowConnection = true; sut.PasswordReceived += (a) => { args = a; sync.Set(); }; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new PasswordReplyMessage(requestId, success, password) { CommunicationToken = token }; @@ -251,7 +251,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication sut.AllowConnection = true; sut.ReconfigurationRequested += (a) => { args = a; sync.Set(); }; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new ReconfigurationMessage(path) { CommunicationToken = token }; @@ -270,7 +270,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication public void MustReturnUnknownMessageAsDefault() { sut.AllowConnection = true; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; var message = new TestMessage { CommunicationToken = token } as Message; @@ -292,7 +292,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Communication public void MustNotFailIfNoEventHandlersSubscribed() { sut.AllowConnection = true; - sut.StartupToken = Guid.Empty; + sut.AuthenticationToken = Guid.Empty; var token = sut.Connect(Guid.Empty).CommunicationToken.Value; diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/ClientOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/ClientOperationTests.cs index 6dd03762..920f0acc 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/ClientOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/ClientOperationTests.cs @@ -34,7 +34,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations private Mock processFactory; private Mock proxyFactory; private Mock runtimeHost; - private Mock session; + private SessionConfiguration session; private SessionContext sessionContext; private Settings settings; private ClientOperation sut; @@ -50,7 +50,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations proxy = new Mock(); proxyFactory = new Mock(); runtimeHost = new Mock(); - session = new Mock(); + session = new SessionConfiguration(); sessionContext = new SessionContext(); settings = new Settings(); terminated = new Action(() => @@ -59,10 +59,10 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations process.Raise(p => p.Terminated += null, 0); }); - session.SetupGet(s => s.AppConfig).Returns(appConfig); - session.SetupGet(s => s.Settings).Returns(settings); - sessionContext.Current = session.Object; - sessionContext.Next = session.Object; + session.AppConfig = appConfig; + session.Settings = settings; + sessionContext.Current = session; + sessionContext.Next = session; proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny())).Returns(proxy.Object); sut = new ClientOperation(logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, sessionContext, 0); diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/ClientTerminationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/ClientTerminationOperationTests.cs index 8a5a8248..56d0664d 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/ClientTerminationOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/ClientTerminationOperationTests.cs @@ -31,7 +31,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations private Mock processFactory; private Mock proxyFactory; private Mock runtimeHost; - private Mock session; + private SessionConfiguration session; private SessionContext sessionContext; private ClientTerminationOperation sut; @@ -47,7 +47,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations proxy = new Mock(); proxyFactory = new Mock(); runtimeHost = new Mock(); - session = new Mock(); + session = new SessionConfiguration(); sessionContext = new SessionContext(); terminated = new Action(() => { @@ -55,11 +55,11 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations process.Raise(p => p.Terminated += null, 0); }); - session.SetupGet(s => s.AppConfig).Returns(appConfig); + session.AppConfig = appConfig; sessionContext.ClientProcess = process.Object; sessionContext.ClientProxy = proxy.Object; - sessionContext.Current = session.Object; - sessionContext.Next = session.Object; + sessionContext.Current = session; + sessionContext.Next = session; proxyFactory.Setup(f => f.CreateClientProxy(It.IsAny())).Returns(proxy.Object); sut = new ClientTerminationOperation(logger.Object, processFactory.Object, proxyFactory.Object, runtimeHost.Object, sessionContext, 0); diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs index 806351ba..40b3a0f8 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/ConfigurationOperationTests.cs @@ -30,8 +30,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations private Mock hashAlgorithm; private Mock logger; private Mock repository; - private Mock currentSession; - private Mock nextSession; + private SessionConfiguration currentSession; + private SessionConfiguration nextSession; private SessionContext sessionContext; [TestInitialize] @@ -41,16 +41,16 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations hashAlgorithm = new Mock(); logger = new Mock(); repository = new Mock(); - currentSession = new Mock(); - nextSession = new Mock(); + currentSession = new SessionConfiguration(); + nextSession = new SessionConfiguration(); sessionContext = new SessionContext(); appConfig.AppDataFilePath = $@"C:\Not\Really\AppData\File.xml"; appConfig.ProgramDataFilePath = $@"C:\Not\Really\ProgramData\File.xml"; - currentSession.SetupGet(s => s.AppConfig).Returns(appConfig); - nextSession.SetupGet(s => s.AppConfig).Returns(appConfig); - sessionContext.Current = currentSession.Object; - sessionContext.Next = nextSession.Object; + currentSession.AppConfig = appConfig; + nextSession.AppConfig = appConfig; + sessionContext.Current = currentSession; + sessionContext.Next = nextSession; } [TestMethod] @@ -112,7 +112,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam }; var url = @"http://www.safeexambrowser.org/whatever.seb"; - nextSession.SetupGet(s => s.Settings).Returns(settings); + nextSession.Settings = settings; repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, It.IsAny())).Returns(LoadStatus.LoadWithBrowser); var sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); @@ -125,20 +125,17 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations [TestMethod] public void Perform_MustFallbackToDefaultsAsLastPrio() { - var actualSettings = default(Settings); var defaultSettings = new Settings(); repository.Setup(r => r.LoadDefaultSettings()).Returns(defaultSettings); - nextSession.SetupSet(s => s.Settings = It.IsAny()).Callback(s => actualSettings = s); var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var result = sut.Perform(); repository.Verify(r => r.LoadDefaultSettings(), Times.Once); - nextSession.VerifySet(s => s.Settings = defaultSettings); Assert.AreEqual(OperationResult.Success, result); - Assert.AreSame(defaultSettings, actualSettings); + Assert.AreSame(defaultSettings, nextSession.Settings); } [TestMethod] @@ -241,26 +238,24 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations [TestMethod] public void Perform_MustNotFailWithoutCommandLineArgs() { - var actualSettings = default(Settings); var defaultSettings = new Settings(); var result = OperationResult.Failed; repository.Setup(r => r.LoadDefaultSettings()).Returns(defaultSettings); - nextSession.SetupSet(s => s.Settings = It.IsAny()).Callback(s => actualSettings = s); var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); result = sut.Perform(); repository.Verify(r => r.LoadDefaultSettings(), Times.Once); Assert.AreEqual(OperationResult.Success, result); - Assert.AreSame(defaultSettings, actualSettings); + Assert.AreSame(defaultSettings, nextSession.Settings); sut = new ConfigurationOperation(new string[] { }, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); result = sut.Perform(); repository.Verify(r => r.LoadDefaultSettings(), Times.Exactly(2)); Assert.AreEqual(OperationResult.Success, result); - Assert.AreSame(defaultSettings, actualSettings); + Assert.AreSame(defaultSettings, nextSession.Settings); } [TestMethod] @@ -285,7 +280,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations repository.Setup(r => r.TryLoadSettings(It.IsAny(), out settings, It.IsAny())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.Is(u => u.LocalPath.Contains(FILE_NAME)), out localSettings, It.IsAny())).Returns(LoadStatus.Success); - nextSession.SetupGet(s => s.Settings).Returns(settings); + nextSession.Settings = settings; var sut = new ConfigurationOperation(new[] { "blubb.exe", url }, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); sut.ActionRequired += args => @@ -338,7 +333,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var nextSettings = new Settings { AdminPasswordHash = "9876", ConfigurationMode = ConfigurationMode.ConfigureClient }; var url = @"http://www.safeexambrowser.org/whatever.seb"; - nextSession.SetupGet(s => s.Settings).Returns(nextSettings); + nextSession.Settings = nextSettings; hashAlgorithm.Setup(h => h.GenerateHashFor(It.Is(p => p == password))).Returns(currentSettings.AdminPasswordHash); repository.Setup(r => r.TryLoadSettings(It.IsAny(), out currentSettings, It.IsAny())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.Is(u => u.AbsoluteUri == url), out nextSettings, It.IsAny())).Returns(LoadStatus.Success); @@ -368,7 +363,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var nextSettings = new Settings { AdminPasswordHash = "1234", ConfigurationMode = ConfigurationMode.ConfigureClient }; var url = @"http://www.safeexambrowser.org/whatever.seb"; - nextSession.SetupGet(s => s.Settings).Returns(nextSettings); + nextSession.Settings = nextSettings; repository.Setup(r => r.TryLoadSettings(It.IsAny(), out currentSettings, It.IsAny())).Returns(LoadStatus.Success); repository.Setup(r => r.TryLoadSettings(It.Is(u => u.AbsoluteUri == url), out nextSettings, It.IsAny())).Returns(LoadStatus.Success); repository.Setup(r => r.ConfigureClientWith(It.IsAny(), It.IsAny())).Returns(SaveStatus.Success); @@ -452,7 +447,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var url = @"http://www.safeexambrowser.org/whatever.seb"; appConfig.AppDataFilePath = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), nameof(Operations), "Testdata", FILE_NAME); - nextSession.SetupGet(s => s.Settings).Returns(nextSettings); + nextSession.Settings = nextSettings; hashAlgorithm.Setup(h => h.GenerateHashFor(It.Is(p => p == password))).Returns(currentSettings.AdminPasswordHash); repository.Setup(r => r.TryLoadSettings(It.IsAny(), out currentSettings, It.IsAny())).Returns(LoadStatus.Success); @@ -504,14 +499,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME)); var settings = new Settings { ConfigurationMode = ConfigurationMode.Exam }; - currentSession.SetupGet(s => s.Settings).Returns(currentSettings); + currentSession.Settings = currentSettings; sessionContext.ReconfigurationFilePath = resource.LocalPath; repository.Setup(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, It.IsAny())).Returns(LoadStatus.Success); var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var result = sut.Repeat(); - nextSession.VerifySet(s => s.Settings = settings, Times.Once); repository.Verify(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, It.IsAny()), Times.AtLeastOnce); repository.Verify(r => r.ConfigureClientWith(It.Is(u => u.Equals(resource)), It.IsAny()), Times.Never); @@ -526,7 +520,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME)); var settings = new Settings { ConfigurationMode = ConfigurationMode.ConfigureClient }; - currentSession.SetupGet(s => s.Settings).Returns(currentSettings); + currentSession.Settings = currentSettings; sessionContext.ReconfigurationFilePath = resource.LocalPath; repository.Setup(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, It.IsAny())).Returns(LoadStatus.Success); repository.Setup(r => r.ConfigureClientWith(It.Is(u => u.Equals(resource)), It.IsAny())).Returns(SaveStatus.Success); @@ -534,7 +528,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var result = sut.Repeat(); - nextSession.VerifySet(s => s.Settings = settings, Times.Once); repository.Verify(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, It.IsAny()), Times.AtLeastOnce); repository.Verify(r => r.ConfigureClientWith(It.Is(u => u.Equals(resource)), It.IsAny()), Times.Once); @@ -571,7 +564,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var resource = new Uri(Path.Combine(location, nameof(Operations), "Testdata", FILE_NAME)); var settings = new Settings { ConfigurationMode = ConfigurationMode.ConfigureClient }; - currentSession.SetupGet(s => s.Settings).Returns(currentSettings); + currentSession.Settings = currentSettings; sessionContext.ReconfigurationFilePath = resource.LocalPath; repository.Setup(r => r.TryLoadSettings(It.Is(u => u.Equals(resource)), out settings, It.IsAny())).Returns(LoadStatus.PasswordNeeded); @@ -590,14 +583,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations } [TestMethod] - public void Rever_MustDoNothing() + public void Revert_MustDoNothing() { var sut = new ConfigurationOperation(null, repository.Object, hashAlgorithm.Object, logger.Object, sessionContext); var result = sut.Revert(); - currentSession.VerifyNoOtherCalls(); hashAlgorithm.VerifyNoOtherCalls(); - nextSession.VerifyNoOtherCalls(); repository.VerifyNoOtherCalls(); Assert.AreEqual(OperationResult.Success, result); diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs index 6752748c..f8da212c 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeOperationTests.cs @@ -20,12 +20,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations [TestClass] public class KioskModeOperationTests { - private Mock currentSession; + private SessionConfiguration currentSession; private Settings currentSettings; private Mock desktopFactory; private Mock explorerShell; private Mock logger; - private Mock nextSession; + private SessionConfiguration nextSession; private Settings nextSettings; private Mock processFactory; private SessionContext sessionContext; @@ -35,20 +35,20 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations [TestInitialize] public void Initialize() { - currentSession = new Mock(); + currentSession = new SessionConfiguration(); currentSettings = new Settings(); desktopFactory = new Mock(); explorerShell = new Mock(); logger = new Mock(); - nextSession = new Mock(); + nextSession = new SessionConfiguration(); nextSettings = new Settings(); processFactory = new Mock(); sessionContext = new SessionContext(); - currentSession.SetupGet(s => s.Settings).Returns(currentSettings); - nextSession.SetupGet(s => s.Settings).Returns(nextSettings); - sessionContext.Current = currentSession.Object; - sessionContext.Next = nextSession.Object; + currentSession.Settings = currentSettings; + nextSession.Settings = nextSettings; + sessionContext.Current = currentSession; + sessionContext.Next = nextSession; sut = new KioskModeOperation(desktopFactory.Object, explorerShell.Object, logger.Object, processFactory.Object, sessionContext); } diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeTerminationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeTerminationOperationTests.cs index 53c4a351..23c40c11 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeTerminationOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/KioskModeTerminationOperationTests.cs @@ -23,32 +23,32 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations private Mock desktopFactory; private Mock explorerShell; private Mock logger; - private Mock nextSession; + private SessionConfiguration nextSession; private Settings nextSettings; private Mock processFactory; private SessionContext sessionContext; private KioskModeTerminationOperation sut; - private Mock currentSession; + private SessionConfiguration currentSession; private Settings currentSettings; [TestInitialize] public void Initialize() { - currentSession = new Mock(); + currentSession = new SessionConfiguration(); currentSettings = new Settings(); desktopFactory = new Mock(); explorerShell = new Mock(); logger = new Mock(); - nextSession = new Mock(); + nextSession = new SessionConfiguration(); nextSettings = new Settings(); processFactory = new Mock(); sessionContext = new SessionContext(); - currentSession.SetupGet(s => s.Settings).Returns(currentSettings); - nextSession.SetupGet(s => s.Settings).Returns(nextSettings); - sessionContext.Current = currentSession.Object; - sessionContext.Next = nextSession.Object; + currentSession.Settings = currentSettings; + nextSession.Settings = nextSettings; + sessionContext.Current = currentSession; + sessionContext.Next = nextSession; sut = new KioskModeTerminationOperation(desktopFactory.Object, explorerShell.Object, logger.Object, processFactory.Object, sessionContext); } @@ -58,11 +58,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var result = sut.Perform(); - currentSession.VerifyNoOtherCalls(); desktopFactory.VerifyNoOtherCalls(); explorerShell.VerifyNoOtherCalls(); logger.VerifyNoOtherCalls(); - nextSession.VerifyNoOtherCalls(); processFactory.VerifyNoOtherCalls(); Assert.AreEqual(OperationResult.Success, result); @@ -178,11 +176,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var result = sut.Revert(); - currentSession.VerifyNoOtherCalls(); desktopFactory.VerifyNoOtherCalls(); explorerShell.VerifyNoOtherCalls(); logger.VerifyNoOtherCalls(); - nextSession.VerifyNoOtherCalls(); processFactory.VerifyNoOtherCalls(); Assert.AreEqual(OperationResult.Success, result); diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs index 4be304bb..644d4fd4 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs @@ -25,7 +25,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations private Mock logger; private Mock runtimeHost; private Mock service; - private Mock session; + private SessionConfiguration session; private SessionContext sessionContext; private Settings settings; private ServiceOperation sut; @@ -36,13 +36,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations logger = new Mock(); runtimeHost = new Mock(); service = new Mock(); - session = new Mock(); + session = new SessionConfiguration(); sessionContext = new SessionContext(); settings = new Settings(); - sessionContext.Current = session.Object; - sessionContext.Next = session.Object; - session.SetupGet(s => s.Settings).Returns(settings); + sessionContext.Current = session; + sessionContext.Next = session; + session.Settings = settings; settings.ServicePolicy = ServicePolicy.Mandatory; sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, 0); @@ -70,13 +70,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations service.SetupGet(s => s.IsConnected).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true); service - .Setup(s => s.StartSession(It.IsAny(), It.IsAny())) + .Setup(s => s.StartSession(It.IsAny())) .Returns(new CommunicationResult(true)) .Callback(() => runtimeHost.Raise(h => h.ServiceSessionStarted += null)); var result = sut.Perform(); - service.Verify(s => s.StartSession(It.IsAny(), It.IsAny()), Times.Once); + service.Verify(s => s.StartSession(It.IsAny()), Times.Once); Assert.AreEqual(OperationResult.Success, result); } @@ -87,13 +87,13 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations service.SetupGet(s => s.IsConnected).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true); service - .Setup(s => s.StartSession(It.IsAny(), It.IsAny())) + .Setup(s => s.StartSession(It.IsAny())) .Returns(new CommunicationResult(true)) .Callback(() => runtimeHost.Raise(h => h.ServiceFailed += null)); var result = sut.Perform(); - service.Verify(s => s.StartSession(It.IsAny(), It.IsAny()), Times.Once); + service.Verify(s => s.StartSession(It.IsAny()), Times.Once); Assert.AreEqual(OperationResult.Failed, result); } @@ -108,7 +108,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations service.SetupGet(s => s.IsConnected).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true); - service.Setup(s => s.StartSession(It.IsAny(), It.IsAny())).Returns(new CommunicationResult(true)); + service.Setup(s => s.StartSession(It.IsAny())).Returns(new CommunicationResult(true)); sut = new ServiceOperation(logger.Object, runtimeHost.Object, service.Object, sessionContext, TIMEOUT); @@ -116,7 +116,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var result = sut.Perform(); after = DateTime.Now; - service.Verify(s => s.StartSession(It.IsAny(), It.IsAny()), Times.Once); + service.Verify(s => s.StartSession(It.IsAny()), Times.Once); Assert.AreEqual(OperationResult.Failed, result); Assert.IsTrue(after - before >= new TimeSpan(0, 0, 0, 0, TIMEOUT)); @@ -130,7 +130,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations sut.Perform(); - service.Verify(s => s.StartSession(It.IsAny(), It.IsAny()), Times.Never); + service.Verify(s => s.StartSession(It.IsAny()), Times.Never); } [TestMethod] @@ -172,7 +172,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations service.Verify(s => s.Connect(It.IsAny(), It.IsAny()), Times.Once); service.Verify(s => s.StopSession(It.IsAny()), Times.Once); - service.Verify(s => s.StartSession(It.IsAny(), It.IsAny()), Times.Exactly(2)); + service.Verify(s => s.StartSession(It.IsAny()), Times.Exactly(2)); service.Verify(s => s.Disconnect(), Times.Never); Assert.AreEqual(OperationResult.Success, result); @@ -188,7 +188,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var result = sut.Repeat(); service.Verify(s => s.StopSession(It.IsAny()), Times.Once); - service.Verify(s => s.StartSession(It.IsAny(), It.IsAny()), Times.Once); + service.Verify(s => s.StartSession(It.IsAny()), Times.Once); service.Verify(s => s.Disconnect(), Times.Never); Assert.AreEqual(OperationResult.Failed, result); @@ -320,7 +320,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations service.SetupGet(s => s.IsConnected).Returns(true); service.Setup(s => s.Connect(null, true)).Returns(true); service - .Setup(s => s.StartSession(It.IsAny(), It.IsAny())) + .Setup(s => s.StartSession(It.IsAny())) .Returns(new CommunicationResult(true)) .Callback(() => runtimeHost.Raise(h => h.ServiceSessionStarted += null)); diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/SessionActivationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/SessionActivationOperationTests.cs index 8453ebcb..495249d4 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/SessionActivationOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/SessionActivationOperationTests.cs @@ -19,9 +19,9 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations [TestClass] public class SessionActivationOperationTests { - private Mock currentSession; + private SessionConfiguration currentSession; private Mock logger; - private Mock nextSession; + private SessionConfiguration nextSession; private Settings nextSettings; private SessionContext sessionContext; @@ -30,15 +30,15 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations [TestInitialize] public void Initialize() { - currentSession = new Mock(); + currentSession = new SessionConfiguration(); logger = new Mock(); - nextSession = new Mock(); + nextSession = new SessionConfiguration(); nextSettings = new Settings(); sessionContext = new SessionContext(); - nextSession.SetupGet(s => s.Settings).Returns(nextSettings); - sessionContext.Current = currentSession.Object; - sessionContext.Next = nextSession.Object; + nextSession.Settings = nextSettings; + sessionContext.Current = currentSession; + sessionContext.Next = nextSession; sut = new SessionActivationOperation(logger.Object, sessionContext); } @@ -50,11 +50,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations var result = sut.Perform(); - currentSession.VerifyNoOtherCalls(); - nextSession.VerifyGet(s => s.Id); - Assert.AreEqual(OperationResult.Success, result); - Assert.AreSame(sessionContext.Current, nextSession.Object); + Assert.AreSame(sessionContext.Current, nextSession); Assert.IsNull(sessionContext.Next); } @@ -73,11 +70,8 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var result = sut.Repeat(); - currentSession.VerifyGet(s => s.Id); - nextSession.VerifyGet(s => s.Id); - Assert.AreEqual(OperationResult.Success, result); - Assert.AreSame(sessionContext.Current, nextSession.Object); + Assert.AreSame(sessionContext.Current, nextSession); Assert.IsNull(sessionContext.Next); } @@ -96,9 +90,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var result = sut.Revert(); - currentSession.VerifyNoOtherCalls(); - nextSession.VerifyNoOtherCalls(); - Assert.AreEqual(OperationResult.Success, result); } } diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/SessionInitializationOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/SessionInitializationOperationTests.cs index affd32e0..e74c469a 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/SessionInitializationOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/SessionInitializationOperationTests.cs @@ -23,7 +23,7 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations private Mock configuration; private Mock logger; private Mock runtimeHost; - private Mock session; + private SessionConfiguration session; private SessionContext sessionContext; private SessionInitializationOperation sut; @@ -35,12 +35,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations configuration = new Mock(); logger = new Mock(); runtimeHost = new Mock(); - session = new Mock(); + session = new SessionConfiguration(); sessionContext = new SessionContext(); - configuration.Setup(c => c.InitializeSessionConfiguration()).Returns(session.Object); - session.SetupGet(s => s.AppConfig).Returns(appConfig); - sessionContext.Next = session.Object; + configuration.Setup(c => c.InitializeSessionConfiguration()).Returns(session); + session.AppConfig = appConfig; + sessionContext.Next = session; sut = new SessionInitializationOperation(configuration.Object, logger.Object, runtimeHost.Object, sessionContext); } @@ -50,12 +50,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var token = Guid.NewGuid(); - session.SetupGet(s => s.StartupToken).Returns(token); + session.ClientAuthenticationToken = token; sut.Perform(); configuration.Verify(c => c.InitializeSessionConfiguration(), Times.Once); - runtimeHost.VerifySet(r => r.StartupToken = token, Times.Once); + runtimeHost.VerifySet(r => r.AuthenticationToken = token, Times.Once); } [TestMethod] @@ -63,12 +63,12 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations { var token = Guid.NewGuid(); - session.SetupGet(s => s.StartupToken).Returns(token); + session.ClientAuthenticationToken = token; sut.Repeat(); configuration.Verify(c => c.InitializeSessionConfiguration(), Times.Once); - runtimeHost.VerifySet(r => r.StartupToken = token, Times.Once); + runtimeHost.VerifySet(r => r.AuthenticationToken = token, Times.Once); } [TestMethod] diff --git a/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs b/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs index c78a5171..4cc4b73b 100644 --- a/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/RuntimeControllerTests.cs @@ -34,11 +34,11 @@ namespace SafeExamBrowser.Runtime.UnitTests private Mock bootstrapSequence; private Mock clientProcess; private Mock clientProxy; - private Mock currentSession; + private SessionConfiguration currentSession; private Settings currentSettings; private Mock logger; private Mock messageBox; - private Mock nextSession; + private SessionConfiguration nextSession; private Settings nextSettings; private Mock shutdown; private Mock text; @@ -56,11 +56,11 @@ namespace SafeExamBrowser.Runtime.UnitTests bootstrapSequence = new Mock(); clientProcess = new Mock(); clientProxy = new Mock(); - currentSession = new Mock(); + currentSession = new SessionConfiguration(); currentSettings = new Settings(); logger = new Mock(); messageBox = new Mock(); - nextSession = new Mock(); + nextSession = new SessionConfiguration(); nextSettings = new Settings(); runtimeHost = new Mock(); service = new Mock(); @@ -70,13 +70,13 @@ namespace SafeExamBrowser.Runtime.UnitTests text = new Mock(); uiFactory = new Mock(); - currentSession.SetupGet(s => s.Settings).Returns(currentSettings); - nextSession.SetupGet(s => s.Settings).Returns(nextSettings); + currentSession.Settings = currentSettings; + nextSession.Settings = nextSettings; sessionContext.ClientProcess = clientProcess.Object; sessionContext.ClientProxy = clientProxy.Object; - sessionContext.Current = currentSession.Object; - sessionContext.Next = nextSession.Object; + sessionContext.Current = currentSession; + sessionContext.Next = nextSession; uiFactory.Setup(u => u.CreateRuntimeWindow(It.IsAny())).Returns(new Mock().Object); uiFactory.Setup(u => u.CreateSplashScreen(It.IsAny())).Returns(new Mock().Object); @@ -135,9 +135,9 @@ namespace SafeExamBrowser.Runtime.UnitTests var nextSessionId = Guid.NewGuid(); var nextSettings = new Settings(); - nextSession.SetupGet(s => s.AppConfig).Returns(nextAppConfig); - nextSession.SetupGet(s => s.Id).Returns(nextSessionId); - nextSession.SetupGet(s => s.Settings).Returns(nextSettings); + nextSession.AppConfig = nextAppConfig; + nextSession.SessionId = nextSessionId; + nextSession.Settings = nextSettings; StartSession(); runtimeHost.Raise(r => r.ClientConfigurationNeeded += null, args); @@ -472,7 +472,7 @@ namespace SafeExamBrowser.Runtime.UnitTests var session = 0; bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => bootstrap = ++order); - sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => { session = ++order; sessionContext.Current = currentSession.Object; }); + sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => { session = ++order; sessionContext.Current = currentSession; }); sessionContext.Current = null; var success = sut.TryStart(); @@ -496,7 +496,7 @@ namespace SafeExamBrowser.Runtime.UnitTests var session = 0; bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Failed).Callback(() => bootstrap = ++order); - sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => { session = ++order; sessionContext.Current = currentSession.Object; }); + sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => { session = ++order; sessionContext.Current = currentSession; }); sessionContext.Current = null; var success = sut.TryStart(); @@ -516,7 +516,7 @@ namespace SafeExamBrowser.Runtime.UnitTests public void Startup_MustTerminateOnSessionStartFailure() { bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success); - sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Failed).Callback(() => sessionContext.Current = currentSession.Object); + sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Failed).Callback(() => sessionContext.Current = currentSession); sessionContext.Current = null; var success = sut.TryStart(); @@ -534,7 +534,7 @@ namespace SafeExamBrowser.Runtime.UnitTests public void Startup_MustNotTerminateOnSessionStartAbortion() { bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success); - sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Aborted).Callback(() => sessionContext.Current = currentSession.Object); + sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Aborted).Callback(() => sessionContext.Current = currentSession); sessionContext.Current = null; var success = sut.TryStart(); @@ -551,7 +551,7 @@ namespace SafeExamBrowser.Runtime.UnitTests private void StartSession() { bootstrapSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success); - sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => sessionContext.Current = currentSession.Object); + sessionSequence.Setup(b => b.TryPerform()).Returns(OperationResult.Success).Callback(() => sessionContext.Current = currentSession); sessionContext.Current = null; sut.TryStart(); diff --git a/SafeExamBrowser.Runtime/Communication/RuntimeHost.cs b/SafeExamBrowser.Runtime/Communication/RuntimeHost.cs index c115f70d..60c71a13 100644 --- a/SafeExamBrowser.Runtime/Communication/RuntimeHost.cs +++ b/SafeExamBrowser.Runtime/Communication/RuntimeHost.cs @@ -18,7 +18,7 @@ namespace SafeExamBrowser.Runtime.Communication internal class RuntimeHost : BaseHost, IRuntimeHost { public bool AllowConnection { get; set; } - public Guid StartupToken { private get; set; } + public Guid AuthenticationToken { private get; set; } public event CommunicationEventHandler ClientDisconnected; public event CommunicationEventHandler ClientReady; @@ -38,7 +38,7 @@ namespace SafeExamBrowser.Runtime.Communication protected override bool OnConnect(Guid? token = null) { - var authenticated = StartupToken == token; + var authenticated = AuthenticationToken == token; var accepted = AllowConnection && authenticated; if (accepted) diff --git a/SafeExamBrowser.Runtime/Operations/ClientOperation.cs b/SafeExamBrowser.Runtime/Operations/ClientOperation.cs index 8ee838f7..3159576d 100644 --- a/SafeExamBrowser.Runtime/Operations/ClientOperation.cs +++ b/SafeExamBrowser.Runtime/Operations/ClientOperation.cs @@ -95,11 +95,11 @@ namespace SafeExamBrowser.Runtime.Operations private bool TryStartClient() { - var clientExecutable = Context.Next.AppConfig.ClientExecutablePath; - var clientLogFile = $"{'"' + Context.Next.AppConfig.ClientLogFilePath + '"'}"; - var clientLogLevel = Context.Next.Settings.LogLevel.ToString(); + var authenticationToken = Context.Next.ClientAuthenticationToken.ToString("D"); + var executablePath = Context.Next.AppConfig.ClientExecutablePath; + var logFilePath = $"{'"' + Context.Next.AppConfig.ClientLogFilePath + '"'}"; + var logLevel = Context.Next.Settings.LogLevel.ToString(); var runtimeHostUri = Context.Next.AppConfig.RuntimeAddress; - var startupToken = Context.Next.StartupToken.ToString("D"); var uiMode = Context.Next.Settings.UserInterfaceMode.ToString(); var clientReady = false; @@ -112,7 +112,7 @@ namespace SafeExamBrowser.Runtime.Operations logger.Info("Starting new client process..."); runtimeHost.AllowConnection = true; runtimeHost.ClientReady += clientReadyEventHandler; - ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, clientLogLevel, runtimeHostUri, startupToken, uiMode); + ClientProcess = processFactory.StartNew(executablePath, logFilePath, logLevel, runtimeHostUri, authenticationToken, uiMode); ClientProcess.Terminated += clientTerminatedEventHandler; logger.Info("Waiting for client to complete initialization..."); @@ -147,7 +147,7 @@ namespace SafeExamBrowser.Runtime.Operations logger.Info("Client has been successfully started and initialized. Creating communication proxy for client host..."); ClientProxy = proxyFactory.CreateClientProxy(Context.Next.AppConfig.ClientAddress); - if (ClientProxy.Connect(Context.Next.StartupToken)) + if (ClientProxy.Connect(Context.Next.ClientAuthenticationToken)) { logger.Info("Connection with client has been established. Requesting authentication..."); diff --git a/SafeExamBrowser.Runtime/Operations/ServiceOperation.cs b/SafeExamBrowser.Runtime/Operations/ServiceOperation.cs index 80dcb5f8..f3874ff2 100644 --- a/SafeExamBrowser.Runtime/Operations/ServiceOperation.cs +++ b/SafeExamBrowser.Runtime/Operations/ServiceOperation.cs @@ -10,11 +10,14 @@ using System.Threading; using SafeExamBrowser.Contracts.Communication.Events; using SafeExamBrowser.Contracts.Communication.Hosts; using SafeExamBrowser.Contracts.Communication.Proxies; +using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Core.OperationModel.Events; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; +using SafeExamBrowser.Contracts.UserInterface.MessageBox; +using SafeExamBrowser.Runtime.Operations.Events; namespace SafeExamBrowser.Runtime.Operations { @@ -25,7 +28,7 @@ namespace SafeExamBrowser.Runtime.Operations private IServiceProxy service; private int timeout_ms; - public override event ActionRequiredEventHandler ActionRequired { add { } remove { } } + public override event ActionRequiredEventHandler ActionRequired; public override event StatusChangedEventHandler StatusChanged; public ServiceOperation( @@ -99,6 +102,7 @@ namespace SafeExamBrowser.Runtime.Operations private bool TryEstablishConnection() { var mandatory = Context.Next.Settings.ServicePolicy == ServicePolicy.Mandatory; + var warn = Context.Next.Settings.ServicePolicy == ServicePolicy.Warn; var connected = service.Connect(); var success = connected || !mandatory; @@ -106,10 +110,26 @@ namespace SafeExamBrowser.Runtime.Operations { service.Ignore = !connected; logger.Info($"The service is {(mandatory ? "mandatory" : "optional")} and {(connected ? "connected." : "not connected. All service-related operations will be ignored!")}"); + + if (!connected && warn) + { + ActionRequired?.Invoke(new MessageEventArgs + { + Icon = MessageBoxIcon.Warning, + Message = TextKey.MessageBox_ServiceUnavailableWarning, + Title = TextKey.MessageBox_ServiceUnavailableWarningTitle + }); + } } else { logger.Error("The service is mandatory but no connection could be established!"); + ActionRequired?.Invoke(new MessageEventArgs + { + Icon = MessageBoxIcon.Error, + Message = TextKey.MessageBox_ServiceUnavailableError, + Title = TextKey.MessageBox_ServiceUnavailableErrorTitle + }); } return success; @@ -151,6 +171,13 @@ namespace SafeExamBrowser.Runtime.Operations private bool TryStartSession() { + var configuration = new ServiceConfiguration + { + AppConfig = Context.Next.AppConfig, + AuthenticationToken = Context.Next.ServiceAuthenticationToken, + SessionId = Context.Next.SessionId, + Settings = Context.Next.Settings + }; var failure = false; var success = false; var serviceEvent = new AutoResetEvent(false); @@ -162,7 +189,7 @@ namespace SafeExamBrowser.Runtime.Operations logger.Info("Starting new service session..."); - var communication = service.StartSession(Context.Next.Id, Context.Next.Settings); + var communication = service.StartSession(configuration); if (communication.Success) { @@ -205,7 +232,7 @@ namespace SafeExamBrowser.Runtime.Operations logger.Info("Stopping current service session..."); - var communication = service.StopSession(Context.Current.Id); + var communication = service.StopSession(Context.Current.SessionId); if (communication.Success) { diff --git a/SafeExamBrowser.Runtime/Operations/SessionActivationOperation.cs b/SafeExamBrowser.Runtime/Operations/SessionActivationOperation.cs index 71548669..b4eece88 100644 --- a/SafeExamBrowser.Runtime/Operations/SessionActivationOperation.cs +++ b/SafeExamBrowser.Runtime/Operations/SessionActivationOperation.cs @@ -63,11 +63,11 @@ namespace SafeExamBrowser.Runtime.Operations if (isFirstSession) { - logger.Info($"Successfully activated first session '{Context.Next.Id}'."); + logger.Info($"Successfully activated first session '{Context.Next.SessionId}'."); } else { - logger.Info($"Successfully terminated old session '{Context.Current.Id}' and activated new session '{Context.Next.Id}'."); + logger.Info($"Successfully terminated old session '{Context.Current.SessionId}' and activated new session '{Context.Next.SessionId}'."); } Context.Current = Context.Next; diff --git a/SafeExamBrowser.Runtime/Operations/SessionInitializationOperation.cs b/SafeExamBrowser.Runtime/Operations/SessionInitializationOperation.cs index 5d42f0dc..790284ec 100644 --- a/SafeExamBrowser.Runtime/Operations/SessionInitializationOperation.cs +++ b/SafeExamBrowser.Runtime/Operations/SessionInitializationOperation.cs @@ -63,11 +63,11 @@ namespace SafeExamBrowser.Runtime.Operations StatusChanged?.Invoke(TextKey.OperationStatus_InitializeSession); Context.Next = configuration.InitializeSessionConfiguration(); - runtimeHost.StartupToken = Context.Next.StartupToken; + runtimeHost.AuthenticationToken = Context.Next.ClientAuthenticationToken; logger.Info($" -> Client-ID: {Context.Next.AppConfig.ClientId}"); logger.Info($" -> Runtime-ID: {Context.Next.AppConfig.RuntimeId}"); - logger.Info($" -> Session-ID: {Context.Next.Id}"); + logger.Info($" -> Session-ID: {Context.Next.SessionId}"); } private void FinalizeSessionConfiguration() diff --git a/SafeExamBrowser.Runtime/RuntimeController.cs b/SafeExamBrowser.Runtime/RuntimeController.cs index 1640f183..67908360 100644 --- a/SafeExamBrowser.Runtime/RuntimeController.cs +++ b/SafeExamBrowser.Runtime/RuntimeController.cs @@ -42,7 +42,7 @@ namespace SafeExamBrowser.Runtime private IText text; private IUserInterfaceFactory uiFactory; - private ISessionConfiguration Session + private SessionConfiguration Session { get { return sessionContext.Current; } } @@ -329,7 +329,7 @@ namespace SafeExamBrowser.Runtime args.ClientConfiguration = new ClientConfiguration { AppConfig = sessionContext.Next.AppConfig, - SessionId = sessionContext.Next.Id, + SessionId = sessionContext.Next.SessionId, Settings = sessionContext.Next.Settings }; } diff --git a/SafeExamBrowser.Runtime/SessionContext.cs b/SafeExamBrowser.Runtime/SessionContext.cs index 4efeeb89..8443ebc0 100644 --- a/SafeExamBrowser.Runtime/SessionContext.cs +++ b/SafeExamBrowser.Runtime/SessionContext.cs @@ -36,7 +36,7 @@ namespace SafeExamBrowser.Runtime /// /// The configuration of the currently active session. /// - internal ISessionConfiguration Current { get; set; } + internal SessionConfiguration Current { get; set; } /// /// The new desktop, if is currently active. @@ -46,7 +46,7 @@ namespace SafeExamBrowser.Runtime /// /// The configuration of the next session to be activated. /// - internal ISessionConfiguration Next { get; set; } + internal SessionConfiguration Next { get; set; } /// /// The original desktop, if is currently active. diff --git a/SafeExamBrowser.Service.UnitTests/ServiceControllerTests.cs b/SafeExamBrowser.Service.UnitTests/ServiceControllerTests.cs index f96e0ca4..2ea721ad 100644 --- a/SafeExamBrowser.Service.UnitTests/ServiceControllerTests.cs +++ b/SafeExamBrowser.Service.UnitTests/ServiceControllerTests.cs @@ -9,6 +9,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using SafeExamBrowser.Contracts.Communication.Hosts; +using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Core.OperationModel; namespace SafeExamBrowser.Service.UnitTests @@ -65,6 +66,7 @@ namespace SafeExamBrowser.Service.UnitTests bootstrapSequence.Setup(b => b.TryRevert()).Returns(OperationResult.Success).Callback(() => bootstrap = ++order); sessionSequence.Setup(b => b.TryRevert()).Returns(OperationResult.Success).Callback(() => session = ++order); + sessionContext.Current = new ServiceConfiguration(); sut.Terminate(); diff --git a/SafeExamBrowser.Service/ServiceController.cs b/SafeExamBrowser.Service/ServiceController.cs index 1bcd22a6..baac85f4 100644 --- a/SafeExamBrowser.Service/ServiceController.cs +++ b/SafeExamBrowser.Service/ServiceController.cs @@ -7,6 +7,7 @@ */ using SafeExamBrowser.Contracts.Communication.Hosts; +using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Service; @@ -19,7 +20,7 @@ namespace SafeExamBrowser.Service private IServiceHost serviceHost; private SessionContext sessionContext; - private object Session + private ServiceConfiguration Session { get { return sessionContext.Current; } } diff --git a/SafeExamBrowser.Service/SessionContext.cs b/SafeExamBrowser.Service/SessionContext.cs index 3600d69b..ef126012 100644 --- a/SafeExamBrowser.Service/SessionContext.cs +++ b/SafeExamBrowser.Service/SessionContext.cs @@ -6,6 +6,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using SafeExamBrowser.Contracts.Configuration; + namespace SafeExamBrowser.Service { /// @@ -16,11 +18,11 @@ namespace SafeExamBrowser.Service /// /// The configuration of the currently active session. /// - internal object Current { get; set; } + internal ServiceConfiguration Current { get; set; } /// /// The configuration of the next session to be activated. /// - internal object Next { get; set; } + internal ServiceConfiguration Next { get; set; } } }