예제 #1
0
        public async Task <TResult> CreateAuthenticatedAsync <TResult>(Guid integrationId, Guid authenticationId,
                                                                       string methodName, IDictionary <string, string> paramSet,
                                                                       Func <TResult> onSuccess,
                                                                       Func <TResult> onAlreadyExists)
        {
            var rollback = new RollbackAsync <TResult>();

            var docByMethod = new AccessDocument
            {
                LookupId = integrationId,
                Method   = methodName,
            };

            rollback.AddTaskCreate(authenticationId, methodName, docByMethod, onAlreadyExists, this.repository);

            var integrationDoc = new AuthenticationRequestDocument
            {
                LinkedAuthenticationId = authenticationId,
                Method = methodName,
                Action = Enum.GetName(typeof(AuthenticationActions), AuthenticationActions.access)
            };

            integrationDoc.SetExtraParams(paramSet);
            rollback.AddTaskCreate(integrationId, integrationDoc, onAlreadyExists, this.repository);

            return(await rollback.ExecuteAsync(onSuccess));
        }
예제 #2
0
        internal async Task <TResult> CreateCredentialMappingAsync <TResult>(Guid credentialMappingId,
                                                                             CredentialValidationMethodTypes method, string subjectId, Guid actorId,
                                                                             Func <TResult> onSuccess,
                                                                             Func <TResult> onAlreadyExists,
                                                                             Func <TResult> onTokenAlreadyInUse)
        {
            var rollback = new RollbackAsync <TResult>();

            var methodName           = Enum.GetName(typeof(CredentialValidationMethodTypes), method);
            var credentialMappingDoc = new Documents.CredentialMappingDocument()
            {
                Method  = methodName,
                Subject = subjectId,
                ActorId = actorId,
            };

            rollback.AddTaskCreate(credentialMappingId, credentialMappingDoc, onAlreadyExists, this.repository);

            var lookupDocument = new Azure.Documents.CredentialMappingLookupDocument()
            {
                CredentialMappingId = credentialMappingId,
                Method  = methodName,
                Subject = subjectId,
            };

            rollback.AddTaskCreate(subjectId, methodName, lookupDocument, onTokenAlreadyInUse, this.repository);

            rollback.AddTaskCreateOrUpdate(actorId,
                                           (Documents.ActorMappingsDocument authDoc) => authDoc.AddInviteId(credentialMappingId),
                                           (authDoc) => authDoc.RemoveInviteId(credentialMappingId),
                                           onAlreadyExists, // This should fail on the action above as well
                                           this.repository);

            return(await rollback.ExecuteAsync(onSuccess));
        }
예제 #3
0
        public async Task <TResult> CreateUnauthenticatedAsync <TResult>(Guid integrationId, Guid accountId,
                                                                         string methodName,
                                                                         Func <TResult> onSuccess,
                                                                         Func <TResult> onAlreadyExists)
        {
            var rollback = new RollbackAsync <TResult>();

            var docByMethod = new AccessDocument
            {
                LookupId = integrationId,
                Method   = methodName,
            };

            rollback.AddTaskCreate(accountId, methodName, docByMethod, onAlreadyExists, this.repository);

            var docById = new AccessDocument
            {
                LookupId = accountId,
                Method   = methodName,
            };

            rollback.AddTaskCreate(integrationId, docById, onAlreadyExists, this.repository);

            return(await rollback.ExecuteAsync(onSuccess));
        }
예제 #4
0
        public async Task <TResult> CreatePasswordCredentialAsync <TResult>(Guid passwordCredentialId,
                                                                            Guid actorId, Guid loginId, DateTime?emailLastSent,
                                                                            Func <TResult> onSuccess,
                                                                            Func <TResult> onAlreadyExists,
                                                                            Func <TResult> onRelationshipAlreadyExists,
                                                                            Func <TResult> onLoginAlreadyUsed)
        {
            var rollback = new RollbackAsync <TResult>();

            var lookupDoc = new Documents.LoginActorLookupDocument
            {
                ActorId = actorId,
            };

            rollback.AddTaskCreate(loginId, lookupDoc,
                                   onLoginAlreadyUsed, this.repository);

            rollback.AddTaskCreateOrUpdate(actorId,
                                           (Documents.ActorMappingsDocument actorDoc) =>
                                           actorDoc.AddPasswordCredential(passwordCredentialId),
                                           actorDoc => actorDoc.RemovePasswordCredential(passwordCredentialId),
                                           onRelationshipAlreadyExists,
                                           this.repository);

            var passwordCredentialDoc = new Documents.PasswordCredentialDocument
            {
                LoginId       = loginId,
                EmailLastSent = emailLastSent,
            };

            rollback.AddTaskCreate(passwordCredentialId, passwordCredentialDoc,
                                   onAlreadyExists, this.repository);

            return(await rollback.ExecuteAsync(onSuccess));
        }
