Projekt

Obecné

Profil

Stáhnout (10.3 KB) Statistiky
| Větev: | Tag: | Revize:
1 24e1c89d Vojtěch Bartička
using Core.Contexts;
2
using Core.Entities;
3
using Models.Documents;
4
using Serilog;
5
using System;
6
using System.Collections.Generic;
7
using System.IO.Compression;
8
using System.Linq;
9
using System.Text;
10
using System.Threading.Tasks;
11
using System.Web;
12 5a08541d Vojtěch Bartička
using AutoMapper;
13
using Models.Users;
14 3c185841 Vojtěch Bartička
using Ganss.XSS;
15 42bb0025 Vojtěch Bartička
using Microsoft.EntityFrameworkCore;
16 24e1c89d Vojtěch Bartička
17
namespace Core.Services.DocumentService
18
{
19
    public class DocumentServiceEF : IDocumentService
20
    {
21
        private readonly DatabaseContext databaseContext;
22
        private readonly ILogger logger;
23 5a08541d Vojtěch Bartička
        private readonly IMapper mapper;
24 24e1c89d Vojtěch Bartička
25 5a08541d Vojtěch Bartička
        public DocumentServiceEF(DatabaseContext databaseContext, ILogger logger, IMapper mapper)
26 24e1c89d Vojtěch Bartička
        {
27
            this.databaseContext = databaseContext;
28
            this.logger = logger;
29 5a08541d Vojtěch Bartička
            this.mapper = mapper;
30 24e1c89d Vojtěch Bartička
        }
31
32
        /// <summary>
33
        /// Adds the documents in request to the database
34
        /// </summary>
35
        /// <param name="request">request</param>
36
        /// <param name="userId">GUID of the user</param>
37
        /// <exception cref="InvalidOperationException">No User with passed GUID</exception>
38
        /// <exception cref="FormatException">Error decoding BASE64 content</exception>
39
        /// <exception cref="InvalidDataException">Zip file has wrong format</exception>
40
        /// <exception cref="IOException">Error reading entries from the zip file</exception>
41
        public void AddDocuments(DocumentAddRequest request, Guid userId)
42
        {
43
            User user = databaseContext.Users.Single(u => u.Id == userId);
44 ceb95b98 Vojtěch Bartička
            int requiredAnnotations = int.Parse(databaseContext.ConfigurationItems.Single(ci => ci.Key == Constants.Constants.RequiredAnnotationsKey).Value);
45 005202c6 Vojtěch Bartička
46 24e1c89d Vojtěch Bartička
            foreach (var documentInfo in request.Documents)
47
            {
48 52fe46f9 Vojtěch Bartička
                if (documentInfo.Format == Models.Enums.EAddDocumentFormat.TEXTFILE)
49 24e1c89d Vojtěch Bartička
                {
50 7b2e66d3 Vojtěch Bartička
                    // TODO hardcoded UTF-8 - maybe do something smarter
51
                    var documentContent = Encoding.UTF8.GetString(Convert.FromBase64String(documentInfo.Content));
52 ceb95b98 Vojtěch Bartička
                    SaveDocument(documentContent, user, documentInfo.Name, requiredAnnotations);
53 24e1c89d Vojtěch Bartička
                }
54 7b2e66d3 Vojtěch Bartička
                else if (documentInfo.Format == Models.Enums.EAddDocumentFormat.ZIP)
55 24e1c89d Vojtěch Bartička
                {
56
                    var (names, contents) = UnzipDocuments(documentInfo.Content);
57
                    for (int i = 0; i < names.Count; i++)
58
                    {
59 ceb95b98 Vojtěch Bartička
                        SaveDocument(contents[i], user, names[i], requiredAnnotations);
60 24e1c89d Vojtěch Bartička
                    }
61
                }
62
            }
63
        }
64
65
        /// <summary>
66 a35cb648 Vojtěch Bartička
        /// Process a zip file and returns a list of names and documents
67 24e1c89d Vojtěch Bartička
        /// </summary>
68
        /// <param name="base64encoded"></param>
69
        /// <returns></returns>
70
        private (List<string> Names, List<string> Contents) UnzipDocuments(string base64encoded)
71
        {
72
            List<string> names = new();
73
            List<string> contents = new();
74
75
            byte[] decoded = Convert.FromBase64String(base64encoded);
76
77
            using (var zipStream = new MemoryStream(decoded))
78
            using (var zipArchive = new ZipArchive(zipStream))
79
            {
80
                foreach (var entry in zipArchive.Entries)
81
                {
82
                    names.Add(entry.Name);
83
                    using (var streamReader = new StreamReader(entry.Open()))
84
                    {
85
                        string text = streamReader.ReadToEnd();
86
                        contents.Add(text);
87
                    }
88
                }
89
            }
90
91
            return (names, contents);
92
        }
93
94 a35cb648 Vojtěch Bartička
        /// <summary>
95
        /// Save a document in the database
96
        /// </summary>
97
        /// <param name="content"></param>
98
        /// <param name="userAdded"></param>
99
        /// <param name="documentName"></param>
100
        /// <param name="requiredAnnotations"></param>
101 ceb95b98 Vojtěch Bartička
        private void SaveDocument(string content, User userAdded, string documentName, int requiredAnnotations)
102 24e1c89d Vojtěch Bartička
        {
103
            DocumentContent documentContent = new DocumentContent()
104
            {
105
                Content = content
106
            };
107
108
            Document document = new Document()
109
            {
110
                DateAdded = DateTime.Now,
111
                Content = documentContent,
112
                UserAdded = userAdded,
113
                Name = documentName,
114
                Length = documentContent.Content.Length,
115 ceb95b98 Vojtěch Bartička
                RequiredAnnotations = requiredAnnotations
116 24e1c89d Vojtěch Bartička
            };
117
118
            databaseContext.DocumentContents.Add(documentContent);
119
            databaseContext.Documents.Add(document);
120 5adba4c4 Vojtěch Bartička
            databaseContext.SaveChanges();
121 24e1c89d Vojtěch Bartička
        }
122
123 004c4a4e Vojtěch Bartička
        public DocumentListResponse GetDocuments()
124 24e1c89d Vojtěch Bartička
        {
125 004c4a4e Vojtěch Bartička
            var documents = databaseContext.Documents.ToList();
126 24e1c89d Vojtěch Bartička
            List<DocumentListInfo> documentInfos = new List<DocumentListInfo>();
127 004c4a4e Vojtěch Bartička
            foreach (var document in documents)
128 24e1c89d Vojtěch Bartička
            {
129 8c9ce202 Vojtěch Bartička
                var annotatingUsers = databaseContext.Annotations
130
                    .Where(a => !(a is FinalAnnotation))
131
                    .Where(a => a.Document == document)
132
                    .Select(a => a.User).ToList();
133
134 3cee56d3 Vojtěch Bartička
                List<DocumentUserInfo> annotatingUsersDto = new();
135 85b8834f Vojtěch Bartička
136 3cee56d3 Vojtěch Bartička
                // Include annotation state
137
                foreach (var annotatingUser in annotatingUsers)
138
                {
139
                    var annotation = databaseContext.Annotations
140 8c9ce202 Vojtěch Bartička
                        .Where(a => !(a is FinalAnnotation))
141 3cee56d3 Vojtěch Bartička
                        .Include(a => a.Document)
142 8c9ce202 Vojtěch Bartička
                        .Single(a => a.Document == document && a.User == annotatingUser && !(a is FinalAnnotation));
143 3cee56d3 Vojtěch Bartička
                    var dui = mapper.Map<DocumentUserInfo>(annotatingUser);
144 d7a375f5 Vojtěch Bartička
                    dui.AnnotationId = annotation.Id;
145 3cee56d3 Vojtěch Bartička
                    dui.State = annotation.State;
146
                    annotatingUsersDto.Add(dui);
147
                }
148 5a08541d Vojtěch Bartička
149 85b8834f Vojtěch Bartička
                DocumentListInfo dli = mapper.Map<DocumentListInfo>(document);
150 a35cb648 Vojtěch Bartička
                // Add list of users taht annotate the document
151 85b8834f Vojtěch Bartička
                dli.AnnotatingUsers = annotatingUsersDto;
152
153 a35cb648 Vojtěch Bartička
                // Add info about the finalized version
154 85b8834f Vojtěch Bartička
                dli.FinalizedExists = databaseContext.FinalAnnotations.Any(fa => fa.Document == document);
155
                if (dli.FinalizedExists)
156
                {
157
                    var finalizedAnnotation = databaseContext.FinalAnnotations
158
                        .Include(fa => fa.Annotations)
159
                        .ThenInclude(a => a.User)
160
                        .Single(fa => fa.Document == document);
161 c8159dc5 Vojtěch Bartička
162 4ed6b05c Vojtěch Bartička
                    dli.FinalizedAnnotationId = finalizedAnnotation.Id;
163 85b8834f Vojtěch Bartička
                    dli.FinalizedState = finalizedAnnotation.State;
164
                    dli.FinalAnnotations = new();
165
166 a35cb648 Vojtěch Bartička
                    // Add information about which annotations were used to create the finalized version
167 85b8834f Vojtěch Bartička
                    foreach (var annotation in finalizedAnnotation.Annotations)
168
                    {
169
                        dli.FinalAnnotations.Add(new()
170
                        {
171
                            AnnotationId = annotation.Id,
172
                            UserId = annotation.User.Id,
173
                            Username = annotation.User.Username,
174
                            UserFirstName = annotation.User.Name,
175 4ed6b05c Vojtěch Bartička
                            UserSurname = annotation.User.Surname,
176 85b8834f Vojtěch Bartička
                        });
177
                    }
178
179
                }
180
181
                documentInfos.Add(dli);
182 24e1c89d Vojtěch Bartička
            }
183
184
            return new DocumentListResponse()
185
            {
186 02fc62a8 Vojtěch Bartička
                Documents = documentInfos.OrderBy(di => di.Name).ToList()
187 24e1c89d Vojtěch Bartička
            };
188
        }
189
190 4540d7b6 Vojtěch Bartička
        public void RemoveAnnotatorFromDocument(Guid documentId, Guid annotatorId)
191
        {
192
            var document = databaseContext.Documents.Single(d => d.Id == documentId);
193
            var annotation = databaseContext.Annotations.Single(a => a.Document == document && a.User.Id == annotatorId );
194
195
            databaseContext.Annotations.Remove(annotation);
196
            databaseContext.SaveChanges();
197
        }
198
199 5adba4c4 Vojtěch Bartička
        public void SetRequiredAnnotationsForDocuments(SetRequiredAnnotationsRequest request)
200
        {
201
            var documents = databaseContext.Documents.Where(d => request.DocumentIds.Contains(d.Id));
202
            foreach (var doc in documents)
203
            {
204
                doc.RequiredAnnotations = request.RequiredAnnotations;
205
            }
206
            databaseContext.SaveChanges();
207
        }
208 0a6d22b7 Vojtěch Bartička
209
        public void SetRequiredAnnotationsGlobal(int requiredAnnotations)
210
        {
211 ceb95b98 Vojtěch Bartička
            var requiredAnnotationsItem = databaseContext.ConfigurationItems.Single(ci => ci.Key == Constants.Constants.RequiredAnnotationsKey);
212
            requiredAnnotationsItem.Value = requiredAnnotations.ToString();
213
            databaseContext.SaveChanges();
214 0a6d22b7 Vojtěch Bartička
        }
215
216 ceb95b98 Vojtěch Bartička
        public int GetRequiredAnnotationsGlobal()
217
        {
218
            var requiredAnnotationsItem = databaseContext.ConfigurationItems.Single(ci => ci.Key == Constants.Constants.RequiredAnnotationsKey);
219
            return int.Parse(requiredAnnotationsItem.Value);
220 3ea0ef00 Vojtěch Bartička
        }
221
222 c8159dc5 Vojtěch Bartička
        public void DeleteDocuments(DeleteDocumentsRequest request)
223
        {
224
            var documentsToDelete = databaseContext.Documents.
225
                Where(d => request.DocumentIds.Contains(d.Id)).ToList();
226
227
            var associatedAnnotations = databaseContext.Annotations.
228
                Where(a => documentsToDelete.Contains(a.Document)).ToList();
229
230
            databaseContext.Annotations.RemoveRange(associatedAnnotations);
231
            databaseContext.Documents.RemoveRange(documentsToDelete);
232
233
            databaseContext.SaveChanges();
234
        }
235
236 42bb0025 Vojtěch Bartička
        public DocumentPreviewResponse GetDocumentPreview(Guid documentId)
237
        {
238
            try
239
            {
240
                var document = databaseContext.Documents.Include(d => d.Content).Single(d => d.Id == documentId);
241
                HtmlSanitizer sanitizer = new HtmlSanitizer();
242 343aa66b Vojtěch Bartička
                sanitizer.AllowedAttributes.Clear();
243
                if (sanitizer.AllowedTags.Contains("img"))
244
                {
245
                    sanitizer.AllowedTags.Remove("img");
246
                }
247 42bb0025 Vojtěch Bartička
                return new DocumentPreviewResponse()
248
                {
249
                    Content = sanitizer.Sanitize(document.Content.Content)
250
                };
251
            }
252
            catch (InvalidOperationException e)
253
            {
254
                throw new InvalidOperationException("Document not found");
255
            }
256
        }
257 24e1c89d Vojtěch Bartička
    }
258
}