Begin stubbling out device alert service.

This commit is contained in:
Jared Goodwin 2020-01-12 13:55:47 -08:00
parent 205f846bf2
commit e56307bc31
15 changed files with 207 additions and 202 deletions

View File

@ -10,6 +10,7 @@ using System.ServiceProcess;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading;
using Microsoft.Extensions.DependencyInjection;
namespace Remotely.Agent
{
@ -17,12 +18,17 @@ namespace Remotely.Agent
{
public static bool IsDebug { get; set; }
public static IServiceProvider Services { get; set; }
public static void Main(string[] args)
{
try
{
// TODO: Replace static services with scoped instances in IoC container.
var serviceCollection = new ServiceCollection();
Services = serviceCollection.BuildServiceProvider();
Task.Run(()=> { Init(args); });
Task.Run(() => { Init(args); });
Thread.Sleep(Timeout.Infinite);

View File

@ -120,7 +120,7 @@ namespace Remotely.Agent.Services
var partialResult = new GenericCommandResult()
{
CommandContextID = LastInputID,
DeviceID = Utilities.GetConnectionInfo().DeviceID,
DeviceID = ConfigService.GetConnectionInfo().DeviceID,
CommandType = "Bash",
StandardOutput = StandardOut,
ErrorOutput = "WARNING: The command execution froze and was forced to return before finishing. " +
@ -136,7 +136,7 @@ namespace Remotely.Agent.Services
return new GenericCommandResult()
{
CommandContextID = LastInputID,
DeviceID = Utilities.GetConnectionInfo().DeviceID,
DeviceID = ConfigService.GetConnectionInfo().DeviceID,
CommandType = "Bash",
StandardOutput = StandardOut,
ErrorOutput = ErrorOut

View File

@ -11,44 +11,6 @@ namespace Remotely.Agent.Services
{
public class CMD
{
private static ConcurrentDictionary<string, CMD> Sessions { get; set; } = new ConcurrentDictionary<string, CMD>();
private string ConnectionID { get; set; }
private string LastInputID { get; set; }
private bool OutputDone { get; set; }
private string StandardOut { get; set; }
private string ErrorOut { get; set; }
private System.Timers.Timer ProcessIdleTimeout { get; set; }
public static CMD GetCurrent(string connectionID)
{
if (Sessions.ContainsKey(connectionID))
{
var bash = Sessions[connectionID];
bash.ProcessIdleTimeout.Stop();
bash.ProcessIdleTimeout.Start();
return bash;
}
else
{
var cmd = new CMD();
cmd.ConnectionID = connectionID;
cmd.ProcessIdleTimeout = new System.Timers.Timer(600000); // 10 minutes.
cmd.ProcessIdleTimeout.AutoReset = false;
cmd.ProcessIdleTimeout.Elapsed += cmd.ProcessIdleTimeout_Elapsed;
Sessions.AddOrUpdate(connectionID, cmd, (id, c) => cmd);
cmd.ProcessIdleTimeout.Start();
return cmd;
}
}
private void ProcessIdleTimeout_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
Sessions.Remove(ConnectionID, out var outResult);
outResult.CMDProc.Kill();
}
private Process CMDProc { get; }
private CMD()
{
var psi = new ProcessStartInfo("cmd.exe");
@ -70,24 +32,34 @@ namespace Remotely.Agent.Services
CMDProc.BeginOutputReadLine();
}
private void CMDProc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e?.Data?.Contains(LastInputID) == true)
{
OutputDone = true;
}
else if (!OutputDone)
{
StandardOut += e.Data + Environment.NewLine;
}
private static ConcurrentDictionary<string, CMD> Sessions { get; set; } = new ConcurrentDictionary<string, CMD>();
private Process CMDProc { get; }
private string ConnectionID { get; set; }
}
private void CMDProc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
private string ErrorOut { get; set; }
private string LastInputID { get; set; }
private bool OutputDone { get; set; }
private System.Timers.Timer ProcessIdleTimeout { get; set; }
private string StandardOut { get; set; }
public static CMD GetCurrent(string connectionID)
{
if (e?.Data != null)
if (Sessions.ContainsKey(connectionID))
{
ErrorOut += e.Data + Environment.NewLine;
var bash = Sessions[connectionID];
bash.ProcessIdleTimeout.Stop();
bash.ProcessIdleTimeout.Start();
return bash;
}
else
{
var cmd = new CMD();
cmd.ConnectionID = connectionID;
cmd.ProcessIdleTimeout = new System.Timers.Timer(600000); // 10 minutes.
cmd.ProcessIdleTimeout.AutoReset = false;
cmd.ProcessIdleTimeout.Elapsed += cmd.ProcessIdleTimeout_Elapsed;
Sessions.AddOrUpdate(connectionID, cmd, (id, c) => cmd);
cmd.ProcessIdleTimeout.Start();
return cmd;
}
}
@ -112,7 +84,40 @@ namespace Remotely.Agent.Services
}
return GenerateCompletedResult();
}
}
private void CMDProc_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
if (e?.Data != null)
{
ErrorOut += e.Data + Environment.NewLine;
}
}
private void CMDProc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (e?.Data?.Contains(LastInputID) == true)
{
OutputDone = true;
}
else if (!OutputDone)
{
StandardOut += e.Data + Environment.NewLine;
}
}
private GenericCommandResult GenerateCompletedResult()
{
return new GenericCommandResult()
{
CommandContextID = LastInputID,
DeviceID = ConfigService.GetConnectionInfo().DeviceID,
CommandType = "CMD",
StandardOutput = StandardOut,
ErrorOutput = ErrorOut
};
}
private GenericCommandResult GeneratePartialResult()
@ -121,7 +126,7 @@ namespace Remotely.Agent.Services
var partialResult = new GenericCommandResult()
{
CommandContextID = LastInputID,
DeviceID = Utilities.GetConnectionInfo().DeviceID,
DeviceID = ConfigService.GetConnectionInfo().DeviceID,
CommandType = "CMD",
StandardOutput = StandardOut,
ErrorOutput = "WARNING: The command execution froze and was forced to return before finishing. " +
@ -132,17 +137,10 @@ namespace Remotely.Agent.Services
return partialResult;
}
private GenericCommandResult GenerateCompletedResult()
private void ProcessIdleTimeout_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
return new GenericCommandResult()
{
CommandContextID = LastInputID,
DeviceID = Utilities.GetConnectionInfo().DeviceID,
CommandType = "CMD",
StandardOutput = StandardOut,
ErrorOutput = ErrorOut
};
Sessions.Remove(ConnectionID, out var outResult);
outResult.CMDProc.Kill();
}
}
}

