Skip to content
Snippets Groups Projects
Commit 7256d2c2 authored by Marcel Nellesen's avatar Marcel Nellesen
Browse files

Merge branch 'Sprint/2021-08' into 'master'

Sprint/2021 08

See merge request !143
parents c57d461d 294714ac
Branches
Tags
1 merge request!143Sprint/2021 08
File changed. Contains only whitespace changes. Show whitespace changes.
...@@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 ...@@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.28803.156 VisualStudioVersion = 16.0.28803.156
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Project", "Project\Project.csproj", "{16C4EBA5-BA87-45EC-AE1A-E8569A897959}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Project", "Project\Project.csproj", "{16C4EBA5-BA87-45EC-AE1A-E8569A897959}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Project.Tests", "Project.Tests\Project.Tests.csproj", "{EEE96892-A211-44EE-B2B8-11FAB31F2E26}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Project.Tests", "Project.Tests\Project.Tests.csproj", "{EEE96892-A211-44EE-B2B8-11FAB31F2E26}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
... ...
......
using Coscine.Action; using Coscine.Action;
using Coscine.Action.EventArgs; using Coscine.Action.EventArgs;
using Coscine.Action.Utils;
using Coscine.Api.Project.ParameterObjects; using Coscine.Api.Project.ParameterObjects;
using Coscine.Api.Project.ReturnObjects; using Coscine.Api.Project.ReturnObjects;
using Coscine.ApiCommons; using Coscine.ApiCommons;
...@@ -15,6 +16,7 @@ using Coscine.ResourceLoader; ...@@ -15,6 +16,7 @@ using Coscine.ResourceLoader;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
...@@ -39,7 +41,13 @@ namespace Coscine.Api.Project.Controllers ...@@ -39,7 +41,13 @@ namespace Coscine.Api.Project.Controllers
private readonly ResourceModel _resourceModel; private readonly ResourceModel _resourceModel;
private readonly CoscineLogger _coscineLogger; private readonly CoscineLogger _coscineLogger;
private readonly VisibilityModel _visibilityModel; private readonly VisibilityModel _visibilityModel;
private readonly InvitationModel _invitationModel;
private readonly RoleModel _roleModel;
private readonly UserModel _userModel;
private readonly int _maxAvailable = 100; private readonly int _maxAvailable = 100;
private readonly string _userUrlPrefix = "https://purl.org/coscine/users";
private readonly Uri _orgPrefixUrl = new Uri("http://www.w3.org/ns/org#");
private readonly RdfStoreConnector _rdfStoreConnector;
/// <summary> /// <summary>
/// ProjectController constructor /// ProjectController constructor
...@@ -58,6 +66,10 @@ namespace Coscine.Api.Project.Controllers ...@@ -58,6 +66,10 @@ namespace Coscine.Api.Project.Controllers
_projectQuotaModel = new ProjectQuotaModel(); _projectQuotaModel = new ProjectQuotaModel();
_coscineLogger = new CoscineLogger(logger); _coscineLogger = new CoscineLogger(logger);
_visibilityModel = new VisibilityModel(); _visibilityModel = new VisibilityModel();
_rdfStoreConnector = new RdfStoreConnector(Program.Configuration.GetString("coscine/local/virtuoso/additional/url"));
_invitationModel = new InvitationModel();
_roleModel = new RoleModel();
_userModel = new UserModel();
} }
/// <summary> /// <summary>
...@@ -506,6 +518,11 @@ namespace Coscine.Api.Project.Controllers ...@@ -506,6 +518,11 @@ namespace Coscine.Api.Project.Controllers
_projectQuotaModel.Delete(projectQuota); _projectQuotaModel.Delete(projectQuota);
} }
foreach (var invitation in _invitationModel.GetAllWhere((x) => x.Project == project.Id))
{
_invitationModel.Delete(invitation);
}
_activatedFeaturesModel.DeactivateAllFeatures(project); _activatedFeaturesModel.DeactivateAllFeatures(project);
if (propegateAction) if (propegateAction)
...@@ -532,7 +549,6 @@ namespace Coscine.Api.Project.Controllers ...@@ -532,7 +549,6 @@ namespace Coscine.Api.Project.Controllers
public IActionResult Store() public IActionResult Store()
{ {
var user = _authenticator.GetUser(); var user = _authenticator.GetUser();
var isRWTHMember = IsRWTHMember(user);
var projectObject = ObjectFactory<ProjectObject>.DeserializeFromStream(Request.Body); var projectObject = ObjectFactory<ProjectObject>.DeserializeFromStream(Request.Body);
if (projectObject?.ParentId != new Guid() if (projectObject?.ParentId != new Guid()
...@@ -541,7 +557,7 @@ namespace Coscine.Api.Project.Controllers ...@@ -541,7 +557,7 @@ namespace Coscine.Api.Project.Controllers
return Unauthorized("User is not allowed to create SubProjects."); return Unauthorized("User is not allowed to create SubProjects.");
} }
var project = _projectModel.StoreFromObject(projectObject, user, isRWTHMember); var project = _projectModel.StoreFromObject(projectObject, user, _rdfStoreConnector.GetQuotaDefault(user.Id.ToString()));
if (projectObject.ParentId != new Guid() if (projectObject.ParentId != new Guid()
// for now, only an owner can add subprojects to projects // for now, only an owner can add subprojects to projects
...@@ -563,24 +579,197 @@ namespace Coscine.Api.Project.Controllers ...@@ -563,24 +579,197 @@ namespace Coscine.Api.Project.Controllers
} }
/// <summary> /// <summary>
/// Checks if the given user is a member of the RWTH /// List all invitations of a project.
/// </summary> /// </summary>
/// <param name="user">User object</param> /// <param name="projectId">Project id of the project</param>
/// <returns>True, if member of RWTH or false, if not a member of RWTH</returns> /// <returns>List of invitations</returns>
private bool IsRWTHMember(User user) [HttpGet("[controller]/invitation/list/{projectId}")]
public ActionResult<IEnumerable<InvitationReturnObject>> ListInvitations(Guid projectId)
{ {
var externalIds = new ExternalIdModel().GetAllWhere((externalId) => externalId.UserId == user.Id); var project = _projectModel.GetById(projectId);
if (!externalIds.Any())
if (project == null)
{ {
return false; return NotFound($@"The project ""{projectId}"" was not found.");
}
var user = _authenticator.GetUser();
if (!_projectModel.HasAccess(user, project, UserRoles.Owner))
{
return Unauthorized($"You are not an owner of the project.");
} }
var externalIdList = new List<string>();
foreach (var externalId in externalIds) var invitations = _invitationModel.GetAllWhere(x => x.Project == projectId && x.Expiration > DateTime.UtcNow)
.Select(x => new InvitationReturnObject
{ {
externalIdList.Add(externalId.ExternalId1); Id = x.Id,
Expiration = x.Expiration,
Issuer = x.Issuer,
ProjectId = x.Project,
RoleId = x.Role,
UserMail = x.InviteeEmail
});
return new ActionResult<IEnumerable<InvitationReturnObject>>(invitations);
}
/// <summary>
/// Create and send an invitation to specified mail.
/// </summary>
/// <param name="sendInvitationObject">Informations for sending an invitation</param>
/// <returns>NoContent</returns>
[HttpPost("[controller]/invitation")]
public IActionResult SendInvitation(SendInvitationObject sendInvitationObject)
{
var user = _authenticator.GetUser();
if (!IsValidEmail(sendInvitationObject.Mail))
{
return BadRequest($@"The email ""{sendInvitationObject.Mail}"" is invalid.");
}
var project = _projectModel.GetById(sendInvitationObject.Project);
if (project == null)
{
return NotFound($@"The project ""{sendInvitationObject.Project}"" was not found.");
}
if (_roleModel.GetById(sendInvitationObject.Role) == null)
{
return NotFound($@"The role ""{sendInvitationObject.Role}"" was not found.");
}
if (!_projectModel.HasAccess(user, project, UserRoles.Owner))
{
return Unauthorized($"You are not an owner of the project.");
}
var invitations = _invitationModel.GetAllWhere(
x => x.Project == sendInvitationObject.Project &&
x.InviteeEmail == sendInvitationObject.Mail &&
x.Expiration > DateTime.UtcNow
);
if (invitations != null && invitations.Any())
{
return BadRequest("This invitee already has a valid invitation to this project.");
}
var token = _invitationModel.CreateInvitation(sendInvitationObject.Project, user.Id, sendInvitationObject.Role, sendInvitationObject.Mail);
var body = new JObject
{
["Args"] = new JObject()
{
["placeholder"] = new JObject()
{
["confirmation_link"] = $@"{_configuration.GetString("coscine/local/api/additional/url")}/invitation?token={token}"
}
}
};
NotificationBusUtil.Send(Program.Configuration, "user_invitation", NotificationBusUtil.GetUserList(new User { EmailAddress = sendInvitationObject.Mail }), sendInvitationObject.Project.ToString(), body);
return NoContent();
}
/// <summary>
/// Deletes an invitation.
/// </summary>
/// <param name="invitationId">Id of a invitation</param>
/// <returns>NoContent</returns>
[HttpDelete("[controller]/invitation/{invitationId}")]
public IActionResult DeleteInvitation(Guid invitationId)
{
var invitation = _invitationModel.GetById(invitationId);
if(invitation == null)
{
return NotFound("Invitation was not found.");
}
var user = _authenticator.GetUser();
if (!_projectModel.HasAccess(user, _projectModel.GetById(invitation.Project), UserRoles.Owner))
{
return Unauthorized($"You are not an owner of this project.");
}
_invitationModel.Delete(invitation);
return NoContent();
}
/// <summary>
/// Resolve an invitation for the current user.
/// </summary>
/// <param name="token">Token of a invitation</param>
/// <returns>NoContent</returns>
[HttpGet("[controller]/invitation/resolve/{token}")]
public IActionResult ResolveInvitation(Guid token)
{
var user = _authenticator.GetUser();
var invitation = _invitationModel.GetByToken(token);
if(invitation == null)
{
return NotFound("Invitation was not found.");
}
if (invitation.Expiration < DateTime.UtcNow)
{
return BadRequest("The invitation has expired");
}
var project = _projectModel.GetById(invitation.Project);
if (!_projectModel.HasAccess(_userModel.GetById(invitation.Issuer), project, UserRoles.Owner))
{
return Unauthorized($"The issuer is not an owner of the project.");
}
if (_projectRoleModel.GetAllWhere(x => x.ProjectId == invitation.Project && x.UserId == user.Id).Any())
{
return BadRequest($"The invitee is already part of the project.");
}
var role = _roleModel.GetById(invitation.Role);
_emitter.EmitUserAdd(new UserEventArgs(_configuration)
{
Project = project,
Role = role,
User = user,
});
var projectRole = new ProjectRole()
{
RelationId = Guid.NewGuid(),
ProjectId = invitation.Project,
UserId = user.Id,
RoleId = invitation.Role
};
_projectRoleModel.Insert(projectRole);
_invitationModel.Delete(invitation);
return Ok($"User {user.Id} is now {role.DisplayName} of project {project.Id}.");
}
private static bool IsValidEmail(string email)
{
try
{
return new System.Net.Mail.MailAddress(email).Address == email;
}
catch
{
return false;
} }
return new RdfStoreConnector(Program.Configuration.GetStringAndWait("coscine/local/virtuoso/additional/url")).GetTriples(new Uri("https://ror.org/04xfq0f34"), null, null, 1, externalIdList).Any();
} }
private void LogAnalyticsViewHome(List<string> projectIds) private void LogAnalyticsViewHome(List<string> projectIds)
... ...
......
using System;
namespace Coscine.Api.Project.ParameterObjects
{
/// <summary>
/// Parameter object containing the invitation informations.
/// </summary>
public class SendInvitationObject
{
/// <summary>
/// Id of the project
/// </summary>
public Guid Project { get; set; }
/// <summary>
/// Id of the target role
/// </summary>
public Guid Role { get; set; }
/// <summary>
/// Email of the target user
/// </summary>
public string Mail { get; set; }
}
}
using System;
namespace Coscine.Api.Project.ReturnObjects
{
/// <summary>
/// Return object for an invitation.
/// </summary>
public class InvitationReturnObject
{
/// <summary>
/// The invitation id.
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// When the invite will expire.
/// </summary>
public DateTime Expiration { get; set; }
/// <summary>
/// Email of the invitee.
/// </summary>
public string UserMail { get; set; }
/// <summary>
/// Id of the issuer.
/// </summary>
public Guid Issuer { get; set; }
/// <summary>
/// Id of the project.
/// </summary>
public Guid ProjectId { get; set; }
/// <summary>
/// Id of the target Role.
/// </summary>
public Guid RoleId { get; set; }
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment