SEBWIN-405: Implemented loading of server exam configuration.

This commit is contained in:
Damian Büchel 2020-07-27 15:58:30 +02:00
parent 7915d4dff9
commit ef13cfe9c5
4 changed files with 96 additions and 20 deletions

View file

@ -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));

View file

@ -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;

View file

@ -63,6 +63,10 @@
<Compile Include="ServerProxy.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SafeExamBrowser.Configuration.Contracts\SafeExamBrowser.Configuration.Contracts.csproj">
<Project>{7d74555e-63e1-4c46-bd0a-8580552368c8}</Project>
<Name>SafeExamBrowser.Configuration.Contracts</Name>
</ProjectReference>
<ProjectReference Include="..\SafeExamBrowser.Logging.Contracts\SafeExamBrowser.Logging.Contracts.csproj">
<Project>{64ea30fb-11d4-436a-9c2b-88566285363e}</Project>
<Name>SafeExamBrowser.Logging.Contracts</Name>

View file

@ -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<IEnumerable<Exam>> 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<Exam>);
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<IEnumerable<Exam>>(hasExams && hasToken, exams, message);
return new ServerResponse<IEnumerable<Exam>>(success, exams, message);
}
public ServerResponse<Uri> GetConfigurationFor(Exam exam)
{
// 4. Send exam ID
var authorization = ("Authorization", $"Bearer {oauth2Token}");
var token = ("SEBConnectionToken", connectionToken);
var uri = default(Uri);
return new ServerResponse<Uri>(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<Uri>(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 () =>