commit ceb95b98f31af59944eaeb50125c1afeca4ede11
Author: Vojtěch Bartička <aitakaitov@gmail.com>
Date:   Wed Apr 27 11:29:30 2022 +0200

    Added endpoint to get global required annotations, moved configuration to database

diff --git a/Backend/Backend/Controllers/DocumentController.cs b/Backend/Backend/Controllers/DocumentController.cs
index 34168b8..54afd9f 100644
--- a/Backend/Backend/Controllers/DocumentController.cs
+++ b/Backend/Backend/Controllers/DocumentController.cs
@@ -127,5 +127,35 @@ public class DocumentController : Common.CommonControllerBase
 
         return Ok();
     }
+
+    [HttpGet("/documents/requiredAnnotations/global")]
+    [Authorize(Models.Enums.ERole.ADMINISTRATOR)]
+    [ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(GetRequiredAnnotationsGlobalResponse))]
+    [ProducesResponseType((int)HttpStatusCode.Forbidden)]
+    public ActionResult<GetRequiredAnnotationsGlobalResponse> GetRequiredAnnotationsGlobal([FromServices] ClientInfo clientInfo)
+    {
+        if (clientInfo.LoggedUser == null)
+        {
+            logger.Warning("ClientInfo has null LoggerUser in [Authorized] controller /documents");
+            return Problem();
+        }
+
+        try
+        {
+            return Ok(new GetRequiredAnnotationsGlobalResponse()
+            {
+                RequiredAnnotationsGlobal = documentService.GetRequiredAnnotationsGlobal()
+            });
+
+        }
+        catch (InvalidOperationException e)
+        {
+            throw new BadRequestException(e.Message);
+        }
+        catch (Exception e)
+        {
+            throw new InternalErrorException(e.Message);
+        }
+    }
 }
 
diff --git a/Backend/Core/Constants/Constants.cs b/Backend/Core/Constants/Constants.cs
new file mode 100644
index 0000000..fece77c
--- /dev/null
+++ b/Backend/Core/Constants/Constants.cs
@@ -0,0 +1,13 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Core.Constants
+{
+    public class Constants
+    {
+        public static string RequiredAnnotationsKey { get; } = "RequiredAnnotations"; 
+    }
+}
diff --git a/Backend/Core/Contexts/DatabaseContext.cs b/Backend/Core/Contexts/DatabaseContext.cs
index ff34af6..d65e36f 100644
--- a/Backend/Core/Contexts/DatabaseContext.cs
+++ b/Backend/Core/Contexts/DatabaseContext.cs
@@ -23,11 +23,11 @@ namespace Core.Contexts
         public DbSet<User> Users { get; set; }
         public DbSet<Annotation> Annotations { get; set; }
         public DbSet<Class> Classes { get; set; }
-        //public DbSet<AnnotationClass> AnnotationsClasses { get; set; }
         public DbSet<AnnotationTag> AnnotationTags { get; set; }
         public DbSet<Tag> Tags { get; set; }
         public DbSet<SubTag> SubTags { get; set; }
         public DbSet<TagCategory> TagCategories { get; set; }
+        public DbSet<ConfigurationItem> ConfigurationItems { get; set; }
 
         protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
         {
diff --git a/Backend/Core/Entities/ConfigurationItem.cs b/Backend/Core/Entities/ConfigurationItem.cs
new file mode 100644
index 0000000..e0f822f
--- /dev/null
+++ b/Backend/Core/Entities/ConfigurationItem.cs
@@ -0,0 +1,14 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Core.Entities
+{
+    public class ConfigurationItem : BaseEntity
+    {
+        public string Value { get; set; }
+        public string Key { get; set; }
+    }
+}
diff --git a/Backend/Core/Seeding/Seeder.cs b/Backend/Core/Seeding/Seeder.cs
index 7fe2795..33b2374 100644
--- a/Backend/Core/Seeding/Seeder.cs
+++ b/Backend/Core/Seeding/Seeder.cs
@@ -21,6 +21,13 @@ namespace Core.Seeding
                 DummyTags.AddDummyTags(context);
                 context.SaveChanges();
 
+                ConfigurationItem configurationItem = new ConfigurationItem()
+                {
+                    Key = Constants.Constants.RequiredAnnotationsKey,
+                    Value = "3"
+                };
+                context.ConfigurationItems.Add(configurationItem);
+
                 AddTagInstance(context);
                 context.SaveChanges();
             }
@@ -126,6 +133,14 @@ namespace Core.Seeding
                     Password = BCrypt.Net.BCrypt.HashPassword("123a456b789c")
                 };
                 context.Users.Add(admin);
+
+                ConfigurationItem configurationItem = new ConfigurationItem()
+                {
+                    Key = Constants.Constants.RequiredAnnotationsKey,
+                    Value = "3"
+                };
+                context.ConfigurationItems.Add(configurationItem);
+
                 context.SaveChanges();
             }
         }
diff --git a/Backend/Core/Services/DocumentService/DocumentServiceEF.cs b/Backend/Core/Services/DocumentService/DocumentServiceEF.cs
index fc7fc92..5fe689d 100644
--- a/Backend/Core/Services/DocumentService/DocumentServiceEF.cs
+++ b/Backend/Core/Services/DocumentService/DocumentServiceEF.cs
@@ -12,7 +12,6 @@ using System.Web;
 using AutoMapper;
 using Models.Users;
 using Ganss.XSS;
