/// <summary>
        /// Validates a personal goal data received from client application is valid.
        /// </summary>
        /// <param name="personalGoalData">Details of a personal goal to be saved/updated in storage</param>
        /// <returns> Returns response representing whether data received is valid or not</returns>
        private ObjectResult ValidatePersonalGoal(PersonalGoalDetail personalGoalData)
        {
            if (!Guid.TryParse(personalGoalData.PersonalGoalId, out _))
            {
                this.logger.LogError(StatusCodes.Status400BadRequest, $"Personal goal id:{personalGoalData.PersonalGoalId} is not a valid GUID.");
                return(this.BadRequest($"Personal goal id:{personalGoalData.PersonalGoalId} is not a valid GUID."));
            }
            else if (personalGoalData.UserAadObjectId != this.UserObjectId)
            {
                this.logger.LogError(StatusCodes.Status403Forbidden, $"User {personalGoalData.UserAadObjectId} is forbidden to perform this operation.");
                return(this.StatusCode(StatusCodes.Status403Forbidden, $"User {personalGoalData.UserAadObjectId} is forbidden to perform this operation."));
            }
            else if (personalGoalData.CreatedBy != this.HttpContext.User.Identity.Name)
            {
                this.logger.LogError(StatusCodes.Status403Forbidden, $"User {personalGoalData.CreatedBy} is forbidden to perform this operation.");
                return(this.StatusCode(StatusCodes.Status403Forbidden, $"User {personalGoalData.CreatedBy} is forbidden to perform this operation."));
            }
            else if (DateTime.Parse(personalGoalData.StartDate, CultureInfo.InvariantCulture) >= DateTime.Parse(personalGoalData.EndDate, CultureInfo.InvariantCulture))
            {
                this.logger.LogError(StatusCodes.Status400BadRequest, $"Personal goal start date is greater than end date.");
                return(this.BadRequest("Personal goal start date is greater than end date."));
            }
            else if (DateTime.Parse(personalGoalData.EndDate, CultureInfo.InvariantCulture).ToUniversalTime() < DateTime.Now.ToUniversalTime())
            {
                this.logger.LogError(StatusCodes.Status400BadRequest, $"Personal goal end date is smaller than current date.");
                return(this.BadRequest("Personal goal end date is smaller than current date."));
            }

            this.logger.LogInformation(StatusCodes.Status200OK, $"Personal goal detail received is valid.");
            return(this.Ok("Personal goal detail received is valid."));
        }
        /// <summary>
        /// Method to send goal reminder card to personal bot.
        /// </summary>
        /// <param name="personalGoalDetail">Holds personal goal detail entity data sent from background service.</param>
        /// <param name="isReminderBeforeThreeDays">Determines reminder to be sent prior 3 days to end date.</param>
        /// <returns>A Task represents goal reminder card is sent to the bot, installed in the personal scope.</returns>
        public async Task SendGoalReminderToPersonalBotAsync(PersonalGoalDetail personalGoalDetail, bool isReminderBeforeThreeDays = false)
        {
            personalGoalDetail = personalGoalDetail ?? throw new ArgumentNullException(nameof(personalGoalDetail));
            var conversationReference = new ConversationReference()
            {
                ChannelId = Constants.TeamsBotFrameworkChannelId,
                Bot       = new ChannelAccount()
                {
                    Id = $"28:{this.microsoftAppCredentials.MicrosoftAppId}"
                },
                ServiceUrl   = personalGoalDetail.ServiceUrl,
                Conversation = new ConversationAccount()
                {
                    ConversationType = Constants.PersonalConversationType, Id = personalGoalDetail.ConversationId, TenantId = this.options.Value.TenantId
                },
            };

            try
            {
                await this.retryPolicy.ExecuteAsync(async() =>
                {
                    await((BotFrameworkAdapter)this.adapter).ContinueConversationAsync(
                        this.microsoftAppCredentials.MicrosoftAppId,
                        conversationReference,
                        async(turnContext, cancellationToken) =>
                    {
                        string reminderType = string.Empty;
                        AdaptiveTextColor reminderTypeColor = AdaptiveTextColor.Accent;
                        if (isReminderBeforeThreeDays)
                        {
                            reminderType      = this.localizer.GetString("PersonalGoalEndingAfterThreeDays");
                            reminderTypeColor = AdaptiveTextColor.Attention;
                        }
                        else
                        {
                            reminderType = this.GetReminderTypeString(personalGoalDetail.ReminderFrequency);
                        }

                        var goalReminderAttachment = MessageFactory.Attachment(GoalReminderCard.GetGoalReminderCard(this.localizer, this.options.Value.ManifestId, this.options.Value.GoalsTabEntityId, reminderType, reminderTypeColor));
                        this.logger.LogInformation($"Sending goal reminder card to Personal bot. Conversation id: {personalGoalDetail.ConversationId}");
                        await turnContext.SendActivityAsync(goalReminderAttachment, cancellationToken);
                    },
                        CancellationToken.None);
                });
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, $"Error while sending goal reminder card to personal bot: {ex.Message} at {nameof(this.SendGoalReminderToPersonalBotAsync)}");
                throw;
            }
        }
        public async Task <IActionResult> UpdatePersonalGoalDetailAsync(PersonalGoalDetail personalGoalData)
        {
            try
            {
#pragma warning disable CA1062 // Patch details are validated by model validations for null check and is responded with bad request status
                var validationErrorResponse = this.ValidatePersonalGoal(personalGoalData);
#pragma warning restore CA1062 // Patch details are validated by model validations for null check and is responded with bad request status
                if (validationErrorResponse.StatusCode != StatusCodes.Status200OK)
                {
                    return(validationErrorResponse);
                }

                var existingGoalDetail = await this.personalGoalStorageProvider.GetPersonalGoalDetailByGoalIdAsync(personalGoalData.PersonalGoalId, this.UserObjectId);

                if (existingGoalDetail == null)
                {
                    this.logger.LogError(StatusCodes.Status404NotFound, $"The personal goal user trying to update does not exist. Personal goal id: {personalGoalData.PersonalGoalId} ");
                    return(this.NotFound("The personal goal user trying to update does not exist."));
                }

                this.logger.LogInformation("Initiated call to personal goal storage provider.");
                var result = await this.personalGoalStorageProvider.CreateOrUpdatePersonalGoalDetailAsync(personalGoalData);

                this.logger.LogInformation("PATCH call for saving personal goal detail in storage is successful");

                if (!result)
                {
                    this.logger.LogError($"Could not save or update goal data received with personal goal id: {personalGoalData.PersonalGoalId}.");
                    return(this.StatusCode(StatusCodes.Status500InternalServerError, "Could not save or update goal data received."));
                }

                // Update list card of personal bot. Enqueue task to task wrapper and it will be executed by goal background service.
                this.backgroundTaskWrapper.Enqueue(this.cardHelper.UpdatePersonalGoalListCardAsync(personalGoalData));
                return(this.Ok(result));
            }
#pragma warning disable CA1031 // Catching all generic exceptions in order to log exception details in logger
            catch (Exception ex)
#pragma warning restore CA1031 // Catching all generic exceptions in order to log exception details in logger
            {
                this.logger.LogError(ex, "Error while saving personal goal detail");
                throw;
            }
        }
