Example #1
0
        public async Task <ServiceProviderResponse> CreateOrUpdateTemplateAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            [FromBody] TemplateCreateOrUpdateRequest request)
        {
            Validator.ArgumentNotNull(request, nameof(request));
            Validator.ArgumentNotNullOrEmpty(request.Name, nameof(request.Name));
            Validator.ArgumentNotNullOrEmpty(request.SenderAlias, nameof(request.SenderAlias));
            Validator.ArgumentNotNullOrEmpty(request.HtmlMsg, nameof(request.HtmlMsg));
            if (request.SenderAddrID != null)
            {
                Validator.ArgumentValidGuid(request.SenderAddrID, nameof(request.SenderAddrID));
            }

            var currentAccount = await EnsureAccount(account, requestId);

            var template = new Template
            {
                Name = request.Name,
                EngagementAccount = currentAccount.EngagementAccount,
                SenderId          = new Guid(request.SenderAddrID),
                SenderAlias       = request.SenderAlias,
                Subject           = request.Subject,
                HtmlMsg           = request.HtmlMsg,
                EnableUnSubscribe = request.EnableUnSubscribe,
                State             = ResourceState.Active,
            };

            var templateResult = await this.engine.CreateOrUpdateTemplateAsync(template, requestId);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, templateResult));
        }
        public async Task <ServiceProviderResponse> GetMessageDetailAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            string messageId,
            [FromQuery] string continuationToken = null,
            [FromQuery] int count = ContinuationToken.DefaultCount)
        {
            var currentAccount = await this.ValidateAccount(account);

            Validator.IsTrue <ArgumentException>(count > 0 && count <= SmsConstant.PagingMaxTakeCount, nameof(count), $"Count should be between 0 and {SmsConstant.PagingMaxTakeCount}.");

            var token = new AzureStorageContinuationToken(continuationToken);

            Validator.IsTrue <ArgumentException>(token.IsValid, nameof(token), "ContinuationToken is invalid.");

            var details = await this.reportManager.GetMessageAsync(account, messageId, count, token.TableContinuationToken);

            Validator.IsTrue <ArgumentException>(details != null, nameof(details), "Message does not exist.");

            var response = ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, details);

            if (details.ContinuationToken != null)
            {
                response.Headers = new Dictionary <string, IEnumerable <string> >
                {
                    { ContinuationToken.ContinuationTokenKey, new List <string> {
                          new AzureStorageContinuationToken(details.ContinuationToken).Token
                      } }
                };
            }

            return(response);
        }
Example #3
0
        public async Task <ServiceProviderResponse> ListTemplatesAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            [FromQuery] string continuationToken = null,
            [FromQuery] int count = ContinuationToken.DefaultCount)
        {
            await ValidateAccount(account);

            Validator.IsTrue <ArgumentException>(count > 0 && count <= SmsConstant.PagingMaxTakeCount, nameof(count), $"Count should be between 0 and {SmsConstant.PagingMaxTakeCount}.");

            var token = new DbContinuationToken(continuationToken);

            Validator.IsTrue <ArgumentException>(token.IsValid, nameof(token), "ContinuationToken is invalid.");

            var templates = await this.store.ListTemplatesAsync(account, token, count);

            var response = ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, templates);

            if (templates.NextLink != null)
            {
                response.Headers = new Dictionary <string, IEnumerable <string> >
                {
                    { ContinuationToken.ContinuationTokenKey, new List <string> {
                          templates.NextLink.Token
                      } }
                };
            }

            return(response);
        }
        public async Task <ServiceProviderResponse> GetAccount(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account)
        {
            var result = await this.GetAccountAsync(account);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, result));
        }
Example #5
0
        public async Task <ServiceProviderResponse> DeleteCredential(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string provider,
            string id)
        {
            await this.credentialManager.DeleteConnectorCredentialAsync(new ConnectorIdentifier(provider, id));

            return(ServiceProviderResponse.CreateResponse(HttpStatusCode.OK));
        }
Example #6
0
        public HttpResponseMessage SaveCommunicationLogInDetails(ServiceProviderViewModel request)
        {
            ServiceProviderResponse response = serviceProviderService.SaveServiceProvider(new ServiceProviderRequest()
            {
                ServiceProviderViewModel = request
            });

            return(Request.BuildResponse(response));
        }
        public async Task <ServiceProviderResponse> DeleteAccount(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account)
        {
            await ValidateAccount(account);
            await DeleteAccountAsync(account);

            return(ServiceProviderResponse.CreateResponse(HttpStatusCode.OK));
        }
