using Coscine.Action; using Coscine.Action.EventArgs; using Coscine.Database.Models; using Coscine.Database.ReturnObjects; using Coscine.ApiCommons; using Coscine.ApiCommons.Factories; using Coscine.Configuration; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using System; using System.Linq; using Coscine.Database.Util; using Coscine.Logging; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using System.Collections.Generic; using Coscine.Database.DataModel; 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 to the given 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(string projectId) { var userModel = new UserModel(); var roleModel = new RoleModel(); var projectModel = new ProjectModel(); Guid.TryParse(projectId, out Guid projectIdGuid); var user = _authenticator.GetUser(); if (projectModel.HasAccess(user, projectModel.GetById(projectIdGuid), UserRoles.Owner, UserRoles.Member)) { var users = _projectRoleModel.GetAllWhere((projectRole) => (projectRole.ProjectId == projectIdGuid) ).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); } return Json(users); } else { return Unauthorized("User is not allowed to list all users to the given project!"); } } /// <summary> /// Gets all roles for current user and given object /// </summary> /// <param name="projectId">Id of the project</param> /// <returns>Json Object or ProjectRoleObject</returns> [HttpGet("[controller]/project/{projectId}")] public ActionResult<IEnumerable<ProjectRoleObject>> Get(string projectId) { var roleModel = new RoleModel(); Guid.TryParse(projectId, out Guid projectIdGuid); var user = _authenticator.GetUser(); var userObject = new UserObject(user.Id, user.DisplayName, user.Givenname, user.Surname, user.EmailAddress); return Json(_projectRoleModel.GetAllWhere((projectRole) => (projectRole.UserId == user.Id && projectRole.ProjectId == projectIdGuid) ).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 project role for the given project /// </summary> /// <returns>Json Object or Statuscode 401</returns> [HttpPost("[controller]")] public ActionResult<ProjectRoleObject> Set() { var projectRoleObject = ObjectFactory<ProjectRoleObject>.DeserializeFromStream(Request.Body); 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(); if (projectModel.HasAccess(user, project, UserRoles.Owner)) { var userIsAlreadymember = projectModel.HasAccess(userToAdd, project, UserRoles.Owner, UserRoles.Member); _emitter.EmitUserAdd(new UserEventArgs(_configuration) { Project = project, Role = role, User = userToAdd }); LogAnalytics(userIsAlreadymember == true ? "Change Role" : "Add Member", user, null, project.Id.ToString()); return Json(_projectRoleModel.SetFromObject(projectRoleObject)); } else { return Unauthorized("The user is not authorized to store a project role to the given project!"); } } /// <summary> /// deletes project role for the given 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); 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 Json(_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 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); if (projectModel.HasAccess(user, project, UserRoles.Owner, UserRoles.Member)) { _projectRoleModel.CheckIfLastOwnerWillBeRemoved((Guid)roleId, projectId); _emitter.EmitUserRemove(new UserEventArgs(this._configuration) { Project = project, User = user }); LogAnalytics("Leave Project", user, null, project.Id.ToString()); return Json(_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) { List<string> 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); } } } }