示例#4
0
        /// <summary>
        /// Stores or update personal goal detail in storage.
        /// </summary>
        /// <param name="personalGoalEntity">Holds personal goal data.</param>
        /// <returns>A boolean that represents personal goal detail entity data is saved or updated.</returns>
        public async Task <bool> CreateOrUpdatePersonalGoalDetailAsync(PersonalGoalDetail personalGoalEntity)
        {
            personalGoalEntity = personalGoalEntity ?? throw new ArgumentNullException(nameof(personalGoalEntity));

            try
            {
                await this.EnsureInitializedAsync();

                TableOperation operation = TableOperation.InsertOrReplace(personalGoalEntity);
                var            result    = await this.CloudTable.ExecuteAsync(operation);

                return(result.HttpStatusCode == (int)HttpStatusCode.NoContent);
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, $"An error occurred in {nameof(this.CreateOrUpdatePersonalGoalDetailAsync)} while saving personal goal data.");
                throw;
            }
        }
示例#5
0
        /// <summary>
        /// Gets the add note submit card.
        /// </summary>
        /// <param name="personalGoalNoteDetail">Instance containing personal goal note related details.</param>
        /// <param name="personalGoalDetail">Instance containing personal goal related details.</param>
        /// <param name="localizer">The current cultures' string localizer.</param>
        /// <returns>Attachment having add note submit card.</returns>
        public static Attachment GetsAddNoteSubmitCard(PersonalGoalNoteDetail personalGoalNoteDetail, PersonalGoalDetail personalGoalDetail, IStringLocalizer <Strings> localizer)
        {
            personalGoalDetail     = personalGoalDetail ?? throw new ArgumentNullException(nameof(personalGoalDetail));
            personalGoalNoteDetail = personalGoalNoteDetail ?? throw new ArgumentNullException(nameof(personalGoalNoteDetail));
            var isSourceEmpty = string.IsNullOrEmpty(personalGoalNoteDetail?.SourceName) ? true : false;

            AdaptiveCard addCardSubmitCard = new AdaptiveCard(Constants.AdaptiveCardVersion)
            {
                Body = new List <AdaptiveElement>()
                {
                    new AdaptiveTextBlock
                    {
                        Text   = localizer.GetString("AddNoteHeading"),
                        Weight = AdaptiveTextWeight.Bolder,
                        Size   = AdaptiveTextSize.Large,
                        Wrap   = true,
                    },
                    new AdaptiveColumnSet
                    {
                        Spacing = AdaptiveSpacing.Padding,
                        Columns = new List <AdaptiveColumn>
                        {
                            new AdaptiveColumn
                            {
                                Width = "1",
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Size = AdaptiveTextSize.Medium,
                                        Wrap = true,
                                        Text = localizer.GetString("AddNoteGoalNameSubheading"),
                                    },
                                },
                            },
                            new AdaptiveColumn
                            {
                                Width = "4",
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Size   = AdaptiveTextSize.Medium,
                                        Wrap   = true,
                                        Text   = personalGoalDetail.GoalName,
                                        Weight = AdaptiveTextWeight.Bolder,
                                    },
                                },
                            },
                        },
                    },
                    new AdaptiveColumnSet
                    {
                        Spacing = AdaptiveSpacing.Padding,
                        Columns = new List <AdaptiveColumn>
                        {
                            new AdaptiveColumn
                            {
                                Width = "1",
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Size   = AdaptiveTextSize.Medium,
                                        Wrap   = true,
                                        Text   = localizer.GetString("AddNoteNoteSubheading"),
                                        Weight = AdaptiveTextWeight.Bolder,
                                    },
                                },
                            },
                            new AdaptiveColumn
                            {
                                Width = "4",
                                Items = new List <AdaptiveElement>
                                {
                                    new AdaptiveTextBlock
                                    {
                                        Size = AdaptiveTextSize.Medium,
                                        Wrap = true,
                                        Text = personalGoalNoteDetail.PersonalGoalNoteDescription,
                                    },
                                },
                            },
                        },
                    },
                },
            };

            if (!isSourceEmpty)
            {
                addCardSubmitCard.Body.Add(new AdaptiveColumnSet()
                {
                    Spacing = AdaptiveSpacing.None,
                    Columns = new List <AdaptiveColumn>
                    {
                        new AdaptiveColumn
                        {
                            Width = "1",
                            Items = new List <AdaptiveElement>
                            {
                                new AdaptiveTextBlock
                                {
                                    Size   = AdaptiveTextSize.Medium,
                                    Wrap   = true,
                                    Text   = localizer.GetString("AddNoteSourceSubheading"),
                                    Weight = AdaptiveTextWeight.Bolder,
                                },
                            },
                        },
                        new AdaptiveColumn
                        {
                            Width = "4",
                            Items = new List <AdaptiveElement>
                            {
                                new AdaptiveTextBlock
                                {
                                    Size = AdaptiveTextSize.Medium,
                                    Wrap = true,
                                    Text = personalGoalNoteDetail.SourceName,
                                },
                            },
                        },
                    },
                });
            }

            addCardSubmitCard.Body.Add(new AdaptiveColumnSet()
            {
                Spacing = AdaptiveSpacing.None,
                Columns = new List <AdaptiveColumn>
                {
                    new AdaptiveColumn
                    {
                        Width = "1",
                        Items = new List <AdaptiveElement>
                        {
                            new AdaptiveTextBlock
                            {
                                Size   = AdaptiveTextSize.Medium,
                                Wrap   = true,
                                Text   = localizer.GetString("AddNoteDateSubheading"),
                                Weight = AdaptiveTextWeight.Bolder,
                            },
                        },
                    },
                    new AdaptiveColumn
                    {
                        Width = "4",
                        Items = new List <AdaptiveElement>
                        {
                            new AdaptiveTextBlock
                            {
                                Size = AdaptiveTextSize.Medium,
                                Wrap = true,
                                Text = CardHelper.FormatDateStringToAdaptiveCardDateFormat(DateTime.Now.ToString(CultureInfo.CurrentCulture)),
                            },
                        },
                    },
                },
            });

            addCardSubmitCard.Actions = new List <AdaptiveAction>
            {
                new AdaptiveSubmitAction
                {
                    Title = localizer.GetString("AddNoteEditButtonText"),
                    Data  = new AdaptiveSubmitActionData
                    {
                        MsTeams = new TaskModuleAction(
                            localizer.GetString("AddNoteEditButtonText"),
                            new
                        {
                            data = JsonConvert.SerializeObject(new AdaptiveSubmitActionData
                            {
                                AdaptiveActionType = Constants.EditNoteCommand,
                                PersonalGoalNoteId = personalGoalNoteDetail.PersonalGoalNoteId,
                                PersonalGoalId     = personalGoalNoteDetail.PersonalGoalId,
                                GoalNoteId         = personalGoalNoteDetail.AdaptiveCardActivityId,
                            }),
                        }),
                    },
                },
            };

            return(new Attachment
            {
                ContentType = AdaptiveCard.ContentType,
                Content = addCardSubmitCard,
            });
        }