Example #8
0
        public async Task <ServiceProviderResponse> GetCredential(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string provider,
            string id)
        {
            var connectorCredential = await this.credentialManager.GetConnectorCredentialByIdAsync(new ConnectorIdentifier(provider, id));

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, new Credential(connectorCredential)));
        }
        public async Task <ServiceProviderResponse> GetInboundMessagesync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account)
        {
            var currentAccount = await this.ValidateAccount(account);

            var messages = await this.inboundManager.GetInboundMessages(account);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, messages));
        }
        public async Task <ServiceProviderResponse> ListCredentialAssignments(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account)
        {
            var currentAccount = await EnsureAccount(account, requestId);

            var response = await this.credentialManager.ListCredentialAssignmentsByAccountAsync(currentAccount.EngagementAccount, false);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, response));
        }
        public async Task <ServiceProviderResponse> CreateOrUpdateAccount(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromBody] Account request)
        {
            Validator.ArgumentNotNull(request, nameof(request));
            Validator.ArgumentNotNullOrEmpty(request.EngagementAccount, nameof(request.EngagementAccount));

            var account = await this.CreateOrUpdateAccountAsync(request);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, account));
        }
Example #12
0
        public async Task <ServiceProviderResponse> GetTemplateAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            string value)
        {
            var currentAccount = await EnsureAccount(account, requestId);

            var template = await this.engine.GetTemplateAsync(currentAccount.EngagementAccount, value, requestId);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, template));
        }
        public async Task <ServiceProviderResponse> DeleteCredentialAssignments(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account,
            string provider,
            string id)
        {
            var currentAccount = await EnsureAccount(account, requestId);

            await this.credentialManager.DeleteCredentialAssignmentsAsync(currentAccount.EngagementAccount, new ConnectorIdentifier(provider, id));

            return(ServiceProviderResponse.CreateResponse(HttpStatusCode.OK));
        }
        public async Task <ServiceProviderResponse> ListCredentialAssignments(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account)
        {
            await ValidateAccount(account);

            var assignmentList = await this.credentialManager.ListCredentialAssignmentsByAccountAsync(account, ChannelType.Both, false);

            var response = assignmentList?.Select(a => new CredentialAssignment(a)).ToList();

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, response));
        }
Example #15
0
        public async Task <ServiceProviderResponse> CreateOrUpdateCredential(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromBody] Credential request)
        {
            Validator.ArgumentNotNull(request, nameof(request));
            Validator.ArgumentNotNull(request.ConnectorProperties, nameof(request.ConnectorProperties));
            Validator.ArgumentNotNullOrEmpty(request.ConnectorName, nameof(request.ConnectorName));
            Validator.ArgumentNotNullOrEmpty(request.ConnectorKey, nameof(request.ConnectorKey));

            await this.credentialManager.CreateOrUpdateConnectorCredentialAsync(request.ToConnectorCredential());

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, request));
        }
Example #16
0
        public async Task <ServiceProviderResponse> GetTemplateAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            string value)
        {
            await ValidateAccount(account);

            var template = await this.store.GetTemplateAsync(account, value);

            Validator.IsTrue <ResourceNotFoundException>(template != null, nameof(template), "The template '{0}' does not exist.", value);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, template));
        }
        public async Task <ServiceProviderResponse> GetSignatureExtensionAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account,
            string value)
        {
            var currentAccount = await ValidateAccount(account);

            var signature = await this.store.GetSignatureAsync(account, value);

            Validator.IsTrue <ResourceNotFoundException>(signature != null, nameof(signature), "The signature '{0}' does not exist.", value);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, new SignatureEx(signature)));
        }
Example #18
0
        public async Task <ServiceProviderResponse> GetDomainAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            string value)
        {
            var currentAccount = await EnsureAccount(account, requestId);

            var domain = await this.store.GetDomainAsync(currentAccount.EngagementAccount, value);

            Validator.IsTrue <ResourceNotFoundException>(domain != null, nameof(domain), "The Domain '{0}' does not exist.", value);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, domain));
        }
        public ServiceProviderResponse GetServiceProvider(ServiceProviderRequest request)
        {
            Logger.Current.Verbose("Request to fetch communication logindetails for specific contact.");
            ServiceProviderResponse response        = new ServiceProviderResponse();
            ServiceProvider         serviceProvider = serviceProviderRepository.GetServiceProviders(Convert.ToInt16(request.ServiceProviderViewModel.AccountID), request.ServiceProviderViewModel.CommunicationTypeID, request.ServiceProviderViewModel.MailType);

            if (serviceProvider != null)
            {
                ServiceProviderViewModel ServiceProviderViewModel = Mapper.Map <ServiceProvider, ServiceProviderViewModel>(serviceProvider as ServiceProvider);
                response.ServiceProviderViewModel = ServiceProviderViewModel;
            }

            return(response);
        }
