SEBWIN-405: Implemented scaffolding for detection of session identifier.
This commit is contained in:
parent
bc06a0c985
commit
22f6e8b664
12 changed files with 145 additions and 7 deletions
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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.Browser.Contracts.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handler used to indicate that the browser has detected a session identifier of a LMS.
|
||||
/// </summary>
|
||||
public delegate void SessionIdentifierDetectedEventHandler(string identifier);
|
||||
}
|
|
@ -21,6 +21,11 @@ namespace SafeExamBrowser.Browser.Contracts
|
|||
/// </summary>
|
||||
event DownloadRequestedEventHandler ConfigurationDownloadRequested;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the browser application detects a session identifier of an LMS.
|
||||
/// </summary>
|
||||
event SessionIdentifierDetectedEventHandler SessionIdentifierDetected;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the browser application detects a request to terminate SEB.
|
||||
/// </summary>
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
<Compile Include="Events\DownloadEventArgs.cs" />
|
||||
<Compile Include="Events\DownloadFinishedCallback.cs" />
|
||||
<Compile Include="Events\DownloadRequestedEventHandler.cs" />
|
||||
<Compile Include="Events\SessionIdentifierDetectedEventHandler.cs" />
|
||||
<Compile Include="Events\TerminationRequestedEventHandler.cs" />
|
||||
<Compile Include="Filters\IRequestFilter.cs" />
|
||||
<Compile Include="Filters\IRule.cs" />
|
||||
|
|
|
@ -10,6 +10,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Timers;
|
||||
using CefSharp;
|
||||
using CefSharp.WinForms;
|
||||
using SafeExamBrowser.Applications.Contracts;
|
||||
|
@ -39,8 +40,10 @@ namespace SafeExamBrowser.Browser
|
|||
private IFileSystemDialog fileSystemDialog;
|
||||
private IMessageBox messageBox;
|
||||
private IModuleLogger logger;
|
||||
private List<string> sessionCookies;
|
||||
private BrowserSettings settings;
|
||||
private IText text;
|
||||
private Timer timer;
|
||||
private IUserInterfaceFactory uiFactory;
|
||||
|
||||
public bool AutoStart { get; private set; }
|
||||
|
@ -50,8 +53,9 @@ namespace SafeExamBrowser.Browser
|
|||
public string Tooltip { get; private set; }
|
||||
|
||||
public event DownloadRequestedEventHandler ConfigurationDownloadRequested;
|
||||
public event WindowsChangedEventHandler WindowsChanged;
|
||||
public event SessionIdentifierDetectedEventHandler SessionIdentifierDetected;
|
||||
public event TerminationRequestedEventHandler TerminationRequested;
|
||||
public event WindowsChangedEventHandler WindowsChanged;
|
||||
|
||||
public BrowserApplication(
|
||||
AppConfig appConfig,
|
||||
|
@ -67,8 +71,10 @@ namespace SafeExamBrowser.Browser
|
|||
this.instances = new List<BrowserApplicationInstance>();
|
||||
this.logger = logger;
|
||||
this.messageBox = messageBox;
|
||||
this.sessionCookies = new List<string>();
|
||||
this.settings = settings;
|
||||
this.text = text;
|
||||
this.timer = new Timer();
|
||||
this.uiFactory = uiFactory;
|
||||
}
|
||||
|
||||
|
@ -104,12 +110,15 @@ namespace SafeExamBrowser.Browser
|
|||
public void Start()
|
||||
{
|
||||
CreateNewInstance();
|
||||
StartMonitoringCookies();
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
logger.Info("Initiating termination...");
|
||||
|
||||
StopMonitoringCookies();
|
||||
|
||||
foreach (var instance in instances)
|
||||
{
|
||||
instance.Terminated -= Instance_Terminated;
|
||||
|
@ -294,6 +303,19 @@ namespace SafeExamBrowser.Browser
|
|||
return userAgent;
|
||||
}
|
||||
|
||||
private void StartMonitoringCookies()
|
||||
{
|
||||
timer.AutoReset = false;
|
||||
timer.Interval = 1000;
|
||||
timer.Elapsed += Timer_Elapsed;
|
||||
timer.Start();
|
||||
}
|
||||
|
||||
private void StopMonitoringCookies()
|
||||
{
|
||||
timer.Stop();
|
||||
}
|
||||
|
||||
private string ToScheme(ProxyProtocol protocol)
|
||||
{
|
||||
switch (protocol)
|
||||
|
@ -322,5 +344,35 @@ namespace SafeExamBrowser.Browser
|
|||
instances.Remove(instances.First(i => i.Id == id));
|
||||
WindowsChanged?.Invoke();
|
||||
}
|
||||
|
||||
private void Timer_Elapsed(object sender, ElapsedEventArgs args)
|
||||
{
|
||||
try
|
||||
{
|
||||
var manager = Cef.GetGlobalCookieManager();
|
||||
var task = manager.VisitAllCookiesAsync();
|
||||
var cookies = task.GetAwaiter().GetResult();
|
||||
var edxLogin = cookies.FirstOrDefault(c => c.Name == "edxloggedin");
|
||||
|
||||
// TODO: MoodleSession
|
||||
|
||||
if (edxLogin != default(Cookie))
|
||||
{
|
||||
var edxSession = cookies.FirstOrDefault(c => c.Domain == edxLogin.Domain && c.Name == "sessionid");
|
||||
|
||||
if (edxSession != default(Cookie) && !sessionCookies.Contains(edxSession.Domain))
|
||||
{
|
||||
sessionCookies.Add(edxSession.Domain);
|
||||
SessionIdentifierDetected?.Invoke(edxSession.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error("Failed to read cookies!", e);
|
||||
}
|
||||
|
||||
timer.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace SafeExamBrowser.Client
|
|||
internal IClientHost ClientHost { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The server proxy, if the current session mode is <see cref="SessionMode.Server"/>.
|
||||
/// The server proxy (if the current session mode is <see cref="SessionMode.Server"/>).
|
||||
/// </summary>
|
||||
internal IServerProxy Server { get; set; }
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using SafeExamBrowser.Applications.Contracts;
|
||||
using SafeExamBrowser.Browser.Contracts;
|
||||
using SafeExamBrowser.Browser.Contracts.Events;
|
||||
|
@ -183,6 +184,7 @@ namespace SafeExamBrowser.Client
|
|||
applicationMonitor.ExplorerStarted += ApplicationMonitor_ExplorerStarted;
|
||||
applicationMonitor.TerminationFailed += ApplicationMonitor_TerminationFailed;
|
||||
Browser.ConfigurationDownloadRequested += Browser_ConfigurationDownloadRequested;
|
||||
Browser.SessionIdentifierDetected += Browser_SessionIdentifierDetected;
|
||||
Browser.TerminationRequested += Browser_TerminationRequested;
|
||||
ClientHost.MessageBoxRequested += ClientHost_MessageBoxRequested;
|
||||
ClientHost.PasswordRequested += ClientHost_PasswordRequested;
|
||||
|
@ -218,6 +220,8 @@ namespace SafeExamBrowser.Client
|
|||
if (Browser != null)
|
||||
{
|
||||
Browser.ConfigurationDownloadRequested -= Browser_ConfigurationDownloadRequested;
|
||||
Browser.SessionIdentifierDetected -= Browser_SessionIdentifierDetected;
|
||||
Browser.TerminationRequested -= Browser_TerminationRequested;
|
||||
}
|
||||
|
||||
if (ClientHost != null)
|
||||
|
@ -341,6 +345,24 @@ namespace SafeExamBrowser.Client
|
|||
}
|
||||
}
|
||||
|
||||
private void Browser_SessionIdentifierDetected(string identifier)
|
||||
{
|
||||
if (Settings.SessionMode == SessionMode.Server)
|
||||
{
|
||||
var response = Server.SendSessionIdentifier(identifier);
|
||||
|
||||
while (!response.Success)
|
||||
{
|
||||
logger.Error($"Failed to communicate session identifier with server! {response.Message}");
|
||||
// TODO: Check that is running in separat thread (not UI thread!!) or use different mechanism to wait!
|
||||
Thread.Sleep(Settings.Server.RequestAttemptInterval);
|
||||
response = Server.SendSessionIdentifier(identifier);
|
||||
}
|
||||
|
||||
Server.StartConnectivity();
|
||||
}
|
||||
}
|
||||
|
||||
private void Browser_TerminationRequested()
|
||||
{
|
||||
logger.Info("Attempting to shutdown as requested by the browser...");
|
||||
|
|
|
@ -244,6 +244,8 @@ namespace SafeExamBrowser.Client
|
|||
var server = new ServerProxy(context.AppConfig, logger);
|
||||
var operation = new ServerOperation(actionCenter, context, logger, server, taskbar);
|
||||
|
||||
context.Server = server;
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,12 @@ namespace SafeExamBrowser.Client.Operations
|
|||
logger.Info("Initializing server...");
|
||||
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeServer);
|
||||
|
||||
server.Initialize(Context.AppConfig.ServerApi, Context.AppConfig.ServerConnectionToken, Context.AppConfig.ServerOauth2Token, Context.Settings.Server);
|
||||
server.Initialize(
|
||||
Context.AppConfig.ServerApi,
|
||||
Context.AppConfig.ServerConnectionToken,
|
||||
Context.AppConfig.ServerExamId,
|
||||
Context.AppConfig.ServerOauth2Token,
|
||||
Context.Settings.Server);
|
||||
|
||||
// TODO: Add action center and taskbar notifications
|
||||
}
|
||||
|
@ -66,6 +71,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
StatusChanged?.Invoke(TextKey.OperationStatus_FinalizeServer);
|
||||
|
||||
// TODO: Stop sending pings and logs (or in controller?)
|
||||
server.StopConnectivity();
|
||||
// TODO: Stop action center and taskbar notifications
|
||||
}
|
||||
|
||||
|
|
|
@ -161,6 +161,11 @@ namespace SafeExamBrowser.Configuration.Contracts
|
|||
/// </summary>
|
||||
public string ServerConnectionToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The identifier of the selected server exam.
|
||||
/// </summary>
|
||||
public string ServerExamId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The OAuth2 token for a server.
|
||||
/// </summary>
|
||||
|
|
|
@ -77,11 +77,18 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
|
||||
if (status == LoadStatus.Success)
|
||||
{
|
||||
var serverSettings = Context.Next.Settings.Server;
|
||||
|
||||
Context.Next.AppConfig.ServerApi = info.Api;
|
||||
Context.Next.AppConfig.ServerConnectionToken = info.ConnectionToken;
|
||||
Context.Next.AppConfig.ServerExamId = exam.Id;
|
||||
Context.Next.AppConfig.ServerOauth2Token = info.Oauth2Token;
|
||||
|
||||
Context.Next.Settings = settings;
|
||||
Context.Next.Settings.Browser.StartUrl = exam.Url;
|
||||
Context.Next.Settings.Server = serverSettings;
|
||||
Context.Next.Settings.SessionMode = SessionMode.Server;
|
||||
|
||||
result = OperationResult.Success;
|
||||
}
|
||||
else
|
||||
|
@ -105,6 +112,7 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
|
||||
if (fallback)
|
||||
{
|
||||
Context.Next.Settings.SessionMode = SessionMode.Normal;
|
||||
result = OperationResult.Success;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,11 +51,21 @@ namespace SafeExamBrowser.Server.Contracts
|
|||
/// <summary>
|
||||
/// Initializes the configuration and server settings to be used for communication.
|
||||
/// </summary>
|
||||
void Initialize(string api, string connectionToken, string oauth2Token, ServerSettings settings);
|
||||
void Initialize(string api, string connectionToken, string examId, string oauth2Token, ServerSettings settings);
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
ServerResponse SendSessionInfo(string sessionId);
|
||||
ServerResponse SendSessionIdentifier(string identifier);
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
void StartConnectivity();
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
void StopConnectivity();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace SafeExamBrowser.Server
|
|||
{
|
||||
private ApiVersion1 api;
|
||||
private string connectionToken;
|
||||
private string examId;
|
||||
private HttpClient httpClient;
|
||||
private readonly AppConfig appConfig;
|
||||
private ILogger logger;
|
||||
|
@ -173,20 +174,31 @@ namespace SafeExamBrowser.Server
|
|||
}
|
||||
}
|
||||
|
||||
public void Initialize(string api, string connectionToken, string oauth2Token, ServerSettings settings)
|
||||
public void Initialize(string api, string connectionToken, string examId, string oauth2Token, ServerSettings settings)
|
||||
{
|
||||
this.api = JsonConvert.DeserializeObject<ApiVersion1>(api);
|
||||
this.connectionToken = connectionToken;
|
||||
this.examId = examId;
|
||||
this.oauth2Token = oauth2Token;
|
||||
|
||||
Initialize(settings);
|
||||
}
|
||||
|
||||
public ServerResponse SendSessionInfo(string sessionId)
|
||||
public ServerResponse SendSessionIdentifier(string identifier)
|
||||
{
|
||||
return new ServerResponse(false, "TODO!");
|
||||
}
|
||||
|
||||
public void StartConnectivity()
|
||||
{
|
||||
// TODO: Start sending logs and pings
|
||||
}
|
||||
|
||||
public void StopConnectivity()
|
||||
{
|
||||
// TODO: Stop sending logs and pings
|
||||
}
|
||||
|
||||
private bool TryParseApi(HttpContent content)
|
||||
{
|
||||
var success = false;
|
||||
|
|
Loading…
Reference in a new issue