ProjectController.cs 15.1 KB
Newer Older
1
using Coscine.Action;
2
using Coscine.Action.EventArgs;
Marcel Nellesen's avatar
Marcel Nellesen committed
3
4
using Coscine.Database.Models;
using Coscine.Database.ReturnObjects;
5
6
using Coscine.ApiCommons;
using Coscine.ApiCommons.Factories;
7
8
9
using Microsoft.AspNetCore.Mvc;
using System;
using System.Linq;
10
using Coscine.Configuration;
11
using Microsoft.AspNetCore.Authorization;
Marcel Nellesen's avatar
Marcel Nellesen committed
12
using Coscine.Database.Util;
13
14
15
16
17
using Coscine.Logging;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Coscine.Database.DataModel;
using System.Collections.Generic;
18
using System.Text.RegularExpressions;
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
19
20
21

namespace Coscine.Api.Project.Controllers
{
22
    [Authorize]
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
23
24
25
    public class ProjectController : Controller
    {
        private readonly Authenticator _authenticator;
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
26
        private readonly ProjectModel _projectModel;
27
        private readonly IConfiguration _configuration;
28
        private readonly Emitter _emitter;
Marcel Nellesen's avatar
Marcel Nellesen committed
29
        private readonly ActivatedFeaturesModel _activatedFeaturesModel;
30
31
32
        private readonly ProjectRoleModel _projectRoleModel;
        private readonly CoscineLogger _coscineLogger;
        private readonly AnalyticsLogObject _analyticsLogObject;
33

34
        public ProjectController(ILogger<ProjectController> logger)
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
35
        {
36
            _authenticator = new Authenticator(this, Program.Configuration);
37
            _configuration = Program.Configuration;
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
38
            _projectModel = new ProjectModel();
39
            _emitter = new Emitter(_configuration);
Marcel Nellesen's avatar
Marcel Nellesen committed
40
            _activatedFeaturesModel = new ActivatedFeaturesModel();
41
42
43
            _projectRoleModel = new ProjectRoleModel();
            _coscineLogger = new CoscineLogger(logger);
            _analyticsLogObject = new AnalyticsLogObject();
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
44
        }
45
        
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
46
47
48
        [Route("[controller]")]
        public IActionResult Index()
        {
49
            var user = _authenticator.GetUser();
50
            var result = _projectModel.GetWithAccess(user, UserRoles.Member, UserRoles.Owner).ToList()
51
                .Select((project) => _projectModel.CreateReturnObjectFromDatabaseObject(project))
52
53
                .OrderBy(element => element.DisplayName);

54
55
56
57
            if (Request.Query != null && Request.Query["noanalyticslog"] != "true")
            {
                LogAnalytics("View Home", result);
            }
58
59

            return Ok(result);
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
60
61
62
63
64
        }

