Projekt

Obecné

Profil

Stáhnout (8.76 KB) Statistiky
| Větev: | Tag: | Revize:
1
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
using AutoMapper;
13
using Models.Users;
14
using Ganss.XSS;
15
using Microsoft.EntityFrameworkCore;
16

    
17
namespace Core.Services.DocumentService
18
{
19
    public class DocumentServiceEF : IDocumentService
20
    {
21
        private readonly DatabaseContext databaseContext;
22
        private readonly ILogger logger;
23
        private readonly IMapper mapper;
24

    
25
        public DocumentServiceEF(DatabaseContext databaseContext, ILogger logger, IMapper mapper)
26
        {
27
            this.databaseContext = databaseContext;
28
            this.logger = logger;
29
            this.mapper = mapper;
30
        }
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
            int requiredAnnotations = int.Parse(databaseContext.ConfigurationItems.Single(ci => ci.Key == Constants.Constants.RequiredAnnotationsKey).Value);
45

    
46
            foreach (var documentInfo in request.Documents)
47
            {
48
                if (documentInfo.Format == Models.Enums.EAddDocumentFormat.TEXTFILE)
49
                {
50
                    // TODO hardcoded UTF-8 - maybe do something smarter
51
                    var documentContent = Encoding.UTF8.GetString(Convert.FromBase64String(documentInfo.Content));
52
                    SaveDocument(documentContent, user, documentInfo.Name, requiredAnnotations);
53
                }
54
                else if (documentInfo.Format == Models.Enums.EAddDocumentFormat.ZIP)
55
                {
56
                    var (names, contents) = UnzipDocuments(documentInfo.Content);
57
                    for (int i = 0; i < names.Count; i++)
58
                    {
59
                        SaveDocument(contents[i], user, names[i], requiredAnnotations);
60
                    }
61
                }
62
            }
63
        }
64

    
65
        /// <summary>
66
        /// 
67
        /// </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
        private void SaveDocument(string content, User userAdded, string documentName, int requiredAnnotations)
95
        {
96
            DocumentContent documentContent = new DocumentContent()
97
            {
98
                Content = content
99
            };
100

    
101
            Document document = new Document()
102
            {
103
                DateAdded = DateTime.Now,
104
                Content = documentContent,
105
                UserAdded = userAdded,
106
                Name = documentName,
107
                Length = documentContent.Content.Length,
108
                RequiredAnnotations = requiredAnnotations
109
            };
110

    
111
            databaseContext.DocumentContents.Add(documentContent);
112
            databaseContext.Documents.Add(document);
113
            databaseContext.SaveChanges();
114
        }
115

    
116
        public DocumentListResponse GetDocuments()
117
        {
118
            var documents = databaseContext.Documents.ToList();
119
            List<DocumentListInfo> documentInfos = new List<DocumentListInfo>();
120
            foreach (var document in documents)
121
            {
122
                var annotatingUsers = databaseContext.Annotations
123
                    .Where(a => !(a is FinalAnnotation))
124
                    .Where(a => a.Document == document)
125
                    .Select(a => a.User).ToList();
126

    
127
                List<DocumentUserInfo> annotatingUsersDto = new();
128

    
129
                // Include annotation state
130
                foreach (var annotatingUser in annotatingUsers)
131
                {
132
                    var annotation = databaseContext.Annotations
133
                        .Where(a => !(a is FinalAnnotation))
134
                        .Include(a => a.Document)
135
                        .Single(a => a.Document == document && a.User == annotatingUser && !(a is FinalAnnotation));
136
                    var dui = mapper.Map<DocumentUserInfo>(annotatingUser);
137
                    dui.State = annotation.State;
138
                    annotatingUsersDto.Add(dui);
139
                }
140

    
141
                DocumentListInfo dli = mapper.Map<DocumentListInfo>(document);
142
                dli.AnnotatingUsers = annotatingUsersDto;
143

    
144
                dli.FinalizedExists = databaseContext.FinalAnnotations.Any(fa => fa.Document == document);
145
                if (dli.FinalizedExists)
146
                {
147
                    var finalizedAnnotation = databaseContext.FinalAnnotations
148
                        .Include(fa => fa.Annotations)
149
                        .ThenInclude(a => a.User)
150
                        .Single(fa => fa.Document == document);
151
                    
152
                    dli.FinalizedAnnotationId = finalizedAnnotation.Id;
153
                    dli.FinalizedState = finalizedAnnotation.State;
154
                    dli.FinalAnnotations = new();
155

    
156
                    foreach (var annotation in finalizedAnnotation.Annotations)
157
                    {
158
                        dli.FinalAnnotations.Add(new()
159
                        {
160
                            AnnotationId = annotation.Id,
161
                            UserId = annotation.User.Id,
162
                            Username = annotation.User.Username,
163
                            UserFirstName = annotation.User.Name,
164
                            UserSurname = annotation.User.Surname,
165
                        });
166
                    }
167

    
168
                }
169

    
170
                documentInfos.Add(dli);
171
            }
172

    
173
            return new DocumentListResponse()
174
            {
175
                Documents = documentInfos.OrderBy(di => di.Name).ToList()
176
            };
177
        }
178

    
179
        public void SetRequiredAnnotationsForDocuments(SetRequiredAnnotationsRequest request)
180
        {
181
            var documents = databaseContext.Documents.Where(d => request.DocumentIds.Contains(d.Id));
182
            foreach (var doc in documents)
183
            {
184
                doc.RequiredAnnotations = request.RequiredAnnotations;
185
            }
186
            databaseContext.SaveChanges();
187
        }
188

    
189
        public void SetRequiredAnnotationsGlobal(int requiredAnnotations)
190
        {
191
            var requiredAnnotationsItem = databaseContext.ConfigurationItems.Single(ci => ci.Key == Constants.Constants.RequiredAnnotationsKey);
192
            requiredAnnotationsItem.Value = requiredAnnotations.ToString();
193
            databaseContext.SaveChanges();
194
        }
195

    
196
        public int GetRequiredAnnotationsGlobal()
197
        {
198
            var requiredAnnotationsItem = databaseContext.ConfigurationItems.Single(ci => ci.Key == Constants.Constants.RequiredAnnotationsKey);
199
            return int.Parse(requiredAnnotationsItem.Value);
200
        }
201

    
202
        public DocumentPreviewResponse GetDocumentPreview(Guid documentId)
203
        {
204
            try
205
            {
206
                var document = databaseContext.Documents.Include(d => d.Content).Single(d => d.Id == documentId);
207
                HtmlSanitizer sanitizer = new HtmlSanitizer();
208
                sanitizer.AllowedAttributes.Clear();
209
                if (sanitizer.AllowedTags.Contains("img"))
210
                {
211
                    sanitizer.AllowedTags.Remove("img");
212
                }
213
                return new DocumentPreviewResponse()
214
                {
215
                    Content = sanitizer.Sanitize(document.Content.Content)
216
                };
217
            }
218
            catch (InvalidOperationException e)
219
            {
220
                throw new InvalidOperationException("Document not found");
221
            }
222
        }
223
    }
224
}
(1-1/2)