Example #20
0
        public async Task <ServiceProviderResponse> CreateOrUpdateTemplateAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            [FromBody] TemplateCreateOrUpdateRequest request)
        {
            await ValidateAccount(account);

            Validator.ArgumentNotNull(request, nameof(request));
            Validator.ArgumentNotNullOrEmpty(request.Name, request.Name);
            Validator.ArgumentNotNullOrEmpty(request.Signature, request.Signature);
            Validator.IsTrue <ArgumentException>(request.Category != MessageCategory.Invalid, nameof(request.Category), "Invalid message category.");
            ValidateTemplateBody(request.Body, request.Category);

            var signature = await this.store.GetSignatureAsync(account, request.Signature);

            Validator.IsTrue <ResourceNotFoundException>(signature != null, nameof(signature), "The signature '{0}' does not exist.", request.Signature);
            Validator.IsTrue <ArgumentException>(signature.State == ResourceState.Active, nameof(signature), "The signature '{0}' is not active.", request.Signature);
            ValidateSignagureForMessageCategory(signature, request.Category);

            var template = new Template
            {
                EngagementAccount = account,
                Name      = request.Name,
                Signature = request.Signature,
                Category  = request.Category,
                Body      = request.Body,
                State     = ResourceState.Pending
            };

            template = await this.store.CreateOrUpdateTemplateAsync(template);

            // Send ops mail
            if (this.mailHelper != null)
            {
                SmsProviderEventSource.Current.Info(requestId, this, nameof(this.CreateOrUpdateTemplateAsync), OperationStates.Starting, $"Sending ops mail. account={account} template={template.Name}");

                var channelType = SmsConstant.MessageSendChannelMappings[template.Category];
                var assignment  = await this.credentialManager.GetCredentialAssignmentByAccountAsync(account, channelType);

                this.mailHelper.SendMailOnTemplateCreatedOrUpdated(template, assignment != null ? new CredentialAssignment(assignment) : null, requestId);

                SmsProviderEventSource.Current.Info(requestId, this, nameof(this.CreateOrUpdateTemplateAsync), OperationStates.Succeeded, $"Sent ops mail. account={account} template={template.Name}");
            }
            else
            {
                SmsProviderEventSource.Current.Warning(requestId, this, nameof(this.CreateOrUpdateTemplateAsync), OperationStates.Dropped, $"Cannot send ops email because of mailing is not ready. account={account} template={template.Name}");
            }

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, template));
        }
        public async Task <ServiceProviderResponse> CreateOrUpdateCredentialAssignments(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account,
            [FromBody] CredentialAssignment request)
        {
            await ValidateAccount(account);

            Validator.ArgumentNotNull(request, nameof(request));
            Validator.ArgumentNotNullOrEmpty(request.Provider, nameof(request.Provider));
            Validator.ArgumentNotNullOrEmpty(request.ConnectorId, nameof(request.ConnectorId));
            Validator.IsTrue <ArgumentException>(request.ChannelType != ChannelType.Invalid, nameof(request.ChannelType), "Invalid channel type.");

            var identifier = new ConnectorIdentifier(request.Provider, request.ConnectorId);
            var credential = await this.credentialManager.GetConnectorCredentialByIdAsync(identifier);

            Validator.IsTrue <ResourceNotFoundException>(credential != null, nameof(credential), "Credential '{0}' does not exist.", identifier);
            Validator.IsTrue <ArgumentException>(credential.ChannelType == request.ChannelType, nameof(request.ChannelType), "Credential '{0}' is for channel type '{1}' but not '{2}'", identifier, credential.ChannelType.ToString(), request.ChannelType.ToString());

            if (string.IsNullOrEmpty(request.ExtendedCode))
            {
                // Auto-assign account code
                var otherAccounts = await this.credentialManager.ListCredentialAssignmentsById(identifier, false);

                if (otherAccounts != null && otherAccounts.Count > 0)
                {
                    var last = otherAccounts.Where(a => a.ExtendedCode != null).OrderBy(a => a.ExtendedCode).LastOrDefault();
                    if (int.TryParse(last.ExtendedCode, out int code) && code < Math.Pow(10, SmsConstant.ExtendedCodeCompanyLength) - 1)
                    {
                        request.ExtendedCode = (code + 1).ToString().PadLeft(SmsConstant.ExtendedCodeCompanyLength, '0');
                    }
                    else
                    {
                        throw new ApplicationException($"Failed the generate new code. The last one is '{last.ExtendedCode}'");
                    }
                }
                else
                {
                    request.ExtendedCode = 1.ToString().PadLeft(SmsConstant.ExtendedCodeCompanyLength, '0');
                }
            }

            await this.credentialManager.CreateOrUpdateCredentialAssignmentAsync(request.ToDataContract(account));

            var assignmentList = await this.credentialManager.ListCredentialAssignmentsByAccountAsync(account, ChannelType.Both, false);

            var response = assignmentList?.Select(a => new CredentialAssignment(a)).ToList();

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, response));
        }
        public async Task <ServiceProviderResponse> GetMessageDetailAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            string messageId)
        {
            var currentAccount = await EnsureAccount(account, requestId);

            var details = await this.reportManager.GetReportAsync(currentAccount.EngagementAccount, messageId);

            Validator.IsTrue <ArgumentException>(details != null, nameof(details), "Message does not exist.");

            var response = ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, details);

            return(response);
        }
        public async Task <ServiceProviderResponse> DeleteAccount(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account)
        {
            var result = await this.GetAccountAsync(account);

            if (result == null)
            {
                return(ServiceProviderResponse.CreateResponse(HttpStatusCode.OK));
            }

            await this.DeleteAccountAsync(result.EngagementAccount);

            return(ServiceProviderResponse.CreateResponse(HttpStatusCode.OK));
        }
        public async Task <ServiceProviderResponse> GetSenderAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            System.Guid value,
            [FromQuery] string continuationToken = null,
            [FromQuery] int count = ContinuationToken.DefaultCount)
        {
            Validator.IsTrue <ArgumentException>(count > 0 && count <= EmailConstant.PagingMaxTakeCount, nameof(count), $"Count should be between 0 and {EmailConstant.PagingMaxTakeCount}.");

            var currentAccount = await EnsureAccount(account, requestId);

            var sender = await this.engine.GetSenderAsync(currentAccount.EngagementAccount, value, requestId);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, sender));
        }
        public async Task <ServiceProviderResponse> DeleteSenderAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            Guid value)
        {
            var currentAccount = await EnsureAccount(account, requestId);

            var sender = await this.engine.GetSenderAsync(currentAccount.EngagementAccount, value, requestId);

            await this.engine.DeleteTemplatesbySenderAsync(currentAccount.EngagementAccount, value, requestId);

            await this.engine.DeleteSenderAsync(currentAccount.EngagementAccount, value, requestId);

            return(ServiceProviderResponse.CreateResponse(HttpStatusCode.OK));
        }
        public async Task <ServiceProviderResponse> RemoveSignatureQuotaAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account,
            string value)
        {
            var currentAccount = await ValidateAccount(account);

            var signature = await this.store.GetSignatureAsync(account, value);

            Validator.IsTrue <ResourceNotFoundException>(signature != null, nameof(signature), "The signature '{0}' does not exist.", value);

            var quotaName = string.Format(Constants.SmsSignatureMAUNamingTemplate, value);
            await QuotaCheckClient.RemoveQuotaAsync(account, quotaName);

            return(ServiceProviderResponse.CreateResponse(HttpStatusCode.OK));
        }
