using Coscine.Action; using Coscine.Action.EventArgs; using Coscine.ApiCommons; using Coscine.Configuration; using Coscine.Database.DataModel; using Coscine.Database.Models; using Coscine.Database.ReturnObjects; using Coscine.Database.Util; using Coscine.Logging; 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 { /// <summary> /// This represents the actions which can be taken with a ProjectRole Object /// </summary> [Authorize] public class ProjectRoleController : Controller { private readonly Authenticator _authenticator; private readonly ProjectRoleModel _projectRoleModel; private readonly Emitter _emitter; private readonly IConfiguration _configuration; private readonly CoscineLogger _coscineLogger; private readonly AnalyticsLogObject _analyticsLogObject; /// <summary> /// ProjectRoleController specifying an Emmiter, an Authentication,a ProjectRoleModel and a AnalyticsLogObject /// </summary> /// <param name="logger">Logger</param> public ProjectRoleController(ILogger<ProjectRoleController> logger) { _emitter = new Emitter(Program.Configuration); _authenticator = new Authenticator(this, Program.Configuration); _projectRoleModel = new ProjectRoleModel(); _configuration = Program.Configuration; _coscineLogger = new CoscineLogger(logger); _analyticsLogObject = new AnalyticsLogObject(); } /// <summary> /// Lists all users in a project. /// </summary> /// <param name="projectId">Id of the project</param> /// <returns>ProjectRoleObject or Json Object or Statuscode 401</returns> [Route("[controller]/{projectId}")] public ActionResult<IEnumerable<ProjectRoleObject>> Index(Guid projectId) { var userModel = new UserModel(); var roleModel = new RoleModel(); var projectModel = new ProjectModel(); var user = _authenticator.GetUser(); // Rights Matrix (https://git.rwth-aachen.de/coscine/docs/private/internal-wiki/-/blob/master/coscine/Definition%20of%20rights%20Matrix.md) // - Project: View Members of Project on Project page if (projectModel.HasAccess(user, projectModel.GetById(projectId), UserRoles.Owner, UserRoles.Member, UserRoles.Guest)) { var users = _projectRoleModel.GetAllWhere((projectRole) => (projectRole.ProjectId == projectId) ).Select((projectRole) => { var userInst = projectRole.User; if (userInst == null) { userInst = userModel.GetById(projectRole.UserId); } var role = projectRole.Role; if (role == null) { role = roleModel.GetById(projectRole.RoleId); } return new ProjectRoleObject(projectRole.ProjectId, new UserObject(userInst.Id, userInst.DisplayName, userInst.Givenname, userInst.Surname, userInst.EmailAddress), new RoleObject(role.Id, role.DisplayName)); }); if (Request.Query != null && Request.Query["noanalyticslog"] != "true") { LogAnalytics("View Users", user, users, projectId.ToString()); } return Ok(users); } else { return Unauthorized("User is not allowed to list all users to the given project!"); } } /// <summary> /// Gets all roles for the current user and a project. /// </summary> /// <param name="projectId">Id of the project</param> /// <returns>Json Object or ProjectRoleObject</returns> [HttpGet("[controller]/project/{projectId}")] public ActionResult<IEnumerable<ProjectRoleObject>> Get(Guid projectId) { var roleModel = new RoleModel(); var user = _authenticator.GetUser(); var userObject = new UserObject(user.Id, user.DisplayName, user.Givenname, user.Surname, user.EmailAddress); return Ok(_projectRoleModel.GetAllWhere((projectRole) => (projectRole.UserId == user.Id && projectRole.ProjectId == projectId) ).Select((projectRole) => { if (projectRole.Role == null) { projectRole.Role = roleModel.GetById(projectRole.RoleId); } return new ProjectRoleObject(projectRole.RelationId, userObject, new RoleObject(projectRole.Role.Id, projectRole.Role.DisplayName)); })); } /// <summary> /// Sets a role for the current user in a project /// </summary> /// <returns>Json Object or Status Code 401</returns> [HttpPost("[controller]")] public ActionResult<ProjectRoleObject> Set([FromBody] ProjectRoleObject projectRoleObject) { var projectModel = new ProjectModel(); var project = projectModel.GetById(projectRoleObject.ProjectId); var roleModel = new RoleModel(); var role = roleModel.GetById(projectRoleObject.Role.Id); var userModel = new UserModel(); var userToAdd = userModel.GetById(projectRoleObject.User.Id); var user = _authenticator.GetUser(); // Rights Matrix (https://git.rwth-aachen.de/coscine/docs/private/internal-wiki/-/blob/master/coscine/Definition%20of%20rights%20Matrix.md) // - Project: Project: Change Settings (project, user, quota) if (projectModel.HasAccess(user, project, UserRoles.Owner)) { // Rights Matrix (https://git.rwth-aachen.de/coscine/docs/private/internal-wiki/-/blob/master/coscine/Definition%20of%20rights%20Matrix.md) // - none var userAlreadyHasRole = projectModel.HasAccess(userToAdd, project, UserRoles.Owner, UserRoles.Member, UserRoles.Guest); _emitter.EmitUserAdd(new UserEventArgs(_configuration) { Project = project, Role = role, User = userToAdd }); LogAnalytics(userAlreadyHasRole == true ? "Change Role" : "Add Member", user, null, project.Id.ToString()); return Ok(_projectRoleModel.SetFromObject(projectRoleObject)); } else { return Unauthorized("The user is not authorized to store a project role to the given project!"); } } /// <summary> /// Deletes a user from a project /// </summary> /// <param name="projectId">Id of the project</param> /// <param name="userId">Id of the user</param> /// <param name="roleId">Id of the role</param> /// <returns>Json Object or Statuscode 401</returns> [HttpDelete("[controller]/project/{projectId}/user/{userId}/role/{roleId}")] public IActionResult Delete(Guid projectId, Guid userId, Guid roleId) { var projectModel = new ProjectModel(); var user = _authenticator.GetUser(); var project = projectModel.GetById(projectId); // Rights Matrix (https://git.rwth-aachen.de/coscine/docs/private/internal-wiki/-/blob/master/coscine/Definition%20of%20rights%20Matrix.md) // - Project: Project: Change Settings (project, user, quota) if (projectModel.HasAccess(user, project, UserRoles.Owner)) { _projectRoleModel.CheckIfLastOwnerWillBeRemoved(roleId, projectId); var userModel = new UserModel(); var userToRemove = userModel.GetById(userId); _emitter.EmitUserRemove(new UserEventArgs(this._configuration) { Project = project, User = userToRemove }); LogAnalytics("Remove User", user, null, project.Id.ToString()); return Ok(_projectRoleModel.Delete(_projectRoleModel.GetWhere((projectRole) => projectRole.ProjectId == projectId && projectRole.UserId == userId && projectRole.RoleId == roleId))); } else { return Unauthorized("The user is not authorized to delete a project role for the given project!"); } } /// <summary> /// Deletes the current user from a project /// </summary> /// <param name="projectId">Id of the project</param> /// <returns>Json Object or Statuscode 401</returns> [HttpDelete("[controller]/project/{projectId}/user")] public IActionResult Delete(Guid projectId) { var projectModel = new ProjectModel(); var user = _authenticator.GetUser(); var project = projectModel.GetById(projectId); var roleId = _projectRoleModel.GetGetUserRoleForProject(projectId, user.Id); // Rights Matrix (https://git.rwth-aachen.de/coscine/docs/private/internal-wiki/-/blob/master/coscine/Definition%20of%20rights%20Matrix.md) // - ??? // Guests have the right to leave a project on their own. if (projectModel.HasAccess(user, project, UserRoles.Owner, UserRoles.Member, UserRoles.Guest)) { _projectRoleModel.CheckIfLastOwnerWillBeRemoved((Guid)roleId, projectId); _emitter.EmitUserRemove(new UserEventArgs(this._configuration) { Project = project, User = user }); LogAnalytics("Leave Project", user, null, project.Id.ToString()); return Ok(_projectRoleModel.Delete(_projectRoleModel.GetWhere((projectRole) => projectRole.ProjectId == projectId && projectRole.UserId == user.Id && projectRole.RoleId == roleId))); } else { return Unauthorized("The user is not authorized to access the given project!"); } } /// <summary> /// Log Analytics /// </summary> /// <param name="operation">Operation</param> /// <param name="user">User object</param> /// <param name="users">Users</param> /// <param name="projectId">Id of the project</param> private void LogAnalytics(string operation, User user, IEnumerable<ProjectRoleObject> users = null, string projectId = null ) { if (CoscineLoggerConfiguration.IsLogLevelActivated(LogType.Analytics)) { _analyticsLogObject.Type = "Action"; _analyticsLogObject.Operation = operation; if (users != null) { var shownUsers = new List<string>(); foreach (var entry in users) { shownUsers.Add(entry.User.Id.ToString()); } _analyticsLogObject.UserList = shownUsers; } if (projectId != null) { _analyticsLogObject.ProjectId = projectId; _analyticsLogObject.RoleId = _projectRoleModel.GetGetUserRoleForProject(new Guid(_analyticsLogObject.ProjectId), user.Id).ToString(); } _coscineLogger.AnalyticsLog(_analyticsLogObject); } } } }