mirror of
https://github.com/immense/Remotely.git
synced 2025-10-26 11:27:15 +00:00
Added server config page.
This commit is contained in:
parent
3e8f429e48
commit
57eb9b3a7e
@ -122,7 +122,7 @@ Note: To retain your settings between upgrades, copy your settings to appsetting
|
||||
* 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 (see below).
|
||||
* 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).
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
<input asp-for="Input.PhoneNumber" class="form-control" />
|
||||
<span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-secondary">Save</button>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -27,6 +27,8 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
|
||||
public static string ServerLogs => "ServerLogs";
|
||||
|
||||
public static string ServerConfig => "ServerConfig";
|
||||
|
||||
public static string IndexNavClass(ViewContext viewContext) => PageNavClass(viewContext, Index);
|
||||
|
||||
public static string ChangePasswordNavClass(ViewContext viewContext) => PageNavClass(viewContext, ChangePassword);
|
||||
@ -45,6 +47,8 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
public static string ApiTokensNavClass(ViewContext viewContext) => PageNavClass(viewContext, ApiTokens);
|
||||
public static string ServerLogsNavClass(ViewContext viewContext) => PageNavClass(viewContext, ServerLogs);
|
||||
|
||||
public static string ServerConfigNavClass(ViewContext viewContext) => PageNavClass(viewContext, ServerConfig);
|
||||
|
||||
public static string PageNavClass(ViewContext viewContext, string page)
|
||||
{
|
||||
var activePage = viewContext.ViewData["ActivePage"] as string
|
||||
|
||||
@ -9,14 +9,14 @@
|
||||
<div class="col-md-6">
|
||||
<partial name="_StatusMessage" for="Message" />
|
||||
<form method="post">
|
||||
<div asp-validation-summary="All"></div>
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="Options.Theme" class="control-label"></label>
|
||||
<br />
|
||||
<select asp-for="Options.Theme" asp-items="@Html.GetEnumSelectList<Remotely.Shared.Enums.Theme>()" class="form-control" ></select>
|
||||
<br />
|
||||
<span asp-validation-for="Options.Theme"></span>
|
||||
<span asp-validation-for="Options.Theme" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
<br />
|
||||
<input asp-for="Options.ConsolePrompt" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="Options.ConsolePrompt"></span>
|
||||
<span asp-validation-for="Options.ConsolePrompt" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@ -40,39 +40,39 @@
|
||||
<br />
|
||||
<input asp-for="Options.CommandModeShortcutWeb" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="Options.CommandModeShortcutWeb"></span>
|
||||
<span asp-validation-for="Options.CommandModeShortcutWeb" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Options.CommandModeShortcutPSCore" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="Options.CommandModeShortcutPSCore" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="Options.CommandModeShortcutPSCore"></span>
|
||||
<span asp-validation-for="Options.CommandModeShortcutPSCore" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Options.CommandModeShortcutWinPS" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="Options.CommandModeShortcutWinPS" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="Options.CommandModeShortcutWinPS"></span>
|
||||
<span asp-validation-for="Options.CommandModeShortcutWinPS" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Options.CommandModeShortcutCMD" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="Options.CommandModeShortcutCMD" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="Options.CommandModeShortcutCMD"></span>
|
||||
<span asp-validation-for="Options.CommandModeShortcutCMD" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="Options.CommandModeShortcutBash" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="Options.CommandModeShortcutBash" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="Options.CommandModeShortcutBash"></span>
|
||||
<span asp-validation-for="Options.CommandModeShortcutBash" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-secondary">Save</button>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@ -61,9 +61,7 @@
|
||||
|
||||
<div class="input-group">
|
||||
<input id="deviceGroupInput" placeholder="Add new device group" asp-for="Input.DeviceGroupName" class="form-control" maxlength="200" />
|
||||
<span class="input-group-btn">
|
||||
<button id="addDeviceGroupButton" type="submit" class="btn btn-secondary">Add</button>
|
||||
</span>
|
||||
<button id="addDeviceGroupButton" type="submit" class="btn btn-secondary">Add</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -161,7 +159,7 @@
|
||||
</div>
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text pl-1">
|
||||
<input asp-for="Input.IsAdmin" class="checkbox-inline" type="checkbox" />
|
||||
<input asp-for="Input.IsAdmin" type="checkbox" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="input-group-append">
|
||||
@ -210,11 +208,9 @@
|
||||
|
||||
<div class="input-group">
|
||||
<input placeholder="Add user to device group" class="form-control add-user-to-devicegroup-input" group="@Model.DeviceGroups[i].ID" maxlength="200" />
|
||||
<span class="input-group-btn">
|
||||
<button type="button" class="btn btn-secondary add-user-to-devicegroup-button" group="@Model.DeviceGroups[i].ID">
|
||||
Add
|
||||
</button>
|
||||
</span>
|
||||
<button type="button" class="btn btn-secondary add-user-to-devicegroup-button" group="@Model.DeviceGroups[i].ID">
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
255
Server/Areas/Identity/Pages/Account/Manage/ServerConfig.cshtml
Normal file
255
Server/Areas/Identity/Pages/Account/Manage/ServerConfig.cshtml
Normal file
@ -0,0 +1,255 @@
|
||||
@page
|
||||
@using Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
@model ServerConfigModel
|
||||
@{
|
||||
ViewData["Title"] = "Server Config";
|
||||
}
|
||||
|
||||
<h4>@ViewData["Title"]</h4>
|
||||
|
||||
@if (Model.IsServerAdmin)
|
||||
{
|
||||
<partial name="_StatusMessage" for="StatusMessage" />
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<form method="post" autocomplete="off">
|
||||
<div asp-validation-summary="All" class="text-danger"></div>
|
||||
|
||||
<h4>Application Settings</h4>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.AllowApiLogin"></label>
|
||||
<br />
|
||||
<input type="checkbox" asp-for="AppSettingsInput.AllowApiLogin" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.AllowApiLogin" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.DataRetentionInDays" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="AppSettingsInput.DataRetentionInDays" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.DataRetentionInDays" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.DBProvider" class="control-label"></label>
|
||||
<br />
|
||||
<select asp-for="AppSettingsInput.DBProvider" asp-items="@Html.GetEnumSelectList<ServerConfigModel.DBProviders>()" class="form-control"></select>
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.DBProvider" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.DefaultPrompt" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="AppSettingsInput.DefaultPrompt" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.DefaultPrompt" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.EnableWindowsEventLog"></label>
|
||||
<br />
|
||||
<input type="checkbox" asp-for="AppSettingsInput.EnableWindowsEventLog" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.EnableWindowsEventLog" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.KnownProxies" class="control-label"></label>
|
||||
<br />
|
||||
<select id="knownProxiesSelect" asp-for="AppSettingsInput.KnownProxies" class="form-control"></select>
|
||||
<div class="text-right mb-2 mt-1">
|
||||
<button id="knownProxiesRemoveButton" type="button" class="btn btn-secondary">Remove</button>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input id="knownProxiesInput" placeholder="Add a known proxy" class="form-control" />
|
||||
<button id="knownProxiesAddButton" type="button" class="btn btn-secondary">Add</button>
|
||||
</div>
|
||||
<span asp-validation-for="AppSettingsInput.KnownProxies" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.MaxOrganizationCount" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="AppSettingsInput.MaxOrganizationCount" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.MaxOrganizationCount" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.RecordRemoteControlSessions"></label>
|
||||
<br />
|
||||
<input type="checkbox" asp-for="AppSettingsInput.RecordRemoteControlSessions" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.RecordRemoteControlSessions" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.RedirectToHttps"></label>
|
||||
<br />
|
||||
<input type="checkbox" asp-for="AppSettingsInput.RedirectToHttps" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.RedirectToHttps" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.RemoteControlRequiresAuthentication"></label>
|
||||
<br />
|
||||
<input type="checkbox" asp-for="AppSettingsInput.RemoteControlRequiresAuthentication" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.RemoteControlRequiresAuthentication" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.RemoteControlSessionLimit" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="AppSettingsInput.RemoteControlSessionLimit" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.RemoteControlSessionLimit" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.Require2FA"></label>
|
||||
<br />
|
||||
<input type="checkbox" asp-for="AppSettingsInput.Require2FA" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.Require2FA" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.SmtpDisplayName" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="AppSettingsInput.SmtpDisplayName" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.SmtpDisplayName" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.SmtpEmail" class="control-label"></label>
|
||||
<br />
|
||||
<input type="email" asp-for="AppSettingsInput.SmtpEmail" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.SmtpEmail" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.SmtpEnableSsl"></label>
|
||||
<br />
|
||||
<input type="checkbox" asp-for="AppSettingsInput.SmtpEnableSsl" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.SmtpEnableSsl" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.SmtpHost" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="AppSettingsInput.SmtpHost" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.SmtpHost" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.SmtpPassword" class="control-label"></label>
|
||||
<br />
|
||||
<input type="password" asp-for="AppSettingsInput.SmtpPassword" class="form-control" autocomplete="new-password" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.SmtpPassword" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.SmtpPort" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="AppSettingsInput.SmtpPort" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.SmtpPort" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.SmtpUserName" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="AppSettingsInput.SmtpUserName" class="form-control" autocomplete="new-password" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.SmtpUserName" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.Theme" class="control-label"></label>
|
||||
<br />
|
||||
<select asp-for="AppSettingsInput.Theme" asp-items="@Html.GetEnumSelectList<Remotely.Shared.Enums.Theme>()" class="form-control"></select>
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.Theme" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.TrustedCorsOrigins" class="control-label"></label>
|
||||
<br />
|
||||
<select id="trustedCorsSelect" asp-for="AppSettingsInput.TrustedCorsOrigins" class="form-control"></select>
|
||||
|
||||
<div class="text-right mb-2 mt-1">
|
||||
<button id="trustedCorsRemoveButton" type="button" class="btn btn-secondary">Remove</button>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input id="trustedCorsInput" placeholder="Add trusted URL" class="form-control" />
|
||||
<button id="trustedCorsAddButton" type="button" class="btn btn-secondary">Add</button>
|
||||
</div>
|
||||
<span asp-validation-for="AppSettingsInput.TrustedCorsOrigins" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.UseHsts"></label>
|
||||
<br />
|
||||
<input type="checkbox" asp-for="AppSettingsInput.UseHsts" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.UseHsts" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label asp-for="AppSettingsInput.UseWebRtc"></label>
|
||||
<br />
|
||||
<input type="checkbox" asp-for="AppSettingsInput.UseWebRtc" />
|
||||
<br />
|
||||
<span asp-validation-for="AppSettingsInput.UseWebRtc" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<h4>Connection Strings</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="ConnectionStrings.PostgreSQL" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="ConnectionStrings.PostgreSQL" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="ConnectionStrings.PostgreSQL" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="ConnectionStrings.SQLite" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="ConnectionStrings.SQLite" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="ConnectionStrings.SQLite" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="ConnectionStrings.SQLServer" class="control-label"></label>
|
||||
<br />
|
||||
<input asp-for="ConnectionStrings.SQLServer" class="form-control" />
|
||||
<br />
|
||||
<span asp-validation-for="ConnectionStrings.SQLServer" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<h4>Server Admins</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label asp-for="ServerAdmins" class="control-label"></label>
|
||||
<br />
|
||||
<select id="serverAdminsSelect" asp-for="ServerAdmins" class="form-control"></select>
|
||||
<div class="text-right mb-2 mt-1">
|
||||
<button id="serverAdminsRemoveButton" type="button" class="btn btn-secondary">Remove</button>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<input id="serverAdminsInput" placeholder="Add a user as a server admin" class="form-control" />
|
||||
<button id="serverAdminsAddButton" type="button" class="btn btn-secondary">Add</button>
|
||||
</div>
|
||||
<span asp-validation-for="ServerAdmins" class="text-danger"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group mt-3">
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module" src="~/scripts/Pages/ServerConfig.js"></script>
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
<h5 class="text-muted">Only organization administrators can view this page.</h5>
|
||||
}
|
||||
@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Remotely.Server.Services;
|
||||
using Remotely.Shared.Enums;
|
||||
using Remotely.Shared.Models;
|
||||
|
||||
namespace Remotely.Server.Areas.Identity.Pages.Account.Manage
|
||||
{
|
||||
public class ServerConfigModel : PageModel
|
||||
{
|
||||
public ServerConfigModel(IConfiguration configuration, IWebHostEnvironment hostEnv, UserManager<RemotelyUser> userManager)
|
||||
{
|
||||
Configuration = configuration;
|
||||
HostEnv = hostEnv;
|
||||
UserManager = userManager;
|
||||
}
|
||||
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
public IWebHostEnvironment HostEnv { get; }
|
||||
|
||||
[BindProperty]
|
||||
public AppSettingsModel AppSettingsInput { get; set; } = new AppSettingsModel();
|
||||
|
||||
[BindProperty]
|
||||
[Display(Name = "Server Admins")]
|
||||
public List<string> ServerAdmins { get; set; } = new List<string>();
|
||||
|
||||
[BindProperty]
|
||||
public ConnectionStringsModel ConnectionStrings { get; set; } = new ConnectionStringsModel();
|
||||
|
||||
public bool IsServerAdmin { get; set; }
|
||||
|
||||
[TempData]
|
||||
public string StatusMessage { get; set; }
|
||||
|
||||
public UserManager<RemotelyUser> UserManager { get; }
|
||||
public async Task<IActionResult> OnGet()
|
||||
{
|
||||
IsServerAdmin = (await UserManager.GetUserAsync(User)).IsServerAdmin;
|
||||
if (!IsServerAdmin)
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
Configuration.Bind("ApplicationOptions", AppSettingsInput);
|
||||
Configuration.Bind("ConnectionStrings", ConnectionStrings);
|
||||
|
||||
return Page();
|
||||
}
|
||||
public async Task<IActionResult> OnPost()
|
||||
{
|
||||
IsServerAdmin = (await UserManager.GetUserAsync(User)).IsServerAdmin;
|
||||
if (!IsServerAdmin)
|
||||
{
|
||||
return Unauthorized();
|
||||
}
|
||||
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return Page();
|
||||
}
|
||||
|
||||
await SaveAppSettings();
|
||||
|
||||
return RedirectToPage();
|
||||
|
||||
}
|
||||
|
||||
private async Task SaveAppSettings()
|
||||
{
|
||||
string savePath;
|
||||
var prodSettings = HostEnv.ContentRootFileProvider.GetFileInfo("appsettings.Production.json");
|
||||
var settings = HostEnv.ContentRootFileProvider.GetFileInfo("appsettings.json");
|
||||
if (prodSettings.Exists)
|
||||
{
|
||||
savePath = prodSettings.PhysicalPath;
|
||||
}
|
||||
else if (settings.Exists)
|
||||
{
|
||||
savePath = settings.PhysicalPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var settingsJson = JsonSerializer.Deserialize<IDictionary<string, object>>(await System.IO.File.ReadAllTextAsync(savePath));
|
||||
|
||||
settingsJson["ApplicationOptions"] = AppSettingsInput;
|
||||
settingsJson["ConnectionStrings"] = ConnectionStrings;
|
||||
|
||||
await System.IO.File.WriteAllTextAsync(savePath, JsonSerializer.Serialize(settingsJson, new JsonSerializerOptions() { WriteIndented = true }));
|
||||
|
||||
// TODO: Save server admins.
|
||||
}
|
||||
|
||||
|
||||
public class AppSettingsModel
|
||||
{
|
||||
[Display(Name = "Allow API Login")]
|
||||
public bool AllowApiLogin { get; set; }
|
||||
|
||||
[Display(Name = "Data Retention (days)")]
|
||||
public double DataRetentionInDays { get; set; }
|
||||
|
||||
[Display(Name = "Database Provider")]
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public DBProviders DBProvider { get; set; }
|
||||
|
||||
[Display(Name = "Default Prompt")]
|
||||
public string DefaultPrompt { get; set; }
|
||||
|
||||
[Display(Name = "Enable Windows Event Log")]
|
||||
public bool EnableWindowsEventLog { get; set; }
|
||||
|
||||
[Display(Name = "Known Proxies")]
|
||||
public string[] KnownProxies { get; set; }
|
||||
|
||||
[Display(Name = "Max Organizations")]
|
||||
public int MaxOrganizationCount { get; set; }
|
||||
[Display(Name = "Record Remote Control Sessions")]
|
||||
public bool RecordRemoteControlSessions { get; set; }
|
||||
|
||||
[Display(Name = "Redirect To HTTPS")]
|
||||
public bool RedirectToHttps { get; set; }
|
||||
|
||||
[Display(Name = "Remote Control Requires Authentication")]
|
||||
public bool RemoteControlRequiresAuthentication { get; set; }
|
||||
|
||||
[Display(Name = "Remote Control Session Limit")]
|
||||
public double RemoteControlSessionLimit { get; set; }
|
||||
|
||||
[Display(Name = "Require 2FA")]
|
||||
public bool Require2FA { get; set; }
|
||||
|
||||
[Display(Name = "SMTP Display Name")]
|
||||
public string SmtpDisplayName { get; set; }
|
||||
|
||||
[Display(Name = "SMTP Email")]
|
||||
[EmailAddress]
|
||||
public string SmtpEmail { get; set; }
|
||||
|
||||
[Display(Name = "SMTP Enable SSL")]
|
||||
public bool SmtpEnableSsl { get; set; }
|
||||
|
||||
[Display(Name = "SMTP Host")]
|
||||
public string SmtpHost { get; set; }
|
||||
|
||||
[Display(Name = "SMTP Password")]
|
||||
public string SmtpPassword { get; set; }
|
||||
|
||||
[Display(Name = "SMTP Port")]
|
||||
public int SmtpPort { get; set; }
|
||||
|
||||
[Display(Name = "SMTP Username")]
|
||||
public string SmtpUserName { get; set; }
|
||||
|
||||
[Display(Name = "Theme")]
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public Theme Theme { get; set; }
|
||||
|
||||
[Display(Name = "Trusted CORS Origins")]
|
||||
public string[] TrustedCorsOrigins { get; set; }
|
||||
|
||||
[Display(Name = "Use HSTS")]
|
||||
public bool UseHsts { get; set; }
|
||||
|
||||
[Display(Name = "Use WebRTC")]
|
||||
public bool UseWebRtc { get; set; }
|
||||
}
|
||||
|
||||
public class ConnectionStringsModel
|
||||
{
|
||||
[Display(Name = "PostgreSQL")]
|
||||
public string PostgreSQL { get; set; }
|
||||
|
||||
[Display(Name = "SQLite")]
|
||||
public string SQLite { get; set; }
|
||||
|
||||
|
||||
[Display(Name = "SQL Server")]
|
||||
public string SQLServer { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public enum DBProviders
|
||||
{
|
||||
PostgreSQL,
|
||||
SQLite,
|
||||
SQLServer
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,26 @@
|
||||
@inject SignInManager<RemotelyUser> SignInManager
|
||||
@inject UserManager<RemotelyUser> UserManager
|
||||
@{
|
||||
var hasExternalLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()).Any();
|
||||
var user = await UserManager.GetUserAsync(User);
|
||||
}
|
||||
|
||||
<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.ApiTokensNavClass(ViewContext)" asp-page="./ApiTokens">API Access</a></li>
|
||||
<li class="nav-item"><a id="options" class="nav-link @ManageNavPages.ServerLogsNavClass(ViewContext)" asp-page="./ServerLogs">Server Logs</a></li>
|
||||
@if (user.IsAdministrator)
|
||||
{
|
||||
<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.ApiTokensNavClass(ViewContext)" asp-page="./ApiTokens">API Access</a></li>
|
||||
<li class="nav-item"><a id="options" class="nav-link @ManageNavPages.ServerLogsNavClass(ViewContext)" asp-page="./ServerLogs">Server Logs</a></li>
|
||||
}
|
||||
|
||||
@if (user.IsServerAdmin)
|
||||
{
|
||||
<li class="nav-item"><a id="options" class="nav-link @ManageNavPages.ServerConfigNavClass(ViewContext)" asp-page="./ServerConfig">Server Config</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>
|
||||
|
||||
@ -88,7 +88,12 @@ namespace Remotely.Server.Areas.Identity.Pages.Account
|
||||
ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
var user = new RemotelyUser { UserName = Input.Email, Email = Input.Email };
|
||||
var user = new RemotelyUser
|
||||
{
|
||||
UserName = Input.Email,
|
||||
Email = Input.Email ,
|
||||
IsServerAdmin = organizationCount == 0
|
||||
};
|
||||
var result = await _userManager.CreateAsync(user, Input.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
|
||||
662
Server/Migrations/20200306013915_IsServerAdmin property.Designer.cs
generated
Normal file
662
Server/Migrations/20200306013915_IsServerAdmin property.Designer.cs
generated
Normal file
@ -0,0 +1,662 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Remotely.Server.Data;
|
||||
|
||||
namespace Remotely.Server.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationDbContext))]
|
||||
[Migration("20200306013915_IsServerAdmin property")]
|
||||
partial class IsServerAdminproperty
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "3.1.2");
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Discriminator")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("LockoutEnd")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasName("UserNameIndex");
|
||||
|
||||
b.ToTable("RemotelyUsers");
|
||||
|
||||
b.HasDiscriminator<string>("Discriminator").HasValue("IdentityUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(128);
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(128);
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(128);
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(128);
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.ApiToken", b =>
|
||||
{
|
||||
b.Property<string>("ID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("LastUsed")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(200);
|
||||
|
||||
b.Property<string>("OrganizationID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Secret")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Token")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("OrganizationID");
|
||||
|
||||
b.HasIndex("Token");
|
||||
|
||||
b.ToTable("ApiTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.CommandResult", b =>
|
||||
{
|
||||
b.Property<string>("ID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CommandMode")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CommandResults")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("CommandText")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("OrganizationID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PSCoreResults")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SenderConnectionID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("SenderUserID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TargetDeviceIDs")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TimeStamp")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("OrganizationID");
|
||||
|
||||
b.ToTable("CommandResults");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.Device", b =>
|
||||
{
|
||||
b.Property<string>("ID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("AgentVersion")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Alias")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(100);
|
||||
|
||||
b.Property<double>("CpuUtilization")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<string>("CurrentUser")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DeviceGroupID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DeviceName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Drives")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("Is64Bit")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("IsOnline")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("LastOnline")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("OSArchitecture")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("OSDescription")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("OrganizationID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Platform")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("ProcessorCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ServerVerificationToken")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Tags")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(200);
|
||||
|
||||
b.Property<double>("TotalMemory")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<double>("TotalStorage")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<double>("UsedMemory")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.Property<double>("UsedStorage")
|
||||
.HasColumnType("REAL");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeviceGroupID");
|
||||
|
||||
b.HasIndex("DeviceName");
|
||||
|
||||
b.HasIndex("OrganizationID");
|
||||
|
||||
b.ToTable("Devices");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.DeviceGroup", b =>
|
||||
{
|
||||
b.Property<string>("ID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(200);
|
||||
|
||||
b.Property<string>("OrganizationID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("OrganizationID");
|
||||
|
||||
b.ToTable("DeviceGroups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.EventLog", b =>
|
||||
{
|
||||
b.Property<string>("ID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("EventType")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Message")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("OrganizationID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Source")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("StackTrace")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("TimeStamp")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("OrganizationID");
|
||||
|
||||
b.ToTable("EventLogs");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.InviteLink", b =>
|
||||
{
|
||||
b.Property<string>("ID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DateSent")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("InvitedUser")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("IsAdmin")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("OrganizationID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ResetUrl")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("OrganizationID");
|
||||
|
||||
b.ToTable("InviteLinks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.Organization", b =>
|
||||
{
|
||||
b.Property<string>("ID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("OrganizationName")
|
||||
.HasColumnType("TEXT")
|
||||
.HasMaxLength(25);
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.ToTable("Organizations");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.SharedFile", b =>
|
||||
{
|
||||
b.Property<string>("ID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ContentType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<byte[]>("FileContents")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<string>("FileName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("OrganizationID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Timestamp")
|
||||
.IsRequired()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("OrganizationID");
|
||||
|
||||
b.ToTable("SharedFiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.UserDevicePermission", b =>
|
||||
{
|
||||
b.Property<string>("ID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("DeviceGroupID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("ID");
|
||||
|
||||
b.HasIndex("DeviceGroupID");
|
||||
|
||||
b.HasIndex("UserID");
|
||||
|
||||
b.ToTable("PermissionLinks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.RemotelyUser", b =>
|
||||
{
|
||||
b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser");
|
||||
|
||||
b.Property<bool>("IsAdministrator")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("IsServerAdmin")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("OrganizationID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("UserOptions")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasIndex("OrganizationID");
|
||||
|
||||
b.HasIndex("UserName");
|
||||
|
||||
b.HasDiscriminator().HasValue("RemotelyUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.ApiToken", b =>
|
||||
{
|
||||
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
|
||||
.WithMany("ApiTokens")
|
||||
.HasForeignKey("OrganizationID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.CommandResult", b =>
|
||||
{
|
||||
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
|
||||
.WithMany("CommandResults")
|
||||
.HasForeignKey("OrganizationID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.Device", b =>
|
||||
{
|
||||
b.HasOne("Remotely.Shared.Models.DeviceGroup", "DeviceGroup")
|
||||
.WithMany("Devices")
|
||||
.HasForeignKey("DeviceGroupID");
|
||||
|
||||
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
|
||||
.WithMany("Devices")
|
||||
.HasForeignKey("OrganizationID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.DeviceGroup", b =>
|
||||
{
|
||||
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
|
||||
.WithMany("DeviceGroups")
|
||||
.HasForeignKey("OrganizationID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.EventLog", b =>
|
||||
{
|
||||
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
|
||||
.WithMany("EventLogs")
|
||||
.HasForeignKey("OrganizationID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.InviteLink", b =>
|
||||
{
|
||||
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
|
||||
.WithMany("InviteLinks")
|
||||
.HasForeignKey("OrganizationID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.SharedFile", b =>
|
||||
{
|
||||
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
|
||||
.WithMany("SharedFiles")
|
||||
.HasForeignKey("OrganizationID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.UserDevicePermission", b =>
|
||||
{
|
||||
b.HasOne("Remotely.Shared.Models.DeviceGroup", "DeviceGroup")
|
||||
.WithMany("PermissionLinks")
|
||||
.HasForeignKey("DeviceGroupID");
|
||||
|
||||
b.HasOne("Remotely.Shared.Models.RemotelyUser", "User")
|
||||
.WithMany("PermissionLinks")
|
||||
.HasForeignKey("UserID");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Remotely.Shared.Models.RemotelyUser", b =>
|
||||
{
|
||||
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
|
||||
.WithMany("RemotelyUsers")
|
||||
.HasForeignKey("OrganizationID");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
22
Server/Migrations/20200306013915_IsServerAdmin property.cs
Normal file
22
Server/Migrations/20200306013915_IsServerAdmin property.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace Remotely.Server.Migrations
|
||||
{
|
||||
public partial class IsServerAdminproperty : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsServerAdmin",
|
||||
table: "RemotelyUsers",
|
||||
nullable: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsServerAdmin",
|
||||
table: "RemotelyUsers");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -517,6 +517,9 @@ namespace Remotely.Server.Migrations
|
||||
b.Property<bool>("IsAdministrator")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("IsServerAdmin")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("OrganizationID")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
||||
@ -50,6 +50,7 @@
|
||||
<Content Remove="wwwroot\scripts\Pages\ApiTokens.ts" />
|
||||
<Content Remove="wwwroot\scripts\Pages\IndexNotLoggedIn.ts" />
|
||||
<Content Remove="wwwroot\scripts\Pages\OrganizationManagement.ts" />
|
||||
<Content Remove="wwwroot\scripts\Pages\ServerConfig.ts" />
|
||||
<Content Remove="wwwroot\scripts\RemoteControl\ClipboardWatcher.ts" />
|
||||
<Content Remove="wwwroot\scripts\RemoteControl\Main.ts" />
|
||||
<Content Remove="wwwroot\scripts\RemoteControl\RtcSession.ts" />
|
||||
@ -161,6 +162,7 @@
|
||||
<TypeScriptCompile Include="wwwroot\scripts\Pages\ApiTokens.ts" />
|
||||
<TypeScriptCompile Include="wwwroot\scripts\Pages\IndexNotLoggedIn.ts" />
|
||||
<TypeScriptCompile Include="wwwroot\scripts\Pages\OrganizationManagement.ts" />
|
||||
<TypeScriptCompile Include="wwwroot\scripts\Pages\ServerConfig.ts" />
|
||||
<TypeScriptCompile Include="wwwroot\scripts\RemoteControl\ClipboardWatcher.ts" />
|
||||
<TypeScriptCompile Include="wwwroot\scripts\RemoteControl\Main.ts" />
|
||||
<TypeScriptCompile Include="wwwroot\scripts\RemoteControl\RtcSession.ts" />
|
||||
|
||||
@ -19,6 +19,11 @@ h6 {
|
||||
font-size: 1rem !important;
|
||||
}
|
||||
|
||||
input[type='checkbox'] {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
|
||||
.container {
|
||||
max-width: 95vw !important;
|
||||
|
||||
76
Server/wwwroot/scripts/Pages/ServerConfig.js
Normal file
76
Server/wwwroot/scripts/Pages/ServerConfig.js
Normal file
@ -0,0 +1,76 @@
|
||||
var trustedCorsAddButton = document.getElementById("trustedCorsAddButton");
|
||||
var trustedCorsRemoveButton = document.getElementById("trustedCorsRemoveButton");
|
||||
var trustedCorsInput = document.getElementById("trustedCorsInput");
|
||||
var trustedCorsSelect = document.getElementById("trustedCorsSelect");
|
||||
var knownProxiesAddButton = document.getElementById("knownProxiesAddButton");
|
||||
var knownProxiesRemoveButton = document.getElementById("knownProxiesRemoveButton");
|
||||
var knownProxiesInput = document.getElementById("knownProxiesInput");
|
||||
var knownProxiesSelect = document.getElementById("knownProxiesSelect");
|
||||
var serverAdminsAddButton = document.getElementById("serverAdminsAddButton");
|
||||
var serverAdminsRemoveButton = document.getElementById("serverAdminsRemoveButton");
|
||||
var serverAdminsInput = document.getElementById("serverAdminsInput");
|
||||
var serverAdminsSelect = document.getElementById("serverAdminsSelect");
|
||||
trustedCorsAddButton.addEventListener("click", ev => {
|
||||
if (trustedCorsInput.value.length > 0) {
|
||||
var option = document.createElement("option");
|
||||
option.value = trustedCorsInput.value;
|
||||
option.text = trustedCorsInput.value;
|
||||
trustedCorsSelect.add(option);
|
||||
trustedCorsInput.value = "";
|
||||
}
|
||||
});
|
||||
trustedCorsInput.addEventListener("keypress", ev => {
|
||||
if (ev.key.toLowerCase() == "enter") {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
trustedCorsAddButton.click();
|
||||
}
|
||||
});
|
||||
trustedCorsRemoveButton.addEventListener("click", ev => {
|
||||
while (trustedCorsSelect.selectedOptions.length > 0) {
|
||||
trustedCorsSelect.selectedOptions[0].remove();
|
||||
}
|
||||
});
|
||||
knownProxiesAddButton.addEventListener("click", ev => {
|
||||
if (knownProxiesInput.value.length > 0) {
|
||||
var option = document.createElement("option");
|
||||
option.value = knownProxiesInput.value;
|
||||
option.text = knownProxiesInput.value;
|
||||
knownProxiesSelect.add(option);
|
||||
knownProxiesInput.value = "";
|
||||
}
|
||||
});
|
||||
knownProxiesInput.addEventListener("keypress", ev => {
|
||||
if (ev.key.toLowerCase() == "enter") {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
knownProxiesAddButton.click();
|
||||
}
|
||||
});
|
||||
knownProxiesRemoveButton.addEventListener("click", ev => {
|
||||
while (knownProxiesSelect.selectedOptions.length > 0) {
|
||||
knownProxiesSelect.selectedOptions[0].remove();
|
||||
}
|
||||
});
|
||||
serverAdminsAddButton.addEventListener("click", ev => {
|
||||
if (serverAdminsInput.value.length > 0) {
|
||||
var option = document.createElement("option");
|
||||
option.value = serverAdminsInput.value;
|
||||
option.text = serverAdminsInput.value;
|
||||
serverAdminsSelect.add(option);
|
||||
serverAdminsInput.value = "";
|
||||
}
|
||||
});
|
||||
serverAdminsInput.addEventListener("keypress", ev => {
|
||||
if (ev.key.toLowerCase() == "enter") {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
serverAdminsAddButton.click();
|
||||
}
|
||||
});
|
||||
serverAdminsRemoveButton.addEventListener("click", ev => {
|
||||
while (serverAdminsSelect.selectedOptions.length > 0) {
|
||||
serverAdminsSelect.selectedOptions[0].remove();
|
||||
}
|
||||
});
|
||||
//# sourceMappingURL=ServerConfig.js.map
|
||||
1
Server/wwwroot/scripts/Pages/ServerConfig.js.map
Normal file
1
Server/wwwroot/scripts/Pages/ServerConfig.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"ServerConfig.js","sourceRoot":"","sources":["ServerConfig.ts"],"names":[],"mappings":"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"}
|
||||
90
Server/wwwroot/scripts/Pages/ServerConfig.ts
Normal file
90
Server/wwwroot/scripts/Pages/ServerConfig.ts
Normal file
@ -0,0 +1,90 @@
|
||||
var trustedCorsAddButton = document.getElementById("trustedCorsAddButton") as HTMLButtonElement;
|
||||
var trustedCorsRemoveButton = document.getElementById("trustedCorsRemoveButton") as HTMLButtonElement;
|
||||
var trustedCorsInput = document.getElementById("trustedCorsInput") as HTMLInputElement;
|
||||
var trustedCorsSelect = document.getElementById("trustedCorsSelect") as HTMLSelectElement;
|
||||
|
||||
var knownProxiesAddButton = document.getElementById("knownProxiesAddButton") as HTMLButtonElement;
|
||||
var knownProxiesRemoveButton = document.getElementById("knownProxiesRemoveButton") as HTMLButtonElement;
|
||||
var knownProxiesInput = document.getElementById("knownProxiesInput") as HTMLInputElement;
|
||||
var knownProxiesSelect = document.getElementById("knownProxiesSelect") as HTMLSelectElement;
|
||||
|
||||
var serverAdminsAddButton = document.getElementById("serverAdminsAddButton") as HTMLButtonElement;
|
||||
var serverAdminsRemoveButton = document.getElementById("serverAdminsRemoveButton") as HTMLButtonElement;
|
||||
var serverAdminsInput = document.getElementById("serverAdminsInput") as HTMLInputElement;
|
||||
var serverAdminsSelect = document.getElementById("serverAdminsSelect") as HTMLSelectElement;
|
||||
|
||||
|
||||
|
||||
trustedCorsAddButton.addEventListener("click", ev => {
|
||||
if (trustedCorsInput.value.length > 0) {
|
||||
var option = document.createElement("option");
|
||||
option.value = trustedCorsInput.value;
|
||||
option.text = trustedCorsInput.value;
|
||||
trustedCorsSelect.add(option);
|
||||
trustedCorsInput.value = "";
|
||||
}
|
||||
});
|
||||
|
||||
trustedCorsInput.addEventListener("keypress", ev => {
|
||||
if (ev.key.toLowerCase() == "enter") {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
trustedCorsAddButton.click();
|
||||
}
|
||||
})
|
||||
|
||||
trustedCorsRemoveButton.addEventListener("click", ev => {
|
||||
while (trustedCorsSelect.selectedOptions.length > 0) {
|
||||
trustedCorsSelect.selectedOptions[0].remove();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
knownProxiesAddButton.addEventListener("click", ev => {
|
||||
if (knownProxiesInput.value.length > 0) {
|
||||
var option = document.createElement("option");
|
||||
option.value = knownProxiesInput.value;
|
||||
option.text = knownProxiesInput.value;
|
||||
knownProxiesSelect.add(option);
|
||||
knownProxiesInput.value = "";
|
||||
}
|
||||
});
|
||||
|
||||
knownProxiesInput.addEventListener("keypress", ev => {
|
||||
if (ev.key.toLowerCase() == "enter") {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
knownProxiesAddButton.click();
|
||||
}
|
||||
})
|
||||
|
||||
knownProxiesRemoveButton.addEventListener("click", ev => {
|
||||
while (knownProxiesSelect.selectedOptions.length > 0) {
|
||||
knownProxiesSelect.selectedOptions[0].remove();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
serverAdminsAddButton.addEventListener("click", ev => {
|
||||
if (serverAdminsInput.value.length > 0) {
|
||||
var option = document.createElement("option");
|
||||
option.value = serverAdminsInput.value;
|
||||
option.text = serverAdminsInput.value;
|
||||
serverAdminsSelect.add(option);
|
||||
serverAdminsInput.value = "";
|
||||
}
|
||||
});
|
||||
|
||||
serverAdminsInput.addEventListener("keypress", ev => {
|
||||
if (ev.key.toLowerCase() == "enter") {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
serverAdminsAddButton.click();
|
||||
}
|
||||
})
|
||||
|
||||
serverAdminsRemoveButton.addEventListener("click", ev => {
|
||||
while (serverAdminsSelect.selectedOptions.length > 0) {
|
||||
serverAdminsSelect.selectedOptions[0].remove();
|
||||
}
|
||||
});
|
||||
@ -22,7 +22,7 @@ namespace Remotely.Shared.Models
|
||||
public string OrganizationID { get; set; }
|
||||
|
||||
public bool IsAdministrator { get; set; } = true;
|
||||
|
||||
public bool IsServerAdmin { get; set; }
|
||||
public List<UserDevicePermission> PermissionLinks { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user