diff --git a/src/Api/Controllers/OrganizationUsersController.cs b/src/Api/Controllers/OrganizationUsersController.cs index 2c5c08f114..7bf2ded914 100644 --- a/src/Api/Controllers/OrganizationUsersController.cs +++ b/src/Api/Controllers/OrganizationUsersController.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Authorization; using Bit.Core.Models.Api; using Bit.Core.Exceptions; using Bit.Core.Services; +using Bit.Core; namespace Bit.Api.Controllers { @@ -19,26 +20,29 @@ namespace Bit.Api.Controllers private readonly IOrganizationService _organizationService; private readonly ISubvaultRepository _subvaultRepository; private readonly IUserService _userService; + private readonly CurrentContext _currentContext; public OrganizationUsersController( IOrganizationRepository organizationRepository, IOrganizationUserRepository organizationUserRepository, IOrganizationService organizationService, ISubvaultRepository subvaultRepository, - IUserService userService) + IUserService userService, + CurrentContext currentContext) { _organizationRepository = organizationRepository; _organizationUserRepository = organizationUserRepository; _organizationService = organizationService; _subvaultRepository = subvaultRepository; _userService = userService; + _currentContext = currentContext; } [HttpGet("{id}")] public async Task Get(string orgId, string id) { var organizationUser = await _organizationUserRepository.GetDetailsByIdAsync(new Guid(id)); - if(organizationUser == null) + if(organizationUser == null || !_currentContext.OrganizationAdmin(organizationUser.Item1.OrganizationId)) { throw new NotFoundException(); } @@ -49,7 +53,13 @@ namespace Bit.Api.Controllers [HttpGet("")] public async Task> Get(string orgId) { - var organizationUsers = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(new Guid(orgId)); + var orgGuidId = new Guid(orgId); + if(!_currentContext.OrganizationAdmin(orgGuidId)) + { + throw new NotFoundException(); + } + + var organizationUsers = await _organizationUserRepository.GetManyDetailsByOrganizationAsync(orgGuidId); var responses = organizationUsers.Select(o => new OrganizationUserResponseModel(o)); return new ListResponseModel(responses); } @@ -57,8 +67,14 @@ namespace Bit.Api.Controllers [HttpPost("invite")] public async Task Invite(string orgId, [FromBody]OrganizationUserInviteRequestModel model) { + var orgGuidId = new Guid(orgId); + if(!_currentContext.OrganizationAdmin(orgGuidId)) + { + throw new NotFoundException(); + } + var userId = _userService.GetProperUserId(User); - var result = await _organizationService.InviteUserAsync(new Guid(orgId), userId.Value, model.Email, model.Type.Value, + var result = await _organizationService.InviteUserAsync(orgGuidId, userId.Value, model.Email, model.Type.Value, model.Subvaults?.Select(s => s.ToSubvaultUser())); } @@ -66,8 +82,14 @@ namespace Bit.Api.Controllers [HttpPost("{id}/reinvite")] public async Task Reinvite(string orgId, string id) { + var orgGuidId = new Guid(orgId); + if(!_currentContext.OrganizationAdmin(orgGuidId)) + { + throw new NotFoundException(); + } + var userId = _userService.GetProperUserId(User); - await _organizationService.ResendInviteAsync(new Guid(orgId), userId.Value, new Guid(id)); + await _organizationService.ResendInviteAsync(orgGuidId, userId.Value, new Guid(id)); } [HttpPut("{id}/accept")] @@ -82,16 +104,28 @@ namespace Bit.Api.Controllers [HttpPost("{id}/confirm")] public async Task Confirm(string orgId, string id, [FromBody]OrganizationUserConfirmRequestModel model) { + var orgGuidId = new Guid(orgId); + if(!_currentContext.OrganizationAdmin(orgGuidId)) + { + throw new NotFoundException(); + } + var userId = _userService.GetProperUserId(User); - var result = await _organizationService.ConfirmUserAsync(new Guid(orgId), new Guid(id), model.Key, userId.Value); + var result = await _organizationService.ConfirmUserAsync(orgGuidId, new Guid(id), model.Key, userId.Value); } [HttpPut("{id}")] [HttpPost("{id}")] public async Task Put(string orgId, string id, [FromBody]OrganizationUserUpdateRequestModel model) { + var orgGuidId = new Guid(orgId); + if(!_currentContext.OrganizationAdmin(orgGuidId)) + { + throw new NotFoundException(); + } + var organizationUser = await _organizationUserRepository.GetByIdAsync(new Guid(id)); - if(organizationUser == null) + if(organizationUser == null || organizationUser.OrganizationId != orgGuidId) { throw new NotFoundException(); } @@ -105,8 +139,14 @@ namespace Bit.Api.Controllers [HttpPost("{id}/delete")] public async Task Delete(string orgId, string id) { + var orgGuidId = new Guid(orgId); + if(!_currentContext.OrganizationAdmin(orgGuidId)) + { + throw new NotFoundException(); + } + var userId = _userService.GetProperUserId(User); - await _organizationService.DeleteUserAsync(new Guid(orgId), new Guid(id), userId.Value); + await _organizationService.DeleteUserAsync(orgGuidId, new Guid(id), userId.Value); } } } diff --git a/src/Core/Repositories/IOrganizationUserRepository.cs b/src/Core/Repositories/IOrganizationUserRepository.cs index f4984925f9..e418d6d1e3 100644 --- a/src/Core/Repositories/IOrganizationUserRepository.cs +++ b/src/Core/Repositories/IOrganizationUserRepository.cs @@ -9,7 +9,6 @@ namespace Bit.Core.Repositories { public interface IOrganizationUserRepository : IRepository { - Task GetByOrganizationAsync(Guid organizationId, Guid userId); Task> GetManyByUserAsync(Guid userId); Task> GetManyByOrganizationAsync(Guid organizationId, OrganizationUserType? type); Task GetByOrganizationAsync(Guid organizationId, string email); diff --git a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs index df0e95eef6..729c6f30aa 100644 --- a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs +++ b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs @@ -21,19 +21,6 @@ namespace Bit.Core.Repositories.SqlServer : base(connectionString) { } - public async Task GetByOrganizationAsync(Guid organizationId, Guid userId) - { - using(var connection = new SqlConnection(ConnectionString)) - { - var results = await connection.QueryAsync( - "[dbo].[OrganizationUser_ReadByOrganizationIdUserId]", - new { OrganizationId = organizationId, UserId = userId }, - commandType: CommandType.StoredProcedure); - - return results.SingleOrDefault(); - } - } - public async Task GetByOrganizationAsync(Guid organizationId, string email) { using(var connection = new SqlConnection(ConnectionString)) diff --git a/src/Core/Services/Implementations/OrganizationService.cs b/src/Core/Services/Implementations/OrganizationService.cs index 5181f1b909..553ef8bf94 100644 --- a/src/Core/Services/Implementations/OrganizationService.cs +++ b/src/Core/Services/Implementations/OrganizationService.cs @@ -9,7 +9,6 @@ using Bit.Core.Exceptions; using System.Collections.Generic; using Microsoft.AspNetCore.DataProtection; using Stripe; -using Bit.Core.Models.StaticStore; namespace Bit.Core.Services { @@ -149,11 +148,6 @@ namespace Bit.Core.Services public async Task InviteUserAsync(Guid organizationId, Guid invitingUserId, string email, Enums.OrganizationUserType type, IEnumerable subvaults) { - if(!(await OrganizationUserHasAdminRightsAsync(organizationId, invitingUserId))) - { - throw new BadRequestException("Cannot invite users."); - } - // Make sure user is not already invited var existingOrgUser = await _organizationUserRepository.GetByOrganizationAsync(organizationId, email); if(existingOrgUser != null) @@ -185,11 +179,6 @@ namespace Bit.Core.Services public async Task ResendInviteAsync(Guid organizationId, Guid invitingUserId, Guid organizationUserId) { - if(!(await OrganizationUserHasAdminRightsAsync(organizationId, invitingUserId))) - { - throw new BadRequestException("Cannot invite users."); - } - var orgUser = await _organizationUserRepository.GetByIdAsync(organizationUserId); if(orgUser == null || orgUser.OrganizationId != organizationId || orgUser.Status != Enums.OrganizationUserStatusType.Invited) @@ -257,11 +246,6 @@ namespace Bit.Core.Services public async Task ConfirmUserAsync(Guid organizationId, Guid organizationUserId, string key, Guid confirmingUserId) { - if(!(await OrganizationUserHasAdminRightsAsync(organizationId, confirmingUserId))) - { - throw new BadRequestException("Cannot confirm users."); - } - var orgUser = await _organizationUserRepository.GetByIdAsync(organizationUserId); if(orgUser == null || orgUser.Status != Enums.OrganizationUserStatusType.Accepted || orgUser.OrganizationId != organizationId) @@ -286,11 +270,6 @@ namespace Bit.Core.Services throw new BadRequestException("Invite the user first."); } - if(!(await OrganizationUserHasAdminRightsAsync(user.OrganizationId, savingUserId))) - { - throw new BadRequestException("Cannot update users."); - } - var confirmedOwners = (await GetConfirmedOwnersAsync(user.OrganizationId)).ToList(); if(user.Type != Enums.OrganizationUserType.Owner && confirmedOwners.Count == 1 && confirmedOwners[0].Id == user.Id) { @@ -306,11 +285,6 @@ namespace Bit.Core.Services public async Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId) { - if(!(await OrganizationUserHasAdminRightsAsync(organizationId, deletingUserId))) - { - throw new BadRequestException("Cannot delete users."); - } - var orgUser = await _organizationUserRepository.GetByIdAsync(organizationUserId); if(orgUser == null || orgUser.OrganizationId != organizationId) { @@ -333,18 +307,6 @@ namespace Bit.Core.Services return owners.Where(o => o.Status == Enums.OrganizationUserStatusType.Confirmed); } - private async Task OrganizationUserHasAdminRightsAsync(Guid organizationId, Guid userId) - { - var orgUser = await _organizationUserRepository.GetByOrganizationAsync(organizationId, userId); - if(orgUser == null) - { - return false; - } - - return orgUser.Status == Enums.OrganizationUserStatusType.Confirmed && - orgUser.Type != Enums.OrganizationUserType.User; - } - private async Task SaveUserSubvaultsAsync(OrganizationUser user, IEnumerable subvaults, bool newUser) { if(subvaults == null) diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index c999a772e0..eeea3951de 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -171,7 +171,6 @@ - diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadByOrganizationIdUserId.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadByOrganizationIdUserId.sql deleted file mode 100644 index 96838916c7..0000000000 --- a/src/Sql/dbo/Stored Procedures/OrganizationUser_ReadByOrganizationIdUserId.sql +++ /dev/null @@ -1,15 +0,0 @@ -CREATE PROCEDURE [dbo].[OrganizationUser_ReadByOrganizationIdUserId] - @OrganizationId UNIQUEIDENTIFIER, - @UserId UNIQUEIDENTIFIER -AS -BEGIN - SET NOCOUNT ON - - SELECT - * - FROM - [dbo].[OrganizationUserView] - WHERE - [OrganizationId] = @OrganizationId - AND [UserId] = @UserId -END \ No newline at end of file