Unattended remote control session invitees require an authorized account with access to the device. Refactored remote control session info organization.

This commit is contained in:
Jared Goodwin 2019-07-05 22:10:09 -07:00
parent 04f7de98ac
commit a694765e9c
11 changed files with 104 additions and 96 deletions

View File

@ -83,22 +83,26 @@ namespace Remotely.Server.API
{
return BadRequest("There are already the maximum amount of active remote control sessions for your organization.");
}
var existingSessions = RCDeviceSocketHub.SessionInfoList.Where(x => x.Value.MachineName == targetDevice.Value.DeviceName);
await DeviceHub.Clients.Client(targetDevice.Key).SendAsync("RemoteControl", Request.HttpContext.Connection.Id, targetDevice.Key);
var stopWatch = Stopwatch.StartNew();
while (!RCDeviceSocketHub.MachineNameToSessionIDLookup.ContainsKey(targetDevice.Value.DeviceName) && stopWatch.Elapsed.TotalSeconds < 5)
while (!RCDeviceSocketHub.SessionInfoList.Values.Any(x=>x.MachineName == targetDevice.Value.DeviceName && !existingSessions.Any(y=>y.Key != x.RCSocketID)) && stopWatch.Elapsed.TotalSeconds < 5)
{
await Task.Delay(10);
}
if (!RCDeviceSocketHub.MachineNameToSessionIDLookup.ContainsKey(targetDevice.Value.DeviceName))
if (!RCDeviceSocketHub.SessionInfoList.Values.Any(x => x.MachineName == targetDevice.Value.DeviceName && !existingSessions.Any(y => y.Key != x.RCSocketID)))
{
return StatusCode(500, "The remote control process failed to start in time on the remote device.");
}
else
{
var rcSessionID = RCDeviceSocketHub.MachineNameToSessionIDLookup[targetDevice.Value.DeviceName];
return Ok($"{HttpContext.Request.Scheme}://{Request.Host}/RemoteControl?clientID={rcSessionID}&serviceID={targetDevice.Key}");
var rcSession = RCDeviceSocketHub.SessionInfoList.Values.FirstOrDefault(x=>x.MachineName == targetDevice.Value.DeviceName && !existingSessions.Any(y=>y.Key != x.RCSocketID));
return Ok($"{HttpContext.Request.Scheme}://{Request.Host}/RemoteControl?clientID={rcSession.RCSocketID}&serviceID={targetDevice.Key}");
}
}
else

View File

