From e2be4d237198ec1fe4034e39622b7e43e5ec230f Mon Sep 17 00:00:00 2001 From: Jared Goodwin Date: Tue, 25 Feb 2020 19:37:31 -0800 Subject: [PATCH] Move to PostgreSQL. Start adding stuff for device permissions. --- .../Pages/Account/Manage/Organization.cshtml | 87 ++- .../Account/Manage/Organization.cshtml.cs | 39 +- Server/Data/ApplicationDbContext.cs | 9 +- .../20191211163438_Initial.Designer.cs | 575 ----------------- .../20191212152649_Device alias.Designer.cs | 579 ------------------ .../Migrations/20191212152649_Device alias.cs | 23 - ...218144304_API Tokens and Device Updates.cs | 109 ---- ....cs => 20200226021333_Initial.Designer.cs} | 257 ++++---- ...8_Initial.cs => 20200226021333_Initial.cs} | 178 ++++-- .../ApplicationDbContextModelSnapshot.cs | 253 ++++---- Server/Server.csproj | 1 + Server/Services/DataService.cs | 2 +- Server/Startup.cs | 14 +- Server/appsettings.json | 8 +- .../scripts/Pages/OrganizationManagement.js | 50 +- .../Pages/OrganizationManagement.js.map | 2 +- .../scripts/Pages/OrganizationManagement.ts | 55 +- Shared/Models/ApiToken.cs | 2 +- Shared/Models/CommandContext.cs | 2 +- Shared/Models/Device.cs | 4 +- Shared/Models/DeviceGroup.cs | 6 +- Shared/Models/EventLog.cs | 2 +- Shared/Models/InviteLink.cs | 2 +- Shared/Models/Organization.cs | 16 +- Shared/Models/RemotelyUser.cs | 4 +- Shared/Models/SharedFile.cs | 2 +- Shared/Models/UserDevicePermission.cs | 19 + 27 files changed, 669 insertions(+), 1631 deletions(-) delete mode 100644 Server/Migrations/20191211163438_Initial.Designer.cs delete mode 100644 Server/Migrations/20191212152649_Device alias.Designer.cs delete mode 100644 Server/Migrations/20191212152649_Device alias.cs delete mode 100644 Server/Migrations/20200218144304_API Tokens and Device Updates.cs rename Server/Migrations/{20200218144304_API Tokens and Device Updates.Designer.cs => 20200226021333_Initial.Designer.cs} (68%) rename Server/Migrations/{20191211163438_Initial.cs => 20200226021333_Initial.cs} (81%) create mode 100644 Shared/Models/UserDevicePermission.cs diff --git a/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml b/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml index 77687aa7..97469b6f 100644 --- a/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml +++ b/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml @@ -45,24 +45,29 @@
+
@* Device Groups *@ -
- - - +
+
+ + + -
- -
+
+ + +
-
- - - - +
+ + + + +
-
+
+
@@ -150,7 +155,7 @@
- +
Admin?
@@ -169,6 +174,58 @@
+ + @* Device Permission Modals *@ + @for (var i = 0; i < Model.DeviceGroups.Count; i++) + { + + + } + diff --git a/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml.cs b/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml.cs index fa11f304..aa6fadd7 100644 --- a/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml.cs +++ b/Server/Areas/Identity/Pages/Account/Manage/Organization.cshtml.cs @@ -24,7 +24,8 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage UserManager = userManager; EmailSender = emailSender; } - public List DeviceGroups { get; } = new List(); + public List DeviceGroupSelectItems { get; } = new List(); + public List DeviceGroups { get; } = new List(); [BindProperty] public InputModel Input { get; set; } = new InputModel(); @@ -117,12 +118,41 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage return Page(); } + public async Task OnPostCreateDeviceGroupAsync() + { + var currentUser = await UserManager.FindByEmailAsync(User.Identity.Name); + if (!currentUser.IsAdministrator) + { + return RedirectToPage("Index"); + } + + if (ModelState.IsValid) + { + var deviceGroup = new DeviceGroup() + { + Name = Input.DeviceGroupName + }; + + var result = DataService.AddDeviceGroup(currentUser.OrganizationID, deviceGroup, out _, out var errorMessage); + if (!result) + { + PopulateViewModel(); + ModelState.AddModelError("AddDeviceGroup", errorMessage); + return Page(); + } + StatusMessage = "Device group created."; + return RedirectToPage(); + } + PopulateViewModel(); + return Page(); + } + private void PopulateViewModel() { OrganizationName = DataService.GetOrganizationName(User.Identity.Name); - var groups = DataService.GetDeviceGroupsForUserName(User.Identity.Name); - DeviceGroups.AddRange(groups.Select(x => new SelectListItem(x.Name, x.ID))); + DeviceGroups.AddRange(DataService.GetDeviceGroupsForUserName(User.Identity.Name)); + DeviceGroupSelectItems.AddRange(DeviceGroups.Select(x => new SelectListItem(x.Name, x.ID))); Users = DataService.GetAllUsers(User.Identity.Name) .Select(x => new OrganizationUser() @@ -147,6 +177,9 @@ namespace Remotely.Server.Areas.Identity.Pages.Account.Manage [EmailAddress] public string UserEmail { get; set; } + + [StringLength(200)] + public string DeviceGroupName { get; set; } } } diff --git a/Server/Data/ApplicationDbContext.cs b/Server/Data/ApplicationDbContext.cs index 14e0f647..4e9665be 100644 --- a/Server/Data/ApplicationDbContext.cs +++ b/Server/Data/ApplicationDbContext.cs @@ -34,7 +34,9 @@ namespace Remotely.Server.Data public DbSet DeviceGroups { get; set; } - protected override void OnModelCreating(ModelBuilder builder) + public DbSet PermissionLinks { get; set; } + + protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); @@ -55,6 +57,8 @@ namespace Remotely.Server.Data builder.Entity() .HasMany(x => x.Devices) .WithOne(x => x.DeviceGroup); + builder.Entity() + .HasMany(x => x.PermissionLinks); builder.Entity() .HasMany(x => x.DeviceGroups) .WithOne(x => x.Organization); @@ -90,6 +94,9 @@ namespace Remotely.Server.Data .HasOne(x => x.Organization) .WithMany(x => x.RemotelyUsers); + builder.Entity() + .HasMany(x => x.PermissionLinks); + builder.Entity() .Property(x => x.UserOptions) .HasConversion( diff --git a/Server/Migrations/20191211163438_Initial.Designer.cs b/Server/Migrations/20191211163438_Initial.Designer.cs deleted file mode 100644 index dc038a98..00000000 --- a/Server/Migrations/20191211163438_Initial.Designer.cs +++ /dev/null @@ -1,575 +0,0 @@ -// -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("20191211163438_Initial")] - partial class Initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "3.1.0"); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("NormalizedName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasName("RoleNameIndex"); - - b.ToTable("AspNetRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("AccessFailedCount") - .HasColumnType("INTEGER"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Discriminator") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Email") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("EmailConfirmed") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnabled") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnd") - .HasColumnType("TEXT"); - - b.Property("NormalizedEmail") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("NormalizedUserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("PasswordHash") - .HasColumnType("TEXT"); - - b.Property("PhoneNumber") - .HasColumnType("TEXT"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); - - b.Property("SecurityStamp") - .HasColumnType("TEXT"); - - b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER"); - - b.Property("UserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex"); - - b.ToTable("RemotelyUsers"); - - b.HasDiscriminator("Discriminator").HasValue("IdentityUser"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("ProviderKey") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("ProviderDisplayName") - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("Name") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.CommandContext", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("CommandMode") - .HasColumnType("TEXT"); - - b.Property("CommandResults") - .HasColumnType("TEXT"); - - b.Property("CommandText") - .HasColumnType("TEXT"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("PSCoreResults") - .HasColumnType("TEXT"); - - b.Property("SenderConnectionID") - .HasColumnType("TEXT"); - - b.Property("SenderUserID") - .HasColumnType("TEXT"); - - b.Property("TargetDeviceIDs") - .HasColumnType("TEXT"); - - b.Property("TimeStamp") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("CommandContexts"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.Device", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("AgentVersion") - .HasColumnType("TEXT"); - - b.Property("CurrentUser") - .HasColumnType("TEXT"); - - b.Property("DeviceGroupID") - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .HasColumnType("TEXT"); - - b.Property("Drives") - .HasColumnType("TEXT"); - - b.Property("FreeMemory") - .HasColumnType("REAL"); - - b.Property("FreeStorage") - .HasColumnType("REAL"); - - b.Property("Is64Bit") - .HasColumnType("INTEGER"); - - b.Property("IsOnline") - .HasColumnType("INTEGER"); - - b.Property("LastOnline") - .HasColumnType("TEXT"); - - b.Property("OSArchitecture") - .HasColumnType("INTEGER"); - - b.Property("OSDescription") - .HasColumnType("TEXT"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("Platform") - .HasColumnType("TEXT"); - - b.Property("ProcessorCount") - .HasColumnType("INTEGER"); - - b.Property("ServerVerificationToken") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("TotalMemory") - .HasColumnType("REAL"); - - b.Property("TotalStorage") - .HasColumnType("REAL"); - - b.HasKey("ID"); - - b.HasIndex("DeviceGroupID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.DeviceGroup", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("DeviceGroups"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.EventLog", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("EventType") - .HasColumnType("INTEGER"); - - b.Property("Message") - .HasColumnType("TEXT"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("Source") - .HasColumnType("TEXT"); - - b.Property("StackTrace") - .HasColumnType("TEXT"); - - b.Property("TimeStamp") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("EventLogs"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.InviteLink", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("DateSent") - .HasColumnType("TEXT"); - - b.Property("InvitedUser") - .HasColumnType("TEXT"); - - b.Property("IsAdmin") - .HasColumnType("INTEGER"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("ResetUrl") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("InviteLinks"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.Organization", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("OrganizationName") - .HasColumnType("TEXT") - .HasMaxLength(25); - - b.HasKey("ID"); - - b.ToTable("Organizations"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.SharedFile", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("ContentType") - .HasColumnType("TEXT"); - - b.Property("FileContents") - .HasColumnType("BLOB"); - - b.Property("FileName") - .HasColumnType("TEXT"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("SharedFiles"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.RemotelyUser", b => - { - b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); - - b.Property("IsAdministrator") - .HasColumnType("INTEGER"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("UserOptions") - .HasColumnType("TEXT"); - - b.HasIndex("OrganizationID"); - - b.HasDiscriminator().HasValue("RemotelyUser"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Remotely.Shared.Models.CommandContext", b => - { - b.HasOne("Remotely.Shared.Models.Organization", "Organization") - .WithMany("CommandContexts") - .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.RemotelyUser", b => - { - b.HasOne("Remotely.Shared.Models.Organization", "Organization") - .WithMany("RemotelyUsers") - .HasForeignKey("OrganizationID"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Server/Migrations/20191212152649_Device alias.Designer.cs b/Server/Migrations/20191212152649_Device alias.Designer.cs deleted file mode 100644 index f1630eca..00000000 --- a/Server/Migrations/20191212152649_Device alias.Designer.cs +++ /dev/null @@ -1,579 +0,0 @@ -// -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("20191212152649_Device alias")] - partial class Devicealias - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "3.1.0"); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("NormalizedName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasName("RoleNameIndex"); - - b.ToTable("AspNetRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => - { - b.Property("Id") - .HasColumnType("TEXT"); - - b.Property("AccessFailedCount") - .HasColumnType("INTEGER"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("TEXT"); - - b.Property("Discriminator") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Email") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("EmailConfirmed") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnabled") - .HasColumnType("INTEGER"); - - b.Property("LockoutEnd") - .HasColumnType("TEXT"); - - b.Property("NormalizedEmail") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("NormalizedUserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("PasswordHash") - .HasColumnType("TEXT"); - - b.Property("PhoneNumber") - .HasColumnType("TEXT"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); - - b.Property("SecurityStamp") - .HasColumnType("TEXT"); - - b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER"); - - b.Property("UserName") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex"); - - b.ToTable("RemotelyUsers"); - - b.HasDiscriminator("Discriminator").HasValue("IdentityUser"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ClaimType") - .HasColumnType("TEXT"); - - b.Property("ClaimValue") - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("ProviderKey") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("ProviderDisplayName") - .HasColumnType("TEXT"); - - b.Property("UserId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("RoleId") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("LoginProvider") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("Name") - .HasColumnType("TEXT") - .HasMaxLength(128); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.CommandContext", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("CommandMode") - .HasColumnType("TEXT"); - - b.Property("CommandResults") - .HasColumnType("TEXT"); - - b.Property("CommandText") - .HasColumnType("TEXT"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("PSCoreResults") - .HasColumnType("TEXT"); - - b.Property("SenderConnectionID") - .HasColumnType("TEXT"); - - b.Property("SenderUserID") - .HasColumnType("TEXT"); - - b.Property("TargetDeviceIDs") - .HasColumnType("TEXT"); - - b.Property("TimeStamp") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("CommandContexts"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.Device", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("AgentVersion") - .HasColumnType("TEXT"); - - b.Property("Alias") - .HasColumnType("TEXT") - .HasMaxLength(100); - - b.Property("CurrentUser") - .HasColumnType("TEXT"); - - b.Property("DeviceGroupID") - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .HasColumnType("TEXT"); - - b.Property("Drives") - .HasColumnType("TEXT"); - - b.Property("FreeMemory") - .HasColumnType("REAL"); - - b.Property("FreeStorage") - .HasColumnType("REAL"); - - b.Property("Is64Bit") - .HasColumnType("INTEGER"); - - b.Property("IsOnline") - .HasColumnType("INTEGER"); - - b.Property("LastOnline") - .HasColumnType("TEXT"); - - b.Property("OSArchitecture") - .HasColumnType("INTEGER"); - - b.Property("OSDescription") - .HasColumnType("TEXT"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("Platform") - .HasColumnType("TEXT"); - - b.Property("ProcessorCount") - .HasColumnType("INTEGER"); - - b.Property("ServerVerificationToken") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("TotalMemory") - .HasColumnType("REAL"); - - b.Property("TotalStorage") - .HasColumnType("REAL"); - - b.HasKey("ID"); - - b.HasIndex("DeviceGroupID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.DeviceGroup", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT") - .HasMaxLength(200); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("DeviceGroups"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.EventLog", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("EventType") - .HasColumnType("INTEGER"); - - b.Property("Message") - .HasColumnType("TEXT"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("Source") - .HasColumnType("TEXT"); - - b.Property("StackTrace") - .HasColumnType("TEXT"); - - b.Property("TimeStamp") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("EventLogs"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.InviteLink", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("DateSent") - .HasColumnType("TEXT"); - - b.Property("InvitedUser") - .HasColumnType("TEXT"); - - b.Property("IsAdmin") - .HasColumnType("INTEGER"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("ResetUrl") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("InviteLinks"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.Organization", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("OrganizationName") - .HasColumnType("TEXT") - .HasMaxLength(25); - - b.HasKey("ID"); - - b.ToTable("Organizations"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.SharedFile", b => - { - b.Property("ID") - .HasColumnType("TEXT"); - - b.Property("ContentType") - .HasColumnType("TEXT"); - - b.Property("FileContents") - .HasColumnType("BLOB"); - - b.Property("FileName") - .HasColumnType("TEXT"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("Timestamp") - .HasColumnType("TEXT"); - - b.HasKey("ID"); - - b.HasIndex("OrganizationID"); - - b.ToTable("SharedFiles"); - }); - - modelBuilder.Entity("Remotely.Shared.Models.RemotelyUser", b => - { - b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser"); - - b.Property("IsAdministrator") - .HasColumnType("INTEGER"); - - b.Property("OrganizationID") - .HasColumnType("TEXT"); - - b.Property("UserOptions") - .HasColumnType("TEXT"); - - b.HasIndex("OrganizationID"); - - b.HasDiscriminator().HasValue("RemotelyUser"); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", 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", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Remotely.Shared.Models.CommandContext", b => - { - b.HasOne("Remotely.Shared.Models.Organization", "Organization") - .WithMany("CommandContexts") - .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.RemotelyUser", b => - { - b.HasOne("Remotely.Shared.Models.Organization", "Organization") - .WithMany("RemotelyUsers") - .HasForeignKey("OrganizationID"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Server/Migrations/20191212152649_Device alias.cs b/Server/Migrations/20191212152649_Device alias.cs deleted file mode 100644 index 2108ff2b..00000000 --- a/Server/Migrations/20191212152649_Device alias.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Remotely.Server.Migrations -{ - public partial class Devicealias : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Alias", - table: "Devices", - maxLength: 100, - nullable: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Alias", - table: "Devices"); - } - } -} diff --git a/Server/Migrations/20200218144304_API Tokens and Device Updates.cs b/Server/Migrations/20200218144304_API Tokens and Device Updates.cs deleted file mode 100644 index e7806082..00000000 --- a/Server/Migrations/20200218144304_API Tokens and Device Updates.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Remotely.Server.Migrations -{ - public partial class APITokensandDeviceUpdates : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "FreeMemory", - table: "Devices", - newName: "UsedMemory"); - - migrationBuilder.RenameColumn( - name: "FreeStorage", - table: "Devices", - newName: "UsedStorage"); - - migrationBuilder.AddColumn( - name: "CpuUtilization", - table: "Devices", - nullable: false, - defaultValue: 0.0); - - migrationBuilder.CreateTable( - name: "ApiTokens", - columns: table => new - { - ID = table.Column(nullable: false), - LastUsed = table.Column(nullable: true), - Name = table.Column(maxLength: 200, nullable: true), - OrganizationID = table.Column(nullable: true), - Secret = table.Column(nullable: true), - Token = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiTokens", x => x.ID); - table.ForeignKey( - name: "FK_ApiTokens_Organizations_OrganizationID", - column: x => x.OrganizationID, - principalTable: "Organizations", - principalColumn: "ID", - onDelete: ReferentialAction.Restrict); - }); - - migrationBuilder.CreateIndex( - name: "IX_RemotelyUsers_UserName", - table: "RemotelyUsers", - column: "UserName"); - - migrationBuilder.CreateIndex( - name: "IX_Devices_DeviceName", - table: "Devices", - column: "DeviceName"); - - migrationBuilder.CreateIndex( - name: "IX_ApiTokens_OrganizationID", - table: "ApiTokens", - column: "OrganizationID"); - - migrationBuilder.CreateIndex( - name: "IX_ApiTokens_Token", - table: "ApiTokens", - column: "Token"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ApiTokens"); - - migrationBuilder.DropIndex( - name: "IX_RemotelyUsers_UserName", - table: "RemotelyUsers"); - - migrationBuilder.DropIndex( - name: "IX_Devices_DeviceName", - table: "Devices"); - - migrationBuilder.DropColumn( - name: "CpuUtilization", - table: "Devices"); - - migrationBuilder.DropColumn( - name: "UsedMemory", - table: "Devices"); - - migrationBuilder.DropColumn( - name: "UsedStorage", - table: "Devices"); - - migrationBuilder.AddColumn( - name: "FreeMemory", - table: "Devices", - type: "REAL", - nullable: false, - defaultValue: 0.0); - - migrationBuilder.AddColumn( - name: "FreeStorage", - table: "Devices", - type: "REAL", - nullable: false, - defaultValue: 0.0); - } - } -} diff --git a/Server/Migrations/20200218144304_API Tokens and Device Updates.Designer.cs b/Server/Migrations/20200226021333_Initial.Designer.cs similarity index 68% rename from Server/Migrations/20200218144304_API Tokens and Device Updates.Designer.cs rename to Server/Migrations/20200226021333_Initial.Designer.cs index 475c5057..39ae38bc 100644 --- a/Server/Migrations/20200218144304_API Tokens and Device Updates.Designer.cs +++ b/Server/Migrations/20200226021333_Initial.Designer.cs @@ -4,35 +4,38 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using Remotely.Server.Data; namespace Remotely.Server.Migrations { [DbContext(typeof(ApplicationDbContext))] - [Migration("20200218144304_API Tokens and Device Updates")] - partial class APITokensandDeviceUpdates + [Migration("20200226021333_Initial")] + partial class Initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.1"); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.2") + .HasAnnotation("Relational:MaxIdentifierLength", 63); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Name") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.Property("NormalizedName") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.HasKey("Id"); @@ -48,17 +51,18 @@ namespace Remotely.Server.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("ClaimType") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ClaimValue") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("RoleId") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("Id"); @@ -70,57 +74,57 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => { b.Property("Id") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("AccessFailedCount") - .HasColumnType("INTEGER"); + .HasColumnType("integer"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Discriminator") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Email") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.Property("EmailConfirmed") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("LockoutEnabled") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("LockoutEnd") - .HasColumnType("TEXT"); + .HasColumnType("timestamp with time zone"); b.Property("NormalizedEmail") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.Property("NormalizedUserName") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.Property("PasswordHash") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("PhoneNumber") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("SecurityStamp") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("UserName") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.HasKey("Id"); @@ -141,17 +145,18 @@ namespace Remotely.Server.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("ClaimType") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ClaimValue") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("UserId") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("Id"); @@ -163,19 +168,19 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") - .HasColumnType("TEXT") + .HasColumnType("character varying(128)") .HasMaxLength(128); b.Property("ProviderKey") - .HasColumnType("TEXT") + .HasColumnType("character varying(128)") .HasMaxLength(128); b.Property("ProviderDisplayName") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("UserId") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("LoginProvider", "ProviderKey"); @@ -187,10 +192,10 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { b.Property("UserId") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("RoleId") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("UserId", "RoleId"); @@ -202,18 +207,18 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { b.Property("UserId") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("LoginProvider") - .HasColumnType("TEXT") + .HasColumnType("character varying(128)") .HasMaxLength(128); b.Property("Name") - .HasColumnType("TEXT") + .HasColumnType("character varying(128)") .HasMaxLength(128); b.Property("Value") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("UserId", "LoginProvider", "Name"); @@ -223,23 +228,23 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.ApiToken", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("LastUsed") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.Property("Name") - .HasColumnType("TEXT") + .HasColumnType("character varying(200)") .HasMaxLength(200); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Secret") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Token") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("ID"); @@ -253,34 +258,34 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.CommandContext", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("CommandMode") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("CommandResults") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("CommandText") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("PSCoreResults") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("SenderConnectionID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("SenderUserID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("TargetDeviceIDs") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("TimeStamp") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.HasKey("ID"); @@ -292,72 +297,72 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.Device", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("AgentVersion") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Alias") - .HasColumnType("TEXT") + .HasColumnType("character varying(100)") .HasMaxLength(100); b.Property("CpuUtilization") - .HasColumnType("REAL"); + .HasColumnType("double precision"); b.Property("CurrentUser") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("DeviceGroupID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("DeviceName") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Drives") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Is64Bit") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("IsOnline") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("LastOnline") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.Property("OSArchitecture") - .HasColumnType("INTEGER"); + .HasColumnType("integer"); b.Property("OSDescription") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Platform") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ProcessorCount") - .HasColumnType("INTEGER"); + .HasColumnType("integer"); b.Property("ServerVerificationToken") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Tags") - .HasColumnType("TEXT") + .HasColumnType("character varying(200)") .HasMaxLength(200); b.Property("TotalMemory") - .HasColumnType("REAL"); + .HasColumnType("double precision"); b.Property("TotalStorage") - .HasColumnType("REAL"); + .HasColumnType("double precision"); b.Property("UsedMemory") - .HasColumnType("REAL"); + .HasColumnType("double precision"); b.Property("UsedStorage") - .HasColumnType("REAL"); + .HasColumnType("double precision"); b.HasKey("ID"); @@ -373,14 +378,14 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.DeviceGroup", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Name") - .HasColumnType("TEXT") + .HasColumnType("character varying(200)") .HasMaxLength(200); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("ID"); @@ -392,25 +397,25 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.EventLog", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("EventType") - .HasColumnType("INTEGER"); + .HasColumnType("integer"); b.Property("Message") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Source") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("StackTrace") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("TimeStamp") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.HasKey("ID"); @@ -422,22 +427,22 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.InviteLink", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("DateSent") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.Property("InvitedUser") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("IsAdmin") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ResetUrl") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("ID"); @@ -449,10 +454,10 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.Organization", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("OrganizationName") - .HasColumnType("TEXT") + .HasColumnType("character varying(25)") .HasMaxLength(25); b.HasKey("ID"); @@ -463,22 +468,22 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.SharedFile", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ContentType") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("FileContents") - .HasColumnType("BLOB"); + .HasColumnType("bytea"); b.Property("FileName") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Timestamp") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.HasKey("ID"); @@ -487,18 +492,43 @@ namespace Remotely.Server.Migrations b.ToTable("SharedFiles"); }); + modelBuilder.Entity("Remotely.Shared.Models.UserDevicePermission", b => + { + b.Property("ID") + .HasColumnType("text"); + + b.Property("DeviceGroupID") + .HasColumnType("text"); + + b.Property("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("DeviceGroupID") + .HasColumnType("text"); + b.Property("IsAdministrator") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("UserOptions") - .HasColumnType("TEXT"); + .HasColumnType("text"); + + b.HasIndex("DeviceGroupID"); b.HasIndex("OrganizationID"); @@ -611,8 +641,23 @@ namespace Remotely.Server.Migrations .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.DeviceGroup", null) + .WithMany("Users") + .HasForeignKey("DeviceGroupID"); + b.HasOne("Remotely.Shared.Models.Organization", "Organization") .WithMany("RemotelyUsers") .HasForeignKey("OrganizationID"); diff --git a/Server/Migrations/20191211163438_Initial.cs b/Server/Migrations/20200226021333_Initial.cs similarity index 81% rename from Server/Migrations/20191211163438_Initial.cs rename to Server/Migrations/20200226021333_Initial.cs index fe6acbdc..b4ffa354 100644 --- a/Server/Migrations/20191211163438_Initial.cs +++ b/Server/Migrations/20200226021333_Initial.cs @@ -1,5 +1,6 @@ using System; using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace Remotely.Server.Migrations { @@ -38,7 +39,7 @@ namespace Remotely.Server.Migrations columns: table => new { Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), RoleId = table.Column(nullable: false), ClaimType = table.Column(nullable: true), ClaimValue = table.Column(nullable: true) @@ -54,6 +55,28 @@ namespace Remotely.Server.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "ApiTokens", + columns: table => new + { + ID = table.Column(nullable: false), + LastUsed = table.Column(nullable: true), + Name = table.Column(maxLength: 200, nullable: true), + OrganizationID = table.Column(nullable: true), + Secret = table.Column(nullable: true), + Token = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiTokens", x => x.ID); + table.ForeignKey( + name: "FK_ApiTokens_Organizations_OrganizationID", + column: x => x.OrganizationID, + principalTable: "Organizations", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + }); + migrationBuilder.CreateTable( name: "CommandContexts", columns: table => new @@ -144,41 +167,6 @@ namespace Remotely.Server.Migrations onDelete: ReferentialAction.Restrict); }); - migrationBuilder.CreateTable( - name: "RemotelyUsers", - columns: table => new - { - Id = table.Column(nullable: false), - UserName = table.Column(maxLength: 256, nullable: true), - NormalizedUserName = table.Column(maxLength: 256, nullable: true), - Email = table.Column(maxLength: 256, nullable: true), - NormalizedEmail = table.Column(maxLength: 256, nullable: true), - EmailConfirmed = table.Column(nullable: false), - PasswordHash = table.Column(nullable: true), - SecurityStamp = table.Column(nullable: true), - ConcurrencyStamp = table.Column(nullable: true), - PhoneNumber = table.Column(nullable: true), - PhoneNumberConfirmed = table.Column(nullable: false), - TwoFactorEnabled = table.Column(nullable: false), - LockoutEnd = table.Column(nullable: true), - LockoutEnabled = table.Column(nullable: false), - AccessFailedCount = table.Column(nullable: false), - Discriminator = table.Column(nullable: false), - UserOptions = table.Column(nullable: true), - OrganizationID = table.Column(nullable: true), - IsAdministrator = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_RemotelyUsers", x => x.Id); - table.ForeignKey( - name: "FK_RemotelyUsers_Organizations_OrganizationID", - column: x => x.OrganizationID, - principalTable: "Organizations", - principalColumn: "ID", - onDelete: ReferentialAction.Restrict); - }); - migrationBuilder.CreateTable( name: "SharedFiles", columns: table => new @@ -207,12 +195,14 @@ namespace Remotely.Server.Migrations { ID = table.Column(nullable: false), AgentVersion = table.Column(nullable: true), + Alias = table.Column(maxLength: 100, nullable: true), + CpuUtilization = table.Column(nullable: false), CurrentUser = table.Column(nullable: true), - DeviceName = table.Column(nullable: true), DeviceGroupID = table.Column(nullable: true), + DeviceName = table.Column(nullable: true), Drives = table.Column(nullable: true), - FreeMemory = table.Column(nullable: false), - FreeStorage = table.Column(nullable: false), + UsedMemory = table.Column(nullable: false), + UsedStorage = table.Column(nullable: false), Is64Bit = table.Column(nullable: false), IsOnline = table.Column(nullable: false), LastOnline = table.Column(nullable: false), @@ -243,12 +233,54 @@ namespace Remotely.Server.Migrations onDelete: ReferentialAction.Restrict); }); + migrationBuilder.CreateTable( + name: "RemotelyUsers", + columns: table => new + { + Id = table.Column(nullable: false), + UserName = table.Column(maxLength: 256, nullable: true), + NormalizedUserName = table.Column(maxLength: 256, nullable: true), + Email = table.Column(maxLength: 256, nullable: true), + NormalizedEmail = table.Column(maxLength: 256, nullable: true), + EmailConfirmed = table.Column(nullable: false), + PasswordHash = table.Column(nullable: true), + SecurityStamp = table.Column(nullable: true), + ConcurrencyStamp = table.Column(nullable: true), + PhoneNumber = table.Column(nullable: true), + PhoneNumberConfirmed = table.Column(nullable: false), + TwoFactorEnabled = table.Column(nullable: false), + LockoutEnd = table.Column(nullable: true), + LockoutEnabled = table.Column(nullable: false), + AccessFailedCount = table.Column(nullable: false), + Discriminator = table.Column(nullable: false), + UserOptions = table.Column(nullable: true), + OrganizationID = table.Column(nullable: true), + IsAdministrator = table.Column(nullable: true), + DeviceGroupID = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_RemotelyUsers", x => x.Id); + table.ForeignKey( + name: "FK_RemotelyUsers_DeviceGroups_DeviceGroupID", + column: x => x.DeviceGroupID, + principalTable: "DeviceGroups", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_RemotelyUsers_Organizations_OrganizationID", + column: x => x.OrganizationID, + principalTable: "Organizations", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + }); + migrationBuilder.CreateTable( name: "AspNetUserClaims", columns: table => new { Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), UserId = table.Column(nullable: false), ClaimType = table.Column(nullable: true), ClaimValue = table.Column(nullable: true) @@ -328,6 +360,41 @@ namespace Remotely.Server.Migrations onDelete: ReferentialAction.Cascade); }); + migrationBuilder.CreateTable( + name: "PermissionLinks", + columns: table => new + { + ID = table.Column(nullable: false), + UserID = table.Column(nullable: true), + DeviceGroupID = table.Column(nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PermissionLinks", x => x.ID); + table.ForeignKey( + name: "FK_PermissionLinks_DeviceGroups_DeviceGroupID", + column: x => x.DeviceGroupID, + principalTable: "DeviceGroups", + principalColumn: "ID", + onDelete: ReferentialAction.Restrict); + table.ForeignKey( + name: "FK_PermissionLinks_RemotelyUsers_UserID", + column: x => x.UserID, + principalTable: "RemotelyUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + }); + + migrationBuilder.CreateIndex( + name: "IX_ApiTokens_OrganizationID", + table: "ApiTokens", + column: "OrganizationID"); + + migrationBuilder.CreateIndex( + name: "IX_ApiTokens_Token", + table: "ApiTokens", + column: "Token"); + migrationBuilder.CreateIndex( name: "IX_AspNetRoleClaims_RoleId", table: "AspNetRoleClaims", @@ -369,6 +436,11 @@ namespace Remotely.Server.Migrations table: "Devices", column: "DeviceGroupID"); + migrationBuilder.CreateIndex( + name: "IX_Devices_DeviceName", + table: "Devices", + column: "DeviceName"); + migrationBuilder.CreateIndex( name: "IX_Devices_OrganizationID", table: "Devices", @@ -384,6 +456,16 @@ namespace Remotely.Server.Migrations table: "InviteLinks", column: "OrganizationID"); + migrationBuilder.CreateIndex( + name: "IX_PermissionLinks_DeviceGroupID", + table: "PermissionLinks", + column: "DeviceGroupID"); + + migrationBuilder.CreateIndex( + name: "IX_PermissionLinks_UserID", + table: "PermissionLinks", + column: "UserID"); + migrationBuilder.CreateIndex( name: "EmailIndex", table: "RemotelyUsers", @@ -395,11 +477,21 @@ namespace Remotely.Server.Migrations column: "NormalizedUserName", unique: true); + migrationBuilder.CreateIndex( + name: "IX_RemotelyUsers_DeviceGroupID", + table: "RemotelyUsers", + column: "DeviceGroupID"); + migrationBuilder.CreateIndex( name: "IX_RemotelyUsers_OrganizationID", table: "RemotelyUsers", column: "OrganizationID"); + migrationBuilder.CreateIndex( + name: "IX_RemotelyUsers_UserName", + table: "RemotelyUsers", + column: "UserName"); + migrationBuilder.CreateIndex( name: "IX_SharedFiles_OrganizationID", table: "SharedFiles", @@ -408,6 +500,9 @@ namespace Remotely.Server.Migrations protected override void Down(MigrationBuilder migrationBuilder) { + migrationBuilder.DropTable( + name: "ApiTokens"); + migrationBuilder.DropTable( name: "AspNetRoleClaims"); @@ -435,6 +530,9 @@ namespace Remotely.Server.Migrations migrationBuilder.DropTable( name: "InviteLinks"); + migrationBuilder.DropTable( + name: "PermissionLinks"); + migrationBuilder.DropTable( name: "SharedFiles"); diff --git a/Server/Migrations/ApplicationDbContextModelSnapshot.cs b/Server/Migrations/ApplicationDbContextModelSnapshot.cs index 69f61cef..cabdabd5 100644 --- a/Server/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Server/Migrations/ApplicationDbContextModelSnapshot.cs @@ -3,6 +3,7 @@ using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using Remotely.Server.Data; namespace Remotely.Server.Migrations @@ -14,23 +15,25 @@ namespace Remotely.Server.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.1"); + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.2") + .HasAnnotation("Relational:MaxIdentifierLength", 63); modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { b.Property("Id") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Name") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.Property("NormalizedName") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.HasKey("Id"); @@ -46,17 +49,18 @@ namespace Remotely.Server.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("ClaimType") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ClaimValue") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("RoleId") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("Id"); @@ -68,57 +72,57 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => { b.Property("Id") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("AccessFailedCount") - .HasColumnType("INTEGER"); + .HasColumnType("integer"); b.Property("ConcurrencyStamp") .IsConcurrencyToken() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Discriminator") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Email") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.Property("EmailConfirmed") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("LockoutEnabled") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("LockoutEnd") - .HasColumnType("TEXT"); + .HasColumnType("timestamp with time zone"); b.Property("NormalizedEmail") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.Property("NormalizedUserName") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.Property("PasswordHash") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("PhoneNumber") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("PhoneNumberConfirmed") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("SecurityStamp") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("TwoFactorEnabled") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("UserName") - .HasColumnType("TEXT") + .HasColumnType("character varying(256)") .HasMaxLength(256); b.HasKey("Id"); @@ -139,17 +143,18 @@ namespace Remotely.Server.Migrations { b.Property("Id") .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); + .HasColumnType("integer") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); b.Property("ClaimType") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ClaimValue") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("UserId") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("Id"); @@ -161,19 +166,19 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.Property("LoginProvider") - .HasColumnType("TEXT") + .HasColumnType("character varying(128)") .HasMaxLength(128); b.Property("ProviderKey") - .HasColumnType("TEXT") + .HasColumnType("character varying(128)") .HasMaxLength(128); b.Property("ProviderDisplayName") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("UserId") .IsRequired() - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("LoginProvider", "ProviderKey"); @@ -185,10 +190,10 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { b.Property("UserId") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("RoleId") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("UserId", "RoleId"); @@ -200,18 +205,18 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { b.Property("UserId") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("LoginProvider") - .HasColumnType("TEXT") + .HasColumnType("character varying(128)") .HasMaxLength(128); b.Property("Name") - .HasColumnType("TEXT") + .HasColumnType("character varying(128)") .HasMaxLength(128); b.Property("Value") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("UserId", "LoginProvider", "Name"); @@ -221,23 +226,23 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.ApiToken", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("LastUsed") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.Property("Name") - .HasColumnType("TEXT") + .HasColumnType("character varying(200)") .HasMaxLength(200); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Secret") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Token") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("ID"); @@ -251,34 +256,34 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.CommandContext", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("CommandMode") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("CommandResults") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("CommandText") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("PSCoreResults") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("SenderConnectionID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("SenderUserID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("TargetDeviceIDs") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("TimeStamp") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.HasKey("ID"); @@ -290,72 +295,72 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.Device", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("AgentVersion") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Alias") - .HasColumnType("TEXT") + .HasColumnType("character varying(100)") .HasMaxLength(100); b.Property("CpuUtilization") - .HasColumnType("REAL"); + .HasColumnType("double precision"); b.Property("CurrentUser") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("DeviceGroupID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("DeviceName") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Drives") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Is64Bit") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("IsOnline") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("LastOnline") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.Property("OSArchitecture") - .HasColumnType("INTEGER"); + .HasColumnType("integer"); b.Property("OSDescription") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Platform") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ProcessorCount") - .HasColumnType("INTEGER"); + .HasColumnType("integer"); b.Property("ServerVerificationToken") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Tags") - .HasColumnType("TEXT") + .HasColumnType("character varying(200)") .HasMaxLength(200); b.Property("TotalMemory") - .HasColumnType("REAL"); + .HasColumnType("double precision"); b.Property("TotalStorage") - .HasColumnType("REAL"); + .HasColumnType("double precision"); b.Property("UsedMemory") - .HasColumnType("REAL"); + .HasColumnType("double precision"); b.Property("UsedStorage") - .HasColumnType("REAL"); + .HasColumnType("double precision"); b.HasKey("ID"); @@ -371,14 +376,14 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.DeviceGroup", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Name") - .HasColumnType("TEXT") + .HasColumnType("character varying(200)") .HasMaxLength(200); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("ID"); @@ -390,25 +395,25 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.EventLog", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("EventType") - .HasColumnType("INTEGER"); + .HasColumnType("integer"); b.Property("Message") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Source") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("StackTrace") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("TimeStamp") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.HasKey("ID"); @@ -420,22 +425,22 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.InviteLink", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("DateSent") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.Property("InvitedUser") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("IsAdmin") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ResetUrl") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.HasKey("ID"); @@ -447,10 +452,10 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.Organization", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("OrganizationName") - .HasColumnType("TEXT") + .HasColumnType("character varying(25)") .HasMaxLength(25); b.HasKey("ID"); @@ -461,22 +466,22 @@ namespace Remotely.Server.Migrations modelBuilder.Entity("Remotely.Shared.Models.SharedFile", b => { b.Property("ID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("ContentType") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("FileContents") - .HasColumnType("BLOB"); + .HasColumnType("bytea"); b.Property("FileName") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("Timestamp") - .HasColumnType("TEXT"); + .HasColumnType("timestamp without time zone"); b.HasKey("ID"); @@ -485,18 +490,43 @@ namespace Remotely.Server.Migrations b.ToTable("SharedFiles"); }); + modelBuilder.Entity("Remotely.Shared.Models.UserDevicePermission", b => + { + b.Property("ID") + .HasColumnType("text"); + + b.Property("DeviceGroupID") + .HasColumnType("text"); + + b.Property("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("DeviceGroupID") + .HasColumnType("text"); + b.Property("IsAdministrator") - .HasColumnType("INTEGER"); + .HasColumnType("boolean"); b.Property("OrganizationID") - .HasColumnType("TEXT"); + .HasColumnType("text"); b.Property("UserOptions") - .HasColumnType("TEXT"); + .HasColumnType("text"); + + b.HasIndex("DeviceGroupID"); b.HasIndex("OrganizationID"); @@ -609,8 +639,23 @@ namespace Remotely.Server.Migrations .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.DeviceGroup", null) + .WithMany("Users") + .HasForeignKey("DeviceGroupID"); + b.HasOne("Remotely.Shared.Models.Organization", "Organization") .WithMany("RemotelyUsers") .HasForeignKey("OrganizationID"); diff --git a/Server/Server.csproj b/Server/Server.csproj index b96d0739..4306e881 100644 --- a/Server/Server.csproj +++ b/Server/Server.csproj @@ -10,6 +10,7 @@ AnyCPU;x86;x64 Remotely.Server Remotely_Server + 36e32491-91a5-42e6-a466-819233f0c593 diff --git a/Server/Services/DataService.cs b/Server/Services/DataService.cs index 152d7609..32b004ae 100644 --- a/Server/Services/DataService.cs +++ b/Server/Services/DataService.cs @@ -267,7 +267,7 @@ namespace Remotely.Server.Services x.ID == deviceGroupId && x.OrganizationID == orgID); - deviceGroup.Devices.ForEach(x => + deviceGroup.Devices?.ForEach(x => { x.DeviceGroup = null; }); diff --git a/Server/Startup.cs b/Server/Startup.cs index e1665ffc..0330776e 100644 --- a/Server/Startup.cs +++ b/Server/Startup.cs @@ -30,6 +30,8 @@ using Microsoft.Extensions.Hosting; using Swashbuckle.AspNetCore.Swagger; using Microsoft.OpenApi.Models; using Remotely.Server.Auth; +using Microsoft.Data.SqlClient; +using Npgsql; namespace Remotely.Server { @@ -69,9 +71,17 @@ namespace Remotely.Server } else if (dbProvider == "postgresql") { + var connectionBuilder = new NpgsqlConnectionStringBuilder(Configuration.GetConnectionString("PostgreSQL")); + + // Password needs to 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 (IsDev) + { + connectionBuilder.Password = Configuration["PostgresPassword"]; + } + services.AddDbContext(options => - options.UseNpgsql( - Configuration.GetConnectionString("PostgreSQL"))); + options.UseNpgsql(connectionBuilder.ConnectionString)); } services.AddIdentity(options => options.Stores.MaxLengthForKeys = 128) diff --git a/Server/appsettings.json b/Server/appsettings.json index 3bd4ddd3..9f4788ad 100644 --- a/Server/appsettings.json +++ b/Server/appsettings.json @@ -2,7 +2,7 @@ "ConnectionStrings": { "SQLite": "DataSource=Server.db", "SQLServer": "Server=(localdb)\\mssqllocaldb;Database=Remotely-Server-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true", - "PostgreSQL": "Host=localhost;Database=;Username=;Password=" + "PostgreSQL": "Host=localhost;Database=Remotely;Username=postgres;" }, "Logging": { "LogLevel": { @@ -13,7 +13,7 @@ "AllowApiLogin": false, "MaxOrganizationCount": 1, "DataRetentionInDays": 90, - "DBProvider": "SQLite", + "DBProvider": "PostgreSQL", "DefaultPrompt": "~>", "EnableWindowsEventLog": false, "KnownProxies": [], @@ -21,7 +21,7 @@ "RedirectToHttps": false, "RemoteControlSessionLimit": 1, "RemoteControlRequiresAuthentication": true, - "Require2FA": false, + "Require2FA": false, "SmtpHost": "", "SmtpPort": 25, "SmtpUserName": "", @@ -32,6 +32,6 @@ "TrustedCorsOrigins": [], "Theme": "Light", "UseHsts": false, - "UseWebRtc": true + "UseWebRtc": true } } \ No newline at end of file diff --git a/Server/wwwroot/scripts/Pages/OrganizationManagement.js b/Server/wwwroot/scripts/Pages/OrganizationManagement.js index 7a524717..5e7389a2 100644 --- a/Server/wwwroot/scripts/Pages/OrganizationManagement.js +++ b/Server/wwwroot/scripts/Pages/OrganizationManagement.js @@ -13,6 +13,19 @@ document.getElementById("invitesHelpButton").addEventListener("click", (ev) => { document.getElementById("deviceGroupHelpButton").addEventListener("click", (ev) => { ShowModal("Device Groups", `Device groups can be used to organize and filter computers on the grid.`); }); +document.getElementById("addUsersToDeviceGroupButton").addEventListener("click", (ev) => { + var selectList = document.getElementById("deviceGroupList"); + if (selectList.selectedOptions.length == 0) { + return; + } + if (selectList.selectedOptions.length > 1) { + ShowModal("Device Group Users", "You can only edit users for 1 device group at a time."); + return; + } + var groupID = selectList.selectedOptions[0].value; + var modalDiv = document.querySelector(`.modal[group='${groupID}']`); + $(modalDiv).modal("show"); +}); document.getElementById("removeDeviceGroupButton").addEventListener("click", (ev) => { var selectList = document.getElementById("deviceGroupList"); for (var i = 0; i < selectList.selectedOptions.length; i++) { @@ -45,33 +58,20 @@ document.getElementById("deviceGroupInput").addEventListener("keypress", (e) => document.getElementById("addDeviceGroupButton").click(); } }); -document.getElementById("addDeviceGroupButton").addEventListener("click", () => { - var input = document.getElementById("deviceGroupInput"); - if (input.checkValidity() && input.value.length > 0) { - var xhr = new XMLHttpRequest(); - xhr.onload = () => { - if (xhr.status == 200) { - document.querySelectorAll(`.all-device-groups-list`).forEach((list) => { - var newOption = new Option(input.value, xhr.responseText); - list.options.add(newOption); - }); - input.value = ""; - } - else if (xhr.status == 400) { - ShowModal("Invalid Request", xhr.responseText); - } - else { - showError(xhr); - } - }; - xhr.onerror = () => { - showError(xhr); - }; - xhr.open("post", location.origin + "/api/OrganizationManagement/DeviceGroup"); - xhr.setRequestHeader("Content-Type", "application/json"); - xhr.send(JSON.stringify({ Name: input.value })); +document.querySelectorAll(".remove-user-from-device-group-button").forEach((x) => { + var groupID = x.getAttribute("group"); + var selectList = document.querySelector(`.modal[group='${groupID}'] select.device-group-user-list`); + for (var i = 0; i < selectList.selectedOptions.length; i++) { + // TODO: XHR to remove users and remove from list. } }); +document.querySelectorAll(".add-user-to-devicegroup-button").forEach((x) => { + var groupID = x.getAttribute("group"); + var modal = document.querySelector(`.modal[group='${groupID}']`); + var selectList = modal.querySelector(`select.device-group-user-list`); + var userInput = modal.querySelector(`input.add-user-to-devicegroup-input`); + // TODO: XHR to add user to group and add to select list. +}); document.getElementById("organizationNameInput").addEventListener("input", (ev) => { var addon = ev.currentTarget.parentElement.querySelector(".fa"); addon.classList.remove("fa-check-circle"); diff --git a/Server/wwwroot/scripts/Pages/OrganizationManagement.js.map b/Server/wwwroot/scripts/Pages/OrganizationManagement.js.map index 2c067b66..ebb977c1 100644 --- a/Server/wwwroot/scripts/Pages/OrganizationManagement.js.map +++ b/Server/wwwroot/scripts/Pages/OrganizationManagement.js.map @@ -1 +1 @@ -{"version":3,"file":"OrganizationManagement.js","sourceRoot":"","sources":["OrganizationManagement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAA+B,MAAM,UAAU,CAAC;AAGlE,QAAQ,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;IACxE,SAAS,CAAC,OAAO,EAAE;4FACqE,CAAC,CAAC;AAC9F,CAAC,CAAC,CAAC;AACH,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;IAC1E,SAAS,CAAC,aAAa,EAAE;;;;+GAIkF,CAAC,CAAC;AACjH,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,cAAc,CAAC,uBAAuB,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;IAC9E,SAAS,CAAC,eAAe,EAAE,yEAAyE,CAAC,CAAC;AAC1G,CAAC,CAAC,CAAC;AAGH,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;IAChF,IAAI,UAAU,GAAG,QAAQ,CAAC,cAAc,CAAC,iBAAiB,CAAsB,CAAC;IACjF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACxD,IAAI,aAAa,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QACxD,IAAI,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;QAC/B,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,EAAE,EAAE;YAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;YAC3B,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;gBACnB,QAAQ,CAAC,gBAAgB,CAAC,yCAAyC,aAAa,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;oBACnG,MAAM,CAAC,MAAM,EAAE,CAAC;gBACpB,CAAC,CAAC,CAAA;aACL;iBACI,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;gBACxB,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;aAClD;iBACI;gBACD,SAAS,CAAC,GAAG,CAAC,CAAC;aAClB;QACL,CAAC,CAAA;QACD,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE;YACf,SAAS,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC,CAAA;QACD,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,yCAAyC,CAAC,CAAC;QAChF,GAAG,CAAC,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QACzD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;KAC3C;AAEL,CAAC,CAAC,CAAC;AACH,QAAQ,CAAC,cAAc,CAAC,kBAAkB,CAAC,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE;IAC3E,IAAI,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,IAAI,OAAO,EAAE;QAChC,QAAQ,CAAC,cAAc,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;KAC3D;AACL,CAAC,CAAC,CAAA;AACF,QAAQ,CAAC,cAAc,CAAC,sBAAsB,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;IAC3E,IAAI,KAAK,GAAG,QAAQ,CAAC,cAAc,CAAC,kBAAkB,CAAqB,CAAC;IAE5E,IAAI,KAAK,CAAC,aAAa,EAAE,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;QACjD,IAAI,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;QAC/B,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;YACd,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;gBACnB,QAAQ,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,CAAC,OAAO,CAAC,CAAC,IAAuB,EAAE,EAAE;oBACrF,IAAI,SAAS,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;oBAC1D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;gBAChC,CAAC,CAAC,CAAA;gBACF,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;aACpB;iBACI,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;gBACxB,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;aAClD;iBACI;gBACD,SAAS,CAAC,GAAG,CAAC,CAAC;aAClB;QACL,CAAC,CAAA;QACD,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE;YACf,SAAS,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC,CAAA;QACD,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,yCAAyC,CAAC,CAAC;QAC9E,GAAG,CAAC,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QACzD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;KACnD;AACL,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,cAAc,CAAC,uBAAuB,CAAC,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;IAC9E,IAAI,KAAK,GAAI,EAAE,CAAC,aAAkC,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACtF,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC1C,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC,CAAC,CAAC;AACH,QAAQ,CAAC,cAAc,CAAC,uBAAuB,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE;IAC7E,IAAI,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;IAC/B,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;QACd,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;YACnB,IAAI,KAAK,GAAI,EAAE,CAAC,MAA2B,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC/E,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAClC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;SAC1C;aACI,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;YACxB,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;SAClD;aACI;YACD,SAAS,CAAC,GAAG,CAAC,CAAC;SAClB;IACL,CAAC,CAAA;IACD,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE;QACf,SAAS,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC,CAAA;IACD,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,GAAG,kCAAkC,CAAC,CAAC;IACtE,GAAG,CAAC,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;IACzD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAE,EAAE,CAAC,aAAkC,CAAC,KAAK,CAAC,CAAC,CAAC;AAC3E,CAAC,CAAC,CAAC;AAGH,QAAQ,CAAC,gBAAgB,CAAC,yBAAyB,CAAC,CAAC,OAAO,CAAC,CAAC,QAA0B,EAAE,EAAE;IACxF,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE;QACvC,IAAI,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;QAC/B,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;YACd,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;aAEtB;iBACI,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;gBACxB,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;aAClD;iBACI;gBACD,SAAS,CAAC,GAAG,CAAC,CAAC;aAClB;QACL,CAAC,CAAA;QACD,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE;YACf,SAAS,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC,CAAA;QACD,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,6CAA6C,MAAM,EAAE,CAAC,CAAC;QAC1F,GAAG,CAAC,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QACzD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAE,EAAE,CAAC,aAAkC,CAAC,OAAO,CAAC,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAC;AACH,QAAQ,CAAC,gBAAgB,CAAC,wBAAwB,CAAC,CAAC,OAAO,CAAC,CAAC,WAA8B,EAAE,EAAE;IAC3F,WAAW,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;QACzC,IAAI,MAAM,GAAG,WAAW,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;QAC/B,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;YACd,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;gBACnB,SAAS,CAAC,gBAAgB,EAC1B;;+CAE+B,GAAG,CAAC,YAAY;;;;;;iBAM9C,CAAC,CAAA;aACL;iBACI,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;gBACxB,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;aAClD;iBACI;gBACD,SAAS,CAAC,GAAG,CAAC,CAAC;aAClB;QACL,CAAC,CAAA;QACD,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE;YACf,SAAS,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC,CAAA;QACD,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,QAAQ,CAAC,MAAM,gDAAgD,MAAM,EAAE,CAAC,CAAC;QAC5F,GAAG,CAAC,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QACzD,GAAG,CAAC,IAAI,EAAE,CAAC;IACf,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAC;AACH,QAAQ,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,CAAC,OAAO,CAAC,CAAC,YAA+B,EAAE,EAAE;IACzF,YAAY,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;QAC1C,IAAI,MAAM,GAAG,OAAO,CAAC,4CAA4C,CAAC,CAAC;QACnE,IAAI,MAAM,EAAE;YACR,IAAI,MAAM,GAAG,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAC/C,IAAI,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;YAC/B,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;gBACd,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;oBACnB,QAAQ,CAAC,aAAa,CAAC,YAAY,MAAM,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;iBAC3D;qBACI,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;oBACxB,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;iBAClD;qBACI;oBACD,SAAS,CAAC,GAAG,CAAC,CAAC;iBAClB;YACL,CAAC,CAAA;YACD,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE;gBACf,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC,CAAA;YACD,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,QAAQ,CAAC,MAAM,0CAA0C,MAAM,EAAE,CAAC,CAAC;YACzF,GAAG,CAAC,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;YACzD,GAAG,CAAC,IAAI,EAAE,CAAC;SACd;IACL,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC,OAAO,CAAC,CAAC,YAA+B,EAAE,EAAE;IAC3F,YAAY,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE;QAC1C,YAAY,CAAC,EAAE,CAAC,CAAC;IACrB,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA;AAEF,SAAS,YAAY,CAAC,EAAc;IAChC,IAAI,QAAQ,GAAI,EAAE,CAAC,aAAmC,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC9E,IAAI,GAAG,GAAG,IAAI,cAAc,EAAE,CAAC;IAC/B,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE;QACd,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;YACnB,IAAI,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,cAAc,QAAQ,IAAI,CAAC,CAAC;YAC7D,GAAG,CAAC,MAAM,EAAE,CAAC;SAChB;aACI,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,EAAE;YACxB,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;SAClD;aACI;YACD,SAAS,CAAC,GAAG,CAAC,CAAC;SAClB;IACL,CAAC,CAAA;IACD,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE;QACf,SAAS,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC,CAAA;IACD,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,GAAG,4CAA4C,QAAQ,EAAE,CAAC,CAAC;IAC7F,GAAG,CAAC,gBAAgB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;IACzD,GAAG,CAAC,IAAI,EAAE,CAAC;AACf,CAAC;AACD,SAAS,SAAS,CAAC,GAAmB;IAClC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,SAAS,CAAC,OAAO,EAAE,qCAAqC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAChG,CAAC"} \ No newline at end of file +{"version":3,"file":"OrganizationManagement.js","sourceRoot":"","sources":["OrganizationManagement.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/Server/wwwroot/scripts/Pages/OrganizationManagement.ts b/Server/wwwroot/scripts/Pages/OrganizationManagement.ts index b86ba630..819dbde8 100644 --- a/Server/wwwroot/scripts/Pages/OrganizationManagement.ts +++ b/Server/wwwroot/scripts/Pages/OrganizationManagement.ts @@ -18,6 +18,21 @@ document.getElementById("deviceGroupHelpButton").addEventListener("click", (ev) }); +document.getElementById("addUsersToDeviceGroupButton").addEventListener("click", (ev) => { + var selectList = document.getElementById("deviceGroupList") as HTMLSelectElement; + if (selectList.selectedOptions.length == 0) { + return; + } + if (selectList.selectedOptions.length > 1) { + ShowModal("Device Group Users", "You can only edit users for 1 device group at a time."); + return; + } + + var groupID = selectList.selectedOptions[0].value; + var modalDiv = document.querySelector(`.modal[group='${groupID}']`) as HTMLDivElement; + $(modalDiv).modal("show"); +}); + document.getElementById("removeDeviceGroupButton").addEventListener("click", (ev) => { var selectList = document.getElementById("deviceGroupList") as HTMLSelectElement; for (var i = 0; i < selectList.selectedOptions.length; i++) { @@ -51,34 +66,22 @@ document.getElementById("deviceGroupInput").addEventListener("keypress", (e) => document.getElementById("addDeviceGroupButton").click(); } }) -document.getElementById("addDeviceGroupButton").addEventListener("click", () => { - var input = document.getElementById("deviceGroupInput") as HTMLInputElement; - if (input.checkValidity() && input.value.length > 0) { - var xhr = new XMLHttpRequest(); - xhr.onload = () => { - if (xhr.status == 200) { - document.querySelectorAll(`.all-device-groups-list`).forEach((list: HTMLSelectElement) => { - var newOption = new Option(input.value, xhr.responseText); - list.options.add(newOption); - }) - input.value = ""; - } - else if (xhr.status == 400) { - ShowModal("Invalid Request", xhr.responseText); - } - else { - showError(xhr); - } - } - xhr.onerror = () => { - showError(xhr); - } - xhr.open("post", location.origin + "/api/OrganizationManagement/DeviceGroup"); - xhr.setRequestHeader("Content-Type", "application/json"); - xhr.send(JSON.stringify({ Name: input.value })); +document.querySelectorAll(".remove-user-from-device-group-button").forEach((x:HTMLElement) => { + var groupID = x.getAttribute("group"); + var selectList = document.querySelector(`.modal[group='${groupID}'] select.device-group-user-list`) as HTMLSelectElement; + for (var i = 0; i < selectList.selectedOptions.length; i++) { + // TODO: XHR to remove users and remove from list. } -}) +}); + +document.querySelectorAll(".add-user-to-devicegroup-button").forEach((x: HTMLElement) => { + var groupID = x.getAttribute("group"); + var modal = document.querySelector(`.modal[group='${groupID}']`); + var selectList = modal.querySelector(`select.device-group-user-list`) as HTMLSelectElement; + var userInput = modal.querySelector(`input.add-user-to-devicegroup-input`); + // TODO: XHR to add user to group and add to select list. +}); document.getElementById("organizationNameInput").addEventListener("input", (ev) => { var addon = (ev.currentTarget as HTMLInputElement).parentElement.querySelector(".fa"); diff --git a/Shared/Models/ApiToken.cs b/Shared/Models/ApiToken.cs index 9c7bbac4..2915c4d3 100644 --- a/Shared/Models/ApiToken.cs +++ b/Shared/Models/ApiToken.cs @@ -17,7 +17,7 @@ namespace Remotely.Shared.Models public string Name { get; set; } [JsonIgnore] - public virtual Organization Organization { get; set; } + public Organization Organization { get; set; } public string OrganizationID { get; set; } public string Secret { get; set; } diff --git a/Shared/Models/CommandContext.cs b/Shared/Models/CommandContext.cs index 3cbe1fba..1e022ca5 100644 --- a/Shared/Models/CommandContext.cs +++ b/Shared/Models/CommandContext.cs @@ -19,7 +19,7 @@ namespace Remotely.Shared.Models public ICollection CommandResults { get; set; } = new List(); public DateTime TimeStamp { get; set; } = DateTime.Now; [JsonIgnore] - public virtual Organization Organization { get; set; } + public Organization Organization { get; set; } public string OrganizationID { get; set; } } } diff --git a/Shared/Models/Device.cs b/Shared/Models/Device.cs index 144d7c45..81b5c973 100644 --- a/Shared/Models/Device.cs +++ b/Shared/Models/Device.cs @@ -19,7 +19,7 @@ namespace Remotely.Shared.Models public string Alias { get; set; } public double CpuUtilization { get; set; } public string CurrentUser { get; set; } - public virtual DeviceGroup DeviceGroup { get; set; } + public DeviceGroup DeviceGroup { get; set; } public string DeviceGroupID { get; set; } public string DeviceName { get; set; } public List Drives { get; set; } @@ -37,7 +37,7 @@ namespace Remotely.Shared.Models public DateTime LastOnline { get; set; } [JsonIgnore] - public virtual Organization Organization { get; set; } + public Organization Organization { get; set; } public string OrganizationID { get; set; } public Architecture OSArchitecture { get; set; } diff --git a/Shared/Models/DeviceGroup.cs b/Shared/Models/DeviceGroup.cs index d2c5f1b2..d17aadb5 100644 --- a/Shared/Models/DeviceGroup.cs +++ b/Shared/Models/DeviceGroup.cs @@ -14,11 +14,15 @@ namespace Remotely.Shared.Models [Key] public string ID { get; set; } = Guid.NewGuid().ToString(); - public virtual List Devices { get; set; } + public List Devices { get; set; } + + public List Users { get; set; } [JsonIgnore] public Organization Organization { get; set; } public string OrganizationID { get; set; } + + public List PermissionLinks { get; set; } } } diff --git a/Shared/Models/EventLog.cs b/Shared/Models/EventLog.cs index 56e69874..5dc822fe 100644 --- a/Shared/Models/EventLog.cs +++ b/Shared/Models/EventLog.cs @@ -17,7 +17,7 @@ namespace Remotely.Shared.Models public string OrganizationID { get; set; } public DateTime TimeStamp { get; set; } = DateTime.Now; [JsonIgnore] - public virtual Organization Organization { get; set; } + public Organization Organization { get; set; } } public enum EventType { diff --git a/Shared/Models/InviteLink.cs b/Shared/Models/InviteLink.cs index 65e660d4..37cb8ae6 100644 --- a/Shared/Models/InviteLink.cs +++ b/Shared/Models/InviteLink.cs @@ -14,7 +14,7 @@ namespace Remotely.Shared.Models public bool IsAdmin { get; set; } public DateTime DateSent { get; set; } [JsonIgnore] - public virtual Organization Organization { get; set; } + public Organization Organization { get; set; } public string OrganizationID { get; set; } public string ResetUrl { get; set; } } diff --git a/Shared/Models/Organization.cs b/Shared/Models/Organization.cs index b84de729..5552face 100644 --- a/Shared/Models/Organization.cs +++ b/Shared/Models/Organization.cs @@ -7,24 +7,24 @@ namespace Remotely.Shared.Models { public class Organization { - public virtual ICollection ApiTokens { get; set; } + public ICollection ApiTokens { get; set; } - public virtual ICollection CommandContexts { get; set; } + public ICollection CommandContexts { get; set; } - public virtual ICollection DeviceGroups { get; set; } + public ICollection DeviceGroups { get; set; } - public virtual ICollection Devices { get; set; } + public ICollection Devices { get; set; } - public virtual ICollection EventLogs { get; set; } + public ICollection EventLogs { get; set; } [Key] public string ID { get; set; } = Guid.NewGuid().ToString(); - public virtual ICollection InviteLinks { get; set; } + public ICollection InviteLinks { get; set; } [StringLength(25)] public string OrganizationName { get; set; } - public virtual ICollection RemotelyUsers { get; set; } - public virtual ICollection SharedFiles { get; set; } + public ICollection RemotelyUsers { get; set; } + public ICollection SharedFiles { get; set; } } } \ No newline at end of file diff --git a/Shared/Models/RemotelyUser.cs b/Shared/Models/RemotelyUser.cs index 5b02e3bd..ee6b3c61 100644 --- a/Shared/Models/RemotelyUser.cs +++ b/Shared/Models/RemotelyUser.cs @@ -18,9 +18,11 @@ namespace Remotely.Shared.Models public RemotelyUserOptions UserOptions { get; set; } [JsonIgnore] - public virtual Organization Organization { get; set; } + public Organization Organization { get; set; } public string OrganizationID { get; set; } public bool IsAdministrator { get; set; } = true; + + public List PermissionLinks { get; set; } } } diff --git a/Shared/Models/SharedFile.cs b/Shared/Models/SharedFile.cs index d71b0a07..835830a1 100644 --- a/Shared/Models/SharedFile.cs +++ b/Shared/Models/SharedFile.cs @@ -13,7 +13,7 @@ namespace Remotely.Shared.Models public string ContentType { get; set; } public byte[] FileContents { get; set; } public DateTime Timestamp { get; set; } = DateTime.Now; - public virtual Organization Organization { get; set; } + public Organization Organization { get; set; } public string OrganizationID { get; set; } } } diff --git a/Shared/Models/UserDevicePermission.cs b/Shared/Models/UserDevicePermission.cs new file mode 100644 index 00000000..f9d71733 --- /dev/null +++ b/Shared/Models/UserDevicePermission.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Text; + +namespace Remotely.Shared.Models +{ + public class UserDevicePermission + { + [Key] + public string ID { get; set; } = Guid.NewGuid().ToString(); + + public string UserID { get; set; } + public RemotelyUser User { get; set; } + + public string DeviceGroupID { get; set; } + public DeviceGroup DeviceGroup { get; set; } + } +}