using System; using System.Linq; using System.Threading.Tasks; using Bit.Api.Models.Request; using Bit.Api.Models.Request.Organizations; using Bit.Api.Models.Response; using Bit.Core.Entities; using Bit.Core.Exceptions; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Settings; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Bit.Api.Controllers { [Route("emergency-access")] [Authorize("Application")] public class EmergencyAccessController : Controller { private readonly IUserService _userService; private readonly IEmergencyAccessRepository _emergencyAccessRepository; private readonly IEmergencyAccessService _emergencyAccessService; private readonly IGlobalSettings _globalSettings; public EmergencyAccessController( IUserService userService, IEmergencyAccessRepository emergencyAccessRepository, IEmergencyAccessService emergencyAccessService, IGlobalSettings globalSettings) { _userService = userService; _emergencyAccessRepository = emergencyAccessRepository; _emergencyAccessService = emergencyAccessService; _globalSettings = globalSettings; } [HttpGet("trusted")] public async Task> GetContacts() { var userId = _userService.GetProperUserId(User); var granteeDetails = await _emergencyAccessRepository.GetManyDetailsByGrantorIdAsync(userId.Value); var responses = granteeDetails.Select(d => new EmergencyAccessGranteeDetailsResponseModel(d)); return new ListResponseModel(responses); } [HttpGet("granted")] public async Task> GetGrantees() { var userId = _userService.GetProperUserId(User); var granteeDetails = await _emergencyAccessRepository.GetManyDetailsByGranteeIdAsync(userId.Value); var responses = granteeDetails.Select(d => new EmergencyAccessGrantorDetailsResponseModel(d)); return new ListResponseModel(responses); } [HttpGet("{id}")] public async Task Get(string id) { var userId = _userService.GetProperUserId(User); var result = await _emergencyAccessService.GetAsync(new Guid(id), userId.Value); return new EmergencyAccessGranteeDetailsResponseModel(result); } [HttpGet("{id}/policies")] public async Task> Policies(string id) { var user = await _userService.GetUserByPrincipalAsync(User); var policies = await _emergencyAccessService.GetPoliciesAsync(new Guid(id), user); var responses = policies.Select(policy => new PolicyResponseModel(policy)); return new ListResponseModel(responses); } [HttpPut("{id}")] [HttpPost("{id}")] public async Task Put(string id, [FromBody] EmergencyAccessUpdateRequestModel model) { var emergencyAccess = await _emergencyAccessRepository.GetByIdAsync(new Guid(id)); if (emergencyAccess == null) { throw new NotFoundException(); } var userId = _userService.GetProperUserId(User); await _emergencyAccessService.SaveAsync(model.ToEmergencyAccess(emergencyAccess), userId.Value); } [HttpDelete("{id}")] [HttpPost("{id}/delete")] public async Task Delete(string id) { var userId = _userService.GetProperUserId(User); await _emergencyAccessService.DeleteAsync(new Guid(id), userId.Value); } [HttpPost("invite")] public async Task Invite([FromBody] EmergencyAccessInviteRequestModel model) { var user = await _userService.GetUserByPrincipalAsync(User); await _emergencyAccessService.InviteAsync(user, model.Email, model.Type.Value, model.WaitTimeDays); } [HttpPost("{id}/reinvite")] public async Task Reinvite(string id) { var user = await _userService.GetUserByPrincipalAsync(User); await _emergencyAccessService.ResendInviteAsync(user, new Guid(id)); } [HttpPost("{id}/accept")] public async Task Accept(string id, [FromBody] OrganizationUserAcceptRequestModel model) { var user = await _userService.GetUserByPrincipalAsync(User); await _emergencyAccessService.AcceptUserAsync(new Guid(id), user, model.Token, _userService); } [HttpPost("{id}/confirm")] public async Task Confirm(string id, [FromBody] OrganizationUserConfirmRequestModel model) { var userId = _userService.GetProperUserId(User); await _emergencyAccessService.ConfirmUserAsync(new Guid(id), model.Key, userId.Value); } [HttpPost("{id}/initiate")] public async Task Initiate(string id) { var user = await _userService.GetUserByPrincipalAsync(User); await _emergencyAccessService.InitiateAsync(new Guid(id), user); } [HttpPost("{id}/approve")] public async Task Accept(string id) { var user = await _userService.GetUserByPrincipalAsync(User); await _emergencyAccessService.ApproveAsync(new Guid(id), user); } [HttpPost("{id}/reject")] public async Task Reject(string id) { var user = await _userService.GetUserByPrincipalAsync(User); await _emergencyAccessService.RejectAsync(new Guid(id), user); } [HttpPost("{id}/takeover")] public async Task Takeover(string id) { var user = await _userService.GetUserByPrincipalAsync(User); var (result, grantor) = await _emergencyAccessService.TakeoverAsync(new Guid(id), user); return new EmergencyAccessTakeoverResponseModel(result, grantor); } [HttpPost("{id}/password")] public async Task Password(string id, [FromBody] EmergencyAccessPasswordRequestModel model) { var user = await _userService.GetUserByPrincipalAsync(User); await _emergencyAccessService.PasswordAsync(new Guid(id), user, model.NewMasterPasswordHash, model.Key); } [HttpPost("{id}/view")] public async Task ViewCiphers(string id) { var user = await _userService.GetUserByPrincipalAsync(User); var viewResult = await _emergencyAccessService.ViewAsync(new Guid(id), user); return new EmergencyAccessViewResponseModel(_globalSettings, viewResult.EmergencyAccess, viewResult.Ciphers); } [HttpGet("{id}/{cipherId}/attachment/{attachmentId}")] public async Task GetAttachmentData(string id, string cipherId, string attachmentId) { var user = await _userService.GetUserByPrincipalAsync(User); var result = await _emergencyAccessService.GetAttachmentDownloadAsync(new Guid(id), cipherId, attachmentId, user); return new AttachmentResponseModel(result.Id, result.Data, result.Cipher, _globalSettings); } } }