Beispiel #1
0
        private static async Task CreateSubscription(string channelId, QandAModel model, GraphServiceClient graph)
        {
            var subscription = new Subscription
            {
                Resource        = $"teams/{model.teamId}/channels/{model.channelId}/messages",
                ChangeType      = "created,updated,deleted",
                NotificationUrl = ConfigurationManager.AppSettings["NotificationUrl"],
                ClientState     = Guid.NewGuid().ToString(),
                //ExpirationDateTime = DateTime.UtcNow + new TimeSpan(days: 0, hours: 0, minutes: 10, seconds: 0),
                ExpirationDateTime       = DateTime.UtcNow + new TimeSpan(days: 0, hours: 0, minutes: 1, seconds: 0),
                IncludeProperties        = false,
                LifecycleNotificationUrl = "https://qna.ngrok.io/webhookLifecyle",
                AdditionalData           = new Dictionary <string, object>()
                {
                    ["includeResourceData"]     = false,
                    ["encryptionCertificate"]   = SelfSignedCert,
                    ["encryptionCertificateId"] = "testcert",
                }
            };

            try
            {
                if (channelToSubscription.ContainsKey(channelId))
                {
                    // refresh subscription
                    var subId = channelToSubscription[channelId];

                    // Since this is a fake encryption subscription, we can't update the encryption properties
                    subscription.AdditionalData = null;

                    var newSubscription = await graph.Subscriptions[subId].Request().UpdateAsync(subscription);
                }
                else
                {
                    try
                    {
                        var newSubscription = await graph.Subscriptions.Request().AddAsync(subscription);

                        channelToSubscription[channelId] = newSubscription.Id;
                    }
                    catch (Exception e) when(e.Message.Contains("has reached its limit of 1 TEAMS"))
                    {
                        // ignore, we're still being notified
                    }
                }
            }
            catch (Exception)
            {
                // Bail on subscriptions without killing the whole demo
            }
        }
Beispiel #2
0
        public ActionResult MarkAsUnanswered(
            [FromUri(Name = "tenantId")] string tenantId,
            [FromUri(Name = "teamId")] string teamId,
            [FromUri(Name = "channelId")] string channelId,
            [FromUri(Name = "messageId")] string messageId)
        //,
        //[FromQuery(Name = "replyId")] string replyId)
        {
            QandAModel model = GetModel(tenantId, teamId, channelId, ""); //messageId);

            //model.IsQuestionAnswered[replyId] = true;
            model.IsQuestionAnswered[messageId] = false;
            string url = $"~/First?tenantId={tenantId}&teamId={teamId}&channelId={channelId}&messageId={messageId}&skipRefresh=true&useRSC=false";

            return(Redirect(url));
        }
Beispiel #3
0
        public async Task RefreshQandA(QandAModel qAndA, GraphServiceClient graph)
        {
            var handle = graph.Teams[qAndA.teamId].Channels[qAndA.channelId]
                         .Messages.Request().Top(30);

            try
            {
                var msgs = await handle.GetAsync();

                //var msgs = await graph.Teams[qAndA.teamId].Channels[qAndA.channelId]
                //    .Messages.Request().Top(30).GetAsync();
                ////var msgs = await graph.Teams[qAndA.teamId].Channels[qAndA.channelId]
                //    .Messages[qAndA.messageId].Replies.Request().Top(50).GetAsync();

                // merge w/ existing questions
                var questions =
                    from m in msgs
                    where IsQuestion(m)
                    select new Question()
                {
                    MessageId = m.Id,
                    Text      = StripHTML(m.Body.Content),
                    Votes     = m.Reactions.Count()
                };
                qAndA.Questions = questions.OrderByDescending(m => m.Votes).ToList();

                foreach (var q in questions)
                {
                    if (!qAndA.IsQuestionAnswered.ContainsKey(q.MessageId))
                    {
                        qAndA.IsQuestionAnswered[q.MessageId] = false;
                    }
                }

                //await UpdateCard(qAndA);
            } catch (Exception e)
            {
                string m = String.Format("{0}\n {1}\n {2}\n {3}\n --- trace {4}",
                                         handle.GetHttpRequestMessage().GetRequestContext().ClientRequestId,
                                         handle.GetHttpRequestMessage().Method,
                                         handle.GetHttpRequestMessage().RequestUri,
                                         handle.GetHttpRequestMessage().Content,
                                         //handle.GetHttpRequestMessage().Headers.Authorization.Parameter,
                                         e.StackTrace);
                throw new Exception(m);
            }
        }
Beispiel #4
0
        public ActionResult MarkAsAnswered(
            [FromUri(Name = "tenantId")] string tenantId,
            [FromUri(Name = "teamId")] string teamId,
            [FromUri(Name = "channelId")] string channelId,
            [FromUri(Name = "messageId")] string messageId)
        //,
        //[FromQuery(Name = "replyId")] string replyId)
        {
            QandAModel model = GetModel(tenantId, teamId, channelId, ""); //messageId);

            //model.IsQuestionAnswered[replyId] = true;
            model.IsQuestionAnswered[messageId] = true;

            // to-do -- consider escaping these parameters, even though they aren't trusted on the other end
            string url = $"~/First?tenantId={tenantId}&teamId={teamId}&channelId={channelId}&messageId={messageId}&skipRefresh=true&useRSC=false";

            return(Redirect(url));
        }
Beispiel #5
0
        public async Task <ActionResult> First(
            [FromUri(Name = "tenantId")] string tenantId,
            [FromUri(Name = "teamId")] string teamId,
            [FromUri(Name = "channelId")] string channelId,
            [FromUri(Name = "skipRefresh")] Nullable <bool> skipRefresh,
            [FromUri(Name = "useRSC")] Nullable <bool> useRSC
            )
        {
            bool usingRSC = (useRSC != false);

            try
            {
                // Do our auth check first
                GraphServiceClient graph = await Authorization.GetGraphClient(teamId, Request.Cookies, Response.Cookies, usingRSC);

                QandAModel        model   = GetModel(tenantId, teamId, channelId, "");
                QandAModelWrapper wrapper = new QandAModelWrapper()
                {
                    useRSC    = usingRSC,
                    showLogin = false,
                    model     = model
                };

                if (skipRefresh != true)
                {
                    await RefreshQandA(model, graph);

                    GraphServiceClient graphForWebhooks = await Authorization.GetGraphClientForCreatingWebhooks(teamId, Request.Cookies, Response.Cookies, usingRSC);
                    await CreateSubscription(channelId, model, graphForWebhooks);
                }
                ViewBag.MyModel = model;
                return(View("First", wrapper));
            }
            catch (Exception e) when(e.Message.Contains("Unauthorized") || e.Message.Contains("Access token has expired."))
            {
                return(ShowSignin(usingRSC));
            }
        }
Beispiel #6
0
        private QandAModel GetModel(string tenantId, string teamId, string channelId, string messageId)
        {
            // TODO: Validate the user has access to the team (or at least the tenant) before retrieving the model.
            // It's not critical right now since we'll fail out when we make the inevitable Graph calls to
            // update the model, but it's a little fragile.

            string     key = QandAModel.Encode(tenantId, teamId, channelId, messageId);
            QandAModel model;

            if (QandAModel.qAndALookup.ContainsKey(key))
            {
                model = QandAModel.qAndALookup[key];
            }
            else
            {
                model = new QandAModel()
                {
                    tenantId = tenantId, teamId = teamId, channelId = channelId, messageId = messageId
                };
                QandAModel.qAndALookup[key] = model;
            }
            return(model);
        }