diff --git a/SafeExamBrowser.Runtime/CompositionRoot.cs b/SafeExamBrowser.Runtime/CompositionRoot.cs
index 4ed0bade..6ca5f035 100644
--- a/SafeExamBrowser.Runtime/CompositionRoot.cs
+++ b/SafeExamBrowser.Runtime/CompositionRoot.cs
@@ -63,11 +63,12 @@ namespace SafeExamBrowser.Runtime
var uiFactory = new UserInterfaceFactory(text);
var desktopFactory = new DesktopFactory(ModuleLogger(nameof(DesktopFactory)));
var explorerShell = new ExplorerShell(ModuleLogger(nameof(ExplorerShell)), nativeMethods);
+ var fileSystem = new FileSystem();
var processFactory = new ProcessFactory(ModuleLogger(nameof(ProcessFactory)));
var proxyFactory = new ProxyFactory(new ProxyObjectFactory(), ModuleLogger(nameof(ProxyFactory)));
var runtimeHost = new RuntimeHost(appConfig.RuntimeAddress, new HostObjectFactory(), ModuleLogger(nameof(RuntimeHost)), FIVE_SECONDS);
var runtimeWindow = uiFactory.CreateRuntimeWindow(appConfig);
- var server = new ServerProxy(ModuleLogger(nameof(ServerProxy)));
+ var server = new ServerProxy(appConfig, ModuleLogger(nameof(ServerProxy)));
var serviceProxy = new ServiceProxy(appConfig.ServiceAddress, new ProxyObjectFactory(), ModuleLogger(nameof(ServiceProxy)), Interlocutor.Runtime);
var sessionContext = new SessionContext();
var splashScreen = uiFactory.CreateSplashScreen(appConfig);
@@ -82,7 +83,7 @@ namespace SafeExamBrowser.Runtime
sessionOperations.Enqueue(new SessionInitializationOperation(configuration, logger, runtimeHost, sessionContext));
sessionOperations.Enqueue(new ConfigurationOperation(args, configuration, new FileSystem(), new HashAlgorithm(), logger, sessionContext));
- sessionOperations.Enqueue(new ServerOperation(args, configuration, logger, sessionContext, server));
+ sessionOperations.Enqueue(new ServerOperation(args, configuration, fileSystem, logger, sessionContext, server));
sessionOperations.Enqueue(new VirtualMachineOperation(vmDetector, logger, sessionContext));
sessionOperations.Enqueue(new ServiceOperation(logger, runtimeHost, serviceProxy, sessionContext, THIRTY_SECONDS, userInfo));
sessionOperations.Enqueue(new ClientTerminationOperation(logger, processFactory, proxyFactory, runtimeHost, sessionContext, THIRTY_SECONDS));
diff --git a/SafeExamBrowser.Runtime/Operations/ServerOperation.cs b/SafeExamBrowser.Runtime/Operations/ServerOperation.cs
index 4e3de3cd..68eb0aed 100644
--- a/SafeExamBrowser.Runtime/Operations/ServerOperation.cs
+++ b/SafeExamBrowser.Runtime/Operations/ServerOperation.cs
@@ -16,11 +16,13 @@ using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Runtime.Operations.Events;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Settings;
+using SafeExamBrowser.SystemComponents.Contracts;
namespace SafeExamBrowser.Runtime.Operations
{
internal class ServerOperation : ConfigurationBaseOperation
{
+ private readonly IFileSystem fileSystem;
private readonly ILogger logger;
private readonly IServerProxy server;
@@ -30,10 +32,12 @@ namespace SafeExamBrowser.Runtime.Operations
public ServerOperation(
string[] commandLineArgs,
IConfigurationRepository configuration,
+ IFileSystem fileSystem,
ILogger logger,
SessionContext context,
IServerProxy server) : base(commandLineArgs, configuration, context)
{
+ this.fileSystem = fileSystem;
this.logger = logger;
this.server = server;
}
@@ -67,6 +71,8 @@ namespace SafeExamBrowser.Runtime.Operations
{
var status = TryLoadSettings(uri, UriSource.Server, out _, out var settings);
+ fileSystem.Delete(uri.LocalPath);
+
if (status == LoadStatus.Success)
{
Context.Next.Settings = settings;
diff --git a/SafeExamBrowser.Server/SafeExamBrowser.Server.csproj b/SafeExamBrowser.Server/SafeExamBrowser.Server.csproj
index 16f24cf8..22fc33de 100644
--- a/SafeExamBrowser.Server/SafeExamBrowser.Server.csproj
+++ b/SafeExamBrowser.Server/SafeExamBrowser.Server.csproj
@@ -63,6 +63,10 @@
+
+ {7d74555e-63e1-4c46-bd0a-8580552368c8}
+ SafeExamBrowser.Configuration.Contracts
+
{64ea30fb-11d4-436a-9c2b-88566285363e}
SafeExamBrowser.Logging.Contracts
diff --git a/SafeExamBrowser.Server/ServerProxy.cs b/SafeExamBrowser.Server/ServerProxy.cs
index e5909291..0bf55d62 100644
--- a/SafeExamBrowser.Server/ServerProxy.cs
+++ b/SafeExamBrowser.Server/ServerProxy.cs
@@ -16,6 +16,7 @@ using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using SafeExamBrowser.Configuration.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.Server.Contracts;
using SafeExamBrowser.Server.Data;
@@ -28,13 +29,15 @@ namespace SafeExamBrowser.Server
private ApiVersion1 api;
private string connectionToken;
private HttpClient httpClient;
+ private readonly AppConfig appConfig;
private ILogger logger;
private string oauth2Token;
private ServerSettings settings;
- public ServerProxy(ILogger logger)
+ public ServerProxy(AppConfig appConfig, ILogger logger)
{
this.api = new ApiVersion1();
+ this.appConfig = appConfig;
this.httpClient = new HttpClient();
this.logger = logger;
}
@@ -75,7 +78,7 @@ namespace SafeExamBrowser.Server
public ServerResponse Disconnect()
{
- return new ServerResponse(false, "Some error message here");
+ return new ServerResponse(false, "TODO!");
}
public ServerResponse> GetAvailableExams()
@@ -83,37 +86,69 @@ namespace SafeExamBrowser.Server
var authorization = ("Authorization", $"Bearer {oauth2Token}");
var content = $"institutionId={settings.Institution}";
var contentType = "application/x-www-form-urlencoded";
+ var exams = default(IList);
var success = TryExecute(HttpMethod.Post, api.HandshakeEndpoint, out var response, content, contentType, authorization);
var message = ToString(response);
- var hasToken = TryParseConnectionToken(response);
- var hasExams = TryParseExams(response.Content, out var exams);
- if (success && hasExams && hasToken)
+ if (success)
{
- logger.Info("Successfully retrieved connection token and available exams.");
- }
- else if (!hasExams)
- {
- logger.Error("Failed to retrieve available exams!");
- }
- else if (!hasToken)
- {
- logger.Error("Failed to retrieve connection token!");
+ var hasExams = TryParseExams(response.Content, out exams);
+ var hasToken = TryParseConnectionToken(response);
+
+ success = hasExams && hasToken;
+
+ if (success)
+ {
+ logger.Info("Successfully retrieved connection token and available exams.");
+ }
+ else if (!hasExams)
+ {
+ logger.Error("Failed to retrieve available exams!");
+ }
+ else if (!hasToken)
+ {
+ logger.Error("Failed to retrieve connection token!");
+ }
}
else
{
logger.Error("Failed to load connection token and available exams!");
}
- return new ServerResponse>(hasExams && hasToken, exams, message);
+ return new ServerResponse>(success, exams, message);
}
public ServerResponse GetConfigurationFor(Exam exam)
{
- // 4. Send exam ID
+ var authorization = ("Authorization", $"Bearer {oauth2Token}");
+ var token = ("SEBConnectionToken", connectionToken);
+ var uri = default(Uri);
- return new ServerResponse(false, default(Uri), "Some error message here");
+ var success = TryExecute(HttpMethod.Get, $"{api.ConfigurationEndpoint}?examId={exam.Id}", out var response, default(string), default(string), authorization, token);
+ var message = ToString(response);
+
+ if (success)
+ {
+ logger.Info("Successfully retrieved exam configuration.");
+
+ success = TrySaveFile(response.Content, out uri);
+
+ if (success)
+ {
+ logger.Info($"Successfully saved exam configuration as '{uri}'.");
+ }
+ else
+ {
+ logger.Error("Failed to save exam configuration!");
+ }
+ }
+ else
+ {
+ logger.Error("Failed to retrieve exam configuration!");
+ }
+
+ return new ServerResponse(success, uri, message);
}
public void Initialize(ServerSettings settings)
@@ -129,7 +164,7 @@ namespace SafeExamBrowser.Server
public ServerResponse SendSessionInfo(string sessionId)
{
- return new ServerResponse(false, "Some error message here");
+ return new ServerResponse(false, "TODO!");
}
private bool TryParseApi(HttpContent content)
@@ -301,6 +336,36 @@ namespace SafeExamBrowser.Server
return response != default(HttpResponseMessage) && response.IsSuccessStatusCode;
}
+ private bool TrySaveFile(HttpContent content, out Uri uri)
+ {
+ uri = new Uri(Path.Combine(appConfig.TemporaryDirectory, $"ServerExam{appConfig.ConfigurationFileExtension}"));
+
+ try
+ {
+ var task = Task.Run(async () =>
+ {
+ return await content.ReadAsStreamAsync();
+ });
+
+ using (var data = task.GetAwaiter().GetResult())
+ using (var file = new FileStream(uri.LocalPath, FileMode.Create))
+ {
+ data.Seek(0, SeekOrigin.Begin);
+ data.CopyTo(file);
+ data.Flush();
+ file.Flush();
+ }
+
+ return true;
+ }
+ catch (Exception e)
+ {
+ logger.Error($"Failed to save file '{uri.LocalPath}'!", e);
+ }
+
+ return false;
+ }
+
private string Extract(HttpContent content)
{
var task = Task.Run(async () =>