public async Task <Invitation> Handle(GetInvitationByIdQuery request, CancellationToken cancellationToken)
        {
            //==========================================================================
            // PRE QUERY CHECKLIST
            //==========================================================================
            // 1. CACHING: Check if item exists in cache.
            //     a. Use MediatR, Caching Library or Caching Routine within Accounts
            //
            // NOTE: Redis Multiplexer is already setup in our DI container using IRedisContext
            //--------------------------------------------------------------------------

            // Create the query
            string sqlQuery = "SELECT * FROM Documents d WHERE d.id ='" + request.Id + "'";
            var    sqlSpec  = new SqlQuerySpec {
                QueryText = sqlQuery
            };

            // Generate collection uri
            Uri collectionUri = UriFactory.CreateDocumentCollectionUri(_documentContext.Settings.Database, _documentContext.Settings.Collection);

            // Generate FeedOptions/ParitionKey
            var feedOptions = new FeedOptions
            {
                PartitionKey = new PartitionKey(Common.Constants.DocumentType.Invitation())
            };

            // Run query against the document store
            var result = _documentContext.Client.CreateDocumentQuery <InvitationDocumentModel>(
                collectionUri,
                sqlSpec,
                feedOptions
                );

            InvitationDocumentModel invitationDocumentModel = null;

            try
            {
                invitationDocumentModel = result.AsEnumerable().FirstOrDefault();
            }
            catch (Exception ex)
            {
                // throw AzureCosmoDBException (if a custom exception type is desired)
                // ... Will be caught, logged and handled by the ExceptionHandlerMiddleware

                // ...Or pass along as inner exception:
                throw new Exception("An error occured trying to use the document store", ex);
            }

            Invitation invitation = null;

            //==========================================================================
            // POST QUERY CHECKLIST
            //==========================================================================
            // 1. CACHING: Update results in cache.
            //     a. Use MediatR, Caching Library or Caching Routine within Accounts
            //
            // NOTE: Redis Multiplexer is already setup in our DI container using IRedisContext
            //--------------------------------------------------------------------------

            if (invitationDocumentModel != null)
            {
                //Use AutoMapper to transform DocumentModel into Domain Model (Configure via Core.Startup.AutoMapperConfiguration)
                invitation = AutoMapper.Mapper.Map <Core.Domain.Entities.Invitation>(invitationDocumentModel);


                // Assign expiration details
                invitation.DaysSinceCreated = (DateTime.UtcNow - invitation.CreatedDate).Days;

                if (invitation.DaysSinceCreated >= _coreConfiguration.Invitations.ExpirationDays)
                {
                    invitation.IsExpired = true;
                }
            }

            return(invitation);
        }
Exemple #2
0
        public async Task <BaseResponse> Handle(InviteUserCommand request, CancellationToken cancellationToken)
        {
            //=========================================================================
            // VALIDATE OUR COMMAND REQUEST USING FLUENT VALIDATION
            // ValidationExceptions can be captured using Middleware. However it is not as testable or portable outside of the MVC framework
            // I prefer using manual/granular validation within each command.
            //=========================================================================

            InviteUserValidator validator        = new InviteUserValidator(_mediator); //, _coreConfiguration);
            ValidationResult    validationResult = validator.Validate(request);

            if (!validationResult.IsValid)
            {
                return(new BaseResponse(validationResult.Errors)
                {
                    Message = "One or more validation errors occurred"
                });
            }


            //=========================================================================
            // CREATE AND STORE OUR DOCUMENT MODEL
            //=========================================================================

            var invitationDocumentModel = new InvitationDocumentModel(request.Email, request.Roles);

            // Generate collection uri
            Uri collectionUri = UriFactory.CreateDocumentCollectionUri(_documentContext.Settings.Database, _documentContext.Settings.Collection);

            ResourceResponse <Document> result;

            try
            {
                // Save the document to document store using the IDocumentContext dependency
                result = await _documentContext.Client.CreateDocumentAsync(
                    collectionUri,
                    invitationDocumentModel
                    );
            }
            catch (Exception ex)
            {
                // throw DocumentStoreException (if a custom exception type is desired)
                // ... Will be caught, logged and handled by the ExceptionHandlerMiddleware

                // Pass exception up the chain:
                throw ex;

                // ...Or pass along as inner exception:
                //throw new Exception("An error occured trying to use the document store", ex);
            }
            finally
            {
                // Close any open connections, etc...
            }


            if (result.StatusCode == System.Net.HttpStatusCode.Created)
            {
                //=========================================================================
                // SEND EMAIL
                //=========================================================================
                // Send an email to the new user using the IEmailService dependency
                var invitationLink = String.Concat(_coreConfiguration.Endpoints.ClientDomain, _coreConfiguration.Endpoints.AcceptInvitationsPath, invitationDocumentModel.Id);

                var emailMessage = new EmailMessage
                {
                    ToEmail = request.Email,
                    //ToName = String.Concat(""),
                    Subject     = String.Concat("Invitation to ", _coreConfiguration.Application.Name),
                    TextContent = String.Concat("You have been invited to ", _coreConfiguration.Application.Name, ". Please accept your invite and create your identity by following the instructions at this link: ", invitationLink),
                    HtmlContent = String.Concat("You have been invited to ", _coreConfiguration.Application.Name, ".</br></br> Please accept your invite and create your identity by following the instructions at the link below.<br/><br/>" + Common.Emails.EmailButtonGenerator.Generate(invitationLink, "Accept Invitation", 140)),
                };

                try
                {
                    var emailSent = await _emailService.SendEmail(emailMessage);
                }
                catch (Exception ex)
                {
                    // throw EmailServiceException (if a custom exception type is desired)
                    // ... Will be caught, logged and handled by the ExceptionHandlerMiddleware

                    // Pass the exception up the chain:
                    throw ex;

                    // ...Or pass along as inner exception:
                    //throw new Exception("An error occured trying to use the email service", ex);
                }
                finally
                {
                    // Use alternate communication method...
                }

                //=========================================================================
                // LOG ACTIVITY
                //=========================================================================
                Log.Information("Invitation created {@invitation}", invitationDocumentModel);

                //==========================================================================
                // POST COMMAND CHECKLIST
                //=========================================================================
                // 1. CACHING: Update cache.
                // 2. SEARCH INDEX: Update Search index or send indexer request.
                //-----------------------------------------------------------------------

                return(new BaseResponse {
                    isSuccess = true, Message = "Invitation sent"
                });
            }
            else
            {
                return(new BaseResponse {
                    Message = "Could not save model to document store. Status code: " + result.StatusCode
                });
            }
        }