Select Git revision
-
Marcel Nellesen authoredMarcel Nellesen authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ProjectController.cs 16.92 KiB
using Coscine.Action;
using Coscine.Action.EventArgs;
using Coscine.ApiCommons;
using Coscine.ApiCommons.Factories;
using Coscine.Configuration;
using Coscine.Database.DataModel;
using Coscine.Database.Models;
using Coscine.Database.ReturnObjects;
using Coscine.Database.Util;
using Coscine.Logging;
using Coscine.Metadata;
using Coscine.ResourceLoader;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Coscine.Api.Project.Controllers
{
[Authorize]
public class ProjectController : Controller
{
private readonly Authenticator _authenticator;
private readonly ProjectModel _projectModel;
private readonly IConfiguration _configuration;
private readonly Emitter _emitter;
private readonly ActivatedFeaturesModel _activatedFeaturesModel;
private readonly ProjectRoleModel _projectRoleModel;
private readonly CoscineLogger _coscineLogger;
private readonly AnalyticsLogObject _analyticsLogObject;
public ProjectController(ILogger<ProjectController> logger)
{
_authenticator = new Authenticator(this, Program.Configuration);
_configuration = Program.Configuration;
_projectModel = new ProjectModel();
_emitter = new Emitter(_configuration);
_activatedFeaturesModel = new ActivatedFeaturesModel();
_projectRoleModel = new ProjectRoleModel();
_coscineLogger = new CoscineLogger(logger);
_analyticsLogObject = new AnalyticsLogObject();
}
[Route("[controller]")]
public IActionResult Index()
{
var user = _authenticator.GetUser();
var result = _projectModel.GetWithAccess(user, UserRoles.Member, UserRoles.Owner).ToList()
.Select((project) => _projectModel.CreateReturnObjectFromDatabaseObject(project))
.OrderBy(element => element.DisplayName);
if (Request.Query != null && Request.Query["noanalyticslog"] != "true")
{
LogAnalytics("List Projects", result);
}
return Ok(result);
}
[Route("[controller]/-/topLevel")]
public IActionResult GetTopLevelProjects()
{
var user = _authenticator.GetUser();
var result = _projectModel.GetTopLevelWithAccess(user, UserRoles.Member, UserRoles.Owner).ToList()
.Select((project) => _projectModel.CreateReturnObjectFromDatabaseObject(project))
.OrderBy(element => element.DisplayName);
if (Request.Query != null && Request.Query["noanalyticslog"] != "true")
{
LogAnalytics("View Home", result);
}
return Ok(result);
}
[HttpGet("[controller]/{id}")]
public IActionResult Get(string id)
{
var user = _authenticator.GetUser();
var project = _projectModel.GetById(Guid.Parse(id));
if (_projectModel.HasAccess(user, project, UserRoles.Member, UserRoles.Owner))
{
SubProjectModel subProjectModel = new SubProjectModel();
var subProjectRel = subProjectModel.GetAllWhere((subProject) => subProject.SubProjectId == project.Id && project.Deleted == false);
var parentProjectRelation = subProjectRel.FirstOrDefault();
if (parentProjectRelation != null && _projectModel.HasAccess(user, parentProjectRelation.ProjectId, UserRoles.Member, UserRoles.Owner))
{
return Ok(_projectModel.CreateReturnObjectFromDatabaseObject(project, parentProjectRelation.ProjectId));
}
return Ok(_projectModel.CreateReturnObjectFromDatabaseObject(project));
}
else
{
return Unauthorized($"User is not allowed to see given the project {id}");
}
}
[HttpGet("[controller]/{id}/resources")]
public IActionResult GetResources(string id)
{
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))
{
var resources = resourceModel.GetAllWhere((resource) =>
(from projectResource in resource.ProjectResourceResourceIdIds
where projectResource.ProjectId == project.Id
select projectResource).Any())
.Select((resource) =>
{
return resourceModel.CreateReturnObjectFromDatabaseObject(resource);
}).OrderBy(element => element.DisplayName);
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
}
return Json(resources);
}
else
{
return Unauthorized($"User is not allowed to see given the project {id}");
}
}
[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));
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) =>
resource.TypeId == projectQuota.ResourceType.Id
&& (from connection in resource.ProjectResourceResourceIdIds
where connection.ProjectId == guidId
select connection).Any());
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!");
}
}
[HttpPost("[controller]/{id}")]
public IActionResult Update(string id)
{
var user = _authenticator.GetUser();
var projectObject = ObjectFactory<ProjectObject>.DeserializeFromStream(Request.Body);
var project = _projectModel.GetById(Guid.Parse(id));
if (_projectModel.HasAccess(user, project, UserRoles.Owner))
{
LogAnalytics("Edit Project", null, null, id, user);
return Ok(_projectModel.UpdateByObject(project, projectObject));
}
else
{
return Unauthorized("The user is not authorized to perform an update on the selected project!");
}
}
[HttpDelete("[controller]/{id}")]
public IActionResult Delete(string id)
{
var user = _authenticator.GetUser();
var project = _projectModel.GetById(Guid.Parse(id));
if (_projectModel.HasAccess(user, project, UserRoles.Owner))
{
LogAnalytics("Delete Project", null, null, id, user);
DeleteProject(project);
return Json(_projectModel.CreateReturnObjectFromDatabaseObject(project));
}
else
{
return Unauthorized("The user is not authorized to perform an update on the selected project!");
}
}
public void DeleteProject(Database.DataModel.Project project, bool isHard = false, bool propegateAction = true)
{
var subProjectModel = new SubProjectModel();
foreach (var subProject in subProjectModel.GetAllWhere(
(subProject) => subProject.ProjectId == project.Id
&& (subProject.SubProject_FK.Deleted == false || isHard)
))
{
Database.DataModel.Project subProjectObject;
if (isHard)
{
subProjectObject = _projectModel.GetByIdIncludingDeleted(subProject.SubProjectId);
subProjectModel.Delete(subProject);
}
else
{
subProjectObject = _projectModel.GetById(subProject.SubProjectId);
}
DeleteProject(subProjectObject, isHard, propegateAction);
}
foreach (var subProject in subProjectModel.GetAllWhere((subProject) => subProject.SubProjectId == project.Id))
{
if (isHard)
{
subProjectModel.Delete(subProject);
}
}
if (isHard)
{
var projectResourceModel = new ProjectResourceModel();
var resourceModel = new ResourceModel();
var resourceTypeModel = new ResourceTypeModel();
foreach (var projectResource in projectResourceModel.GetAllWhere((projectResource) => projectResource.ProjectId == project.Id))
{
var resource = resourceModel.GetById(projectResource.ResourceId);
var resourceTypeOptions = resourceModel.GetResourceTypeOptions(projectResource.ResourceId);
var resourceTypeDefinition = ResourceTypeFactory.CreateResourceTypeObject(resourceTypeModel.GetById(resource.TypeId).DisplayName, _configuration);
resourceTypeDefinition.DeleteResource(projectResource.ResourceId.ToString(), resourceTypeOptions);
projectResourceModel.Delete(projectResource);
resourceModel.Delete(resource);
}
var projectRoleModel = new ProjectRoleModel();
foreach (var projectRole in projectRoleModel.GetAllWhere((projectRole) => projectRole.ProjectId == project.Id))
{
projectRoleModel.Delete(projectRole);
}
var projectDisciplineModel = new ProjectDisciplineModel();
foreach (var projectDiscipline in projectDisciplineModel.GetAllWhere((projectDiscipline) => projectDiscipline.ProjectId == project.Id))
{
projectDisciplineModel.Delete(projectDiscipline);
}
var projectInstituteModel = new ProjectInstituteModel();
foreach (var projectInstitute in projectInstituteModel.GetAllWhere((projectInstitute) => projectInstitute.ProjectId == project.Id))
{
projectInstituteModel.Delete(projectInstitute);
}
var projectQuotaModel = new ProjectQuotaModel();
foreach (var projectQuota in projectQuotaModel.GetAllWhere((Quota) => Quota.ProjectId == project.Id))
{
projectQuotaModel.Delete(projectQuota);
}
_activatedFeaturesModel.DeactivateAllFeatures(project);
if (propegateAction)
{
_emitter.EmitProjectDelete(new ProjectEventArgs(_configuration)
{
Project = project
});
}
_projectModel.HardDelete(project);
}
else
{
_projectModel.Delete(project);
}
}
[HttpPost("[controller]")]
public IActionResult Store()
{
var user = _authenticator.GetUser();
var isRWTHMember = IsRWTHMember(user);
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, isRWTHMember);
if (projectObject.ParentId != null
&& 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
});
LogAnalytics("Add Project", null, null, project.Id.ToString(), user);
return Json(_projectModel.CreateReturnObjectFromDatabaseObject(project));
}
private bool IsRWTHMember(User user)
{
var externalIds = new ExternalIdModel().GetAllWhere((externalId) => externalId.UserId == user.Id);
if(externalIds.Count() == 0)
{
return false;
}
var externalIdList = new List<string>();
foreach (var externalId in externalIds)
{
externalIdList.Add(externalId.ExternalIdColumn);
}
return new RdfStoreConnector(Program.Configuration.GetStringAndWait("coscine/local/virtuoso/additional/url")).GetTriples(new Uri("https://ror.org/04xfq0f34"), null, null, 1, externalIdList).Count() != 0;
}
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);
}
}
}
}