mirror of
https://github.com/immense/Remotely.git
synced 2025-10-26 11:27:15 +00:00
Moved code from Razor components to code-behind to fix Identity UI scaffolding.
This commit is contained in:
parent
57b86763a4
commit
1a033fb0e7
@ -24,18 +24,18 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="7.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.3.4" />
|
||||
<PackageReference Include="Microsoft.WSMan.Management" Version="7.3.4" />
|
||||
<PackageReference Include="Microsoft.WSMan.Runtime" Version="7.3.4" />
|
||||
<PackageReference Include="System.Management.Automation" Version="7.3.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.PowerShell.SDK" Version="7.3.6" />
|
||||
<PackageReference Include="Microsoft.WSMan.Management" Version="7.3.6" />
|
||||
<PackageReference Include="Microsoft.WSMan.Runtime" Version="7.3.6" />
|
||||
<PackageReference Include="System.Management.Automation" Version="7.3.6" />
|
||||
<PackageReference Include="System.ServiceProcess.ServiceController" Version="7.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@ -1,49 +1,123 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
|
||||
namespace Remotely.Server.Areas.Identity.Pages.Account.Manage;
|
||||
|
||||
public static class ManageNavPages
|
||||
namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
{
|
||||
public static string Index => "Index";
|
||||
|
||||
public static string Email => "Email";
|
||||
|
||||
public static string ChangePassword => "ChangePassword";
|
||||
|
||||
public static string DownloadPersonalData => "DownloadPersonalData";
|
||||
|
||||
public static string DeletePersonalData => "DeletePersonalData";
|
||||
|
||||
public static string ExternalLogins => "ExternalLogins";
|
||||
|
||||
public static string PersonalData => "PersonalData";
|
||||
|
||||
public static string TwoFactorAuthentication => "TwoFactorAuthentication";
|
||||
|
||||
public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index);
|
||||
|
||||
public static string EmailNavClass(ViewContext viewContext) => PageNavClass(viewContext, Email);
|
||||
|
||||
public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword);
|
||||
|
||||
public static string DownloadPersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DownloadPersonalData);
|
||||
|
||||
public static string DeletePersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DeletePersonalData);
|
||||
|
||||
public static string ExternalLoginsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ExternalLogins);
|
||||
|
||||
public static string PersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, PersonalData);
|
||||
|
||||
public static string TwoFactorAuthenticationNavClass(ViewContext viewContext) => PageNavClass(viewContext, TwoFactorAuthentication);
|
||||
|
||||
private static string PageNavClass(ViewContext viewContext, string page)
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static class ManageNavPages
|
||||
{
|
||||
var activePage = viewContext.ViewData["ActivePage"] as string
|
||||
?? System.IO.Path.GetFileNameWithoutExtension(viewContext.ActionDescriptor.DisplayName);
|
||||
return string.Equals(activePage, page, StringComparison.OrdinalIgnoreCase) ? "active" : "";
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string Index => "Index";
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string Email => "Email";
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string ChangePassword => "ChangePassword";
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string DownloadPersonalData => "DownloadPersonalData";
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string DeletePersonalData => "DeletePersonalData";
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string ExternalLogins => "ExternalLogins";
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string PersonalData => "PersonalData";
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string TwoFactorAuthentication => "TwoFactorAuthentication";
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index);
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string EmailNavClass(ViewContext viewContext) => PageNavClass(viewContext, Email);
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword);
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string DownloadPersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DownloadPersonalData);
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string DeletePersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, DeletePersonalData);
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string ExternalLoginsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ExternalLogins);
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string PersonalDataNavClass(ViewContext viewContext) => PageNavClass(viewContext, PersonalData);
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string TwoFactorAuthenticationNavClass(ViewContext viewContext) => PageNavClass(viewContext, TwoFactorAuthentication);
|
||||
|
||||
/// <summary>
|
||||
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
|
||||
/// directly from your code. This API may change or be removed in future releases.
|
||||
/// </summary>
|
||||
public static string PageNavClass(ViewContext viewContext, string page)
|
||||
{
|
||||
var activePage = viewContext.ViewData["ActivePage"] as string
|
||||
?? System.IO.Path.GetFileNameWithoutExtension(viewContext.ActionDescriptor.DisplayName);
|
||||
return string.Equals(activePage, page, StringComparison.OrdinalIgnoreCase) ? "active" : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
18
Server/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml
Normal file
18
Server/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml
Normal file
@ -0,0 +1,18 @@
|
||||
<environment include="Development">
|
||||
<script src="~/Identity/lib/jquery-validation/dist/jquery.validate.js"></script>
|
||||
<script src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
|
||||
</environment>
|
||||
<environment exclude="Development">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
|
||||
asp-fallback-src="~/Identity/lib/jquery-validation/dist/jquery.validate.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-rZfj/ogBloos6wzLGpPkkOr/gpkBNLZ6b6yLy4o+ok+t/SAKlL5mvXLr0OXNi1Hp">
|
||||
</script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-src="~/Identity/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
|
||||
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
|
||||
crossorigin="anonymous"
|
||||
integrity="sha384-R3vNCHsZ+A2Lo3d5A6XNP7fdQkeswQWTIPfiYwSpEP3YV079R+93YzTeZRah7f/F">
|
||||
</script>
|
||||
</environment>
|
||||
@ -1,7 +1,5 @@
|
||||
@attribute [Authorize]
|
||||
@inherits AuthComponentBase
|
||||
@inject IDataService DataService
|
||||
@inject IToastService ToastService
|
||||
@inherits AuthComponentBase
|
||||
|
||||
<h5 class="text-info">
|
||||
Editing @EditUser?.UserName
|
||||
@ -10,55 +8,12 @@
|
||||
@foreach (var group in DeviceGroups ?? Array.Empty<DeviceGroup>())
|
||||
{
|
||||
<div @key="group.ID">
|
||||
<input id="@group.ID" type="checkbox" class="align-middle mr-2" checked="@(DoesGroupContainUser(group))" @onchange="ev => GroupCheckChanged(ev, group)" />
|
||||
<input
|
||||
id="@group.ID"
|
||||
type="checkbox"
|
||||
class="align-middle mr-2"
|
||||
checked="@(DoesGroupContainUser(group))"
|
||||
@onchange="ev => GroupCheckChanged(ev, group)" />
|
||||
<label class="align-middle mb-0" for="@group.ID">@group.Name</label>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@code {
|
||||
public static string EditUserPropName => nameof(EditUser);
|
||||
public static string DeviceGroupsPropName => nameof(DeviceGroups);
|
||||
|
||||
[Parameter]
|
||||
public required RemotelyUser EditUser { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public required DeviceGroup[] DeviceGroups { get; set; }
|
||||
|
||||
|
||||
private bool DoesGroupContainUser(DeviceGroup group)
|
||||
{
|
||||
return group.Users.Any(x => x.Id == EditUser.Id);
|
||||
}
|
||||
|
||||
private async Task GroupCheckChanged(ChangeEventArgs args, DeviceGroup group)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(EditUser.UserName) &&
|
||||
args.Value is bool boolValue &&
|
||||
boolValue)
|
||||
{
|
||||
if (!DataService.AddUserToDeviceGroup(EditUser.OrganizationID, group.ID, EditUser.UserName, out var result))
|
||||
{
|
||||
ToastService.ShowToast(result, classString: "bg-warning");
|
||||
}
|
||||
else
|
||||
{
|
||||
ToastService.ShowToast("User added to group.");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await DataService.RemoveUserFromDeviceGroup(EditUser.OrganizationID, group.ID, EditUser.Id);
|
||||
if (!result)
|
||||
{
|
||||
ToastService.ShowToast("Failed to remove from group.", classString: "bg-warning");
|
||||
}
|
||||
else
|
||||
{
|
||||
ToastService.ShowToast("Removed user from group.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
63
Server/Components/ModalContents/EditDeviceGroup.razor.cs
Normal file
63
Server/Components/ModalContents/EditDeviceGroup.razor.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Remotely.Server.Services;
|
||||
using Remotely.Shared.Entities;
|
||||
using Remotely.Shared.Models;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Remotely.Server.Components.ModalContents;
|
||||
|
||||
[Authorize]
|
||||
public partial class EditDeviceGroup : AuthComponentBase
|
||||
{
|
||||
public static string DeviceGroupsPropName => nameof(DeviceGroups);
|
||||
public static string EditUserPropName => nameof(EditUser);
|
||||
[Parameter]
|
||||
public required DeviceGroup[] DeviceGroups { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public required RemotelyUser EditUser { get; set; }
|
||||
|
||||
[Inject]
|
||||
private IDataService DataService { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IToastService ToastService { get; init; } = null!;
|
||||
|
||||
|
||||
private bool DoesGroupContainUser(DeviceGroup group)
|
||||
{
|
||||
return group.Users.Any(x => x.Id == EditUser.Id);
|
||||
}
|
||||
|
||||
private async Task GroupCheckChanged(ChangeEventArgs args, DeviceGroup group)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(EditUser.UserName) &&
|
||||
args.Value is bool boolValue &&
|
||||
boolValue)
|
||||
{
|
||||
if (!DataService.AddUserToDeviceGroup(EditUser.OrganizationID, group.ID, EditUser.UserName, out var result))
|
||||
{
|
||||
ToastService.ShowToast(result, classString: "bg-warning");
|
||||
}
|
||||
else
|
||||
{
|
||||
ToastService.ShowToast("User added to group.");
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await DataService.RemoveUserFromDeviceGroup(EditUser.OrganizationID, group.ID, EditUser.Id);
|
||||
if (!result)
|
||||
{
|
||||
ToastService.ShowToast("Failed to remove from group.", classString: "bg-warning");
|
||||
}
|
||||
else
|
||||
{
|
||||
ToastService.ShowToast("Removed user from group.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace Remotely.Server.Components.ModalContents;
|
||||
|
||||
public partial class QuickScriptsSelector : ComponentBase
|
||||
{
|
||||
}
|
||||
@ -1,10 +1,12 @@
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Remotely.Shared.Entities;
|
||||
using Remotely.Shared.Models;
|
||||
@ -23,6 +25,13 @@ public class AppDb : IdentityDbContext
|
||||
c => c.Aggregate(0, (a, b) => HashCode.Combine(a, b.GetHashCode())),
|
||||
c => c.ToArray());
|
||||
|
||||
private readonly IWebHostEnvironment _hostEnv;
|
||||
|
||||
public AppDb(IWebHostEnvironment hostEnvironment)
|
||||
{
|
||||
_hostEnv = hostEnvironment;
|
||||
}
|
||||
|
||||
public DbSet<Alert> Alerts { get; set; }
|
||||
|
||||
public DbSet<ApiToken> ApiTokens { get; set; }
|
||||
@ -31,10 +40,10 @@ public class AppDb : IdentityDbContext
|
||||
public DbSet<Device> Devices { get; set; }
|
||||
public DbSet<InviteLink> InviteLinks { get; set; }
|
||||
public DbSet<Organization> Organizations { get; set; }
|
||||
public DbSet<ScriptRun> ScriptRuns { get; set; }
|
||||
public DbSet<SavedScript> SavedScripts { get; set; }
|
||||
public DbSet<ScriptSchedule> ScriptSchedules { get; set; }
|
||||
public DbSet<ScriptResult> ScriptResults { get; set; }
|
||||
public DbSet<ScriptRun> ScriptRuns { get; set; }
|
||||
public DbSet<ScriptSchedule> ScriptSchedules { get; set; }
|
||||
public DbSet<SharedFile> SharedFiles { get; set; }
|
||||
public new DbSet<RemotelyUser> Users { get; set; }
|
||||
|
||||
@ -43,6 +52,12 @@ public class AppDb : IdentityDbContext
|
||||
{
|
||||
options.ConfigureWarnings(x => x.Ignore(RelationalEventId.MultipleCollectionIncludeWarning));
|
||||
options.LogTo((message) => System.Diagnostics.Debug.Write(message));
|
||||
|
||||
if (_hostEnv.IsDevelopment())
|
||||
{
|
||||
options.EnableDetailedErrors();
|
||||
options.EnableSensitiveDataLogging();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Remotely.Server.Services;
|
||||
using System;
|
||||
|
||||
@ -13,21 +14,26 @@ public class AppDbFactory : IAppDbFactory
|
||||
{
|
||||
private readonly IApplicationConfig _appConfig;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly IWebHostEnvironment _hostEnv;
|
||||
|
||||
public AppDbFactory(IApplicationConfig appConfig, IConfiguration configuration)
|
||||
public AppDbFactory(
|
||||
IApplicationConfig appConfig,
|
||||
IConfiguration configuration,
|
||||
IWebHostEnvironment hostEnv)
|
||||
{
|
||||
_appConfig = appConfig;
|
||||
_configuration = configuration;
|
||||
_hostEnv = hostEnv;
|
||||
}
|
||||
|
||||
public AppDb GetContext()
|
||||
{
|
||||
return _appConfig.DBProvider.ToLower() switch
|
||||
{
|
||||
"sqlite" => new SqliteDbContext(_configuration),
|
||||
"sqlserver" => new SqlServerDbContext(_configuration),
|
||||
"postgresql" => new PostgreSqlDbContext(_configuration),
|
||||
"inmemory" => new TestingDbContext(),
|
||||
"sqlite" => new SqliteDbContext(_configuration, _hostEnv),
|
||||
"sqlserver" => new SqlServerDbContext(_configuration, _hostEnv),
|
||||
"postgresql" => new PostgreSqlDbContext(_configuration, _hostEnv),
|
||||
"inmemory" => new TestingDbContext(_hostEnv),
|
||||
_ => throw new ArgumentException("Unknown DB provider."),
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -14,7 +15,8 @@ public class PostgreSqlDbContext : AppDb
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public PostgreSqlDbContext(IConfiguration configuration)
|
||||
public PostgreSqlDbContext(IConfiguration configuration, IWebHostEnvironment hostEnv)
|
||||
: base(hostEnv)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -13,7 +14,8 @@ public class SqlServerDbContext : AppDb
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public SqlServerDbContext(IConfiguration configuration)
|
||||
public SqlServerDbContext(IConfiguration configuration, IWebHostEnvironment hostEnv)
|
||||
: base(hostEnv)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@ -13,7 +14,8 @@ public class SqliteDbContext : AppDb
|
||||
{
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
public SqliteDbContext(IConfiguration configuration)
|
||||
public SqliteDbContext(IConfiguration configuration, IWebHostEnvironment hostEnv)
|
||||
: base(hostEnv)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Remotely.Server.Data;
|
||||
using System;
|
||||
@ -11,6 +12,11 @@ namespace Remotely.Server.Data;
|
||||
|
||||
public class TestingDbContext : AppDb
|
||||
{
|
||||
public TestingDbContext(IWebHostEnvironment hostEnvironment)
|
||||
: base(hostEnvironment)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder options)
|
||||
{
|
||||
options.UseInMemoryDatabase("Remotely");
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
@page "/scripts/{activeTab?}"
|
||||
@attribute [Authorize]
|
||||
@inherits AuthComponentBase
|
||||
@using System.Collections
|
||||
@inject IDataService DataService
|
||||
|
||||
<CascadingValue Value="this">
|
||||
<TabControl InitialActiveTab="@(ActiveTab ?? "saved-scripts")">
|
||||
@ -30,135 +28,3 @@
|
||||
</TabContents>
|
||||
</TabControl>
|
||||
</CascadingValue>
|
||||
|
||||
|
||||
@code {
|
||||
private readonly List<ScriptTreeNode> _treeNodes = new();
|
||||
private IEnumerable<SavedScript> _allScripts = Enumerable.Empty<SavedScript>();
|
||||
|
||||
private bool _showOnlyMyScripts = true;
|
||||
|
||||
[Parameter]
|
||||
public string? ActiveTab { get; set; }
|
||||
|
||||
public bool ShowOnlyMyScripts
|
||||
{
|
||||
get => _showOnlyMyScripts;
|
||||
set
|
||||
{
|
||||
_showOnlyMyScripts = value;
|
||||
_treeNodes.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<ScriptTreeNode> TreeNodes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_treeNodes.Any() == true)
|
||||
{
|
||||
return _treeNodes;
|
||||
}
|
||||
|
||||
RefreshTreeNodes();
|
||||
|
||||
return _treeNodes;
|
||||
}
|
||||
}
|
||||
|
||||
public string GetItemIconCss(ScriptTreeNode viewModel)
|
||||
{
|
||||
if (viewModel.ItemType == TreeItemType.Folder)
|
||||
{
|
||||
return "oi oi-folder text-warning";
|
||||
}
|
||||
return "oi oi-script text-success";
|
||||
}
|
||||
|
||||
public async Task RefreshScripts()
|
||||
{
|
||||
_treeNodes.Clear();
|
||||
|
||||
_allScripts = await DataService.GetSavedScriptsWithoutContent(User.Id, User.OrganizationID);
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
await RefreshScripts();
|
||||
}
|
||||
|
||||
|
||||
private void CreateTreeNode(SavedScript script)
|
||||
{
|
||||
var root = _treeNodes;
|
||||
ScriptTreeNode? targetParent = null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(script.FolderPath))
|
||||
{
|
||||
var paths = script.FolderPath.Split("/", StringSplitOptions.RemoveEmptyEntries);
|
||||
for (var i = 0; i < paths.Length; i++)
|
||||
{
|
||||
var existingParent = root.Find(x => x.Name == paths[i]);
|
||||
|
||||
if (existingParent is null)
|
||||
{
|
||||
var newItem = new ScriptTreeNode()
|
||||
{
|
||||
Name = paths[i],
|
||||
ItemType = TreeItemType.Folder,
|
||||
ParentNode = existingParent
|
||||
};
|
||||
root.Add(newItem);
|
||||
root = newItem.ChildItems;
|
||||
targetParent = newItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
root = existingParent.ChildItems;
|
||||
targetParent = existingParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var scriptNode = new ScriptTreeNode()
|
||||
{
|
||||
Name = script.Name,
|
||||
Script = script,
|
||||
ItemType = TreeItemType.Item,
|
||||
ParentNode = targetParent
|
||||
};
|
||||
|
||||
root.Add(scriptNode);
|
||||
}
|
||||
|
||||
private void RefreshTreeNodes()
|
||||
{
|
||||
_treeNodes.Clear();
|
||||
|
||||
foreach (var script in _allScripts)
|
||||
{
|
||||
var showScript = ShowOnlyMyScripts ?
|
||||
script.CreatorId == User.Id :
|
||||
script.CreatorId == User.Id || script.IsPublic;
|
||||
|
||||
if (!showScript)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CreateTreeNode(script);
|
||||
}
|
||||
|
||||
_treeNodes.Sort((a, b) =>
|
||||
{
|
||||
if (a.ItemType != b.ItemType)
|
||||
{
|
||||
return Comparer.Default.Compare(a.ItemType, b.ItemType);
|
||||
}
|
||||
|
||||
return Comparer.Default.Compare(a.Name, b.Name);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
148
Server/Pages/ScriptsPage.razor.cs
Normal file
148
Server/Pages/ScriptsPage.razor.cs
Normal file
@ -0,0 +1,148 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Remotely.Server.Components;
|
||||
using Remotely.Server.Components.Scripts;
|
||||
using Remotely.Server.Components.TreeView;
|
||||
using Remotely.Server.Services;
|
||||
using Remotely.Shared.Entities;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Remotely.Server.Pages;
|
||||
|
||||
[Authorize]
|
||||
public partial class ScriptsPage : AuthComponentBase
|
||||
{
|
||||
private readonly List<ScriptTreeNode> _treeNodes = new();
|
||||
private IEnumerable<SavedScript> _allScripts = Enumerable.Empty<SavedScript>();
|
||||
private bool _showOnlyMyScripts = true;
|
||||
|
||||
[Parameter]
|
||||
public string? ActiveTab { get; set; }
|
||||
|
||||
public bool ShowOnlyMyScripts
|
||||
{
|
||||
get => _showOnlyMyScripts;
|
||||
set
|
||||
{
|
||||
_showOnlyMyScripts = value;
|
||||
_treeNodes.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<ScriptTreeNode> TreeNodes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_treeNodes.Any() == true)
|
||||
{
|
||||
return _treeNodes;
|
||||
}
|
||||
|
||||
RefreshTreeNodes();
|
||||
|
||||
return _treeNodes;
|
||||
}
|
||||
}
|
||||
|
||||
[Inject]
|
||||
private IDataService DataService { get; init; } = null!;
|
||||
|
||||
public string GetItemIconCss(ScriptTreeNode viewModel)
|
||||
{
|
||||
if (viewModel.ItemType == TreeItemType.Folder)
|
||||
{
|
||||
return "oi oi-folder text-warning";
|
||||
}
|
||||
return "oi oi-script text-success";
|
||||
}
|
||||
|
||||
public async Task RefreshScripts()
|
||||
{
|
||||
_treeNodes.Clear();
|
||||
|
||||
_allScripts = await DataService.GetSavedScriptsWithoutContent(User.Id, User.OrganizationID);
|
||||
}
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
await RefreshScripts();
|
||||
}
|
||||
|
||||
|
||||
private void CreateTreeNode(SavedScript script)
|
||||
{
|
||||
var root = _treeNodes;
|
||||
ScriptTreeNode? targetParent = null;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(script.FolderPath))
|
||||
{
|
||||
var paths = script.FolderPath.Split("/", StringSplitOptions.RemoveEmptyEntries);
|
||||
for (var i = 0; i < paths.Length; i++)
|
||||
{
|
||||
var existingParent = root.Find(x => x.Name == paths[i]);
|
||||
|
||||
if (existingParent is null)
|
||||
{
|
||||
var newItem = new ScriptTreeNode()
|
||||
{
|
||||
Name = paths[i],
|
||||
ItemType = TreeItemType.Folder,
|
||||
ParentNode = existingParent
|
||||
};
|
||||
root.Add(newItem);
|
||||
root = newItem.ChildItems;
|
||||
targetParent = newItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
root = existingParent.ChildItems;
|
||||
targetParent = existingParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var scriptNode = new ScriptTreeNode()
|
||||
{
|
||||
Name = script.Name,
|
||||
Script = script,
|
||||
ItemType = TreeItemType.Item,
|
||||
ParentNode = targetParent
|
||||
};
|
||||
|
||||
root.Add(scriptNode);
|
||||
}
|
||||
|
||||
private void RefreshTreeNodes()
|
||||
{
|
||||
_treeNodes.Clear();
|
||||
|
||||
foreach (var script in _allScripts)
|
||||
{
|
||||
var showScript = ShowOnlyMyScripts ?
|
||||
script.CreatorId == User.Id :
|
||||
script.CreatorId == User.Id || script.IsPublic;
|
||||
|
||||
if (!showScript)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
CreateTreeNode(script);
|
||||
}
|
||||
|
||||
_treeNodes.Sort((a, b) =>
|
||||
{
|
||||
if (a.ItemType != b.ItemType)
|
||||
{
|
||||
return Comparer.Default.Compare(a.ItemType, b.ItemType);
|
||||
}
|
||||
|
||||
return Comparer.Default.Compare(a.Name, b.Name);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,10 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.AspNetCore.Components.Server.Circuits;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.UI;
|
||||
using Microsoft.AspNetCore.Identity.UI.Services;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@ -26,14 +23,10 @@ using Remotely.Server.Services;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Remotely.Shared.Utilities;
|
||||
using Immense.RemoteControl.Server.Extensions;
|
||||
using Remotely.Server.Services.RcImplementations;
|
||||
using Immense.RemoteControl.Server.Abstractions;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Remotely.Shared.Services;
|
||||
using System;
|
||||
using Immense.RemoteControl.Server.Services;
|
||||
using Serilog;
|
||||
using Nihs.SimpleMessenger;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
@ -63,37 +56,15 @@ if (string.IsNullOrWhiteSpace(dbProvider))
|
||||
|
||||
if (dbProvider == "sqlite")
|
||||
{
|
||||
services.AddDbContext<AppDb, SqliteDbContext>(options =>
|
||||
{
|
||||
options.UseSqlite(configuration.GetConnectionString("SQLite"));
|
||||
});
|
||||
services.AddDbContext<AppDb, SqliteDbContext>();
|
||||
}
|
||||
else if (dbProvider == "sqlserver")
|
||||
{
|
||||
services.AddDbContext<AppDb, SqlServerDbContext>(options =>
|
||||
{
|
||||
options.UseSqlServer(configuration.GetConnectionString("SQLServer"));
|
||||
});
|
||||
services.AddDbContext<AppDb, SqlServerDbContext>();
|
||||
}
|
||||
else if (dbProvider == "postgresql")
|
||||
{
|
||||
services.AddDbContext<AppDb, PostgreSqlDbContext>(options =>
|
||||
{
|
||||
// Password should be set in User Secrets in dev environment.
|
||||
// See https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1
|
||||
if (!string.IsNullOrWhiteSpace(configuration.GetValue<string>("PostgresPassword")))
|
||||
{
|
||||
var connectionBuilder = new NpgsqlConnectionStringBuilder(configuration.GetConnectionString("PostgreSQL"))
|
||||
{
|
||||
Password = configuration["PostgresPassword"]
|
||||
};
|
||||
options.UseNpgsql(connectionBuilder.ConnectionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.UseNpgsql(configuration.GetConnectionString("PostgreSQL"));
|
||||
}
|
||||
});
|
||||
services.AddDbContext<AppDb, PostgreSqlDbContext>();
|
||||
}
|
||||
|
||||
services.AddIdentity<RemotelyUser, IdentityRole>(options =>
|
||||
|
||||
@ -17,21 +17,21 @@
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MailKit" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.7">
|
||||
<PackageReference Include="MailKit" Version="4.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.9">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.EventLog" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="7.0.8" />
|
||||
<PackageReference Include="Nihs.SimpleMessenger" Version="1.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="7.0.0" />
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="7.0.9" />
|
||||
<PackageReference Include="Nihs.ConcurrentList" Version="1.0.0" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" />
|
||||
|
||||
@ -13,12 +13,12 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.7" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.9" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
|
||||
<PackageReference Include="Moq" Version="4.18.4" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.0.4" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@ -13,9 +13,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.0.4" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.0.4" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
|
||||
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit d571422a0e282fd009769bf14c7f6adf8867b0d8
|
||||
Subproject commit 7a548c24cc95c0d1c002672873516a59ecbde2c6
|
||||
Loading…
Reference in New Issue
Block a user