예제 #5
0
        internal async Task <TResult> MarkInviteRedeemedAsync <TResult>(Guid inviteToken, Guid loginId,
                                                                        Func <Guid, TResult> onFound,
                                                                        Func <TResult> onNotFound,
                                                                        Func <Guid, TResult> onAlreadyRedeemed,
                                                                        Func <TResult> onAlreadyInUse,
                                                                        Func <TResult> onAlreadyConnected)
        {
            var lookupResults = await await repository.FindByIdAsync(inviteToken,
                                                                     async (Documents.InviteTokenDocument tokenDocument) =>
            {
                var rollback = new RollbackAsync <TResult>();

                rollback.AddTaskUpdate(tokenDocument.InviteId,
                                       (Documents.InviteDocument inviteDoc) => { inviteDoc.LoginId = loginId; },
                                       (inviteDoc) => { inviteDoc.LoginId = default(Guid?); },
                                       onNotFound,
                                       this.repository);

                var loginLookup = new Documents.LoginActorLookupDocument()
                {
                    ActorId = tokenDocument.ActorId,
                };
                rollback.AddTaskCreate(loginId, loginLookup, onAlreadyInUse, this.repository);

                return(await rollback.ExecuteAsync(() => onFound(tokenDocument.ActorId)));
            },
                                                                     () => onNotFound().ToTask());

            return(lookupResults);
        }
예제 #6
0
        public static async Task <TRollback> ExecuteDeleteJoinAsync <TRollback, TDocument>(this RollbackAsync <Guid?, TRollback> rollback,
                                                                                           Func <TRollback> onSuccess,
                                                                                           AzureStorageRepository repo)
            where TDocument : class, ITableEntity
        {
            var result = await await rollback.ExecuteAsync <Task <TRollback> >(
                async (joinIds) =>
            {
                var joinId = joinIds.First(joinIdCandidate => joinIdCandidate.HasValue);
                if (!joinId.HasValue)
                {
                    return(onSuccess());
                }
                return(await repo.DeleteIfAsync <TDocument, TRollback>(joinId.Value,
                                                                       async(doc, delete) =>
                {
                    await delete();
                    return onSuccess();
                },
                                                                       () =>
                {
                    // TODO: Log data inconsistency
                    return onSuccess();
                }));
            },
                (failureResult) => failureResult.ToTask());

            return(result);
        }
        internal static Task <TResult> CreateAsync <TResult>(Guid processStageId, Guid actorId,
                                                             Guid processStageTypeId, string title,
                                                             KeyValuePair <Guid[], Guid>[] confirmableActorIds, Guid[] editableActorIds, Guid[] viewableActorIds,
                                                             Func <TResult> onSuccess,
                                                             Func <TResult> onAlreadyExists)
        {
            return(AzureStorageRepository.Connection(
                       azureStorageRepository =>
            {
                var rollback = new RollbackAsync <TResult>();

                var procStageDoc = new ProcessStageDocument()
                {
                    Owner = actorId,
                    ProcessStageType = processStageTypeId,
                    Title = title,
                };
                procStageDoc.SetConfirmables(confirmableActorIds);
                procStageDoc.SetEditables(editableActorIds);
                procStageDoc.SetViewables(viewableActorIds);
                rollback.AddTaskCreate(processStageId, procStageDoc,
                                       onAlreadyExists, azureStorageRepository);

                rollback.AddTaskCreateOrUpdate <TResult, Documents.ProcessStageActorLookupDocument>(actorId,
                                                                                                    (created, lookupDoc) => lookupDoc.AddLookupDocumentId(processStageId),
                                                                                                    lookupDoc => lookupDoc.RemoveLookupDocumentId(processStageId),
                                                                                                    azureStorageRepository);


                return rollback.ExecuteAsync(onSuccess);
            }));
        }
예제 #8
0
        public async Task <TResult> CreateAsync <TResult>(Guid integrationId, Guid accountId,
                                                          CredentialValidationMethodTypes method, IDictionary <string, string> paramSet,
                                                          Func <TResult> onSuccess,
                                                          Func <TResult> onAlreadyExists)
        {
            var methodName  = Enum.GetName(typeof(CredentialValidationMethodTypes), method);
            var docByMethod = new AccessDocument
            {
                LookupId = integrationId,
                Method   = methodName,
            };

            docByMethod.SetExtraParams(paramSet);
            var docById = new AccessDocument
            {
                LookupId = accountId,
                Method   = methodName,
            };

            docById.SetExtraParams(paramSet);
            var rollback = new RollbackAsync <TResult>();

            rollback.AddTaskCreate(accountId, methodName, docByMethod, onAlreadyExists, this.repository);
            rollback.AddTaskCreate(integrationId, docById, onAlreadyExists, this.repository);
            return(await rollback.ExecuteAsync(onSuccess));
        }
예제 #9
0
        public async Task <TResult> CreateAsync <TResult>(
            Guid id, Guid actorId, string name,
            Func <TResult> onSuccess,
            Func <TResult> onAlreadyExists,
            Func <TResult> onActorNotFound)
        {
            var rollback = new RollbackAsync <TResult>();
            var document = new Documents.RoleDocument()
            {
                Name    = name,
                ActorId = actorId,
            };

            rollback.AddTaskCreate(id, document, onAlreadyExists, this.azureStorageRepository);

            rollback.AddTaskCreateOrUpdate(actorId,
                                           (Documents.ActorMappingsDocument actorDoc) =>
            {
                actorDoc.AddRole(id);
                return(true);
            },
                                           (actorDoc) => actorDoc.RemoveRole(id),
                                           onActorNotFound,
                                           this.azureStorageRepository);

            return(await rollback.ExecuteAsync(onSuccess));
        }
 public static Task <TResult> Transaction <TResult>(Func <RollbackAsync <TResult>, AzureStorageRepository, Func <TResult> > onConnected)
 {
     return(AzureStorageRepository.Connection(
                connection =>
     {
         var rollback = new RollbackAsync <TResult>();
         var onSuccess = onConnected(rollback, connection);
         return rollback.ExecuteAsync(onSuccess);
     }));
 }
예제 #11
0
        public async Task <TResult> CreateOrUpdateAsync <TResult>(Guid actorId, Guid claimId, string type, string value,
                                                                  Func <TResult> onSuccess,
                                                                  Func <TResult> onFailure,
                                                                  Func <TResult> onActorNotFound)
        {
            return(await await repository.FindLinkedDocumentsAsync <ActorMappingsDocument, ClaimDocument, Task <TResult> >(actorId,
                                                                                                                           (ActorMappingsDocument actorMappingsDocument) => actorMappingsDocument.Claims.ToGuidsFromByteArray(),
                                                                                                                           async (ActorMappingsDocument actorMappingsDocument, ClaimDocument[] claimDocuments) =>
            {
                var claimDocs =
                    claimDocuments.Where(
                        doc => string.Compare(doc.Type, type, StringComparison.OrdinalIgnoreCase) == 0)
                    .ToArray();
                if (claimDocs.Length >= 1)
                {
                    var claimDoc = claimDocs[0];
                    return await repository.UpdateAsync <ClaimDocument, TResult>(claimDoc.ClaimId,
                                                                                 async(currentDoc, saveAsync) =>
                    {
                        currentDoc.Value = value;
                        await saveAsync(currentDoc);
                        return onSuccess();
                    },
                                                                                 () => onFailure());
                }

                var rollback = new RollbackAsync <TResult>();
                var newClaimDoc = new ClaimDocument()
                {
                    ClaimId = claimId,
                    Issuer = actorId.ToString("N"),     //TODO - Is this is the correct issuer data???
                    Type = type,
                    Value = value
                };
                rollback.AddTaskCreate(claimId, newClaimDoc, onFailure, repository);
                rollback.AddTaskUpdate(actorId,
                                       (ActorMappingsDocument actorMapDocument) => actorMapDocument.AddClaim(claimId),
                                       (actorMapDocument) => actorMapDocument.RemoveClaim(claimId),
                                       onActorNotFound, repository);
                return await rollback.ExecuteAsync(onSuccess);
            },
                                                                                                                           () => onActorNotFound().ToTask()));
        }
예제 #12
0
        internal async Task <TResult> CreateCredentialMappingAsync <TResult>(Guid credentialMappingId,
                                                                             Guid loginId, Guid actorId, string email, Guid token, DateTime lastSent, bool isToken, bool overrideLoginId,
                                                                             Func <TResult> onSuccess,
                                                                             Func <TResult> onAlreadyExists,
                                                                             Func <TResult> onTokenAlreadyInUse,
                                                                             Func <TResult> onLoginAlreadyInUse)
        {
            var rollback = new RollbackAsync <TResult>();

            var inviteDocument = new Documents.InviteDocument()
            {
                ActorId  = actorId,
                Email    = email,
                IsToken  = isToken,
                LastSent = lastSent,
                Token    = token,
                LoginId  = loginId,
            };

            rollback.AddTaskCreate(credentialMappingId, inviteDocument, onAlreadyExists, this.repository);

            var inviteTokenDocument = new Documents.InviteTokenDocument()
            {
                ActorId  = actorId,
                InviteId = credentialMappingId,
            };

            rollback.AddTaskCreate(token, inviteTokenDocument, onTokenAlreadyInUse, this.repository);

            if (overrideLoginId)
            {
                var oldActorId = default(Guid);
                rollback.AddTaskCreateOrUpdate(loginId,
                                               (Documents.LoginActorLookupDocument loginActorDocument) =>
                {
                    oldActorId = loginActorDocument.ActorId;
                    loginActorDocument.ActorId = actorId;
                    return(true);
                },
                                               (loginActorDocument) =>
                {
                    loginActorDocument.ActorId = oldActorId;
                    return(true);
                },
                                               () => { throw new Exception("Login override failed"); }, // Should never happend because always return true on mutate
                                               this.repository);
            }
            else
            {
                var loginActorDocument = new Documents.LoginActorLookupDocument()
                {
                    ActorId = actorId,
                };
                rollback.AddTaskCreate(loginId, loginActorDocument, onLoginAlreadyInUse, this.repository);
            }

            rollback.AddTaskCreateOrUpdate(actorId,
                                           (Documents.ActorMappingsDocument authDoc) => authDoc.AddInviteId(credentialMappingId),
                                           (authDoc) => authDoc.RemoveInviteId(credentialMappingId),
                                           onAlreadyExists, // This should fail on the action above as well
                                           this.repository);

            return(await rollback.ExecuteAsync(onSuccess));
        }
예제 #13
0
        public static async Task <TResult> AddJoinAsync <TJoin, TDocJoin, TDoc1, TDoc2, TResult>(this AzureStorageRepository repo,
                                                                                                 Guid id, Guid id1, Guid id2, TDocJoin document,
                                                                                                 Func <TDoc1, TJoin[]> getJoins1,
                                                                                                 Func <TDoc2, TJoin[]> getJoins2,
                                                                                                 Func <TJoin, Guid> id1FromJoin,
                                                                                                 Func <TJoin, Guid> id2FromJoin,
                                                                                                 Action <TDoc1> mutateUpdate1,
                                                                                                 Action <TDoc1> mutateRollback1,
                                                                                                 Action <TDoc2> mutateUpdate2,
                                                                                                 Action <TDoc2> mutateRollback2,
                                                                                                 Func <TResult> onSuccess,
                                                                                                 Func <TResult> joinIdAlreadyExist,
                                                                                                 Func <TJoin, TResult> joinAlreadyExist,
                                                                                                 Func <TResult> doc1DoesNotExist,
                                                                                                 Func <TResult> doc2DoesNotExist)
            where TDocJoin : class, ITableEntity
            where TDoc1 : class, ITableEntity
            where TDoc2 : class, ITableEntity
        {
            var parallel = new RollbackAsync <TResult>();

            var duplicateJoin1 = default(TJoin);

            parallel.AddTaskUpdate <Guid, TResult, TDoc1>(id1,
                                                          (doc, successSave, successNoSave, reject) =>
            {
                var matches = getJoins1(doc).Where(join => id2FromJoin(join) == id2).ToArray();
                if (matches.Length > 0)
                {
                    duplicateJoin1 = matches[0];
                    return(reject());
                }
                mutateUpdate1(doc);
                return(successSave(id1));
            },
                                                          (id1Again, doc) => { mutateRollback1(doc); return(true); },
                                                          () => joinAlreadyExist(duplicateJoin1),
                                                          doc1DoesNotExist,
                                                          repo);

            var duplicateJoin2 = default(TJoin);

            parallel.AddTaskUpdate <Guid, TResult, TDoc2>(id2,
                                                          (doc, successSave, successNoSave, reject) =>
            {
                var matches = getJoins2(doc).Where(join => id1FromJoin(join) == id1).ToArray();
                if (matches.Length > 0)
                {
                    duplicateJoin2 = matches[0];
                    return(reject());
                }
                mutateUpdate2(doc);
                return(successSave(id2));
            },
                                                          (id1Again, doc) => { mutateRollback2(doc); return(true); },
                                                          () => joinAlreadyExist(duplicateJoin2),
                                                          doc2DoesNotExist,
                                                          repo);

            //parallel.AddTaskUpdate(id2,
            //    mutateUpdate2,
            //    mutateRollback2,
            //    doc2DoesNotExist,
            //    repo);

            parallel.AddTaskCreate(id, document,
                                   () => joinIdAlreadyExist(),
                                   repo);

            var result = await parallel.ExecuteAsync(
                () => onSuccess(),
                (failureResult) => failureResult);

            return(result);
        }