View File

@ -0,0 +1,35 @@
using Remotely.Shared.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace Remotely.Agent.Services
{
public static class ConfigService
{
private static ConnectionInfo connectionInfo;
public static ConnectionInfo GetConnectionInfo()
{
if (connectionInfo == null)
{
if (!File.Exists("ConnectionInfo.json"))
{
Logger.Write(new Exception("No connection info available. Please create ConnectionInfo.json file with appropriate values."));
return null;
}
connectionInfo = JsonConvert.DeserializeObject<ConnectionInfo>(File.ReadAllText("ConnectionInfo.json"));
}
return connectionInfo;
}
public static void SaveConnectionInfo(ConnectionInfo connectionInfo)
{
File.WriteAllText("ConnectionInfo.json", JsonConvert.SerializeObject(connectionInfo));
}
}
}

View File

@ -27,7 +27,7 @@ namespace Remotely.Agent.Services
public static async Task Connect()
{
ConnectionInfo = Utilities.GetConnectionInfo();
ConnectionInfo = ConfigService.GetConnectionInfo();
HubConnection = new HubConnectionBuilder()
.WithUrl(ConnectionInfo.Host + "/DeviceHub")
@ -47,18 +47,15 @@ namespace Remotely.Agent.Services
IsServerVerified = true;
ConnectionInfo.ServerVerificationToken = Guid.NewGuid().ToString();
await HubConnection.InvokeAsync("SetServerVerificationToken", ConnectionInfo.ServerVerificationToken);
Utilities.SaveConnectionInfo(ConnectionInfo);
ConfigService.SaveConnectionInfo(ConnectionInfo);
}
else
{
await HubConnection.InvokeAsync("SendServerVerificationToken");
}
if (HeartbeatTimer != null)
{
HeartbeatTimer.Stop();
}
HeartbeatTimer = new Timer(300000);
HeartbeatTimer?.Dispose();
HeartbeatTimer = new Timer(TimeSpan.FromMinutes(5).TotalMilliseconds);
HeartbeatTimer.Elapsed += HeartbeatTimer_Elapsed;
HeartbeatTimer.Start();
}
@ -171,7 +168,7 @@ namespace Remotely.Agent.Services
hubConnection.On("TransferFiles", async (string transferID, List<string> fileIDs, string requesterID) =>
{
Logger.Write($"File transfer started by {requesterID}.");
var connectionInfo = Utilities.GetConnectionInfo();
var connectionInfo = ConfigService.GetConnectionInfo();
var sharedFilePath = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(),"RemotelySharedFiles")).FullName;
foreach (var fileID in fileIDs)
@ -201,7 +198,7 @@ namespace Remotely.Agent.Services
await HubConnection.InvokeAsync("TransferCompleted", transferID, requesterID);
});
hubConnection.On("DeployScript", async (string mode, string fileID, string commandContextID, string requesterID) => {
var connectionInfo = Utilities.GetConnectionInfo();
var connectionInfo = ConfigService.GetConnectionInfo();
var sharedFilePath = Directory.CreateDirectory(Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"Remotely",
@ -253,11 +250,11 @@ namespace Remotely.Agent.Services
if (Program.IsDebug)
{
Process.Start(rcBinaryPath, $"-mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -desktop default");
Process.Start(rcBinaryPath, $"-mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {ConfigService.GetConnectionInfo().Host} -desktop default");
}
else
{
var result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -desktop default", "default", true, out _);
var result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {ConfigService.GetConnectionInfo().Host} -desktop default", "default", true, out _);
if (!result)
{
await hubConnection.InvokeAsync("DisplayMessage", "Remote control failed to start on target device.", "Failed to start remote control.", requesterID);
@ -272,7 +269,7 @@ namespace Remotely.Agent.Services
var psi = new ProcessStartInfo()
{
FileName = "sudo",
Arguments = $"-u {username} {rcBinaryPath} -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -desktop default & disown"
Arguments = $"-u {username} {rcBinaryPath} -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {ConfigService.GetConnectionInfo().Host} -desktop default & disown"
};
psi.Environment.Add("DISPLAY", ":0");
psi.Environment.Add("XAUTHORITY", $"{homeDir}/.Xauthority");
@ -304,7 +301,7 @@ namespace Remotely.Agent.Services
Logger.Write("Restarting screen caster.");
if (Program.IsDebug)
{
var proc = Process.Start(rcBinaryPath, $"-mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)}");
var proc = Process.Start(rcBinaryPath, $"-mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {ConfigService.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)}");
var stopwatch = Stopwatch.StartNew();
while (stopwatch.Elapsed.TotalSeconds < 10)
{
@ -317,7 +314,7 @@ namespace Remotely.Agent.Services
}
else
{
var result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)}", "default", true, out var procInfo);
var result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {ConfigService.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)}", "default", true, out var procInfo);
if (result)
{
@ -332,7 +329,7 @@ namespace Remotely.Agent.Services
if (Process.GetProcessesByName(Path.GetFileNameWithoutExtension(rcBinaryPath))?.Where(x=>x.Id == procInfo.dwProcessId)?.Any() != true)
{
Logger.Write("Restarting screen caster after failed relaunch.");
result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)}", "default", true, out procInfo);
result = Win32Interop.OpenInteractiveProcess(rcBinaryPath + $" -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {ConfigService.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)}", "default", true, out procInfo);
}
}
}
@ -353,7 +350,7 @@ namespace Remotely.Agent.Services
var psi = new ProcessStartInfo()
{
FileName = "sudo",
Arguments = $"-u {username} {rcBinaryPath} -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {Utilities.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)} & disown"
Arguments = $"-u {username} {rcBinaryPath} -mode Unattended -requester {requesterID} -serviceid {serviceID} -deviceid {ConnectionInfo.DeviceID} -host {ConfigService.GetConnectionInfo().Host} -relaunch true -desktop default -viewers {String.Join(",", viewerIDs)} & disown"
};
psi.Environment.Add("DISPLAY", ":0");
psi.Environment.Add("XAUTHORITY", $"{homeDir}/.Xauthority");
@ -375,7 +372,7 @@ namespace Remotely.Agent.Services
hubConnection.On("ServerVerificationToken", (string verificationToken) =>
{
if (verificationToken == Utilities.GetConnectionInfo().ServerVerificationToken)
if (verificationToken == ConfigService.GetConnectionInfo().ServerVerificationToken)
{
IsServerVerified = true;
if (!Program.IsDebug)
@ -394,7 +391,7 @@ namespace Remotely.Agent.Services
private static void SendResultsViaAjax(string resultType, object result)
{
var targetURL = Utilities.GetConnectionInfo().Host + $"/API/Commands/{resultType}";
var targetURL = ConfigService.GetConnectionInfo().Host + $"/API/Commands/{resultType}";
var webRequest = WebRequest.CreateHttp(targetURL);
webRequest.Method = "POST";

View File

@ -72,7 +72,7 @@ namespace Remotely.Agent.Services
return new PSCoreCommandResult()
{
CommandContextID = commandID,
DeviceID = Utilities.GetConnectionInfo().DeviceID,
DeviceID = ConfigService.GetConnectionInfo().DeviceID,
DebugOutput = debugOut,
ErrorOutput = errorOut,
VerboseOutput = verboseOut,

View File

@ -20,7 +20,7 @@ namespace Remotely.Agent.Services
try
{
var wc = new WebClient();
var response = new HttpClient().GetAsync(Utilities.GetConnectionInfo().Host + $"/API/CoreVersion/").Result;
var response = new HttpClient().GetAsync(ConfigService.GetConnectionInfo().Host + $"/API/CoreVersion/").Result;
var latestVersion = response.Content.ReadAsStringAsync().Result;
var thisVersion = FileVersionInfo.GetVersionInfo("Remotely_Agent.dll").FileVersion.ToString().Trim();
if (thisVersion != latestVersion)
@ -37,7 +37,7 @@ namespace Remotely.Agent.Services
{
Directory.Delete(tempFolder, true);
}
wc.DownloadFile(new Uri(Utilities.GetConnectionInfo().Host + $"/Downloads/{fileName}"), tempFile);
wc.DownloadFile(new Uri(ConfigService.GetConnectionInfo().Host + $"/Downloads/{fileName}"), tempFile);
Logger.Write($"Service Updater: Extracting files.");
@ -187,10 +187,8 @@ namespace Remotely.Agent.Services
{
throw new Exception("Unsupported operating system.");
}
var response = await new HttpClient().GetAsync(Utilities.GetConnectionInfo().Host + $"/API/ScreenCastVersion/{platform}");
var response = await new HttpClient().GetAsync(ConfigService.GetConnectionInfo().Host + $"/API/ScreenCastVersion/{platform}");
return await response.Content.ReadAsStringAsync();
}
}
}

View File

@ -1,65 +0,0 @@
using Remotely.Shared.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace Remotely.Agent.Services
{
public static class Utilities
{
public static ConnectionInfo GetConnectionInfo()
{
if (!File.Exists("ConnectionInfo.json"))
{
Logger.Write(new Exception("No connection info available. Please create ConnectionInfo.json file with appropriate values."));
}
return JsonConvert.DeserializeObject<ConnectionInfo>(File.ReadAllText("ConnectionInfo.json"));
}
public static string AppDataDir
{
get
{
return Directory.CreateDirectory(
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"Remotely")
).FullName;
}
}
public static void KillProcs()
{
var procs = Process.GetProcessesByName("Agent_Win").Where(proc => proc.Id != Process.GetCurrentProcess().Id);
foreach (var proc in procs)
{
proc.Kill();
}
}
public static Dictionary<string, string> ProcessArgs(string[] args)
{
var argDict = new Dictionary<string, string>();
var argString = String.Join(" ", args).ToLower();
var argArray = argString.Split("-".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
foreach (var arg in argArray)
{
var split = arg.Split(" ".ToCharArray(), 2, StringSplitOptions.RemoveEmptyEntries);
var key = split[0];
var value = split.Length == 2 ? split[1] : "";
argDict.Add(key, value);
}
return argDict;
}
public static void SaveConnectionInfo(ConnectionInfo connectionInfo)
{
File.WriteAllText("ConnectionInfo.json", JsonConvert.SerializeObject(connectionInfo));
}
}
}

View File

@ -118,7 +118,7 @@ namespace Remotely.Agent.Services
var partialResult = new GenericCommandResult()
{
CommandContextID = LastInputID,
DeviceID = Utilities.GetConnectionInfo().DeviceID,
DeviceID = ConfigService.GetConnectionInfo().DeviceID,
CommandType = "WinPS",
StandardOutput = StandardOut,
ErrorOutput = "WARNING: The command execution froze and was forced to return before finishing. " +
@ -134,7 +134,7 @@ namespace Remotely.Agent.Services
return new GenericCommandResult()
{
CommandContextID = LastInputID,
DeviceID = Utilities.GetConnectionInfo().DeviceID,
DeviceID = ConfigService.GetConnectionInfo().DeviceID,
CommandType = "WinPS",
StandardOutput = StandardOut,
ErrorOutput = ErrorOut

View File

@ -392,17 +392,6 @@ namespace Remotely.Server.Data
.UserOptions;
}
public List<RemotelyUser> GetUsersWithAccessToDevice(IEnumerable<string> userIDs, Device device)
{
var targetDevice = RemotelyContext.Devices
.FirstOrDefault(x => x.ID == device.ID && x.OrganizationID == device.OrganizationID);
var targetUsers = RemotelyContext.Users.Where(x =>
x.OrganizationID == device.OrganizationID &&
userIDs.Contains(x.Id)).ToList();
return targetUsers.ToList();
}
public bool JoinViaInvitation(string userName, string inviteID)
{
var invite = RemotelyContext.InviteLinks

View File

@ -0,0 +1,38 @@
using Remotely.Server.Data;
using Remotely.Shared.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Remotely.Server.Services
{
public class DeviceAlertService
{
public DeviceAlertService(DataService dataService, ApplicationConfig appConfig)
{
DataService = dataService;
AppConfig = appConfig;
}
public DataService DataService { get; }
public ApplicationConfig AppConfig { get; }
public bool ShouldSendAlert(Device device, out DeviceAlert alert)
{
if (true) // Check
{
//DataService.AddDeviceAlert(alert);
//TrySendAlertEmail(alert);
//TrySendAlertWebRequest(alert);
alert = new DeviceAlert();
return true;
}
else
{
alert = null;
return false;
}
}
}
}

View File

@ -14,14 +14,19 @@ namespace Remotely.Server.Services
{
public class DeviceSocketHub : Hub
{
public DeviceSocketHub(DataService dataService, IHubContext<BrowserSocketHub> browserHub, IHubContext<RCBrowserSocketHub> rcBrowserHub)
public DeviceSocketHub(DataService dataService,
IHubContext<BrowserSocketHub> browserHub,
IHubContext<RCBrowserSocketHub> rcBrowserHub,
DeviceAlertService deviceAlertService)
{
DataService = dataService;
BrowserHub = browserHub;
RCBrowserHub = rcBrowserHub;
DeviceAlertService = deviceAlertService;
}
public static ConcurrentDictionary<string, Device> ServiceConnections { get; } = new ConcurrentDictionary<string, Device>();
public DeviceAlertService DeviceAlertService { get; }
public IHubContext<RCBrowserSocketHub> RCBrowserHub { get; }
private IHubContext<BrowserSocketHub> BrowserHub { get; }
private DataService DataService { get; }
@ -79,14 +84,10 @@ namespace Remotely.Server.Services
Device = updatedDevice;
ServiceConnections.AddOrUpdate(Context.ConnectionId, Device, (id, d) => Device);
var onlineOrganizationUsers = BrowserSocketHub.ConnectionIdToUserLookup
.Where(x => x.Value.OrganizationID == Device.OrganizationID);
var authorizedUsers = DataService.GetUsersWithAccessToDevice(onlineOrganizationUsers.Select(x => x.Value.Id), Device);
var connectionIds = onlineOrganizationUsers
.Where(onlineUser => authorizedUsers.Any(authorizedUser => authorizedUser.Id == onlineUser.Value.Id))
.Select(x => x.Key)
.ToList();
var connectionIds = BrowserSocketHub.ConnectionIdToUserLookup
.Where(x => x.Value.OrganizationID == Device.OrganizationID)
.Select(x => x.Key)
.ToList();
await BrowserHub.Clients.Clients(connectionIds).SendAsync("DeviceCameOnline", Device);
}
@ -107,16 +108,17 @@ namespace Remotely.Server.Services
{
DataService.AddOrUpdateDevice(device, out var updatedDevice);
Device = updatedDevice;
var onlineOrganizationUsers = BrowserSocketHub.ConnectionIdToUserLookup
.Where(x => x.Value.OrganizationID == Device.OrganizationID);
var authorizedUsers = DataService.GetUsersWithAccessToDevice(onlineOrganizationUsers.Select(x=>x.Value.Id), Device);
var connectionIds = onlineOrganizationUsers
.Where(onlineUser => authorizedUsers.Any(authorizedUser => authorizedUser.Id == onlineUser.Value.Id))
.Select(x => x.Key)
.ToList();
var connectionIds = BrowserSocketHub.ConnectionIdToUserLookup
.Where(x => x.Value.OrganizationID == Device.OrganizationID)
.Select(x => x.Key)
.ToList();
await BrowserHub.Clients.Clients(connectionIds).SendAsync("DeviceHeartbeat", Device);
if (DeviceAlertService.ShouldSendAlert(Device, out var alert))
{
await BrowserHub.Clients.Clients(connectionIds).SendAsync("DeviceAlert", alert);
}
}
public async Task DisplayMessage(string consoleMessage, string popupMessage, string requesterID)
@ -135,18 +137,19 @@ namespace Remotely.Server.Services
Device.IsOnline = false;
var onlineOrganizationUsers = BrowserSocketHub.ConnectionIdToUserLookup
.Where(x => x.Value.OrganizationID == Device.OrganizationID);
var authorizedUsers = DataService.GetUsersWithAccessToDevice(onlineOrganizationUsers.Select(x => x.Value.Id), Device);
var connectionIds = onlineOrganizationUsers
.Where(onlineUser => authorizedUsers.Any(authorizedUser => authorizedUser.Id == onlineUser.Value.Id))
.Select(x => x.Key)
.ToList();
var connectionIds = BrowserSocketHub.ConnectionIdToUserLookup
.Where(x => x.Value.OrganizationID == Device.OrganizationID)
.Select(x => x.Key)
.ToList();
await BrowserHub.Clients.Clients(connectionIds).SendAsync("DeviceWentOffline", Device);
ServiceConnections.Remove(Context.ConnectionId, out _);
if (DeviceAlertService.ShouldSendAlert(Device, out var alert))
{
await BrowserHub.Clients.Clients(connectionIds).SendAsync("DeviceAlert", alert);
}
}
await base.OnDisconnectedAsync(exception);

View File

@ -25,5 +25,6 @@ namespace Remotely.Shared.Models
}
public string OrganizationID { get; set; }
public string ServerVerificationToken { get; set; }
}
}

View File

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Remotely.Shared.Models
{
public class DeviceAlert
{
}
}

View File

@ -10,15 +10,10 @@ namespace Remotely.Shared.Models
{
public class RemotelyUser : IdentityUser
{
public RemotelyUser()
{
UserOptions = new RemotelyUserOptions();
Organization = new Organization();
}
public RemotelyUserOptions UserOptions { get; set; }
public RemotelyUserOptions UserOptions { get; set; } = new RemotelyUserOptions();
[JsonIgnore]
public virtual Organization Organization { get; set; }
public virtual Organization Organization { get; set; } = new Organization();
public string OrganizationID { get; set; }
public bool IsAdministrator { get; set; } = true;