From 653f0234ca6e3c8936f44b0286fc2e36bc41e73e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Janis=20Daniel=20Da=CC=88hne?= <janis.daehne2@student.uni-halle.de> Date: Thu, 1 Aug 2019 17:14:27 +0200 Subject: [PATCH] - migration wrong fks step 1 --- src/ClientServer/Controllers/Core/Init.cs | 793 +----- src/ClientServer/Db/YapexDbContext.cs | 2 + ...1144540_addFakeFksToOtherSides.Designer.cs | 2159 +++++++++++++++++ .../20190801144540_addFakeFksToOtherSides.cs | 111 + .../Migrations/YapexDbContextModelSnapshot.cs | 41 + .../CustomProjectTestSettings.cs | 42 + .../Exercises/Solution/SolutionAssessment.cs | 5 + .../Models/Exercises/Tests/TestSettings.cs | 6 + .../Models/Users/GroupRolePermission.cs | 4 + .../Users/Settings/CodeEditorSettings.cs | 4 + .../Models/Users/SystemRolePermission.cs | 4 + 11 files changed, 2511 insertions(+), 660 deletions(-) create mode 100755 src/ClientServer/Migrations/20190801144540_addFakeFksToOtherSides.Designer.cs create mode 100755 src/ClientServer/Migrations/20190801144540_addFakeFksToOtherSides.cs create mode 100644 src/ClientServer/Models/CustomProjects/CustomProjectTestSettings.cs diff --git a/src/ClientServer/Controllers/Core/Init.cs b/src/ClientServer/Controllers/Core/Init.cs index a352027..3b7214a 100644 --- a/src/ClientServer/Controllers/Core/Init.cs +++ b/src/ClientServer/Controllers/Core/Init.cs @@ -312,666 +312,139 @@ namespace ClientServer.Controllers.Core } -// [HttpGet("migrate/markdown")] -// public void MigrateMarkdownFiles() -// { -// var basePath = Files.GetUploadFilePath(UploadDirType.MarkdownAssets); -// -// var exDescriptions = _context.ExerciseDescriptions -// .Include(p => p.Assets) -// .Where(p => p.Assets.Count > 0) -// .ToList() -// ; -// -// int count = 0; -// foreach (var exerciseDescription in exDescriptions) -// { -// foreach (var descriptionAsset in exerciseDescription.Assets) -// { -// //create the real file -// -// try -// { -// using (var transaction = _context.Database.BeginTransaction()) -// { -// try -// { -// var fileRef = new FileReferenceMarkdownAsset() -// { -// OriginalName = descriptionAsset.DisplayName, -// CreatedAt = (DateTime) _context.Entry(descriptionAsset) -// .Property(YapexDbContext.CreatedAt) -// .CurrentValue, -// LastUpdatedAt = (DateTime) _context.Entry(descriptionAsset) -// .Property(YapexDbContext.LastUpdatedAt).CurrentValue, -// MimeType = descriptionAsset.MimeType, -// SizeInBytes = descriptionAsset.Content.Length, -// Hash = "", -// }; -// -// var conn = new ExerciseDescriptionWithFileAsAssetReference() -// { -// ExerciseDescription = exerciseDescription, -// FileReferenceMarkdownAsset = fileRef -// }; -// -// _context.ExerciseDescriptionWithFileAsAssetReferences.Add(conn); -// _context.SaveChanges(); -// -// if (fileRef.Id <= 0) -// { -// throw new Exception("fileRef must be tracked in db context"); -// } -// -// try -// { -// var info = new FileInfo(Path.Combine(basePath, fileRef.Id.ToString())); -// -// if (info.Exists) -// { -// throw new Exception("file already exists"); -// } -// -// using (var stream = new FileStream(info.FullName, FileMode.Create)) -// { -// stream.Write(descriptionAsset.Content, 0, descriptionAsset.Content.Length); -// -// using (var md5 = MD5.Create()) -// { -// var result = md5.ComputeHash(descriptionAsset.Content); -// fileRef.Hash = String.Join(String.Empty, -// result.Select(p => p.ToString("x2"))); -// } -// } -// } -// catch (Exception e) -// { -// Console.WriteLine( -// $"[ERROR] error creating file name: {descriptionAsset.DisplayName}"); -// Console.WriteLine(e.Message); -// throw; -// } -// -// -// _context.SaveChanges(); -// transaction.Commit(); -// } -// catch (Exception e) -// { -// transaction.Rollback(); -// Console.WriteLine(e); -// throw; -// } -// } -// -// count++; -// } -// catch (Exception e) -// { -// Console.WriteLine(e); -// throw; -// } -// } -// } -// -// -// Response.WriteAsync("OK -" + count); -// } -// -// -// [HttpGet("migrate/ex/markdown")] -// public void MigrateMarkdownExerciseDescriptionContent() -// { -// var allDescriptions = _context.ExerciseDescriptions -// .Include(p => p.AssetReferences) -// .ThenInclude(p => p.FileReferenceMarkdownAsset) -// .Include(p => p.Assets) -// .ToList(); -// -// -// int count = 0; -// int count2 = 0; -// -// using (var transaction = _context.Database.BeginTransaction()) -// { -// try -// { -// foreach (var exerciseDescription in allDescriptions) -// { -// if (exerciseDescription.Content.Contains(Constants.MarkdownAssetFileUrlPrefix)) -// { -// -// foreach (var asset in exerciseDescription.Assets) -// { -// //find asset ref -// -// var assetRef = exerciseDescription.AssetReferences.FirstOrDefault(p => -// p.FileReferenceMarkdownAsset.OriginalName == asset.DisplayName && -// p.FileReferenceMarkdownAsset.SizeInBytes == asset.Content.Length); -// -// if (assetRef == null) -// { -// throw new Exception($"could not find asset ref for asset id {asset.Id} for ex desc {exerciseDescription.Id}"); -// } -// -// exerciseDescription.Content = exerciseDescription.Content.Replace(asset.AssetUrl, -// Constants.MarkdownAssetFileUrlPrefix + assetRef.FileReferenceMarkdownAssetId); -// count2++; -// } -// -// count++; -// -// } -// } -// -// _context.SaveChanges(); -// transaction.Commit(); -// } -// catch (Exception e) -// { -// transaction.Rollback(); -// Console.WriteLine(e); -// throw; -// } -// } -// -// -// Response.WriteAsync($"OK - {count} - ${count2}"); -// } -// -// -// [HttpGet("migrate/tests")] -// public void MigrateTestFiles() -// { -// var basePath = Files.GetUploadFilePath(UploadDirType.TestAssets); -// -// var testsWithAssets = _context.Tests -// .Include(p => p.TestAssets) -// .Where(p => p.TestAssets.Count > 0) -// .ToList() -// ; -// -// int count = 0; -// foreach (var testWithAsset in testsWithAssets) -// { -// foreach (var testAsset in testWithAsset.TestAssets) -// { -// //create the real file -// -// try -// { -// using (var transaction = _context.Database.BeginTransaction()) -// { -// try -// { -// var fileRef = new FileReferenceTestAsset() -// { -// OriginalName = testAsset.DisplayName, -// CreatedAt = (DateTime) _context.Entry(testAsset) -// .Property(YapexDbContext.CreatedAt) -// .CurrentValue, -// LastUpdatedAt = (DateTime) _context.Entry(testAsset) -// .Property(YapexDbContext.LastUpdatedAt).CurrentValue, -// MimeType = testAsset.MimeType, -// SizeInBytes = testAsset.Content.Length, -// Hash = "", -// }; -// -// var conn = new TestWithFileAsAssetReference() -// { -// Test = testWithAsset, -// FileReferenceTestAsset = fileRef -// }; -// -// _context.TestWithFileAsAssetReferences.Add(conn); -// _context.SaveChanges(); -// -// if (fileRef.Id <= 0) -// { -// throw new Exception("fileRef must be tracked in db context"); -// } -// -// try -// { -// var info = new FileInfo(Path.Combine(basePath, fileRef.Id.ToString())); -// -// if (info.Exists) -// { -// throw new Exception($"file already exists: {info.FullName}"); -// } -// -// using (var stream = new FileStream(info.FullName, FileMode.Create)) -// { -// stream.Write(testAsset.Content, 0, testAsset.Content.Length); -// -// using (var md5 = MD5.Create()) -// { -// var result = md5.ComputeHash(testAsset.Content); -// fileRef.Hash = String.Join(String.Empty, -// result.Select(p => p.ToString("x2"))); -// } -// } -// } -// catch (Exception e) -// { -// Console.WriteLine( -// $"[ERROR] error creating file name: {testAsset.DisplayName}"); -// Console.WriteLine(e.Message); -// throw; -// } -// -// -// _context.SaveChanges(); -// transaction.Commit(); -// } -// catch (Exception e) -// { -// transaction.Rollback(); -// Console.WriteLine(e); -// throw; -// } -// } -// -// count++; -// } -// catch (Exception e) -// { -// Console.WriteLine(e); -// throw; -// } -// } -// } -// -// -// Response.WriteAsync("OK -" + count); -// } -// -// -// [HttpGet("migrate/custom/tests")] -// public void MigrateCustomTestAssets() -// { -// var basePath = Files.GetUploadFilePath(UploadDirType.UserAssets); -// -// var testsWithAssets = _context.CustomTest -// .Include(p => p.TestAssets) -// .Where(p => p.TestAssets.Count > 0) -// .ToList() -// ; -// -// int count = 0; -// -// foreach (var customTest in testsWithAssets) -// { -// foreach (var customTestAsset in customTest.TestAssets) -// { -// //create the real file -// -// try -// { -// using (var transaction = _context.Database.BeginTransaction()) -// { -// try -// { -// var fileRef = new FileReferenceUserFileAsset() -// { -// OriginalName = customTestAsset.DisplayName, -// CreatedAt = (DateTime) _context.Entry(customTestAsset) -// .Property(YapexDbContext.CreatedAt) -// .CurrentValue, -// LastUpdatedAt = (DateTime) _context.Entry(customTestAsset) -// .Property(YapexDbContext.LastUpdatedAt).CurrentValue, -// MimeType = customTestAsset.MimeType, -// SizeInBytes = customTestAsset.Content.Length, -// Hash = "", -// }; -// -// var conn = new CustomTestWithFileAsAssetReference() -// { -// CustomTest = customTest, -// FileReferenceUserFileAsset = fileRef -// }; -// -// _context.CustomTestWithFileAsAssetReferences.Add(conn); -// _context.SaveChanges(); -// -// if (fileRef.Id <= 0) -// { -// throw new Exception("fileRef must be tracked in db context"); -// } -// -// try -// { -// var info = new FileInfo(Path.Combine(basePath, fileRef.Id.ToString())); -// -// if (info.Exists) -// { -// throw new Exception($"file already exists: {info.FullName}"); -// } -// -// using (var stream = new FileStream(info.FullName, FileMode.Create)) -// { -// stream.Write(customTestAsset.Content, 0, customTestAsset.Content.Length); -// -// using (var md5 = MD5.Create()) -// { -// var result = md5.ComputeHash(customTestAsset.Content); -// fileRef.Hash = String.Join(String.Empty, -// result.Select(p => p.ToString("x2"))); -// } -// } -// } -// catch (Exception e) -// { -// Console.WriteLine( -// $"[ERROR] error creating file name: {customTestAsset.DisplayName}"); -// Console.WriteLine(e.Message); -// throw; -// } -// -// -// _context.SaveChanges(); -// transaction.Commit(); -// } -// catch (Exception e) -// { -// transaction.Rollback(); -// Console.WriteLine(e); -// throw; -// } -// } -// -// count++; -// } -// catch (Exception e) -// { -// Console.WriteLine(e); -// throw; -// } -// } -// -// } -// -// Response.WriteAsync("OK -" + count); -// -// } -// -// -// [HttpGet("migrate/custom/project/description")] -// public void MigrateCustomProjectDescriptionAssets() -// { -// var basePath = Files.GetUploadFilePath(UploadDirType.UserAssets); -// -// var customProjectDescriptions = _context.CustomProjectDescriptions -// .Include(p => p.Assets) -// .Where(p => p.Assets.Count > 0) -// .ToList() -// ; -// -// int count = 0; -// -// foreach (var customProjectDescription in customProjectDescriptions) -// { -// foreach (var customAsset in customProjectDescription.Assets) -// { -// //create the real file -// -// try -// { -// using (var transaction = _context.Database.BeginTransaction()) -// { -// try -// { -// var fileRef = new FileReferenceUserFileAsset() -// { -// OriginalName = customAsset.DisplayName, -// CreatedAt = (DateTime) _context.Entry(customAsset) -// .Property(YapexDbContext.CreatedAt) -// .CurrentValue, -// LastUpdatedAt = (DateTime) _context.Entry(customAsset) -// .Property(YapexDbContext.LastUpdatedAt).CurrentValue, -// MimeType = customAsset.MimeType, -// SizeInBytes = customAsset.Content.Length, -// Hash = "", -// }; -// -// var conn = new CustomProjectDescriptionWithFileAsAssetReference() -// { -// CustomProjectDescription = customProjectDescription, -// FileReferenceUserFileAsset = fileRef -// }; -// -// _context.CustomProjectDescriptionWithFileAsAssetReferences.Add(conn); -// _context.SaveChanges(); -// -// if (fileRef.Id <= 0) -// { -// throw new Exception("fileRef must be tracked in db context"); -// } -// -// try -// { -// var info = new FileInfo(Path.Combine(basePath, fileRef.Id.ToString())); -// -// if (info.Exists) -// { -// throw new Exception($"file already exists: {info.FullName}"); -// } -// -// using (var stream = new FileStream(info.FullName, FileMode.Create)) -// { -// stream.Write(customAsset.Content, 0, customAsset.Content.Length); -// -// using (var md5 = MD5.Create()) -// { -// var result = md5.ComputeHash(customAsset.Content); -// fileRef.Hash = String.Join(String.Empty, -// result.Select(p => p.ToString("x2"))); -// } -// } -// } -// catch (Exception e) -// { -// Console.WriteLine( -// $"[ERROR] error creating file name: {customAsset.DisplayName}"); -// Console.WriteLine(e.Message); -// throw; -// } -// -// -// _context.SaveChanges(); -// transaction.Commit(); -// } -// catch (Exception e) -// { -// transaction.Rollback(); -// Console.WriteLine(e); -// throw; -// } -// } -// -// count++; -// } -// catch (Exception e) -// { -// Console.WriteLine(e); -// throw; -// } -// } -// -// } -// -// Response.WriteAsync("OK -" + count); -// -// } -// -// [HttpGet("migrate/custom/project/markdown")] -// public void MigrateMarkdownCustomProjectDescriptionContent() -// { -// -// var allDescriptions = _context.CustomProjectDescriptions -// .Include(p => p.AssetReferences) -// .ThenInclude(p => p.FileReferenceUserFileAsset) -// .Include(p => p.Assets) -// .ToList(); -// -// -// int count = 0; -// int count2 = 0; -// -// using (var transaction = _context.Database.BeginTransaction()) -// { -// try -// { -// foreach (var customProjectDescription in allDescriptions) -// { -// if (customProjectDescription.Content.Contains(Constants.MarkdownAssetFileUrlPrefix)) -// { -// -// foreach (var asset in customProjectDescription.Assets) -// { -// //find asset ref -// -// var assetRef = customProjectDescription.AssetReferences.FirstOrDefault(p => -// p.FileReferenceUserFileAsset.OriginalName == asset.DisplayName && -// p.FileReferenceUserFileAsset.SizeInBytes == asset.Content.Length); -// -// if (assetRef == null) -// { -// throw new Exception($"could not find asset ref for asset id {asset.Id} for ex desc {customProjectDescription.Id}"); -// } -// -// customProjectDescription.Content = customProjectDescription.Content.Replace(asset.AssetUrl, -// Constants.MarkdownAssetFileUrlPrefix + assetRef.FileReferenceUserFileAssetId); -// count2++; -// } -// -// count++; -// -// } -// } -// -// _context.SaveChanges(); -// transaction.Commit(); -// } -// catch (Exception e) -// { -// transaction.Rollback(); -// Console.WriteLine(e); -// throw; -// } -// } -// -// -// Response.WriteAsync($"OK - {count} - ${count2}"); -// } -// -// [HttpGet("migrate/custom/project/tests")] -// public void MigrateCustomProjectTestAssets() -// { -// var basePath = Files.GetUploadFilePath(UploadDirType.UserAssets); -// -// var testsWithAssets = _context.CustomProjectTests -// .Include(p => p.TestAssets) -// .Where(p => p.TestAssets.Count > 0) -// .ToList() -// ; -// -// int count = 0; -// -// foreach (var customProjectTest in testsWithAssets) -// { -// foreach (var customProjectTestAsset in customProjectTest.TestAssets) -// { -// //create the real file -// -// try -// { -// using (var transaction = _context.Database.BeginTransaction()) -// { -// try -// { -// var fileRef = new FileReferenceUserFileAsset() -// { -// OriginalName = customProjectTestAsset.DisplayName, -// CreatedAt = (DateTime) _context.Entry(customProjectTestAsset) -// .Property(YapexDbContext.CreatedAt) -// .CurrentValue, -// LastUpdatedAt = (DateTime) _context.Entry(customProjectTestAsset) -// .Property(YapexDbContext.LastUpdatedAt).CurrentValue, -// MimeType = customProjectTestAsset.MimeType, -// SizeInBytes = customProjectTestAsset.Content.Length, -// Hash = "", -// }; -// -// var conn = new CustomProjectTestWithFileAsAssetReference() -// { -// CustomProjectTest = customProjectTest, -// FileReferenceUserFileAsset = fileRef -// }; -// -// _context.CustomProjectTestWithFileAsAssetReferences.Add(conn); -// _context.SaveChanges(); -// -// if (fileRef.Id <= 0) -// { -// throw new Exception("fileRef must be tracked in db context"); -// } -// -// try -// { -// var info = new FileInfo(Path.Combine(basePath, fileRef.Id.ToString())); -// -// if (info.Exists) -// { -// throw new Exception($"file already exists: {info.FullName}"); -// } -// -// using (var stream = new FileStream(info.FullName, FileMode.Create)) -// { -// stream.Write(customProjectTestAsset.Content, 0, customProjectTestAsset.Content.Length); -// -// using (var md5 = MD5.Create()) -// { -// var result = md5.ComputeHash(customProjectTestAsset.Content); -// fileRef.Hash = String.Join(String.Empty, -// result.Select(p => p.ToString("x2"))); -// } -// } -// } -// catch (Exception e) -// { -// Console.WriteLine( -// $"[ERROR] error creating file name: {customProjectTestAsset.DisplayName}"); -// Console.WriteLine(e.Message); -// throw; -// } -// -// -// _context.SaveChanges(); -// transaction.Commit(); -// } -// catch (Exception e) -// { -// transaction.Rollback(); -// Console.WriteLine(e); -// throw; -// } -// } -// -// count++; -// } -// catch (Exception e) -// { -// Console.WriteLine(e); -// throw; -// } -// } -// -// } -// -// Response.WriteAsync("OK -" + count); -// -// } + [HttpGet("migrate/addfks")] + public void MigrateMarkdownFiles() + { + var systemRoles = _context.SystemRoles + .Include(p => p.SystemRolePermission) + .ToList(); + + foreach (var systemRole in systemRoles) + { + systemRole.SystemRolePermission.SystemRoleId = systemRole.Id; + } + + + var groupRoles = _context.GroupRoles + .Include(p => p.GroupRolePermission) + .ToList() + ; + + foreach (var groupRole in groupRoles) + { + groupRole.GroupRolePermission.GroupRoleId = groupRole.Id; + } + + + var userSettings = _context.UserSettingses + .Include(p => p.CodeEditorSetting) + .ToList(); + + foreach (var userSetting in userSettings) + { + userSetting.CodeEditorSetting.UserSettingId = userSetting.Id; + } + + + var solutions = _context.Solutions + .Include(p => p.Assessment) + .ToList(); + + solutions = solutions.Where(p => p.Assessment != null).ToList(); + + foreach (var solution in solutions) + { + solution.Assessment.PLangId = solution.PLangId; + solution.Assessment.UserId = solution.UserId; + solution.Assessment.ExerciseReleaseId = solution.ExerciseReleaseId; + } + + + var allTestSettings = _context.TestCaseSettingses.ToList(); + + + + var allValidTestSettingsIds = new List<int>(); + + var exTests = _context.Tests + .Include(p => p.TestSettings) + .ToList() + ; + + foreach (var exTest in exTests) + { + exTest.TestSettings.TestId = exTest.Id; + allValidTestSettingsIds.Add(exTest.TestSettings.Id); + } + + //we need to delete the old test settings... BUT it has on delete cascade + //so first migrate then drop the constraint and then remove the old test settings... + var customProjectTests = _context.CustomProjectTests + .Include(p => p.TestSettings) + .ToList(); + + + foreach (var customProjectTest in customProjectTests) + { + var customProjectTestSettings = new CustomProjectTestSettings() + { + Id = customProjectTest.TestSettings.Id, + CompileTimeoutInMs = customProjectTest.TestSettings.CompileTimeoutInMs, + CompilerOptions = customProjectTest.TestSettings.CompilerOptions, + TimeoutInMs = customProjectTest.TestSettings.TimeoutInMs, + MemoryLimitInKb = customProjectTest.TestSettings.MemoryLimitInKb, + MaxDiskSpaceInKb = customProjectTest.TestSettings.MaxDiskSpaceInKb, + CustomProjectTestId = customProjectTest.Id + }; + + _context.CustomProjectTestSettings.Add(customProjectTestSettings); + allValidTestSettingsIds.Add(customProjectTest.TestSettings.Id); + } + + + var count1 = exTests.Count + customProjectTests.Count; + var removedCount = 0; + + + //because we have the delete cascade on the wrong side... we never delete test settings... + foreach (var allTestSetting in allTestSettings) + { + + if (allValidTestSettingsIds.Contains(allTestSetting.Id)) + { + //valid + } + else + { + _context.TestCaseSettingses.Remove(allTestSetting); + removedCount++; + } + } + + var newCount2 = allTestSettings.Count - removedCount; + if (newCount2 != count1) + { + Response.WriteAsync("wrong"); + return; + } + + int rows; + try + { + rows = _context.SaveChanges(); + } + catch (Exception e) + { + Console.WriteLine(e); + throw; + } + + + Response.WriteAsync("OK -" + rows); + } + + //remove test case settings fk on delete cascade... because when we add the new CustomProjectTestSettings we want to delete the old + } } diff --git a/src/ClientServer/Db/YapexDbContext.cs b/src/ClientServer/Db/YapexDbContext.cs index 01889b4..88862aa 100644 --- a/src/ClientServer/Db/YapexDbContext.cs +++ b/src/ClientServer/Db/YapexDbContext.cs @@ -69,6 +69,7 @@ namespace ClientServer.Db public DbSet<CustomProjectSolution> CustomProjectSolutions { get; set; } public DbSet<CustomProjectSolutionFile> CustomProjectSolutionFiles { get; set; } public DbSet<CustomProjectTest> CustomProjectTests { get; set; } + public DbSet<CustomProjectTestSettings> CustomProjectTestSettings { get; set; } public DbSet<CustomProjectTestWithSolutionAsTestResult> CustomProjectTestWithSolutionAsTestResults { get; set; } public DbSet<CustomProjectTestAsset> CustomProjectTestAssets { get; set; } @@ -155,6 +156,7 @@ namespace ClientServer.Db typeof(CustomProjectSolution), typeof(CustomProjectSolutionFile), typeof(CustomProjectTest), + typeof(CustomProjectTestSettings), typeof(CustomProjectTestWithSolutionAsTestResult), typeof(CustomProjectTestAsset), diff --git a/src/ClientServer/Migrations/20190801144540_addFakeFksToOtherSides.Designer.cs b/src/ClientServer/Migrations/20190801144540_addFakeFksToOtherSides.Designer.cs new file mode 100755 index 0000000..a3cd140 --- /dev/null +++ b/src/ClientServer/Migrations/20190801144540_addFakeFksToOtherSides.Designer.cs @@ -0,0 +1,2159 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using ClientServer.Db; +using ClientServer.Models.Exercises.Release; + +namespace ClientServer.Migrations +{ + [DbContext(typeof(YapexDbContext))] + [Migration("20190801144540_addFakeFksToOtherSides")] + partial class addFakeFksToOtherSides + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.0.3"); + + modelBuilder.Entity("ClientServer.Models.AwaitDummy", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.HasKey("Id"); + + b.ToTable("AwaitDummies"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProject", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<int>("LastEditorPLangId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("CustomProjects"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectDescription", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Content") + .HasMaxLength(50000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("CustomProjectId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.HasIndex("CustomProjectId") + .IsUnique(); + + b.ToTable("CustomProjectDescriptions"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectDescriptionWithFileAsAssetReference", b => + { + b.Property<int>("CustomProjectDescriptionId"); + + b.Property<int>("FileReferenceUserFileAssetId"); + + b.HasKey("CustomProjectDescriptionId", "FileReferenceUserFileAssetId"); + + b.HasIndex("CustomProjectDescriptionId"); + + b.HasIndex("FileReferenceUserFileAssetId"); + + b.ToTable("CustomProjectDescriptionWithFileAsAssetReferences"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectSolution", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("CustomProjectId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int?>("MainFileId"); + + b.Property<int>("PLangId"); + + b.HasKey("Id"); + + b.HasIndex("CustomProjectId"); + + b.HasIndex("MainFileId") + .IsUnique(); + + b.HasIndex("PLangId"); + + b.ToTable("CustomProjectSolutions"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectSolutionFile", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Content") + .HasMaxLength(70000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int?>("CustomProjectSolutionId") + .IsRequired(); + + b.Property<int>("DisplayIndex"); + + b.Property<string>("FileNameWithExtension") + .HasMaxLength(2000); + + b.Property<bool>("IsDisplayed"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.HasIndex("CustomProjectSolutionId"); + + b.ToTable("CustomProjectSolutionFiles"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectTest", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Content") + .HasMaxLength(80000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("CustomProjectId"); + + b.Property<int>("DisplayIndex"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("TestSettingsId"); + + b.Property<int>("TestTypeId"); + + b.Property<int>("Weight"); + + b.HasKey("Id"); + + b.HasIndex("CustomProjectId"); + + b.HasIndex("TestSettingsId") + .IsUnique(); + + b.HasIndex("TestTypeId"); + + b.ToTable("CustomProjectTests"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectTestAsset", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<byte[]>("Content"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<string>("Hash") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<string>("MimeType") + .HasMaxLength(2000); + + b.HasKey("Id"); + + b.ToTable("CustomProjectTestAssets"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectTestSettings", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<int>("CompileTimeoutInMs"); + + b.Property<string>("CompilerOptions") + .HasMaxLength(2000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("CustomProjectTestId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("MaxDiskSpaceInKb"); + + b.Property<int>("MemoryLimitInKb"); + + b.Property<int>("TimeoutInMs"); + + b.HasKey("Id"); + + b.ToTable("CustomProjectTestSettings"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectTestWithFileAsAssetReference", b => + { + b.Property<int>("CustomProjectTestId"); + + b.Property<int>("FileReferenceUserFileAssetId"); + + b.HasKey("CustomProjectTestId", "FileReferenceUserFileAssetId"); + + b.HasIndex("CustomProjectTestId"); + + b.HasIndex("FileReferenceUserFileAssetId"); + + b.ToTable("CustomProjectTestWithFileAsAssetReferences"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectTestWithSolutionAsTestResult", b => + { + b.Property<int>("CustomProjectSolutionId"); + + b.Property<int>("CustomProjectTestId"); + + b.Property<bool>("CharacterLimitExceeded"); + + b.Property<int?>("CharacterLimitUsed"); + + b.Property<int?>("CompileTimeoutInMsUsed"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<bool?>("HasCompiled"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<bool?>("Passed"); + + b.Property<int?>("ProgramExitCode"); + + b.Property<string>("Protocol") + .HasMaxLength(160100); + + b.Property<string>("RunnerVersion") + .HasMaxLength(2000); + + b.Property<int?>("TestResultCode"); + + b.Property<string>("TestServerVersion") + .HasMaxLength(2000); + + b.Property<int?>("TimeForCompiling"); + + b.Property<int?>("TimeForUserProgram"); + + b.Property<int?>("TimeoutInMsUsed"); + + b.HasKey("CustomProjectSolutionId", "CustomProjectTestId"); + + b.HasIndex("CustomProjectSolutionId"); + + b.HasIndex("CustomProjectTestId"); + + b.ToTable("CustomProjectTestWithSolutionAsTestResults"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.AfterSolutions.AfterSolution", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int?>("MainFileId"); + + b.Property<int>("SolutionExerciseReleaseId"); + + b.Property<int>("SolutionPLangId"); + + b.Property<int>("SolutionUserId"); + + b.HasKey("Id"); + + b.HasIndex("MainFileId") + .IsUnique(); + + b.HasIndex("SolutionUserId", "SolutionExerciseReleaseId", "SolutionPLangId") + .IsUnique(); + + b.ToTable("AfterSolutions"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.AfterSolutions.AfterSolutionFile", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<int>("AfterSolutionId"); + + b.Property<string>("Content") + .HasMaxLength(70000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("DisplayIndex"); + + b.Property<string>("FileNameWithExtension") + .HasMaxLength(2000); + + b.Property<bool>("IsDisplayed"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int?>("TemplateFileId"); + + b.HasKey("Id"); + + b.HasIndex("AfterSolutionId"); + + b.HasIndex("TemplateFileId"); + + b.ToTable("AfterSolutionFiles"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.AfterSolutions.CustomTestWithAfterSolutionAsTestResult", b => + { + b.Property<int>("CustomTestId"); + + b.Property<int>("AfterSolutionId"); + + b.Property<bool>("CharacterLimitExceeded"); + + b.Property<int?>("CharacterLimitUsed"); + + b.Property<int?>("CompileTimeoutInMsUsed"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<bool?>("HasCompiled"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<bool?>("Passed"); + + b.Property<int?>("ProgramExitCode"); + + b.Property<string>("Protocol") + .HasMaxLength(160100); + + b.Property<string>("RunnerVersion") + .HasMaxLength(2000); + + b.Property<int?>("TestResultCode"); + + b.Property<string>("TestServerVersion") + .HasMaxLength(2000); + + b.Property<int?>("TimeForCompiling"); + + b.Property<int?>("TimeForUserProgram"); + + b.Property<int?>("TimeoutInMsUsed"); + + b.HasKey("CustomTestId", "AfterSolutionId"); + + b.HasIndex("AfterSolutionId"); + + b.HasIndex("CustomTestId"); + + b.ToTable("CustomTestWithAfterSolutionAsTestResults"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.AfterSolutions.TestWithAfterSolutionAsTestResult", b => + { + b.Property<int>("TestId"); + + b.Property<int>("AfterSolutionId"); + + b.Property<bool>("CharacterLimitExceeded"); + + b.Property<int?>("CharacterLimitUsed"); + + b.Property<int?>("CompileTimeoutInMsUsed"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<bool?>("HasCompiled"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<bool?>("Passed"); + + b.Property<int?>("ProgramExitCode"); + + b.Property<string>("Protocol") + .HasMaxLength(160100); + + b.Property<string>("RunnerVersion") + .HasMaxLength(2000); + + b.Property<int?>("TestResultCode"); + + b.Property<string>("TestServerVersion") + .HasMaxLength(2000); + + b.Property<int?>("TimeForCompiling"); + + b.Property<int?>("TimeForUserProgram"); + + b.Property<int?>("TimeoutInMsUsed"); + + b.HasKey("TestId", "AfterSolutionId"); + + b.HasIndex("AfterSolutionId"); + + b.HasIndex("TestId"); + + b.ToTable("TestWithAfterSolutionAsTestResults"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.CodeTemplate", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("ExerciseId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int?>("MainFileId"); + + b.Property<int>("PLangId"); + + b.HasKey("Id"); + + b.HasIndex("ExerciseId"); + + b.HasIndex("MainFileId") + .IsUnique(); + + b.HasIndex("PLangId"); + + b.ToTable("Templates"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.CustomTestWithFileAsAssetReference", b => + { + b.Property<int>("CustomTestId"); + + b.Property<int>("FileReferenceUserFileAssetId"); + + b.HasKey("CustomTestId", "FileReferenceUserFileAssetId"); + + b.HasIndex("CustomTestId"); + + b.HasIndex("FileReferenceUserFileAssetId"); + + b.ToTable("CustomTestWithFileAsAssetReferences"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Exercise", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<bool>("CanUserCreateCustomTests"); + + b.Property<bool>("CanUserCreateFiles"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<bool>("IsOnlyVisibleToOwner"); + + b.Property<bool>("IsPermanentlyLocked"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<string>("Note") + .HasMaxLength(10000); + + b.Property<string>("ShortDescription") + .HasMaxLength(2000); + + b.Property<int>("UserGroupId"); + + b.Property<int?>("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserGroupId"); + + b.HasIndex("UserId"); + + b.ToTable("Exercises"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.ExerciseDescription", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Content") + .HasMaxLength(50000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("ExerciseId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.HasIndex("ExerciseId") + .IsUnique(); + + b.ToTable("ExerciseDescriptions"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.ExerciseDescriptionWithFileAsAssetReference", b => + { + b.Property<int>("ExerciseDescriptionId"); + + b.Property<int>("FileReferenceMarkdownAssetId"); + + b.HasKey("ExerciseDescriptionId", "FileReferenceMarkdownAssetId"); + + b.HasIndex("ExerciseDescriptionId"); + + b.HasIndex("FileReferenceMarkdownAssetId"); + + b.ToTable("ExerciseDescriptionWithFileAsAssetReferences"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.MetaData", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("ExerciseId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.HasIndex("ExerciseId") + .IsUnique(); + + b.ToTable("MetaDatas"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Release.ExerciseRelease", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime?>("AutomaticEndAt"); + + b.Property<DateTime?>("AutomaticStartAt"); + + b.Property<int>("AvailableWorkingTimeInMinutes"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("ExerciseId"); + + b.Property<string>("GeneratedCode") + .IsRequired() + .HasMaxLength(2000); + + b.Property<bool>("HadAutomaticAssessmentErrors"); + + b.Property<bool>("HasAutomaticAssessmentFinished"); + + b.Property<bool>("HasAutomaticAssessmentStarted"); + + b.Property<bool>("HasLimitedWorkingTime"); + + b.Property<bool>("HideExerciseLeaveActions"); + + b.Property<bool>("HideInOverviews"); + + b.Property<bool>("HidePrintOptions"); + + b.Property<bool>("HideSiteHeaderBar"); + + b.Property<bool>("IsReleased"); + + b.Property<bool>("IsVisibleToAllAfterRelease"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int?>("MaxManualPoint"); + + b.Property<string>("Note") + .HasMaxLength(10000); + + b.Property<int>("PLangId"); + + b.Property<int>("ReleaseDurationType"); + + b.Property<int>("ReleaseStartType"); + + b.Property<DateTime?>("ReleasedAt"); + + b.Property<bool>("RunAlsoNormalTests"); + + b.Property<bool>("ShouldAutomaticAssessSubmissions"); + + b.Property<bool>("ShouldClearClipboard"); + + b.Property<bool>("ShowAdditionalLogButton"); + + b.HasKey("Id"); + + b.HasAlternateKey("GeneratedCode") + .HasName("Unique_GeneratedCode"); + + b.HasIndex("ExerciseId"); + + b.HasIndex("PLangId"); + + b.ToTable("ExerciseReleases"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.CustomTestWithSingleSolutionAsTestResult", b => + { + b.Property<int>("CustomTestId"); + + b.Property<int>("SolutionUserId"); + + b.Property<int>("SolutionExerciseReleaseId"); + + b.Property<int>("SolutionPLangId"); + + b.Property<bool>("CharacterLimitExceeded"); + + b.Property<int?>("CharacterLimitUsed"); + + b.Property<int?>("CompileTimeoutInMsUsed"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<bool?>("HasCompiled"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<bool?>("Passed"); + + b.Property<int?>("ProgramExitCode"); + + b.Property<string>("Protocol") + .HasMaxLength(160100); + + b.Property<string>("RunnerVersion") + .HasMaxLength(2000); + + b.Property<int?>("TestResultCode"); + + b.Property<string>("TestServerVersion") + .HasMaxLength(2000); + + b.Property<int?>("TimeForCompiling"); + + b.Property<int?>("TimeForUserProgram"); + + b.Property<int?>("TimeoutInMsUsed"); + + b.HasKey("CustomTestId", "SolutionUserId", "SolutionExerciseReleaseId", "SolutionPLangId"); + + b.HasIndex("CustomTestId"); + + b.HasIndex("SolutionUserId", "SolutionExerciseReleaseId", "SolutionPLangId"); + + b.ToTable("CustomTestWithSingleSolutionAsTestResult"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.ExerciseReleaseWithUserAsParticipation", b => + { + b.Property<int>("UserId"); + + b.Property<int>("ExerciseReleaseId"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("LastEditedPLangId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<bool>("LockSolutionsFlag"); + + b.Property<bool>("ShouldNotCount"); + + b.HasKey("UserId", "ExerciseReleaseId"); + + b.HasIndex("ExerciseReleaseId"); + + b.HasIndex("LastEditedPLangId"); + + b.HasIndex("UserId"); + + b.ToTable("ExerciseReleaseWithUserAsParticipations"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.Solution", b => + { + b.Property<int>("UserId"); + + b.Property<int>("ExerciseReleaseId"); + + b.Property<int>("PLangId"); + + b.Property<int?>("AssessmentId"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("LastEditingIpAddress") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int?>("MainFileId"); + + b.Property<string>("Note") + .HasMaxLength(10000); + + b.HasKey("UserId", "ExerciseReleaseId", "PLangId"); + + b.HasIndex("AssessmentId") + .IsUnique(); + + b.HasIndex("MainFileId") + .IsUnique(); + + b.HasIndex("PLangId"); + + b.HasIndex("UserId", "ExerciseReleaseId"); + + b.ToTable("Solutions"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.SolutionAssessment", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<int>("ExerciseReleaseId"); + + b.Property<string>("FeedbackForStudent") + .HasMaxLength(10000); + + b.Property<string>("LastAssessmentErrorMessage") + .HasMaxLength(80000); + + b.Property<int?>("ManualPoints"); + + b.Property<int>("MaxNormalTestPoints"); + + b.Property<int>("MaxSubmitTestPoints"); + + b.Property<int?>("NormalTestPoints"); + + b.Property<string>("NoteForOtherTutors") + .HasMaxLength(10000); + + b.Property<int>("PLangId"); + + b.Property<int?>("SubmitTestPoints"); + + b.Property<int>("UserId"); + + b.HasKey("Id"); + + b.ToTable("SolutionAssessment"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.SolutionFile", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Content") + .HasMaxLength(70000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("DisplayIndex"); + + b.Property<string>("FileNameWithExtension") + .HasMaxLength(2000); + + b.Property<bool>("IsDisplayed"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("SolutionExerciseReleaseId"); + + b.Property<int>("SolutionPLangId"); + + b.Property<int>("SolutionUserId"); + + b.Property<int?>("TemplateFileId"); + + b.HasKey("Id"); + + b.HasIndex("TemplateFileId"); + + b.HasIndex("SolutionUserId", "SolutionExerciseReleaseId", "SolutionPLangId"); + + b.ToTable("SolutionFiles"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.TestWithSingleSolutionAsTestResult", b => + { + b.Property<int>("TestId"); + + b.Property<int>("SolutionUserId"); + + b.Property<int>("SolutionExerciseReleaseId"); + + b.Property<int>("SolutionPLangId"); + + b.Property<bool>("CharacterLimitExceeded"); + + b.Property<int?>("CharacterLimitUsed"); + + b.Property<int?>("CompileTimeoutInMsUsed"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<bool?>("HasCompiled"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<bool?>("Passed"); + + b.Property<int?>("ProgramExitCode"); + + b.Property<string>("Protocol") + .HasMaxLength(160100); + + b.Property<string>("RunnerVersion") + .HasMaxLength(2000); + + b.Property<int?>("TestResultCode"); + + b.Property<string>("TestServerVersion") + .HasMaxLength(2000); + + b.Property<int?>("TimeForCompiling"); + + b.Property<int?>("TimeForUserProgram"); + + b.Property<int?>("TimeoutInMsUsed"); + + b.HasKey("TestId", "SolutionUserId", "SolutionExerciseReleaseId", "SolutionPLangId"); + + b.HasIndex("TestId"); + + b.HasIndex("SolutionUserId", "SolutionExerciseReleaseId", "SolutionPLangId"); + + b.ToTable("TestWithSingleSolutionAsTestResult"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Tag", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("Description") + .HasMaxLength(2000); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<string>("HtmlBackgroundColor") + .HasMaxLength(2000); + + b.Property<string>("HtmlColor") + .HasMaxLength(2000); + + b.Property<string>("HtmlIcon") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.HasIndex("DisplayName") + .HasName("Unique_Tag"); + + b.ToTable("Tags"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.TagWithMetaData", b => + { + b.Property<int>("TagId"); + + b.Property<int>("MetaDataId"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("TagId", "MetaDataId"); + + b.HasIndex("MetaDataId"); + + b.HasIndex("TagId"); + + b.ToTable("TagWithMetaDatas"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.TemplateFile", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<int?>("CodeTemplateId") + .IsRequired(); + + b.Property<string>("Content") + .HasMaxLength(70000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("DisplayIndex"); + + b.Property<string>("FileNameWithExtension") + .HasMaxLength(2000); + + b.Property<bool>("IsContentVisibleForUser"); + + b.Property<bool>("IsEditableByUser"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.HasIndex("CodeTemplateId"); + + b.ToTable("TemplateFiles"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Tests.CustomTest", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Content") + .HasMaxLength(80000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("DisplayIndex"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<int>("ExerciseReleaseId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("TestTypeId"); + + b.Property<int>("UserId"); + + b.HasKey("Id"); + + b.HasIndex("TestTypeId"); + + b.HasIndex("UserId", "ExerciseReleaseId"); + + b.ToTable("CustomTest"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Tests.DefaultCustomTestSettings", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<int>("CompileTimeoutInMs"); + + b.Property<string>("CompilerOptions") + .HasMaxLength(2000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("ExerciseId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("MaxDiskSpaceInKb"); + + b.Property<int>("MemoryLimitInKb"); + + b.Property<int>("TimeoutInMs"); + + b.HasKey("Id"); + + b.HasIndex("ExerciseId") + .IsUnique(); + + b.ToTable("DefaultCustomTestSettings"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Tests.Test", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<string>("Content") + .HasMaxLength(80000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("DisplayIndex"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<int>("ExerciseId"); + + b.Property<bool>("IsSubmitTest"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("TestSettingsId"); + + b.Property<int>("TestTypeId"); + + b.Property<int>("Weight"); + + b.HasKey("Id"); + + b.HasIndex("ExerciseId"); + + b.HasIndex("TestSettingsId") + .IsUnique(); + + b.HasIndex("TestTypeId"); + + b.ToTable("Tests"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Tests.TestSettings", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<int>("CompileTimeoutInMs"); + + b.Property<string>("CompilerOptions") + .HasMaxLength(2000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("MaxDiskSpaceInKb"); + + b.Property<int>("MemoryLimitInKb"); + + b.Property<int>("TestId"); + + b.Property<int>("TimeoutInMs"); + + b.HasKey("Id"); + + b.ToTable("TestCaseSettingses"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Tests.TestType", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<string>("InternalName") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.ToTable("TestTypes"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.TestWithFileAsAssetReference", b => + { + b.Property<int>("TestId"); + + b.Property<int>("FileReferenceTestAssetId"); + + b.HasKey("TestId", "FileReferenceTestAssetId"); + + b.HasIndex("FileReferenceTestAssetId"); + + b.HasIndex("TestId"); + + b.ToTable("TestWithFileAsAssetReferences"); + }); + + modelBuilder.Entity("ClientServer.Models.Files.FileReferenceMarkdownAsset", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("Hash") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<string>("MimeType") + .HasMaxLength(2000); + + b.Property<string>("OriginalName") + .HasMaxLength(2000); + + b.Property<long>("SizeInBytes"); + + b.HasKey("Id"); + + b.ToTable("FileReferenceMarkdownAssets"); + }); + + modelBuilder.Entity("ClientServer.Models.Files.FileReferenceTestAsset", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("Hash") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<string>("MimeType") + .HasMaxLength(2000); + + b.Property<string>("OriginalName") + .HasMaxLength(2000); + + b.Property<long>("SizeInBytes"); + + b.HasKey("Id"); + + b.ToTable("FileReferenceTestAssets"); + }); + + modelBuilder.Entity("ClientServer.Models.Files.FileReferenceUserFileAsset", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("Hash") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<string>("MimeType") + .HasMaxLength(2000); + + b.Property<string>("OriginalName") + .HasMaxLength(2000); + + b.Property<long>("SizeInBytes"); + + b.HasKey("Id"); + + b.ToTable("FileReferenceUserFileAssets"); + }); + + modelBuilder.Entity("ClientServer.Models.Lang", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("LangShortcut") + .HasMaxLength(2000); + + b.Property<string>("Language") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.ToTable("Langs"); + }); + + modelBuilder.Entity("ClientServer.Models.PLang", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<string>("EditorHighlightModeName") + .HasMaxLength(2000); + + b.Property<string>("FileExtensionsWithDot") + .HasMaxLength(2000); + + b.Property<string>("InternalName") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.ToTable("PLangs"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.AuthToken", b => + { + b.Property<int>("UserId"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("CsrfToken") + .HasMaxLength(2000); + + b.Property<DateTime>("ExpirationDateTime"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<string>("RandomSecret") + .HasMaxLength(2000); + + b.Property<string>("UserAuthToken") + .HasMaxLength(2000); + + b.HasKey("UserId"); + + b.HasIndex("UserAuthToken") + .IsUnique(); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("AuthTokens"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.ExternalUser", b => + { + b.Property<int>("ExternalId") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("Email") + .HasMaxLength(2000); + + b.Property<string>("FirstName") + .HasMaxLength(2000); + + b.Property<string>("LastName") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<bool>("NeedToRefreshData"); + + b.Property<string>("Token") + .IsRequired() + .HasMaxLength(2000); + + b.Property<int>("UserId"); + + b.HasKey("ExternalId"); + + b.HasAlternateKey("Token") + .HasName("Unique_ExternalToken"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("ExternalUsers"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.GroupRole", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<int>("GroupRolePermissionId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.HasIndex("GroupRolePermissionId") + .IsUnique(); + + b.ToTable("GroupRoles"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.GroupRolePermission", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<bool>("CanAddUserToGroup"); + + b.Property<bool>("CanAssessExercises"); + + b.Property<bool>("CanChangeExercises"); + + b.Property<bool>("CanChangeGroupData"); + + b.Property<bool>("CanChangeOtherMembersRole"); + + b.Property<bool>("CanCreateExercises"); + + b.Property<bool>("CanDeleteExercises"); + + b.Property<bool>("CanLockExercisesPermanently"); + + b.Property<bool>("CanManageExerciseReleases"); + + b.Property<bool>("CanRemoveMemberFromGroup"); + + b.Property<bool>("CanSeeExercisesFromOthersInGroup"); + + b.Property<bool>("CanSeeOtherMembers"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("GroupRoleId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.ToTable("GroupRolePermissions"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.Settings.CodeEditorSetting", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("FontSize"); + + b.Property<bool>("HighlightCurrentLine"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<bool>("ShowInvisibles"); + + b.Property<bool>("ShowLineIndentions"); + + b.Property<bool>("ShowLineNumbers"); + + b.Property<int>("TabSize"); + + b.Property<string>("Theme") + .HasMaxLength(2000); + + b.Property<bool>("UseWrapping"); + + b.Property<int>("UserSettingId"); + + b.HasKey("Id"); + + b.ToTable("CodeEditorSettings"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.Settings.UserSetting", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<int>("CodeEditorSettingsId"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int?>("LangId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<string>("Theme") + .HasMaxLength(2000); + + b.Property<int?>("UserId"); + + b.HasKey("Id"); + + b.HasIndex("CodeEditorSettingsId") + .IsUnique(); + + b.HasIndex("LangId"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("UserSettingses"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.SystemRole", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<string>("Email") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("SystemRolePermissionId"); + + b.HasKey("Id"); + + b.HasIndex("SystemRolePermissionId") + .IsUnique(); + + b.ToTable("SystemRoles"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.SystemRolePermission", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<bool>("CanChangeOtherUsersSystemRole"); + + b.Property<bool>("CanChangeRoles"); + + b.Property<bool>("CanChangeSystemSettings"); + + b.Property<bool>("CanChangeUserData"); + + b.Property<bool>("CanCreateGroups"); + + b.Property<bool>("CanCreateRoles"); + + b.Property<bool>("CanDeleteActivatedUsers"); + + b.Property<bool>("CanDeleteGroups"); + + b.Property<bool>("CanDeleteRoles"); + + b.Property<bool>("CanManageNewUsers"); + + b.Property<bool>("CanManageTags"); + + b.Property<bool>("CanViewDashboard"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("SystemRoleId"); + + b.HasKey("Id"); + + b.ToTable("SystemRolePermissions"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.SystemSetting", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("CurrentServerMessage") + .HasMaxLength(10000); + + b.Property<int>("CustomProjectTestCompileTimeoutInMs"); + + b.Property<int>("CustomProjectTestMaxDiskSpaceInKb"); + + b.Property<int>("CustomProjectTestMemoryLimitInKb"); + + b.Property<int>("CustomProjectTestTimeoutInMs"); + + b.Property<int>("DefaultGroupCreatorGroupRoleId"); + + b.Property<int>("DefaultGroupRoleId"); + + b.Property<int>("DefaultUserGroupId"); + + b.Property<int>("JustRunProgramCompileTimeoutInMs"); + + b.Property<int>("JustRunProgramMaxDiskSpaceInKb"); + + b.Property<int>("JustRunProgramMemoryLimitInKb"); + + b.Property<int>("JustRunProgramTimeoutInMs"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("MaxCustomProjectsPerUser"); + + b.Property<int>("MaxCustomTestsPerParticipation"); + + b.Property<int>("MaxNumberOfTestsWithOneRequest"); + + b.Property<int>("MaxNumberOfTestsWithOneRequestSubmitTestServer"); + + b.Property<int>("SubmitTestServerTimeoutInMs"); + + b.Property<string>("SubmitTestServerUrl") + .HasMaxLength(2000); + + b.Property<string>("TestServerConfigUiUrl") + .HasMaxLength(2000); + + b.Property<string>("TestServerStatsUrl") + .HasMaxLength(2000); + + b.Property<int>("TestServerTimeoutInMs"); + + b.Property<string>("TestServerUrl") + .HasMaxLength(2000); + + b.HasKey("Id"); + + b.HasIndex("DefaultGroupCreatorGroupRoleId") + .IsUnique(); + + b.HasIndex("DefaultGroupRoleId") + .IsUnique(); + + b.HasIndex("DefaultUserGroupId") + .IsUnique(); + + b.ToTable("SystemSettings"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.User", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("Email") + .HasMaxLength(2000); + + b.Property<string>("FirstName") + .HasMaxLength(2000); + + b.Property<bool>("IsActivated"); + + b.Property<DateTime>("LastLoginAt"); + + b.Property<string>("LastName") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<string>("Password") + .HasMaxLength(2000); + + b.Property<int?>("SystemRoleId"); + + b.Property<string>("Token") + .IsRequired() + .HasMaxLength(2000); + + b.HasKey("Id"); + + b.HasAlternateKey("Token") + .HasName("Unique_Token"); + + b.HasIndex("SystemRoleId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.UserGroup", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<DateTime>("CreatedAt"); + + b.Property<string>("DisplayName") + .HasMaxLength(2000); + + b.Property<string>("Email") + .HasMaxLength(2000); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("Id"); + + b.ToTable("UserGroups"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.UserWithUserGroup", b => + { + b.Property<int>("UserId"); + + b.Property<int>("UserGroupId"); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("GroupRoleId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.HasKey("UserId", "UserGroupId"); + + b.HasIndex("GroupRoleId"); + + b.HasIndex("UserGroupId"); + + b.HasIndex("UserId"); + + b.ToTable("UserWithUserGroups"); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProject", b => + { + b.HasOne("ClientServer.Models.Users.User", "User") + .WithMany("CustomProjects") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectDescription", b => + { + b.HasOne("ClientServer.Models.CustomProjects.CustomProject", "CustomProject") + .WithOne("Description") + .HasForeignKey("ClientServer.Models.CustomProjects.CustomProjectDescription", "CustomProjectId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectDescriptionWithFileAsAssetReference", b => + { + b.HasOne("ClientServer.Models.CustomProjects.CustomProjectDescription", "CustomProjectDescription") + .WithMany("AssetReferences") + .HasForeignKey("CustomProjectDescriptionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Files.FileReferenceUserFileAsset", "FileReferenceUserFileAsset") + .WithMany("CustomProjectDescriptionWithFileAsAssetReferences") + .HasForeignKey("FileReferenceUserFileAssetId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectSolution", b => + { + b.HasOne("ClientServer.Models.CustomProjects.CustomProject", "CustomProject") + .WithMany("Solutions") + .HasForeignKey("CustomProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.CustomProjects.CustomProjectSolutionFile", "MainFile") + .WithOne() + .HasForeignKey("ClientServer.Models.CustomProjects.CustomProjectSolution", "MainFileId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ClientServer.Models.PLang", "PLang") + .WithMany() + .HasForeignKey("PLangId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectSolutionFile", b => + { + b.HasOne("ClientServer.Models.CustomProjects.CustomProjectSolution") + .WithMany("SolutionFiles") + .HasForeignKey("CustomProjectSolutionId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectTest", b => + { + b.HasOne("ClientServer.Models.CustomProjects.CustomProject", "CustomProject") + .WithMany("Tests") + .HasForeignKey("CustomProjectId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Tests.TestSettings", "TestSettings") + .WithOne() + .HasForeignKey("ClientServer.Models.CustomProjects.CustomProjectTest", "TestSettingsId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Tests.TestType", "TestType") + .WithMany() + .HasForeignKey("TestTypeId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectTestWithFileAsAssetReference", b => + { + b.HasOne("ClientServer.Models.CustomProjects.CustomProjectTest", "CustomProjectTest") + .WithMany("AssetReferences") + .HasForeignKey("CustomProjectTestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Files.FileReferenceUserFileAsset", "FileReferenceUserFileAsset") + .WithMany("CustomProjectTestWithFileAsAssetReferences") + .HasForeignKey("FileReferenceUserFileAssetId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectTestWithSolutionAsTestResult", b => + { + b.HasOne("ClientServer.Models.CustomProjects.CustomProjectSolution", "CustomProjectSolution") + .WithMany("TestResults") + .HasForeignKey("CustomProjectSolutionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.CustomProjects.CustomProjectTest", "CustomProjectTest") + .WithMany("TestResults") + .HasForeignKey("CustomProjectTestId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.AfterSolutions.AfterSolution", b => + { + b.HasOne("ClientServer.Models.Exercises.AfterSolutions.AfterSolutionFile", "MainFile") + .WithOne() + .HasForeignKey("ClientServer.Models.Exercises.AfterSolutions.AfterSolution", "MainFileId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ClientServer.Models.Exercises.Solution.Solution", "Solution") + .WithOne("AfterSolution") + .HasForeignKey("ClientServer.Models.Exercises.AfterSolutions.AfterSolution", "SolutionUserId", "SolutionExerciseReleaseId", "SolutionPLangId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.AfterSolutions.AfterSolutionFile", b => + { + b.HasOne("ClientServer.Models.Exercises.AfterSolutions.AfterSolution", "AfterSolution") + .WithMany("SolutionFiles") + .HasForeignKey("AfterSolutionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.TemplateFile", "TemplateFile") + .WithMany() + .HasForeignKey("TemplateFileId"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.AfterSolutions.CustomTestWithAfterSolutionAsTestResult", b => + { + b.HasOne("ClientServer.Models.Exercises.AfterSolutions.AfterSolution", "AfterSolution") + .WithMany("CustomTestResults") + .HasForeignKey("AfterSolutionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Tests.CustomTest", "CustomTest") + .WithMany("AfterTestResults") + .HasForeignKey("CustomTestId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.AfterSolutions.TestWithAfterSolutionAsTestResult", b => + { + b.HasOne("ClientServer.Models.Exercises.AfterSolutions.AfterSolution", "AfterSolution") + .WithMany("TestResults") + .HasForeignKey("AfterSolutionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Tests.Test", "Test") + .WithMany("AfterTestResults") + .HasForeignKey("TestId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.CodeTemplate", b => + { + b.HasOne("ClientServer.Models.Exercises.Exercise", "Exercise") + .WithMany("CodeTemplates") + .HasForeignKey("ExerciseId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.TemplateFile", "MainFile") + .WithOne() + .HasForeignKey("ClientServer.Models.Exercises.CodeTemplate", "MainFileId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ClientServer.Models.PLang", "PLang") + .WithMany() + .HasForeignKey("PLangId"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.CustomTestWithFileAsAssetReference", b => + { + b.HasOne("ClientServer.Models.Exercises.Tests.CustomTest", "CustomTest") + .WithMany("AssetReferences") + .HasForeignKey("CustomTestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Files.FileReferenceUserFileAsset", "FileReferenceUserFileAsset") + .WithMany("CustomTestWithFileAsAssetReferences") + .HasForeignKey("FileReferenceUserFileAssetId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Exercise", b => + { + b.HasOne("ClientServer.Models.Users.UserGroup", "UserGroup") + .WithMany("Exercises") + .HasForeignKey("UserGroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Users.User", "User") + .WithMany("Exercises") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.ExerciseDescription", b => + { + b.HasOne("ClientServer.Models.Exercises.Exercise", "Exercise") + .WithOne("Description") + .HasForeignKey("ClientServer.Models.Exercises.ExerciseDescription", "ExerciseId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.ExerciseDescriptionWithFileAsAssetReference", b => + { + b.HasOne("ClientServer.Models.Exercises.ExerciseDescription", "ExerciseDescription") + .WithMany("AssetReferences") + .HasForeignKey("ExerciseDescriptionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Files.FileReferenceMarkdownAsset", "FileReferenceMarkdownAsset") + .WithMany("AssetReferences") + .HasForeignKey("FileReferenceMarkdownAssetId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.MetaData", b => + { + b.HasOne("ClientServer.Models.Exercises.Exercise", "Exercise") + .WithOne("MetaData") + .HasForeignKey("ClientServer.Models.Exercises.MetaData", "ExerciseId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Release.ExerciseRelease", b => + { + b.HasOne("ClientServer.Models.Exercises.Exercise", "Exercise") + .WithMany("Releases") + .HasForeignKey("ExerciseId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.PLang", "PLang") + .WithMany() + .HasForeignKey("PLangId"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.CustomTestWithSingleSolutionAsTestResult", b => + { + b.HasOne("ClientServer.Models.Exercises.Tests.CustomTest", "CustomTest") + .WithMany("TestResultsNew") + .HasForeignKey("CustomTestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Solution.Solution", "Solution") + .WithMany("CustomTestResults") + .HasForeignKey("SolutionUserId", "SolutionExerciseReleaseId", "SolutionPLangId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.ExerciseReleaseWithUserAsParticipation", b => + { + b.HasOne("ClientServer.Models.Exercises.Release.ExerciseRelease", "ExerciseRelease") + .WithMany("ExerciseReleaseWithUserAsParticipations") + .HasForeignKey("ExerciseReleaseId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.PLang", "LastEditedPLang") + .WithMany() + .HasForeignKey("LastEditedPLangId"); + + b.HasOne("ClientServer.Models.Users.User", "User") + .WithMany("ExerciseReleaseWithUserAsParticipations") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.Solution", b => + { + b.HasOne("ClientServer.Models.Exercises.Solution.SolutionAssessment", "Assessment") + .WithOne("Solution") + .HasForeignKey("ClientServer.Models.Exercises.Solution.Solution", "AssessmentId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Solution.SolutionFile", "MainFile") + .WithOne() + .HasForeignKey("ClientServer.Models.Exercises.Solution.Solution", "MainFileId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ClientServer.Models.PLang", "PLang") + .WithMany() + .HasForeignKey("PLangId"); + + b.HasOne("ClientServer.Models.Exercises.Solution.ExerciseReleaseWithUserAsParticipation", "ExerciseReleaseWithUserAsParticipation") + .WithMany("Solutions") + .HasForeignKey("UserId", "ExerciseReleaseId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.SolutionFile", b => + { + b.HasOne("ClientServer.Models.Exercises.TemplateFile", "TemplateFile") + .WithMany("SolutionParts") + .HasForeignKey("TemplateFileId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ClientServer.Models.Exercises.Solution.Solution", "Solution") + .WithMany("SolutionFiles") + .HasForeignKey("SolutionUserId", "SolutionExerciseReleaseId", "SolutionPLangId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Solution.TestWithSingleSolutionAsTestResult", b => + { + b.HasOne("ClientServer.Models.Exercises.Tests.Test", "Test") + .WithMany("TestResultsNew") + .HasForeignKey("TestId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Solution.Solution", "Solution") + .WithMany("TestResults") + .HasForeignKey("SolutionUserId", "SolutionExerciseReleaseId", "SolutionPLangId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.TagWithMetaData", b => + { + b.HasOne("ClientServer.Models.Exercises.MetaData", "MetaData") + .WithMany("TagWithMetaDatas") + .HasForeignKey("MetaDataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Tag", "Tag") + .WithMany() + .HasForeignKey("TagId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.TemplateFile", b => + { + b.HasOne("ClientServer.Models.Exercises.CodeTemplate") + .WithMany("TemplateFiles") + .HasForeignKey("CodeTemplateId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Tests.CustomTest", b => + { + b.HasOne("ClientServer.Models.Exercises.Tests.TestType", "TestType") + .WithMany() + .HasForeignKey("TestTypeId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Solution.ExerciseReleaseWithUserAsParticipation") + .WithMany("CustomTests") + .HasForeignKey("UserId", "ExerciseReleaseId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Tests.DefaultCustomTestSettings", b => + { + b.HasOne("ClientServer.Models.Exercises.Exercise", "Exercise") + .WithOne("DefaultCustomTestSettings") + .HasForeignKey("ClientServer.Models.Exercises.Tests.DefaultCustomTestSettings", "ExerciseId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.Tests.Test", b => + { + b.HasOne("ClientServer.Models.Exercises.Exercise", "Exercise") + .WithMany("Tests") + .HasForeignKey("ExerciseId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Tests.TestSettings", "TestSettings") + .WithOne() + .HasForeignKey("ClientServer.Models.Exercises.Tests.Test", "TestSettingsId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Tests.TestType", "TestType") + .WithMany() + .HasForeignKey("TestTypeId"); + }); + + modelBuilder.Entity("ClientServer.Models.Exercises.TestWithFileAsAssetReference", b => + { + b.HasOne("ClientServer.Models.Files.FileReferenceTestAsset", "FileReferenceTestAsset") + .WithMany("AssetReferences") + .HasForeignKey("FileReferenceTestAssetId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Exercises.Tests.Test", "Test") + .WithMany("AssetReferences") + .HasForeignKey("TestId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Users.AuthToken", b => + { + b.HasOne("ClientServer.Models.Users.User", "User") + .WithOne() + .HasForeignKey("ClientServer.Models.Users.AuthToken", "UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Users.ExternalUser", b => + { + b.HasOne("ClientServer.Models.Users.User", "User") + .WithOne("ExternalUser") + .HasForeignKey("ClientServer.Models.Users.ExternalUser", "UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Users.GroupRole", b => + { + b.HasOne("ClientServer.Models.Users.GroupRolePermission", "GroupRolePermission") + .WithOne() + .HasForeignKey("ClientServer.Models.Users.GroupRole", "GroupRolePermissionId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Users.Settings.UserSetting", b => + { + b.HasOne("ClientServer.Models.Users.Settings.CodeEditorSetting", "CodeEditorSetting") + .WithOne() + .HasForeignKey("ClientServer.Models.Users.Settings.UserSetting", "CodeEditorSettingsId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Lang", "Lang") + .WithMany() + .HasForeignKey("LangId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ClientServer.Models.Users.User", "User") + .WithOne("UserSettings") + .HasForeignKey("ClientServer.Models.Users.Settings.UserSetting", "UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Users.SystemRole", b => + { + b.HasOne("ClientServer.Models.Users.SystemRolePermission", "SystemRolePermission") + .WithOne() + .HasForeignKey("ClientServer.Models.Users.SystemRole", "SystemRolePermissionId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ClientServer.Models.Users.SystemSetting", b => + { + b.HasOne("ClientServer.Models.Users.GroupRole", "DefaultGroupCreatorGroupRole") + .WithOne() + .HasForeignKey("ClientServer.Models.Users.SystemSetting", "DefaultGroupCreatorGroupRoleId"); + + b.HasOne("ClientServer.Models.Users.GroupRole", "DefaultGroupRole") + .WithOne() + .HasForeignKey("ClientServer.Models.Users.SystemSetting", "DefaultGroupRoleId"); + + b.HasOne("ClientServer.Models.Users.UserGroup", "DefaultUserGroup") + .WithOne() + .HasForeignKey("ClientServer.Models.Users.SystemSetting", "DefaultUserGroupId"); + }); + + modelBuilder.Entity("ClientServer.Models.Users.User", b => + { + b.HasOne("ClientServer.Models.Users.SystemRole", "SystemRole") + .WithMany() + .HasForeignKey("SystemRoleId") + .OnDelete(DeleteBehavior.SetNull); + }); + + modelBuilder.Entity("ClientServer.Models.Users.UserWithUserGroup", b => + { + b.HasOne("ClientServer.Models.Users.GroupRole", "GroupRole") + .WithMany("UserUserGroups") + .HasForeignKey("GroupRoleId"); + + b.HasOne("ClientServer.Models.Users.UserGroup", "UserGroup") + .WithMany("UserWithUserGroups") + .HasForeignKey("UserGroupId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ClientServer.Models.Users.User", "User") + .WithMany("UserWithUserGroups") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + } + } +} diff --git a/src/ClientServer/Migrations/20190801144540_addFakeFksToOtherSides.cs b/src/ClientServer/Migrations/20190801144540_addFakeFksToOtherSides.cs new file mode 100755 index 0000000..431e5d6 --- /dev/null +++ b/src/ClientServer/Migrations/20190801144540_addFakeFksToOtherSides.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace ClientServer.Migrations +{ + public partial class addFakeFksToOtherSides : Migration + { + + //actually we want to drop the foreign key constraint to on delete no action + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "CustomProjectTestSettings", + columns: table => new + { + Id = table.Column<int>(nullable: false) + .Annotation("Npgsql:ValueGeneratedOnAdd", true), + CompileTimeoutInMs = table.Column<int>(nullable: false), + CompilerOptions = table.Column<string>(maxLength: 2000, nullable: true), + CreatedAt = table.Column<DateTime>(nullable: false), + CustomProjectTestId = table.Column<int>(nullable: false), + LastUpdatedAt = table.Column<DateTime>(nullable: false), + MaxDiskSpaceInKb = table.Column<int>(nullable: false), + MemoryLimitInKb = table.Column<int>(nullable: false), + TimeoutInMs = table.Column<int>(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CustomProjectTestSettings", x => x.Id); + }); + + migrationBuilder.AddColumn<int>( + name: "SystemRoleId", + table: "SystemRolePermissions", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn<int>( + name: "UserSettingId", + table: "CodeEditorSettings", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn<int>( + name: "GroupRoleId", + table: "GroupRolePermissions", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn<int>( + name: "TestId", + table: "TestCaseSettingses", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn<int>( + name: "ExerciseReleaseId", + table: "SolutionAssessment", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn<int>( + name: "PLangId", + table: "SolutionAssessment", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn<int>( + name: "UserId", + table: "SolutionAssessment", + nullable: false, + defaultValue: 0); + + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SystemRoleId", + table: "SystemRolePermissions"); + + migrationBuilder.DropColumn( + name: "UserSettingId", + table: "CodeEditorSettings"); + + migrationBuilder.DropColumn( + name: "GroupRoleId", + table: "GroupRolePermissions"); + + migrationBuilder.DropColumn( + name: "TestId", + table: "TestCaseSettingses"); + + migrationBuilder.DropColumn( + name: "ExerciseReleaseId", + table: "SolutionAssessment"); + + migrationBuilder.DropColumn( + name: "PLangId", + table: "SolutionAssessment"); + + migrationBuilder.DropColumn( + name: "UserId", + table: "SolutionAssessment"); + + migrationBuilder.DropTable( + name: "CustomProjectTestSettings"); + } + } +} diff --git a/src/ClientServer/Migrations/YapexDbContextModelSnapshot.cs b/src/ClientServer/Migrations/YapexDbContextModelSnapshot.cs index fee1131..295dacc 100755 --- a/src/ClientServer/Migrations/YapexDbContextModelSnapshot.cs +++ b/src/ClientServer/Migrations/YapexDbContextModelSnapshot.cs @@ -204,6 +204,33 @@ namespace ClientServer.Migrations b.ToTable("CustomProjectTestAssets"); }); + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectTestSettings", b => + { + b.Property<int>("Id") + .ValueGeneratedOnAdd(); + + b.Property<int>("CompileTimeoutInMs"); + + b.Property<string>("CompilerOptions") + .HasMaxLength(2000); + + b.Property<DateTime>("CreatedAt"); + + b.Property<int>("CustomProjectTestId"); + + b.Property<DateTime>("LastUpdatedAt"); + + b.Property<int>("MaxDiskSpaceInKb"); + + b.Property<int>("MemoryLimitInKb"); + + b.Property<int>("TimeoutInMs"); + + b.HasKey("Id"); + + b.ToTable("CustomProjectTestSettings"); + }); + modelBuilder.Entity("ClientServer.Models.CustomProjects.CustomProjectTestWithFileAsAssetReference", b => { b.Property<int>("CustomProjectTestId"); @@ -755,6 +782,8 @@ namespace ClientServer.Migrations b.Property<int>("Id") .ValueGeneratedOnAdd(); + b.Property<int>("ExerciseReleaseId"); + b.Property<string>("FeedbackForStudent") .HasMaxLength(10000); @@ -772,8 +801,12 @@ namespace ClientServer.Migrations b.Property<string>("NoteForOtherTutors") .HasMaxLength(10000); + b.Property<int>("PLangId"); + b.Property<int?>("SubmitTestPoints"); + b.Property<int>("UserId"); + b.HasKey("Id"); b.ToTable("SolutionAssessment"); @@ -1068,6 +1101,8 @@ namespace ClientServer.Migrations b.Property<int>("MemoryLimitInKb"); + b.Property<int>("TestId"); + b.Property<int>("TimeoutInMs"); b.HasKey("Id"); @@ -1351,6 +1386,8 @@ namespace ClientServer.Migrations b.Property<DateTime>("CreatedAt"); + b.Property<int>("GroupRoleId"); + b.Property<DateTime>("LastUpdatedAt"); b.HasKey("Id"); @@ -1384,6 +1421,8 @@ namespace ClientServer.Migrations b.Property<bool>("UseWrapping"); + b.Property<int>("UserSettingId"); + b.HasKey("Id"); b.ToTable("CodeEditorSettings"); @@ -1478,6 +1517,8 @@ namespace ClientServer.Migrations b.Property<DateTime>("LastUpdatedAt"); + b.Property<int>("SystemRoleId"); + b.HasKey("Id"); b.ToTable("SystemRolePermissions"); diff --git a/src/ClientServer/Models/CustomProjects/CustomProjectTestSettings.cs b/src/ClientServer/Models/CustomProjects/CustomProjectTestSettings.cs new file mode 100644 index 0000000..78d54e3 --- /dev/null +++ b/src/ClientServer/Models/CustomProjects/CustomProjectTestSettings.cs @@ -0,0 +1,42 @@ +using System.ComponentModel.DataAnnotations; +using ClientServer.Db; +using ClientServer.Models.Exercises.Tests; +using ClientServer.Models.Interfaces; + +namespace ClientServer.Models.CustomProjects +{ + public class CustomProjectTestSettings : ITestSettings + { + public int Id { get; set; } + + /// <summary> + /// the timeout in ms + /// </summary> + public int TimeoutInMs { get; set; } + + /// <summary> + /// the compile timeout in ms + /// </summary> + public int CompileTimeoutInMs { get; set; } + + /// <summary> + /// the max amount of ram in mb for the <see cref="Test"/> + /// </summary> + public int MemoryLimitInKb { get; set; } + + /// <summary> + /// the max amount of disk space the <see cref="Test"/> can write to + /// </summary> + public int MaxDiskSpaceInKb { get; set; } + + /// <summary> + /// some compiler options .g. -Xlint options needs to be separated by whitespaces (like normal command args) + /// </summary> + [MaxLength(YapexDbContext.DefaultMaxStringLength)] + public string CompilerOptions { get; set; } + + //fk + public int CustomProjectTestId { get; set; } +// public CustomProjectTest CustomProjectTest { get; set; } + } +} diff --git a/src/ClientServer/Models/Exercises/Solution/SolutionAssessment.cs b/src/ClientServer/Models/Exercises/Solution/SolutionAssessment.cs index 6dfb963..c6149f4 100644 --- a/src/ClientServer/Models/Exercises/Solution/SolutionAssessment.cs +++ b/src/ClientServer/Models/Exercises/Solution/SolutionAssessment.cs @@ -60,6 +60,10 @@ namespace ClientServer.Models.Exercises.Solution [MaxLength(YapexDbContext.NotesMaxStringLength)] public string FeedbackForStudent { get; set; } + //fks of solution + public int PLangId { get; set; } + public int UserId { get; set; } + public int ExerciseReleaseId { get; set; } /// <summary> /// the connected <see cref="Solution"/> /// </summary> @@ -72,6 +76,7 @@ namespace ClientServer.Models.Exercises.Solution // /// always the latest version is used (normally) or null if the user did not submit something // /// </summary> // public SolutionVersion SolutionVersion { get; set; } + } } diff --git a/src/ClientServer/Models/Exercises/Tests/TestSettings.cs b/src/ClientServer/Models/Exercises/Tests/TestSettings.cs index 8972147..2c84115 100644 --- a/src/ClientServer/Models/Exercises/Tests/TestSettings.cs +++ b/src/ClientServer/Models/Exercises/Tests/TestSettings.cs @@ -1,5 +1,6 @@ using System.ComponentModel.DataAnnotations; using ClientServer.Db; +using ClientServer.Models.CustomProjects; using ClientServer.Models.Interfaces; namespace ClientServer.Models.Exercises.Tests @@ -36,5 +37,10 @@ namespace ClientServer.Models.Exercises.Tests /// </summary> [MaxLength(YapexDbContext.DefaultMaxStringLength)] public string CompilerOptions { get; set; } + + //fk + public int TestId { get; set; } +// public Test Test { get; set; } + } } diff --git a/src/ClientServer/Models/Users/GroupRolePermission.cs b/src/ClientServer/Models/Users/GroupRolePermission.cs index 88b9c43..fc76ce4 100644 --- a/src/ClientServer/Models/Users/GroupRolePermission.cs +++ b/src/ClientServer/Models/Users/GroupRolePermission.cs @@ -100,5 +100,9 @@ namespace ClientServer.Models.Users /// false: not /// </summary> public bool CanChangeGroupData { get; set; } + + //fk + public int GroupRoleId { get; set; } +// public GroupRole GroupRole { get; set; } } } diff --git a/src/ClientServer/Models/Users/Settings/CodeEditorSettings.cs b/src/ClientServer/Models/Users/Settings/CodeEditorSettings.cs index 3238a93..46a35b9 100644 --- a/src/ClientServer/Models/Users/Settings/CodeEditorSettings.cs +++ b/src/ClientServer/Models/Users/Settings/CodeEditorSettings.cs @@ -44,5 +44,9 @@ namespace ClientServer.Models.Users.Settings /// </summary> public bool UseWrapping { get; set; } + //fk + public int UserSettingId { get; set; } +// public UserSetting UserSetting { get; set; } + } } diff --git a/src/ClientServer/Models/Users/SystemRolePermission.cs b/src/ClientServer/Models/Users/SystemRolePermission.cs index b9df0a6..e8554f9 100644 --- a/src/ClientServer/Models/Users/SystemRolePermission.cs +++ b/src/ClientServer/Models/Users/SystemRolePermission.cs @@ -77,5 +77,9 @@ namespace ClientServer.Models.Users /// </summary> public bool CanViewDashboard { get; set; } + //fk + public int SystemRoleId { get; set; } +// public SystemRole SystemRole { get; set; } + } } -- GitLab