Add Notes property to device.

This commit is contained in:
Jared Goodwin 2020-03-26 20:50:55 -07:00
parent f3e38ed2ed
commit 718ab4c76b
11 changed files with 764 additions and 15 deletions

View File

@ -0,0 +1,712 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Remotely.Server.Data;
namespace Remotely.Server.Migrations
{
[DbContext(typeof(ApplicationDbContext))]
[Migration("20200327034430_Device Notes")]
partial class DeviceNotes
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.2");
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasColumnType("TEXT")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ClaimType")
.HasColumnType("TEXT");
b.Property<string>("ClaimValue")
.HasColumnType("TEXT");
b.Property<string>("RoleId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b =>
{
b.Property<string>("Id")
.HasColumnType("TEXT");
b.Property<int>("AccessFailedCount")
.HasColumnType("INTEGER");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasColumnType("TEXT");
b.Property<string>("Discriminator")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Email")
.HasColumnType("TEXT")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed")
.HasColumnType("INTEGER");
b.Property<bool>("LockoutEnabled")
.HasColumnType("INTEGER");
b.Property<string>("LockoutEnd")
.HasColumnType("TEXT");
b.Property<string>("NormalizedEmail")
.HasColumnType("TEXT")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasColumnType("TEXT")
.HasMaxLength(256);
b.Property<string>("PasswordHash")
.HasColumnType("TEXT");
b.Property<string>("PhoneNumber")
.HasColumnType("TEXT");
b.Property<bool>("PhoneNumberConfirmed")
.HasColumnType("INTEGER");
b.Property<string>("SecurityStamp")
.HasColumnType("TEXT");
b.Property<bool>("TwoFactorEnabled")
.HasColumnType("INTEGER");
b.Property<string>("UserName")
.HasColumnType("TEXT")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("RemotelyUsers");
b.HasDiscriminator<string>("Discriminator").HasValue("IdentityUser");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("ClaimType")
.HasColumnType("TEXT");
b.Property<string>("ClaimValue")
.HasColumnType("TEXT");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasColumnType("TEXT")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasColumnType("TEXT")
.HasMaxLength(128);
b.Property<string>("ProviderDisplayName")
.HasColumnType("TEXT");
b.Property<string>("UserId")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("TEXT");
b.Property<string>("RoleId")
.HasColumnType("TEXT");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId")
.HasColumnType("TEXT");
b.Property<string>("LoginProvider")
.HasColumnType("TEXT")
.HasMaxLength(128);
b.Property<string>("Name")
.HasColumnType("TEXT")
.HasMaxLength(128);
b.Property<string>("Value")
.HasColumnType("TEXT");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("Remotely.Shared.Models.Alert", b =>
{
b.Property<string>("ID")
.HasColumnType("TEXT");
b.Property<string>("CreatedOn")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("DeviceID")
.HasColumnType("TEXT");
b.Property<string>("Message")
.HasColumnType("TEXT");
b.Property<string>("OrganizationID")
.HasColumnType("TEXT");
b.Property<string>("UserID")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("DeviceID");
b.HasIndex("OrganizationID");
b.HasIndex("UserID");
b.ToTable("Alerts");
});
modelBuilder.Entity("Remotely.Shared.Models.ApiToken", b =>
{
b.Property<string>("ID")
.HasColumnType("TEXT");
b.Property<string>("LastUsed")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT")
.HasMaxLength(200);
b.Property<string>("OrganizationID")
.HasColumnType("TEXT");
b.Property<string>("Secret")
.HasColumnType("TEXT");
b.Property<string>("Token")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("OrganizationID");
b.HasIndex("Token");
b.ToTable("ApiTokens");
});
modelBuilder.Entity("Remotely.Shared.Models.CommandResult", b =>
{
b.Property<string>("ID")
.HasColumnType("TEXT");
b.Property<string>("CommandMode")
.HasColumnType("TEXT");
b.Property<string>("CommandResults")
.HasColumnType("TEXT");
b.Property<string>("CommandText")
.HasColumnType("TEXT");
b.Property<string>("OrganizationID")
.HasColumnType("TEXT");
b.Property<string>("PSCoreResults")
.HasColumnType("TEXT");
b.Property<string>("SenderConnectionID")
.HasColumnType("TEXT");
b.Property<string>("SenderUserID")
.HasColumnType("TEXT");
b.Property<string>("TargetDeviceIDs")
.HasColumnType("TEXT");
b.Property<string>("TimeStamp")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("OrganizationID");
b.ToTable("CommandResults");
});
modelBuilder.Entity("Remotely.Shared.Models.Device", b =>
{
b.Property<string>("ID")
.HasColumnType("TEXT");
b.Property<string>("AgentVersion")
.HasColumnType("TEXT");
b.Property<string>("Alias")
.HasColumnType("TEXT")
.HasMaxLength(100);
b.Property<double>("CpuUtilization")
.HasColumnType("REAL");
b.Property<string>("CurrentUser")
.HasColumnType("TEXT");
b.Property<string>("DeviceGroupID")
.HasColumnType("TEXT");
b.Property<string>("DeviceName")
.HasColumnType("TEXT");
b.Property<string>("Drives")
.HasColumnType("TEXT");
b.Property<bool>("Is64Bit")
.HasColumnType("INTEGER");
b.Property<bool>("IsOnline")
.HasColumnType("INTEGER");
b.Property<string>("LastOnline")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Notes")
.HasColumnType("TEXT");
b.Property<int>("OSArchitecture")
.HasColumnType("INTEGER");
b.Property<string>("OSDescription")
.HasColumnType("TEXT");
b.Property<string>("OrganizationID")
.HasColumnType("TEXT");
b.Property<string>("Platform")
.HasColumnType("TEXT");
b.Property<int>("ProcessorCount")
.HasColumnType("INTEGER");
b.Property<string>("ServerVerificationToken")
.HasColumnType("TEXT");
b.Property<string>("Tags")
.HasColumnType("TEXT")
.HasMaxLength(200);
b.Property<double>("TotalMemory")
.HasColumnType("REAL");
b.Property<double>("TotalStorage")
.HasColumnType("REAL");
b.Property<double>("UsedMemory")
.HasColumnType("REAL");
b.Property<double>("UsedStorage")
.HasColumnType("REAL");
b.HasKey("ID");
b.HasIndex("DeviceGroupID");
b.HasIndex("DeviceName");
b.HasIndex("OrganizationID");
b.ToTable("Devices");
});
modelBuilder.Entity("Remotely.Shared.Models.DeviceGroup", b =>
{
b.Property<string>("ID")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT")
.HasMaxLength(200);
b.Property<string>("OrganizationID")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("OrganizationID");
b.ToTable("DeviceGroups");
});
modelBuilder.Entity("Remotely.Shared.Models.EventLog", b =>
{
b.Property<string>("ID")
.HasColumnType("TEXT");
b.Property<int>("EventType")
.HasColumnType("INTEGER");
b.Property<string>("Message")
.HasColumnType("TEXT");
b.Property<string>("OrganizationID")
.HasColumnType("TEXT");
b.Property<string>("Source")
.HasColumnType("TEXT");
b.Property<string>("StackTrace")
.HasColumnType("TEXT");
b.Property<string>("TimeStamp")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("OrganizationID");
b.ToTable("EventLogs");
});
modelBuilder.Entity("Remotely.Shared.Models.InviteLink", b =>
{
b.Property<string>("ID")
.HasColumnType("TEXT");
b.Property<string>("DateSent")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("InvitedUser")
.HasColumnType("TEXT");
b.Property<bool>("IsAdmin")
.HasColumnType("INTEGER");
b.Property<string>("OrganizationID")
.HasColumnType("TEXT");
b.Property<string>("ResetUrl")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("OrganizationID");
b.ToTable("InviteLinks");
});
modelBuilder.Entity("Remotely.Shared.Models.Organization", b =>
{
b.Property<string>("ID")
.HasColumnType("TEXT");
b.Property<string>("OrganizationName")
.HasColumnType("TEXT")
.HasMaxLength(25);
b.HasKey("ID");
b.ToTable("Organizations");
});
modelBuilder.Entity("Remotely.Shared.Models.SharedFile", b =>
{
b.Property<string>("ID")
.HasColumnType("TEXT");
b.Property<string>("ContentType")
.HasColumnType("TEXT");
b.Property<byte[]>("FileContents")
.HasColumnType("BLOB");
b.Property<string>("FileName")
.HasColumnType("TEXT");
b.Property<string>("OrganizationID")
.HasColumnType("TEXT");
b.Property<string>("Timestamp")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("OrganizationID");
b.ToTable("SharedFiles");
});
modelBuilder.Entity("Remotely.Shared.Models.UserDevicePermission", b =>
{
b.Property<string>("ID")
.HasColumnType("TEXT");
b.Property<string>("DeviceGroupID")
.HasColumnType("TEXT");
b.Property<string>("UserID")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("DeviceGroupID");
b.HasIndex("UserID");
b.ToTable("PermissionLinks");
});
modelBuilder.Entity("Remotely.Shared.Models.RemotelyUser", b =>
{
b.HasBaseType("Microsoft.AspNetCore.Identity.IdentityUser");
b.Property<bool>("IsAdministrator")
.HasColumnType("INTEGER");
b.Property<bool>("IsServerAdmin")
.HasColumnType("INTEGER");
b.Property<string>("OrganizationID")
.HasColumnType("TEXT");
b.Property<string>("UserOptions")
.HasColumnType("TEXT");
b.HasIndex("OrganizationID");
b.HasIndex("UserName");
b.HasDiscriminator().HasValue("RemotelyUser");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null)
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Remotely.Shared.Models.Alert", b =>
{
b.HasOne("Remotely.Shared.Models.Device", "Device")
.WithMany("Alerts")
.HasForeignKey("DeviceID");
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
.WithMany("Alerts")
.HasForeignKey("OrganizationID");
b.HasOne("Remotely.Shared.Models.RemotelyUser", "User")
.WithMany("Alerts")
.HasForeignKey("UserID");
});
modelBuilder.Entity("Remotely.Shared.Models.ApiToken", b =>
{
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
.WithMany("ApiTokens")
.HasForeignKey("OrganizationID");
});
modelBuilder.Entity("Remotely.Shared.Models.CommandResult", b =>
{
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
.WithMany("CommandResults")
.HasForeignKey("OrganizationID");
});
modelBuilder.Entity("Remotely.Shared.Models.Device", b =>
{
b.HasOne("Remotely.Shared.Models.DeviceGroup", "DeviceGroup")
.WithMany("Devices")
.HasForeignKey("DeviceGroupID");
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
.WithMany("Devices")
.HasForeignKey("OrganizationID");
});
modelBuilder.Entity("Remotely.Shared.Models.DeviceGroup", b =>
{
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
.WithMany("DeviceGroups")
.HasForeignKey("OrganizationID");
});
modelBuilder.Entity("Remotely.Shared.Models.EventLog", b =>
{
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
.WithMany("EventLogs")
.HasForeignKey("OrganizationID");
});
modelBuilder.Entity("Remotely.Shared.Models.InviteLink", b =>
{
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
.WithMany("InviteLinks")
.HasForeignKey("OrganizationID");
});
modelBuilder.Entity("Remotely.Shared.Models.SharedFile", b =>
{
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
.WithMany("SharedFiles")
.HasForeignKey("OrganizationID");
});
modelBuilder.Entity("Remotely.Shared.Models.UserDevicePermission", b =>
{
b.HasOne("Remotely.Shared.Models.DeviceGroup", "DeviceGroup")
.WithMany("PermissionLinks")
.HasForeignKey("DeviceGroupID");
b.HasOne("Remotely.Shared.Models.RemotelyUser", "User")
.WithMany("PermissionLinks")
.HasForeignKey("UserID");
});
modelBuilder.Entity("Remotely.Shared.Models.RemotelyUser", b =>
{
b.HasOne("Remotely.Shared.Models.Organization", "Organization")
.WithMany("RemotelyUsers")
.HasForeignKey("OrganizationID");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Remotely.Server.Migrations
{
public partial class DeviceNotes : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Notes",
table: "Devices",
nullable: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Notes",
table: "Devices");
}
}
}

View File

@ -357,6 +357,9 @@ namespace Remotely.Server.Migrations
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Notes")
.HasColumnType("TEXT");
b.Property<int>("OSArchitecture")
.HasColumnType("INTEGER");

View File

@ -29,7 +29,7 @@ else
</div>
</div>
<div class="form-group row">
<label for="device-name" class="col-sm-2 col-form-label">Device:</label>
<label for="device-id" class="col-sm-2 col-form-label">Device ID:</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="device-name" readonly value="@Model.DeviceID" />
</div>
@ -63,6 +63,12 @@ else
<input type="text" class="form-control" asp-for="Input.Tags" />
</div>
</div>
<div class="form-group row">
<label for="notes" class="col-sm-2 col-form-label">Notes:</label>
<div class="col-sm-10">
<textarea asp-for="Input.Notes" class="form-control"></textarea>
</div>
</div>
<div class="text-right">
<button type="submit" class="btn btn-primary">Save</button>
<button type="submit" class="btn btn-secondary" onclick="window.close()">Close</button>

View File

@ -57,7 +57,7 @@ namespace Remotely.Server.Pages
return Page();
}
DataService.UpdateDevice(deviceID, Input.Tags, Input.Alias, Input.DeviceGroupID);
DataService.UpdateDevice(deviceID, Input.Tags, Input.Alias, Input.DeviceGroupID, Input.Notes);
return RedirectToPage("EditDevice", new { deviceID, success = true });
}
@ -74,6 +74,7 @@ namespace Remotely.Server.Pages
Input.Alias = device?.Alias;
Input.DeviceGroupID = device?.DeviceGroupID;
Input.Tags = device?.Tags;
Input.Notes = device?.Notes;
}
var groups = DataService.GetDeviceGroups(User.Identity.Name);
@ -89,6 +90,8 @@ namespace Remotely.Server.Pages
[StringLength(200)]
public string Tags { get; set; }
public string Notes { get; set; }
}
}
}