Example #27
0
        public async Task <ServiceProviderResponse> GetCredential(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string provider,
            string id)
        {
            var connectorCredential = await this.credentialManager.GetConnectorCredentialByIdAsync(new ConnectorIdentifier(provider, id));

            Credential credential = new Credential()
            {
                ConnectorName       = connectorCredential.ConnectorName,
                ConnectorKey        = connectorCredential.ConnectorId,
                ConnectorProperties = new PropertyCollection <string>(connectorCredential.ConnectorProperties)
            };

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, credential));
        }
        public async Task <ServiceProviderResponse> CreateOrUpdateSignatureAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account,
            [FromBody] Signature request)
        {
            await ValidateAccount(account);

            Validator.ArgumentNotNull(request, nameof(request));
            Validator.IsTrue <ArgumentException>(request.ChannelType != ChannelType.Invalid, nameof(request.ChannelType), "Invalid channel type.");
            ValidateSignature(request.Value);

            var oldState  = ResourceState.Unknown;
            var signature = await this.store.GetSignatureAsync(account, request.Value);

            if (signature == null)
            {
                // Add restriction that do not create an active signature directly
                // Create a signature with pending status first
                // This is to prevent admin providing incorrect name when activate a signature
                Validator.IsTrue <ArgumentException>(request.State != ResourceState.Active, nameof(request.State), "Cannot create a signature with active state.");

                // Create new with a increased code assigned
                signature = new Signature();
                signature.EngagementAccount = account;
                signature.Value             = request.Value;
                signature.ExtendedCode      = await GetNextExtendedCode(account);
            }

            signature.ChannelType = request.ChannelType;
            signature.State       = request.State;
            signature.Message     = request.Message;

            signature = await this.store.CreateOrUpdateSignatureAsync(signature);

            // Disable all active templates if signature is not in active state, and vice versa
            if (oldState == ResourceState.Active && signature.State != ResourceState.Active)
            {
                await this.store.UpdateTemplateStateBySignatureAsync(account, signature.Value, ResourceState.Active, ResourceState.Disabled, $"Disabled because signature is in state '{signature.State.ToString()}'");
            }
            else if (oldState != ResourceState.Active && signature.State == ResourceState.Active)
            {
                await this.store.UpdateTemplateStateBySignatureAsync(account, signature.Value, ResourceState.Disabled, ResourceState.Active);
            }

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, new SignatureEx(signature)));
        }
        public async Task <ServiceProviderResponse> SendMessageByGroupAsync(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            [FromHeader] string account,
            [FromBody] MessageSendByGroupRequest request)
        {
            Account currentAccount = null;

            try
            {
                // TODO: limit on max target?
                Validator.ArgumentNotNull(request, nameof(request));
                Validator.ArgumentNotNull(request.MessageBody, nameof(request.MessageBody));
                Validator.ArgumentNotNullOrEmpty(request.MessageBody.TemplateName, request.MessageBody.TemplateName);
                Validator.IsTrue <ArgumentException>(request.Targets != null && request.Targets.Count > 0, nameof(request.Targets), "Targets is empty");
                Validator.IsTrue <ArgumentException>(request.Targets.Count <= 10, nameof(request.Targets), "Number of Targets could not be more than 10");

                currentAccount = await EnsureAccount(account, requestId);

                var tuples = await BuildInputMessageAsync(currentAccount, request.MessageBody, request.Targets, TargetType.Group, requestId);

                var message   = tuples.Item1;
                var extension = tuples.Item2;

                // Update report
                await this.reportManager.OnMessageSentAsync(currentAccount.EngagementAccount, message, extension);

                // Dispatch
                await DispatchMessageAsync(message, extension, requestId);

                metricManager.LogSendSuccess(1, currentAccount.EngagementAccount, currentAccount.SubscriptionId ?? string.Empty);

                var response = new MessageSendResponse
                {
                    MessageId = message.MessageInfo.MessageId,
                    SendTime  = message.MessageInfo.SendTime
                };

                return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, response));
            }
            catch
            {
                metricManager.LogSendFailed(1, currentAccount.EngagementAccount, currentAccount?.SubscriptionId ?? string.Empty);
                throw;
            }
        }
        public async Task <ServiceProviderResponse> CreateOrUpdateCredentialAssignments(
            [FromHeader(Constant.OperationTrackingIdHeader)] string requestId,
            string account,
            [FromBody] CredentialAssignment request)
        {
            var currentAccount = await EnsureAccount(account, requestId);

            Validator.ArgumentNotNull(request, nameof(request));
            Validator.ArgumentNotNullOrEmpty(request.Provider, nameof(request.Provider));
            Validator.ArgumentNotNullOrEmpty(request.ConnectorId, nameof(request.ConnectorId));

            request.EngagementAccount = currentAccount.EngagementAccount;
            await this.credentialManager.CreateOrUpdateCredentialAssignmentAsync(request);

            var response = await this.credentialManager.ListCredentialAssignmentsByAccountAsync(currentAccount.EngagementAccount, false);

            return(ServiceProviderResponse.CreateJsonResponse(HttpStatusCode.OK, response));
        }