mirror of
https://github.com/immense/Remotely.git
synced 2025-10-26 11:27:15 +00:00
Added Server Logs page. Added outgoing buffer throttling in screen caster. Refactoring.
This commit is contained in:
parent
8a1a642d2b
commit
9736ed31c3
@ -15,9 +15,9 @@ namespace Remotely.Agent.Services
|
||||
public static object WriteLock { get; } = new object();
|
||||
public static void Write(string message)
|
||||
{
|
||||
lock (WriteLock)
|
||||
try
|
||||
{
|
||||
try
|
||||
lock (WriteLock)
|
||||
{
|
||||
var path = Path.Combine(Path.GetTempPath(), "Remotely_Logs.txt");
|
||||
if (!File.Exists(path))
|
||||
@ -28,12 +28,6 @@ namespace Remotely.Agent.Services
|
||||
Process.Start("sudo", $"chmod 666 {path}").WaitForExit();
|
||||
}
|
||||
}
|
||||
var jsoninfo = new
|
||||
{
|
||||
Type = "Info",
|
||||
Timestamp = DateTime.Now.ToString(),
|
||||
Message = message
|
||||
};
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var fi = new FileInfo(path);
|
||||
@ -44,10 +38,11 @@ namespace Remotely.Agent.Services
|
||||
fi = new FileInfo(path);
|
||||
}
|
||||
}
|
||||
File.AppendAllText(path, JsonConvert.SerializeObject(jsoninfo) + Environment.NewLine);
|
||||
File.AppendAllText(path, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\t[INFO]\t{message}{Environment.NewLine}");
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
public static void Write(Exception ex)
|
||||
@ -59,6 +54,15 @@ namespace Remotely.Agent.Services
|
||||
var exception = ex;
|
||||
var path = Path.Combine(Path.GetTempPath(), "Remotely_Logs.txt");
|
||||
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
File.Create(path).Close();
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
Process.Start("sudo", $"chmod 666 {path}").WaitForExit();
|
||||
}
|
||||
}
|
||||
|
||||
while (exception != null)
|
||||
{
|
||||
var jsonError = new
|
||||
@ -79,7 +83,8 @@ namespace Remotely.Agent.Services
|
||||
fi = new FileInfo(path);
|
||||
}
|
||||
}
|
||||
File.AppendAllText(path, JsonConvert.SerializeObject(jsonError) + Environment.NewLine);
|
||||
File.AppendAllText(path, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\t[ERROR]\t{exception?.Message}\t{exception?.StackTrace}\t{exception?.Source}{Environment.NewLine}");
|
||||
Console.WriteLine(exception.Message);
|
||||
exception = exception.InnerException;
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +98,14 @@ namespace Remotely.ScreenCast.Core.Capture
|
||||
fpsQueue.Dequeue();
|
||||
}
|
||||
fpsQueue.Enqueue(DateTime.Now);
|
||||
Debug.WriteLine("Capture FPS: " + fpsQueue.Count);
|
||||
Debug.WriteLine($"Capture FPS: {fpsQueue.Count}");
|
||||
}
|
||||
|
||||
if (viewer.OutputBuffer > 150_000)
|
||||
{
|
||||
Debug.WriteLine($"Waiting for buffer to clear. Size: {viewer.OutputBuffer}");
|
||||
await Task.Delay(50);
|
||||
continue;
|
||||
}
|
||||
|
||||
capturer.GetNextFrame();
|
||||
@ -120,7 +127,7 @@ namespace Remotely.ScreenCast.Core.Capture
|
||||
if (viewer.AutoAdjustQuality && viewer.Latency > 1000)
|
||||
{
|
||||
var quality = (int)(viewer.ImageQuality * 1000 / viewer.Latency);
|
||||
Logger.Write($"Auto-adjusting image quality. Latency: {viewer.Latency}. Quality: {quality}");
|
||||
Debug.WriteLine($"Auto-adjusting image quality. Latency: {viewer.Latency}. Quality: {quality}");
|
||||
encodedImageBytes = ImageUtils.EncodeBitmap(newImage, new EncoderParameters()
|
||||
{
|
||||
Param = new[]
|
||||
@ -138,6 +145,7 @@ namespace Remotely.ScreenCast.Core.Capture
|
||||
{
|
||||
await conductor.CasterSocket.SendScreenCapture(encodedImageBytes, viewerID, diffArea.Left, diffArea.Top, diffArea.Width, diffArea.Height, DateTime.UtcNow);
|
||||
viewer.Latency += 300;
|
||||
viewer.OutputBuffer += encodedImageBytes.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +53,7 @@ namespace Remotely.ScreenCast.Core.Models
|
||||
|
||||
public double Latency { get; set; } = 1;
|
||||
public string Name { get; set; }
|
||||
public int OutputBuffer { get; set; }
|
||||
public string ViewerConnectionID { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,12 +29,6 @@ namespace Remotely.ScreenCast.Core.Services
|
||||
Process.Start("sudo", $"chmod 666 {path}").WaitForExit();
|
||||
}
|
||||
}
|
||||
var jsoninfo = new
|
||||
{
|
||||
Type = "Info",
|
||||
Timestamp = DateTime.Now.ToString(),
|
||||
Message = message
|
||||
};
|
||||
if (File.Exists(path))
|
||||
{
|
||||
var fi = new FileInfo(path);
|
||||
@ -45,7 +39,7 @@ namespace Remotely.ScreenCast.Core.Services
|
||||
fi = new FileInfo(path);
|
||||
}
|
||||
}
|
||||
File.AppendAllText(path, JsonSerializer.Serialize(jsoninfo) + Environment.NewLine);
|
||||
File.AppendAllText(path, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\t[INFO]\t{message}{Environment.NewLine}");
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
}
|
||||
@ -90,7 +84,7 @@ namespace Remotely.ScreenCast.Core.Services
|
||||
fi = new FileInfo(path);
|
||||
}
|
||||
}
|
||||
File.AppendAllText(path, JsonSerializer.Serialize(jsonError) + Environment.NewLine);
|
||||
File.AppendAllText(path, $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}\t[ERROR]\t{exception?.Message}\t{exception?.StackTrace}\t{exception?.Source}{Environment.NewLine}");
|
||||
Console.WriteLine(exception.Message);
|
||||
exception = exception.InnerException;
|
||||
}
|
||||
|
||||
@ -271,12 +271,13 @@ namespace Remotely.ScreenCast.Core.Sockets
|
||||
conductor.InvokeViewerRemoved(viewerID);
|
||||
|
||||
});
|
||||
Connection.On("LatencyUpdate", (DateTime sentTime, string viewerID) =>
|
||||
Connection.On("LatencyUpdate", (DateTime sentTime, int bytesReceived, string viewerID) =>
|
||||
{
|
||||
if (conductor.Viewers.TryGetValue(viewerID, out var viewer))
|
||||
{
|
||||
var latency = DateTime.UtcNow - sentTime;
|
||||
viewer.Latency = latency.TotalMilliseconds;
|
||||
viewer.OutputBuffer -= bytesReceived;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -3,12 +3,12 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Remotely.Server.Data;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Remotely.Server.Services;
|
||||
|
||||
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||
|
||||
|
||||
@ -7,10 +7,9 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Serialization;
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Server.Data;
|
||||
using Remotely.Server.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||
|
||||
@ -41,7 +40,7 @@ namespace Remotely.Server.API
|
||||
switch (fileExt.ToUpper())
|
||||
{
|
||||
case "JSON":
|
||||
content = JsonConvert.SerializeObject(commandContexts);
|
||||
content = System.Text.Json.JsonSerializer.Serialize(commandContexts);
|
||||
break;
|
||||
case "XML":
|
||||
var serializer = new DataContractSerializer(typeof(CommandContext));
|
||||
@ -67,7 +66,7 @@ namespace Remotely.Server.API
|
||||
switch (fileExt.ToUpper())
|
||||
{
|
||||
case "JSON":
|
||||
content = JsonConvert.SerializeObject(commandContext);
|
||||
content = System.Text.Json.JsonSerializer.Serialize(commandContext);
|
||||
break;
|
||||
case "XML":
|
||||
var serializer = new DataContractSerializer(typeof(CommandContext));
|
||||
@ -108,7 +107,7 @@ namespace Remotely.Server.API
|
||||
{
|
||||
case "PSCore":
|
||||
{
|
||||
var result = JsonConvert.DeserializeObject<PSCoreCommandResult>(content);
|
||||
var result = System.Text.Json.JsonSerializer.Deserialize<PSCoreCommandResult>(content);
|
||||
var commandContext = DataService.GetCommandContext(result.CommandContextID);
|
||||
commandContext.PSCoreResults.Add(result);
|
||||
DataService.AddOrUpdateCommandContext(commandContext);
|
||||
@ -118,7 +117,7 @@ namespace Remotely.Server.API
|
||||
case "CMD":
|
||||
case "Bash":
|
||||
{
|
||||
var result = JsonConvert.DeserializeObject<GenericCommandResult>(content);
|
||||
var result = System.Text.Json.JsonSerializer.Deserialize<GenericCommandResult>(content);
|
||||
var commandContext = DataService.GetCommandContext(result.CommandContextID);
|
||||
commandContext.CommandResults.Add(result);
|
||||
DataService.AddOrUpdateCommandContext(commandContext);
|
||||
|
||||
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Server.Data;
|
||||
using Remotely.Server.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Remotely.Server.Data;
|
||||
using Remotely.Server.Services;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@ -14,14 +14,14 @@ using Microsoft.Net.Http.Headers;
|
||||
namespace Remotely.Server.API
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
public class FileSharing : Controller
|
||||
public class FileSharingController : Controller
|
||||
{
|
||||
public FileSharing(DataService dataService)
|
||||
public FileSharingController(DataService dataService)
|
||||
{
|
||||
DataService = dataService;
|
||||
}
|
||||
public DataService DataService { get; set; }
|
||||
// GET api/<controller>/5
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public ActionResult Get(string id)
|
||||
{
|
||||
@ -36,30 +36,40 @@ namespace Remotely.Server.API
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var orgId = DataService.GetUserByName(login.Email)?.OrganizationID;
|
||||
|
||||
var result = await SignInManager.PasswordSignInAsync(login.Email, login.Password, false, true);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
DataService.WriteEvent($"API login successful for {login.Email}.");
|
||||
DataService.WriteEvent($"API login successful for {login.Email}.", orgId);
|
||||
return Ok();
|
||||
}
|
||||
else if (result.IsLockedOut)
|
||||
{
|
||||
DataService.WriteEvent($"API login unsuccessful due to lockout for {login.Email}.");
|
||||
DataService.WriteEvent($"API login unsuccessful due to lockout for {login.Email}.", orgId);
|
||||
return Unauthorized("Account is locked.");
|
||||
}
|
||||
else if (result.RequiresTwoFactor)
|
||||
{
|
||||
DataService.WriteEvent($"API login unsuccessful due to 2FA for {login.Email}.");
|
||||
DataService.WriteEvent($"API login unsuccessful due to 2FA for {login.Email}.", orgId);
|
||||
return Unauthorized("Account requires two-factor authentication.");
|
||||
}
|
||||
DataService.WriteEvent($"API login unsuccessful due to bad attempt for {login.Email}.");
|
||||
DataService.WriteEvent($"API login unsuccessful due to bad attempt for {login.Email}.", orgId);
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
[HttpGet("Logout")]
|
||||
public async Task<IActionResult> Logout()
|
||||
{
|
||||
string orgId = null;
|
||||
|
||||
if (HttpContext?.User?.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
orgId = DataService.GetUserByName(HttpContext.User.Identity.Name)?.OrganizationID;
|
||||
}
|
||||
await SignInManager.SignOutAsync();
|
||||
DataService.WriteEvent($"API logout successful for {HttpContext?.User?.Identity?.Name}.", orgId);
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,23 +47,26 @@ namespace Remotely.Server.API
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var orgId = DataService.GetUserByName(rcRequest.Email)?.OrganizationID;
|
||||
|
||||
var result = await SignInManager.PasswordSignInAsync(rcRequest.Email, rcRequest.Password, false, true);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
DataService.WriteEvent($"API login successful for {rcRequest.Email}.");
|
||||
DataService.WriteEvent($"API login successful for {rcRequest.Email}.", orgId);
|
||||
return await InitiateRemoteControl(rcRequest.DeviceID, rcRequest.Email);
|
||||
}
|
||||
else if (result.IsLockedOut)
|
||||
{
|
||||
DataService.WriteEvent($"API login unsuccessful due to lockout for {rcRequest.Email}.");
|
||||
DataService.WriteEvent($"API login unsuccessful due to lockout for {rcRequest.Email}.", orgId);
|
||||
return Unauthorized("Account is locked.");
|
||||
}
|
||||
else if (result.RequiresTwoFactor)
|
||||
{
|
||||
DataService.WriteEvent($"API login unsuccessful due to 2FA for {rcRequest.Email}.");
|
||||
DataService.WriteEvent($"API login unsuccessful due to 2FA for {rcRequest.Email}.", orgId);
|
||||
return Unauthorized("Account requires two-factor authentication.");
|
||||
}
|
||||
DataService.WriteEvent($"API login unsuccessful due to bad attempt for {rcRequest.Email}.");
|
||||
DataService.WriteEvent($"API login unsuccessful due to bad attempt for {rcRequest.Email}.", orgId);
|
||||
return BadRequest();
|
||||
}
|
||||
|
||||
|
||||
37
Server/API/ServerLogsController.cs
Normal file
37
Server/API/ServerLogsController.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Mime;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Remotely.Server.Services;
|
||||
using Remotely.Shared.Models;
|
||||
|
||||
namespace Remotely.Server.API
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class ServerLogsController : ControllerBase
|
||||
{
|
||||
|
||||
public ServerLogsController(DataService dataService)
|
||||
{
|
||||
DataService = dataService;
|
||||
}
|
||||
public DataService DataService { get; set; }
|
||||
|
||||
// GET: api/ServerLogs
|
||||
[HttpGet("Download")]
|
||||
public ActionResult Download()
|
||||
{
|
||||
var logs = DataService.GetAllEventLogs(HttpContext.User.Identity.Name);
|
||||
var fileBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(logs));
|
||||
return File(fileBytes, "application/octet-stream", "ServerLogs.json");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -24,6 +24,8 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
public static string Options => "Options";
|
||||
public static string Organization => "Organization";
|
||||
|
||||
public static string ServerLogs => "ServerLogs";
|
||||
|
||||
public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index);
|
||||
|
||||
public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword);
|
||||
@ -39,6 +41,7 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
public static string TwoFactorAuthenticationNavClass(ViewContext viewContext) => PageNavClass(viewContext, TwoFactorAuthentication);
|
||||
public static string OptionsNavClass(ViewContext viewContext) => PageNavClass(viewContext, Options);
|
||||
public static string OrganizationNavClass(ViewContext viewContext) => PageNavClass(viewContext, Organization);
|
||||
public static string ServerLogsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ServerLogs);
|
||||
|
||||
public static string PageNavClass(ViewContext viewContext, string page)
|
||||
{
|
||||
|
||||
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Server.Data;
|
||||
using Remotely.Server.Services;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Shared.ViewModels;
|
||||
using Remotely.Server.Data;
|
||||
using Remotely.Server.Services;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using System.Collections.Generic;
|
||||
@ -13,10 +13,9 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
{
|
||||
public class OrganizationModel : PageModel
|
||||
{
|
||||
public OrganizationModel(DataService dataService, UserManager<RemotelyUser> userManager)
|
||||
public OrganizationModel(DataService dataService)
|
||||
{
|
||||
DataService = dataService;
|
||||
UserManager = userManager;
|
||||
}
|
||||
public List<SelectListItem> DeviceGroups { get; } = new List<SelectListItem>();
|
||||
|
||||
@ -31,7 +30,6 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
public List<OrganizationUser> Users { get; set; }
|
||||
|
||||
private DataService DataService { get; }
|
||||
private UserManager<RemotelyUser> UserManager { get; }
|
||||
public void OnGet()
|
||||
{
|
||||
OrganizationName = DataService.GetOrganizationName(User.Identity.Name);
|
||||
|
||||
53
Server/Areas/Identity/Pages/Account/Manage/ServerLogs.cshtml
Normal file
53
Server/Areas/Identity/Pages/Account/Manage/ServerLogs.cshtml
Normal file
@ -0,0 +1,53 @@
|
||||
@page
|
||||
@model Remotely.Server.Areas.Identity.Pages.Account.Manage.ServerLogsModel
|
||||
@inject DataService DataService
|
||||
@{
|
||||
ViewData["Title"] = "Server Logs";
|
||||
var currentUser = DataService.GetUserByName(User.Identity.Name);
|
||||
var isAdmin = currentUser.IsAdministrator;
|
||||
var eventLogs = DataService.GetAllEventLogs(User.Identity.Name);
|
||||
}
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
|
||||
@if (isAdmin)
|
||||
{
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-12 text-right">
|
||||
<button class="btn btn-primary mr-3"
|
||||
onclick="location.assign('/API/Commands/JSON')">
|
||||
Scripting History
|
||||
</button>
|
||||
<button class="btn btn-primary"
|
||||
onclick="location.assign('/API/ServerLogs/Download')">
|
||||
Server Logs
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<table class="table table-hover table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Timestamp</th>
|
||||
<th>Message</th>
|
||||
<th>Source</th>
|
||||
<th>Stack Trace</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var eventLog in eventLogs)
|
||||
{
|
||||
<tr>
|
||||
<td>@eventLog.EventType</td>
|
||||
<td>@eventLog.TimeStamp</td>
|
||||
<td>@eventLog.Message</td>
|
||||
<td>@eventLog.Source</td>
|
||||
<td>@eventLog.StackTrace</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
else
|
||||
{
|
||||
<h5 class="text-muted">Only organization administrators can view this page.</h5>
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
{
|
||||
public class ServerLogsModel : PageModel
|
||||
{
|
||||
public void OnGet()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,15 +3,16 @@
|
||||
var hasExternalLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()).Any();
|
||||
}
|
||||
|
||||
<ul class="nav nav-pills flex-column">
|
||||
<li class="nav-item"><a class="nav-link @ManageNavPages.IndexNavClass(ViewContext)" id="profile" asp-page="./Index">Profile</a></li>
|
||||
<li class="nav-item"><a class="nav-link @ManageNavPages.ChangePasswordNavClass(ViewContext)" id="change-password" asp-page="./ChangePassword">Password</a></li>
|
||||
<li class="nav-item"><a id="options" class="nav-link @ManageNavPages.OptionsNavClass(ViewContext)" asp-page="./Options">Options</a></li>
|
||||
<li class="nav-item"><a id="options" class="nav-link @ManageNavPages.OrganizationNavClass(ViewContext)" asp-page="./Organization">Organization</a></li>
|
||||
@if (hasExternalLogins)
|
||||
{
|
||||
<li id="external-logins" class="nav-item"><a id="external-login" class="nav-link @ManageNavPages.ExternalLoginsNavClass(ViewContext)" asp-page="./ExternalLogins">External logins</a></li>
|
||||
}
|
||||
<li class="nav-item"><a class="nav-link @ManageNavPages.TwoFactorAuthenticationNavClass(ViewContext)" id="two-factor" asp-page="./TwoFactorAuthentication">Two-factor authentication</a></li>
|
||||
<li class="nav-item"><a class="nav-link @ManageNavPages.PersonalDataNavClass(ViewContext)" id="personal-data" asp-page="./PersonalData">Personal data</a></li>
|
||||
</ul>
|
||||
<ul class="nav nav-pills flex-column">
|
||||
<li class="nav-item"><a class="nav-link @ManageNavPages.IndexNavClass(ViewContext)" id="profile" asp-page="./Index">Profile</a></li>
|
||||
<li class="nav-item"><a class="nav-link @ManageNavPages.ChangePasswordNavClass(ViewContext)" id="change-password" asp-page="./ChangePassword">Password</a></li>
|
||||
<li class="nav-item"><a id="options" class="nav-link @ManageNavPages.OptionsNavClass(ViewContext)" asp-page="./Options">Options</a></li>
|
||||
<li class="nav-item"><a id="options" class="nav-link @ManageNavPages.OrganizationNavClass(ViewContext)" asp-page="./Organization">Organization</a></li>
|
||||
<li class="nav-item"><a id="options" class="nav-link @ManageNavPages.ServerLogsNavClass(ViewContext)" asp-page="./ServerLogs">Server Logs</a></li>
|
||||
@if (hasExternalLogins)
|
||||
{
|
||||
<li id="external-logins" class="nav-item"><a id="external-login" class="nav-link @ManageNavPages.ExternalLoginsNavClass(ViewContext)" asp-page="./ExternalLogins">External logins</a></li>
|
||||
}
|
||||
<li class="nav-item"><a class="nav-link @ManageNavPages.TwoFactorAuthenticationNavClass(ViewContext)" id="two-factor" asp-page="./TwoFactorAuthentication">Two-factor authentication</a></li>
|
||||
<li class="nav-item"><a class="nav-link @ManageNavPages.PersonalDataNavClass(ViewContext)" id="personal-data" asp-page="./PersonalData">Personal data</a></li>
|
||||
</ul>
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
@using Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
@using Remotely.Server.Data;
|
||||
@using Remotely.Server.Services
|
||||
@using Remotely.Shared.Models
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
@page
|
||||
@inject Remotely.Server.Services.ApplicationConfig AppConfig
|
||||
@inject Remotely.Server.Data.DataService DataService
|
||||
@inject Remotely.Server.Services.DataService DataService
|
||||
@model RegisterModel
|
||||
@{
|
||||
ViewData["Title"] = "Register";
|
||||
|
||||
@ -7,7 +7,7 @@ using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Remotely.Server.Data;
|
||||
using Remotely.Server.Services;
|
||||
|
||||
namespace Remotely.Server.Pages
|
||||
{
|
||||
|
||||
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Remotely.Server.Data;
|
||||
using Remotely.Server.Services;
|
||||
using Microsoft.AspNetCore.Diagnostics;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
@ -38,7 +38,7 @@ namespace Remotely.Server.Pages
|
||||
{
|
||||
var logEntry = new Remotely.Shared.Models.EventLog()
|
||||
{
|
||||
EventType = Remotely.Shared.Models.EventTypes.Error,
|
||||
EventType = Remotely.Shared.Models.EventType.Error,
|
||||
Message = error.Message,
|
||||
Source = error.Source,
|
||||
StackTrace = error.StackTrace,
|
||||
|
||||
@ -2,12 +2,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Remotely.Server.Data;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Remotely.Shared.Models;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Remotely.Server.Services;
|
||||
|
||||
namespace Remotely.Server.Pages
|
||||
{
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Remotely.Server.Data;
|
||||
using Remotely.Server.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
@inject Remotely.Server.Services.ApplicationConfig AppConfig
|
||||
@inject Remotely.Server.Data.DataService DataService
|
||||
@inject Remotely.Server.Services.DataService DataService
|
||||
@model IndexModel
|
||||
@{
|
||||
var organizationCount = DataService.GetOrganizationCount();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
@using Microsoft.AspNetCore.Identity
|
||||
@using Remotely.Server
|
||||
@using Remotely.Server.Data
|
||||
@using Remotely.Server.Services
|
||||
@namespace Remotely.Server.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
||||
@ -140,7 +140,7 @@ namespace Remotely.Server.Services
|
||||
{
|
||||
DataService.WriteEvent(new EventLog()
|
||||
{
|
||||
EventType = EventTypes.Info,
|
||||
EventType = EventType.Info,
|
||||
Message = $"File transfer started by {RemotelyUser.UserName}. File transfer IDs: {string.Join(", ", fileIDs)}.",
|
||||
TimeStamp = DateTime.Now,
|
||||
OrganizationID = RemotelyUser.OrganizationID
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Shared.ViewModels;
|
||||
using Remotely.Server.Services;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -9,8 +8,9 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Remotely.Shared.ViewModels.Organization;
|
||||
using Remotely.Server.Data;
|
||||
|
||||
namespace Remotely.Server.Data
|
||||
namespace Remotely.Server.Services
|
||||
{
|
||||
public class DataService
|
||||
{
|
||||
@ -119,7 +119,7 @@ namespace Remotely.Server.Data
|
||||
{
|
||||
WriteEvent(new EventLog()
|
||||
{
|
||||
EventType = EventTypes.Info,
|
||||
EventType = EventType.Info,
|
||||
Message = $"Unable to add device {device.DeviceName} because organization {device.OrganizationID} does not exist.",
|
||||
Source = "DataService.AddOrUpdateDevice"
|
||||
});
|
||||
@ -269,9 +269,20 @@ namespace Remotely.Server.Data
|
||||
|
||||
public IEnumerable<CommandContext> GetAllCommandContexts(string userName)
|
||||
{
|
||||
var orgID = GetUserByName(userName).OrganizationID;
|
||||
var orgID = RemotelyContext.Users
|
||||
.FirstOrDefault(x => x.UserName == userName)
|
||||
?.OrganizationID;
|
||||
|
||||
return RemotelyContext.CommandContexts.Where(x => x.OrganizationID == orgID);
|
||||
}
|
||||
public IEnumerable<EventLog> GetAllEventLogs(string userName)
|
||||
{
|
||||
var orgID = RemotelyContext.Users
|
||||
.FirstOrDefault(x => x.UserName == userName)
|
||||
?.OrganizationID;
|
||||
|
||||
return RemotelyContext.EventLogs.Where(x => x.OrganizationID == orgID);
|
||||
}
|
||||
|
||||
public IEnumerable<Device> GetAllDevicesForUser(string userID)
|
||||
{
|
||||
@ -513,7 +524,7 @@ namespace Remotely.Server.Data
|
||||
{
|
||||
RemotelyContext.EventLogs.Add(new EventLog()
|
||||
{
|
||||
EventType = EventTypes.Error,
|
||||
EventType = EventType.Error,
|
||||
Message = ex.Message,
|
||||
Source = ex.Source,
|
||||
StackTrace = ex.StackTrace,
|
||||
@ -522,13 +533,26 @@ namespace Remotely.Server.Data
|
||||
RemotelyContext.SaveChanges();
|
||||
}
|
||||
|
||||
public void WriteEvent(string message)
|
||||
public void WriteEvent(string message, string organizationId)
|
||||
{
|
||||
RemotelyContext.EventLogs.Add(new EventLog()
|
||||
{
|
||||
EventType = EventTypes.Info,
|
||||
EventType = EventType.Info,
|
||||
Message = message,
|
||||
TimeStamp = DateTime.Now
|
||||
TimeStamp = DateTime.Now,
|
||||
OrganizationID = organizationId
|
||||
});
|
||||
RemotelyContext.SaveChanges();
|
||||
}
|
||||
|
||||
public void WriteEvent(string message, EventType eventType, string organizationId)
|
||||
{
|
||||
RemotelyContext.EventLogs.Add(new EventLog()
|
||||
{
|
||||
EventType = eventType,
|
||||
Message = message,
|
||||
TimeStamp = DateTime.Now,
|
||||
OrganizationID = organizationId
|
||||
});
|
||||
RemotelyContext.SaveChanges();
|
||||
}
|
||||
@ -68,7 +68,7 @@ namespace Remotely.Server.Services
|
||||
{
|
||||
DataService.WriteEvent(new EventLog()
|
||||
{
|
||||
EventType = EventTypes.Info,
|
||||
EventType = EventType.Info,
|
||||
OrganizationID = device.OrganizationID,
|
||||
Message = $"Device connection for {device?.DeviceName} was denied because it is already connected."
|
||||
});
|
||||
|
||||
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace Remotely.Server.Services
|
||||
{
|
||||
public class PascalCase : JsonNamingPolicy
|
||||
public class PascalCasePolicy : JsonNamingPolicy
|
||||
{
|
||||
public override string ConvertName(string name)
|
||||
{
|
||||
@ -150,9 +150,9 @@ namespace Remotely.Server.Services
|
||||
await RCDeviceHub.Clients.Client(ScreenCasterID).SendAsync("ClipboardTransfer", transferText, typeText, Context.ConnectionId);
|
||||
}
|
||||
|
||||
public async Task SendLatencyUpdate(DateTime sentTime)
|
||||
public async Task SendLatencyUpdate(DateTime sentTime, int bytesRecieved)
|
||||
{
|
||||
await RCDeviceHub.Clients.Client(ScreenCasterID).SendAsync("LatencyUpdate", sentTime, Context.ConnectionId);
|
||||
await RCDeviceHub.Clients.Client(ScreenCasterID).SendAsync("LatencyUpdate", sentTime, bytesRecieved, Context.ConnectionId);
|
||||
}
|
||||
|
||||
public async Task SendQualityChange(int qualityLevel)
|
||||
@ -177,24 +177,35 @@ namespace Remotely.Server.Services
|
||||
|
||||
screenCasterID = RCDeviceSocketHub.SessionInfoList.First(x => x.Value.AttendedSessionID == screenCasterID).Value.RCSocketID;
|
||||
}
|
||||
|
||||
|
||||
string orgId = null;
|
||||
|
||||
if (Context?.User?.Identity?.IsAuthenticated == true)
|
||||
{
|
||||
orgId = DataService.GetUserByID(Context.UserIdentifier).OrganizationID;
|
||||
}
|
||||
|
||||
RCDeviceSocketHub.SessionInfoList.TryGetValue(screenCasterID, out var sessionInfo);
|
||||
|
||||
DataService.WriteEvent(new EventLog()
|
||||
{
|
||||
EventType = EventTypes.Info,
|
||||
EventType = EventType.Info,
|
||||
TimeStamp = DateTime.Now,
|
||||
Message = $"Remote control session requested. " +
|
||||
$"Login ID (if logged in): {Context?.User?.Identity?.Name}. " +
|
||||
$"Machine Name: {sessionInfo.MachineName}. " +
|
||||
$"Requester Name (if specified): {requesterName}. " +
|
||||
$"Connection ID: {Context.ConnectionId}. User ID: {Context.UserIdentifier}. " +
|
||||
$"Screen Caster ID: {screenCasterID}. " +
|
||||
$"Mode: {((RemoteControlMode)remoteControlMode).ToString()}. " +
|
||||
$"Login ID (if logged in): {Context?.User?.Identity?.Name}. " +
|
||||
$"Rquester Name (if specified): {requesterName}. " +
|
||||
$"Requester IP Address: " + Context?.GetHttpContext()?.Connection?.RemoteIpAddress?.ToString()
|
||||
$"Requester IP Address: " + Context?.GetHttpContext()?.Connection?.RemoteIpAddress?.ToString(),
|
||||
OrganizationID = orgId
|
||||
});
|
||||
|
||||
ScreenCasterID = screenCasterID;
|
||||
Mode = (RemoteControlMode)remoteControlMode;
|
||||
RequesterName = requesterName;
|
||||
var sessionInfo = RCDeviceSocketHub.SessionInfoList.FirstOrDefault(x => x.Value.RCSocketID == screenCasterID).Value;
|
||||
|
||||
if (Mode == RemoteControlMode.Unattended)
|
||||
{
|
||||
sessionInfo.Mode = RemoteControlMode.Unattended;
|
||||
|
||||
@ -132,7 +132,7 @@ namespace Remotely.Server
|
||||
services.AddMvc()
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0).AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.PropertyNamingPolicy = new PascalCase();
|
||||
options.JsonSerializerOptions.PropertyNamingPolicy = new PascalCasePolicy();
|
||||
});
|
||||
|
||||
services.AddSignalR(options =>
|
||||
@ -142,7 +142,7 @@ namespace Remotely.Server
|
||||
})
|
||||
.AddJsonProtocol(options =>
|
||||
{
|
||||
options.PayloadSerializerOptions.PropertyNamingPolicy = new PascalCase();
|
||||
options.PayloadSerializerOptions.PropertyNamingPolicy = new PascalCasePolicy();
|
||||
})
|
||||
.AddMessagePackProtocol();
|
||||
|
||||
|
||||
@ -36,8 +36,8 @@ export class RCBrowserSockets {
|
||||
SendScreenCastRequestToDevice() {
|
||||
this.Connection.invoke("SendScreenCastRequestToDevice", RemoteControl.ClientID, RemoteControl.RequesterName, RemoteControl.Mode);
|
||||
}
|
||||
SendLatencyUpdate(sentTime) {
|
||||
this.Connection.invoke("SendLatencyUpdate", sentTime);
|
||||
SendLatencyUpdate(sentTime, bytesReceived) {
|
||||
this.Connection.invoke("SendLatencyUpdate", sentTime, bytesReceived);
|
||||
}
|
||||
SendSelectScreen(index) {
|
||||
this.Connection.invoke("SelectScreen", index);
|
||||
@ -128,7 +128,7 @@ export class RCBrowserSockets {
|
||||
UI.Screen2DContext.clearRect(0, 0, width, height);
|
||||
});
|
||||
hubConnection.on("ScreenCapture", (buffer, left, top, width, height, captureTime) => {
|
||||
this.SendLatencyUpdate(captureTime);
|
||||
this.SendLatencyUpdate(captureTime, buffer.byteLength);
|
||||
var url = window.URL.createObjectURL(new Blob([buffer]));
|
||||
var img = document.createElement("img");
|
||||
img.onload = () => {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -49,8 +49,8 @@ export class RCBrowserSockets {
|
||||
SendScreenCastRequestToDevice() {
|
||||
this.Connection.invoke("SendScreenCastRequestToDevice", RemoteControl.ClientID, RemoteControl.RequesterName, RemoteControl.Mode);
|
||||
}
|
||||
SendLatencyUpdate(sentTime: Date) {
|
||||
this.Connection.invoke("SendLatencyUpdate", sentTime);
|
||||
SendLatencyUpdate(sentTime: Date, bytesReceived: number) {
|
||||
this.Connection.invoke("SendLatencyUpdate", sentTime, bytesReceived);
|
||||
}
|
||||
SendSelectScreen(index: number) {
|
||||
this.Connection.invoke("SelectScreen", index);
|
||||
@ -142,7 +142,7 @@ export class RCBrowserSockets {
|
||||
});
|
||||
hubConnection.on("ScreenCapture", (buffer: Uint8Array, left:number, top:number, width:number, height:number, captureTime: Date) => {
|
||||
|
||||
this.SendLatencyUpdate(captureTime);
|
||||
this.SendLatencyUpdate(captureTime, buffer.byteLength);
|
||||
|
||||
var url = window.URL.createObjectURL(new Blob([buffer]));
|
||||
var img = document.createElement("img");
|
||||
|
||||
@ -10,7 +10,7 @@ namespace Remotely.Shared.Models
|
||||
{
|
||||
[Key]
|
||||
public string ID { get; set; } = Guid.NewGuid().ToString();
|
||||
public EventTypes EventType { get; set; }
|
||||
public EventType EventType { get; set; }
|
||||
public string Message { get; set; }
|
||||
public string Source { get; set; }
|
||||
public string StackTrace { get; set; }
|
||||
@ -19,10 +19,11 @@ namespace Remotely.Shared.Models
|
||||
[JsonIgnore]
|
||||
public virtual Organization Organization { get; set; }
|
||||
}
|
||||
public enum EventTypes
|
||||
public enum EventType
|
||||
{
|
||||
Info = 0,
|
||||
Error = 1,
|
||||
Debug = 2
|
||||
Debug = 2,
|
||||
Warning = 3
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user