View File

@ -500,7 +500,8 @@ namespace Remotely.Server.Services
return RemotelyContext.Alerts
.Include(x => x.Device)
.Include(x => x.User)
.Where(x => x.UserID == userID);
.Where(x => x.UserID == userID)
.OrderByDescending(x => x.CreatedOn);
}
public IEnumerable<ApiToken> GetAllApiTokens(string userID)
{
@ -611,7 +612,8 @@ namespace Remotely.Server.Services
x.PermissionLinks.Count == 0 ||
x.PermissionLinks.Any(x => x.UserID == user.Id)
)
) ?? Enumerable.Empty<DeviceGroup>();
)
.OrderBy(x=>x.Name) ?? Enumerable.Empty<DeviceGroup>();
}
public IEnumerable<Device> GetDevicesForUser(string userName)
@ -841,7 +843,7 @@ namespace Remotely.Server.Services
}
}
public void UpdateDevice(string deviceID, string tag, string alias, string deviceGroupID)
public void UpdateDevice(string deviceID, string tag, string alias, string deviceGroupID, string notes)
{
var device = RemotelyContext.Devices.Find(deviceID);
if (device == null)
@ -852,6 +854,7 @@ namespace Remotely.Server.Services
device.Tags = tag;
device.DeviceGroupID = deviceGroupID;
device.Alias = alias;
device.Notes = notes;
RemotelyContext.SaveChanges();
}