        [HttpGet("[controller]/{id}")]
        public IActionResult Get(string id)
        {
65
66
67
68
            var user = _authenticator.GetUser();
            var project = _projectModel.GetById(Guid.Parse(id));
            if (_projectModel.HasAccess(user, project, UserRoles.Member, UserRoles.Owner))
            {
69
                SubProjectModel subProjectModel = new SubProjectModel();
70
                var subProjectRel = subProjectModel.GetAllWhere((subProject) => subProject.SubProjectId == project.Id && project.Deleted == false);
71
72
73
74
75
76
                
                var parentProjectRelation = subProjectRel.FirstOrDefault();
                if (parentProjectRelation != null && _projectModel.HasAccess(user, parentProjectRelation.ProjectId, UserRoles.Member, UserRoles.Owner))
                {
                    return Ok(_projectModel.CreateReturnObjectFromDatabaseObject(project, parentProjectRelation.ProjectId));
                }
77
78
79
80
81
82
                return Ok(_projectModel.CreateReturnObjectFromDatabaseObject(project));
            }
            else
            {
                return Unauthorized($"User is not allowed to see given the project {id}");
            }
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
83
84
        }

85
86
87
        [HttpGet("[controller]/{id}/resources")]
        public IActionResult GetResources(string id)
        {
88
89
90
91
92
93
94
            var project = _projectModel.GetById(Guid.Parse(id));
            var user = _authenticator.GetUser();

            var resourceModel = new ResourceModel();
            var resourceTypeModel = new ResourceTypeModel();
            if (_projectModel.HasAccess(user, project, UserRoles.Member, UserRoles.Owner))
            {
95
                var resources = resourceModel.GetAllWhere((resource) =>
96
97
98
99
100
101
                        (from projectResource in resource.ProjectResourceResourceIdIds
                         where projectResource.ProjectId == project.Id
                         select projectResource).Any())
                        .Select((resource) =>
                        {
                            return resourceModel.CreateReturnObjectFromDatabaseObject(resource);
102
                        }).OrderBy(element => element.DisplayName);
103
104
105
106
                if (Request.Query != null && Request.Query["noanalyticslog"] != "true")
                {
                    LogAnalytics("View Project", null, resources, id, user); // intentionally log as view project to help identify the related user action
                }
107
                return Json(resources);
108
109
110
111
112
            }
            else
            {
                return Unauthorized($"User is not allowed to see given the project {id}");
            }
113
114
        }

115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
        [HttpGet("[controller]/{id}/quotas")]
        public IActionResult Quotas(string id)
        {
            var user = _authenticator.GetUser();
            var projectObject = ObjectFactory<ProjectObject>.DeserializeFromStream(Request.Body);
            var guidId = Guid.Parse(id);
            var project = _projectModel.GetById(guidId);
            if (_projectModel.HasAccess(user, project, UserRoles.Owner))
            {
                ProjectQuotaModel projectQuotaModel = new ProjectQuotaModel();
                var projectQuotas =
                    projectQuotaModel.GetAllWhere((projectQuota) =>
                        projectQuota.ProjectId == guidId
                        && projectQuota.ResourceType.Enabled == true)
                    .Select((projectQuota) => projectQuotaModel.CreateReturnObjectFromDatabaseObject(projectQuota));

131

132
133
134
135
136
137
138
139
140
                ResourceModel resourceModel = new ResourceModel();
                RDSResourceTypeModel rdsResourceTypeModel = new RDSResourceTypeModel();
                var returnList = new List<dynamic>();
                foreach (var projectQuota in projectQuotas)
                {
                    // TODO: Cleanup quota and give it to every resource, this hard coded solution seems not scalable
                    if (projectQuota.ResourceType.DisplayName == "rds") 
                    {
                        var resources = resourceModel.GetAllWhere((resource) =>
141
142
143
144
                                            resource.TypeId == projectQuota.ResourceType.Id
                                            && (from connection in resource.ProjectResourceResourceIdIds
                                                where connection.ProjectId == guidId
                                                select connection).Any());
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
                        
                        var size = resources.Sum((resource) => 
                                rdsResourceTypeModel.GetById(resource.ResourceTypeOptionId.Value).Size);
                        returnList.Add(new { 
                            type = projectQuota.ResourceType.DisplayName, 
                            available = projectQuota.Quotas,
                            allocated = size
                        });
                    }
                }
                return Json(returnList);
            }
            else
            {
                return Unauthorized("The user is not authorized to perform a get on the selected project!");
            }
        }
162

Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
163
164
165
        [HttpPost("[controller]/{id}")]
        public IActionResult Update(string id)
        {
166
167
168
            var user = _authenticator.GetUser();
            var projectObject = ObjectFactory<ProjectObject>.DeserializeFromStream(Request.Body);
            var project = _projectModel.GetById(Guid.Parse(id));
169
            if (_projectModel.HasAccess(user, project, UserRoles.Owner))
170
            {
171
                LogAnalytics("Edit Project", null, null, id, user);
172
173
174
175
176
177
                return Ok(_projectModel.UpdateByObject(project, projectObject));
            }
            else
            {
                return Unauthorized("The user is not authorized to perform an update on the selected project!");
            }
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
178
179
        }

180
181
182
        [HttpDelete("[controller]/{id}")]
        public IActionResult Delete(string id)
        {
183
184
185
186
            var user = _authenticator.GetUser();
            var project = _projectModel.GetById(Guid.Parse(id));
            if (_projectModel.HasAccess(user, project, UserRoles.Owner))
            {
187
                LogAnalytics("Delete Project", null, null, id, user);
188
189
190
191
192
193
194
                DeleteProject(project);
                return Json(_projectModel.CreateReturnObjectFromDatabaseObject(project));
            }
            else
            {
                return Unauthorized("The user is not authorized to perform an update on the selected project!");
            }
195
196
        }

Marcel Nellesen's avatar
Marcel Nellesen committed
197
        public void DeleteProject(Database.DataModel.Project project, bool isHard = false, bool propegateAction = true)
198
        {
199
            var subProjectModel = new SubProjectModel();
200
201
202
203
            foreach (var subProject in subProjectModel.GetAllWhere(
                (subProject) => subProject.ProjectId == project.Id
                                && (subProject.SubProject_FK.Deleted == false || isHard)
            ))
204
            {
Marcel Nellesen's avatar
Marcel Nellesen committed
205
                Database.DataModel.Project subProjectObject;
206
207
208
                if (isHard)
                {
                    subProjectObject = _projectModel.GetByIdIncludingDeleted(subProject.SubProjectId);
209
                    subProjectModel.Delete(subProject);
210
211
212
213
214
215
                }
                else
                {
                    subProjectObject = _projectModel.GetById(subProject.SubProjectId);
                }
                DeleteProject(subProjectObject, isHard, propegateAction);
216
217
218
219
            }

            foreach (var subProject in subProjectModel.GetAllWhere((subProject) => subProject.SubProjectId == project.Id))
            {
220
221
222
223
                if (isHard)
                {
                    subProjectModel.Delete(subProject);
                }
224
225
            }

226
            var projectResourceModel = new ProjectResourceModel();
227
228
229
            ResourceModel resourceModel = new ResourceModel();
            foreach (var projectResource in projectResourceModel.GetAllWhere((projectResource) => projectResource.ProjectId == project.Id))
            {
230
231
232
233
234
                if (isHard)
                {
                    projectResourceModel.Delete(projectResource);
                    resourceModel.Delete(resourceModel.GetById(projectResource.ResourceId));
                }
235
236
            }

237
            var projectRoleModel = new ProjectRoleModel();
238
239
            foreach (var projectRole in projectRoleModel.GetAllWhere((projectRole) => projectRole.ProjectId == project.Id))
            {
240
241
242
243
                if (isHard)
                {
                    projectRoleModel.Delete(projectRole);
                }
244
245
            }

246
            var projectDisciplineModel = new ProjectDisciplineModel();
247
248
            foreach (var projectDiscipline in projectDisciplineModel.GetAllWhere((projectDiscipline) => projectDiscipline.ProjectId == project.Id))
            {
249
250
251
252
                if (isHard)
                {
                    projectDisciplineModel.Delete(projectDiscipline);
                }
253
254
            }

255
            var projectInstituteModel = new ProjectInstituteModel();
256
257
            foreach (var projectInstitute in projectInstituteModel.GetAllWhere((projectInstitute) => projectInstitute.ProjectId == project.Id))
            {
258
259
260
261
                if (isHard)
                {
                    projectInstituteModel.Delete(projectInstitute);
                }
262
263
            }

Marcel Nellesen's avatar
Marcel Nellesen committed
264
265
266
267
268
            if(isHard)
            {
                _activatedFeaturesModel.DeactivateAllFeatures(project);
            }

269
            if (isHard)
270
            {
271
272
273
274
275
276
277
278
                if (propegateAction)
                {
                    _emitter.EmitProjectDelete(new ProjectEventArgs(_configuration)
                    {
                        Project = project
                    });
                }
            }
279

280
281
282
283
284
285
286
287
            if (isHard)
            {
                _projectModel.HardDelete(project);
            } 
            else
            {
                _projectModel.Delete(project);
            }
288
289
        }

290
        [HttpPost("[controller]")]
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
291
292
        public IActionResult Store()
        {
293
294
295
296
297
298
299
300
301
302
303
304
            var user = _authenticator.GetUser();
            var projectObject = ObjectFactory<ProjectObject>.DeserializeFromStream(Request.Body);

            if (projectObject.ParentId != null
                && projectObject.ParentId != new Guid()
                && !_projectModel.HasAccess(user, _projectModel.GetById(projectObject.ParentId), UserRoles.Owner))
            {
                return Unauthorized("User is not allowed to create SubProjects.");
            }

            var project = _projectModel.StoreFromObject(projectObject, user);

305
            if (projectObject.ParentId != null
306
307
308
309
310
311
312
313
314
315
316
317
318
319
                && projectObject.ParentId != new Guid()
                // for now, only an owner can add subprojects to projects
                && _projectModel.HasAccess(user, _projectModel.GetById(projectObject.ParentId), UserRoles.Owner))
            {
                var subProjectModel = new SubProjectModel();
                subProjectModel.LinkSubProject(projectObject.ParentId, project.Id);
            }

            _emitter.EmitProjectCreate(new ProjectEventArgs(_configuration)
            {
                Project = project,
                ProjectOwner = user
            });

320
321
            LogAnalytics("Add Project", null, null, project.Id.ToString(), user);

322
            return Json(_projectModel.CreateReturnObjectFromDatabaseObject(project));
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
323
        }
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365

