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 ;
42using Bit . Core . AdminConsole . OrganizationFeatures . OrganizationUsers . Interfaces ;
53using Bit . Core . AdminConsole . OrganizationFeatures . Policies ;
64using Bit . Core . AdminConsole . OrganizationFeatures . Policies . PolicyRequirements ;
7- using Bit . Core . AdminConsole . Utilities . v2 . Results ;
85using Bit . Core . Entities ;
96using Bit . Core . Enums ;
107using 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}
0 commit comments