1
0
mirror of https://github.com/bitwarden/server.git synced 2024-11-21 12:05:42 +01:00

[EC-338] Update SCIM code naming conventions (revoked/restore) (#2140)

* Keep old endpoints but mark as deprecated
* Do not change existing sproc naming
This commit is contained in:
Thomas Rittson 2022-07-25 10:47:44 +10:00 committed by GitHub
parent cf16be16c6
commit f6a18db582
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 93 additions and 61 deletions

View File

@ -191,13 +191,13 @@ namespace Bit.Scim.Controllers.v2
});
}
if (model.Active && orgUser.Status == OrganizationUserStatusType.Deactivated)
if (model.Active && orgUser.Status == OrganizationUserStatusType.Revoked)
{
await _organizationService.ActivateUserAsync(orgUser, null);
await _organizationService.RestoreUserAsync(orgUser, null);
}
else if (!model.Active && orgUser.Status != OrganizationUserStatusType.Deactivated)
else if (!model.Active && orgUser.Status != OrganizationUserStatusType.Revoked)
{
await _organizationService.DeactivateUserAsync(orgUser, null);
await _organizationService.RevokeUserAsync(orgUser, null);
}
// Have to get full details object for response model
@ -227,14 +227,14 @@ namespace Bit.Scim.Controllers.v2
if (replaceOp.Value.TryGetProperty("active", out var activeProperty))
{
var active = activeProperty.GetBoolean();
if (active && orgUser.Status == OrganizationUserStatusType.Deactivated)
if (active && orgUser.Status == OrganizationUserStatusType.Revoked)
{
await _organizationService.ActivateUserAsync(orgUser, null);
await _organizationService.RestoreUserAsync(orgUser, null);
operationHandled = true;
}
else if (!active && orgUser.Status != OrganizationUserStatusType.Deactivated)
else if (!active && orgUser.Status != OrganizationUserStatusType.Revoked)
{
await _organizationService.DeactivateUserAsync(orgUser, null);
await _organizationService.RevokeUserAsync(orgUser, null);
operationHandled = true;
}
}

View File

@ -20,7 +20,7 @@ namespace Bit.Scim.Models
DisplayName = orgUser.Name;
Emails = new List<EmailModel> { new EmailModel(orgUser.Email) };
Name = new NameModel(orgUser.Name);
Active = orgUser.Status != Core.Enums.OrganizationUserStatusType.Deactivated;
Active = orgUser.Status != Core.Enums.OrganizationUserStatusType.Revoked;
}
public string Id { get; set; }

View File

