/// <summary> /// Gets all projects for which the current user has access to. Can include archived projects. Can skip decryption. /// </summary> /// <returns>A list of Project objects</returns> public async Task <List <Project> > GetProjects(bool skipDecryption = false, bool includeArchived = false) { // Get user to validate access var currentUser = await _applicationIdentityService.GetCurrentUser(); if (currentUser == null) { throw new Exception("Unauthorised requests are not allowed."); } if (await _applicationIdentityService.IsCurrentUserAdmin()) { return(await GetProjectsForAdmin(skipDecryption)); } // Get projects with access // TODO: attempt to make this in 1 query var projects = new List <Project>(); if (includeArchived) // filter out archived { projects = await _dbContext.Projects .Include(p => p.AccessIdentifiers) .ToListAsync(); } else { projects = await _dbContext.Projects .Where(p => p.IsArchived == false) .Include(p => p.AccessIdentifiers) .ToListAsync(); } // filter our those without access for the current user var projectsWithAccess = projects.Where(p => p.AccessIdentifiers.Any(ai => ai.Identity != null && ai.Identity.Id == currentUser.Id)) .ToList(); if (projectsWithAccess == null) { return(null); } foreach (var project in projectsWithAccess) { project.IsDecrypted = false; } if (skipDecryption == false) // double false... { foreach (var project in projectsWithAccess) { project.IsDecrypted = false; DecryptProject(project); } } return(projectsWithAccess.ToList()); }
/// <summary> /// Sets an Assets archive status to true in the DB. /// </summary> /// <param name="projectId">The project Id of the project owning the Asset</param> /// <param name="assetId">The Asset Id of the asset to archive</param> /// <returns>A Task result</returns> public async Task ArchiveAssetAsync(int projectId, int assetId, string remoteIpAddress) { // Validate if (string.IsNullOrWhiteSpace(remoteIpAddress)) { throw new ArgumentException("You must provide a valid IP address."); } if (projectId < 1) { throw new ArgumentException("You must pass a valid project id."); } if (assetId < 1) { throw new ArgumentException("You must pass a valid asset id."); } // Validate current user var currentUser = await _applicationIdentityService.GetCurrentUser(); if (currentUser == null) { throw new Exception("Unauthorised requests are not allowed."); } ; // Get Asset from DB with a permission and project check var retrievedAsset = await _dbContext.Assets.Where(a => a.Id == assetId && a.IsArchived == false && a.Project.Id == projectId && a.Project.AccessIdentifiers.Any(ai => ai.Identity.Id == currentUser.Id)) .Include(p => p.Project.AccessIdentifiers) .ThenInclude(p => p.Identity) // NOTE: intellisense doesn't work here (23.09.2017) https://github.com/dotnet/roslyn/issues/8237 .FirstOrDefaultAsync(); if (retrievedAsset == null) { throw new Exception("The asset was not found or the current user does not have access to it."); } // Refresh the entity to discard changes and avoid saving a decrypted project _dbContext.Entry(retrievedAsset).State = EntityState.Unchanged; _dbContext.Entry(retrievedAsset.Project).State = EntityState.Unchanged; retrievedAsset.IsArchived = true; // Set modified time/user retrievedAsset.Modified = DateTime.UtcNow; retrievedAsset.ModifiedBy = currentUser; // LOG event var updatedRowCount = await _dbContext.SaveChangesAsync(); if (updatedRowCount > 1) { // we have a problem } }
public async Task <JsonResult> ExportDatabase() { var currentUser = await _applicationIdentityService.GetCurrentUser(); if (currentUser == null) { return(new JsonResult("Unathorised")); } if (await _applicationIdentityService.IsCurrentUserAdmin() == false) { return(new JsonResult("Unathorised")); } var allProjects = await _projectsService.GetProjects(); foreach (var project in allProjects) { await _assetService.LoadAssetsAsync(project); foreach (var asset in project.Assets) { if (asset.GetType() == typeof(Credential)) { var credential = asset as Credential; credential.Password = _assetService.DecryptPassword(credential.Password); } } } return(Json(allProjects, new Newtonsoft.Json.JsonSerializerSettings() { TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All, ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore })); }
/// <summary> /// Grants access to a project /// </summary> /// <param name="projectId">The Id of the project</param> /// <param name="upn">The UPN identifier of the identity for which access will be granted to</param> /// <param name="role">The role/level of access that will be granted</param> /// <param name="remoteIpAddress">The IP address of the incoming request</param> /// <param name="projectsService">An instance of IProjectService to assist with resolving of the project</param> /// <returns>A Task object with an AccessChangeResult representing the result</returns> public async Task <AccessChangeResult> GrantAccessAsync( int projectId, string upn, Role role, string remoteIpAddress, IProjectsService projectsService) { if (string.IsNullOrWhiteSpace(upn)) { throw new ArgumentNullException(nameof(upn)); } if (string.IsNullOrWhiteSpace(remoteIpAddress)) { throw new ArgumentNullException(nameof(remoteIpAddress)); } if (projectId == 0) { throw new ArgumentException("You must provide a valid project id."); } var currentUser = await _applicationIdentityService.GetCurrentUser(); if (currentUser == null) { throw new ArgumentException("The current user could not be retrieved."); } // Get/find the project var project = await projectsService.GetProject(projectId, true); if (project == null) { throw new ArgumentNullException(nameof(project)); } // Refresh the entity to discard changes and avoid saving a decrypted project if (project.IsDecrypted == true) { _dbContext.Entry(project).State = EntityState.Unchanged; // project will be encrypted here } // Verify current user has permissions to grant access, aka Owner if (await CurrentUserHasAccessAsync(projectId, projectsService, Role.Owner) == false) { await _eventService.LogCustomEventAsync(currentUser.Id.ToString(), $"User {currentUser.Upn} attepted to give access to {upn} without having access to project with ID: {projectId}."); throw new Exception("The current user does not have permissions to grant access."); } // Check if the target user already has access if (CheckAccess(project, upn, Role.Owner)) { await _eventService.LogCustomEventAsync(currentUser.Id.ToString(), $"The user {currentUser.Upn} attepted to give access to {upn} who already has access to project with ID: {projectId}."); return(new AccessChangeResult() { Success = false, Message = $"User {upn} already has access." }); // no need to grant } // TODO: grant access to AD group var newAccessIdentifier = new AccessIdentifier(); newAccessIdentifier.Project = project ?? throw new ArgumentNullException(nameof(project)); newAccessIdentifier.Role = role; newAccessIdentifier.Created = DateTime.UtcNow; newAccessIdentifier.CreatedBy = currentUser ?? throw new ArgumentNullException(nameof(currentUser)); newAccessIdentifier.Identity = await _applicationIdentityService.EnsureUserByUpnAsync(upn); project.AccessIdentifiers.Add(newAccessIdentifier); // Validation of the access identifiers before save foreach (var item in project.AccessIdentifiers) { if ((item.Identity == null)) { await _eventService.LogCustomEventAsync(currentUser.Upn, $"Ensure did not return a user for {upn}"); return(new AccessChangeResult() { Success = false, Message = $"The user or group '{upn}' was not found." }); } } // Save Grant event // Issue: LogGrantAccessEventAsync calls SaveChanges. await _eventService.LogGrantAccessEventAsync(projectId, remoteIpAddress, role, newAccessIdentifier.Identity.Id, currentUser.Id, "UPN: " + upn); var modifiedRows = await _dbContext.SaveChangesAsync(); return(new AccessChangeResult() { Success = true }); }