SEBWIN-405: Prepared infrastructure in client for server functionality.

This commit is contained in:
Damian Büchel 2020-07-28 19:56:25 +02:00
parent ef13cfe9c5
commit bc06a0c985
20 changed files with 216 additions and 30 deletions

View file

@ -12,6 +12,7 @@ using SafeExamBrowser.Applications.Contracts;
using SafeExamBrowser.Browser.Contracts;
using SafeExamBrowser.Communication.Contracts.Hosts;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Settings;
using SafeExamBrowser.UserInterface.Contracts.Shell;
@ -47,6 +48,11 @@ namespace SafeExamBrowser.Client
/// </summary>
internal IClientHost ClientHost { get; set; }
/// <summary>
/// The server proxy, if the current session mode is <see cref="SessionMode.Server"/>.
/// </summary>
internal IServerProxy Server { get; set; }
/// <summary>
/// The identifier of the current session.
/// </summary>

View file

@ -26,6 +26,7 @@ using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Monitoring.Contracts.Applications;
using SafeExamBrowser.Monitoring.Contracts.Display;
using SafeExamBrowser.Monitoring.Contracts.System;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Settings;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.FileSystemDialog;
@ -60,6 +61,7 @@ namespace SafeExamBrowser.Client
private IBrowserApplication Browser => context.Browser;
private IClientHost ClientHost => context.ClientHost;
private IServerProxy Server => context.Server;
private AppSettings Settings => context.Settings;
internal ClientController(
@ -196,6 +198,11 @@ namespace SafeExamBrowser.Client
{
activator.Activated += TerminationActivator_Activated;
}
if (Server != null)
{
// TODO
}
}
private void DeregisterEvents()
@ -222,6 +229,11 @@ namespace SafeExamBrowser.Client
ClientHost.Shutdown -= ClientHost_Shutdown;
}
if (Server != null)
{
// TODO
}
foreach (var activator in context.Activators.OfType<ITerminationActivator>())
{
activator.Activated -= TerminationActivator_Activated;

View file

@ -31,6 +31,7 @@ using SafeExamBrowser.Monitoring.Display;
using SafeExamBrowser.Monitoring.Keyboard;
using SafeExamBrowser.Monitoring.Mouse;
using SafeExamBrowser.Monitoring.System;
using SafeExamBrowser.Server;
using SafeExamBrowser.Settings.Logging;
using SafeExamBrowser.Settings.UserInterface;
using SafeExamBrowser.SystemComponents;
@ -118,6 +119,7 @@ namespace SafeExamBrowser.Client
operations.Enqueue(new SystemMonitorOperation(context, systemMonitor, logger));
operations.Enqueue(new LazyInitializationOperation(BuildShellOperation));
operations.Enqueue(new LazyInitializationOperation(BuildBrowserOperation));
operations.Enqueue(new LazyInitializationOperation(BuildServerOperation));
operations.Enqueue(new ClipboardOperation(context, logger, nativeMethods));
var sequence = new OperationSequence(logger, operations);
@ -237,6 +239,14 @@ namespace SafeExamBrowser.Client
return operation;
}
private IOperation BuildServerOperation()
{
var server = new ServerProxy(context.AppConfig, logger);
var operation = new ServerOperation(actionCenter, context, logger, server, taskbar);
return operation;
}
private IOperation BuildShellOperation()
{
var aboutInfo = new AboutNotificationInfo(text);

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2020 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 SafeExamBrowser.Core.Contracts.OperationModel;
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Settings;
using SafeExamBrowser.UserInterface.Contracts.Shell;
namespace SafeExamBrowser.Client.Operations
{
internal class ServerOperation : ClientOperation
{
private readonly IActionCenter actionCenter;
private readonly ILogger logger;
private readonly IServerProxy server;
private readonly ITaskbar taskbar;
public override event ActionRequiredEventHandler ActionRequired { add { } remove { } }
public override event StatusChangedEventHandler StatusChanged;
public ServerOperation(
IActionCenter actionCenter,
ClientContext context,
ILogger logger,
IServerProxy server,
ITaskbar taskbar) : base(context)
{
this.actionCenter = actionCenter;
this.logger = logger;
this.server = server;
this.taskbar = taskbar;
}
public override OperationResult Perform()
{
var result = OperationResult.Success;
if (Context.Settings.SessionMode == SessionMode.Server)
{
logger.Info("Initializing server...");
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeServer);
server.Initialize(Context.AppConfig.ServerApi, Context.AppConfig.ServerConnectionToken, Context.AppConfig.ServerOauth2Token, Context.Settings.Server);
// TODO: Add action center and taskbar notifications
}
return result;
}
public override OperationResult Revert()
{
var result = OperationResult.Success;
if (Context.Settings?.SessionMode == SessionMode.Server)
{
logger.Info("Finalizing server...");
StatusChanged?.Invoke(TextKey.OperationStatus_FinalizeServer);
// TODO: Stop sending pings and logs (or in controller?)
// TODO: Stop action center and taskbar notifications
}
return result;
}
}
}

