Skip to content

Commit 3ee2bf4

Browse files
committed
Clean up clean up everybody everywhere. Clean up clean up everybody do your share.
1 parent 7fb8910 commit 3ee2bf4

File tree

11 files changed

+138
-386
lines changed

11 files changed

+138
-386
lines changed

src/Core/AdminConsole/Models/Data/OrganizationUsers/AcceptedOrganizationUser.cs

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Bit.Core.AdminConsole.Models.Data.OrganizationUsers;
2+
3+
public record AcceptedOrganizationUserToConfirm
4+
{
5+
public required Guid OrganizationUserId { get; init; }
6+
public required Guid UserId { get; init; }
7+
public required string Key { get; init; }
8+
}
Lines changed: 53 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
using Bit.Core.AdminConsole.Entities;
2-
using Bit.Core.AdminConsole.Models.Data.OrganizationUsers;
3-
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.DeleteClaimedAccount;
1+
using Bit.Core.AdminConsole.Models.Data.OrganizationUsers;
42
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
53
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
64
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
7-
using Bit.Core.AdminConsole.Utilities.v2.Results;
85
using Bit.Core.Entities;
96
using Bit.Core.Enums;
107
using Bit.Core.Models.Data;
@@ -26,77 +23,75 @@ public class AutomaticallyConfirmOrganizationUserCommand(IOrganizationUserReposi
2623
IPushRegistrationService pushRegistrationService,
2724
IDeviceRepository deviceRepository,
2825
IPushNotificationService pushNotificationService,
29-
IFeatureService featureService,
3026
IPolicyRequirementQuery policyRequirementQuery,
3127
ICollectionRepository collectionRepository,
28+
TimeProvider timeProvider,
3229
ILogger<AutomaticallyConfirmOrganizationUserCommand> logger) : IAutomaticallyConfirmOrganizationUserCommand
3330
{
3431
public async Task<CommandResult> AutomaticallyConfirmOrganizationUserAsync(AutomaticallyConfirmOrganizationUserRequest request)
3532
{
36-
var requestData = await RetrieveDataAsync(request);
33+
var validatorRequest = await RetrieveDataAsync(request);
3734

38-
if (requestData.IsError)
39-
{
40-
return requestData.AsError;
41-
}
35+
var validatedData = await validator.ValidateAsync(validatorRequest);
4236

43-
var validatedData = await validator.ValidateAsync(requestData.AsSuccess);
44-
45-
if (validatedData.IsError)
37+
if (validatedData.IsValid)
4638
{
47-
return validatedData.AsError;
48-
}
49-
50-
var validatedRequest = validatedData.Request;
39+
var userToConfirm = new AcceptedOrganizationUserToConfirm
40+
{
41+
OrganizationUserId = validatedData.Request.OrganizationUser!.Id,
42+
UserId = validatedData.Request.OrganizationUser.UserId!.Value,
43+
Key = validatedData.Request.Key
44+
};
5145

52-
var successfulConfirmation = await organizationUserRepository.ConfirmOrganizationUserAsync(validatedRequest.OrganizationUser);
46+
// This operation is idempotent. If false, user is already confirmed and no additional side effects are required.
47+
if (!await organizationUserRepository.ConfirmOrganizationUserAsync(userToConfirm))
48+
{
49+
return new None();
50+
}
5351

54-
if (!successfulConfirmation)
55-
{
56-
return new None(); // Operation is idempotent. If this is false, then the user is already confirmed.
52+
await Task.WhenAll([
53+
CreateDefaultCollectionsAsync(validatedData.Request),
54+
LogOrganizationUserConfirmedEventAsync(validatedData.Request),
55+
SendConfirmedOrganizationUserEmailAsync(validatedData.Request),
56+
SyncOrganizationKeysAsync(validatedData.Request)
57+
]);
5758
}
5859

59-
_ = await validatedRequest.ApplyAsync([
60-
CreateDefaultCollectionsAsync,
61-
LogOrganizationUserConfirmedEventAsync,
62-
SendConfirmedOrganizationUserEmailAsync,
63-
DeleteDeviceRegistrationAsync,
64-
PushSyncOrganizationKeysAsync
65-
]);
60+
return new None();
61+
}
6662

67-
return new None(); // Operation is idempotent. If this is false, then the user is already confirmed.
63+
private async Task SyncOrganizationKeysAsync(AutomaticallyConfirmOrganizationUserValidationRequest rqeuest)
64+
{
65+
await DeleteDeviceRegistrationAsync(rqeuest);
66+
await PushSyncOrganizationKeysAsync(rqeuest);
6867
}
6968

70-
private async Task<CommandResult<AutomaticallyConfirmOrganizationUserValidationRequest>> CreateDefaultCollectionsAsync(
71-
AutomaticallyConfirmOrganizationUserValidationRequest request)
69+
private async Task CreateDefaultCollectionsAsync(AutomaticallyConfirmOrganizationUserValidationRequest request)
7270
{
7371
try
7472
{
7573
if (!await ShouldCreateDefaultCollectionAsync(request))
7674
{
77-
return request;
75+
return;
7876
}
7977

8078
await collectionRepository.CreateAsync(
8179
new Collection
8280
{
83-
OrganizationId = request.Organization.Id,
81+
OrganizationId = request.Organization!.Id,
8482
Name = request.DefaultUserCollectionName,
8583
Type = CollectionType.DefaultUserCollection
8684
},
8785
groups: null,
8886
[new CollectionAccessSelection
8987
{
90-
Id = request.OrganizationUser.Id,
88+
Id = request.OrganizationUser!.Id,
9189
Manage = true
9290
}]);
93-
94-
return request;
9591
}
9692
catch (Exception ex)
9793
{
9894
logger.LogError(ex, "Failed to create default collection for user.");
99-
return new CommandResult<AutomaticallyConfirmOrganizationUserValidationRequest>(new FailedToCreateDefaultCollection());
10095
}
10196
}
10297

@@ -108,120 +103,81 @@ [new CollectionAccessSelection
108103
/// </param>
109104
/// <returns>The result is a boolean value indicating whether a default collection should be created.</returns>
110105
private async Task<bool> ShouldCreateDefaultCollectionAsync(AutomaticallyConfirmOrganizationUserValidationRequest request) =>
111-
featureService.IsEnabled(FeatureFlagKeys.CreateDefaultLocation)
112-
&& !string.IsNullOrWhiteSpace(request.DefaultUserCollectionName)
113-
&& (await policyRequirementQuery.GetAsync<OrganizationDataOwnershipPolicyRequirement>(request.OrganizationUser.UserId))
114-
.RequiresDefaultCollectionOnConfirm(request.Organization.Id);
106+
!string.IsNullOrWhiteSpace(request.DefaultUserCollectionName)
107+
&& (await policyRequirementQuery.GetAsync<OrganizationDataOwnershipPolicyRequirement>(request.OrganizationUser!.UserId!.Value))
108+
.RequiresDefaultCollectionOnConfirm(request.Organization!.Id);
115109

116-
private async Task<CommandResult<AutomaticallyConfirmOrganizationUserValidationRequest>> PushSyncOrganizationKeysAsync(AutomaticallyConfirmOrganizationUserValidationRequest request)
110+
private async Task PushSyncOrganizationKeysAsync(AutomaticallyConfirmOrganizationUserValidationRequest request)
117111
{
118112
try
119113
{
120-
await pushNotificationService.PushSyncOrgKeysAsync(request.OrganizationUser.UserId);
121-
return request;
114+
await pushNotificationService.PushSyncOrgKeysAsync(request.OrganizationUser!.UserId!.Value);
122115
}
123116
catch (Exception ex)
124117
{
125118
logger.LogError(ex, "Failed to push organization keys.");
126-
return new FailedToPushOrganizationSyncKeys();
127119
}
128120
}
129121

130-
private async Task<CommandResult<AutomaticallyConfirmOrganizationUserValidationRequest>> LogOrganizationUserConfirmedEventAsync(
131-
AutomaticallyConfirmOrganizationUserValidationRequest request)
122+
private async Task LogOrganizationUserConfirmedEventAsync(AutomaticallyConfirmOrganizationUserValidationRequest request)
132123
{
133124
try
134125
{
135126
await eventService.LogOrganizationUserEventAsync(request.OrganizationUser,
136127
EventType.OrganizationUser_AutomaticallyConfirmed,
137128
request.PerformedOn.UtcDateTime);
138-
return request;
139129
}
140130
catch (Exception ex)
141131
{
142132
logger.LogError(ex, "Failed to log OrganizationUser_AutomaticallyConfirmed event.");
143-
return new FailedToWriteToEventLog();
144133
}
145134
}
146135

147-
private async Task<CommandResult<AutomaticallyConfirmOrganizationUserValidationRequest>> SendConfirmedOrganizationUserEmailAsync(
148-
AutomaticallyConfirmOrganizationUserValidationRequest request)
136+
private async Task SendConfirmedOrganizationUserEmailAsync(AutomaticallyConfirmOrganizationUserValidationRequest request)
149137
{
150138
try
151139
{
152-
var user = await userRepository.GetByIdAsync(request.OrganizationUser.UserId);
140+
var user = await userRepository.GetByIdAsync(request.OrganizationUser!.UserId!.Value);
153141

154-
if (user is null) return new UserNotFoundError();
155-
156-
await mailService.SendOrganizationConfirmedEmailAsync(request.Organization.Name,
157-
user.Email,
142+
await mailService.SendOrganizationConfirmedEmailAsync(request.Organization!.Name,
143+
user!.Email,
158144
request.OrganizationUser.AccessSecretsManager);
159-
160-
return request;
161145
}
162146
catch (Exception ex)
163147
{
164148
logger.LogError(ex, "Failed to send OrganizationUserConfirmed.");
165-
return new FailedToSendConfirmedUserEmail();
166149
}
167150
}
168151

169-
private async Task<CommandResult<AutomaticallyConfirmOrganizationUserValidationRequest>> DeleteDeviceRegistrationAsync(
170-
AutomaticallyConfirmOrganizationUserValidationRequest request)
152+
private async Task DeleteDeviceRegistrationAsync(AutomaticallyConfirmOrganizationUserValidationRequest request)
171153
{
172154
try
173155
{
174-
var devices = (await deviceRepository.GetManyByUserIdAsync(request.OrganizationUser.UserId))
156+
var devices = (await deviceRepository.GetManyByUserIdAsync(request.OrganizationUser!.UserId!.Value))
175157
.Where(d => !string.IsNullOrWhiteSpace(d.PushToken))
176158
.Select(d => d.Id.ToString());
177159

178-
await pushRegistrationService.DeleteUserRegistrationOrganizationAsync(devices, request.Organization.Id.ToString());
179-
return request;
160+
await pushRegistrationService.DeleteUserRegistrationOrganizationAsync(devices, request.Organization!.Id.ToString());
180161
}
181162
catch (Exception ex)
182163
{
183164
logger.LogError(ex, "Failed to delete device registration.");
184-
return new FailedToDeleteDeviceRegistration();
185165
}
186166
}
187167

188-
private async Task<CommandResult<AutomaticallyConfirmOrganizationUserValidationRequest>> RetrieveDataAsync(
168+
private async Task<AutomaticallyConfirmOrganizationUserValidationRequest> RetrieveDataAsync(
189169
AutomaticallyConfirmOrganizationUserRequest request)
190170
{
191-
var organizationUser = await GetOrganizationUserAsync(request);
192-
193-
if (organizationUser.IsError) return organizationUser.AsError;
194-
195-
var organization = await GetOrganizationAsync(request.OrganizationId);
196-
197-
if (organization.IsError) return organization.AsError;
198-
199171
return new AutomaticallyConfirmOrganizationUserValidationRequest
200172
{
201-
OrganizationUser = organizationUser.AsSuccess,
202-
Organization = organization.AsSuccess,
203-
PerformedBy = request.PerformedBy,
173+
OrganizationUserId = request.OrganizationUserId,
174+
OrganizationId = request.OrganizationId,
175+
Key = request.Key,
204176
DefaultUserCollectionName = request.DefaultUserCollectionName,
205-
PerformedOn = request.PerformedOn
206-
};
207-
}
208-
209-
private async Task<CommandResult<AcceptedOrganizationUser>> GetOrganizationUserAsync(AutomaticallyConfirmOrganizationUserRequest request)
210-
{
211-
var organizationUser = await organizationUserRepository.GetByIdAsync(request.OrganizationUserId);
212-
213-
return organizationUser switch
214-
{
215-
null or { UserId: null } => new UserNotFoundError(),
216-
{ Status: not OrganizationUserStatusType.Accepted } => new UserIsNotAccepted(),
217-
_ => new AcceptedOrganizationUser(organizationUser, request.Key)
177+
PerformedBy = request.PerformedBy,
178+
PerformedOn = timeProvider.GetUtcNow(),
179+
OrganizationUser = await organizationUserRepository.GetByIdAsync(request.OrganizationUserId),
180+
Organization = await organizationRepository.GetByIdAsync(request.OrganizationId)
218181
};
219182
}
220-
221-
private async Task<CommandResult<Organization>> GetOrganizationAsync(Guid organizationId)
222-
{
223-
var organization = await organizationRepository.GetByIdAsync(organizationId);
224-
225-
return organization is not null ? organization : new OrganizationNotFound();
226-
}
227183
}
Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Bit.Core.AdminConsole.Entities;
22
using Bit.Core.AdminConsole.Models.Data;
3-
using Bit.Core.AdminConsole.Models.Data.OrganizationUsers;
3+
using Bit.Core.Entities;
44

55
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.AutoConfirmUser;
66

@@ -9,20 +9,13 @@ public record AutomaticallyConfirmOrganizationUserRequest
99
public required Guid OrganizationUserId { get; init; }
1010
public required Guid OrganizationId { get; init; }
1111
public required string Key { get; init; }
12-
1312
public required string DefaultUserCollectionName { get; init; }
1413
public required IActingUser PerformedBy { get; init; }
1514
public required DateTimeOffset PerformedOn { get; init; }
1615
}
1716

18-
public record AutomaticallyConfirmOrganizationUserValidationRequest
17+
public record AutomaticallyConfirmOrganizationUserValidationRequest : AutomaticallyConfirmOrganizationUserRequest
1918
{
20-
public required AcceptedOrganizationUser OrganizationUser { get; init; }
21-
22-
public required Organization Organization { get; init; }
23-
24-
public required IActingUser PerformedBy { get; init; }
25-
public required DateTimeOffset PerformedOn { get; init; }
26-
27-
public required string DefaultUserCollectionName { get; init; }
19+
public OrganizationUser? OrganizationUser { get; set; }
20+
public Organization? Organization { get; set; }
2821
}

0 commit comments

Comments
 (0)