Add Alerts migration.

This commit is contained in:
Jared Goodwin 2020-03-25 07:48:57 -07:00
parent 8dac140f54
commit d4efc1d41d
7 changed files with 872 additions and 7 deletions

View File

@ -109,6 +109,9 @@ namespace Remotely.Server.Data
builder.Entity<RemotelyUser>()
.HasMany(x => x.PermissionLinks);
builder.Entity<RemotelyUser>()
.HasMany(x => x.Alerts)
.WithOne(x => x.User);
builder.Entity<RemotelyUser>()
.Property(x => x.UserOptions)
@ -134,6 +137,10 @@ namespace Remotely.Server.Data
builder.Entity<ApiToken>()
.HasIndex(x => x.Token);
builder.Entity<Alert>()
.HasOne(x => x.User)
.WithMany(x => x.Alerts);
if (Database.ProviderName == "Microsoft.EntityFrameworkCore.Sqlite")
{
// SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations

View File

@ -0,0 +1,718 @@
// <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("20200325144430_Alerts")]
partial class Alerts
{
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>("UserIDId")
.HasColumnType("TEXT");
b.Property<string>("UserId")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("DeviceID");
b.HasIndex("OrganizationID");
b.HasIndex("UserIDId");
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<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", "UserID")
.WithMany()
.HasForeignKey("UserIDId");
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,77 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Remotely.Server.Migrations
{
public partial class Alerts : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Alerts",
columns: table => new
{
ID = table.Column<string>(nullable: false),
CreatedOn = table.Column<string>(nullable: false),
DeviceID = table.Column<string>(nullable: true),
Message = table.Column<string>(nullable: true),
OrganizationID = table.Column<string>(nullable: true),
UserId = table.Column<string>(nullable: true),
UserIDId = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Alerts", x => x.ID);
table.ForeignKey(
name: "FK_Alerts_Devices_DeviceID",
column: x => x.DeviceID,
principalTable: "Devices",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_Alerts_Organizations_OrganizationID",
column: x => x.OrganizationID,
principalTable: "Organizations",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_Alerts_RemotelyUsers_UserIDId",
column: x => x.UserIDId,
principalTable: "RemotelyUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_Alerts_RemotelyUsers_UserId",
column: x => x.UserId,
principalTable: "RemotelyUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_Alerts_DeviceID",
table: "Alerts",
column: "DeviceID");
migrationBuilder.CreateIndex(
name: "IX_Alerts_OrganizationID",
table: "Alerts",
column: "OrganizationID");
migrationBuilder.CreateIndex(
name: "IX_Alerts_UserIDId",
table: "Alerts",
column: "UserIDId");
migrationBuilder.CreateIndex(
name: "IX_Alerts_UserId",
table: "Alerts",
column: "UserId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Alerts");
}
}
}

View File

@ -218,6 +218,43 @@ namespace Remotely.Server.Migrations
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>("UserIDId")
.HasColumnType("TEXT");
b.Property<string>("UserId")
.HasColumnType("TEXT");
b.HasKey("ID");
b.HasIndex("DeviceID");
b.HasIndex("OrganizationID");
b.HasIndex("UserIDId");
b.HasIndex("UserId");
b.ToTable("Alerts");
});
modelBuilder.Entity("Remotely.Shared.Models.ApiToken", b =>
{
b.Property<string>("ID")
@ -584,6 +621,25 @@ namespace Remotely.Server.Migrations
.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", "UserID")
.WithMany()
.HasForeignKey("UserIDId");
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")

View File

@ -36,7 +36,11 @@ namespace Remotely.Server.Services
public async Task AddAlert(Alert alert)
{
RemotelyContext.Alerts.Add(alert);
await RemotelyContext.Users
.Include(x => x.Alerts)
.Where(x => x.OrganizationID == alert.OrganizationID)
.ForEachAsync(x => x.Alerts.Add(alert));
await RemotelyContext.SaveChangesAsync();
}

View File

@ -22,6 +22,8 @@ namespace Remotely.Shared.Models
public string OrganizationID { get; set; }
public ICollection<RemotelyUser> SeenBy { get; set; }
[JsonIgnore]
public RemotelyUser User { get; set; }
public RemotelyUser UserID { get; set; }
}
}

View File

@ -15,14 +15,15 @@ namespace Remotely.Shared.Models
UserOptions = new RemotelyUserOptions();
Organization = new Organization();
}
public RemotelyUserOptions UserOptions { get; set; }
[JsonIgnore]
public Organization Organization { get; set; }
public string OrganizationID { get; set; }
public ICollection<Alert> Alerts { get; set; }
public bool IsAdministrator { get; set; } = true;
public bool IsServerAdmin { get; set; }
[JsonIgnore]
public Organization Organization { get; set; }
public string OrganizationID { get; set; }
public List<UserDevicePermission> PermissionLinks { get; set; }
public RemotelyUserOptions UserOptions { get; set; }
}
}