View file

@ -94,6 +94,7 @@
<Compile Include="Operations\KeyboardInterceptorOperation.cs" />
<Compile Include="Operations\MouseInterceptorOperation.cs" />
<Compile Include="Operations\ApplicationOperation.cs" />
<Compile Include="Operations\ServerOperation.cs" />
<Compile Include="Operations\ShellOperation.cs" />
<Compile Include="Operations\SystemMonitorOperation.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
@ -193,6 +194,14 @@
<Project>{EF563531-4EB5-44B9-A5EC-D6D6F204469B}</Project>
<Name>SafeExamBrowser.Monitoring</Name>
</ProjectReference>
<ProjectReference Include="..\SafeExamBrowser.Server.Contracts\SafeExamBrowser.Server.Contracts.csproj">
<Project>{db701e6f-bddc-4cec-b662-335a9dc11809}</Project>
<Name>SafeExamBrowser.Server.Contracts</Name>
</ProjectReference>
<ProjectReference Include="..\SafeExamBrowser.Server\SafeExamBrowser.Server.csproj">
<Project>{46edbde0-58b4-4725-9783-0c55c3d49c0c}</Project>
<Name>SafeExamBrowser.Server</Name>
</ProjectReference>
<ProjectReference Include="..\SafeExamBrowser.Settings\SafeExamBrowser.Settings.csproj">
<Project>{30b2d907-5861-4f39-abad-c4abf1b3470e}</Project>
<Name>SafeExamBrowser.Settings</Name>

View file

@ -151,6 +151,21 @@ namespace SafeExamBrowser.Configuration.Contracts
/// </summary>
public string SebUriSchemeSecure { get; set; }
/// <summary>
/// The server API as JSON string.
/// </summary>
public string ServerApi { get; set; }
/// <summary>
/// The connection token for a server.
/// </summary>
public string ServerConnectionToken { get; set; }
/// <summary>
/// The OAuth2 token for a server.
/// </summary>
public string ServerOauth2Token { get; set; }
/// <summary>
/// The communication address of the service component.
/// </summary>

View file