View File

@ -206,6 +206,8 @@ var commands = [
<li>FreeMemory (between 0 and 1)</li>
<li>TotalMemory (number in GB)</li>
<li>ProcessorCount (number)</li>
<li>Tags (text)</li>
<li>Notes (text)</li>
</ul>`, (parameters, paramDictionary) => {
if (typeof paramDictionary["all"] != "undefined") {
Main.DataGrid.DataSource.forEach(x => {

File diff suppressed because one or more lines are too long

View File

@ -316,6 +316,8 @@ var commands: Array<ConsoleCommand> = [
<li>FreeMemory (between 0 and 1)</li>
<li>TotalMemory (number in GB)</li>
<li>ProcessorCount (number)</li>
<li>Tags (text)</li>
<li>Notes (text)</li>
</ul>`,
(parameters, paramDictionary) => {

View File

@ -10,6 +10,7 @@
Is64Bit: boolean;
IsOnline: boolean;
LastOnline: Date;
Notes: string;
OrganizationID: string;
OSArchitecture: any;
OSDescription: string;

View File

@ -25,26 +25,20 @@ namespace Remotely.Shared.Models
public string DeviceName { get; set; }
public List<Drive> Drives { get; set; }
public double UsedMemory { get; set; }
public double UsedStorage { get; set; }
[Key]
public string ID { get; set; }
public bool Is64Bit { get; set; }
public bool IsOnline { get; set; }
public DateTimeOffset LastOnline { get; set; }
public string Notes { get; set; }
[JsonIgnore]
public Organization Organization { get; set; }
public string OrganizationID { get; set; }
public Architecture OSArchitecture { get; set; }
public string OSDescription { get; set; }
public string Platform { get; set; }
public int ProcessorCount { get; set; }
public string ServerVerificationToken { get; set; }
[StringLength(200)]
@ -52,7 +46,8 @@ namespace Remotely.Shared.Models
public double TotalMemory { get; set; }
public double TotalStorage { get; set; }
public double UsedMemory { get; set; }
public double UsedStorage { get; set; }
}
}