@ -373,35 +373,67 @@ namespace Bit.Api.Controllers
new OrganizationUserBulkResponseModel(r.Item1.Id, r.Item2)));
}
[Obsolete("2022-07-22 Moved to {id}/revoke endpoint")]
[HttpPatch("{id}/deactivate")]
[HttpPut("{id}/deactivate")]
public async Task Deactivate(Guid orgId, Guid id)
{
await ActivateOrDeactivateUserAsync(orgId, id, _organizationService.DeactivateUserAsync);
await RevokeAsync(orgId, id);
}
[Obsolete("2022-07-22 Moved to /revoke endpoint")]
[HttpPatch("deactivate")]
[HttpPut("deactivate")]
public async Task<ListResponseModel<OrganizationUserBulkResponseModel>> BulkDeactivate(Guid orgId, [FromBody] OrganizationUserBulkRequestModel model)
{
return await ActivateOrDeactivateUsersAsync(orgId, model, _organizationService.DeactivateUsersAsync);
return await BulkRevokeAsync(orgId, model);
}
[Obsolete("2022-07-22 Moved to {id}/restore endpoint")]
[HttpPatch("{id}/activate")]
[HttpPut("{id}/activate")]
public async Task Activate(Guid orgId, Guid id)
{
await ActivateOrDeactivateUserAsync(orgId, id, _organizationService.ActivateUserAsync);
await RestoreAsync(orgId, id);
}
[Obsolete("2022-07-22 Moved to /restore endpoint")]
[HttpPatch("activate")]
[HttpPut("activate")]
public async Task<ListResponseModel<OrganizationUserBulkResponseModel>> BulkActivate(Guid orgId, [FromBody] OrganizationUserBulkRequestModel model)
{
return await ActivateOrDeactivateUsersAsync(orgId, model, _organizationService.ActivateUsersAsync);
return await BulkRestoreAsync(orgId, model);
}
private async Task ActivateOrDeactivateUserAsync(
[HttpPatch("{id}/revoke")]
[HttpPut("{id}/revoke")]
public async Task RevokeAsync(Guid orgId, Guid id)
{
await RestoreOrRevokeUserAsync(orgId, id, _organizationService.RevokeUserAsync);
}
[HttpPatch("revoke")]
[HttpPut("revoke")]
public async Task<ListResponseModel<OrganizationUserBulkResponseModel>> BulkRevokeAsync(Guid orgId, [FromBody] OrganizationUserBulkRequestModel model)
{
return await RestoreOrRevokeUsersAsync(orgId, model, _organizationService.RevokeUsersAsync);
}
[HttpPatch("{id}/restore")]
[HttpPut("{id}/restore")]
public async Task RestoreAsync(Guid orgId, Guid id)
{
await RestoreOrRevokeUserAsync(orgId, id, _organizationService.RestoreUserAsync);
}
[HttpPatch("restore")]
[HttpPut("restore")]
public async Task<ListResponseModel<OrganizationUserBulkResponseModel>> BulkRestoreAsync(Guid orgId, [FromBody] OrganizationUserBulkRequestModel model)
{
return await RestoreOrRevokeUsersAsync(orgId, model, _organizationService.RestoreUsersAsync);
}
private async Task RestoreOrRevokeUserAsync(
Guid orgId,
Guid id,
Func<OrganizationUser, Guid?, Task> statusAction)
@ -421,7 +453,7 @@ namespace Bit.Api.Controllers
await statusAction(orgUser, userId);
}
private async Task<ListResponseModel<OrganizationUserBulkResponseModel>> ActivateOrDeactivateUsersAsync(
private async Task<ListResponseModel<OrganizationUserBulkResponseModel>> RestoreOrRevokeUsersAsync(
Guid orgId,
OrganizationUserBulkRequestModel model,
Func<Guid, IEnumerable<Guid>, Guid?, Task<List<Tuple<OrganizationUser, string>>>> statusAction)

View File

@ -51,8 +51,8 @@
OrganizationUser_AdminResetPassword = 1508,
OrganizationUser_ResetSsoLink = 1509,
OrganizationUser_FirstSsoLogin = 1510,
OrganizationUser_Deactivated = 1511,
OrganizationUser_Activated = 1512,
OrganizationUser_Revoked = 1511,
OrganizationUser_Restored = 1512,
Organization_Updated = 1600,
Organization_PurgedVault = 1601,

View File

@ -5,6 +5,6 @@
Invited = 0,
Accepted = 1,
Confirmed = 2,
Deactivated = -1,
Revoked = -1,
}
}

View File

@ -36,7 +36,7 @@ namespace Bit.Core.Repositories
Task<OrganizationUser> GetByOrganizationEmailAsync(Guid organizationId, string email);
Task<IEnumerable<OrganizationUserPublicKey>> GetManyPublicKeysByOrganizationUserAsync(Guid organizationId, IEnumerable<Guid> Ids);
Task<IEnumerable<OrganizationUserUserDetails>> GetManyByMinimumRoleAsync(Guid organizationId, OrganizationUserType minRole);
Task DeactivateAsync(Guid id);
Task ActivateAsync(Guid id, OrganizationUserStatusType status);
Task RevokeAsync(Guid id);
Task RestoreAsync(Guid id, OrganizationUserStatusType status);
}
}

View File

@ -58,11 +58,11 @@ namespace Bit.Core.Services
Task DeleteSsoUserAsync(Guid userId, Guid? organizationId);
Task<Organization> UpdateOrganizationKeysAsync(Guid orgId, string publicKey, string privateKey);
Task<bool> HasConfirmedOwnersExceptAsync(Guid organizationId, IEnumerable<Guid> organizationUsersId, bool includeProvider = true);
Task DeactivateUserAsync(OrganizationUser organizationUser, Guid? disablingUserId);
Task<List<Tuple<OrganizationUser, string>>> DeactivateUsersAsync(Guid organizationId,
IEnumerable<Guid> organizationUserIds, Guid? disablingUserId);
Task ActivateUserAsync(OrganizationUser organizationUser, Guid? enablingUserId);
Task<List<Tuple<OrganizationUser, string>>> ActivateUsersAsync(Guid organizationId,
IEnumerable<Guid> organizationUserIds, Guid? enablingUserId);
Task RevokeUserAsync(OrganizationUser organizationUser, Guid? revokingUserId);
Task<List<Tuple<OrganizationUser, string>>> RevokeUsersAsync(Guid organizationId,
IEnumerable<Guid> organizationUserIds, Guid? revokingUserId);
Task RestoreUserAsync(OrganizationUser organizationUser, Guid? restoringUserId);
Task<List<Tuple<OrganizationUser, string>>> RestoreUsersAsync(Guid organizationId,
IEnumerable<Guid> organizationUserIds, Guid? restoringUserId);
}
}

View File

@ -2213,19 +2213,19 @@ namespace Bit.Core.Services
}
}
public async Task DeactivateUserAsync(OrganizationUser organizationUser, Guid? disablingUserId)
public async Task RevokeUserAsync(OrganizationUser organizationUser, Guid? revokingUserId)
{
if (organizationUser.Status == OrganizationUserStatusType.Deactivated)
if (organizationUser.Status == OrganizationUserStatusType.Revoked)
{
throw new BadRequestException("Already revoked.");
}
if (disablingUserId.HasValue && organizationUser.UserId == disablingUserId.Value)
if (revokingUserId.HasValue && organizationUser.UserId == revokingUserId.Value)
{
throw new BadRequestException("You cannot revoke yourself.");
}
if (organizationUser.Type == OrganizationUserType.Owner && disablingUserId.HasValue &&
if (organizationUser.Type == OrganizationUserType.Owner && revokingUserId.HasValue &&
!await _currentContext.OrganizationOwner(organizationUser.OrganizationId))
{
throw new BadRequestException("Only owners can revoke other owners.");
@ -2236,13 +2236,13 @@ namespace Bit.Core.Services
throw new BadRequestException("Organization must have at least one confirmed owner.");
}
await _organizationUserRepository.DeactivateAsync(organizationUser.Id);
organizationUser.Status = OrganizationUserStatusType.Deactivated;
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Deactivated);
await _organizationUserRepository.RevokeAsync(organizationUser.Id);
organizationUser.Status = OrganizationUserStatusType.Revoked;
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Revoked);
}
public async Task<List<Tuple<OrganizationUser, string>>> DeactivateUsersAsync(Guid organizationId,
IEnumerable<Guid> organizationUserIds, Guid? disablingUserId)
public async Task<List<Tuple<OrganizationUser, string>>> RevokeUsersAsync(Guid organizationId,
IEnumerable<Guid> organizationUserIds, Guid? revokingUserId)
{
var orgUsers = await _organizationUserRepository.GetManyAsync(organizationUserIds);
var filteredUsers = orgUsers.Where(u => u.OrganizationId == organizationId)
@ -2259,7 +2259,7 @@ namespace Bit.Core.Services
}
var deletingUserIsOwner = false;
if (disablingUserId.HasValue)
if (revokingUserId.HasValue)
{
deletingUserIsOwner = await _currentContext.OrganizationOwner(organizationId);
}
@ -2270,24 +2270,24 @@ namespace Bit.Core.Services
{
try
{
if (organizationUser.Status == OrganizationUserStatusType.Deactivated)
if (organizationUser.Status == OrganizationUserStatusType.Revoked)
{
throw new BadRequestException("Already revoked.");
}
if (disablingUserId.HasValue && organizationUser.UserId == disablingUserId)
if (revokingUserId.HasValue && organizationUser.UserId == revokingUserId)
{
throw new BadRequestException("You cannot revoke yourself.");
}
if (organizationUser.Type == OrganizationUserType.Owner && disablingUserId.HasValue && !deletingUserIsOwner)
if (organizationUser.Type == OrganizationUserType.Owner && revokingUserId.HasValue && !deletingUserIsOwner)
{
throw new BadRequestException("Only owners can revoke other owners.");
}
await _organizationUserRepository.DeactivateAsync(organizationUser.Id);
organizationUser.Status = OrganizationUserStatusType.Deactivated;
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Deactivated);
await _organizationUserRepository.RevokeAsync(organizationUser.Id);
organizationUser.Status = OrganizationUserStatusType.Revoked;
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Revoked);
result.Add(Tuple.Create(organizationUser, ""));
}
@ -2300,19 +2300,19 @@ namespace Bit.Core.Services
return result;
}
public async Task ActivateUserAsync(OrganizationUser organizationUser, Guid? enablingUserId)
public async Task RestoreUserAsync(OrganizationUser organizationUser, Guid? restoringUserId)
{
if (organizationUser.Status != OrganizationUserStatusType.Deactivated)
if (organizationUser.Status != OrganizationUserStatusType.Revoked)
{
throw new BadRequestException("Already active.");
}
if (enablingUserId.HasValue && organizationUser.UserId == enablingUserId.Value)
if (restoringUserId.HasValue && organizationUser.UserId == restoringUserId.Value)
{
throw new BadRequestException("You cannot restore yourself.");
}
if (organizationUser.Type == OrganizationUserType.Owner && enablingUserId.HasValue &&
if (organizationUser.Type == OrganizationUserType.Owner && restoringUserId.HasValue &&
!await _currentContext.OrganizationOwner(organizationUser.OrganizationId))
{
throw new BadRequestException("Only owners can restore other owners.");
@ -2320,13 +2320,13 @@ namespace Bit.Core.Services
var status = GetPriorActiveOrganizationUserStatusType(organizationUser);
await _organizationUserRepository.ActivateAsync(organizationUser.Id, status);
await _organizationUserRepository.RestoreAsync(organizationUser.Id, status);
organizationUser.Status = status;
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Activated);
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Restored);
}
public async Task<List<Tuple<OrganizationUser, string>>> ActivateUsersAsync(Guid organizationId,
IEnumerable<Guid> organizationUserIds, Guid? enablingUserId)
public async Task<List<Tuple<OrganizationUser, string>>> RestoreUsersAsync(Guid organizationId,
IEnumerable<Guid> organizationUserIds, Guid? restoringUserId)
{
var orgUsers = await _organizationUserRepository.GetManyAsync(organizationUserIds);
var filteredUsers = orgUsers.Where(u => u.OrganizationId == organizationId)
@ -2338,7 +2338,7 @@ namespace Bit.Core.Services
}
var deletingUserIsOwner = false;
if (enablingUserId.HasValue)
if (restoringUserId.HasValue)
{
deletingUserIsOwner = await _currentContext.OrganizationOwner(organizationId);
}
@ -2349,26 +2349,26 @@ namespace Bit.Core.Services
{
try
{
if (organizationUser.Status != OrganizationUserStatusType.Deactivated)
if (organizationUser.Status != OrganizationUserStatusType.Revoked)
{
throw new BadRequestException("Already active.");
}
if (enablingUserId.HasValue && organizationUser.UserId == enablingUserId)
if (restoringUserId.HasValue && organizationUser.UserId == restoringUserId)
{
throw new BadRequestException("You cannot restore yourself.");
}
if (organizationUser.Type == OrganizationUserType.Owner && enablingUserId.HasValue && !deletingUserIsOwner)
if (organizationUser.Type == OrganizationUserType.Owner && restoringUserId.HasValue && !deletingUserIsOwner)
{
throw new BadRequestException("Only owners can restore other owners.");
}
var status = GetPriorActiveOrganizationUserStatusType(organizationUser);
await _organizationUserRepository.ActivateAsync(organizationUser.Id, status);
await _organizationUserRepository.RestoreAsync(organizationUser.Id, status);
organizationUser.Status = status;
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Activated);
await _eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_Restored);
result.Add(Tuple.Create(organizationUser, ""));
}

View File

@ -406,7 +406,7 @@ namespace Bit.Infrastructure.Dapper.Repositories
}
}
public async Task DeactivateAsync(Guid id)
public async Task RevokeAsync(Guid id)
{
using (var connection = new SqlConnection(ConnectionString))
{
@ -417,7 +417,7 @@ namespace Bit.Infrastructure.Dapper.Repositories
}
}
public async Task ActivateAsync(Guid id, OrganizationUserStatusType status)
public async Task RestoreAsync(Guid id, OrganizationUserStatusType status)
{
using (var connection = new SqlConnection(ConnectionString))
{

View File

@ -424,7 +424,7 @@ namespace Bit.Infrastructure.EntityFramework.Repositories
}
}
public async Task DeactivateAsync(Guid id)
public async Task RevokeAsync(Guid id)
{
using (var scope = ServiceScopeFactory.CreateScope())
{
@ -433,7 +433,7 @@ namespace Bit.Infrastructure.EntityFramework.Repositories
if (orgUser != null)
{
dbContext.Update(orgUser);
orgUser.Status = OrganizationUserStatusType.Deactivated;
orgUser.Status = OrganizationUserStatusType.Revoked;
await dbContext.SaveChangesAsync();
if (orgUser.UserId.HasValue)
{
@ -443,7 +443,7 @@ namespace Bit.Infrastructure.EntityFramework.Repositories
}
}
public async Task ActivateAsync(Guid id, OrganizationUserStatusType status)
public async Task RestoreAsync(Guid id, OrganizationUserStatusType status)
{
using (var scope = ServiceScopeFactory.CreateScope())
{