@ -8,7 +8,7 @@
using System.Collections.Generic;
using SafeExamBrowser.Core.Contracts.OperationModel.Events;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Contracts.Data;
namespace SafeExamBrowser.Runtime.Operations.Events
{

View file

@ -15,6 +15,7 @@ using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Runtime.Operations.Events;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.Settings;
using SafeExamBrowser.SystemComponents.Contracts;
@ -53,7 +54,7 @@ namespace SafeExamBrowser.Runtime.Operations
server.Initialize(Context.Next.Settings.Server);
var (abort, fallback, success) = TryPerformWithFallback(() => server.Connect(), out var token);
var (abort, fallback, success) = TryPerformWithFallback(() => server.Connect());
if (success)
{
@ -69,12 +70,16 @@ namespace SafeExamBrowser.Runtime.Operations
if (success)
{
var info = server.GetConnectionInfo();
var status = TryLoadSettings(uri, UriSource.Server, out _, out var settings);
fileSystem.Delete(uri.LocalPath);
if (status == LoadStatus.Success)
{
Context.Next.AppConfig.ServerApi = info.Api;
Context.Next.AppConfig.ServerConnectionToken = info.ConnectionToken;
Context.Next.AppConfig.ServerOauth2Token = info.Oauth2Token;
Context.Next.Settings = settings;
Context.Next.Settings.Browser.StartUrl = exam.Url;
result = OperationResult.Success;
@ -121,7 +126,7 @@ namespace SafeExamBrowser.Runtime.Operations
public override OperationResult Revert()
{
var result = OperationResult.Failed;
var result = OperationResult.Success;
if (Context.Current?.Settings.SessionMode == SessionMode.Server)
{
@ -139,10 +144,6 @@ namespace SafeExamBrowser.Runtime.Operations
result = OperationResult.Failed;
}
}
else
{
result = OperationResult.Success;
}
return result;
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2020 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/.
*/
namespace SafeExamBrowser.Server.Contracts.Data
{
/// <summary>
/// Contains all information required to establish a connection with a server.
/// </summary>
public class ConnectionInfo
{
/// <summary>
/// The API of the server as JSON string.
/// </summary>
public string Api { get; set; }
/// <summary>
/// The connection token for authentication with the server.
/// </summary>
public string ConnectionToken { get; set; }
/// <summary>
/// The OAuth2 token for authentication with the server.
/// </summary>
public string Oauth2Token { get; set; }
}
}

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
namespace SafeExamBrowser.Server.Contracts
namespace SafeExamBrowser.Server.Contracts.Data
{
/// <summary>
/// Defines a server exam.

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
namespace SafeExamBrowser.Server.Contracts
namespace SafeExamBrowser.Server.Contracts.Data
{
/// <summary>
/// Defines the result of a communication with a SEB server.

View file

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.Settings.Server;
namespace SafeExamBrowser.Server.Contracts
@ -18,33 +19,42 @@ namespace SafeExamBrowser.Server.Contracts
public interface IServerProxy
{
/// <summary>
/// TODO: Return API as well or re-load in proxy instance of client?
/// Attempts to initialize a connection to the server. If successful, returns a OAuth2 token as response value.
/// Attempts to initialize a connection to the server.
/// </summary>
ServerResponse<string> Connect();
ServerResponse Connect();
/// <summary>
///
/// TODO
/// </summary>
ServerResponse Disconnect();
/// <summary>
///
/// Retrieves a list of all currently available exams.
/// </summary>
ServerResponse<IEnumerable<Exam>> GetAvailableExams();
/// <summary>
///
/// Retrieves the URI of the configuration file for the given exam.
/// </summary>
ServerResponse<Uri> GetConfigurationFor(Exam exam);
/// <summary>
/// Retrieves the information required to establish a connection with this server.
/// </summary>
ConnectionInfo GetConnectionInfo();
/// <summary>
/// Initializes the server settings to be used for communication.
/// </summary>
void Initialize(ServerSettings settings);
/// <summary>
///
/// Initializes the configuration and server settings to be used for communication.
/// </summary>
void Initialize(string api, string connectionToken, string oauth2Token, ServerSettings settings);
/// <summary>
/// TODO
/// </summary>
ServerResponse SendSessionInfo(string sessionId);
}

View file

@ -54,10 +54,11 @@
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<Compile Include="Exam.cs" />
<Compile Include="Data\ConnectionInfo.cs" />
<Compile Include="Data\Exam.cs" />
<Compile Include="IServerProxy.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServerResponse.cs" />
<Compile Include="Data\ServerResponse.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SafeExamBrowser.Settings\SafeExamBrowser.Settings.csproj">

View file

@ -11,13 +11,9 @@ namespace SafeExamBrowser.Server.Data
internal class ApiVersion1
{
public string AccessTokenEndpoint { get; set; }
public string HandshakeEndpoint { get; set; }
public string ConfigurationEndpoint { get; set; }
public string PingEndpoint { get; set; }
public string LogEndpoint { get; set; }
}
}

View file

@ -19,6 +19,7 @@ using Newtonsoft.Json.Linq;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.Server.Data;
using SafeExamBrowser.Settings.Server;
@ -42,7 +43,7 @@ namespace SafeExamBrowser.Server
this.logger = logger;
}
public ServerResponse<string> Connect()
public ServerResponse Connect()
{
var success = TryExecute(HttpMethod.Get, settings.ApiUrl, out var response);
var message = ToString(response);
@ -73,7 +74,7 @@ namespace SafeExamBrowser.Server
logger.Error("Failed to load server API!");
}
return new ServerResponse<string>(success, oauth2Token, message);
return new ServerResponse(success, message);
}
public ServerResponse Disconnect()
@ -151,6 +152,16 @@ namespace SafeExamBrowser.Server
return new ServerResponse<Uri>(success, uri, message);
}
public ConnectionInfo GetConnectionInfo()
{
return new ConnectionInfo
{
Api = JsonConvert.SerializeObject(api),
ConnectionToken = connectionToken,
Oauth2Token = oauth2Token
};
}
public void Initialize(ServerSettings settings)
{
this.settings = settings;
@ -162,6 +173,15 @@ namespace SafeExamBrowser.Server
}
}
public void Initialize(string api, string connectionToken, string oauth2Token, ServerSettings settings)
{
this.api = JsonConvert.DeserializeObject<ApiVersion1>(api);
this.connectionToken = connectionToken;
this.oauth2Token = oauth2Token;
Initialize(settings);
}
public ServerResponse SendSessionInfo(string sessionId)
{
return new ServerResponse(false, "TODO!");
@ -324,7 +344,7 @@ namespace SafeExamBrowser.Server
}
catch (TaskCanceledException)
{
logger.Error($"Request {request.Method} '{request.RequestUri}' did not complete within {settings.RequestTimeout}ms!");
logger.Debug($"Request {request.Method} '{request.RequestUri}' did not complete within {settings.RequestTimeout}ms!");
break;
}
catch (Exception e)

View file

@ -12,7 +12,7 @@ using SafeExamBrowser.Client.Contracts;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.Settings.Browser;
using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard;

View file

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Contracts.Data;
namespace SafeExamBrowser.UserInterface.Contracts.Windows.Data
{

View file

@ -16,7 +16,7 @@ using SafeExamBrowser.Client.Contracts;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.Settings.Browser;
using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard;

View file

@ -10,7 +10,7 @@ using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.UserInterface.Contracts.Windows;
using SafeExamBrowser.UserInterface.Contracts.Windows.Data;

View file

@ -16,7 +16,7 @@ using SafeExamBrowser.Client.Contracts;
using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Contracts.Data;
using SafeExamBrowser.Settings.Browser;
using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard;