mirror of
https://github.com/immense/Remotely.git
synced 2025-10-26 11:27:15 +00:00
Add Linux session indicator. Add NotifyUser to app settings. Add ShutdownService.
This commit is contained in:
parent
b94435d55e
commit
75db74c85e
12
Desktop.Core/Interfaces/IShutdownService.cs
Normal file
12
Desktop.Core/Interfaces/IShutdownService.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Remotely.Desktop.Core.Interfaces
|
||||
{
|
||||
public interface IShutdownService
|
||||
{
|
||||
Task Shutdown();
|
||||
}
|
||||
}
|
||||
@ -103,8 +103,11 @@ namespace Remotely.Desktop.Core.Models
|
||||
public void Dispose()
|
||||
{
|
||||
DisconnectRequested = true;
|
||||
RtcSession?.Dispose();
|
||||
Capturer?.Dispose();
|
||||
Disposer.TryDisposeAll(new IDisposable[]
|
||||
{
|
||||
RtcSession,
|
||||
Capturer
|
||||
});
|
||||
}
|
||||
|
||||
public async Task InitializeWebRtc()
|
||||
|
||||
@ -272,11 +272,16 @@ namespace Remotely.Desktop.Core.Services
|
||||
await DisconnectAllViewers();
|
||||
});
|
||||
|
||||
Connection.On("GetScreenCast", (string viewerID, string requesterName) =>
|
||||
Connection.On("GetScreenCast", (string viewerID, string requesterName, bool notifyUser) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
ScreenCaster.BeginScreenCasting(new ScreenCastRequest() { ViewerID = viewerID, RequesterName = requesterName });
|
||||
ScreenCaster.BeginScreenCasting(new ScreenCastRequest()
|
||||
{
|
||||
NotifyUser = notifyUser,
|
||||
ViewerID = viewerID,
|
||||
RequesterName = requesterName
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -292,9 +297,14 @@ namespace Remotely.Desktop.Core.Services
|
||||
}
|
||||
});
|
||||
|
||||
Connection.On("RequestScreenCast", (string viewerID, string requesterName) =>
|
||||
Connection.On("RequestScreenCast", (string viewerID, string requesterName, bool notifyUser) =>
|
||||
{
|
||||
conductor.InvokeScreenCastRequested(new ScreenCastRequest() { ViewerID = viewerID, RequesterName = requesterName });
|
||||
conductor.InvokeScreenCastRequested(new ScreenCastRequest()
|
||||
{
|
||||
NotifyUser = notifyUser,
|
||||
ViewerID = viewerID,
|
||||
RequesterName = requesterName
|
||||
});
|
||||
});
|
||||
|
||||
Connection.On("KeyDown", (string key, string viewerID) =>
|
||||
|
||||
@ -22,16 +22,19 @@ namespace Remotely.Desktop.Core.Services
|
||||
{
|
||||
public ScreenCaster(Conductor conductor,
|
||||
ICursorIconWatcher cursorIconWatcher,
|
||||
ISessionIndicator sessionIndicator)
|
||||
ISessionIndicator sessionIndicator,
|
||||
IShutdownService shutdownService)
|
||||
{
|
||||
Conductor = conductor;
|
||||
CursorIconWatcher = cursorIconWatcher;
|
||||
SessionIndicator = sessionIndicator;
|
||||
ShutdownService = shutdownService;
|
||||
}
|
||||
|
||||
private Conductor Conductor { get; }
|
||||
private ICursorIconWatcher CursorIconWatcher { get; }
|
||||
private ISessionIndicator SessionIndicator { get; }
|
||||
private IShutdownService ShutdownService { get; }
|
||||
|
||||
public async Task BeginScreenCasting(ScreenCastRequest screenCastRequest)
|
||||
{
|
||||
@ -56,7 +59,8 @@ namespace Remotely.Desktop.Core.Services
|
||||
{
|
||||
Conductor.InvokeViewerAdded(viewer);
|
||||
}
|
||||
else
|
||||
|
||||
if (mode == AppMode.Unattended && screenCastRequest.NotifyUser)
|
||||
{
|
||||
SessionIndicator.Show();
|
||||
}
|
||||
@ -174,8 +178,7 @@ namespace Remotely.Desktop.Core.Services
|
||||
// Close if no one is viewing.
|
||||
if (Conductor.Viewers.Count == 0 && mode == AppMode.Unattended)
|
||||
{
|
||||
Logger.Debug($"Exiting process ID {Process.GetCurrentProcess().Id}.");
|
||||
Environment.Exit(0);
|
||||
await ShutdownService.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using MessagePack;
|
||||
using Microsoft.MixedReality.WebRTC;
|
||||
using Remotely.Desktop.Core.Models;
|
||||
using Remotely.Shared.Helpers;
|
||||
using Remotely.Shared.Models;
|
||||
using Remotely.Shared.Models.RtcDtos;
|
||||
using Remotely.Shared.Utilities;
|
||||
@ -57,18 +58,17 @@ namespace Remotely.Desktop.Core.Services
|
||||
{
|
||||
try
|
||||
{
|
||||
Transceiver?.LocalVideoTrack?.Dispose();
|
||||
VideoSource?.Dispose();
|
||||
try
|
||||
{
|
||||
// Unable to exit process until DataChannel is removed/disposed,
|
||||
// and this throws internally (at least in 2.0 version).
|
||||
PeerSession?.RemoveDataChannel(CaptureChannel);
|
||||
}
|
||||
catch { }
|
||||
PeerSession?.Dispose();
|
||||
// Unable to exit process until DataChannel is removed/disposed,
|
||||
// and this throws internally (at least in 2.0 version).
|
||||
PeerSession?.RemoveDataChannel(CaptureChannel);
|
||||
}
|
||||
catch { }
|
||||
Disposer.TryDisposeAll(new IDisposable[]
|
||||
{
|
||||
PeerSession,
|
||||
Transceiver?.LocalVideoTrack,
|
||||
VideoSource
|
||||
});
|
||||
}
|
||||
|
||||
public async Task Init(IceServerModel[] iceServers)
|
||||
|
||||
@ -9,7 +9,7 @@ namespace Remotely.Desktop.Linux.Controls
|
||||
{
|
||||
public HostNamePrompt()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
|
||||
@ -34,7 +34,7 @@ namespace Remotely.Desktop.Linux.Controls
|
||||
}
|
||||
public MessageBox()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
|
||||
@ -109,6 +109,7 @@ namespace Remotely.Desktop.Linux
|
||||
serviceCollection.AddScoped<IWebRtcSessionFactory, WebRtcSessionFactory>();
|
||||
serviceCollection.AddSingleton<ICursorIconWatcher, CursorIconWatcherLinux>();
|
||||
serviceCollection.AddSingleton<ISessionIndicator, SessionIndicatorLinux>();
|
||||
serviceCollection.AddSingleton<IShutdownService, ShutdownServiceLinux>();
|
||||
|
||||
ServiceContainer.Instance = serviceCollection.BuildServiceProvider();
|
||||
}
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using Remotely.Desktop.Core.Interfaces;
|
||||
using Avalonia.Threading;
|
||||
using Remotely.Desktop.Core.Interfaces;
|
||||
using Remotely.Desktop.Linux.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
@ -9,7 +11,11 @@ namespace Remotely.Desktop.Linux.Services
|
||||
{
|
||||
public void Show()
|
||||
{
|
||||
// TODO.
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
var indicatorWindow = new SessionIndicatorWindow();
|
||||
indicatorWindow.Show();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
Desktop.Linux/Services/ShutdownServiceLinux.cs
Normal file
24
Desktop.Linux/Services/ShutdownServiceLinux.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Remotely.Desktop.Core;
|
||||
using Remotely.Desktop.Core.Interfaces;
|
||||
using Remotely.Desktop.Core.Services;
|
||||
using Remotely.Shared.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Remotely.Desktop.Linux.Services
|
||||
{
|
||||
public class ShutdownServiceLinux : IShutdownService
|
||||
{
|
||||
public async Task Shutdown()
|
||||
{
|
||||
Logger.Debug($"Exiting process ID {Process.GetCurrentProcess().Id}.");
|
||||
var casterSocket = ServiceContainer.Instance.GetRequiredService<CasterSocket>();
|
||||
await casterSocket.DisconnectAllViewers();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -15,7 +15,7 @@ namespace Remotely.Desktop.Linux.Views
|
||||
{
|
||||
public ChatWindow()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
@ -40,7 +40,7 @@ namespace Remotely.Desktop.Linux.Views
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
this.Closed += ChatWindow_Closed;
|
||||
Closed += ChatWindow_Closed;
|
||||
|
||||
this.FindControl<Border>("TitleBanner").PointerPressed += TitleBanner_PointerPressed;
|
||||
|
||||
@ -63,7 +63,7 @@ namespace Remotely.Desktop.Linux.Views
|
||||
{
|
||||
if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == Avalonia.Input.PointerUpdateKind.LeftButtonPressed)
|
||||
{
|
||||
this.BeginMoveDrag(e);
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,11 +7,10 @@ namespace Remotely.Desktop.Linux.Views
|
||||
{
|
||||
public class MainWindow : Window
|
||||
{
|
||||
public static MainWindow Current { get; set; }
|
||||
public MainWindow()
|
||||
{
|
||||
Current = this;
|
||||
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
#if DEBUG
|
||||
@ -19,26 +18,27 @@ namespace Remotely.Desktop.Linux.Views
|
||||
#endif
|
||||
}
|
||||
|
||||
private void TitleBanner_PointerPressed(object sender, Avalonia.Input.PointerPressedEventArgs e)
|
||||
{
|
||||
if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == Avalonia.Input.PointerUpdateKind.LeftButtonPressed)
|
||||
{
|
||||
this.BeginMoveDrag(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static MainWindow Current { get; set; }
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
this.FindControl<Border>("TitleBanner").PointerPressed += TitleBanner_PointerPressed;
|
||||
|
||||
this.Opened += MainWindow_Opened;
|
||||
Opened += MainWindow_Opened;
|
||||
}
|
||||
|
||||
private async void MainWindow_Opened(object sender, System.EventArgs e)
|
||||
{
|
||||
await (this.DataContext as MainWindowViewModel).Init();
|
||||
await (DataContext as MainWindowViewModel).Init();
|
||||
}
|
||||
|
||||
private void TitleBanner_PointerPressed(object sender, Avalonia.Input.PointerPressedEventArgs e)
|
||||
{
|
||||
if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == Avalonia.Input.PointerUpdateKind.LeftButtonPressed)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
23
Desktop.Linux/Views/SessionIndicatorWindow.axaml
Normal file
23
Desktop.Linux/Views/SessionIndicatorWindow.axaml
Normal file
@ -0,0 +1,23 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
Width="300"
|
||||
Height="100"
|
||||
x:Class="Remotely.Desktop.Linux.Views.SessionIndicatorWindow"
|
||||
Background="#2b2726"
|
||||
Title="Remotely Desktop"
|
||||
Icon="/Assets/favicon.ico"
|
||||
WindowStartupLocation="Manual"
|
||||
SizeToContent="WidthAndHeight">
|
||||
|
||||
<StackPanel Margin="15 10 40 15">
|
||||
<TextBlock Classes="SectionHeader" Foreground="White">
|
||||
Remote Control Started
|
||||
</TextBlock>
|
||||
<TextBlock Foreground="LightGray">
|
||||
A remote control session has started.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Window>
|
||||
58
Desktop.Linux/Views/SessionIndicatorWindow.axaml.cs
Normal file
58
Desktop.Linux/Views/SessionIndicatorWindow.axaml.cs
Normal file
@ -0,0 +1,58 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Remotely.Desktop.Core;
|
||||
using Remotely.Desktop.Core.Interfaces;
|
||||
using Remotely.Desktop.Linux.Controls;
|
||||
using System;
|
||||
|
||||
namespace Remotely.Desktop.Linux.Views
|
||||
{
|
||||
public class SessionIndicatorWindow : Window
|
||||
{
|
||||
public SessionIndicatorWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
#if DEBUG
|
||||
this.AttachDevTools();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
Closing += SessionIndicatorWindow_Closing;
|
||||
PointerPressed += SessionIndicatorWindow_PointerPressed;
|
||||
Opened += SessionIndicatorWindow_Opened;
|
||||
}
|
||||
|
||||
private void SessionIndicatorWindow_Opened(object sender, EventArgs e)
|
||||
{
|
||||
var left = Screens.Primary.WorkingArea.Width - Width;
|
||||
var top = Screens.Primary.WorkingArea.Width - Width;
|
||||
|
||||
Position = new PixelPoint((int)left, (int)top);
|
||||
}
|
||||
|
||||
private void SessionIndicatorWindow_PointerPressed(object sender, Avalonia.Input.PointerPressedEventArgs e)
|
||||
{
|
||||
if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == Avalonia.Input.PointerUpdateKind.LeftButtonPressed)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
}
|
||||
|
||||
private async void SessionIndicatorWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
e.Cancel = true;
|
||||
var result = await MessageBox.Show("Stop the remote control session?", "Stop Session", MessageBoxType.YesNo);
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
var shutdownService = ServiceContainer.Instance.GetRequiredService<IShutdownService>();
|
||||
await shutdownService.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
using SharpDX.Direct3D11;
|
||||
using Remotely.Shared.Helpers;
|
||||
using SharpDX.Direct3D11;
|
||||
using SharpDX.DXGI;
|
||||
using System;
|
||||
|
||||
@ -24,10 +25,13 @@ namespace Remotely.Desktop.Win.Models
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Adapter?.Dispose();
|
||||
Device?.Dispose();
|
||||
OutputDuplication?.Dispose();
|
||||
Texture2D?.Dispose();
|
||||
Disposer.TryDisposeAll(new IDisposable[]
|
||||
{
|
||||
Adapter,
|
||||
Device,
|
||||
OutputDuplication,
|
||||
Texture2D
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,6 +98,7 @@ namespace Remotely.Desktop.Win
|
||||
serviceCollection.AddScoped<IWebRtcSessionFactory, WebRtcSessionFactory>();
|
||||
serviceCollection.AddScoped<IFileTransferService, FileTransferService>();
|
||||
serviceCollection.AddSingleton<ISessionIndicator, SessionIndicatorWin>();
|
||||
serviceCollection.AddSingleton<IShutdownService, ShutdownServiceWin>();
|
||||
|
||||
BackgroundForm = new Form()
|
||||
{
|
||||
|
||||
@ -149,7 +149,11 @@ namespace Remotely.Desktop.Win.Services
|
||||
{
|
||||
foreach (var screen in directxScreens.Values)
|
||||
{
|
||||
screen.Dispose();
|
||||
try
|
||||
{
|
||||
screen.Dispose();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
directxScreens.Clear();
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ namespace Remotely.Desktop.Win.Services
|
||||
return;
|
||||
}
|
||||
|
||||
BackgroundForm.Invoke(new Action(()=>
|
||||
BackgroundForm.Invoke(new Action(() =>
|
||||
{
|
||||
container = new Container();
|
||||
contextMenuStrip = new ContextMenuStrip(container);
|
||||
|
||||
25
Desktop.Win/Services/ShutdownServiceWin.cs
Normal file
25
Desktop.Win/Services/ShutdownServiceWin.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Remotely.Desktop.Core;
|
||||
using Remotely.Desktop.Core.Interfaces;
|
||||
using Remotely.Desktop.Core.Services;
|
||||
using Remotely.Shared.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Remotely.Desktop.Win.Services
|
||||
{
|
||||
public class ShutdownServiceWin : IShutdownService
|
||||
{
|
||||
public async Task Shutdown()
|
||||
{
|
||||
Logger.Debug($"Exiting process ID {Process.GetCurrentProcess().Id}.");
|
||||
var casterSocket = ServiceContainer.Instance.GetRequiredService<CasterSocket>();
|
||||
await casterSocket.DisconnectAllViewers();
|
||||
System.Windows.Forms.Application.Exit();
|
||||
App.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
15
README.md
15
README.md
@ -99,21 +99,24 @@ The following settings are available in appsettings.json.
|
||||
|
||||
Note: To retain your settings between upgrades, copy your settings to appsettings.Production.json, which will supersede the original.
|
||||
|
||||
* DefaultPrompt: The default prompt string you'll see for each line on the console.
|
||||
* AllowApiLogin: Whether to allow logging in via the API controller. API access tokens are recommended over this approach.
|
||||
* DataRetentionInDays: How long event logs and remote command logs will be kept.
|
||||
* DBProvider: Determines which of the three connection strings (at the top) will be used. The appropriate DB provider for the database type is automatically loaded in code.
|
||||
* DefaultPrompt: The default prompt string you'll see for each line on the console.
|
||||
* EnableWindowsEventLog: Whether to also add server log entries to the Windows Event Log.
|
||||
* IceServers: The ICE (STUN/TURN) servers to use for WebRTC.
|
||||
* KnownProxies: If your Nginx server is on a different machine and is forwarding requests to the Remotely server, you will need to add the IP of the Nginx server to this array.
|
||||
* MaxOrganizationCount: By default, one organization can exist on the server, which is created automatically when the first account is registered. Afterward, self-registration will be disabled.
|
||||
* Set this to -1 or increase it to a specific number to allow multi-tenancy.
|
||||
* RedirectToHttps: Whether ASP.NET Core will redirect all traffic from HTTP to HTTPS. This is independent of Nginx and IIS configurations that do the same.
|
||||
* UseHsts: Whether ASP.NET Core will use HTTP Strict Transport Security.
|
||||
* DataRetentionInDays: How long event logs and remote command logs will be kept.
|
||||
* RemoteControlNotifyUsers: Whether to show a notification to the end user when an unattended remote control session starts.
|
||||
* RemoteControlSessionLimit: How many concurrent remote control sessions are allowed per organization.
|
||||
* RemoteControlRequiresAuthentication: Whether the remote control page requires authentication to establish a connection.
|
||||
* Require2FA: Require users to set up 2FA before they can use the main app.
|
||||
* AllowApiLogin: Whether to allow logging in via the API controller. API access tokens are recommended over this approach.
|
||||
* TrustedCorsOrigins: For cross-origin API requests via JavaScript. The websites listed in this array with be allowed to make requests to the API. This does not grant authentication, which is still required on most endpoints.
|
||||
* KnownProxies: If your Nginx server is on a different machine and is forwarding requests to the Remotely server, you will need to add the IP of the Nginx server to this array.
|
||||
* Smpt*: SMTP settings for auto-generated system emails (such as registration and password reset).
|
||||
* Theme: The color theme to use for the site. Values are "Light" or "Dark". This can also be configured per-user in Account - Options.
|
||||
* TrustedCorsOrigins: For cross-origin API requests via JavaScript. The websites listed in this array with be allowed to make requests to the API. This does not grant authentication, which is still required on most endpoints.
|
||||
* UseHsts: Whether ASP.NET Core will use HTTP Strict Transport Security.
|
||||
* UseWebRtc: Attempt to create a peer-to-peer connection via WebRTC for screen sharing.
|
||||
* Only works on Windows agents.
|
||||
|
||||
|
||||
@ -92,6 +92,13 @@
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.RedirectToHttps" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.RemoteControlNotifyUser"></label>
|
||||
<br />
|
||||
<input type="checkbox" asp-for="AppSettingsInput.RemoteControlNotifyUser" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.RemoteControlNotifyUser" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.RemoteControlRequiresAuthentication"></label>
|
||||
<br />
|
||||
|
||||
@ -169,6 +169,9 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
[Display(Name = "Redirect To HTTPS")]
|
||||
public bool RedirectToHttps { get; set; }
|
||||
|
||||
[Display(Name = "Remote Control Notify User")]
|
||||
public bool RemoteControlNotifyUser { get; set; }
|
||||
|
||||
[Display(Name = "Remote Control Requires Authentication")]
|
||||
public bool RemoteControlRequiresAuthentication { get; set; }
|
||||
|
||||
|
||||
@ -268,7 +268,7 @@ namespace Remotely.Server.Hubs
|
||||
(Context.User.Identity.IsAuthenticated &&
|
||||
DataService.DoesUserHaveAccessToDevice(deviceID, Context.UserIdentifier)))
|
||||
{
|
||||
return CasterHubContext.Clients.Client(screenCasterID).SendAsync("GetScreenCast", Context.ConnectionId, requesterName);
|
||||
return CasterHubContext.Clients.Client(screenCasterID).SendAsync("GetScreenCast", Context.ConnectionId, requesterName, AppConfig.RemoteControlNotifyUser);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -279,7 +279,7 @@ namespace Remotely.Server.Hubs
|
||||
{
|
||||
SessionInfo.Mode = RemoteControlMode.Normal;
|
||||
_ = Clients.Caller.SendAsync("RequestingScreenCast");
|
||||
return CasterHubContext.Clients.Client(screenCasterID).SendAsync("RequestScreenCast", Context.ConnectionId, requesterName);
|
||||
return CasterHubContext.Clients.Client(screenCasterID).SendAsync("RequestScreenCast", Context.ConnectionId, requesterName, AppConfig.RemoteControlNotifyUser);
|
||||
}
|
||||
}
|
||||
public Task SendSetKeyStatesUp()
|
||||
|
||||
@ -26,6 +26,7 @@ namespace Remotely.Server.Services
|
||||
public int MaxConcurrentUpdates => int.Parse(Config["ApplicationOptions:MaxConcurrentUpdates"] ?? "10");
|
||||
public int MaxOrganizationCount => int.Parse(Config["ApplicationOptions:MaxOrganizationCount"] ?? "1");
|
||||
public bool RedirectToHttps => bool.Parse(Config["ApplicationOptions:RedirectToHttps"] ?? "false");
|
||||
public bool RemoteControlNotifyUser => bool.Parse(Config["ApplicationOptions:RemoteControlNotifyUser"] ?? "true");
|
||||
public bool RemoteControlRequiresAuthentication => bool.Parse(Config["ApplicationOptions:RemoteControlRequiresAuthentication"] ?? "true");
|
||||
public double RemoteControlSessionLimit => double.Parse(Config["ApplicationOptions:RemoteControlSessionLimit"] ?? "3");
|
||||
public bool Require2FA => bool.Parse(Config["ApplicationOptions:Require2FA"] ?? "false");
|
||||
|
||||
@ -81,8 +81,6 @@ namespace Remotely.Server
|
||||
.AddDefaultUI()
|
||||
.AddDefaultTokenProviders();
|
||||
|
||||
var remoteControlAuthentication = Configuration.GetSection("ApplicationOptions:RemoteControlRequiresAuthentication").Get<bool>();
|
||||
|
||||
services.ConfigureApplicationCookie(cookieOptions =>
|
||||
{
|
||||
cookieOptions.Cookie.SameSite = SameSiteMode.None;
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
"MaxConcurrentUpdates": 10,
|
||||
"MaxOrganizationCount": 1,
|
||||
"RedirectToHttps": false,
|
||||
"RemoteControlNotifyUser": true,
|
||||
"RemoteControlSessionLimit": 3,
|
||||
"RemoteControlRequiresAuthentication": true,
|
||||
"Require2FA": false,
|
||||
|
||||
26
Shared/Helpers/Disposer.cs
Normal file
26
Shared/Helpers/Disposer.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Remotely.Shared.Helpers
|
||||
{
|
||||
public static class Disposer
|
||||
{
|
||||
public static void TryDisposeAll(IDisposable[] disposables)
|
||||
{
|
||||
if (disposables is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var disposable in disposables)
|
||||
{
|
||||
try
|
||||
{
|
||||
disposable?.Dispose();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,8 @@
|
||||
{
|
||||
public class ScreenCastRequest
|
||||
{
|
||||
public string ViewerID { get; set; }
|
||||
public bool NotifyUser { get; set; }
|
||||
public string RequesterName { get; set; }
|
||||
public string ViewerID { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user