@ -109,6 +109,19 @@ namespace Remotely.Server.Data
targetDevice.DevicePermissionLinks.Any(x => x.PermissionGroup.UserPermissionLinks.Any(y => y.RemotelyUserID == remotelyUser.Id));
}
public bool DoesUserHaveAccessToDevice(string deviceID, string remotelyUserID)
{
var remotelyUser = RemotelyContext.Users.Find(remotelyUserID);
var targetDevice = RemotelyContext.Devices
.Include(x => x.DevicePermissionLinks)
.FirstOrDefault(x => x.ID == deviceID && x.OrganizationID == remotelyUser.OrganizationID);
return remotelyUser.IsAdministrator ||
targetDevice.DevicePermissionLinks.Count == 0 ||
targetDevice.DevicePermissionLinks.Any(x => x.PermissionGroup.UserPermissionLinks.Any(y => y.RemotelyUserID == remotelyUser.Id));
}
public string[] FilterDeviceIDsByUserPermission(string[] deviceIDs, RemotelyUser remotelyUser)
{
return RemotelyContext.Devices.Where(x =>

View File

@ -0,0 +1,19 @@
using Remotely.Shared.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Remotely.Server.Models
{
public class RCSessionInfo
{
public string AttendedSessionID { get; set; }
public string MachineName { get; set; }
public RemoteControlMode Mode { get; set; }
public string RCSocketID { get; set; }
public string RequesterName { get; set; }
public string ServiceID { get; set; }
public DateTime StartTime { get; set; }
}
}

View File

@ -21,7 +21,7 @@ namespace Remotely.Server.Services
RCBrowserHub = rcBrowserHub;
}
public static ConcurrentDictionary<string, Device> ServiceConnections { get; set; } = new ConcurrentDictionary<string, Device>();
public static ConcurrentDictionary<string, Device> ServiceConnections { get; } = new ConcurrentDictionary<string, Device>();
public IHubContext<RCBrowserSocketHub> RCBrowserHub { get; }
private IHubContext<BrowserSocketHub> BrowserHub { get; }
private DataService DataService { get; }

View File

@ -167,13 +167,13 @@ namespace Remotely.Server.Services
{
if ((RemoteControlMode)remoteControlMode == RemoteControlMode.Normal)
{
if (!RCDeviceSocketHub.AttendedSessionList.ContainsKey(screenCasterID))
if (!RCDeviceSocketHub.SessionInfoList.Any(x => x.Value.AttendedSessionID == screenCasterID))
{
await Clients.Caller.SendAsync("SessionIDNotFound");
return;
}
screenCasterID = RCDeviceSocketHub.AttendedSessionList[screenCasterID];
screenCasterID = RCDeviceSocketHub.SessionInfoList.First(x => x.Value.AttendedSessionID == screenCasterID).Value.RCSocketID;
}
DataService.WriteEvent(new EventLog()
@ -194,7 +194,12 @@ namespace Remotely.Server.Services
RequesterName = requesterName;
if (Mode == RemoteControlMode.Unattended)
{
await RCDeviceHub.Clients.Client(screenCasterID).SendAsync("GetScreenCast", Context.ConnectionId, requesterName);
var serviceID = RCDeviceSocketHub.SessionInfoList.FirstOrDefault(x => x.Value.RCSocketID == screenCasterID).Value?.ServiceID;
var deviceID = DeviceSocketHub.ServiceConnections[serviceID].ID;
if (Context.User.Identity.IsAuthenticated && DataService.DoesUserHaveAccessToDevice(deviceID, Context.UserIdentifier))
{
await RCDeviceHub.Clients.Client(screenCasterID).SendAsync("GetScreenCast", Context.ConnectionId, requesterName);
}
}
else
{

View File

@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Hosting;
using System.IO;
using System.Drawing;
using Remotely.Shared.Models;
using Remotely.Server.Models;
namespace Remotely.Server.Services
{
@ -29,9 +30,7 @@ namespace Remotely.Server.Services
AppConfig = appConfig;
}
public static ConcurrentDictionary<string, string> AttendedSessionList { get; set; } = new ConcurrentDictionary<string, string>();
public static ConcurrentDictionary<string, string> MachineNameToSessionIDLookup { get; set; } = new ConcurrentDictionary<string, string>();
public static ConcurrentDictionary<string, RCSessionInfo> SessionInfoList { get; } = new ConcurrentDictionary<string, RCSessionInfo>();
public ApplicationConfig AppConfig { get; }
public RemoteControlSessionRecorder RCSessionRecorder { get; }
private IHubContext<BrowserSocketHub> BrowserHub { get; }
@ -53,65 +52,30 @@ namespace Remotely.Server.Services
Context.Items["CurrentScreenSize"] = value;
}
}
private RCSessionInfo SessionInfo
{
get
{
if (Context.Items.ContainsKey("SessionInfo"))
{
return (RCSessionInfo)Context.Items["SessionInfo"];
}
else
{
return null;
}
}
set
{
Context.Items["SessionInfo"] = value;
}
}
private DataService DataService { get; }
private IHubContext<DeviceSocketHub> DeviceHub { get; }
private string MachineName
{
get
{
if (Context.Items.ContainsKey("MachineName"))
{
return Context.Items["MachineName"] as string;
}
else
{
return null;
}
}
set
{
Context.Items["MachineName"] = value;
}
}
private IHubContext<RCBrowserSocketHub> RCBrowserHub { get; }
private string ServiceID
{
get
{
if (Context.Items.ContainsKey("ServiceID"))
{
return Context.Items["ServiceID"] as string;
}
else
{
return null;
}
}
set
{
Context.Items["ServiceID"] = value;
}
}
private DateTime StartTime
{
get
{
if (Context.Items.ContainsKey("StartTime"))
{
return (DateTime)Context.Items["StartTime"];
}
else
{
return DateTime.Now;
}
}
set
{
Context.Items["StartTime"] = value;
}
}
private List<string> ViewerList
{
@ -127,7 +91,7 @@ namespace Remotely.Server.Services
public async Task CtrlAltDel()
{
await DeviceHub.Clients.Client(ServiceID).SendAsync("CtrlAltDel");
await DeviceHub.Clients.Client(SessionInfo.ServiceID).SendAsync("CtrlAltDel");
}
public async Task GetSessionID()
{
@ -139,10 +103,7 @@ namespace Remotely.Server.Services
}
Context.Items["SessionID"] = sessionID;
while (!AttendedSessionList.TryAdd(sessionID, Context.ConnectionId))
{
await Task.Delay(1000);
}
SessionInfoList[Context.ConnectionId].AttendedSessionID = sessionID;
await Clients.Caller.SendAsync("SessionID", sessionID);
}
@ -157,44 +118,46 @@ namespace Remotely.Server.Services
await RCBrowserHub.Clients.Clients(viewerIDs).SendAsync("RelaunchedScreenCasterReady", Context.ConnectionId);
}
public override Task OnConnectedAsync()
public override async Task OnConnectedAsync()
{
StartTime = DateTime.Now;
return base.OnConnectedAsync();
SessionInfo = new RCSessionInfo()
{
RCSocketID = Context.ConnectionId,
StartTime = DateTime.Now
};
while (!SessionInfoList.TryAdd(Context.ConnectionId, SessionInfo))
{
await Task.Delay(100);
}
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
if (Context.Items.ContainsKey("SessionID") && AttendedSessionList.ContainsKey(Context.Items["SessionID"].ToString()))
{
while (!SessionInfoList.TryRemove(Context.ConnectionId, out _))
{
await Task.Delay(100);
}
if (SessionInfo.Mode == Shared.Enums.RemoteControlMode.Unattended)
{
while (!AttendedSessionList.TryRemove(Context.Items["SessionID"].ToString(), out var value))
{
await Task.Delay(1000);
}
await RCBrowserHub.Clients.Clients(ViewerList).SendAsync("ScreenCasterDisconnected");
}
else
else if (SessionInfo.Mode == Shared.Enums.RemoteControlMode.Unattended)
{
if (ViewerList.Count > 0)
{
await RCBrowserHub.Clients.Clients(ViewerList).SendAsync("Reconnecting");
await DeviceHub.Clients.Client(ServiceID).SendAsync("RestartScreenCaster", ViewerList, ServiceID, Context.ConnectionId);
await DeviceHub.Clients.Client(SessionInfo.ServiceID).SendAsync("RestartScreenCaster", ViewerList, SessionInfo.ServiceID, Context.ConnectionId);
}
}
if (!string.IsNullOrWhiteSpace(MachineName) && MachineNameToSessionIDLookup.ContainsKey(MachineName))
{
while (!MachineNameToSessionIDLookup.TryRemove(MachineName, out _))
{
await Task.Delay(1000);
}
}
await base.OnDisconnectedAsync(exception);
}
public void ReceiveDeviceInfo(string serviceID, string machineName)
{
ServiceID = serviceID;
MachineName = machineName;
MachineNameToSessionIDLookup[MachineName] = Context.ConnectionId;
SessionInfo.ServiceID = serviceID;
SessionInfo.MachineName = machineName;
}
public async Task SendMachineName(string machineName, string viewerID)
{
@ -219,7 +182,8 @@ namespace Remotely.Server.Services
{
if (AppConfig.RecordRemoteControlSessions)
{
RCSessionRecorder.SaveFrame(captureBytes, left, top, CurrentScreenSize.Width, CurrentScreenSize.Height, rcBrowserHubConnectionID, MachineName, StartTime);
RCSessionRecorder.SaveFrame(captureBytes, left, top, CurrentScreenSize.Width, CurrentScreenSize.Height,
rcBrowserHubConnectionID, SessionInfo.MachineName, SessionInfo.StartTime);
}
return RCBrowserHub.Clients.Client(rcBrowserHubConnectionID).SendAsync("ScreenCapture", captureBytes, left, top, width, height, captureTime);

View File

@ -1,7 +1,7 @@
{
"ConnectionStrings": {
"SQLite": "DataSource=Server.db",
"SQLServer": "Server=(localdb)\\mssqllocaldb;Database=aspnet-Server-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true",
"SQLServer": "Server=(localdb)\\mssqllocaldb;Database=Remotely-Server-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true",
"PostgreSQL": "Host=localhost;Database=;Username=;Password="
},
"Logging": {

View File

@ -1,6 +1,7 @@
export var RemoteControlMode;
(function (RemoteControlMode) {
RemoteControlMode[RemoteControlMode["Unattended"] = 0] = "Unattended";
RemoteControlMode[RemoteControlMode["Normal"] = 1] = "Normal";
RemoteControlMode[RemoteControlMode["None"] = 0] = "None";
RemoteControlMode[RemoteControlMode["Unattended"] = 1] = "Unattended";
RemoteControlMode[RemoteControlMode["Normal"] = 2] = "Normal";
})(RemoteControlMode || (RemoteControlMode = {}));
//# sourceMappingURL=RemoteControlMode.js.map

View File

@ -1 +1 @@
{"version":3,"file":"RemoteControlMode.js","sourceRoot":"","sources":["RemoteControlMode.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,iBAGX;AAHD,WAAY,iBAAiB;IACzB,qEAAU,CAAA;IACV,6DAAM,CAAA;AACV,CAAC,EAHW,iBAAiB,KAAjB,iBAAiB,QAG5B"}
{"version":3,"file":"RemoteControlMode.js","sourceRoot":"","sources":["RemoteControlMode.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,iBAIX;AAJD,WAAY,iBAAiB;IACzB,yDAAI,CAAA;IACJ,qEAAU,CAAA;IACV,6DAAM,CAAA;AACV,CAAC,EAJW,iBAAiB,KAAjB,iBAAiB,QAI5B"}

View File

@ -1,4 +1,5 @@
export enum RemoteControlMode {
None,
Unattended,
Normal
}

View File

@ -6,6 +6,7 @@ namespace Remotely.Shared.Enums
{
public enum RemoteControlMode
{
None,
Unattended,
Normal
}