-using Core.StaticConfig;
 
 namespace Core.Services.DocumentService
 {
@@ -41,8 +40,7 @@ namespace Core.Services.DocumentService
         public void AddDocuments(DocumentAddRequest request, Guid userId)
         {
             User user = databaseContext.Users.Single(u => u.Id == userId);
-
-            var users = databaseContext.Users.Select(u => u).ToList();
+            int requiredAnnotations = int.Parse(databaseContext.ConfigurationItems.Single(ci => ci.Key == Constants.Constants.RequiredAnnotationsKey).Value);
 
             foreach (var documentInfo in request.Documents)
             {
@@ -50,14 +48,14 @@ namespace Core.Services.DocumentService
                 {
                     // TODO hardcoded UTF-8 - maybe do something smarter
                     var documentContent = Encoding.UTF8.GetString(Convert.FromBase64String(documentInfo.Content));
-                    SaveDocument(documentContent, user, documentInfo.Name, users);
+                    SaveDocument(documentContent, user, documentInfo.Name, requiredAnnotations);
                 }
                 else if (documentInfo.Format == Models.Enums.EAddDocumentFormat.ZIP)
                 {
                     var (names, contents) = UnzipDocuments(documentInfo.Content);
                     for (int i = 0; i < names.Count; i++)
                     {
-                        SaveDocument(contents[i], user, names[i], users);
+                        SaveDocument(contents[i], user, names[i], requiredAnnotations);
                     }
                 }
             }
@@ -92,7 +90,7 @@ namespace Core.Services.DocumentService
             return (names, contents);
         }
 
-        private void SaveDocument(string content, User userAdded, string documentName, List<User> users)
+        private void SaveDocument(string content, User userAdded, string documentName, int requiredAnnotations)
         {
             DocumentContent documentContent = new DocumentContent()
             {
@@ -106,7 +104,7 @@ namespace Core.Services.DocumentService
                 UserAdded = userAdded,
                 Name = documentName,
                 Length = documentContent.Content.Length,
-                RequiredAnnotations = GlobalConfiguration.RequiredAnnotations
+                RequiredAnnotations = requiredAnnotations
             };
 
             databaseContext.DocumentContents.Add(documentContent);
@@ -167,8 +165,15 @@ namespace Core.Services.DocumentService
 
         public void SetRequiredAnnotationsGlobal(int requiredAnnotations)
         {
-            GlobalConfiguration.RequiredAnnotations = requiredAnnotations;
+            var requiredAnnotationsItem = databaseContext.ConfigurationItems.Single(ci => ci.Key == Constants.Constants.RequiredAnnotationsKey);
+            requiredAnnotationsItem.Value = requiredAnnotations.ToString();
+            databaseContext.SaveChanges();
         }
 
+        public int GetRequiredAnnotationsGlobal()
+        {
+            var requiredAnnotationsItem = databaseContext.ConfigurationItems.Single(ci => ci.Key == Constants.Constants.RequiredAnnotationsKey);
+            return int.Parse(requiredAnnotationsItem.Value);
+        }
     }
 }
diff --git a/Backend/Core/Services/DocumentService/IDocumentService.cs b/Backend/Core/Services/DocumentService/IDocumentService.cs
index f77643f..0882815 100644
--- a/Backend/Core/Services/DocumentService/IDocumentService.cs
+++ b/Backend/Core/Services/DocumentService/IDocumentService.cs
@@ -18,5 +18,7 @@ namespace Core.Services.DocumentService
         public void SetRequiredAnnotationsForDocuments(SetRequiredAnnotationsRequest request);
 
         public void SetRequiredAnnotationsGlobal(int requiredAnnotations);
+
+        public int GetRequiredAnnotationsGlobal();
     }
 }
diff --git a/Backend/Core/StaticConfig/GlobalConfiguration.cs b/Backend/Core/StaticConfig/GlobalConfiguration.cs
deleted file mode 100644
index 1048034..0000000
--- a/Backend/Core/StaticConfig/GlobalConfiguration.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-﻿using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Core.StaticConfig
-{
-    public class GlobalConfiguration
-    {
-        // Default count of required annotations
-        private static Mutex RequiredAnnotationsMutex = new Mutex();
-        private static int requiredAnnotations = 3;
-        public static int RequiredAnnotations
-        {
-            get { return requiredAnnotations; }
-            set
-            {
-                RequiredAnnotationsMutex.WaitOne();
-                requiredAnnotations = value;
-                RequiredAnnotationsMutex.ReleaseMutex();
-            }
-        }     
-    }
-}
diff --git a/Backend/Models/Documents/GetRequiredAnnotationsGlobalResponse.cs b/Backend/Models/Documents/GetRequiredAnnotationsGlobalResponse.cs
new file mode 100644
index 0000000..71053bd
--- /dev/null
+++ b/Backend/Models/Documents/GetRequiredAnnotationsGlobalResponse.cs
@@ -0,0 +1,13 @@
+﻿using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Models.Documents
+{
+    public class GetRequiredAnnotationsGlobalResponse
+    {
+        public int RequiredAnnotationsGlobal { get; set; }
+    }
+}
