diff --git a/Server/Data/ApplicationDbContext.cs b/Server/Data/ApplicationDbContext.cs index fdec54c8..a9227b17 100644 --- a/Server/Data/ApplicationDbContext.cs +++ b/Server/Data/ApplicationDbContext.cs @@ -109,6 +109,9 @@ namespace Remotely.Server.Data builder.Entity() .HasMany(x => x.PermissionLinks); + builder.Entity() + .HasMany(x => x.Alerts) + .WithOne(x => x.User); builder.Entity() .Property(x => x.UserOptions) @@ -134,6 +137,10 @@ namespace Remotely.Server.Data builder.Entity() .HasIndex(x => x.Token); + builder.Entity() + .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 diff --git a/Server/Migrations/20200325144430_Alerts.Designer.cs b/Server/Migrations/20200325144430_Alerts.Designer.cs new file mode 100644 index 00000000..d0534183 --- /dev/null +++ b/Server/Migrations/20200325144430_Alerts.Designer.cs @@ -0,0 +1,718 @@ +// +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("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.Alert", b => + { + b.Property("ID") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DeviceID") + .HasColumnType("TEXT"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("OrganizationID") + .HasColumnType("TEXT"); + + b.Property("UserIDId") + .HasColumnType("TEXT"); + + b.Property("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("ID") + .HasColumnType("TEXT"); + + b.Property("LastUsed") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT") + .HasMaxLength(200); + + b.Property("OrganizationID") + .HasColumnType("TEXT"); + + b.Property("Secret") + .HasColumnType("TEXT"); + + b.Property("Token") + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("OrganizationID"); + + b.HasIndex("Token"); + + b.ToTable("ApiTokens"); + }); + + modelBuilder.Entity("Remotely.Shared.Models.CommandResult", 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") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("OrganizationID"); + + b.ToTable("CommandResults"); + }); + + 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("CpuUtilization") + .HasColumnType("REAL"); + + b.Property("CurrentUser") + .HasColumnType("TEXT"); + + b.Property("DeviceGroupID") + .HasColumnType("TEXT"); + + b.Property("DeviceName") + .HasColumnType("TEXT"); + + b.Property("Drives") + .HasColumnType("TEXT"); + + b.Property("Is64Bit") + .HasColumnType("INTEGER"); + + b.Property("IsOnline") + .HasColumnType("INTEGER"); + + b.Property("LastOnline") + .IsRequired() + .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.Property("UsedMemory") + .HasColumnType("REAL"); + + b.Property("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("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") + .IsRequired() + .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") + .IsRequired() + .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") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("ID"); + + b.HasIndex("OrganizationID"); + + 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("IsAdministrator") + .HasColumnType("INTEGER"); + + b.Property("IsServerAdmin") + .HasColumnType("INTEGER"); + + b.Property("OrganizationID") + .HasColumnType("TEXT"); + + b.Property("UserOptions") + .HasColumnType("TEXT"); + + b.HasIndex("OrganizationID"); + + b.HasIndex("UserName"); + + 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.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 + } + } +} diff --git a/Server/Migrations/20200325144430_Alerts.cs b/Server/Migrations/20200325144430_Alerts.cs new file mode 100644 index 00000000..faf097c0 --- /dev/null +++ b/Server/Migrations/20200325144430_Alerts.cs @@ -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(nullable: false), + CreatedOn = table.Column(nullable: false), + DeviceID = table.Column(nullable: true), + Message = table.Column(nullable: true), + OrganizationID = table.Column(nullable: true), + UserId = table.Column(nullable: true), + UserIDId = table.Column(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"); + } + } +} diff --git a/Server/Migrations/ApplicationDbContextModelSnapshot.cs b/Server/Migrations/ApplicationDbContextModelSnapshot.cs index 6327d8f3..1a3d4c02 100644 --- a/Server/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/Server/Migrations/ApplicationDbContextModelSnapshot.cs @@ -218,6 +218,43 @@ namespace Remotely.Server.Migrations b.ToTable("AspNetUserTokens"); }); + modelBuilder.Entity("Remotely.Shared.Models.Alert", b => + { + b.Property("ID") + .HasColumnType("TEXT"); + + b.Property("CreatedOn") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DeviceID") + .HasColumnType("TEXT"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("OrganizationID") + .HasColumnType("TEXT"); + + b.Property("UserIDId") + .HasColumnType("TEXT"); + + b.Property("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("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") diff --git a/Server/Services/DataService.cs b/Server/Services/DataService.cs index 4478527e..c3e63aef 100644 --- a/Server/Services/DataService.cs +++ b/Server/Services/DataService.cs @@ -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(); } diff --git a/Shared/Models/Alert.cs b/Shared/Models/Alert.cs index 150a844e..01c1d88e 100644 --- a/Shared/Models/Alert.cs +++ b/Shared/Models/Alert.cs @@ -22,6 +22,8 @@ namespace Remotely.Shared.Models public string OrganizationID { get; set; } - public ICollection SeenBy { get; set; } + [JsonIgnore] + public RemotelyUser User { get; set; } + public RemotelyUser UserID { get; set; } } } diff --git a/Shared/Models/RemotelyUser.cs b/Shared/Models/RemotelyUser.cs index 2af1e2d8..35019f7b 100644 --- a/Shared/Models/RemotelyUser.cs +++ b/Shared/Models/RemotelyUser.cs @@ -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 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 PermissionLinks { get; set; } + public RemotelyUserOptions UserOptions { get; set; } } }