        private void LogAnalytics(string operation,
            IEnumerable<ProjectObject> projects = null,
            IEnumerable<ResourceObject> resources = null,
            string projectId = null,
            User user = null
        )
        {
            if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics))
            {
                _analyticsLogObject.Type = "Action";
                _analyticsLogObject.Operation = operation;

                if (projects != null)
                {
                    List<string> projectList = new List<string>();
                    foreach (var entry in projects)
                    {
                        projectList.Add(entry.Id.ToString());
                    }
                    _analyticsLogObject.ProjectList = projectList;
                }
                if (resources != null)
                {
                    List<string> shownResources = new List<string>();
                    foreach (var entry in resources)
                    {
                        shownResources.Add(entry.Id.ToString());
                    }
                    _analyticsLogObject.ResourceList = shownResources;
                }
                if (projectId != null)
                {
                    _analyticsLogObject.ProjectId = projectId;
                    if (user != null)
                    {
                        _analyticsLogObject.RoleId = _projectRoleModel.GetGetUserRoleForProject(new Guid(_analyticsLogObject.ProjectId), user.Id).ToString();
                    }
                }
                _coscineLogger.AnalyticsLog(_analyticsLogObject);
            }
        }
Benedikt Heinrichs's avatar
Benedikt Heinrichs committed
366
367
    }
}