예제 #14
0
 public static async Task <TRollback> ExecuteAsync <TRollback>(this RollbackAsync <TRollback> rollback,
                                                               Func <TRollback> onSuccess)
 {
     return(await rollback.ExecuteAsync(onSuccess, r => r));
 }
예제 #15
0
        internal static Task <TResult> CreateAsync <TResult>(Guid processId,
                                                             Guid processStageId,
                                                             Guid actorId, Guid resourceId, Type resourceType, DateTime createdOn,
                                                             Process.ProcessStageResource[] resources,
                                                             Guid?previousStepId, DateTime?confirmedWhen, Guid?confirmedBy,
                                                             Guid [] lookupActorIds,
                                                             Func <TResult> onSuccess,
                                                             Func <TResult> onAlreadyExists)
        {
            return(AzureStorageRepository.Connection(
                       azureStorageRepository =>
            {
                var rollback = new RollbackAsync <TResult>();

                var resourceTypeString = resourceType.AssemblyQualifiedName;
                var processDocument = new ProcessDocument()
                {
                    ProcessStage = processStageId,

                    Resource = resourceId,
                    ResourceType = resourceTypeString,
                    CreatedOn = createdOn,
                    Owner = actorId,

                    ConfirmedBy = confirmedBy,
                    PreviousStep = previousStepId,
                    ConfirmedWhen = confirmedWhen,
                };
                processDocument.SetResources(resources);
                rollback.AddTaskCreate(processId, processDocument,
                                       onAlreadyExists, azureStorageRepository);

                foreach (var lookupActorId in lookupActorIds.Distinct())
                {
                    rollback.AddTaskCreateOrUpdate <TResult, Documents.ProcessStepActorLookupDocument>(lookupActorId, resourceTypeString,
                                                                                                       (created, lookupDoc) => lookupDoc.AddLookupDocumentId(processId),
                                                                                                       actorDoc => actorDoc.RemoveLookupDocumentId(processId),
                                                                                                       azureStorageRepository);
                }

                rollback.AddTaskCreateOrUpdate <TResult, Documents.ProcessStepResourceLookupDocument>(resourceId, resourceTypeString,
                                                                                                      (created, lookupDoc) => lookupDoc.AddLookupDocumentId(processId),
                                                                                                      actorDoc => actorDoc.RemoveLookupDocumentId(processId),
                                                                                                      azureStorageRepository);

                bool[] updates = resources
                                 .Select(
                    resource =>
                {
                    if (!resource.resourceId.HasValue)
                    {
                        return true;
                    }
                    rollback.AddTaskCreateOrUpdate <TResult, Documents.ProcessStepResourceKeyLookupDocument>(
                        resource.resourceId.Value, resource.type.AssemblyQualifiedName,
                        (created, lookupDoc) => lookupDoc.AddLookupDocumentId(processId),
                        lookupDoc => lookupDoc.RemoveLookupDocumentId(processId),
                        azureStorageRepository);
                    return true;
                })
                                 .ToArray();

                return rollback.ExecuteAsync(onSuccess);
            }));
        }